Compare commits
17 Commits
frontier
...
155e7e0deb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
155e7e0deb | ||
|
|
add29eba08 | ||
|
|
163e59c0f3 | ||
|
|
07ece29c7c | ||
|
|
991a903fa9 | ||
|
|
cf7c81170c | ||
|
|
6dda2061dd | ||
|
|
e9de41b7e8 | ||
|
|
b34c79a94b | ||
|
|
8a0d96afd3 | ||
|
|
37f9b94dee | ||
|
|
95284d859b | ||
|
|
a552592b5a | ||
|
|
e305f1b4a8 | ||
| a88497c3ab | |||
|
|
0f1d2e0e48 | ||
|
|
936e2f5206 |
28
README.md
28
README.md
@@ -1,11 +1,11 @@
|
||||
> [!IMPORTANT]
|
||||
> `master主分支`最新动态(2025.2.4): 增加deepseek-r1支持;增加字体自定义功能
|
||||
> `master主分支`最新动态(2025.2.2): 三分钟快速接入最强qwen2.5-max[视频](https://www.bilibili.com/video/BV1LeFuerEG4)
|
||||
> `master主分支`最新动态(2025.2.4): 增加deepseek-r1支持
|
||||
> `frontier开发分支`最新动态(2024.12.9): 更新对话时间线功能,优化xelatex论文翻译
|
||||
> `wiki文档`最新动态(2024.12.5): 更新ollama接入指南
|
||||
>
|
||||
> 2025.2.2: 三分钟快速接入最强qwen2.5-max[视频](https://www.bilibili.com/video/BV1LeFuerEG4)
|
||||
> 2025.2.1: 支持自定义字体
|
||||
> 2024.10.10: 突发停电,紧急恢复了提供[whl包](https://drive.google.com/drive/folders/14kR-3V-lIbvGxri4AHc8TpiA1fqsw7SK?usp=sharing)的文件服务器
|
||||
> 2024.10.8: 版本3.90加入对llama-index的初步支持,版本3.80加入插件二级菜单功能(详见wiki)
|
||||
> 2024.5.1: 加入Doc2x翻译PDF论文的功能,[查看详情](https://github.com/binary-husky/gpt_academic/wiki/Doc2x)
|
||||
> 2024.3.11: 全力支持Qwen、GLM、DeepseekCoder等中文大语言模型! SoVits语音克隆模块,[查看详情](https://www.bilibili.com/video/BV1Rp421S7tF/)
|
||||
> 2024.1.17: 安装依赖时,请选择`requirements.txt`中**指定的版本**。 安装命令:`pip install -r requirements.txt`。本项目完全开源免费,您可通过订阅[在线服务](https://github.com/binary-husky/gpt_academic/wiki/online)的方式鼓励本项目的发展。
|
||||
@@ -129,20 +129,20 @@ Latex论文一键校对 | [插件] 仿Grammarly对Latex文章进行语法、拼
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A{"安装方法"} --> W1("I. 🔑直接运行 (Windows, Linux or MacOS)")
|
||||
W1 --> W11["1. Python pip包管理依赖"]
|
||||
W1 --> W12["2. Anaconda包管理依赖(推荐⭐)"]
|
||||
A{"安装方法"} --> W1("I 🔑直接运行 (Windows, Linux or MacOS)")
|
||||
W1 --> W11["1 Python pip包管理依赖"]
|
||||
W1 --> W12["2 Anaconda包管理依赖(推荐⭐)"]
|
||||
|
||||
A --> W2["II. 🐳使用Docker (Windows, Linux or MacOS)"]
|
||||
A --> W2["II 🐳使用Docker (Windows, Linux or MacOS)"]
|
||||
|
||||
W2 --> k1["1. 部署项目全部能力的大镜像(推荐⭐)"]
|
||||
W2 --> k2["2. 仅在线模型(GPT, GLM4等)镜像"]
|
||||
W2 --> k3["3. 在线模型 + Latex的大镜像"]
|
||||
W2 --> k1["1 部署项目全部能力的大镜像(推荐⭐)"]
|
||||
W2 --> k2["2 仅在线模型(GPT, GLM4等)镜像"]
|
||||
W2 --> k3["3 在线模型 + Latex的大镜像"]
|
||||
|
||||
A --> W4["IV. 🚀其他部署方法"]
|
||||
W4 --> C1["1. Windows/MacOS 一键安装运行脚本(推荐⭐)"]
|
||||
W4 --> C2["2. Huggingface, Sealos远程部署"]
|
||||
W4 --> C4["3. ... 其他 ..."]
|
||||
A --> W4["IV 🚀其他部署方法"]
|
||||
W4 --> C1["1 Windows/MacOS 一键安装运行脚本(推荐⭐)"]
|
||||
W4 --> C2["2 Huggingface, Sealos远程部署"]
|
||||
W4 --> C4["3 其他 ..."]
|
||||
```
|
||||
|
||||
### 安装方法I:直接运行 (Windows, Linux or MacOS)
|
||||
|
||||
@@ -81,7 +81,7 @@ API_URL_REDIRECT = {}
|
||||
|
||||
# 多线程函数插件中,默认允许多少路线程同时访问OpenAI。Free trial users的限制是每分钟3次,Pay-as-you-go users的限制是每分钟3500次
|
||||
# 一言以蔽之:免费(5刀)用户填3,OpenAI绑了信用卡的用户可以填 16 或者更高。提高限制请查询:https://platform.openai.com/docs/guides/rate-limits/overview
|
||||
DEFAULT_WORKER_NUM = 3
|
||||
DEFAULT_WORKER_NUM = 8
|
||||
|
||||
|
||||
# 色彩主题, 可选 ["Default", "Chuanhu-Small-and-Beautiful", "High-Contrast"]
|
||||
@@ -103,6 +103,7 @@ AVAIL_FONTS = [
|
||||
"华文中宋(STZhongsong)",
|
||||
"华文新魏(STXinwei)",
|
||||
"华文隶书(STLiti)",
|
||||
# 备注:以下字体需要网络支持,您可以自定义任意您喜欢的字体,如下所示,需要满足的格式为 "字体昵称(字体英文真名@字体css下载链接)"
|
||||
"思源宋体(Source Han Serif CN VF@https://chinese-fonts-cdn.deno.dev/packages/syst/dist/SourceHanSerifCN/result.css)",
|
||||
"月星楷(Moon Stars Kai HW@https://chinese-fonts-cdn.deno.dev/packages/moon-stars-kai/dist/MoonStarsKaiHW-Regular/result.css)",
|
||||
"珠圆体(MaokenZhuyuanTi@https://chinese-fonts-cdn.deno.dev/packages/mkzyt/dist/猫啃珠圆体/result.css)",
|
||||
|
||||
444
config_private.py
Normal file
444
config_private.py
Normal file
@@ -0,0 +1,444 @@
|
||||
"""
|
||||
以下所有配置也都支持利用环境变量覆写,环境变量配置格式见docker-compose.yml。
|
||||
读取优先级:环境变量 > config_private.py > config.py
|
||||
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
|
||||
All the following configurations also support using environment variables to override,
|
||||
and the environment variable configuration format can be seen in docker-compose.yml.
|
||||
Configuration reading priority: environment variable > config_private.py > config.py
|
||||
"""
|
||||
|
||||
# [step 1-1]>> ( 接入GPT等模型 ) API_KEY = "sk-123456789xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx123456789"。极少数情况下,还需要填写组织(格式如org-123456789abcdefghijklmno的),请向下翻,找 API_ORG 设置项
|
||||
API_KEY = "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" # 可同时填写多个API-KEY,用英文逗号分割,例如API_KEY = "sk-openaikey1,sk-openaikey2,fkxxxx-api2dkey1,fkxxxx-api2dkey2"
|
||||
|
||||
# [step 1-2]>> ( 接入通义 qwen-max ) 接入通义千问在线大模型,api-key获取地址 https://dashscope.console.aliyun.com/
|
||||
DASHSCOPE_API_KEY = "" # 阿里灵积云API_KEY
|
||||
|
||||
# [step 1-3]>> ( 接入 deepseek-reasoner, 即 deepseek-r1 ) 深度求索(DeepSeek) API KEY,默认请求地址为"https://api.deepseek.com/v1/chat/completions"
|
||||
DEEPSEEK_API_KEY = "sk-d99b8cc6b7414cc88a5d950a3ff7585e"
|
||||
|
||||
# [step 2]>> 改为True应用代理。如果使用本地或无地域限制的大模型时,此处不修改;如果直接在海外服务器部署,此处不修改
|
||||
USE_PROXY = True
|
||||
if USE_PROXY:
|
||||
proxies = {
|
||||
"http":"socks5h://192.168.8.9:1070", # 再例如 "http": "http://127.0.0.1:7890",
|
||||
"https":"socks5h://192.168.8.9:1070", # 再例如 "https": "http://127.0.0.1:7890",
|
||||
}
|
||||
else:
|
||||
proxies = None
|
||||
DEFAULT_WORKER_NUM = 256
|
||||
|
||||
# [step 3]>> 模型选择是 (注意: LLM_MODEL是默认选中的模型, 它*必须*被包含在AVAIL_LLM_MODELS列表中 )
|
||||
LLM_MODEL = "gpt-4-32k" # 可选 ↓↓↓
|
||||
AVAIL_LLM_MODELS = ["deepseek-chat", "deepseek-coder", "deepseek-reasoner",
|
||||
"gpt-4-1106-preview", "gpt-4-turbo-preview", "gpt-4-vision-preview",
|
||||
"gpt-4o", "gpt-4o-mini", "gpt-4-turbo", "gpt-4-turbo-2024-04-09",
|
||||
"gpt-3.5-turbo-1106", "gpt-3.5-turbo-16k", "gpt-3.5-turbo", "azure-gpt-3.5",
|
||||
"gpt-4", "gpt-4-32k", "azure-gpt-4", "glm-4", "glm-4v", "glm-3-turbo",
|
||||
"gemini-1.5-pro", "chatglm3", "chatglm4",
|
||||
]
|
||||
|
||||
EMBEDDING_MODEL = "text-embedding-3-small"
|
||||
|
||||
# --- --- --- ---
|
||||
# P.S. 其他可用的模型还包括
|
||||
# AVAIL_LLM_MODELS = [
|
||||
# "glm-4-0520", "glm-4-air", "glm-4-airx", "glm-4-flash",
|
||||
# "qianfan", "deepseekcoder",
|
||||
# "spark", "sparkv2", "sparkv3", "sparkv3.5", "sparkv4",
|
||||
# "qwen-turbo", "qwen-plus", "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", "gpt-4o-2024-05-13"
|
||||
# "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",
|
||||
# "deepseek-chat" ,"deepseek-coder",
|
||||
# "gemini-1.5-flash",
|
||||
# "yi-34b-chat-0205","yi-34b-chat-200k","yi-large","yi-medium","yi-spark","yi-large-turbo","yi-large-preview",
|
||||
# "grok-beta",
|
||||
# ]
|
||||
# --- --- --- ---
|
||||
# 此外,您还可以在接入one-api/vllm/ollama/Openroute时,
|
||||
# 使用"one-api-*","vllm-*","ollama-*","openrouter-*"前缀直接使用非标准方式接入的模型,例如
|
||||
# AVAIL_LLM_MODELS = ["one-api-claude-3-sonnet-20240229(max_token=100000)", "ollama-phi3(max_token=4096)","openrouter-openai/gpt-4o-mini","openrouter-openai/chatgpt-4o-latest"]
|
||||
# --- --- --- ---
|
||||
|
||||
|
||||
# --------------- 以下配置可以优化体验 ---------------
|
||||
|
||||
# 重新URL重新定向,实现更换API_URL的作用(高危设置! 常规情况下不要修改! 通过修改此设置,您将把您的API-KEY和对话隐私完全暴露给您设定的中间人!)
|
||||
# 格式: API_URL_REDIRECT = {"https://api.openai.com/v1/chat/completions": "在这里填写重定向的api.openai.com的URL"}
|
||||
# 举例: API_URL_REDIRECT = {"https://api.openai.com/v1/chat/completions": "https://reverse-proxy-url/v1/chat/completions", "http://localhost:11434/api/chat": "在这里填写您ollama的URL"}
|
||||
API_URL_REDIRECT = {}
|
||||
|
||||
|
||||
# 多线程函数插件中,默认允许多少路线程同时访问OpenAI。Free trial users的限制是每分钟3次,Pay-as-you-go users的限制是每分钟3500次
|
||||
# 一言以蔽之:免费(5刀)用户填3,OpenAI绑了信用卡的用户可以填 16 或者更高。提高限制请查询:https://platform.openai.com/docs/guides/rate-limits/overview
|
||||
DEFAULT_WORKER_NUM = 64
|
||||
|
||||
|
||||
# 色彩主题, 可选 ["Default", "Chuanhu-Small-and-Beautiful", "High-Contrast"]
|
||||
# 更多主题, 请查阅Gradio主题商店: https://huggingface.co/spaces/gradio/theme-gallery 可选 ["Gstaff/Xkcd", "NoCrypt/Miku", ...]
|
||||
THEME = "Default"
|
||||
AVAIL_THEMES = ["Default", "Chuanhu-Small-and-Beautiful", "High-Contrast", "Gstaff/Xkcd", "NoCrypt/Miku"]
|
||||
|
||||
FONT = "Theme-Default-Font"
|
||||
AVAIL_FONTS = [
|
||||
"默认值(Theme-Default-Font)",
|
||||
"宋体(SimSun)",
|
||||
"黑体(SimHei)",
|
||||
"楷体(KaiTi)",
|
||||
"仿宋(FangSong)",
|
||||
"华文细黑(STHeiti Light)",
|
||||
"华文楷体(STKaiti)",
|
||||
"华文仿宋(STFangsong)",
|
||||
"华文宋体(STSong)",
|
||||
"华文中宋(STZhongsong)",
|
||||
"华文新魏(STXinwei)",
|
||||
"华文隶书(STLiti)",
|
||||
"思源宋体(Source Han Serif CN VF@https://chinese-fonts-cdn.deno.dev/packages/syst/dist/SourceHanSerifCN/result.css)",
|
||||
"月星楷(Moon Stars Kai HW@https://chinese-fonts-cdn.deno.dev/packages/moon-stars-kai/dist/MoonStarsKaiHW-Regular/result.css)",
|
||||
"珠圆体(MaokenZhuyuanTi@https://chinese-fonts-cdn.deno.dev/packages/mkzyt/dist/猫啃珠圆体/result.css)",
|
||||
"平方萌萌哒(PING FANG MENG MNEG DA@https://chinese-fonts-cdn.deno.dev/packages/pfmmd/dist/平方萌萌哒/result.css)",
|
||||
"Helvetica",
|
||||
"ui-sans-serif",
|
||||
"sans-serif",
|
||||
"system-ui"
|
||||
]
|
||||
|
||||
|
||||
# 默认的系统提示词(system prompt)
|
||||
INIT_SYS_PROMPT = "Serve me as a writing and programming assistant."
|
||||
|
||||
|
||||
# 对话窗的高度 (仅在LAYOUT="TOP-DOWN"时生效)
|
||||
CHATBOT_HEIGHT = 1115
|
||||
|
||||
|
||||
# 代码高亮
|
||||
CODE_HIGHLIGHT = True
|
||||
|
||||
|
||||
# 窗口布局
|
||||
LAYOUT = "LEFT-RIGHT" # "LEFT-RIGHT"(左右布局) # "TOP-DOWN"(上下布局)
|
||||
|
||||
|
||||
# 暗色模式 / 亮色模式
|
||||
DARK_MODE = True
|
||||
|
||||
|
||||
# 发送请求到OpenAI后,等待多久判定为超时
|
||||
TIMEOUT_SECONDS = 60
|
||||
|
||||
|
||||
# 网页的端口, -1代表随机端口
|
||||
WEB_PORT = 19998
|
||||
|
||||
# 是否自动打开浏览器页面
|
||||
AUTO_OPEN_BROWSER = True
|
||||
|
||||
|
||||
# 如果OpenAI不响应(网络卡顿、代理失败、KEY失效),重试的次数限制
|
||||
MAX_RETRY = 5
|
||||
|
||||
|
||||
# 插件分类默认选项
|
||||
DEFAULT_FN_GROUPS = ['对话', '编程', '学术', '智能体']
|
||||
|
||||
|
||||
# 定义界面上“询问多个GPT模型”插件应该使用哪些模型,请从AVAIL_LLM_MODELS中选择,并在不同模型之间用`&`间隔,例如"gpt-3.5-turbo&chatglm3&azure-gpt-4"
|
||||
MULTI_QUERY_LLM_MODELS = "gpt-3.5-turbo&chatglm3"
|
||||
|
||||
|
||||
# 选择本地模型变体(只有当AVAIL_LLM_MODELS包含了对应本地模型时,才会起作用)
|
||||
# 如果你选择Qwen系列的模型,那么请在下面的QWEN_MODEL_SELECTION中指定具体的模型
|
||||
# 也可以是具体的模型路径
|
||||
QWEN_LOCAL_MODEL_SELECTION = "Qwen/Qwen-1_8B-Chat-Int8"
|
||||
|
||||
|
||||
# 百度千帆(LLM_MODEL="qianfan")
|
||||
BAIDU_CLOUD_API_KEY = ''
|
||||
BAIDU_CLOUD_SECRET_KEY = ''
|
||||
BAIDU_CLOUD_QIANFAN_MODEL = 'ERNIE-Bot' # 可选 "ERNIE-Bot-4"(文心大模型4.0), "ERNIE-Bot"(文心一言), "ERNIE-Bot-turbo", "BLOOMZ-7B", "Llama-2-70B-Chat", "Llama-2-13B-Chat", "Llama-2-7B-Chat", "ERNIE-Speed-128K", "ERNIE-Speed-8K", "ERNIE-Lite-8K"
|
||||
|
||||
|
||||
# 如果使用ChatGLM3或ChatGLM4本地模型,请把 LLM_MODEL="chatglm3" 或LLM_MODEL="chatglm4",并在此处指定模型路径
|
||||
CHATGLM_LOCAL_MODEL_PATH = "THUDM/glm-4-9b-chat" # 例如"/home/hmp/ChatGLM3-6B/"
|
||||
|
||||
# 如果使用ChatGLM2微调模型,请把 LLM_MODEL="chatglmft",并在此处指定模型路径
|
||||
CHATGLM_PTUNING_CHECKPOINT = "" # 例如"/home/hmp/ChatGLM2-6B/ptuning/output/6b-pt-128-1e-2/checkpoint-100"
|
||||
|
||||
|
||||
# 本地LLM模型如ChatGLM的执行方式 CPU/GPU
|
||||
LOCAL_MODEL_DEVICE = "cpu" # 可选 "cuda"
|
||||
LOCAL_MODEL_QUANT = "FP16" # 默认 "FP16" "INT4" 启用量化INT4版本 "INT8" 启用量化INT8版本
|
||||
|
||||
|
||||
# 设置gradio的并行线程数(不需要修改)
|
||||
CONCURRENT_COUNT = 100
|
||||
|
||||
|
||||
# 是否在提交时自动清空输入框
|
||||
AUTO_CLEAR_TXT = False
|
||||
|
||||
|
||||
# 加一个live2d装饰
|
||||
ADD_WAIFU = False
|
||||
|
||||
|
||||
# 设置用户名和密码(不需要修改)(相关功能不稳定,与gradio版本和网络都相关,如果本地使用不建议加这个)
|
||||
# [("username", "password"), ("username2", "password2"), ...]
|
||||
AUTHENTICATION = [("van", "L807878712"),("林", "L807878712"),("源", "L807878712"),("欣", "L807878712"),("z", "czh123456789")]
|
||||
|
||||
|
||||
# 如果需要在二级路径下运行(常规情况下,不要修改!!)
|
||||
# (举例 CUSTOM_PATH = "/gpt_academic",可以让软件运行在 http://ip:port/gpt_academic/ 下。)
|
||||
CUSTOM_PATH = "/"
|
||||
|
||||
|
||||
# HTTPS 秘钥和证书(不需要修改)
|
||||
SSL_KEYFILE = ""
|
||||
SSL_CERTFILE = ""
|
||||
|
||||
|
||||
# 极少数情况下,openai的官方KEY需要伴随组织编码(格式如org-xxxxxxxxxxxxxxxxxxxxxxxx)使用
|
||||
API_ORG = ""
|
||||
|
||||
|
||||
# 如果需要使用Slack Claude,使用教程详情见 request_llms/README.md
|
||||
SLACK_CLAUDE_BOT_ID = ''
|
||||
SLACK_CLAUDE_USER_TOKEN = ''
|
||||
|
||||
|
||||
# 如果需要使用AZURE(方法一:单个azure模型部署)详情请见额外文档 docs\use_azure.md
|
||||
AZURE_ENDPOINT = "https://你亲手写的api名称.openai.azure.com/"
|
||||
AZURE_API_KEY = "填入azure openai api的密钥" # 建议直接在API_KEY处填写,该选项即将被弃用
|
||||
AZURE_ENGINE = "填入你亲手写的部署名" # 读 docs\use_azure.md
|
||||
|
||||
|
||||
# 如果需要使用AZURE(方法二:多个azure模型部署+动态切换)详情请见额外文档 docs\use_azure.md
|
||||
AZURE_CFG_ARRAY = {}
|
||||
|
||||
|
||||
# 阿里云实时语音识别 配置难度较高
|
||||
# 参考 https://github.com/binary-husky/gpt_academic/blob/master/docs/use_audio.md
|
||||
ENABLE_AUDIO = False
|
||||
ALIYUN_TOKEN="" # 例如 f37f30e0f9934c34a992f6f64f7eba4f
|
||||
ALIYUN_APPKEY="" # 例如 RoPlZrM88DnAFkZK
|
||||
ALIYUN_ACCESSKEY="" # (无需填写)
|
||||
ALIYUN_SECRET="" # (无需填写)
|
||||
|
||||
|
||||
# GPT-SOVITS 文本转语音服务的运行地址(将语言模型的生成文本朗读出来)
|
||||
TTS_TYPE = "DISABLE" # EDGE_TTS / LOCAL_SOVITS_API / DISABLE
|
||||
GPT_SOVITS_URL = ""
|
||||
EDGE_TTS_VOICE = "zh-CN-XiaoxiaoNeural"
|
||||
|
||||
|
||||
# 接入讯飞星火大模型 https://console.xfyun.cn/services/iat
|
||||
XFYUN_APPID = "00000000"
|
||||
XFYUN_API_SECRET = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||
XFYUN_API_KEY = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
|
||||
|
||||
# 接入智谱大模型
|
||||
ZHIPUAI_API_KEY = ""
|
||||
ZHIPUAI_MODEL = "" # 此选项已废弃,不再需要填写
|
||||
|
||||
|
||||
# Claude API KEY
|
||||
ANTHROPIC_API_KEY = ""
|
||||
|
||||
|
||||
# 月之暗面 API KEY
|
||||
MOONSHOT_API_KEY = ""
|
||||
|
||||
|
||||
# 零一万物(Yi Model) API KEY
|
||||
YIMODEL_API_KEY = ""
|
||||
|
||||
|
||||
# 紫东太初大模型 https://ai-maas.wair.ac.cn
|
||||
TAICHU_API_KEY = ""
|
||||
|
||||
# Grok API KEY
|
||||
GROK_API_KEY = ""
|
||||
|
||||
# Mathpix 拥有执行PDF的OCR功能,但是需要注册账号
|
||||
MATHPIX_APPID = ""
|
||||
MATHPIX_APPKEY = ""
|
||||
|
||||
|
||||
# DOC2X的PDF解析服务,注册账号并获取API KEY: https://doc2x.noedgeai.com/login
|
||||
DOC2X_API_KEY = ""
|
||||
|
||||
|
||||
# 自定义API KEY格式
|
||||
CUSTOM_API_KEY_PATTERN = ""
|
||||
|
||||
|
||||
# Google Gemini API-Key
|
||||
GEMINI_API_KEY = ''
|
||||
|
||||
|
||||
# HUGGINGFACE的TOKEN,下载LLAMA时起作用 https://huggingface.co/docs/hub/security-tokens
|
||||
HUGGINGFACE_ACCESS_TOKEN = "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"
|
||||
|
||||
|
||||
# GROBID服务器地址(填写多个可以均衡负载),用于高质量地读取PDF文档
|
||||
# 获取方法:复制以下空间https://huggingface.co/spaces/qingxu98/grobid,设为public,然后GROBID_URL = "https://(你的hf用户名如qingxu98)-(你的填写的空间名如grobid).hf.space"
|
||||
GROBID_URLS = [
|
||||
"https://qingxu98-grobid.hf.space","https://qingxu98-grobid2.hf.space","https://qingxu98-grobid3.hf.space",
|
||||
"https://qingxu98-grobid4.hf.space","https://qingxu98-grobid5.hf.space", "https://qingxu98-grobid6.hf.space",
|
||||
"https://qingxu98-grobid7.hf.space", "https://qingxu98-grobid8.hf.space",
|
||||
]
|
||||
|
||||
|
||||
# Searxng互联网检索服务(这是一个huggingface空间,请前往huggingface复制该空间,然后把自己新的空间地址填在这里)
|
||||
SEARXNG_URLS = [ f"https://kaletianlre-beardvs{i}dd.hf.space/" for i in range(1,5) ]
|
||||
|
||||
|
||||
# 是否允许通过自然语言描述修改本页的配置,该功能具有一定的危险性,默认关闭
|
||||
ALLOW_RESET_CONFIG = False
|
||||
|
||||
|
||||
# 在使用AutoGen插件时,是否使用Docker容器运行代码
|
||||
AUTOGEN_USE_DOCKER = False
|
||||
|
||||
|
||||
# 临时的上传文件夹位置,请尽量不要修改
|
||||
PATH_PRIVATE_UPLOAD = "private_upload"
|
||||
|
||||
|
||||
# 日志文件夹的位置,请尽量不要修改
|
||||
PATH_LOGGING = "gpt_log"
|
||||
|
||||
|
||||
# 存储翻译好的arxiv论文的路径,请尽量不要修改
|
||||
ARXIV_CACHE_DIR = "gpt_log/arxiv_cache"
|
||||
|
||||
|
||||
# 除了连接OpenAI之外,还有哪些场合允许使用代理,请尽量不要修改
|
||||
WHEN_TO_USE_PROXY = ["Connect_OpenAI", "Download_LLM", "Download_Gradio_Theme", "Connect_Grobid",
|
||||
"Warmup_Modules", "Nougat_Download", "AutoGen", "Connect_OpenAI_Embedding"]
|
||||
|
||||
|
||||
# 启用插件热加载
|
||||
PLUGIN_HOT_RELOAD = False
|
||||
|
||||
|
||||
# 自定义按钮的最大数量限制
|
||||
NUM_CUSTOM_BASIC_BTN = 4
|
||||
|
||||
|
||||
# 媒体智能体的服务地址(这是一个huggingface空间,请前往huggingface复制该空间,然后把自己新的空间地址填在这里)
|
||||
DAAS_SERVER_URLS = [ f"https://niuziniu-biligpt{i}.hf.space/stream" for i in range(1,5) ]
|
||||
|
||||
|
||||
|
||||
"""
|
||||
--------------- 配置关联关系说明 ---------------
|
||||
|
||||
在线大模型配置关联关系示意图
|
||||
│
|
||||
├── "gpt-3.5-turbo" 等openai模型
|
||||
│ ├── API_KEY
|
||||
│ ├── CUSTOM_API_KEY_PATTERN(不常用)
|
||||
│ ├── API_ORG(不常用)
|
||||
│ └── API_URL_REDIRECT(不常用)
|
||||
│
|
||||
├── "azure-gpt-3.5" 等azure模型(单个azure模型,不需要动态切换)
|
||||
│ ├── API_KEY
|
||||
│ ├── AZURE_ENDPOINT
|
||||
│ ├── AZURE_API_KEY
|
||||
│ ├── AZURE_ENGINE
|
||||
│ └── API_URL_REDIRECT
|
||||
│
|
||||
├── "azure-gpt-3.5" 等azure模型(多个azure模型,需要动态切换,高优先级)
|
||||
│ └── AZURE_CFG_ARRAY
|
||||
│
|
||||
├── "spark" 星火认知大模型 spark & sparkv2
|
||||
│ ├── XFYUN_APPID
|
||||
│ ├── XFYUN_API_SECRET
|
||||
│ └── XFYUN_API_KEY
|
||||
│
|
||||
├── "claude-3-opus-20240229" 等claude模型
|
||||
│ └── ANTHROPIC_API_KEY
|
||||
│
|
||||
├── "stack-claude"
|
||||
│ ├── SLACK_CLAUDE_BOT_ID
|
||||
│ └── SLACK_CLAUDE_USER_TOKEN
|
||||
│
|
||||
├── "qianfan" 百度千帆大模型库
|
||||
│ ├── BAIDU_CLOUD_QIANFAN_MODEL
|
||||
│ ├── BAIDU_CLOUD_API_KEY
|
||||
│ └── BAIDU_CLOUD_SECRET_KEY
|
||||
│
|
||||
├── "glm-4", "glm-3-turbo", "zhipuai" 智谱AI大模型
|
||||
│ └── ZHIPUAI_API_KEY
|
||||
│
|
||||
├── "yi-34b-chat-0205", "yi-34b-chat-200k" 等零一万物(Yi Model)大模型
|
||||
│ └── YIMODEL_API_KEY
|
||||
│
|
||||
├── "qwen-turbo" 等通义千问大模型
|
||||
│ └── DASHSCOPE_API_KEY
|
||||
│
|
||||
├── "Gemini"
|
||||
│ └── GEMINI_API_KEY
|
||||
│
|
||||
└── "one-api-...(max_token=...)" 用一种更方便的方式接入one-api多模型管理界面
|
||||
├── AVAIL_LLM_MODELS
|
||||
├── API_KEY
|
||||
└── API_URL_REDIRECT
|
||||
|
||||
|
||||
本地大模型示意图
|
||||
│
|
||||
├── "chatglm4"
|
||||
├── "chatglm3"
|
||||
├── "chatglm"
|
||||
├── "chatglm_onnx"
|
||||
├── "chatglmft"
|
||||
├── "internlm"
|
||||
├── "moss"
|
||||
├── "jittorllms_pangualpha"
|
||||
├── "jittorllms_llama"
|
||||
├── "deepseekcoder"
|
||||
├── "qwen-local"
|
||||
├── RWKV的支持见Wiki
|
||||
└── "llama2"
|
||||
|
||||
|
||||
用户图形界面布局依赖关系示意图
|
||||
│
|
||||
├── CHATBOT_HEIGHT 对话窗的高度
|
||||
├── CODE_HIGHLIGHT 代码高亮
|
||||
├── LAYOUT 窗口布局
|
||||
├── DARK_MODE 暗色模式 / 亮色模式
|
||||
├── DEFAULT_FN_GROUPS 插件分类默认选项
|
||||
├── THEME 色彩主题
|
||||
├── AUTO_CLEAR_TXT 是否在提交时自动清空输入框
|
||||
├── ADD_WAIFU 加一个live2d装饰
|
||||
└── ALLOW_RESET_CONFIG 是否允许通过自然语言描述修改本页的配置,该功能具有一定的危险性
|
||||
|
||||
|
||||
插件在线服务配置依赖关系示意图
|
||||
│
|
||||
├── 互联网检索
|
||||
│ └── SEARXNG_URLS
|
||||
│
|
||||
├── 语音功能
|
||||
│ ├── ENABLE_AUDIO
|
||||
│ ├── ALIYUN_TOKEN
|
||||
│ ├── ALIYUN_APPKEY
|
||||
│ ├── ALIYUN_ACCESSKEY
|
||||
│ └── ALIYUN_SECRET
|
||||
│
|
||||
└── PDF文档精准解析
|
||||
├── GROBID_URLS
|
||||
├── MATHPIX_APPID
|
||||
└── MATHPIX_APPKEY
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ def 载入对话历史存档(txt, llm_kwargs, plugin_kwargs, chatbot, history, s
|
||||
user_request 当前用户的请求信息(IP地址等)
|
||||
"""
|
||||
from crazy_functions.crazy_utils import get_files_from_everything
|
||||
success, file_manifest, _ = get_files_from_everything(txt, type='.html',chatbot=chatbot)
|
||||
success, file_manifest, _ = get_files_from_everything(txt, type='.html')
|
||||
|
||||
if not success:
|
||||
if txt == "": txt = '空空如也的输入栏'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from shared_utils.fastapi_server import validate_path_safety
|
||||
from toolbox import update_ui, trimmed_format_exc, promote_file_to_downloadzone, get_log_folder
|
||||
from toolbox import CatchException, report_exception, write_history_to_file, zip_folder
|
||||
from loguru import logger
|
||||
@@ -156,7 +155,6 @@ def Latex英文润色(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_p
|
||||
import glob, os
|
||||
if os.path.exists(txt):
|
||||
project_folder = txt
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
else:
|
||||
if txt == "": txt = '空空如也的输入栏'
|
||||
report_exception(chatbot, history, a = f"解析项目: {txt}", b = f"找不到本地项目或无权访问: {txt}")
|
||||
@@ -195,7 +193,6 @@ def Latex中文润色(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_p
|
||||
import glob, os
|
||||
if os.path.exists(txt):
|
||||
project_folder = txt
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
else:
|
||||
if txt == "": txt = '空空如也的输入栏'
|
||||
report_exception(chatbot, history, a = f"解析项目: {txt}", b = f"找不到本地项目或无权访问: {txt}")
|
||||
@@ -232,7 +229,6 @@ def Latex英文纠错(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_p
|
||||
import glob, os
|
||||
if os.path.exists(txt):
|
||||
project_folder = txt
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
else:
|
||||
if txt == "": txt = '空空如也的输入栏'
|
||||
report_exception(chatbot, history, a = f"解析项目: {txt}", b = f"找不到本地项目或无权访问: {txt}")
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import glob, shutil, os, re
|
||||
from loguru import logger
|
||||
from shared_utils.fastapi_server import validate_path_safety
|
||||
from toolbox import update_ui, trimmed_format_exc, gen_time_str
|
||||
from toolbox import CatchException, report_exception, get_log_folder
|
||||
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||
@@ -119,7 +118,7 @@ def 多文件翻译(file_manifest, project_folder, llm_kwargs, plugin_kwargs, ch
|
||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||
|
||||
|
||||
def get_files_from_everything(txt, preference='', chatbox=None):
|
||||
def get_files_from_everything(txt, preference=''):
|
||||
if txt == "": return False, None, None
|
||||
success = True
|
||||
if txt.startswith('http'):
|
||||
@@ -147,11 +146,9 @@ def get_files_from_everything(txt, preference='', chatbox=None):
|
||||
# 直接给定文件
|
||||
file_manifest = [txt]
|
||||
project_folder = os.path.dirname(txt)
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
elif os.path.exists(txt):
|
||||
# 本地路径,递归搜索
|
||||
project_folder = txt
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.md', recursive=True)]
|
||||
else:
|
||||
project_folder = None
|
||||
@@ -180,7 +177,7 @@ def Markdown英译中(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_p
|
||||
return
|
||||
history = [] # 清空历史,以免输入溢出
|
||||
|
||||
success, file_manifest, project_folder = get_files_from_everything(txt, preference="Github", chatbox=chatbot)
|
||||
success, file_manifest, project_folder = get_files_from_everything(txt, preference="Github")
|
||||
|
||||
if not success:
|
||||
# 什么都没有
|
||||
|
||||
@@ -26,7 +26,7 @@ def 批量翻译PDF文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst
|
||||
|
||||
# 清空历史,以免输入溢出
|
||||
history = []
|
||||
success, file_manifest, project_folder = get_files_from_everything(txt, type='.pdf', chatbot=chatbot)
|
||||
success, file_manifest, project_folder = get_files_from_everything(txt, type='.pdf')
|
||||
|
||||
# 检测输入参数,如没有给定输入参数,直接退出
|
||||
if (not success) and txt == "": txt = '空空如也的输入栏。提示:请先上传文件(把PDF文件拖入对话)。'
|
||||
|
||||
@@ -2,7 +2,6 @@ import os
|
||||
import threading
|
||||
from loguru import logger
|
||||
from shared_utils.char_visual_effect import scolling_visual_effect
|
||||
from shared_utils.fastapi_server import validate_path_safety
|
||||
from toolbox import update_ui, get_conf, trimmed_format_exc, get_max_token, Singleton
|
||||
|
||||
def input_clipping(inputs, history, max_token_limit, return_clip_flags=False):
|
||||
@@ -540,7 +539,7 @@ def read_and_clean_pdf_text(fp):
|
||||
return meta_txt, page_one_meta
|
||||
|
||||
|
||||
def get_files_from_everything(txt, type, chatbot=None): # type='.md'
|
||||
def get_files_from_everything(txt, type): # type='.md'
|
||||
"""
|
||||
这个函数是用来获取指定目录下所有指定类型(如.md)的文件,并且对于网络上的文件,也可以获取它。
|
||||
下面是对每个参数和返回值的说明:
|
||||
@@ -552,7 +551,6 @@ def get_files_from_everything(txt, type, chatbot=None): # type='.md'
|
||||
- file_manifest: 文件路径列表,里面包含以指定类型为后缀名的所有文件的绝对路径。
|
||||
- project_folder: 字符串,表示文件所在的文件夹路径。如果是网络上的文件,就是临时文件夹的路径。
|
||||
该函数详细注释已添加,请确认是否满足您的需要。
|
||||
- chatbot 带Cookies的Chatbot类,为实现更多强大的功能做基础
|
||||
"""
|
||||
import glob, os
|
||||
|
||||
@@ -575,13 +573,9 @@ def get_files_from_everything(txt, type, chatbot=None): # type='.md'
|
||||
# 直接给定文件
|
||||
file_manifest = [txt]
|
||||
project_folder = os.path.dirname(txt)
|
||||
if chatbot is not None:
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
elif os.path.exists(txt):
|
||||
# 本地路径,递归搜索
|
||||
project_folder = txt
|
||||
if chatbot is not None:
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
file_manifest = [f for f in glob.glob(f'{project_folder}/**/*'+type, recursive=True)]
|
||||
if len(file_manifest) == 0:
|
||||
success = False
|
||||
|
||||
@@ -242,7 +242,9 @@ def 解析PDF_DOC2X_单文件(
|
||||
extract_archive(file_path=this_file_path, dest_dir=ex_folder)
|
||||
|
||||
# edit markdown files
|
||||
success, file_manifest, project_folder = get_files_from_everything(ex_folder, type='.md', chatbot=chatbot)
|
||||
success, file_manifest, project_folder = get_files_from_everything(
|
||||
ex_folder, type=".md"
|
||||
)
|
||||
for generated_fp in file_manifest:
|
||||
# 修正一些公式问题
|
||||
with open(generated_fp, "r", encoding="utf8") as f:
|
||||
|
||||
@@ -27,10 +27,10 @@ def extract_text_from_files(txt, chatbot, history):
|
||||
return False, final_result, page_one, file_manifest, excption #如输入区内容不是文件则直接返回输入区内容
|
||||
|
||||
#查找输入区内容中的文件
|
||||
file_pdf,pdf_manifest,folder_pdf = get_files_from_everything(txt, '.pdf', chatbot=chatbot)
|
||||
file_md,md_manifest,folder_md = get_files_from_everything(txt, '.md', chatbot=chatbot)
|
||||
file_word,word_manifest,folder_word = get_files_from_everything(txt, '.docx', chatbot=chatbot)
|
||||
file_doc,doc_manifest,folder_doc = get_files_from_everything(txt, '.doc', chatbot=chatbot)
|
||||
file_pdf,pdf_manifest,folder_pdf = get_files_from_everything(txt, '.pdf')
|
||||
file_md,md_manifest,folder_md = get_files_from_everything(txt, '.md')
|
||||
file_word,word_manifest,folder_word = get_files_from_everything(txt, '.docx')
|
||||
file_doc,doc_manifest,folder_doc = get_files_from_everything(txt, '.doc')
|
||||
|
||||
if file_doc:
|
||||
excption = "word"
|
||||
|
||||
@@ -104,8 +104,6 @@ def 总结word文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_pr
|
||||
# 检测输入参数,如没有给定输入参数,直接退出
|
||||
if os.path.exists(txt):
|
||||
project_folder = txt
|
||||
from shared_utils.fastapi_server import validate_path_safety
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
else:
|
||||
if txt == "": txt = '空空如也的输入栏'
|
||||
report_exception(chatbot, history, a=f"解析项目: {txt}", b=f"找不到本地项目或无权访问: {txt}")
|
||||
|
||||
@@ -61,7 +61,7 @@ def 批量翻译PDF文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst
|
||||
history = []
|
||||
|
||||
from crazy_functions.crazy_utils import get_files_from_everything
|
||||
success, file_manifest, project_folder = get_files_from_everything(txt, type='.pdf', chatbot=chatbot)
|
||||
success, file_manifest, project_folder = get_files_from_everything(txt, type='.pdf')
|
||||
if len(file_manifest) > 0:
|
||||
# 尝试导入依赖,如果缺少依赖,则给出安装建议
|
||||
try:
|
||||
@@ -73,7 +73,7 @@ def 批量翻译PDF文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst
|
||||
b=f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade nougat-ocr tiktoken```。")
|
||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||
return
|
||||
success_mmd, file_manifest_mmd, _ = get_files_from_everything(txt, type='.mmd', chatbot=chatbot)
|
||||
success_mmd, file_manifest_mmd, _ = get_files_from_everything(txt, type='.mmd')
|
||||
success = success or success_mmd
|
||||
file_manifest += file_manifest_mmd
|
||||
chatbot.append(["文件列表:", ", ".join([e.split('/')[-1] for e in file_manifest])]);
|
||||
|
||||
@@ -87,8 +87,6 @@ def 理解PDF文档内容标准文件输入(txt, llm_kwargs, plugin_kwargs, chat
|
||||
# 检测输入参数,如没有给定输入参数,直接退出
|
||||
if os.path.exists(txt):
|
||||
project_folder = txt
|
||||
from shared_utils.fastapi_server import validate_path_safety
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
else:
|
||||
if txt == "":
|
||||
txt = '空空如也的输入栏'
|
||||
|
||||
@@ -39,8 +39,6 @@ def 批量生成函数注释(txt, llm_kwargs, plugin_kwargs, chatbot, history, s
|
||||
import glob, os
|
||||
if os.path.exists(txt):
|
||||
project_folder = txt
|
||||
from shared_utils.fastapi_server import validate_path_safety
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
else:
|
||||
if txt == "": txt = '空空如也的输入栏'
|
||||
report_exception(chatbot, history, a = f"解析项目: {txt}", b = f"找不到本地项目或无权访问: {txt}")
|
||||
|
||||
@@ -49,7 +49,7 @@ def 知识库文件注入(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst
|
||||
file_manifest = []
|
||||
spl = ["txt", "doc", "docx", "email", "epub", "html", "json", "md", "msg", "pdf", "ppt", "pptx", "rtf"]
|
||||
for sp in spl:
|
||||
_, file_manifest_tmp, _ = get_files_from_everything(txt, type=f'.{sp}', chatbot=chatbot)
|
||||
_, file_manifest_tmp, _ = get_files_from_everything(txt, type=f'.{sp}')
|
||||
file_manifest += file_manifest_tmp
|
||||
|
||||
if len(file_manifest) == 0:
|
||||
|
||||
@@ -126,8 +126,6 @@ def 解析ipynb文件(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_p
|
||||
import os
|
||||
if os.path.exists(txt):
|
||||
project_folder = txt
|
||||
from shared_utils.fastapi_server import validate_path_safety
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
else:
|
||||
if txt == "":
|
||||
txt = '空空如也的输入栏'
|
||||
|
||||
@@ -48,8 +48,6 @@ def 读文章写摘要(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_
|
||||
import glob, os
|
||||
if os.path.exists(txt):
|
||||
project_folder = txt
|
||||
from shared_utils.fastapi_server import validate_path_safety
|
||||
validate_path_safety(project_folder, chatbot.get_user())
|
||||
else:
|
||||
if txt == "": txt = '空空如也的输入栏'
|
||||
report_exception(chatbot, history, a = f"解析项目: {txt}", b = f"找不到本地项目或无权访问: {txt}")
|
||||
|
||||
13
main.py
13
main.py
@@ -1,10 +1,7 @@
|
||||
import os; os.environ['no_proxy'] = '*' # 避免代理网络产生意外污染
|
||||
|
||||
help_menu_description = \
|
||||
"""Github源代码开源和更新[地址🚀](https://github.com/binary-husky/gpt_academic),
|
||||
感谢热情的[开发者们❤️](https://github.com/binary-husky/gpt_academic/graphs/contributors).
|
||||
</br></br>常见问题请查阅[项目Wiki](https://github.com/binary-husky/gpt_academic/wiki),
|
||||
如遇到Bug请前往[Bug反馈](https://github.com/binary-husky/gpt_academic/issues).
|
||||
"""
|
||||
</br></br>普通对话使用说明: 1. 输入问题; 2. 点击提交
|
||||
</br></br>基础功能区使用说明: 1. 输入文本; 2. 点击任意基础功能区按钮
|
||||
</br></br>函数插件区使用说明: 1. 输入路径/问题, 或者上传文件; 2. 点击任意函数插件区按钮
|
||||
@@ -57,7 +54,7 @@ def main():
|
||||
# 如果WEB_PORT是-1, 则随机选取WEB端口
|
||||
PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT
|
||||
from check_proxy import get_current_version
|
||||
from themes.theme import adjust_theme, advanced_css, theme_declaration, js_code_clear, js_code_show_or_hide, js_code_show_or_hide_group2
|
||||
from themes.theme import adjust_theme, advanced_css, theme_declaration, js_code_clear, js_code_show_or_hide
|
||||
from themes.theme import js_code_for_toggle_darkmode
|
||||
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}"
|
||||
@@ -184,7 +181,7 @@ def main():
|
||||
from themes.gui_floating_menu import define_gui_floating_menu
|
||||
area_input_secondary, txt2, area_customize, _, resetBtn2, clearBtn2, stopBtn2 = \
|
||||
define_gui_floating_menu(customize_btns, functional, predefined_btns, cookies, web_cookie_cache)
|
||||
|
||||
|
||||
# 浮动时间线定义
|
||||
gr.Spark()
|
||||
|
||||
@@ -210,14 +207,14 @@ def main():
|
||||
ret.update({area_customize: gr.update(visible=("自定义菜单" in a))})
|
||||
return ret
|
||||
checkboxes_2.select(fn_area_visibility_2, [checkboxes_2], [area_customize] )
|
||||
checkboxes_2.select(None, [checkboxes_2], None, _js=js_code_show_or_hide_group2)
|
||||
checkboxes_2.select(None, [checkboxes_2], None, _js="""apply_checkbox_change_for_group2""")
|
||||
|
||||
# 整理反复出现的控件句柄组合
|
||||
input_combo = [cookies, max_length_sl, md_dropdown, txt, txt2, top_p, temperature, chatbot, history, system_prompt, plugin_advanced_arg]
|
||||
input_combo_order = ["cookies", "max_length_sl", "md_dropdown", "txt", "txt2", "top_p", "temperature", "chatbot", "history", "system_prompt", "plugin_advanced_arg"]
|
||||
output_combo = [cookies, chatbot, history, status]
|
||||
predict_args = dict(fn=ArgsGeneralWrapper(predict), inputs=[*input_combo, gr.State(True)], outputs=output_combo)
|
||||
|
||||
|
||||
# 提交按钮、重置按钮
|
||||
multiplex_submit_btn.click(
|
||||
None, [multiplex_sel], None, _js="""(multiplex_sel)=>multiplex_function_begin(multiplex_sel)""")
|
||||
|
||||
@@ -1072,7 +1072,7 @@ if "zhipuai" in AVAIL_LLM_MODELS: # zhipuai 是glm-4的别名,向后兼容
|
||||
})
|
||||
except:
|
||||
logger.error(trimmed_format_exc())
|
||||
# -=-=-=-=-=-=- 幻方-深度求索大模型 -=-=-=-=-=-=-
|
||||
# -=-=-=-=-=-=- 幻方-深度求索本地大模型 -=-=-=-=-=-=-
|
||||
if "deepseekcoder" in AVAIL_LLM_MODELS: # deepseekcoder
|
||||
try:
|
||||
from .bridge_deepseekcoder import predict_no_ui_long_connection as deepseekcoder_noui
|
||||
|
||||
@@ -6,7 +6,6 @@ from toolbox import get_conf
|
||||
from request_llms.local_llm_class import LocalLLMHandle, get_local_llm_predict_fns
|
||||
from threading import Thread
|
||||
from loguru import logger
|
||||
import torch
|
||||
import os
|
||||
|
||||
def download_huggingface_model(model_name, max_retry, local_dir):
|
||||
@@ -29,6 +28,7 @@ class GetCoderLMHandle(LocalLLMHandle):
|
||||
self.cmd_to_install = cmd_to_install
|
||||
|
||||
def load_model_and_tokenizer(self):
|
||||
import torch
|
||||
# 🏃♂️🏃♂️🏃♂️ 子进程执行
|
||||
with ProxyNetworkActivate('Download_LLM'):
|
||||
from transformers import AutoTokenizer, AutoModelForCausalLM, TextIteratorStreamer
|
||||
|
||||
@@ -512,7 +512,7 @@ def generate_payload(inputs:str, llm_kwargs:dict, history:list, system_prompt:st
|
||||
model, _ = read_one_api_model_name(model)
|
||||
if llm_kwargs['llm_model'].startswith('openrouter-'):
|
||||
model = llm_kwargs['llm_model'][len('openrouter-'):]
|
||||
model= read_one_api_model_name(model)
|
||||
model, _= read_one_api_model_name(model)
|
||||
if model == "gpt-3.5-random": # 随机选择, 绕过openai访问频率限制
|
||||
model = random.choice([
|
||||
"gpt-3.5-turbo",
|
||||
|
||||
@@ -2,15 +2,9 @@ import json
|
||||
import time
|
||||
import traceback
|
||||
import requests
|
||||
from loguru import logger
|
||||
|
||||
# config_private.py放自己的秘密如API和代理网址
|
||||
# 读取时首先看是否存在私密的config_private配置文件(不受git管控),如果有,则覆盖原config文件
|
||||
from toolbox import (
|
||||
get_conf,
|
||||
update_ui,
|
||||
is_the_upload_folder,
|
||||
)
|
||||
from loguru import logger
|
||||
from toolbox import get_conf, is_the_upload_folder, update_ui, update_ui_lastest_msg
|
||||
|
||||
proxies, TIMEOUT_SECONDS, MAX_RETRY = get_conf(
|
||||
"proxies", "TIMEOUT_SECONDS", "MAX_RETRY"
|
||||
@@ -39,27 +33,35 @@ def decode_chunk(chunk):
|
||||
用于解读"content"和"finish_reason"的内容(如果支持思维链也会返回"reasoning_content"内容)
|
||||
"""
|
||||
chunk = chunk.decode()
|
||||
respose = ""
|
||||
response = ""
|
||||
reasoning_content = ""
|
||||
finish_reason = "False"
|
||||
|
||||
# 考虑返回类型是 text/json 和 text/event-stream 两种
|
||||
if chunk.startswith("data: "):
|
||||
chunk = chunk[6:]
|
||||
else:
|
||||
chunk = chunk
|
||||
|
||||
try:
|
||||
chunk = json.loads(chunk[6:])
|
||||
chunk = json.loads(chunk)
|
||||
except:
|
||||
respose = ""
|
||||
response = ""
|
||||
finish_reason = chunk
|
||||
|
||||
# 错误处理部分
|
||||
if "error" in chunk:
|
||||
respose = "API_ERROR"
|
||||
response = "API_ERROR"
|
||||
try:
|
||||
chunk = json.loads(chunk)
|
||||
finish_reason = chunk["error"]["code"]
|
||||
except:
|
||||
finish_reason = "API_ERROR"
|
||||
return respose, finish_reason
|
||||
return response, reasoning_content, finish_reason
|
||||
|
||||
try:
|
||||
if chunk["choices"][0]["delta"]["content"] is not None:
|
||||
respose = chunk["choices"][0]["delta"]["content"]
|
||||
response = chunk["choices"][0]["delta"]["content"]
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
@@ -71,7 +73,7 @@ def decode_chunk(chunk):
|
||||
finish_reason = chunk["choices"][0]["finish_reason"]
|
||||
except:
|
||||
pass
|
||||
return respose, reasoning_content, finish_reason
|
||||
return response, reasoning_content, finish_reason, str(chunk)
|
||||
|
||||
|
||||
def generate_message(input, model, key, history, max_output_token, system_prompt, temperature):
|
||||
@@ -106,7 +108,7 @@ def generate_message(input, model, key, history, max_output_token, system_prompt
|
||||
what_i_ask_now["role"] = "user"
|
||||
what_i_ask_now["content"] = input
|
||||
messages.append(what_i_ask_now)
|
||||
playload = {
|
||||
payload = {
|
||||
"model": model,
|
||||
"messages": messages,
|
||||
"temperature": temperature,
|
||||
@@ -114,7 +116,7 @@ def generate_message(input, model, key, history, max_output_token, system_prompt
|
||||
"max_tokens": max_output_token,
|
||||
}
|
||||
|
||||
return headers, playload
|
||||
return headers, payload
|
||||
|
||||
|
||||
def get_predict_function(
|
||||
@@ -141,7 +143,7 @@ def get_predict_function(
|
||||
history=[],
|
||||
sys_prompt="",
|
||||
observe_window=None,
|
||||
console_slience=False,
|
||||
console_silence=False,
|
||||
):
|
||||
"""
|
||||
发送至chatGPT,等待回复,一次性完成,不显示中间过程。但内部用stream的方法避免中途网线被掐。
|
||||
@@ -157,12 +159,12 @@ def get_predict_function(
|
||||
用于负责跨越线程传递已经输出的部分,大部分时候仅仅为了fancy的视觉效果,留空即可。observe_window[0]:观测窗。observe_window[1]:看门狗
|
||||
"""
|
||||
from .bridge_all import model_info
|
||||
watch_dog_patience = 5 # 看门狗的耐心,设置5秒不准咬人(咬的也不是人
|
||||
watch_dog_patience = 5 # 看门狗的耐心,设置5秒不准咬人 (咬的也不是人)
|
||||
if len(APIKEY) == 0:
|
||||
raise RuntimeError(f"APIKEY为空,请检查配置文件的{APIKEY}")
|
||||
if inputs == "":
|
||||
inputs = "你好👋"
|
||||
headers, playload = generate_message(
|
||||
headers, payload = generate_message(
|
||||
input=inputs,
|
||||
model=llm_kwargs["llm_model"],
|
||||
key=APIKEY,
|
||||
@@ -182,7 +184,7 @@ def get_predict_function(
|
||||
endpoint,
|
||||
headers=headers,
|
||||
proxies=None if disable_proxy else proxies,
|
||||
json=playload,
|
||||
json=payload,
|
||||
stream=True,
|
||||
timeout=TIMEOUT_SECONDS,
|
||||
)
|
||||
@@ -198,7 +200,7 @@ def get_predict_function(
|
||||
result = ""
|
||||
finish_reason = ""
|
||||
if reasoning:
|
||||
resoning_buffer = ""
|
||||
reasoning_buffer = ""
|
||||
|
||||
stream_response = response.iter_lines()
|
||||
while True:
|
||||
@@ -210,7 +212,7 @@ def get_predict_function(
|
||||
break
|
||||
except requests.exceptions.ConnectionError:
|
||||
chunk = next(stream_response) # 失败了,重试一次?再失败就没办法了。
|
||||
response_text, reasoning_content, finish_reason = decode_chunk(chunk)
|
||||
response_text, reasoning_content, finish_reason, decoded_chunk = decode_chunk(chunk)
|
||||
# 返回的数据流第一次为空,继续等待
|
||||
if response_text == "" and (reasoning == False or reasoning_content == "") and finish_reason != "False":
|
||||
continue
|
||||
@@ -226,12 +228,12 @@ def get_predict_function(
|
||||
if chunk:
|
||||
try:
|
||||
if finish_reason == "stop":
|
||||
if not console_slience:
|
||||
if not console_silence:
|
||||
print(f"[response] {result}")
|
||||
break
|
||||
result += response_text
|
||||
if reasoning:
|
||||
resoning_buffer += reasoning_content
|
||||
reasoning_buffer += reasoning_content
|
||||
if observe_window is not None:
|
||||
# 观测窗,把已经获取的数据显示出去
|
||||
if len(observe_window) >= 1:
|
||||
@@ -247,9 +249,8 @@ def get_predict_function(
|
||||
logger.error(error_msg)
|
||||
raise RuntimeError("Json解析不合常规")
|
||||
if reasoning:
|
||||
# reasoning 的部分加上框 (>)
|
||||
return '\n'.join(map(lambda x: '> ' + x, resoning_buffer.split('\n'))) + \
|
||||
'\n\n' + result
|
||||
paragraphs = ''.join([f'<p style="margin: 1.25em 0;">{line}</p>' for line in reasoning_buffer.split('\n')])
|
||||
return f'''<div class="reasoning_process" >{paragraphs}</div>\n\n''' + result
|
||||
return result
|
||||
|
||||
def predict(
|
||||
@@ -268,7 +269,7 @@ def get_predict_function(
|
||||
inputs 是本次问询的输入
|
||||
top_p, temperature是chatGPT的内部调优参数
|
||||
history 是之前的对话列表(注意无论是inputs还是history,内容太长了都会触发token数量溢出的错误)
|
||||
chatbot 为WebUI中显示的对话列表,修改它,然后yeild出去,可以直接修改对话界面内容
|
||||
chatbot 为WebUI中显示的对话列表,修改它,然后yield出去,可以直接修改对话界面内容
|
||||
additional_fn代表点击的哪个按钮,按钮见functional.py
|
||||
"""
|
||||
from .bridge_all import model_info
|
||||
@@ -299,7 +300,7 @@ def get_predict_function(
|
||||
) # 刷新界面
|
||||
time.sleep(2)
|
||||
|
||||
headers, playload = generate_message(
|
||||
headers, payload = generate_message(
|
||||
input=inputs,
|
||||
model=llm_kwargs["llm_model"],
|
||||
key=APIKEY,
|
||||
@@ -321,7 +322,7 @@ def get_predict_function(
|
||||
endpoint,
|
||||
headers=headers,
|
||||
proxies=None if disable_proxy else proxies,
|
||||
json=playload,
|
||||
json=payload,
|
||||
stream=True,
|
||||
timeout=TIMEOUT_SECONDS,
|
||||
)
|
||||
@@ -343,14 +344,21 @@ def get_predict_function(
|
||||
gpt_reasoning_buffer = ""
|
||||
|
||||
stream_response = response.iter_lines()
|
||||
wait_counter = 0
|
||||
while True:
|
||||
try:
|
||||
chunk = next(stream_response)
|
||||
except StopIteration:
|
||||
if wait_counter != 0 and gpt_replying_buffer == "":
|
||||
yield from update_ui_lastest_msg(lastmsg="模型调用失败 ...", chatbot=chatbot, history=history, msg="failed")
|
||||
break
|
||||
except requests.exceptions.ConnectionError:
|
||||
chunk = next(stream_response) # 失败了,重试一次?再失败就没办法了。
|
||||
response_text, reasoning_content, finish_reason = decode_chunk(chunk)
|
||||
response_text, reasoning_content, finish_reason, decoded_chunk = decode_chunk(chunk)
|
||||
if decoded_chunk == ': keep-alive':
|
||||
wait_counter += 1
|
||||
yield from update_ui_lastest_msg(lastmsg="等待中 " + "".join(["."] * (wait_counter%10)), chatbot=chatbot, history=history, msg="waiting ...")
|
||||
continue
|
||||
# 返回的数据流第一次为空,继续等待
|
||||
if response_text == "" and (reasoning == False or reasoning_content == "") and finish_reason != "False":
|
||||
status_text = f"finish_reason: {finish_reason}"
|
||||
@@ -367,7 +375,7 @@ def get_predict_function(
|
||||
chunk_decoded = chunk.decode()
|
||||
chatbot[-1] = (
|
||||
chatbot[-1][0],
|
||||
"[Local Message] {finish_reason},获得以下报错信息:\n"
|
||||
f"[Local Message] {finish_reason}, 获得以下报错信息:\n"
|
||||
+ chunk_decoded,
|
||||
)
|
||||
yield from update_ui(
|
||||
@@ -385,7 +393,8 @@ def get_predict_function(
|
||||
if reasoning:
|
||||
gpt_replying_buffer += response_text
|
||||
gpt_reasoning_buffer += reasoning_content
|
||||
history[-1] = '\n'.join(map(lambda x: '> ' + x, gpt_reasoning_buffer.split('\n'))) + '\n\n' + gpt_replying_buffer
|
||||
paragraphs = ''.join([f'<p style="margin: 1.25em 0;">{line}</p>' for line in gpt_reasoning_buffer.split('\n')])
|
||||
history[-1] = f'<div class="reasoning_process">{paragraphs}</div>\n\n---\n\n' + gpt_replying_buffer
|
||||
else:
|
||||
gpt_replying_buffer += response_text
|
||||
# 如果这里抛出异常,一般是文本过长,详情见get_full_error的输出
|
||||
|
||||
@@ -51,7 +51,7 @@ def validate_path_safety(path_or_url, user):
|
||||
from toolbox import get_conf, default_user_name
|
||||
from toolbox import FriendlyException
|
||||
PATH_PRIVATE_UPLOAD, PATH_LOGGING = get_conf('PATH_PRIVATE_UPLOAD', 'PATH_LOGGING')
|
||||
sensitive_path = None # 必须不能包含 '/',即不能是多级路径
|
||||
sensitive_path = None
|
||||
path_or_url = os.path.relpath(path_or_url)
|
||||
if path_or_url.startswith(PATH_LOGGING): # 日志文件(按用户划分)
|
||||
sensitive_path = PATH_LOGGING
|
||||
|
||||
@@ -111,6 +111,8 @@ def extract_archive(file_path, dest_dir):
|
||||
member_path = os.path.normpath(member.name)
|
||||
full_path = os.path.join(dest_dir, member_path)
|
||||
full_path = os.path.abspath(full_path)
|
||||
if member.islnk() or member.issym():
|
||||
raise Exception(f"Attempted Symlink in {member.name}")
|
||||
if not full_path.startswith(os.path.abspath(dest_dir) + os.sep):
|
||||
raise Exception(f"Attempted Path Traversal in {member.name}")
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from functools import wraps, lru_cache
|
||||
from shared_utils.advanced_markdown_format import format_io
|
||||
from shared_utils.config_loader import get_conf as get_conf
|
||||
|
||||
|
||||
pj = os.path.join
|
||||
default_user_name = 'default_user'
|
||||
|
||||
@@ -11,13 +12,11 @@ default_user_name = 'default_user'
|
||||
openai_regex = re.compile(
|
||||
r"sk-[a-zA-Z0-9_-]{48}$|" +
|
||||
r"sk-[a-zA-Z0-9_-]{92}$|" +
|
||||
r"sk-proj-[a-zA-Z0-9_-]{48}$|" +
|
||||
r"sk-proj-[a-zA-Z0-9_-]{124}$|" +
|
||||
r"sk-proj-[a-zA-Z0-9_-]{156}$|" + #新版apikey位数不匹配故修改此正则表达式
|
||||
r"sk-proj-[a-zA-Z0-9_-]{48}$|"+
|
||||
r"sk-proj-[a-zA-Z0-9_-]{124}$|"+
|
||||
r"sk-proj-[a-zA-Z0-9_-]{156}$|"+ #新版apikey位数不匹配故修改此正则表达式
|
||||
r"sess-[a-zA-Z0-9]{40}$"
|
||||
)
|
||||
|
||||
|
||||
def is_openai_api_key(key):
|
||||
CUSTOM_API_KEY_PATTERN = get_conf('CUSTOM_API_KEY_PATTERN')
|
||||
if len(CUSTOM_API_KEY_PATTERN) != 0:
|
||||
@@ -28,7 +27,7 @@ def is_openai_api_key(key):
|
||||
|
||||
|
||||
def is_azure_api_key(key):
|
||||
API_MATCH_AZURE = re.match(r"^[a-zA-Z0-9]{32}$|^[a-zA-Z0-9]{84}", key)
|
||||
API_MATCH_AZURE = re.match(r"[a-zA-Z0-9]{32}$", key)
|
||||
return bool(API_MATCH_AZURE)
|
||||
|
||||
|
||||
@@ -36,12 +35,10 @@ def is_api2d_key(key):
|
||||
API_MATCH_API2D = re.match(r"fk[a-zA-Z0-9]{6}-[a-zA-Z0-9]{32}$", key)
|
||||
return bool(API_MATCH_API2D)
|
||||
|
||||
|
||||
def is_openroute_api_key(key):
|
||||
API_MATCH_OPENROUTE = re.match(r"sk-or-v1-[a-zA-Z0-9]{64}$", key)
|
||||
return bool(API_MATCH_OPENROUTE)
|
||||
|
||||
|
||||
def is_cohere_api_key(key):
|
||||
API_MATCH_AZURE = re.match(r"[a-zA-Z0-9]{40}$", key)
|
||||
return bool(API_MATCH_AZURE)
|
||||
@@ -104,7 +101,7 @@ def select_api_key(keys, llm_model):
|
||||
if llm_model.startswith('cohere-'):
|
||||
for k in key_list:
|
||||
if is_cohere_api_key(k): avail_key_list.append(k)
|
||||
|
||||
|
||||
if llm_model.startswith('openrouter-'):
|
||||
for k in key_list:
|
||||
if is_openroute_api_key(k): avail_key_list.append(k)
|
||||
@@ -112,7 +109,7 @@ def select_api_key(keys, llm_model):
|
||||
if len(avail_key_list) == 0:
|
||||
raise RuntimeError(f"您提供的api-key不满足要求,不包含任何可用于{llm_model}的api-key。您可能选择了错误的模型或请求源(左上角更换模型菜单中可切换openai,azure,claude,cohere等请求源)。")
|
||||
|
||||
api_key = random.choice(avail_key_list) # 随机负载均衡
|
||||
api_key = random.choice(avail_key_list) # 随机负载均衡
|
||||
return api_key
|
||||
|
||||
|
||||
@@ -128,5 +125,5 @@ def select_api_key_for_embed_models(keys, llm_model):
|
||||
if len(avail_key_list) == 0:
|
||||
raise RuntimeError(f"您提供的api-key不满足要求,不包含任何可用于{llm_model}的api-key。您可能选择了错误的模型或请求源。")
|
||||
|
||||
api_key = random.choice(avail_key_list) # 随机负载均衡
|
||||
api_key = random.choice(avail_key_list) # 随机负载均衡
|
||||
return api_key
|
||||
|
||||
11
start.sh
Normal file
11
start.sh
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
GPT_COMMAND="/home/van/.env/python3.12-venv/bin/python main.py"
|
||||
LOG_FILE="/home/van/project/gpt/gpt.log"
|
||||
GPT_PROCESS=$(ps aux | grep "$/home/van/.env/python3.12-venv/bin/python main.py" | grep -v grep)
|
||||
if [ -n "$GPT_PROCESS" ]; then
|
||||
echo "gpt is running..."
|
||||
else
|
||||
cd /home/van/project/gpt/
|
||||
$GPT_COMMAND > "$LOG_FILE" 2>&1 &
|
||||
echo "gpt start successfully. Log file: $LOG_FILE"
|
||||
fi
|
||||
@@ -311,3 +311,15 @@
|
||||
backdrop-filter: blur(10px);
|
||||
background-color: rgba(var(--block-background-fill), 0.5);
|
||||
}
|
||||
|
||||
|
||||
.reasoning_process {
|
||||
font-size: smaller;
|
||||
font-style: italic;
|
||||
margin: 0px;
|
||||
padding: 1em;
|
||||
line-height: 1.5;
|
||||
text-wrap: wrap;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ def define_gui_toolbar(AVAIL_LLM_MODELS, LLM_MODEL, INIT_SYS_PROMPT, THEME, AVAI
|
||||
fontfamily_dropdown = gr.Dropdown(AVAIL_FONTS, value=get_conf("FONT"), elem_id="elem_fontfamily", label="更换字体类型").style(container=False)
|
||||
fontsize_slider = gr.Slider(minimum=5, maximum=25, value=15, step=1, interactive=True, label="字体大小(默认15)", elem_id="elem_fontsize")
|
||||
checkboxes = gr.CheckboxGroup(["基础功能区", "函数插件区", "浮动输入区", "输入清除键", "插件参数区"], value=["基础功能区", "函数插件区"], label="显示/隐藏功能区", elem_id='cbs').style(container=False)
|
||||
opt = ["自定义菜单"]
|
||||
value=[]
|
||||
opt = ["自定义菜单", "主标题", "副标题", "显示logo"]
|
||||
value=["主标题", "副标题", "显示logo"]
|
||||
if ADD_WAIFU: opt += ["添加Live2D形象"]; value += ["添加Live2D形象"]
|
||||
checkboxes_2 = gr.CheckboxGroup(opt, value=value, label="显示/隐藏自定义菜单", elem_id='cbsc').style(container=False)
|
||||
dark_mode_btn = gr.Button("切换界面明暗 ☀", variant="secondary").style(size="sm")
|
||||
|
||||
145
themes/init.js
145
themes/init.js
@@ -128,6 +128,14 @@ function gpt_academic_change_chatbot_font(fontfamily, fontsize, fontcolor) {
|
||||
}
|
||||
}
|
||||
|
||||
function footer_show_hide(show) {
|
||||
if (show) {
|
||||
document.querySelector('footer').style.display = '';
|
||||
} else {
|
||||
document.querySelector('footer').style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
async function GptAcademicJavaScriptInit(dark, prompt, live2d, layout, tts) {
|
||||
// 第一部分,布局初始化
|
||||
remove_legacy_cookie();
|
||||
@@ -179,6 +187,7 @@ async function GptAcademicJavaScriptInit(dark, prompt, live2d, layout, tts) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 字体
|
||||
gpt_academic_gradio_saveload("load", "elem_fontfamily", "js_fontfamily", null, "str");
|
||||
gpt_academic_change_chatbot_font(getCookie("js_fontfamily"), null, null);
|
||||
@@ -205,7 +214,93 @@ async function GptAcademicJavaScriptInit(dark, prompt, live2d, layout, tts) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (getCookie("js_show_title")) {
|
||||
// have cookie
|
||||
bool_value = getCookie("js_show_title")
|
||||
bool_value = bool_value == "True";
|
||||
searchString = "主标题";
|
||||
tool_bar_group = "cbsc";
|
||||
const true_function = function () {
|
||||
document.querySelector('.prose.svelte-1ybaih5 h1').style.display = '';
|
||||
}
|
||||
const false_function = function () {
|
||||
document.querySelector('.prose.svelte-1ybaih5 h1').style.display = 'none';
|
||||
}
|
||||
if (bool_value) {
|
||||
// make btns appear
|
||||
true_function();
|
||||
// deal with checkboxes
|
||||
let arr_with_clear_btn = update_array(
|
||||
await get_data_from_gradio_component(tool_bar_group), searchString, "add"
|
||||
)
|
||||
push_data_to_gradio_component(arr_with_clear_btn, tool_bar_group, "no_conversion");
|
||||
} else {
|
||||
false_function();
|
||||
// deal with checkboxes
|
||||
let arr_without_clear_btn = update_array(
|
||||
await get_data_from_gradio_component(tool_bar_group), searchString, "remove"
|
||||
)
|
||||
push_data_to_gradio_component(arr_without_clear_btn, tool_bar_group, "no_conversion");
|
||||
}
|
||||
}
|
||||
if (getCookie("js_show_subtitle")) {
|
||||
// have cookie
|
||||
bool_value = getCookie("js_show_subtitle")
|
||||
bool_value = bool_value == "True";
|
||||
searchString = "副标题";
|
||||
tool_bar_group = "cbsc";
|
||||
const true_function = function () {
|
||||
element = document.querySelector('.prose.svelte-1ybaih5 h2');
|
||||
if (element) element.style.display = '';
|
||||
element = document.querySelector('.prose.svelte-1ybaih5 h6');
|
||||
if (element) element.style.display = '';
|
||||
}
|
||||
const false_function = function () {
|
||||
element = document.querySelector('.prose.svelte-1ybaih5 h2');
|
||||
if (element) element.style.display = 'none';
|
||||
element = document.querySelector('.prose.svelte-1ybaih5 h6');
|
||||
if (element) element.style.display = 'none';
|
||||
}
|
||||
if (bool_value) {
|
||||
// make btns appear
|
||||
true_function();
|
||||
// deal with checkboxes
|
||||
let arr_with_clear_btn = update_array(
|
||||
await get_data_from_gradio_component(tool_bar_group), searchString, "add"
|
||||
)
|
||||
push_data_to_gradio_component(arr_with_clear_btn, tool_bar_group, "no_conversion");
|
||||
} else {
|
||||
false_function();
|
||||
// deal with checkboxes
|
||||
let arr_without_clear_btn = update_array(
|
||||
await get_data_from_gradio_component(tool_bar_group), searchString, "remove"
|
||||
)
|
||||
push_data_to_gradio_component(arr_without_clear_btn, tool_bar_group, "no_conversion");
|
||||
}
|
||||
}
|
||||
if (getCookie("js_show_footer")) {
|
||||
// have cookie
|
||||
bool_value = getCookie("js_show_footer")
|
||||
searchString = "显示logo";
|
||||
tool_bar_group = "cbsc";
|
||||
bool_value = bool_value == "True";
|
||||
if (bool_value) {
|
||||
// make btns appear
|
||||
footer_show_hide(true);
|
||||
// deal with checkboxes
|
||||
let arr_with_clear_btn = update_array(
|
||||
await get_data_from_gradio_component(tool_bar_group), searchString, "add"
|
||||
)
|
||||
push_data_to_gradio_component(arr_with_clear_btn, tool_bar_group, "no_conversion");
|
||||
} else {
|
||||
footer_show_hide(false);
|
||||
// deal with checkboxes
|
||||
let arr_without_clear_btn = update_array(
|
||||
await get_data_from_gradio_component(tool_bar_group), searchString, "remove"
|
||||
)
|
||||
push_data_to_gradio_component(arr_without_clear_btn, tool_bar_group, "no_conversion");
|
||||
}
|
||||
}
|
||||
// clearButton 自动清除按钮
|
||||
if (getCookie("js_clearbtn_show_cookie")) {
|
||||
// have cookie
|
||||
@@ -219,7 +314,7 @@ async function GptAcademicJavaScriptInit(dark, prompt, live2d, layout, tts) {
|
||||
let clearButton2 = document.getElementById("elem_clear2"); clearButton2.style.display = "block";
|
||||
// deal with checkboxes
|
||||
let arr_with_clear_btn = update_array(
|
||||
await get_data_from_gradio_component('cbs'), "输入清除键", "add"
|
||||
await get_data_from_gradio_component("cbs"), "输入清除键", "add"
|
||||
)
|
||||
push_data_to_gradio_component(arr_with_clear_btn, "cbs", "no_conversion");
|
||||
} else {
|
||||
@@ -228,7 +323,7 @@ async function GptAcademicJavaScriptInit(dark, prompt, live2d, layout, tts) {
|
||||
let clearButton2 = document.getElementById("elem_clear2"); clearButton2.style.display = "none";
|
||||
// deal with checkboxes
|
||||
let arr_without_clear_btn = update_array(
|
||||
await get_data_from_gradio_component('cbs'), "输入清除键", "remove"
|
||||
await get_data_from_gradio_component("cbs"), "输入清除键", "remove"
|
||||
)
|
||||
push_data_to_gradio_component(arr_without_clear_btn, "cbs", "no_conversion");
|
||||
}
|
||||
@@ -268,3 +363,47 @@ async function GptAcademicJavaScriptInit(dark, prompt, live2d, layout, tts) {
|
||||
change_theme("", "")
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function apply_checkbox_change_for_group2(display_panel_arr) {
|
||||
setTimeout(() => {
|
||||
display_panel_arr = get_checkbox_selected_items("cbsc");
|
||||
|
||||
let searchString = "添加Live2D形象";
|
||||
if (display_panel_arr.includes(searchString)) {
|
||||
setCookie("js_live2d_show_cookie", "True", 365);
|
||||
loadLive2D();
|
||||
} else {
|
||||
try {
|
||||
setCookie("js_live2d_show_cookie", "False", 365);
|
||||
$('.waifu').hide();
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function handleDisplay(searchString, key, displayElement, showFn, hideFn) {
|
||||
if (display_panel_arr.includes(searchString)) {
|
||||
setCookie(key, "True", 365);
|
||||
if (showFn) showFn();
|
||||
if (displayElement) displayElement.style.display = '';
|
||||
} else {
|
||||
setCookie(key, "False", 365);
|
||||
if (hideFn) hideFn();
|
||||
if (displayElement) displayElement.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// 主标题
|
||||
const mainTitle = document.querySelector('.prose.svelte-1ybaih5 h1');
|
||||
handleDisplay("主标题", "js_show_title", mainTitle, null, null);
|
||||
|
||||
// 副标题
|
||||
const subTitle = document.querySelector('.prose.svelte-1ybaih5 h2');
|
||||
handleDisplay("副标题", "js_show_subtitle", subTitle, null, null);
|
||||
|
||||
// 显示logo
|
||||
handleDisplay("显示logo", "js_show_footer", null, () => footer_show_hide(true), () => footer_show_hide(false));
|
||||
}, 50);
|
||||
}
|
||||
@@ -141,23 +141,3 @@ setTimeout(() => {
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
|
||||
js_code_show_or_hide_group2 = """
|
||||
(display_panel_arr)=>{
|
||||
setTimeout(() => {
|
||||
display_panel_arr = get_checkbox_selected_items("cbsc");
|
||||
|
||||
let searchString = "添加Live2D形象";
|
||||
let ele = "none";
|
||||
if (display_panel_arr.includes(searchString)) {
|
||||
setCookie("js_live2d_show_cookie", "True", 365);
|
||||
loadLive2D();
|
||||
} else {
|
||||
setCookie("js_live2d_show_cookie", "False", 365);
|
||||
$('.waifu').hide();
|
||||
}
|
||||
|
||||
}, 50);
|
||||
}
|
||||
"""
|
||||
|
||||
17
toolbox.py
17
toolbox.py
@@ -499,22 +499,6 @@ def to_markdown_tabs(head: list, tabs: list, alignment=":---:", column=False, om
|
||||
|
||||
return tabs_list
|
||||
|
||||
def validate_file_size(files, max_size_mb=500):
|
||||
"""
|
||||
验证文件大小是否在允许范围内。
|
||||
:param files: 文件的完整路径的列表
|
||||
:param max_size_mb: 最大文件大小,单位为MB(默认500MB)
|
||||
:return: True 如果文件大小有效,否则抛出异常
|
||||
"""
|
||||
# 获取文件大小(字节)
|
||||
total_size = 0
|
||||
max_size_bytes = max_size_mb * 1024 * 1024
|
||||
for file in files:
|
||||
total_size += os.path.getsize(file.name)
|
||||
if total_size > max_size_bytes:
|
||||
raise ValueError(f"File size exceeds the allowed limit of {max_size_mb} MB. "
|
||||
f"Current size: {total_size / (1024 * 1024):.2f} MB")
|
||||
return True
|
||||
|
||||
def on_file_uploaded(
|
||||
request: gradio.Request, files:List[str], chatbot:ChatBotWithCookies,
|
||||
@@ -526,7 +510,6 @@ def on_file_uploaded(
|
||||
if len(files) == 0:
|
||||
return chatbot, txt
|
||||
|
||||
validate_file_size(files, max_size_mb=500)
|
||||
# 创建工作路径
|
||||
user_name = default_user_name if not request.username else request.username
|
||||
time_tag = gen_time_str()
|
||||
|
||||
Reference in New Issue
Block a user