From c3d110359ef63cb55861f08e3616487cd83a9e45 Mon Sep 17 00:00:00 2001 From: ikaros <327209194@qq.com> Date: Wed, 28 Feb 2024 20:57:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=99=BA=E8=B0=B1AI=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?=E5=BA=94=E7=94=A8=20=E5=8A=9F=E8=83=BD=E7=9A=84=E5=AF=B9?= =?UTF-8?q?=E6=8E=A5=EF=BC=9B=E5=8A=A8=E6=80=81=E6=96=87=E6=A1=88=20?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E6=96=B0=E5=A2=9E=E6=96=87=E6=A1=88=E7=BB=84?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=A0=E9=99=A4=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9ELLM=E7=B1=BB=E5=9E=8B=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E6=8C=87=E5=AE=9A=E5=8A=A8=E6=80=81=E6=96=87=E6=A1=88?= =?UTF-8?q?=E9=80=89=E7=94=A8=E7=9A=84LLM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.json | 2 + config.json.bak | 2 + main.py | 2 +- requirements.txt | 3 +- requirements_common.txt | 3 +- tests/test_zhipu/api.py | 123 +++++++++++++++++++++++++++++++++++- tests/test_zhipu/app_api.py | 112 ++++++++++++++++++++++++++++++++ utils/common.py | 4 +- utils/gpt_model/zhipu.py | 119 ++++++++++++++++++++++++++++++++++ webui.py | 73 +++++++++++++++++++-- 10 files changed, 430 insertions(+), 13 deletions(-) create mode 100644 tests/test_zhipu/app_api.py diff --git a/config.json b/config.json index 36b6c4be..ad9903fc 100644 --- a/config.json +++ b/config.json @@ -206,6 +206,7 @@ "zhipu": { "api_key": "", "model": "chatglm_lite", + "app_id": "1761340125461340161", "top_p": "0.7", "temperature": "0.9", "history_enable": true, @@ -744,6 +745,7 @@ }, "trends_copywriting": { "enable": false, + "llm_type": "chatgpt", "copywriting": [ { "folder_path": "data/动态文案1", diff --git a/config.json.bak b/config.json.bak index 36b6c4be..ad9903fc 100644 --- a/config.json.bak +++ b/config.json.bak @@ -206,6 +206,7 @@ "zhipu": { "api_key": "", "model": "chatglm_lite", + "app_id": "1761340125461340161", "top_p": "0.7", "temperature": "0.9", "history_enable": true, @@ -744,6 +745,7 @@ }, "trends_copywriting": { "enable": false, + "llm_type": "chatgpt", "copywriting": [ { "folder_path": "data/动态文案1", diff --git a/main.py b/main.py index f83a8275..bc962761 100644 --- a/main.py +++ b/main.py @@ -611,7 +611,7 @@ async def run_trends_copywriting(): } # 调用函数进行LLM处理,以及生成回复内容,进行音频合成,需要好好考虑考虑实现 - data_json["content"] = my_handle.llm_handle(config.get("chat_type"), data_json) + data_json["content"] = my_handle.llm_handle(config.get("trends_copywriting", "llm_type"), data_json) else: data_json = { "username": "trends_copywriting", diff --git a/requirements.txt b/requirements.txt index 78cbbd88..7629673c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -70,4 +70,5 @@ pygtrans jieba gradio==4.16.0 TikTokLive -azure-cognitiveservices-speech \ No newline at end of file +azure-cognitiveservices-speech +pyjwt \ No newline at end of file diff --git a/requirements_common.txt b/requirements_common.txt index a83ea04f..cd0dddbf 100644 --- a/requirements_common.txt +++ b/requirements_common.txt @@ -148,4 +148,5 @@ pygtrans==1.5.3 jieba==0.42.1 gradio==4.16.0 TikTokLive==5.0.8 -azure-cognitiveservices-speech==1.35.0 \ No newline at end of file +azure-cognitiveservices-speech==1.35.0 +pyjwt==2.8.0 \ No newline at end of file diff --git a/tests/test_zhipu/api.py b/tests/test_zhipu/api.py index 95ac0215..9ffbab37 100644 --- a/tests/test_zhipu/api.py +++ b/tests/test_zhipu/api.py @@ -1,5 +1,13 @@ import zhipuai import logging +import time +import jwt # 确保这是 PyJWT 库 +import requests +import traceback +from urllib.parse import urljoin + +# from utils.common import Common +# from utils.logger import Configure_logger class Zhipu: @@ -9,6 +17,8 @@ def __init__(self, data): # file_path = "./log/log-" + self.common.get_bj_time(1) + ".txt" # Configure_logger(file_path) + self.config_data = data + zhipuai.api_key = data["api_key"] self.model = data["model"] self.top_p = float(data["top_p"]) @@ -21,8 +31,44 @@ def __init__(self, data): self.bot_name = data["bot_name"] self.user_name = data["user_name"] + # 非SDK + self.base_url = "https://open.bigmodel.cn" + self.token = None + self.headers = None + if self.model == "应用": + try: + self.token = self.generate_token(apikey=self.config_data["api_key"], exp_seconds=30 * 24 * 3600) + + self.headers = { + "Authorization": f"Bearer {self.token}", + } + + url = urljoin(self.base_url, "/api/llm-application/open/application") + + data = { + "page": 1, + "size": 100 + } + + # get请求 + response = requests.get(url=url, data=data, headers=self.headers) + + logging.debug(response.json()) + + resp_json = response.json() + + tmp_content = "智谱应用列表:" + + for data in resp_json["data"]["list"]: + tmp_content += f"\n应用名:{data['name']},应用ID:{data['id']},知识库:{data['knowledge_ids']}" + + logging.info(tmp_content) + except Exception as e: + logging.error(traceback.format_exc()) + self.history = [] + # 进行智谱AI 通用大模型请求 def invoke_example(self, prompt): response = zhipuai.model_api.invoke( model=self.model, @@ -34,6 +80,7 @@ def invoke_example(self, prompt): return response + # 进行characterglm请求 def invoke_characterglm(self, prompt): response = zhipuai.model_api.invoke( model=self.model, @@ -51,6 +98,7 @@ def invoke_characterglm(self, prompt): return response + def async_invoke_example(self, prompt): response = zhipuai.model_api.async_invoke( model=self.model, @@ -96,6 +144,28 @@ def query_async_invoke_result_example(self): return response + # 非SDK鉴权 + def generate_token(self, apikey: str, exp_seconds: int): + try: + id, secret = apikey.split(".") + except Exception as e: + raise Exception("invalid apikey", e) + + payload = { + "api_key": id, + "exp": int(round(time.time())) + exp_seconds, # PyJWT中exp字段期望的是秒级的时间戳 + "timestamp": int(round(time.time() * 1000)), # 如果需要毫秒级时间戳,可以保留这一行 + } + + # 使用PyJWT编码payload + token = jwt.encode( + payload, + secret, + headers={"alg": "HS256", "sign_type": "SIGN"} + ) + + return token + def get_resp(self, prompt): """请求对应接口,获取返回值 @@ -117,13 +187,61 @@ def get_resp(self, prompt): if self.model == "characterglm": ret = self.invoke_characterglm(data_json) + elif self.model == "应用": + url = urljoin(self.base_url, f"/api/llm-application/open/model-api/{self.config_data['app_id']}/invoke") + + self.history.append({"role": "user", "content": prompt}) + data = { + "prompt": self.history, + "returnType": "json_string", + # "knowledge_ids": [], + # "document_ids": [] + } + + response = requests.post(url=url, json=data, headers=self.headers) + + try: + resp_json = response.json() + + logging.debug(resp_json) + + resp_content = resp_json["data"]["content"] + + # 启用历史就给我记住! + if self.history_enable: + # 把机器人回答添加到历史记录中 + self.history.append({"role": "assistant", "content": resp_content}) + + while True: + # 获取嵌套列表中所有字符串的字符数 + total_chars = sum(len(string) for sublist in self.history for string in sublist) + # 如果大于限定最大历史数,就剔除第1 2个元素 + if total_chars > self.history_max_len: + self.history.pop(0) + self.history.pop(0) + else: + break + + return resp_content + except Exception as e: + def is_odd(number): + # 检查数除以2的余数是否为1 + return number % 2 != 0 + + # 保持history始终为偶数个 + if is_odd(len(self.history)): + self.history.pop(0) + + logging.error(traceback.format_exc()) + return None + else: ret = self.invoke_example(data_json) logging.debug(f"ret={ret}") if False == ret['success']: - logging.error(f"请求zhipuai失败,错误代码:{ret['code']},{ret['msg']}") + logging.error(f"请求智谱ai失败,错误代码:{ret['code']},{ret['msg']}") return None # 启用历史就给我记住! @@ -140,7 +258,7 @@ def get_resp(self, prompt): return ret['data']['choices'][0]['content'] except Exception as e: - logging.error(e) + logging.error(traceback.format_exc()) return None @@ -154,6 +272,7 @@ def get_resp(self, prompt): data = { "api_key": "", + "app_id": "1761340125461340161", # chatglm_pro/chatglm_std/chatglm_lite/characterglm "model": "characterglm", "top_p": 0.7, diff --git a/tests/test_zhipu/app_api.py b/tests/test_zhipu/app_api.py new file mode 100644 index 00000000..b18a9093 --- /dev/null +++ b/tests/test_zhipu/app_api.py @@ -0,0 +1,112 @@ +# import time +# import jwt + +# def generate_token(apikey: str, exp_seconds: int): +# try: +# id, secret = apikey.split(".") +# except Exception as e: +# raise Exception("invalid apikey", e) + +# payload = { +# "api_key": id, +# "exp": int(round(time.time() * 1000)) + exp_seconds * 1000, +# "timestamp": int(round(time.time() * 1000)), +# } + +# tmp = jwt.JWT() + +# return tmp.encode( +# payload, +# secret, +# alg="HS256", +# optional_headers={"alg": "HS256", "sign_type": "SIGN"}, +# ) + +# print(generate_token("25571a2d0af8583121c3248be7e89d29.AuIX3O5ktKuQVMtC", 30 * 24 * 3600)) + +import time +import jwt # 确保这是 PyJWT 库 +import requests +from urllib.parse import urljoin + +def generate_token(apikey: str, exp_seconds: int): + try: + id, secret = apikey.split(".") + except Exception as e: + raise Exception("invalid apikey", e) + + payload = { + "api_key": id, + "exp": int(round(time.time())) + exp_seconds, # PyJWT中exp字段期望的是秒级的时间戳 + "timestamp": int(round(time.time() * 1000)), # 如果需要毫秒级时间戳,可以保留这一行 + } + + # 使用PyJWT编码payload + token = jwt.encode( + payload, + secret, + headers={"alg": "HS256", "sign_type": "SIGN"} + ) + + return token + + +token = generate_token("", 30 * 24 * 3600) + +print(token) + +base_url = "https://open.bigmodel.cn" + +headers = { + "Authorization": f"Bearer {token}", +} + +url = urljoin(base_url, "/api/llm-application/open/application") + +data = { + "page": 1, + "size": 20 +} + +# get请求 +response = requests.get(url=url, data=data, headers=headers) + +print(response.json()) + +resp_json = response.json() + +tmp_content = "智谱应用列表:" + +app_id = None + +try: + for data in resp_json["data"]["list"]: + tmp_content += f"\n应用名:{data['name']},应用ID:{data['id']},知识库:{data['knowledge_ids']}" + app_id = data['id'] + + print(tmp_content) +except Exception as e: + print(e) + +def get_resp(prompt): + url = urljoin(base_url, f"/api/llm-application/open/model-api/{app_id}/invoke") + data = { + "prompt": [{"role": "user", "content": prompt}], + "returnType": "json_string", + # "knowledge_ids": [], + # "document_ids": [] + } + + response = requests.post(url=url, json=data, headers=headers) + + try: + print(response.json()) + + resp_json = response.json() + resp_content = resp_json["data"]["content"] + + print(resp_content) + except Exception as e: + print(e) + +get_resp("伊卡洛斯和妮姆芙的关系") diff --git a/utils/common.py b/utils/common.py index a53ef41a..9a064d35 100644 --- a/utils/common.py +++ b/utils/common.py @@ -733,11 +733,11 @@ def write_content_to_file(self, file_path, content, write_log=True): try: with open(file_path, 'w', encoding='utf-8') as file: file.write(content) - logging.info(f"内容已成功写入文件:{file_path}") + logging.info(f"写入文件:{file_path},内容:【{content}】") return True except IOError as e: - logging.error(f"无法写入文件:{file_path}\n{e}") + logging.error(f"无法写入 【{content}】 到文件:{file_path}\n{e}") return False # 移动文件到指定路径 src dest diff --git a/utils/gpt_model/zhipu.py b/utils/gpt_model/zhipu.py index aee847d5..15bb7495 100644 --- a/utils/gpt_model/zhipu.py +++ b/utils/gpt_model/zhipu.py @@ -3,6 +3,11 @@ import traceback import re +import time +import jwt # 确保这是 PyJWT 库 +import requests +from urllib.parse import urljoin + from utils.common import Common from utils.logger import Configure_logger @@ -13,6 +18,8 @@ def __init__(self, data): file_path = "./log/log-" + self.common.get_bj_time(1) + ".txt" Configure_logger(file_path) + self.config_data = data + zhipuai.api_key = data["api_key"] self.model = data["model"] self.top_p = float(data["top_p"]) @@ -27,6 +34,42 @@ def __init__(self, data): self.remove_useless = data["remove_useless"] + # 非SDK + self.base_url = "https://open.bigmodel.cn" + self.token = None + self.headers = None + if self.model == "应用": + try: + self.token = self.generate_token(apikey=self.config_data["api_key"], exp_seconds=30 * 24 * 3600) + + self.headers = { + "Authorization": f"Bearer {self.token}", + } + + url = urljoin(self.base_url, "/api/llm-application/open/application") + + data = { + "page": 1, + "size": 100 + } + + # get请求 + response = requests.get(url=url, data=data, headers=self.headers) + + logging.debug(response.json()) + + resp_json = response.json() + + tmp_content = "智谱应用列表:" + + for data in resp_json["data"]["list"]: + tmp_content += f"\n应用名:{data['name']},应用ID:{data['id']},知识库:{data['knowledge_ids']}" + + logging.info(tmp_content) + except Exception as e: + logging.error(traceback.format_exc()) + + self.history = [] def invoke_example(self, prompt): @@ -102,6 +145,27 @@ def query_async_invoke_result_example(self): return response + # 非SDK鉴权 + def generate_token(self, apikey: str, exp_seconds: int): + try: + id, secret = apikey.split(".") + except Exception as e: + raise Exception("invalid apikey", e) + + payload = { + "api_key": id, + "exp": int(round(time.time())) + exp_seconds, # PyJWT中exp字段期望的是秒级的时间戳 + "timestamp": int(round(time.time() * 1000)), # 如果需要毫秒级时间戳,可以保留这一行 + } + + # 使用PyJWT编码payload + token = jwt.encode( + payload, + secret, + headers={"alg": "HS256", "sign_type": "SIGN"} + ) + + return token # 使用正则表达式替换多个反斜杠为一个反斜杠 def remove_extra_backslashes(self, input_string): @@ -153,6 +217,61 @@ def get_resp(self, prompt): if self.model == "characterglm": ret = self.invoke_characterglm(data_json) + elif self.model == "应用": + url = urljoin(self.base_url, f"/api/llm-application/open/model-api/{self.config_data['app_id']}/invoke") + + data = { + "prompt": data_json, + "returnType": "json_string", + # "knowledge_ids": [], + # "document_ids": [] + } + + response = requests.post(url=url, json=data, headers=self.headers) + + try: + resp_json = response.json() + + logging.debug(resp_json) + + resp_content = resp_json["data"]["content"] + + # 启用历史就给我记住! + if self.history_enable: + # 把机器人回答添加到历史记录中 + self.history.append({"role": "assistant", "content": resp_content}) + + while True: + # 获取嵌套列表中所有字符串的字符数 + total_chars = sum(len(string) for sublist in self.history for string in sublist) + # 如果大于限定最大历史数,就剔除第1 2个元素 + if total_chars > self.history_max_len: + self.history.pop(0) + self.history.pop(0) + else: + break + + # 返回的文本回答,追加删除\n 字符 + resp_content = resp_content.replace("\\n", "") + # 使用正则表达式替换多个反斜杠为一个反斜杠 + resp_content = self.remove_extra_backslashes(resp_content) + + if self.remove_useless: + resp_content = self.remove_useless_and_contents(resp_content) + + return resp_content + except Exception as e: + def is_odd(number): + # 检查数除以2的余数是否为1 + return number % 2 != 0 + + # 保持history始终为偶数个 + if is_odd(len(self.history)): + self.history.pop(0) + + logging.error(traceback.format_exc()) + return None + else: ret = self.invoke_example(data_json) diff --git a/webui.py b/webui.py index 9a58f1a8..d78940e2 100644 --- a/webui.py +++ b/webui.py @@ -602,6 +602,50 @@ def copywriting_pause_play(): logging.info("暂停文案完毕~") ui.notify(position="top", type="positive", message="暂停文案完毕~") + + """ + 动态文案 + """ + # 动态文案-增加 + def trends_copywriting_add(): + data_len = len(trends_copywriting_copywriting_var) + tmp_config = { + "folder_path": "", + "prompt_change_enable": False, + "prompt_change_content": "" + } + + with trends_copywriting_config_card.style(card_css): + with ui.row(): + trends_copywriting_copywriting_var[str(data_len)] = ui.input(label=f"文案路径#{int(data_len / 3) + 1}", value=tmp_config["folder_path"], placeholder='文案文件存储的文件夹路径').style("width:200px;") + trends_copywriting_copywriting_var[str(data_len + 1)] = ui.switch(text=f"提示词转换#{int(data_len / 3) + 1}", value=tmp_config["prompt_change_enable"]) + trends_copywriting_copywriting_var[str(data_len + 2)] = ui.input(label=f"提示词转换内容#{int(data_len / 3) + 1}", value=tmp_config["prompt_change_content"], placeholder='使用此提示词内容对文案内容进行转换后再进行合成,使用的LLM为聊天类型配置').style("width:500px;") + + + # 动态文案-删除 + def trends_copywriting_del(index): + try: + trends_copywriting_config_card.remove(int(index) - 1) + # 删除操作 + keys_to_delete = [str(3 * (int(index) - 1) + i) for i in range(3)] + for key in keys_to_delete: + if key in trends_copywriting_copywriting_var: + del trends_copywriting_copywriting_var[key] + + # 重新编号剩余的键 + updates = {} + for key in sorted(trends_copywriting_copywriting_var.keys(), key=int): + new_key = str(int(key) - 3 if int(key) > int(keys_to_delete[-1]) else key) + updates[new_key] = trends_copywriting_copywriting_var[key] + + # 应用更新 + trends_copywriting_copywriting_var.clear() + trends_copywriting_copywriting_var.update(updates) + except Exception as e: + ui.notify(position="top", type="negative", message=f"错误,索引值配置有误:{e}") + logging.error(traceback.format_exc()) + + """ 配置操作 """ @@ -870,6 +914,7 @@ def common_textarea_handle(content): # 动态文案 if config.get("webui", "show_card", "common_config", "trends_copywriting"): config_data["trends_copywriting"]["enable"] = switch_trends_copywriting_enable.value + config_data["trends_copywriting"]["llm_type"] = select_trends_copywriting_llm_type.value config_data["trends_copywriting"]["random_play"] = switch_trends_copywriting_random_play.value config_data["trends_copywriting"]["play_interval"] = int(input_trends_copywriting_play_interval.value) tmp_arr = [] @@ -1094,6 +1139,7 @@ def common_textarea_handle(content): if config.get("webui", "show_card", "llm", "zhipu"): config_data["zhipu"]["api_key"] = input_zhipu_api_key.value config_data["zhipu"]["model"] = select_zhipu_model.value + config_data["zhipu"]["app_id"] = input_zhipu_app_id.value config_data["zhipu"]["top_p"] = input_zhipu_top_p.value config_data["zhipu"]["temperature"] = input_zhipu_temperature.value config_data["zhipu"]["history_enable"] = switch_zhipu_history_enable.value @@ -2020,16 +2066,29 @@ def common_textarea_handle(content): if config.get("webui", "show_card", "common_config", "trends_copywriting"): with ui.card().style(card_css): ui.label('动态文案') - with ui.grid(columns=3): + with ui.row(): switch_trends_copywriting_enable = ui.switch('启用', value=config.get("trends_copywriting", "enable")).style(switch_internal_css) + select_trends_copywriting_llm_type = ui.select( + label='LLM类型', + options=chat_type_options, + value=config.get("trends_copywriting", "llm_type") + ).style("width:200px;") switch_trends_copywriting_random_play = ui.switch('随机播放', value=config.get("trends_copywriting", "random_play")).style(switch_internal_css) input_trends_copywriting_play_interval = ui.input(label='文案播放间隔', value=config.get("trends_copywriting", "play_interval"), placeholder='文案于文案之间的播放间隔时间(秒)').style("width:200px;") + + with ui.row(): + input_trends_copywriting_index = ui.input(label='文案索引', value="", placeholder='文案组的排序号,就是说第一个组是1,第二个组是2,以此类推。请填写纯正整数') + button_trends_copywriting_add = ui.button('增加文案组', on_click=trends_copywriting_add, color=button_internal_color).style(button_internal_css) + button_trends_copywriting_del = ui.button('删除文案组', on_click=lambda: trends_copywriting_del(input_trends_copywriting_index.value), color=button_internal_color).style(button_internal_css) + trends_copywriting_copywriting_var = {} + trends_copywriting_config_card = ui.card() for index, trends_copywriting_copywriting in enumerate(config.get("trends_copywriting", "copywriting")): - with ui.grid(columns=3): - trends_copywriting_copywriting_var[str(3 * index)] = ui.input(label=f"文案路径{index}", value=trends_copywriting_copywriting["folder_path"], placeholder='文案文件存储的文件夹路径').style("width:200px;") - trends_copywriting_copywriting_var[str(3 * index + 1)] = ui.switch(text="提示词转换", value=trends_copywriting_copywriting["prompt_change_enable"]) - trends_copywriting_copywriting_var[str(3 * index + 2)] = ui.input(label="提示词转换内容", value=trends_copywriting_copywriting["prompt_change_content"], placeholder='使用此提示词内容对文案内容进行转换后再进行合成,使用的LLM为聊天类型配置').style("width:200px;") + with trends_copywriting_config_card.style(card_css): + with ui.row(): + trends_copywriting_copywriting_var[str(3 * index)] = ui.input(label=f"文案路径#{index + 1}", value=trends_copywriting_copywriting["folder_path"], placeholder='文案文件存储的文件夹路径').style("width:200px;") + trends_copywriting_copywriting_var[str(3 * index + 1)] = ui.switch(text=f"提示词转换#{index + 1}", value=trends_copywriting_copywriting["prompt_change_enable"]) + trends_copywriting_copywriting_var[str(3 * index + 2)] = ui.input(label=f"提示词转换内容#{index + 1}", value=trends_copywriting_copywriting["prompt_change_content"], placeholder='使用此提示词内容对文案内容进行转换后再进行合成,使用的LLM为聊天类型配置').style("width:500px;") if config.get("webui", "show_card", "common_config", "web_captions_printer"): with ui.card().style(card_css): @@ -2475,7 +2534,7 @@ def common_textarea_handle(content): with ui.row(): input_zhipu_api_key = ui.input(label='api key', placeholder='具体参考官方文档,申请地址:https://open.bigmodel.cn/usercenter/apikeys', value=config.get("zhipu", "api_key")) input_zhipu_api_key.style("width:400px") - lines = ['glm-3-turbo', 'glm-4', 'characterglm', 'chatglm_turbo', 'chatglm_pro', 'chatglm_std', 'chatglm_lite', 'chatglm_lite_32k'] + lines = ['glm-3-turbo', 'glm-4', 'characterglm', 'chatglm_turbo', 'chatglm_pro', 'chatglm_std', 'chatglm_lite', 'chatglm_lite_32k', '应用'] data_json = {} for line in lines: data_json[line] = line @@ -2484,6 +2543,8 @@ def common_textarea_handle(content): options=data_json, value=config.get("zhipu", "model") ) + input_zhipu_app_id = ui.input(label='应用ID', value=config.get("zhipu", "app_id"), placeholder='在 模型为:应用,会自动检索你平台上添加的所有应用信息,然后从日志中复制你需要的应用ID即可').style("width:200px") + with ui.row(): input_zhipu_top_p = ui.input(label='top_p', placeholder='用温度取样的另一种方法,称为核取样\n取值范围是:(0.0,1.0);开区间,不能等于 0 或 1,默认值为 0.7\n模型考虑具有 top_p 概率质量的令牌的结果。所以 0.1 意味着模型解码器只考虑从前 10% 的概率的候选集中取tokens\n建议您根据应用场景调整 top_p 或 temperature 参数,但不要同时调整两个参数', value=config.get("zhipu", "top_p")) input_zhipu_top_p.style("width:200px")