Version 3.74: Merge latest updates on dev branch (frontier) (#1621)
* Update version to 3.74 * Add support for Yi Model API (#1635) * 更新以支持零一万物模型 * 删除newbing * 修改config --------- Co-authored-by: binary-husky <qingxu.fu@outlook.com> * Refactor function signatures in bridge files * fix qwen api change * rename and ref functions * rename and move some cookie functions * 增加haiku模型,新增endpoint配置说明 (#1626) * haiku added * 新增haiku,新增endpoint配置说明 * Haiku added * 将说明同步至最新Endpoint --------- Co-authored-by: binary-husky <qingxu.fu@outlook.com> * private_upload目录下进行文件鉴权 (#1596) * private_upload目录下进行文件鉴权 * minor fastapi adjustment * Add logging functionality to enable saving conversation records * waiting to fix username retrieve * support 2rd web path * allow accessing default user dir --------- Co-authored-by: binary-husky <qingxu.fu@outlook.com> * remove yaml deps * fix favicon * fix abs path auth problem * forget to write a return * add `dashscope` to deps * fix GHSA-v9q9-xj86-953p * 用户名重叠越权访问patch (#1681) * add cohere model api access * cohere + can_multi_thread * fix block user access(fail) * fix fastapi bug * change cohere api endpoint * explain version --------- Co-authored-by: Menghuan1918 <menghuan2003@outlook.com> Co-authored-by: Skyzayre <120616113+Skyzayre@users.noreply.github.com> Co-authored-by: XIao <46100050+Kilig947@users.noreply.github.com>
This commit is contained in:
parent
ae51a0e686
commit
bdd46c5dd1
@ -45,7 +45,7 @@ AVAIL_LLM_MODELS = ["gpt-4-1106-preview", "gpt-4-turbo-preview", "gpt-4-vision-p
|
||||
# "qwen-turbo", "qwen-plus", "qwen-max", "qwen-local",
|
||||
# "moonshot-v1-128k", "moonshot-v1-32k", "moonshot-v1-8k",
|
||||
# "gpt-3.5-turbo-0613", "gpt-3.5-turbo-16k-0613", "gpt-3.5-turbo-0125"
|
||||
# "claude-3-sonnet-20240229","claude-3-opus-20240229", "claude-2.1", "claude-instant-1.2",
|
||||
# "claude-3-haiku-20240307","claude-3-sonnet-20240229","claude-3-opus-20240229", "claude-2.1", "claude-instant-1.2",
|
||||
# "moss", "llama2", "chatglm_onnx", "internlm", "jittorllms_pangualpha", "jittorllms_llama",
|
||||
# "yi-34b-chat-0205", "yi-34b-chat-200k"
|
||||
# ]
|
||||
@ -157,7 +157,8 @@ ADD_WAIFU = False
|
||||
AUTHENTICATION = []
|
||||
|
||||
|
||||
# 如果需要在二级路径下运行(常规情况下,不要修改!!)(需要配合修改main.py才能生效!)
|
||||
# 如果需要在二级路径下运行(常规情况下,不要修改!!)
|
||||
# (举例 CUSTOM_PATH = "/gpt_academic",可以让软件运行在 http://ip:port/gpt_academic/ 下。)
|
||||
CUSTOM_PATH = "/"
|
||||
|
||||
|
||||
@ -377,4 +378,4 @@ NUM_CUSTOM_BASIC_BTN = 4
|
||||
└── MATHPIX_APPKEY
|
||||
|
||||
|
||||
"""
|
||||
"""
|
||||
|
120
main.py
120
main.py
@ -13,6 +13,17 @@ help_menu_description = \
|
||||
</br></br>如何语音对话: 请阅读Wiki
|
||||
</br></br>如何临时更换API_KEY: 在输入区输入临时API_KEY后提交(网页刷新后失效)"""
|
||||
|
||||
def enable_log(PATH_LOGGING):
|
||||
import logging, uuid
|
||||
admin_log_path = os.path.join(PATH_LOGGING, "admin")
|
||||
os.makedirs(admin_log_path, exist_ok=True)
|
||||
log_dir = os.path.join(admin_log_path, "chat_secrets.log")
|
||||
try:logging.basicConfig(filename=log_dir, level=logging.INFO, encoding="utf-8", format="%(asctime)s %(levelname)-8s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
except:logging.basicConfig(filename=log_dir, level=logging.INFO, format="%(asctime)s %(levelname)-8s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
# Disable logging output from the 'httpx' logger
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
print(f"所有对话记录将自动保存在本地目录{log_dir}, 请注意自我隐私保护哦!")
|
||||
|
||||
def main():
|
||||
import gradio as gr
|
||||
if gr.__version__ not in ['3.32.9']:
|
||||
@ -31,18 +42,11 @@ def main():
|
||||
from check_proxy import get_current_version
|
||||
from themes.theme import adjust_theme, advanced_css, theme_declaration, js_code_clear, js_code_reset, js_code_show_or_hide, js_code_show_or_hide_group2
|
||||
from themes.theme import js_code_for_css_changing, js_code_for_toggle_darkmode, js_code_for_persistent_cookie_init
|
||||
from themes.theme import load_dynamic_theme, to_cookie_str, from_cookie_str, init_cookie
|
||||
from themes.theme import load_dynamic_theme, to_cookie_str, from_cookie_str, assign_user_uuid
|
||||
title_html = f"<h1 align=\"center\">GPT 学术优化 {get_current_version()}</h1>{theme_declaration}"
|
||||
|
||||
# 对话记录, python 版本建议3.9+(越新越好)
|
||||
import logging, uuid
|
||||
os.makedirs(PATH_LOGGING, exist_ok=True)
|
||||
chat_secrets_log = os.path.join(PATH_LOGGING, "chat_secrets.log")
|
||||
try:logging.basicConfig(filename=chat_secrets_log, level=logging.INFO, encoding="utf-8", format="%(asctime)s %(levelname)-8s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
except:logging.basicConfig(filename=chat_secrets_log, level=logging.INFO, format="%(asctime)s %(levelname)-8s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
# Disable logging output from the 'httpx' logger
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
print(f"所有对话记录将自动保存在本地目录 {chat_secrets_log}, 请注意自我隐私保护哦!")
|
||||
# 对话、日志记录
|
||||
enable_log(PATH_LOGGING)
|
||||
|
||||
# 一些普通功能模块
|
||||
from core_functional import get_core_functions
|
||||
@ -75,9 +79,9 @@ def main():
|
||||
cancel_handles = []
|
||||
customize_btns = {}
|
||||
predefined_btns = {}
|
||||
with gr.Blocks(title="GPT 学术优化", theme=set_theme, analytics_enabled=False, css=advanced_css) as demo:
|
||||
with gr.Blocks(title="GPT 学术优化", theme=set_theme, analytics_enabled=False, css=advanced_css) as app_block:
|
||||
gr.HTML(title_html)
|
||||
secret_css, py_pickle_cookie = gr.Textbox(visible=False), gr.Textbox(visible=False)
|
||||
secret_css, web_cookie_cache = gr.Textbox(visible=False), gr.Textbox(visible=False)
|
||||
cookies = gr.State(load_chat_cookies())
|
||||
with gr_L1():
|
||||
with gr_L2(scale=2, elem_id="gpt-chat"):
|
||||
@ -199,64 +203,19 @@ def main():
|
||||
with gr.Column(scale=1, min_width=70):
|
||||
basic_fn_confirm = gr.Button("确认并保存", variant="primary"); basic_fn_confirm.style(size="sm")
|
||||
basic_fn_clean = gr.Button("恢复默认", variant="primary"); basic_fn_clean.style(size="sm")
|
||||
def assign_btn(persistent_cookie_, cookies_, basic_btn_dropdown_, basic_fn_title, basic_fn_prefix, basic_fn_suffix, clean_up=False):
|
||||
ret = {}
|
||||
# 读取之前的自定义按钮
|
||||
customize_fn_overwrite_ = cookies_['customize_fn_overwrite']
|
||||
# 更新新的自定义按钮
|
||||
customize_fn_overwrite_.update({
|
||||
basic_btn_dropdown_:
|
||||
{
|
||||
"Title":basic_fn_title,
|
||||
"Prefix":basic_fn_prefix,
|
||||
"Suffix":basic_fn_suffix,
|
||||
}
|
||||
}
|
||||
)
|
||||
if clean_up:
|
||||
customize_fn_overwrite_ = {}
|
||||
cookies_.update(customize_fn_overwrite_) # 更新cookie
|
||||
visible = (not clean_up) and (basic_fn_title != "")
|
||||
if basic_btn_dropdown_ in customize_btns:
|
||||
# 是自定义按钮,不是预定义按钮
|
||||
ret.update({customize_btns[basic_btn_dropdown_]: gr.update(visible=visible, value=basic_fn_title)})
|
||||
else:
|
||||
# 是预定义按钮
|
||||
ret.update({predefined_btns[basic_btn_dropdown_]: gr.update(visible=visible, value=basic_fn_title)})
|
||||
ret.update({cookies: cookies_})
|
||||
try: persistent_cookie_ = from_cookie_str(persistent_cookie_) # persistent cookie to dict
|
||||
except: persistent_cookie_ = {}
|
||||
persistent_cookie_["custom_bnt"] = customize_fn_overwrite_ # dict update new value
|
||||
persistent_cookie_ = to_cookie_str(persistent_cookie_) # persistent cookie to dict
|
||||
ret.update({py_pickle_cookie: persistent_cookie_}) # write persistent cookie
|
||||
return ret
|
||||
|
||||
from shared_utils.cookie_manager import assign_btn__fn_builder
|
||||
assign_btn = assign_btn__fn_builder(customize_btns, predefined_btns, cookies, web_cookie_cache)
|
||||
# update btn
|
||||
h = basic_fn_confirm.click(assign_btn, [py_pickle_cookie, cookies, basic_btn_dropdown, basic_fn_title, basic_fn_prefix, basic_fn_suffix],
|
||||
[py_pickle_cookie, cookies, *customize_btns.values(), *predefined_btns.values()])
|
||||
h.then(None, [py_pickle_cookie], None, _js="""(py_pickle_cookie)=>{setCookie("py_pickle_cookie", py_pickle_cookie, 365);}""")
|
||||
h = basic_fn_confirm.click(assign_btn, [web_cookie_cache, cookies, basic_btn_dropdown, basic_fn_title, basic_fn_prefix, basic_fn_suffix],
|
||||
[web_cookie_cache, cookies, *customize_btns.values(), *predefined_btns.values()])
|
||||
h.then(None, [web_cookie_cache], None, _js="""(web_cookie_cache)=>{setCookie("web_cookie_cache", web_cookie_cache, 365);}""")
|
||||
# clean up btn
|
||||
h2 = basic_fn_clean.click(assign_btn, [py_pickle_cookie, cookies, basic_btn_dropdown, basic_fn_title, basic_fn_prefix, basic_fn_suffix, gr.State(True)],
|
||||
[py_pickle_cookie, cookies, *customize_btns.values(), *predefined_btns.values()])
|
||||
h2.then(None, [py_pickle_cookie], None, _js="""(py_pickle_cookie)=>{setCookie("py_pickle_cookie", py_pickle_cookie, 365);}""")
|
||||
h2 = basic_fn_clean.click(assign_btn, [web_cookie_cache, cookies, basic_btn_dropdown, basic_fn_title, basic_fn_prefix, basic_fn_suffix, gr.State(True)],
|
||||
[web_cookie_cache, cookies, *customize_btns.values(), *predefined_btns.values()])
|
||||
h2.then(None, [web_cookie_cache], None, _js="""(web_cookie_cache)=>{setCookie("web_cookie_cache", web_cookie_cache, 365);}""")
|
||||
|
||||
def persistent_cookie_reload(persistent_cookie_, cookies_):
|
||||
ret = {}
|
||||
for k in customize_btns:
|
||||
ret.update({customize_btns[k]: gr.update(visible=False, value="")})
|
||||
|
||||
try: persistent_cookie_ = from_cookie_str(persistent_cookie_) # persistent cookie to dict
|
||||
except: return ret
|
||||
|
||||
customize_fn_overwrite_ = persistent_cookie_.get("custom_bnt", {})
|
||||
cookies_['customize_fn_overwrite'] = customize_fn_overwrite_
|
||||
ret.update({cookies: cookies_})
|
||||
|
||||
for k,v in persistent_cookie_["custom_bnt"].items():
|
||||
if v['Title'] == "": continue
|
||||
if k in customize_btns: ret.update({customize_btns[k]: gr.update(visible=True, value=v['Title'])})
|
||||
else: ret.update({predefined_btns[k]: gr.update(visible=True, value=v['Title'])})
|
||||
return ret
|
||||
|
||||
# 功能区显示开关与功能区的互动
|
||||
def fn_area_visibility(a):
|
||||
@ -376,11 +335,14 @@ def main():
|
||||
audio_mic.stream(deal_audio, inputs=[audio_mic, cookies])
|
||||
|
||||
|
||||
demo.load(init_cookie, inputs=[cookies], outputs=[cookies])
|
||||
demo.load(persistent_cookie_reload, inputs = [py_pickle_cookie, cookies],
|
||||
outputs = [py_pickle_cookie, cookies, *customize_btns.values(), *predefined_btns.values()], _js=js_code_for_persistent_cookie_init)
|
||||
demo.load(None, inputs=[], outputs=None, _js=f"""()=>init_frontend_with_cookies("{DARK_MODE}","{INIT_SYS_PROMPT}","{ADD_WAIFU}")""") # 配置暗色主题或亮色主题
|
||||
demo.load(None, inputs=[gr.Textbox(LAYOUT, visible=False)], outputs=None, _js='(LAYOUT)=>{GptAcademicJavaScriptInit(LAYOUT);}')
|
||||
app_block.load(assign_user_uuid, inputs=[cookies], outputs=[cookies])
|
||||
|
||||
from shared_utils.cookie_manager import load_web_cookie_cache__fn_builder
|
||||
load_web_cookie_cache = load_web_cookie_cache__fn_builder(customize_btns, cookies, predefined_btns)
|
||||
app_block.load(load_web_cookie_cache, inputs = [web_cookie_cache, cookies],
|
||||
outputs = [web_cookie_cache, cookies, *customize_btns.values(), *predefined_btns.values()], _js=js_code_for_persistent_cookie_init)
|
||||
|
||||
app_block.load(None, inputs=[], outputs=None, _js=f"""()=>GptAcademicJavaScriptInit("{DARK_MODE}","{INIT_SYS_PROMPT}","{ADD_WAIFU}","{LAYOUT}")""") # 配置暗色主题或亮色主题
|
||||
|
||||
# gradio的inbrowser触发不太稳定,回滚代码到原始的浏览器打开函数
|
||||
def run_delayed_tasks():
|
||||
@ -395,19 +357,15 @@ def main():
|
||||
|
||||
threading.Thread(target=auto_updates, name="self-upgrade", daemon=True).start() # 查看自动更新
|
||||
threading.Thread(target=open_browser, name="open-browser", daemon=True).start() # 打开浏览器页面
|
||||
threading.Thread(target=warm_up_mods, name="warm-up", daemon=True).start() # 预热tiktoken模块
|
||||
threading.Thread(target=warm_up_mods, name="warm-up", daemon=True).start() # 预热tiktoken模块
|
||||
|
||||
# 运行一些异步任务:自动更新、打开浏览器页面、预热tiktoken模块
|
||||
run_delayed_tasks()
|
||||
demo.queue(concurrency_count=CONCURRENT_COUNT).launch(
|
||||
quiet=True,
|
||||
server_name="0.0.0.0",
|
||||
ssl_keyfile=None if SSL_KEYFILE == "" else SSL_KEYFILE,
|
||||
ssl_certfile=None if SSL_CERTFILE == "" else SSL_CERTFILE,
|
||||
ssl_verify=False,
|
||||
server_port=PORT,
|
||||
favicon_path=os.path.join(os.path.dirname(__file__), "docs/logo.png"),
|
||||
auth=AUTHENTICATION if len(AUTHENTICATION) != 0 else None,
|
||||
blocked_paths=["config.py","__pycache__","config_private.py","docker-compose.yml","Dockerfile",f"{PATH_LOGGING}/admin", chat_secrets_log])
|
||||
|
||||
# 最后,正式开始服务
|
||||
from shared_utils.fastapi_server import start_app
|
||||
start_app(app_block, CONCURRENT_COUNT, AUTHENTICATION, PORT, SSL_KEYFILE, SSL_CERTFILE)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -34,6 +34,9 @@ from .bridge_google_gemini import predict_no_ui_long_connection as genai_noui
|
||||
from .bridge_zhipu import predict_no_ui_long_connection as zhipu_noui
|
||||
from .bridge_zhipu import predict as zhipu_ui
|
||||
|
||||
from .bridge_cohere import predict as cohere_ui
|
||||
from .bridge_cohere import predict_no_ui_long_connection as cohere_noui
|
||||
|
||||
colors = ['#FF00FF', '#00FFFF', '#FF0000', '#990099', '#009999', '#990044']
|
||||
|
||||
class LazyloadTiktoken(object):
|
||||
@ -64,6 +67,7 @@ newbing_endpoint = "wss://sydney.bing.com/sydney/ChatHub"
|
||||
gemini_endpoint = "https://generativelanguage.googleapis.com/v1beta/models"
|
||||
claude_endpoint = "https://api.anthropic.com/v1/messages"
|
||||
yimodel_endpoint = "https://api.lingyiwanwu.com/v1/chat/completions"
|
||||
cohere_endpoint = 'https://api.cohere.ai/v1/chat'
|
||||
|
||||
if not AZURE_ENDPOINT.endswith('/'): AZURE_ENDPOINT += '/'
|
||||
azure_endpoint = AZURE_ENDPOINT + f'openai/deployments/{AZURE_ENGINE}/chat/completions?api-version=2023-05-15'
|
||||
@ -82,6 +86,7 @@ if newbing_endpoint in API_URL_REDIRECT: newbing_endpoint = API_URL_REDIRECT[new
|
||||
if gemini_endpoint in API_URL_REDIRECT: gemini_endpoint = API_URL_REDIRECT[gemini_endpoint]
|
||||
if claude_endpoint in API_URL_REDIRECT: claude_endpoint = API_URL_REDIRECT[claude_endpoint]
|
||||
if yimodel_endpoint in API_URL_REDIRECT: yimodel_endpoint = API_URL_REDIRECT[yimodel_endpoint]
|
||||
if cohere_endpoint in API_URL_REDIRECT: cohere_endpoint = API_URL_REDIRECT[cohere_endpoint]
|
||||
|
||||
# 获取tokenizer
|
||||
tokenizer_gpt35 = LazyloadTiktoken("gpt-3.5-turbo")
|
||||
@ -310,6 +315,18 @@ model_info = {
|
||||
"tokenizer": tokenizer_gpt35,
|
||||
"token_cnt": get_token_num_gpt35,
|
||||
},
|
||||
|
||||
# cohere
|
||||
"cohere-command-r-plus": {
|
||||
"fn_with_ui": cohere_ui,
|
||||
"fn_without_ui": cohere_noui,
|
||||
"can_multi_thread": True,
|
||||
"endpoint": cohere_endpoint,
|
||||
"max_token": 1024 * 4,
|
||||
"tokenizer": tokenizer_gpt35,
|
||||
"token_cnt": get_token_num_gpt35,
|
||||
},
|
||||
|
||||
}
|
||||
# -=-=-=-=-=-=- 月之暗面 -=-=-=-=-=-=-
|
||||
from request_llms.bridge_moonshot import predict as moonshot_ui
|
||||
@ -359,7 +376,7 @@ for model in AVAIL_LLM_MODELS:
|
||||
|
||||
# -=-=-=-=-=-=- 以下部分是新加入的模型,可能附带额外依赖 -=-=-=-=-=-=-
|
||||
# claude家族
|
||||
claude_models = ["claude-instant-1.2","claude-2.0","claude-2.1","claude-3-sonnet-20240229","claude-3-opus-20240229"]
|
||||
claude_models = ["claude-instant-1.2","claude-2.0","claude-2.1","claude-3-haiku-20240307","claude-3-sonnet-20240229","claude-3-opus-20240229"]
|
||||
if any(item in claude_models for item in AVAIL_LLM_MODELS):
|
||||
from .bridge_claude import predict_no_ui_long_connection as claude_noui
|
||||
from .bridge_claude import predict as claude_ui
|
||||
@ -393,6 +410,16 @@ if any(item in claude_models for item in AVAIL_LLM_MODELS):
|
||||
"token_cnt": get_token_num_gpt35,
|
||||
},
|
||||
})
|
||||
model_info.update({
|
||||
"claude-3-haiku-20240307": {
|
||||
"fn_with_ui": claude_ui,
|
||||
"fn_without_ui": claude_noui,
|
||||
"endpoint": claude_endpoint,
|
||||
"max_token": 200000,
|
||||
"tokenizer": tokenizer_gpt35,
|
||||
"token_cnt": get_token_num_gpt35,
|
||||
},
|
||||
})
|
||||
model_info.update({
|
||||
"claude-3-sonnet-20240229": {
|
||||
"fn_with_ui": claude_ui,
|
||||
@ -789,7 +816,7 @@ def LLM_CATCH_EXCEPTION(f):
|
||||
"""
|
||||
装饰器函数,将错误显示出来
|
||||
"""
|
||||
def decorated(inputs, llm_kwargs, history, sys_prompt, observe_window, console_slience):
|
||||
def decorated(inputs:str, llm_kwargs:dict, history:list, sys_prompt:str, observe_window:list, console_slience:bool):
|
||||
try:
|
||||
return f(inputs, llm_kwargs, history, sys_prompt, observe_window, console_slience)
|
||||
except Exception as e:
|
||||
@ -799,9 +826,9 @@ def LLM_CATCH_EXCEPTION(f):
|
||||
return decorated
|
||||
|
||||
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list, sys_prompt:str, observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
发送至LLM,等待回复,一次性完成,不显示中间过程。但内部用stream的方法避免中途网线被掐。
|
||||
发送至LLM,等待回复,一次性完成,不显示中间过程。但内部(尽可能地)用stream的方法避免中途网线被掐。
|
||||
inputs:
|
||||
是本次问询的输入
|
||||
sys_prompt:
|
||||
@ -819,7 +846,6 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, obser
|
||||
model = llm_kwargs['llm_model']
|
||||
n_model = 1
|
||||
if '&' not in model:
|
||||
assert not model.startswith("tgui"), "TGUI不支持函数插件的实现"
|
||||
|
||||
# 如果只询问1个大语言模型:
|
||||
method = model_info[model]["fn_without_ui"]
|
||||
@ -880,15 +906,22 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, obser
|
||||
return res
|
||||
|
||||
|
||||
def predict(inputs, llm_kwargs, *args, **kwargs):
|
||||
def predict(inputs:str, llm_kwargs:dict, *args, **kwargs):
|
||||
"""
|
||||
发送至LLM,流式获取输出。
|
||||
用于基础的对话功能。
|
||||
inputs 是本次问询的输入
|
||||
top_p, temperature是LLM的内部调优参数
|
||||
history 是之前的对话列表(注意无论是inputs还是history,内容太长了都会触发token数量溢出的错误)
|
||||
chatbot 为WebUI中显示的对话列表,修改它,然后yeild出去,可以直接修改对话界面内容
|
||||
additional_fn代表点击的哪个按钮,按钮见functional.py
|
||||
|
||||
完整参数列表:
|
||||
predict(
|
||||
inputs:str, # 是本次问询的输入
|
||||
llm_kwargs:dict, # 是LLM的内部调优参数
|
||||
plugin_kwargs:dict, # 是插件的内部参数
|
||||
chatbot:ChatBotWithCookies, # 原样传递,负责向用户前端展示对话,兼顾前端状态的功能
|
||||
history:list=[], # 是之前的对话列表
|
||||
system_prompt:str='', # 系统静默prompt
|
||||
stream:bool=True, # 是否流式输出(已弃用)
|
||||
additional_fn:str=None # 基础功能区按钮的附加功能
|
||||
):
|
||||
"""
|
||||
|
||||
inputs = apply_gpt_academic_string_mask(inputs, mode="show_llm")
|
||||
|
@ -137,7 +137,8 @@ class GetGLMFTHandle(Process):
|
||||
global glmft_handle
|
||||
glmft_handle = None
|
||||
#################################################################################
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="",
|
||||
observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
多线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
|
@ -23,6 +23,7 @@ import random
|
||||
# 读取时首先看是否存在私密的config_private配置文件(不受git管控),如果有,则覆盖原config文件
|
||||
from toolbox import get_conf, update_ui, is_any_api_key, select_api_key, what_keys, clip_history
|
||||
from toolbox import trimmed_format_exc, is_the_upload_folder, read_one_api_model_name, log_chat
|
||||
from toolbox import ChatBotWithCookies
|
||||
proxies, TIMEOUT_SECONDS, MAX_RETRY, API_ORG, AZURE_CFG_ARRAY = \
|
||||
get_conf('proxies', 'TIMEOUT_SECONDS', 'MAX_RETRY', 'API_ORG', 'AZURE_CFG_ARRAY')
|
||||
|
||||
@ -69,7 +70,7 @@ def verify_endpoint(endpoint):
|
||||
raise ValueError("Endpoint不正确, 请检查AZURE_ENDPOINT的配置! 当前的Endpoint为:" + endpoint)
|
||||
return endpoint
|
||||
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=None, console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="", observe_window:list=None, console_slience:bool=False):
|
||||
"""
|
||||
发送至chatGPT,等待回复,一次性完成,不显示中间过程。但内部用stream的方法避免中途网线被掐。
|
||||
inputs:
|
||||
@ -147,7 +148,8 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
|
||||
return result
|
||||
|
||||
|
||||
def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None):
|
||||
def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWithCookies,
|
||||
history:list=[], system_prompt:str='', stream:bool=True, additional_fn:str=None):
|
||||
"""
|
||||
发送至chatGPT,流式获取输出。
|
||||
用于基础的对话功能。
|
||||
|
@ -13,11 +13,11 @@ import logging
|
||||
import os
|
||||
import time
|
||||
import traceback
|
||||
from toolbox import get_conf, update_ui, trimmed_format_exc, encode_image, every_image_file_in_path
|
||||
import json
|
||||
import requests
|
||||
from toolbox import get_conf, update_ui, trimmed_format_exc, encode_image, every_image_file_in_path, log_chat
|
||||
picture_system_prompt = "\n当回复图像时,必须说明正在回复哪张图像。所有图像仅在最后一个问题中提供,即使它们在历史记录中被提及。请使用'这是第X张图像:'的格式来指明您正在描述的是哪张图像。"
|
||||
Claude_3_Models = ["claude-3-sonnet-20240229", "claude-3-opus-20240229"]
|
||||
Claude_3_Models = ["claude-3-haiku-20240307", "claude-3-sonnet-20240229", "claude-3-opus-20240229"]
|
||||
|
||||
# config_private.py放自己的秘密如API和代理网址
|
||||
# 读取时首先看是否存在私密的config_private配置文件(不受git管控),如果有,则覆盖原config文件
|
||||
@ -95,7 +95,7 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
|
||||
# make a POST request to the API endpoint, stream=False
|
||||
from .bridge_all import model_info
|
||||
endpoint = model_info[llm_kwargs['llm_model']]['endpoint']
|
||||
response = requests.post(endpoint, headers=headers, json=message,
|
||||
response = requests.post(endpoint, headers=headers, json=message,
|
||||
proxies=proxies, stream=True, timeout=TIMEOUT_SECONDS);break
|
||||
except requests.exceptions.ReadTimeout as e:
|
||||
retry += 1
|
||||
@ -116,7 +116,7 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
|
||||
if need_to_pass:
|
||||
pass
|
||||
elif is_last_chunk:
|
||||
logging.info(f'[response] {result}')
|
||||
# logging.info(f'[response] {result}')
|
||||
break
|
||||
else:
|
||||
if chunkjson and chunkjson['type'] == 'content_block_delta':
|
||||
@ -194,7 +194,7 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
|
||||
# make a POST request to the API endpoint, stream=True
|
||||
from .bridge_all import model_info
|
||||
endpoint = model_info[llm_kwargs['llm_model']]['endpoint']
|
||||
response = requests.post(endpoint, headers=headers, json=message,
|
||||
response = requests.post(endpoint, headers=headers, json=message,
|
||||
proxies=proxies, stream=True, timeout=TIMEOUT_SECONDS);break
|
||||
except requests.exceptions.ReadTimeout as e:
|
||||
retry += 1
|
||||
@ -216,7 +216,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
|
||||
if need_to_pass:
|
||||
pass
|
||||
elif is_last_chunk:
|
||||
logging.info(f'[response] {gpt_replying_buffer}')
|
||||
log_chat(llm_model=llm_kwargs["llm_model"], input_str=inputs, output_str=gpt_replying_buffer)
|
||||
# logging.info(f'[response] {gpt_replying_buffer}')
|
||||
break
|
||||
else:
|
||||
if chunkjson and chunkjson['type'] == 'content_block_delta':
|
||||
@ -305,4 +306,4 @@ def generate_payload(inputs, llm_kwargs, history, system_prompt, image_paths):
|
||||
'stream': True,
|
||||
'system': system_prompt
|
||||
}
|
||||
return headers, payload
|
||||
return headers, payload
|
||||
|
328
request_llms/bridge_cohere.py
Normal file
328
request_llms/bridge_cohere.py
Normal file
@ -0,0 +1,328 @@
|
||||
# 借鉴了 https://github.com/GaiZhenbiao/ChuanhuChatGPT 项目
|
||||
|
||||
"""
|
||||
该文件中主要包含三个函数
|
||||
|
||||
不具备多线程能力的函数:
|
||||
1. predict: 正常对话时使用,具备完备的交互功能,不可多线程
|
||||
|
||||
具备多线程调用能力的函数
|
||||
2. predict_no_ui_long_connection:支持多线程
|
||||
"""
|
||||
|
||||
import json
|
||||
import time
|
||||
import gradio as gr
|
||||
import logging
|
||||
import traceback
|
||||
import requests
|
||||
import importlib
|
||||
import random
|
||||
|
||||
# config_private.py放自己的秘密如API和代理网址
|
||||
# 读取时首先看是否存在私密的config_private配置文件(不受git管控),如果有,则覆盖原config文件
|
||||
from toolbox import get_conf, update_ui, is_any_api_key, select_api_key, what_keys, clip_history
|
||||
from toolbox import trimmed_format_exc, is_the_upload_folder, read_one_api_model_name, log_chat
|
||||
from toolbox import ChatBotWithCookies
|
||||
proxies, TIMEOUT_SECONDS, MAX_RETRY, API_ORG, AZURE_CFG_ARRAY = \
|
||||
get_conf('proxies', 'TIMEOUT_SECONDS', 'MAX_RETRY', 'API_ORG', 'AZURE_CFG_ARRAY')
|
||||
|
||||
timeout_bot_msg = '[Local Message] Request timeout. Network error. Please check proxy settings in config.py.' + \
|
||||
'网络错误,检查代理服务器是否可用,以及代理设置的格式是否正确,格式须是[协议]://[地址]:[端口],缺一不可。'
|
||||
|
||||
def get_full_error(chunk, stream_response):
|
||||
"""
|
||||
获取完整的从Cohere返回的报错
|
||||
"""
|
||||
while True:
|
||||
try:
|
||||
chunk += next(stream_response)
|
||||
except:
|
||||
break
|
||||
return chunk
|
||||
|
||||
def decode_chunk(chunk):
|
||||
# 提前读取一些信息 (用于判断异常)
|
||||
chunk_decoded = chunk.decode()
|
||||
chunkjson = None
|
||||
has_choices = False
|
||||
choice_valid = False
|
||||
has_content = False
|
||||
has_role = False
|
||||
try:
|
||||
chunkjson = json.loads(chunk_decoded)
|
||||
has_choices = 'choices' in chunkjson
|
||||
if has_choices: choice_valid = (len(chunkjson['choices']) > 0)
|
||||
if has_choices and choice_valid: has_content = ("content" in chunkjson['choices'][0]["delta"])
|
||||
if has_content: has_content = (chunkjson['choices'][0]["delta"]["content"] is not None)
|
||||
if has_choices and choice_valid: has_role = "role" in chunkjson['choices'][0]["delta"]
|
||||
except:
|
||||
pass
|
||||
return chunk_decoded, chunkjson, has_choices, choice_valid, has_content, has_role
|
||||
|
||||
from functools import lru_cache
|
||||
@lru_cache(maxsize=32)
|
||||
def verify_endpoint(endpoint):
|
||||
"""
|
||||
检查endpoint是否可用
|
||||
"""
|
||||
if "你亲手写的api名称" in endpoint:
|
||||
raise ValueError("Endpoint不正确, 请检查AZURE_ENDPOINT的配置! 当前的Endpoint为:" + endpoint)
|
||||
return endpoint
|
||||
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="", observe_window:list=None, console_slience:bool=False):
|
||||
"""
|
||||
发送,等待回复,一次性完成,不显示中间过程。但内部用stream的方法避免中途网线被掐。
|
||||
inputs:
|
||||
是本次问询的输入
|
||||
sys_prompt:
|
||||
系统静默prompt
|
||||
llm_kwargs:
|
||||
内部调优参数
|
||||
history:
|
||||
是之前的对话列表
|
||||
observe_window = None:
|
||||
用于负责跨越线程传递已经输出的部分,大部分时候仅仅为了fancy的视觉效果,留空即可。observe_window[0]:观测窗。observe_window[1]:看门狗
|
||||
"""
|
||||
watch_dog_patience = 5 # 看门狗的耐心, 设置5秒即可
|
||||
headers, payload = generate_payload(inputs, llm_kwargs, history, system_prompt=sys_prompt, stream=True)
|
||||
retry = 0
|
||||
while True:
|
||||
try:
|
||||
# make a POST request to the API endpoint, stream=False
|
||||
from .bridge_all import model_info
|
||||
endpoint = verify_endpoint(model_info[llm_kwargs['llm_model']]['endpoint'])
|
||||
response = requests.post(endpoint, headers=headers, proxies=proxies,
|
||||
json=payload, stream=True, timeout=TIMEOUT_SECONDS); break
|
||||
except requests.exceptions.ReadTimeout as e:
|
||||
retry += 1
|
||||
traceback.print_exc()
|
||||
if retry > MAX_RETRY: raise TimeoutError
|
||||
if MAX_RETRY!=0: print(f'请求超时,正在重试 ({retry}/{MAX_RETRY}) ……')
|
||||
|
||||
stream_response = response.iter_lines()
|
||||
result = ''
|
||||
json_data = None
|
||||
while True:
|
||||
try: chunk = next(stream_response)
|
||||
except StopIteration:
|
||||
break
|
||||
except requests.exceptions.ConnectionError:
|
||||
chunk = next(stream_response) # 失败了,重试一次?再失败就没办法了。
|
||||
chunk_decoded, chunkjson, has_choices, choice_valid, has_content, has_role = decode_chunk(chunk)
|
||||
if chunkjson['event_type'] == 'stream-start': continue
|
||||
if chunkjson['event_type'] == 'text-generation':
|
||||
result += chunkjson["text"]
|
||||
if not console_slience: print(chunkjson["text"], end='')
|
||||
if observe_window is not None:
|
||||
# 观测窗,把已经获取的数据显示出去
|
||||
if len(observe_window) >= 1:
|
||||
observe_window[0] += chunkjson["text"]
|
||||
# 看门狗,如果超过期限没有喂狗,则终止
|
||||
if len(observe_window) >= 2:
|
||||
if (time.time()-observe_window[1]) > watch_dog_patience:
|
||||
raise RuntimeError("用户取消了程序。")
|
||||
if chunkjson['event_type'] == 'stream-end': break
|
||||
return result
|
||||
|
||||
|
||||
def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWithCookies,
|
||||
history:list=[], system_prompt:str='', stream:bool=True, additional_fn:str=None):
|
||||
"""
|
||||
发送至chatGPT,流式获取输出。
|
||||
用于基础的对话功能。
|
||||
inputs 是本次问询的输入
|
||||
top_p, temperature是chatGPT的内部调优参数
|
||||
history 是之前的对话列表(注意无论是inputs还是history,内容太长了都会触发token数量溢出的错误)
|
||||
chatbot 为WebUI中显示的对话列表,修改它,然后yeild出去,可以直接修改对话界面内容
|
||||
additional_fn代表点击的哪个按钮,按钮见functional.py
|
||||
"""
|
||||
# if is_any_api_key(inputs):
|
||||
# chatbot._cookies['api_key'] = inputs
|
||||
# chatbot.append(("输入已识别为Cohere的api_key", what_keys(inputs)))
|
||||
# yield from update_ui(chatbot=chatbot, history=history, msg="api_key已导入") # 刷新界面
|
||||
# return
|
||||
# elif not is_any_api_key(chatbot._cookies['api_key']):
|
||||
# chatbot.append((inputs, "缺少api_key。\n\n1. 临时解决方案:直接在输入区键入api_key,然后回车提交。\n\n2. 长效解决方案:在config.py中配置。"))
|
||||
# yield from update_ui(chatbot=chatbot, history=history, msg="缺少api_key") # 刷新界面
|
||||
# return
|
||||
|
||||
user_input = inputs
|
||||
if additional_fn is not None:
|
||||
from core_functional import handle_core_functionality
|
||||
inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot)
|
||||
|
||||
raw_input = inputs
|
||||
# logging.info(f'[raw_input] {raw_input}')
|
||||
chatbot.append((inputs, ""))
|
||||
yield from update_ui(chatbot=chatbot, history=history, msg="等待响应") # 刷新界面
|
||||
|
||||
# check mis-behavior
|
||||
if is_the_upload_folder(user_input):
|
||||
chatbot[-1] = (inputs, f"[Local Message] 检测到操作错误!当您上传文档之后,需点击“**函数插件区**”按钮进行处理,请勿点击“提交”按钮或者“基础功能区”按钮。")
|
||||
yield from update_ui(chatbot=chatbot, history=history, msg="正常") # 刷新界面
|
||||
time.sleep(2)
|
||||
|
||||
try:
|
||||
headers, payload = generate_payload(inputs, llm_kwargs, history, system_prompt, stream)
|
||||
except RuntimeError as e:
|
||||
chatbot[-1] = (inputs, f"您提供的api-key不满足要求,不包含任何可用于{llm_kwargs['llm_model']}的api-key。您可能选择了错误的模型或请求源。")
|
||||
yield from update_ui(chatbot=chatbot, history=history, msg="api-key不满足要求") # 刷新界面
|
||||
return
|
||||
|
||||
# 检查endpoint是否合法
|
||||
try:
|
||||
from .bridge_all import model_info
|
||||
endpoint = verify_endpoint(model_info[llm_kwargs['llm_model']]['endpoint'])
|
||||
except:
|
||||
tb_str = '```\n' + trimmed_format_exc() + '```'
|
||||
chatbot[-1] = (inputs, tb_str)
|
||||
yield from update_ui(chatbot=chatbot, history=history, msg="Endpoint不满足要求") # 刷新界面
|
||||
return
|
||||
|
||||
history.append(inputs); history.append("")
|
||||
|
||||
retry = 0
|
||||
while True:
|
||||
try:
|
||||
# make a POST request to the API endpoint, stream=True
|
||||
response = requests.post(endpoint, headers=headers, proxies=proxies,
|
||||
json=payload, stream=True, timeout=TIMEOUT_SECONDS);break
|
||||
except:
|
||||
retry += 1
|
||||
chatbot[-1] = ((chatbot[-1][0], timeout_bot_msg))
|
||||
retry_msg = f",正在重试 ({retry}/{MAX_RETRY}) ……" if MAX_RETRY > 0 else ""
|
||||
yield from update_ui(chatbot=chatbot, history=history, msg="请求超时"+retry_msg) # 刷新界面
|
||||
if retry > MAX_RETRY: raise TimeoutError
|
||||
|
||||
gpt_replying_buffer = ""
|
||||
|
||||
is_head_of_the_stream = True
|
||||
if stream:
|
||||
stream_response = response.iter_lines()
|
||||
while True:
|
||||
try:
|
||||
chunk = next(stream_response)
|
||||
except StopIteration:
|
||||
# 非Cohere官方接口的出现这样的报错,Cohere和API2D不会走这里
|
||||
chunk_decoded = chunk.decode()
|
||||
error_msg = chunk_decoded
|
||||
# 其他情况,直接返回报错
|
||||
chatbot, history = handle_error(inputs, llm_kwargs, chatbot, history, chunk_decoded, error_msg)
|
||||
yield from update_ui(chatbot=chatbot, history=history, msg="非Cohere官方接口返回了错误:" + chunk.decode()) # 刷新界面
|
||||
return
|
||||
|
||||
# 提前读取一些信息 (用于判断异常)
|
||||
chunk_decoded, chunkjson, has_choices, choice_valid, has_content, has_role = decode_chunk(chunk)
|
||||
|
||||
if chunkjson:
|
||||
try:
|
||||
if chunkjson['event_type'] == 'stream-start':
|
||||
continue
|
||||
if chunkjson['event_type'] == 'text-generation':
|
||||
gpt_replying_buffer = gpt_replying_buffer + chunkjson["text"]
|
||||
history[-1] = gpt_replying_buffer
|
||||
chatbot[-1] = (history[-2], history[-1])
|
||||
yield from update_ui(chatbot=chatbot, history=history, msg="正常") # 刷新界面
|
||||
if chunkjson['event_type'] == 'stream-end':
|
||||
log_chat(llm_model=llm_kwargs["llm_model"], input_str=inputs, output_str=gpt_replying_buffer)
|
||||
history[-1] = gpt_replying_buffer
|
||||
chatbot[-1] = (history[-2], history[-1])
|
||||
yield from update_ui(chatbot=chatbot, history=history, msg="正常") # 刷新界面
|
||||
break
|
||||
except Exception as e:
|
||||
yield from update_ui(chatbot=chatbot, history=history, msg="Json解析不合常规") # 刷新界面
|
||||
chunk = get_full_error(chunk, stream_response)
|
||||
chunk_decoded = chunk.decode()
|
||||
error_msg = chunk_decoded
|
||||
chatbot, history = handle_error(inputs, llm_kwargs, chatbot, history, chunk_decoded, error_msg)
|
||||
yield from update_ui(chatbot=chatbot, history=history, msg="Json异常" + error_msg) # 刷新界面
|
||||
print(error_msg)
|
||||
return
|
||||
|
||||
def handle_error(inputs, llm_kwargs, chatbot, history, chunk_decoded, error_msg):
|
||||
from .bridge_all import model_info
|
||||
Cohere_website = ' 请登录Cohere查看详情 https://platform.Cohere.com/signup'
|
||||
if "reduce the length" in error_msg:
|
||||
if len(history) >= 2: history[-1] = ""; history[-2] = "" # 清除当前溢出的输入:history[-2] 是本次输入, history[-1] 是本次输出
|
||||
history = clip_history(inputs=inputs, history=history, tokenizer=model_info[llm_kwargs['llm_model']]['tokenizer'],
|
||||
max_token_limit=(model_info[llm_kwargs['llm_model']]['max_token'])) # history至少释放二分之一
|
||||
chatbot[-1] = (chatbot[-1][0], "[Local Message] Reduce the length. 本次输入过长, 或历史数据过长. 历史缓存数据已部分释放, 您可以请再次尝试. (若再次失败则更可能是因为输入过长.)")
|
||||
elif "does not exist" in error_msg:
|
||||
chatbot[-1] = (chatbot[-1][0], f"[Local Message] Model {llm_kwargs['llm_model']} does not exist. 模型不存在, 或者您没有获得体验资格.")
|
||||
elif "Incorrect API key" in error_msg:
|
||||
chatbot[-1] = (chatbot[-1][0], "[Local Message] Incorrect API key. Cohere以提供了不正确的API_KEY为由, 拒绝服务. " + Cohere_website)
|
||||
elif "exceeded your current quota" in error_msg:
|
||||
chatbot[-1] = (chatbot[-1][0], "[Local Message] You exceeded your current quota. Cohere以账户额度不足为由, 拒绝服务." + Cohere_website)
|
||||
elif "account is not active" in error_msg:
|
||||
chatbot[-1] = (chatbot[-1][0], "[Local Message] Your account is not active. Cohere以账户失效为由, 拒绝服务." + Cohere_website)
|
||||
elif "associated with a deactivated account" in error_msg:
|
||||
chatbot[-1] = (chatbot[-1][0], "[Local Message] You are associated with a deactivated account. Cohere以账户失效为由, 拒绝服务." + Cohere_website)
|
||||
elif "API key has been deactivated" in error_msg:
|
||||
chatbot[-1] = (chatbot[-1][0], "[Local Message] API key has been deactivated. Cohere以账户失效为由, 拒绝服务." + Cohere_website)
|
||||
elif "bad forward key" in error_msg:
|
||||
chatbot[-1] = (chatbot[-1][0], "[Local Message] Bad forward key. API2D账户额度不足.")
|
||||
elif "Not enough point" in error_msg:
|
||||
chatbot[-1] = (chatbot[-1][0], "[Local Message] Not enough point. API2D账户点数不足.")
|
||||
else:
|
||||
from toolbox import regular_txt_to_markdown
|
||||
tb_str = '```\n' + trimmed_format_exc() + '```'
|
||||
chatbot[-1] = (chatbot[-1][0], f"[Local Message] 异常 \n\n{tb_str} \n\n{regular_txt_to_markdown(chunk_decoded)}")
|
||||
return chatbot, history
|
||||
|
||||
def generate_payload(inputs, llm_kwargs, history, system_prompt, stream):
|
||||
"""
|
||||
整合所有信息,选择LLM模型,生成http请求,为发送请求做准备
|
||||
"""
|
||||
# if not is_any_api_key(llm_kwargs['api_key']):
|
||||
# raise AssertionError("你提供了错误的API_KEY。\n\n1. 临时解决方案:直接在输入区键入api_key,然后回车提交。\n\n2. 长效解决方案:在config.py中配置。")
|
||||
|
||||
api_key = select_api_key(llm_kwargs['api_key'], llm_kwargs['llm_model'])
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {api_key}"
|
||||
}
|
||||
if API_ORG.startswith('org-'): headers.update({"Cohere-Organization": API_ORG})
|
||||
if llm_kwargs['llm_model'].startswith('azure-'):
|
||||
headers.update({"api-key": api_key})
|
||||
if llm_kwargs['llm_model'] in AZURE_CFG_ARRAY.keys():
|
||||
azure_api_key_unshared = AZURE_CFG_ARRAY[llm_kwargs['llm_model']]["AZURE_API_KEY"]
|
||||
headers.update({"api-key": azure_api_key_unshared})
|
||||
|
||||
conversation_cnt = len(history) // 2
|
||||
|
||||
messages = [{"role": "SYSTEM", "message": system_prompt}]
|
||||
if conversation_cnt:
|
||||
for index in range(0, 2*conversation_cnt, 2):
|
||||
what_i_have_asked = {}
|
||||
what_i_have_asked["role"] = "USER"
|
||||
what_i_have_asked["message"] = history[index]
|
||||
what_gpt_answer = {}
|
||||
what_gpt_answer["role"] = "CHATBOT"
|
||||
what_gpt_answer["message"] = history[index+1]
|
||||
if what_i_have_asked["message"] != "":
|
||||
if what_gpt_answer["message"] == "": continue
|
||||
if what_gpt_answer["message"] == timeout_bot_msg: continue
|
||||
messages.append(what_i_have_asked)
|
||||
messages.append(what_gpt_answer)
|
||||
else:
|
||||
messages[-1]['message'] = what_gpt_answer['message']
|
||||
|
||||
model = llm_kwargs['llm_model']
|
||||
if model.startswith('cohere-'): model = model[len('cohere-'):]
|
||||
payload = {
|
||||
"model": model,
|
||||
"message": inputs,
|
||||
"chat_history": messages,
|
||||
"temperature": llm_kwargs['temperature'], # 1.0,
|
||||
"top_p": llm_kwargs['top_p'], # 1.0,
|
||||
"n": 1,
|
||||
"stream": stream,
|
||||
"presence_penalty": 0,
|
||||
"frequency_penalty": 0,
|
||||
}
|
||||
|
||||
return headers,payload
|
||||
|
||||
|
@ -7,6 +7,7 @@ import re
|
||||
import os
|
||||
import time
|
||||
from request_llms.com_google import GoogleChatInit
|
||||
from toolbox import ChatBotWithCookies
|
||||
from toolbox import get_conf, update_ui, update_ui_lastest_msg, have_any_recent_upload_image_files, trimmed_format_exc
|
||||
|
||||
proxies, TIMEOUT_SECONDS, MAX_RETRY = get_conf('proxies', 'TIMEOUT_SECONDS', 'MAX_RETRY')
|
||||
@ -44,7 +45,8 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
|
||||
return gpt_replying_buffer
|
||||
|
||||
|
||||
def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream=True, additional_fn=None):
|
||||
def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWithCookies,
|
||||
history:list=[], system_prompt:str='', stream:bool=True, additional_fn:str=None):
|
||||
# 检查API_KEY
|
||||
if get_conf("GEMINI_API_KEY") == "":
|
||||
yield from update_ui_lastest_msg(f"请配置 GEMINI_API_KEY。", chatbot=chatbot, history=history, delay=0)
|
||||
|
@ -1,10 +1,10 @@
|
||||
|
||||
from transformers import AutoModel, AutoTokenizer
|
||||
import time
|
||||
import threading
|
||||
import importlib
|
||||
from toolbox import update_ui, get_conf
|
||||
from multiprocessing import Process, Pipe
|
||||
from transformers import AutoModel, AutoTokenizer
|
||||
|
||||
load_message = "jittorllms尚未加载,加载需要一段时间。注意,请避免混用多种jittor模型,否则可能导致显存溢出而造成卡顿,取决于`config.py`的配置,jittorllms消耗大量的内存(CPU)或显存(GPU),也许会导致低配计算机卡死 ……"
|
||||
|
||||
@ -106,7 +106,8 @@ class GetGLMHandle(Process):
|
||||
global llama_glm_handle
|
||||
llama_glm_handle = None
|
||||
#################################################################################
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="",
|
||||
observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
多线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
|
@ -1,10 +1,10 @@
|
||||
|
||||
from transformers import AutoModel, AutoTokenizer
|
||||
import time
|
||||
import threading
|
||||
import importlib
|
||||
from toolbox import update_ui, get_conf
|
||||
from multiprocessing import Process, Pipe
|
||||
from transformers import AutoModel, AutoTokenizer
|
||||
|
||||
load_message = "jittorllms尚未加载,加载需要一段时间。注意,请避免混用多种jittor模型,否则可能导致显存溢出而造成卡顿,取决于`config.py`的配置,jittorllms消耗大量的内存(CPU)或显存(GPU),也许会导致低配计算机卡死 ……"
|
||||
|
||||
@ -106,7 +106,8 @@ class GetGLMHandle(Process):
|
||||
global pangu_glm_handle
|
||||
pangu_glm_handle = None
|
||||
#################################################################################
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="",
|
||||
observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
多线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
|
@ -106,7 +106,8 @@ class GetGLMHandle(Process):
|
||||
global rwkv_glm_handle
|
||||
rwkv_glm_handle = None
|
||||
#################################################################################
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="",
|
||||
observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
多线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
|
@ -8,6 +8,7 @@ import time
|
||||
import logging
|
||||
|
||||
from toolbox import get_conf, update_ui, log_chat
|
||||
from toolbox import ChatBotWithCookies
|
||||
|
||||
import requests
|
||||
|
||||
@ -146,7 +147,8 @@ def msg_handle_error(llm_kwargs, chunk_decoded):
|
||||
return error_msg
|
||||
|
||||
|
||||
def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream=True, additional_fn=None):
|
||||
def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWithCookies,
|
||||
history:list=[], system_prompt:str='', stream:bool=True, additional_fn:str=None):
|
||||
chatbot.append([inputs, ""])
|
||||
|
||||
if additional_fn is not None:
|
||||
|
@ -171,7 +171,8 @@ class GetGLMHandle(Process):
|
||||
global moss_handle
|
||||
moss_handle = None
|
||||
#################################################################################
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="",
|
||||
observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
多线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
|
@ -117,7 +117,8 @@ def generate_from_baidu_qianfan(inputs, llm_kwargs, history, system_prompt):
|
||||
raise RuntimeError(dec['error_msg'])
|
||||
|
||||
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="",
|
||||
observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
⭐多线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
|
@ -5,7 +5,8 @@ from toolbox import check_packages, report_exception
|
||||
|
||||
model_name = 'Qwen'
|
||||
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="",
|
||||
observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
⭐多线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
@ -47,6 +48,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
|
||||
if additional_fn is not None:
|
||||
from core_functional import handle_core_functionality
|
||||
inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot)
|
||||
chatbot[-1] = (inputs, "")
|
||||
yield from update_ui(chatbot=chatbot, history=history)
|
||||
|
||||
# 开始接收回复
|
||||
from .com_qwenapi import QwenRequestInstance
|
||||
|
@ -9,7 +9,8 @@ def validate_key():
|
||||
if YUNQUE_SECRET_KEY == '': return False
|
||||
return True
|
||||
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="",
|
||||
observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
⭐ 多线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
|
@ -13,7 +13,8 @@ def validate_key():
|
||||
return False
|
||||
return True
|
||||
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="",
|
||||
observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
⭐多线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
|
@ -1,7 +1,8 @@
|
||||
import time
|
||||
import os
|
||||
from toolbox import update_ui, get_conf, update_ui_lastest_msg
|
||||
from toolbox import update_ui, get_conf, update_ui_lastest_msg, log_chat
|
||||
from toolbox import check_packages, report_exception, have_any_recent_upload_image_files
|
||||
from toolbox import ChatBotWithCookies
|
||||
|
||||
model_name = '智谱AI大模型'
|
||||
zhipuai_default_model = 'glm-4'
|
||||
@ -16,7 +17,8 @@ def make_media_input(inputs, image_paths):
|
||||
inputs = inputs + f'<br/><br/><div align="center"><img src="file={os.path.abspath(image_path)}"></div>'
|
||||
return inputs
|
||||
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="",
|
||||
observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
⭐多线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
@ -42,7 +44,8 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
|
||||
return response
|
||||
|
||||
|
||||
def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream=True, additional_fn=None):
|
||||
def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWithCookies,
|
||||
history:list=[], system_prompt:str='', stream:bool=True, additional_fn:str=None):
|
||||
"""
|
||||
⭐单线程方法
|
||||
函数的说明请见 request_llms/bridge_all.py
|
||||
@ -90,4 +93,5 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
|
||||
chatbot[-1] = [inputs, response]
|
||||
yield from update_ui(chatbot=chatbot, history=history)
|
||||
history.extend([inputs, response])
|
||||
log_chat(llm_model=llm_kwargs["llm_model"], input_str=inputs, output_str=response)
|
||||
yield from update_ui(chatbot=chatbot, history=history)
|
@ -1,6 +1,7 @@
|
||||
import time
|
||||
import threading
|
||||
from toolbox import update_ui, Singleton
|
||||
from toolbox import ChatBotWithCookies
|
||||
from multiprocessing import Process, Pipe
|
||||
from contextlib import redirect_stdout
|
||||
from request_llms.queued_pipe import create_queue_pipe
|
||||
@ -214,7 +215,7 @@ class LocalLLMHandle(Process):
|
||||
def get_local_llm_predict_fns(LLMSingletonClass, model_name, history_format='classic'):
|
||||
load_message = f"{model_name}尚未加载,加载需要一段时间。注意,取决于`config.py`的配置,{model_name}消耗大量的内存(CPU)或显存(GPU),也许会导致低配计算机卡死 ……"
|
||||
|
||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||
def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="", observe_window:list=[], console_slience:bool=False):
|
||||
"""
|
||||
refer to request_llms/bridge_all.py
|
||||
"""
|
||||
@ -260,7 +261,8 @@ def get_local_llm_predict_fns(LLMSingletonClass, model_name, history_format='cla
|
||||
raise RuntimeError("程序终止。")
|
||||
return response
|
||||
|
||||
def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream=True, additional_fn=None):
|
||||
def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWithCookies,
|
||||
history:list=[], system_prompt:str='', stream:bool=True, additional_fn:str=None):
|
||||
"""
|
||||
refer to request_llms/bridge_all.py
|
||||
"""
|
||||
|
@ -17,6 +17,7 @@ prompt_toolkit
|
||||
latex2mathml
|
||||
python-docx
|
||||
mdtex2html
|
||||
dashscope
|
||||
pyautogen
|
||||
colorama
|
||||
Markdown
|
||||
@ -25,4 +26,4 @@ pymupdf
|
||||
openai
|
||||
arxiv
|
||||
numpy
|
||||
rich
|
||||
rich
|
@ -1 +1,61 @@
|
||||
from typing import Callable
|
||||
def load_web_cookie_cache__fn_builder(customize_btns, cookies, predefined_btns)->Callable:
|
||||
def load_web_cookie_cache(persistent_cookie_, cookies_):
|
||||
import gradio as gr
|
||||
from themes.theme import load_dynamic_theme, to_cookie_str, from_cookie_str, assign_user_uuid
|
||||
|
||||
ret = {}
|
||||
for k in customize_btns:
|
||||
ret.update({customize_btns[k]: gr.update(visible=False, value="")})
|
||||
|
||||
try: persistent_cookie_ = from_cookie_str(persistent_cookie_) # persistent cookie to dict
|
||||
except: return ret
|
||||
|
||||
customize_fn_overwrite_ = persistent_cookie_.get("custom_bnt", {})
|
||||
cookies_['customize_fn_overwrite'] = customize_fn_overwrite_
|
||||
ret.update({cookies: cookies_})
|
||||
|
||||
for k,v in persistent_cookie_["custom_bnt"].items():
|
||||
if v['Title'] == "": continue
|
||||
if k in customize_btns: ret.update({customize_btns[k]: gr.update(visible=True, value=v['Title'])})
|
||||
else: ret.update({predefined_btns[k]: gr.update(visible=True, value=v['Title'])})
|
||||
return ret
|
||||
return load_web_cookie_cache
|
||||
|
||||
|
||||
def assign_btn__fn_builder(customize_btns, predefined_btns, cookies, web_cookie_cache)->Callable:
|
||||
def assign_btn(persistent_cookie_, cookies_, basic_btn_dropdown_, basic_fn_title, basic_fn_prefix, basic_fn_suffix, clean_up=False):
|
||||
import gradio as gr
|
||||
from themes.theme import load_dynamic_theme, to_cookie_str, from_cookie_str, assign_user_uuid
|
||||
ret = {}
|
||||
# 读取之前的自定义按钮
|
||||
customize_fn_overwrite_ = cookies_['customize_fn_overwrite']
|
||||
# 更新新的自定义按钮
|
||||
customize_fn_overwrite_.update({
|
||||
basic_btn_dropdown_:
|
||||
{
|
||||
"Title":basic_fn_title,
|
||||
"Prefix":basic_fn_prefix,
|
||||
"Suffix":basic_fn_suffix,
|
||||
}
|
||||
}
|
||||
)
|
||||
if clean_up:
|
||||
customize_fn_overwrite_ = {}
|
||||
cookies_.update(customize_fn_overwrite_) # 更新cookie
|
||||
visible = (not clean_up) and (basic_fn_title != "")
|
||||
if basic_btn_dropdown_ in customize_btns:
|
||||
# 是自定义按钮,不是预定义按钮
|
||||
ret.update({customize_btns[basic_btn_dropdown_]: gr.update(visible=visible, value=basic_fn_title)})
|
||||
else:
|
||||
# 是预定义按钮
|
||||
ret.update({predefined_btns[basic_btn_dropdown_]: gr.update(visible=visible, value=basic_fn_title)})
|
||||
ret.update({cookies: cookies_})
|
||||
try: persistent_cookie_ = from_cookie_str(persistent_cookie_) # persistent cookie to dict
|
||||
except: persistent_cookie_ = {}
|
||||
persistent_cookie_["custom_bnt"] = customize_fn_overwrite_ # dict update new value
|
||||
persistent_cookie_ = to_cookie_str(persistent_cookie_) # persistent cookie to dict
|
||||
ret.update({web_cookie_cache: persistent_cookie_}) # write persistent cookie
|
||||
return ret
|
||||
return assign_btn
|
||||
|
||||
|
211
shared_utils/fastapi_server.py
Normal file
211
shared_utils/fastapi_server.py
Normal file
@ -0,0 +1,211 @@
|
||||
"""
|
||||
Tests:
|
||||
|
||||
- custom_path false / no user auth:
|
||||
-- upload file(yes)
|
||||
-- download file(yes)
|
||||
-- websocket(yes)
|
||||
-- block __pycache__ access(yes)
|
||||
-- rel (yes)
|
||||
-- abs (yes)
|
||||
-- block user access(fail) http://localhost:45013/file=gpt_log/admin/chat_secrets.log
|
||||
-- fix(commit f6bf05048c08f5cd84593f7fdc01e64dec1f584a)-> block successful
|
||||
|
||||
- custom_path yes("/cc/gptac") / no user auth:
|
||||
-- upload file(yes)
|
||||
-- download file(yes)
|
||||
-- websocket(yes)
|
||||
-- block __pycache__ access(yes)
|
||||
-- block user access(yes)
|
||||
|
||||
- custom_path yes("/cc/gptac/") / no user auth:
|
||||
-- upload file(yes)
|
||||
-- download file(yes)
|
||||
-- websocket(yes)
|
||||
-- block user access(yes)
|
||||
|
||||
- custom_path yes("/cc/gptac/") / + user auth:
|
||||
-- upload file(yes)
|
||||
-- download file(yes)
|
||||
-- websocket(yes)
|
||||
-- block user access(yes)
|
||||
-- block user-wise access (yes)
|
||||
|
||||
- custom_path no + user auth:
|
||||
-- upload file(yes)
|
||||
-- download file(yes)
|
||||
-- websocket(yes)
|
||||
-- block user access(yes)
|
||||
-- block user-wise access (yes)
|
||||
|
||||
queue cocurrent effectiveness
|
||||
-- upload file(yes)
|
||||
-- download file(yes)
|
||||
-- websocket(yes)
|
||||
"""
|
||||
|
||||
import os, requests, threading, time
|
||||
import uvicorn
|
||||
|
||||
def _authorize_user(path_or_url, request, gradio_app):
|
||||
from toolbox import get_conf, default_user_name
|
||||
PATH_PRIVATE_UPLOAD, PATH_LOGGING = get_conf('PATH_PRIVATE_UPLOAD', 'PATH_LOGGING')
|
||||
sensitive_path = None
|
||||
path_or_url = os.path.relpath(path_or_url)
|
||||
if path_or_url.startswith(PATH_LOGGING):
|
||||
sensitive_path = PATH_LOGGING
|
||||
if path_or_url.startswith(PATH_PRIVATE_UPLOAD):
|
||||
sensitive_path = PATH_PRIVATE_UPLOAD
|
||||
if sensitive_path:
|
||||
token = request.cookies.get("access-token") or request.cookies.get("access-token-unsecure")
|
||||
user = gradio_app.tokens.get(token) # get user
|
||||
allowed_users = [user, 'autogen', default_user_name] # three user path that can be accessed
|
||||
for user_allowed in allowed_users:
|
||||
# exact match
|
||||
if f"{os.sep}".join(path_or_url.split(os.sep)[:2]) == os.path.join(sensitive_path, user_allowed):
|
||||
return True
|
||||
return False # "越权访问!"
|
||||
return True
|
||||
|
||||
|
||||
class Server(uvicorn.Server):
|
||||
# A server that runs in a separate thread
|
||||
def install_signal_handlers(self):
|
||||
pass
|
||||
|
||||
def run_in_thread(self):
|
||||
self.thread = threading.Thread(target=self.run, daemon=True)
|
||||
self.thread.start()
|
||||
while not self.started:
|
||||
time.sleep(1e-3)
|
||||
|
||||
def close(self):
|
||||
self.should_exit = True
|
||||
self.thread.join()
|
||||
|
||||
|
||||
def start_app(app_block, CONCURRENT_COUNT, AUTHENTICATION, PORT, SSL_KEYFILE, SSL_CERTFILE):
|
||||
import uvicorn
|
||||
import fastapi
|
||||
import gradio as gr
|
||||
from fastapi import FastAPI
|
||||
from gradio.routes import App
|
||||
from toolbox import get_conf
|
||||
CUSTOM_PATH, PATH_LOGGING = get_conf('CUSTOM_PATH', 'PATH_LOGGING')
|
||||
|
||||
# --- --- configurate gradio app block --- ---
|
||||
app_block:gr.Blocks
|
||||
app_block.ssl_verify = False
|
||||
app_block.auth_message = '请登录'
|
||||
app_block.favicon_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "docs/logo.png")
|
||||
app_block.auth = AUTHENTICATION if len(AUTHENTICATION) != 0 else None
|
||||
app_block.blocked_paths = ["config.py", "__pycache__", "config_private.py", "docker-compose.yml", "Dockerfile", f"{PATH_LOGGING}/admin"]
|
||||
app_block.dev_mode = False
|
||||
app_block.config = app_block.get_config_file()
|
||||
app_block.enable_queue = True
|
||||
app_block.queue(concurrency_count=CONCURRENT_COUNT)
|
||||
app_block.validate_queue_settings()
|
||||
app_block.show_api = False
|
||||
app_block.config = app_block.get_config_file()
|
||||
max_threads = 40
|
||||
app_block.max_threads = max(
|
||||
app_block._queue.max_thread_count if app_block.enable_queue else 0, max_threads
|
||||
)
|
||||
app_block.is_colab = False
|
||||
app_block.is_kaggle = False
|
||||
app_block.is_sagemaker = False
|
||||
|
||||
gradio_app = App.create_app(app_block)
|
||||
|
||||
# --- --- replace gradio endpoint to forbid access to sensitive files --- ---
|
||||
if len(AUTHENTICATION) > 0:
|
||||
dependencies = []
|
||||
endpoint = None
|
||||
for route in list(gradio_app.router.routes):
|
||||
if route.path == "/file/{path:path}":
|
||||
gradio_app.router.routes.remove(route)
|
||||
if route.path == "/file={path_or_url:path}":
|
||||
dependencies = route.dependencies
|
||||
endpoint = route.endpoint
|
||||
gradio_app.router.routes.remove(route)
|
||||
@gradio_app.get("/file/{path:path}", dependencies=dependencies)
|
||||
@gradio_app.head("/file={path_or_url:path}", dependencies=dependencies)
|
||||
@gradio_app.get("/file={path_or_url:path}", dependencies=dependencies)
|
||||
async def file(path_or_url: str, request: fastapi.Request):
|
||||
if len(AUTHENTICATION) > 0:
|
||||
if not _authorize_user(path_or_url, request, gradio_app):
|
||||
return "越权访问!"
|
||||
return await endpoint(path_or_url, request)
|
||||
|
||||
# --- --- app_lifespan --- ---
|
||||
from contextlib import asynccontextmanager
|
||||
@asynccontextmanager
|
||||
async def app_lifespan(app):
|
||||
async def startup_gradio_app():
|
||||
if gradio_app.get_blocks().enable_queue:
|
||||
gradio_app.get_blocks().startup_events()
|
||||
async def shutdown_gradio_app():
|
||||
pass
|
||||
await startup_gradio_app() # startup logic here
|
||||
yield # The application will serve requests after this point
|
||||
await shutdown_gradio_app() # cleanup/shutdown logic here
|
||||
|
||||
# --- --- FastAPI --- ---
|
||||
fastapi_app = FastAPI(lifespan=app_lifespan)
|
||||
fastapi_app.mount(CUSTOM_PATH, gradio_app)
|
||||
|
||||
# --- --- favicon --- ---
|
||||
if CUSTOM_PATH != '/':
|
||||
from fastapi.responses import FileResponse
|
||||
@fastapi_app.get("/favicon.ico")
|
||||
async def favicon():
|
||||
return FileResponse(app_block.favicon_path)
|
||||
|
||||
# --- --- uvicorn.Config --- ---
|
||||
ssl_keyfile = None if SSL_KEYFILE == "" else SSL_KEYFILE
|
||||
ssl_certfile = None if SSL_CERTFILE == "" else SSL_CERTFILE
|
||||
server_name = "0.0.0.0"
|
||||
config = uvicorn.Config(
|
||||
fastapi_app,
|
||||
host=server_name,
|
||||
port=PORT,
|
||||
reload=False,
|
||||
log_level="warning",
|
||||
ssl_keyfile=ssl_keyfile,
|
||||
ssl_certfile=ssl_certfile,
|
||||
)
|
||||
server = Server(config)
|
||||
url_host_name = "localhost" if server_name == "0.0.0.0" else server_name
|
||||
if ssl_keyfile is not None:
|
||||
if ssl_certfile is None:
|
||||
raise ValueError(
|
||||
"ssl_certfile must be provided if ssl_keyfile is provided."
|
||||
)
|
||||
path_to_local_server = f"https://{url_host_name}:{PORT}/"
|
||||
else:
|
||||
path_to_local_server = f"http://{url_host_name}:{PORT}/"
|
||||
if CUSTOM_PATH != '/':
|
||||
path_to_local_server += CUSTOM_PATH.lstrip('/').rstrip('/') + '/'
|
||||
# --- --- begin --- ---
|
||||
server.run_in_thread()
|
||||
|
||||
# --- --- after server launch --- ---
|
||||
app_block.server = server
|
||||
app_block.server_name = server_name
|
||||
app_block.local_url = path_to_local_server
|
||||
app_block.protocol = (
|
||||
"https"
|
||||
if app_block.local_url.startswith("https") or app_block.is_colab
|
||||
else "http"
|
||||
)
|
||||
|
||||
if app_block.enable_queue:
|
||||
app_block._queue.set_url(path_to_local_server)
|
||||
|
||||
forbid_proxies = {
|
||||
"http": "",
|
||||
"https": "",
|
||||
}
|
||||
requests.get(f"{app_block.local_url}startup-events", verify=app_block.ssl_verify, proxies=forbid_proxies)
|
||||
app_block.is_running = True
|
||||
app_block.block_thread()
|
@ -28,6 +28,11 @@ def is_api2d_key(key):
|
||||
return bool(API_MATCH_API2D)
|
||||
|
||||
|
||||
def is_cohere_api_key(key):
|
||||
API_MATCH_AZURE = re.match(r"[a-zA-Z0-9]{40}$", key)
|
||||
return bool(API_MATCH_AZURE)
|
||||
|
||||
|
||||
def is_any_api_key(key):
|
||||
if ',' in key:
|
||||
keys = key.split(',')
|
||||
@ -35,7 +40,7 @@ def is_any_api_key(key):
|
||||
if is_any_api_key(k): return True
|
||||
return False
|
||||
else:
|
||||
return is_openai_api_key(key) or is_api2d_key(key) or is_azure_api_key(key)
|
||||
return is_openai_api_key(key) or is_api2d_key(key) or is_azure_api_key(key) or is_cohere_api_key(key)
|
||||
|
||||
|
||||
def what_keys(keys):
|
||||
@ -74,8 +79,12 @@ def select_api_key(keys, llm_model):
|
||||
for k in key_list:
|
||||
if is_azure_api_key(k): avail_key_list.append(k)
|
||||
|
||||
if llm_model.startswith('cohere-'):
|
||||
for k in key_list:
|
||||
if is_cohere_api_key(k): avail_key_list.append(k)
|
||||
|
||||
if len(avail_key_list) == 0:
|
||||
raise RuntimeError(f"您提供的api-key不满足要求,不包含任何可用于{llm_model}的api-key。您可能选择了错误的模型或请求源(右下角更换模型菜单中可切换openai,azure,claude,api2d等请求源)。")
|
||||
raise RuntimeError(f"您提供的api-key不满足要求,不包含任何可用于{llm_model}的api-key。您可能选择了错误的模型或请求源(左上角更换模型菜单中可切换openai,azure,claude,cohere等请求源)。")
|
||||
|
||||
api_key = random.choice(avail_key_list) # 随机负载均衡
|
||||
return api_key
|
||||
|
@ -11,28 +11,45 @@ def validate_path():
|
||||
|
||||
|
||||
validate_path() # validate path so you can run from base directory
|
||||
if __name__ == "__main__":
|
||||
# from request_llms.bridge_newbingfree import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_moss import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_jittorllms_pangualpha import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_jittorllms_llama import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_claude import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_internlm import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_deepseekcoder import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_qwen_7B import predict_no_ui_long_connection
|
||||
from request_llms.bridge_qwen_local import predict_no_ui_long_connection
|
||||
|
||||
# from request_llms.bridge_spark import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_zhipu import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_chatglm3 import predict_no_ui_long_connection
|
||||
if "在线模型":
|
||||
if __name__ == "__main__":
|
||||
from request_llms.bridge_cohere import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_spark import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_zhipu import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_chatglm3 import predict_no_ui_long_connection
|
||||
llm_kwargs = {
|
||||
"llm_model": "command-r-plus",
|
||||
"max_length": 4096,
|
||||
"top_p": 1,
|
||||
"temperature": 1,
|
||||
}
|
||||
|
||||
llm_kwargs = {
|
||||
"max_length": 4096,
|
||||
"top_p": 1,
|
||||
"temperature": 1,
|
||||
}
|
||||
result = predict_no_ui_long_connection(
|
||||
inputs="请问什么是质子?", llm_kwargs=llm_kwargs, history=["你好", "我好!"], sys_prompt="系统"
|
||||
)
|
||||
print("final result:", result)
|
||||
print("final result:", result)
|
||||
|
||||
|
||||
if "本地模型":
|
||||
if __name__ == "__main__":
|
||||
# from request_llms.bridge_newbingfree import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_moss import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_jittorllms_pangualpha import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_jittorllms_llama import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_claude import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_internlm import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_deepseekcoder import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_qwen_7B import predict_no_ui_long_connection
|
||||
# from request_llms.bridge_qwen_local import predict_no_ui_long_connection
|
||||
llm_kwargs = {
|
||||
"max_length": 4096,
|
||||
"top_p": 1,
|
||||
"temperature": 1,
|
||||
}
|
||||
result = predict_no_ui_long_connection(
|
||||
inputs="请问什么是质子?", llm_kwargs=llm_kwargs, history=["你好", "我好!"], sys_prompt=""
|
||||
)
|
||||
print("final result:", result)
|
||||
|
||||
result = predict_no_ui_long_connection(
|
||||
inputs="请问什么是质子?", llm_kwargs=llm_kwargs, history=["你好", "我好!"], sys_prompt=""
|
||||
)
|
||||
print("final result:", result)
|
||||
|
154
themes/common.js
154
themes/common.js
@ -2,15 +2,15 @@
|
||||
// 第 1 部分: 工具函数
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
function push_data_to_gradio_component(DAT, ELEM_ID, TYPE){
|
||||
function push_data_to_gradio_component(DAT, ELEM_ID, TYPE) {
|
||||
// type, // type==="str" / type==="float"
|
||||
if (TYPE=="str"){
|
||||
if (TYPE == "str") {
|
||||
// convert dat to string: do nothing
|
||||
}
|
||||
else if (TYPE=="no_conversion"){
|
||||
else if (TYPE == "no_conversion") {
|
||||
// no nothing
|
||||
}
|
||||
else if (TYPE=="float"){
|
||||
else if (TYPE == "float") {
|
||||
// convert dat to float
|
||||
DAT = parseFloat(DAT);
|
||||
}
|
||||
@ -24,7 +24,7 @@ function push_data_to_gradio_component(DAT, ELEM_ID, TYPE){
|
||||
}
|
||||
|
||||
|
||||
async function get_gradio_component(ELEM_ID){
|
||||
async function get_gradio_component(ELEM_ID) {
|
||||
function waitFor(ELEM_ID) {
|
||||
return new Promise((resolve) => {
|
||||
const myEvent = new CustomEvent('gpt_academic_get_gradio_component_value', {
|
||||
@ -41,14 +41,13 @@ async function get_gradio_component(ELEM_ID){
|
||||
}
|
||||
|
||||
|
||||
async function get_data_from_gradio_component(ELEM_ID){
|
||||
async function get_data_from_gradio_component(ELEM_ID) {
|
||||
let comp = await get_gradio_component(ELEM_ID);
|
||||
return comp.props.value;
|
||||
}
|
||||
|
||||
function update_array(arr, item, mode) {
|
||||
// let p = ["基础功能区", "输入清除键", "函数插件区"];
|
||||
|
||||
function update_array(arr, item, mode) {
|
||||
// // Remove "输入清除键"
|
||||
// p = updateArray(p, "输入清除键", "remove");
|
||||
// console.log(p); // Should log: ["基础功能区", "函数插件区"]
|
||||
@ -60,13 +59,13 @@ function update_array(arr, item, mode) {
|
||||
const index = arr.indexOf(item);
|
||||
if (mode === "remove") {
|
||||
if (index !== -1) {
|
||||
// Item found, remove it
|
||||
arr.splice(index, 1);
|
||||
// Item found, remove it
|
||||
arr.splice(index, 1);
|
||||
}
|
||||
} else if (mode === "add") {
|
||||
if (index === -1) {
|
||||
// Item not found, add it
|
||||
arr.push(item);
|
||||
// Item not found, add it
|
||||
arr.push(item);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
@ -85,6 +84,7 @@ function gradioApp() {
|
||||
return elem.shadowRoot ? elem.shadowRoot : elem;
|
||||
}
|
||||
|
||||
|
||||
function setCookie(name, value, days) {
|
||||
var expires = "";
|
||||
|
||||
@ -97,6 +97,7 @@ function setCookie(name, value, days) {
|
||||
document.cookie = name + "=" + value + expires + "; path=/";
|
||||
}
|
||||
|
||||
|
||||
function getCookie(name) {
|
||||
var decodedCookie = decodeURIComponent(document.cookie);
|
||||
var cookies = decodedCookie.split(';');
|
||||
@ -112,6 +113,7 @@ function getCookie(name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
let toastCount = 0;
|
||||
function toast_push(msg, duration) {
|
||||
duration = isNaN(duration) ? 3000 : duration;
|
||||
@ -134,6 +136,7 @@ function toast_push(msg, duration) {
|
||||
toastCount++;
|
||||
}
|
||||
|
||||
|
||||
function toast_up(msg) {
|
||||
var m = document.getElementById('toast_up');
|
||||
if (m) {
|
||||
@ -146,6 +149,7 @@ function toast_up(msg) {
|
||||
document.body.appendChild(m);
|
||||
}
|
||||
|
||||
|
||||
function toast_down() {
|
||||
var m = document.getElementById('toast_up');
|
||||
if (m) {
|
||||
@ -153,6 +157,7 @@ function toast_down() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function begin_loading_status() {
|
||||
// Create the loader div and add styling
|
||||
var loader = document.createElement('div');
|
||||
@ -327,6 +332,7 @@ function do_something_but_not_too_frequently(min_interval, func) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function chatbotContentChanged(attempt = 1, force = false) {
|
||||
// https://github.com/GaiZhenbiao/ChuanhuChatGPT/tree/main/web_assets/javascript
|
||||
for (var i = 0; i < attempt; i++) {
|
||||
@ -343,7 +349,6 @@ function chatbotContentChanged(attempt = 1, force = false) {
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// 第 3 部分: chatbot动态高度调整
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
function chatbotAutoHeight() {
|
||||
// 自动调整高度:立即
|
||||
function update_height() {
|
||||
@ -375,6 +380,7 @@ function chatbotAutoHeight() {
|
||||
setInterval(function () { update_height_slow() }, 50); // 每50毫秒执行一次
|
||||
}
|
||||
|
||||
|
||||
swapped = false;
|
||||
function swap_input_area() {
|
||||
// Get the elements to be swapped
|
||||
@ -394,6 +400,7 @@ function swap_input_area() {
|
||||
else { swapped = true; }
|
||||
}
|
||||
|
||||
|
||||
function get_elements(consider_state_panel = false) {
|
||||
var chatbot = document.querySelector('#gpt-chatbot > div.wrap.svelte-18telvq');
|
||||
if (!chatbot) {
|
||||
@ -491,6 +498,7 @@ async function upload_files(files) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function register_func_paste(input) {
|
||||
let paste_files = [];
|
||||
if (input) {
|
||||
@ -517,6 +525,7 @@ function register_func_paste(input) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function register_func_drag(elem) {
|
||||
if (elem) {
|
||||
const dragEvents = ["dragover"];
|
||||
@ -553,6 +562,7 @@ function register_func_drag(elem) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function elem_upload_component_pop_message(elem) {
|
||||
if (elem) {
|
||||
const dragEvents = ["dragover"];
|
||||
@ -582,6 +592,7 @@ function elem_upload_component_pop_message(elem) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function register_upload_event() {
|
||||
locate_upload_elems();
|
||||
if (elem_upload_float) {
|
||||
@ -604,6 +615,7 @@ function register_upload_event() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function monitoring_input_box() {
|
||||
register_upload_event();
|
||||
|
||||
@ -637,7 +649,6 @@ window.addEventListener("DOMContentLoaded", function () {
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// 第 5 部分: 音频按钮样式变化
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
function audio_fn_init() {
|
||||
let audio_component = document.getElementById('elem_audio');
|
||||
if (audio_component) {
|
||||
@ -674,6 +685,7 @@ function audio_fn_init() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function minor_ui_adjustment() {
|
||||
let cbsc_area = document.getElementById('cbsc');
|
||||
cbsc_area.style.paddingTop = '15px';
|
||||
@ -766,21 +778,6 @@ function limit_scroll_position() {
|
||||
// 第 7 部分: JS初始化函数
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
function GptAcademicJavaScriptInit(LAYOUT = "LEFT-RIGHT") {
|
||||
audio_fn_init();
|
||||
minor_ui_adjustment();
|
||||
chatbotIndicator = gradioApp().querySelector('#gpt-chatbot > div.wrap');
|
||||
var chatbotObserver = new MutationObserver(() => {
|
||||
chatbotContentChanged(1);
|
||||
});
|
||||
chatbotObserver.observe(chatbotIndicator, { attributes: true, childList: true, subtree: true });
|
||||
if (LAYOUT === "LEFT-RIGHT") { chatbotAutoHeight(); }
|
||||
if (LAYOUT === "LEFT-RIGHT") { limit_scroll_position(); }
|
||||
// setInterval(function () { uml("mermaid") }, 5000); // 每50毫秒执行一次
|
||||
|
||||
}
|
||||
|
||||
|
||||
function loadLive2D() {
|
||||
try {
|
||||
$("<link>").attr({ href: "file=themes/waifu_plugin/waifu.css", rel: "stylesheet", type: "text/css" }).appendTo('head');
|
||||
@ -802,12 +799,12 @@ function loadLive2D() {
|
||||
live2d_settings['canTakeScreenshot'] = false;
|
||||
live2d_settings['canTurnToHomePage'] = false;
|
||||
live2d_settings['canTurnToAboutPage'] = false;
|
||||
live2d_settings['showHitokoto'] = false; // 显示一言
|
||||
live2d_settings['showHitokoto'] = false; // 显示一言
|
||||
live2d_settings['showF12Status'] = false; // 显示加载状态
|
||||
live2d_settings['showF12Message'] = false; // 显示看板娘消息
|
||||
live2d_settings['showF12OpenMsg'] = false; // 显示控制台打开提示
|
||||
live2d_settings['showCopyMessage'] = false; // 显示 复制内容 提示
|
||||
live2d_settings['showWelcomeMessage'] = true; // 显示进入面页欢迎词
|
||||
live2d_settings['showF12OpenMsg'] = false; // 显示控制台打开提示
|
||||
live2d_settings['showCopyMessage'] = false; // 显示 复制内容 提示
|
||||
live2d_settings['showWelcomeMessage'] = true; // 显示进入面页欢迎词
|
||||
/* 在 initModel 前添加 */
|
||||
initModel("file=themes/waifu_plugin/waifu-tips.json");
|
||||
}
|
||||
@ -817,7 +814,8 @@ function loadLive2D() {
|
||||
} catch (err) { console.log("[Error] JQuery is not defined.") }
|
||||
}
|
||||
|
||||
function get_checkbox_selected_items(elem_id){
|
||||
|
||||
function get_checkbox_selected_items(elem_id) {
|
||||
display_panel_arr = [];
|
||||
document.getElementById(elem_id).querySelector('[data-testid="checkbox-group"]').querySelectorAll('label').forEach(label => {
|
||||
// Get the span text
|
||||
@ -831,62 +829,24 @@ function get_checkbox_selected_items(elem_id){
|
||||
return display_panel_arr;
|
||||
}
|
||||
|
||||
function set_checkbox(key, bool, set_twice=false) {
|
||||
set_success = false;
|
||||
elem_ids = ["cbsc", "cbs"]
|
||||
elem_ids.forEach(id => {
|
||||
document.getElementById(id).querySelector('[data-testid="checkbox-group"]').querySelectorAll('label').forEach(label => {
|
||||
// Get the span text
|
||||
const spanText = label.querySelector('span').textContent;
|
||||
if (spanText === key) {
|
||||
if (bool){
|
||||
label.classList.add('selected');
|
||||
} else {
|
||||
if (label.classList.contains('selected')) {
|
||||
label.classList.remove('selected');
|
||||
}
|
||||
}
|
||||
if (set_twice){
|
||||
setTimeout(() => {
|
||||
if (bool){
|
||||
label.classList.add('selected');
|
||||
} else {
|
||||
if (label.classList.contains('selected')) {
|
||||
label.classList.remove('selected');
|
||||
}
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
label.querySelector('input').checked = bool;
|
||||
set_success = true;
|
||||
return
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!set_success){
|
||||
console.log("设置checkbox失败,没有找到对应的key")
|
||||
}
|
||||
}
|
||||
|
||||
function gpt_academic_gradio_saveload(
|
||||
save_or_load, // save_or_load==="save" / save_or_load==="load"
|
||||
elem_id, // element id
|
||||
cookie_key, // cookie key
|
||||
save_value="", // save value
|
||||
load_type = "str", // type==="str" / type==="float"
|
||||
load_default=false, // load default value
|
||||
load_default_value=""
|
||||
) {
|
||||
save_or_load, // save_or_load==="save" / save_or_load==="load"
|
||||
elem_id, // element id
|
||||
cookie_key, // cookie key
|
||||
save_value = "", // save value
|
||||
load_type = "str", // type==="str" / type==="float"
|
||||
load_default = false, // load default value
|
||||
load_default_value = ""
|
||||
) {
|
||||
if (save_or_load === "load") {
|
||||
let value = getCookie(cookie_key);
|
||||
if (value) {
|
||||
console.log('加载cookie', elem_id, value)
|
||||
push_data_to_gradio_component(value, elem_id, load_type);
|
||||
}
|
||||
else{
|
||||
if (load_default){
|
||||
else {
|
||||
if (load_default) {
|
||||
console.log('加载cookie的默认值', elem_id, load_default_value)
|
||||
push_data_to_gradio_component(load_default_value, elem_id, load_type);
|
||||
}
|
||||
@ -897,11 +857,24 @@ function gpt_academic_gradio_saveload(
|
||||
}
|
||||
}
|
||||
|
||||
async function init_frontend_with_cookies(dark, prompt, live2d) {
|
||||
let searchString = "输入清除键";
|
||||
let bool_value = "False";
|
||||
|
||||
////////////////// darkmode ///////////////////
|
||||
async function GptAcademicJavaScriptInit(dark, prompt, live2d, layout) {
|
||||
// 第一部分,布局初始化
|
||||
audio_fn_init();
|
||||
minor_ui_adjustment();
|
||||
chatbotIndicator = gradioApp().querySelector('#gpt-chatbot > div.wrap');
|
||||
var chatbotObserver = new MutationObserver(() => {
|
||||
chatbotContentChanged(1);
|
||||
});
|
||||
chatbotObserver.observe(chatbotIndicator, { attributes: true, childList: true, subtree: true });
|
||||
if (layout === "LEFT-RIGHT") { chatbotAutoHeight(); }
|
||||
if (layout === "LEFT-RIGHT") { limit_scroll_position(); }
|
||||
|
||||
// 第二部分,读取Cookie,初始话界面
|
||||
let searchString = "";
|
||||
let bool_value = "";
|
||||
|
||||
// darkmode 深色模式
|
||||
if (getCookie("js_darkmode_cookie")) {
|
||||
dark = getCookie("js_darkmode_cookie")
|
||||
}
|
||||
@ -916,12 +889,13 @@ async function init_frontend_with_cookies(dark, prompt, live2d) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////// SysPrompt ///////////////////////////
|
||||
// SysPrompt 系统静默提示词
|
||||
gpt_academic_gradio_saveload("load", "elem_prompt", "js_system_prompt_cookie", null, "str");
|
||||
////////////////////// Temperature ///////////////////////////
|
||||
|
||||
// Temperature 大模型温度参数
|
||||
gpt_academic_gradio_saveload("load", "elem_temperature", "js_temperature_cookie", null, "float");
|
||||
|
||||
////////////////////// clearButton ///////////////////////////
|
||||
// clearButton 自动清除按钮
|
||||
if (getCookie("js_clearbtn_show_cookie")) {
|
||||
// have cookie
|
||||
bool_value = getCookie("js_clearbtn_show_cookie")
|
||||
@ -949,7 +923,7 @@ async function init_frontend_with_cookies(dark, prompt, live2d) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////// live2d ///////////////////////////
|
||||
// live2d 显示
|
||||
if (getCookie("js_live2d_show_cookie")) {
|
||||
// have cookie
|
||||
searchString = "添加Live2D形象";
|
||||
|
@ -48,7 +48,7 @@ adjust_theme, advanced_css, theme_declaration, _ = load_dynamic_theme(get_conf("
|
||||
cookie相关工具函数
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
"""
|
||||
def init_cookie(cookies):
|
||||
def assign_user_uuid(cookies):
|
||||
# 为每一位访问的用户赋予一个独一无二的uuid编码
|
||||
cookies.update({"uuid": uuid.uuid4()})
|
||||
return cookies
|
||||
@ -106,8 +106,8 @@ js_code_for_toggle_darkmode = """() => {
|
||||
}"""
|
||||
|
||||
|
||||
js_code_for_persistent_cookie_init = """(py_pickle_cookie, cookie) => {
|
||||
return [getCookie("py_pickle_cookie"), cookie];
|
||||
js_code_for_persistent_cookie_init = """(web_cookie_cache, cookie) => {
|
||||
return [getCookie("web_cookie_cache"), cookie];
|
||||
}
|
||||
"""
|
||||
|
||||
|
21
toolbox.py
21
toolbox.py
@ -535,17 +535,13 @@ def on_file_uploaded(
|
||||
|
||||
|
||||
def on_report_generated(cookies:dict, files:List[str], chatbot:ChatBotWithCookies):
|
||||
# from toolbox import find_recent_files
|
||||
# PATH_LOGGING = get_conf('PATH_LOGGING')
|
||||
if "files_to_promote" in cookies:
|
||||
report_files = cookies["files_to_promote"]
|
||||
cookies.pop("files_to_promote")
|
||||
else:
|
||||
report_files = []
|
||||
# report_files = find_recent_files(PATH_LOGGING)
|
||||
if len(report_files) == 0:
|
||||
return cookies, None, chatbot
|
||||
# files.extend(report_files)
|
||||
file_links = ""
|
||||
for f in report_files:
|
||||
file_links += (
|
||||
@ -1009,10 +1005,13 @@ def check_repeat_upload(new_pdf_path, pdf_hash):
|
||||
return False, None
|
||||
|
||||
def log_chat(llm_model: str, input_str: str, output_str: str):
|
||||
if output_str and input_str and llm_model:
|
||||
uid = str(uuid.uuid4().hex)
|
||||
logging.info(f"[Model({uid})] {llm_model}")
|
||||
input_str = input_str.rstrip('\n')
|
||||
logging.info(f"[Query({uid})]\n{input_str}")
|
||||
output_str = output_str.rstrip('\n')
|
||||
logging.info(f"[Response({uid})]\n{output_str}\n\n")
|
||||
try:
|
||||
if output_str and input_str and llm_model:
|
||||
uid = str(uuid.uuid4().hex)
|
||||
logging.info(f"[Model({uid})] {llm_model}")
|
||||
input_str = input_str.rstrip('\n')
|
||||
logging.info(f"[Query({uid})]\n{input_str}")
|
||||
output_str = output_str.rstrip('\n')
|
||||
logging.info(f"[Response({uid})]\n{output_str}\n\n")
|
||||
except:
|
||||
print(trimmed_format_exc())
|
||||
|
4
version
4
version
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 3.73,
|
||||
"version": 3.74,
|
||||
"show_feature": true,
|
||||
"new_feature": "优化oneapi接入方法 <-> 接入月之暗面模型 <-> 支持切换多个智谱ai模型 <-> 用绘图功能增强部分插件 <-> 基础功能区支持自动切换中英提示词 <-> 支持Mermaid绘图库(让大模型绘制脑图)"
|
||||
"new_feature": "增加多用户文件鉴权验证提高安全性 <-> 优化oneapi接入方法 <-> 接入Cohere和月之暗面模型 <-> 简化挂载二级目录的步骤 <-> 支持Mermaid绘图库(让大模型绘制脑图)"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user