Adding tokens and temperature parameters, the smaller the temperature parameter, the more stable the output is, while the larger the output, the more random it is 加入tokens和温度参数,温度参数越小输出约稳定,越大输出更有随机性
200 lines
6.8 KiB
Python
200 lines
6.8 KiB
Python
import os
|
|
import json
|
|
import requests
|
|
import time
|
|
import jwt
|
|
import re
|
|
import tempfile
|
|
import random
|
|
from PIL import Image
|
|
import base64
|
|
import cv2
|
|
|
|
p = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
|
|
def get_zpai_api_key():
|
|
try:
|
|
config_path = os.path.join(p, 'config.json')
|
|
with open(config_path, 'r') as f:
|
|
config = json.load(f)
|
|
api_key = config["Zpai_API_KEY"]
|
|
except Exception as e:
|
|
raise Exception("Error: API key is required", e)
|
|
return api_key
|
|
|
|
|
|
def generate_token(apikey_s: str, exp_second: int):
|
|
try:
|
|
id_t, secret = apikey_s.split(".")
|
|
|
|
except Exception as e:
|
|
raise Exception("invalid apikey", e)
|
|
|
|
payload = {
|
|
"api_key": id_t,
|
|
"exp": int(round(time.time() * 1000)) + exp_second * 1000,
|
|
"timestamp": int(round(time.time() * 1000)),
|
|
}
|
|
return jwt.encode(
|
|
payload,
|
|
secret,
|
|
algorithm="HS256",
|
|
headers={"alg": "HS256", "sign_type": "SIGN"},
|
|
)
|
|
|
|
|
|
class ZhipuaiApi_Txt:
|
|
|
|
def __init__(self):
|
|
self.api_key = get_zpai_api_key()
|
|
if self.api_key is not None:
|
|
client_key = self.api_key
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"prompt": ("STRING", {"multiline": True, "default": "30 words describe a girl walking on the Moon."}),
|
|
"model_name": (["glm-4", "glm-3-turbo"],),
|
|
"max_tokens": ("INT", {"default": 1024, "min": 128, "max": 8192, "step": 128, "display": "slider"}),
|
|
"temperature": ("FLOAT", {"default": 0.95, "min": 0.01, "max": 0.99, "step": 0.01, "round": False, "display": "slider"}),
|
|
"output_language": (["English", "Original_language"],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("text",)
|
|
FUNCTION = "zhipuai_txt_api"
|
|
CATEGORY = "ChatGlm_Api"
|
|
|
|
|
|
def zhipuai_txt_api(self, prompt, model_name, max_tokens, temperature, output_language):
|
|
if not self.api_key:
|
|
raise ValueError("API key is required")
|
|
if prompt == None:
|
|
raise ValueError("need prompt")
|
|
else:
|
|
if output_language == "English":
|
|
prompt_txt = 'Reply in English'
|
|
else:
|
|
prompt_txt = '用提问的语言回复我'
|
|
prompt = ''.join([prompt, prompt_txt])
|
|
url = "https://open.bigmodel.cn/api/paas/v4/chat/completions"
|
|
exp_seconds = int(9)
|
|
client_key = str(get_zpai_api_key())
|
|
token = generate_token(apikey_s=client_key, exp_second=exp_seconds)
|
|
header_txt = {
|
|
'Authorization': f'Bearer {token}',
|
|
'Content-Type': 'application/json'
|
|
}
|
|
data_txt = {"model": f"{model_name}",'max_tokens': f'{max_tokens}','temperature': f'{temperature}', "messages": [{"role": "user", "content": f"{prompt}"}]}
|
|
data_txt = json.dumps(data_txt)
|
|
response = requests.post(url=url, headers=header_txt, data=data_txt)
|
|
txt_content = response.json()
|
|
prompt_txt = txt_content.get("choices", 'Default Value')[0]
|
|
prompt_txt = prompt_txt.get("message", 'Default Value')
|
|
prompt_txt = prompt_txt.get("content", 'Default Value')
|
|
prompt = re.sub(r'\n+', '', prompt_txt)
|
|
return (prompt,)
|
|
|
|
|
|
class ZhipuaiApi_Img:
|
|
|
|
def __init__(self):
|
|
self.api_key = get_zpai_api_key()
|
|
if self.api_key is not None:
|
|
client_key = self.api_key
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"prompt": ("STRING", {"default": "Describe this image", "multiline": True}),
|
|
"image": ("IMAGE",),
|
|
"max_tokens": ("INT", {"default": 1024, "min": 128, "max": 8192, "step": 128, "display": "slider"}),
|
|
"temperature": ("FLOAT", {"default": 0.8, "min": 0.01, "max": 0.99, "step": 0.01, "round": False, "display": "slider"}),
|
|
"output_language": (["English", "Original_language"],),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("text",)
|
|
FUNCTION = "zhipuai_img2txt_api"
|
|
CATEGORY = "ChatGlm_Api"
|
|
|
|
def tensor_to_image(self, tensor):
|
|
tensor = tensor.cpu()
|
|
image_np = tensor.squeeze().mul(255).clamp(0, 255).byte().numpy()
|
|
image = Image.fromarray(image_np, mode='RGB')
|
|
return image
|
|
|
|
def zhipuai_img2txt_api(self, prompt, image, max_tokens, temperature, output_language):
|
|
if not self.api_key:
|
|
raise ValueError("API key is required")
|
|
if prompt == None:
|
|
raise ValueError("need prompt")
|
|
if image == None:
|
|
raise ValueError("Needs img")
|
|
else:
|
|
if output_language == "English":
|
|
prompt_img = 'Reply in English'
|
|
else:
|
|
prompt_img = '用提问的语言回复我'
|
|
prompt = ''.join([prompt, prompt_img])
|
|
|
|
url = "https://open.bigmodel.cn/api/paas/v4/chat/completions"
|
|
|
|
exp_seconds = int(9)
|
|
|
|
client_key = str(get_zpai_api_key())
|
|
|
|
token = generate_token(apikey_s=client_key, exp_second=exp_seconds)
|
|
|
|
pil_image = self.tensor_to_image(image)
|
|
|
|
temp_directory = tempfile.gettempdir()
|
|
unique_suffix = "_temp_" + ''.join(random.choice("abcdefghijklmnopqrstuvwxyz") for _ in range(5))
|
|
filename = f"image{unique_suffix}.png"
|
|
img_path = os.path.join(temp_directory, filename)
|
|
|
|
pil_image.save(img_path)
|
|
|
|
# img to base64
|
|
img = cv2.imread(img_path)
|
|
img_data = cv2.imencode('test.PNG', img)[1].tobytes()
|
|
base64_data = base64.b64encode(img_data)
|
|
img_base64 = str(base64_data, encoding='utf-8')
|
|
|
|
header_img = {
|
|
'Authorization': f'Bearer {token}',
|
|
'Content-Type': 'application/json'
|
|
}
|
|
|
|
data_img = {"model": "glm-4v", 'max_tokens': f'{max_tokens}','temperature': f'{temperature}'"messages": [{"role": "user","content": [{"type": "text", "text": f"{prompt}"},{"type": "image_url","image_url": {"url": f"{img_base64}"}}]}]}
|
|
data_img = json.dumps(data_img)
|
|
|
|
response = requests.post(url=url, headers=header_img, data=data_img)
|
|
|
|
img_content = response.json()
|
|
|
|
content_img = img_content.get("choices", 'Default Value')[0]
|
|
content_img = content_img.get("message", 'Default Value')
|
|
content_img = content_img.get("content", 'Default Value')
|
|
prompt = re.sub(r'\n+', '', content_img)
|
|
|
|
os.remove(img_path)
|
|
|
|
return (prompt,)
|
|
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"ZhipuaiApi_Txt": ZhipuaiApi_Txt,
|
|
"ZhipuaiApi_img": ZhipuaiApi_Img
|
|
}
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
"ZhipuaiApi_Txt": "ZhipuaiApi_Txt",
|
|
"ZhipuaiApi_Img": "ZhipuaiApi_Img"
|
|
}
|