diff --git a/Dockerfile b/Dockerfile index 97ad13d964d051e4bfdd255a668c209120b1ada4..ac47b8e36ea1577c16e2940aaa133dc1774d9348 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,28 +1,34 @@ -# 此Dockerfile适用于“无本地模型”的环境构建,如果需要使用chatglm等本地模型,请参考 docs/Dockerfile+ChatGLM -# 如何构建: 先修改 `config.py`, 然后 docker build -t gpt-academic . -# 如何运行: docker run --rm -it --net=host gpt-academic +# 此Dockerfile适用于“无本地模型”的环境构建,如果需要使用chatglm等本地模型或者latex运行依赖,请参考 docker-compose.yml +# 如何构建: 先修改 `config.py`, 然后 `docker build -t gpt-academic . ` +# 如何运行(Linux下): `docker run --rm -it --net=host gpt-academic ` +# 如何运行(其他操作系统,选择任意一个固定端口50923): `docker run --rm -it -e WEB_PORT=50923 -p 50923:50923 gpt-academic ` FROM python:3.11 + +# 非必要步骤,更换pip源 RUN echo '[global]' > /etc/pip.conf && \ echo 'index-url = https://mirrors.aliyun.com/pypi/simple/' >> /etc/pip.conf && \ echo 'trusted-host = mirrors.aliyun.com' >> /etc/pip.conf +# 进入工作路径 WORKDIR /gpt - - -# 安装依赖 +# 安装大部分依赖,利用Docker缓存加速以后的构建 COPY requirements.txt ./ COPY ./docs/gradio-3.32.2-py3-none-any.whl ./docs/gradio-3.32.2-py3-none-any.whl RUN pip3 install -r requirements.txt -# 装载项目文件 + + +# 装载项目文件,安装剩余依赖 COPY . . RUN pip3 install -r requirements.txt -# 可选步骤,用于预热模块 + +# 非必要步骤,用于预热模块 RUN python3 -c 'from check_proxy import warm_up_modules; warm_up_modules()' + # 启动 CMD ["python3", "-u", "main.py"] diff --git a/README.md b/README.md index 993977384923ae9de07d563932dd8f24cd2722db..62e48896fb45e8381f1b74bf1e5ba043edf61373 100644 --- a/README.md +++ b/README.md @@ -12,33 +12,34 @@ pinned: false # ChatGPT 学术优化 > **Note** > -> 2023.5.27 对Gradio依赖进行了调整,Fork并解决了官方Gradio的若干Bugs。请及时**更新代码**并重新更新pip依赖。安装依赖时,请严格选择`requirements.txt`中**指定的版本**: -> -> `pip install -r requirements.txt` +> 2023.7.8: Gradio, Pydantic依赖调整,已修改 `requirements.txt`。请及时**更新代码**,安装依赖时,请严格选择`requirements.txt`中**指定的版本** > +> `pip install -r requirements.txt` -# GPT 学术优化 (GPT Academic) -**如果喜欢这个项目,请给它一个Star;如果你发明了更好用的快捷键或函数插件,欢迎发pull requests** +#
GPT 学术优化 (GPT Academic)
+ +**如果喜欢这个项目,请给它一个Star;如果您发明了好用的快捷键或函数插件,欢迎发pull requests!** If you like this project, please give it a Star. If you've come up with more useful academic shortcuts or functional plugins, feel free to open an issue or pull request. We also have a README in [English|](docs/README_EN.md)[日本語|](docs/README_JP.md)[한국어|](https://github.com/mldljyh/ko_gpt_academic)[Русский|](docs/README_RS.md)[Français](docs/README_FR.md) translated by this project itself. To translate this project to arbitary language with GPT, read and run [`multi_language.py`](multi_language.py) (experimental). > **Note** > -> 1.请注意只有**红颜色**标识的函数插件(按钮)才支持读取文件,部分插件位于插件区的**下拉菜单**中。另外我们以**最高优先级**欢迎和处理任何新插件的PR! +> 1.请注意只有 **高亮(如红色)** 标识的函数插件(按钮)才支持读取文件,部分插件位于插件区的**下拉菜单**中。另外我们以**最高优先级**欢迎和处理任何新插件的PR。 > > 2.本项目中每个文件的功能都在自译解[`self_analysis.md`](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)详细说明。随着版本的迭代,您也可以随时自行点击相关函数插件,调用GPT重新生成项目的自我解析报告。常见问题汇总在[`wiki`](https://github.com/binary-husky/gpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)当中。[安装方法](#installation)。 > -> 3.本项目兼容并鼓励尝试国产大语言模型chatglm和RWKV, 盘古等等。支持多个api-key共存,可在配置文件中填写如`API_KEY="openai-key1,openai-key2,api2d-key3"`。需要临时更换`API_KEY`时,在输入区输入临时的`API_KEY`然后回车键提交后即可生效。 +> 3.本项目兼容并鼓励尝试国产大语言模型ChatGLM和Moss等等。支持多个api-key共存,可在配置文件中填写如`API_KEY="openai-key1,openai-key2,azure-key3,api2d-key4"`。需要临时更换`API_KEY`时,在输入区输入临时的`API_KEY`然后回车键提交后即可生效。
-功能 | 描述 +功能(⭐= 近期新增功能) | 描述 --- | --- +⭐[接入新模型](https://github.com/binary-husky/gpt_academic/wiki/%E5%A6%82%E4%BD%95%E5%88%87%E6%8D%A2%E6%A8%A1%E5%9E%8B)! | ⭐阿里达摩院[通义千问](https://modelscope.cn/models/qwen/Qwen-7B-Chat/summary),上海AI-Lab[书生](https://github.com/InternLM/InternLM),讯飞[星火](https://xinghuo.xfyun.cn/) 一键润色 | 支持一键润色、一键查找论文语法错误 一键中英互译 | 一键中英互译 一键代码解释 | 显示代码、解释代码、生成代码、给代码加注释 @@ -53,16 +54,19 @@ Markdown[中英互译](https://www.bilibili.com/video/BV1yo4y157jV/) | [函数 chat分析报告生成 | [函数插件] 运行后自动生成总结汇报 [PDF论文全文翻译功能](https://www.bilibili.com/video/BV1KT411x7Wn) | [函数插件] PDF论文提取题目&摘要+翻译全文(多线程) [Arxiv小助手](https://www.bilibili.com/video/BV1LM4y1279X) | [函数插件] 输入arxiv文章url即可一键翻译摘要+下载PDF +Latex论文一键校对 | [函数插件] 仿Grammarly对Latex文章进行语法、拼写纠错+输出对照PDF [谷歌学术统合小助手](https://www.bilibili.com/video/BV19L411U7ia) | [函数插件] 给定任意谷歌学术搜索页面URL,让gpt帮你[写relatedworks](https://www.bilibili.com/video/BV1GP411U7Az/) -互联网信息聚合+GPT | [函数插件] 一键[让GPT先从互联网获取信息](https://www.bilibili.com/video/BV1om4y127ck),再回答问题,让信息永不过时 -⭐Arxiv论文精细翻译 | [函数插件] 一键[以超高质量翻译arxiv论文](https://www.bilibili.com/video/BV1dz4y1v77A/),迄今为止最好的论文翻译工具⭐ +互联网信息聚合+GPT | [函数插件] 一键[让GPT从互联网获取信息](https://www.bilibili.com/video/BV1om4y127ck)回答问题,让信息永不过时 +⭐Arxiv论文精细翻译 ([Docker](https://github.com/binary-husky/gpt_academic/pkgs/container/gpt_academic_with_latex)) | [函数插件] 一键[以超高质量翻译arxiv论文](https://www.bilibili.com/video/BV1dz4y1v77A/),目前最好的论文翻译工具 +⭐[实时语音对话输入](https://github.com/binary-husky/gpt_academic/blob/master/docs/use_audio.md) | [函数插件] 异步[监听音频](https://www.bilibili.com/video/BV1AV4y187Uy/),自动断句,自动寻找回答时机 公式/图片/表格显示 | 可以同时显示公式的[tex形式和渲染形式](https://user-images.githubusercontent.com/96192199/230598842-1d7fcddd-815d-40ee-af60-baf488a199df.png),支持公式、代码高亮 多线程函数插件支持 | 支持多线调用chatgpt,一键处理[海量文本](https://www.bilibili.com/video/BV1FT411H7c5/)或程序 -启动暗色gradio[主题](https://github.com/binary-husky/gpt_academic/issues/173) | 在浏览器url后面添加```/?__theme=dark```可以切换dark主题 -[多LLM模型](https://www.bilibili.com/video/BV1wT411p7yf)支持 | 同时被GPT3.5、GPT4、[清华ChatGLM](https://github.com/THUDM/ChatGLM-6B)、[复旦MOSS](https://github.com/OpenLMLab/MOSS)同时伺候的感觉一定会很不错吧? -更多LLM模型接入,支持[huggingface部署](https://huggingface.co/spaces/qingxu98/gpt-academic) | 加入Newbing接口(新必应),引入清华[Jittorllms](https://github.com/Jittor/JittorLLMs)支持[LLaMA](https://github.com/facebookresearch/llama),[RWKV](https://github.com/BlinkDL/ChatRWKV)和[盘古α](https://openi.org.cn/pangu/) -更多新功能展示(图像生成等) …… | 见本文档结尾处 …… - +启动暗色[主题](https://github.com/binary-husky/gpt_academic/issues/173) | 在浏览器url后面添加```/?__theme=dark```可以切换dark主题 +[多LLM模型](https://www.bilibili.com/video/BV1wT411p7yf)支持 | 同时被GPT3.5、GPT4、[清华ChatGLM2](https://github.com/THUDM/ChatGLM2-6B)、[复旦MOSS](https://github.com/OpenLMLab/MOSS)同时伺候的感觉一定会很不错吧? +⭐ChatGLM2微调模型 | 支持加载ChatGLM2微调模型,提供ChatGLM2微调辅助插件 +更多LLM模型接入,支持[huggingface部署](https://huggingface.co/spaces/qingxu98/gpt-academic) | 加入Newbing接口(新必应),引入清华[Jittorllms](https://github.com/Jittor/JittorLLMs)支持[LLaMA](https://github.com/facebookresearch/llama)和[盘古α](https://openi.org.cn/pangu/) +⭐[虚空终端](https://github.com/binary-husky/void-terminal)pip包 | 脱离GUI,在Python中直接调用本项目的函数插件(开发中) +更多新功能展示 (图像生成等) …… | 见本文档结尾处 ……
@@ -97,13 +101,12 @@ chat分析报告生成 | [函数插件] 运行后自动生成总结汇报 ---- # Installation -## 安装-方法1:直接运行 (Windows, Linux or MacOS) +### 安装方法I:直接运行 (Windows, Linux or MacOS) 1. 下载项目 ```sh -git clone https://github.com/binary-husky/gpt_academic.git +git clone --depth=1 https://github.com/binary-husky/gpt_academic.git cd gpt_academic ``` @@ -126,19 +129,22 @@ python -m pip install -r requirements.txt # 这个步骤和pip安装一样的步 ``` -
如果需要支持清华ChatGLM/复旦MOSS作为后端,请点击展开此处 +
如果需要支持清华ChatGLM2/复旦MOSS/RWKV作为后端,请点击展开此处

-【可选步骤】如果需要支持清华ChatGLM/复旦MOSS作为后端,需要额外安装更多依赖(前提条件:熟悉Python + 用过Pytorch + 电脑配置够强): +【可选步骤】如果需要支持清华ChatGLM2/复旦MOSS作为后端,需要额外安装更多依赖(前提条件:熟悉Python + 用过Pytorch + 电脑配置够强): ```sh -# 【可选步骤I】支持清华ChatGLM。清华ChatGLM备注:如果遇到"Call ChatGLM fail 不能正常加载ChatGLM的参数" 错误,参考如下: 1:以上默认安装的为torch+cpu版,使用cuda需要卸载torch重新安装torch+cuda; 2:如因本机配置不够无法加载模型,可以修改request_llm/bridge_chatglm.py中的模型精度, 将 AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True) 都修改为 AutoTokenizer.from_pretrained("THUDM/chatglm-6b-int4", trust_remote_code=True) +# 【可选步骤I】支持清华ChatGLM2。清华ChatGLM备注:如果遇到"Call ChatGLM fail 不能正常加载ChatGLM的参数" 错误,参考如下: 1:以上默认安装的为torch+cpu版,使用cuda需要卸载torch重新安装torch+cuda; 2:如因本机配置不够无法加载模型,可以修改request_llm/bridge_chatglm.py中的模型精度, 将 AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True) 都修改为 AutoTokenizer.from_pretrained("THUDM/chatglm-6b-int4", trust_remote_code=True) python -m pip install -r request_llm/requirements_chatglm.txt # 【可选步骤II】支持复旦MOSS python -m pip install -r request_llm/requirements_moss.txt -git clone https://github.com/OpenLMLab/MOSS.git request_llm/moss # 注意执行此行代码时,必须处于项目根路径 +git clone --depth=1 https://github.com/OpenLMLab/MOSS.git request_llm/moss # 注意执行此行代码时,必须处于项目根路径 + +# 【可选步骤III】支持RWKV Runner +参考wiki:https://github.com/binary-husky/gpt_academic/wiki/%E9%80%82%E9%85%8DRWKV-Runner -# 【可选步骤III】确保config.py配置文件的AVAIL_LLM_MODELS包含了期望的模型,目前支持的全部模型如下(jittorllms系列目前仅支持docker方案): +# 【可选步骤IV】确保config.py配置文件的AVAIL_LLM_MODELS包含了期望的模型,目前支持的全部模型如下(jittorllms系列目前仅支持docker方案): AVAIL_LLM_MODELS = ["gpt-3.5-turbo", "api2d-gpt-3.5-turbo", "gpt-4", "api2d-gpt-4", "chatglm", "newbing", "moss"] # + ["jittorllms_rwkv", "jittorllms_pangualpha", "jittorllms_llama"] ``` @@ -152,24 +158,28 @@ AVAIL_LLM_MODELS = ["gpt-3.5-turbo", "api2d-gpt-3.5-turbo", "gpt-4", "api2d-gpt- python main.py ``` -## 安装-方法2:使用Docker +### 安装方法II:使用Docker 1. 仅ChatGPT(推荐大多数人选择,等价于docker-compose方案1) +[![basic](https://github.com/binary-husky/gpt_academic/actions/workflows/build-without-local-llms.yml/badge.svg?branch=master)](https://github.com/binary-husky/gpt_academic/actions/workflows/build-without-local-llms.yml) +[![basiclatex](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-latex.yml/badge.svg?branch=master)](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-latex.yml) +[![basicaudio](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-audio-assistant.yml/badge.svg?branch=master)](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-audio-assistant.yml) ``` sh -git clone https://github.com/binary-husky/gpt_academic.git # 下载项目 +git clone --depth=1 https://github.com/binary-husky/gpt_academic.git # 下载项目 cd gpt_academic # 进入路径 nano config.py # 用任意文本编辑器编辑config.py, 配置 “Proxy”, “API_KEY” 以及 “WEB_PORT” (例如50923) 等 docker build -t gpt-academic . # 安装 -#(最后一步-选择1)在Linux环境下,用`--net=host`更方便快捷 +#(最后一步-Linux操作系统)用`--net=host`更方便快捷 docker run --rm -it --net=host gpt-academic -#(最后一步-选择2)在macOS/windows环境下,只能用-p选项将容器上的端口(例如50923)暴露给主机上的端口 +#(最后一步-MacOS/Windows操作系统)只能用-p选项将容器上的端口(例如50923)暴露给主机上的端口 docker run --rm -it -e WEB_PORT=50923 -p 50923:50923 gpt-academic ``` P.S. 如果需要依赖Latex的插件功能,请见Wiki。另外,您也可以直接使用docker-compose获取Latex功能(修改docker-compose.yml,保留方案4并删除其他方案)。 -2. ChatGPT + ChatGLM + MOSS(需要熟悉Docker) +2. ChatGPT + ChatGLM2 + MOSS(需要熟悉Docker) +[![chatglm](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-chatglm.yml/badge.svg?branch=master)](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-chatglm.yml) ``` sh # 修改docker-compose.yml,保留方案2并删除其他方案。修改docker-compose.yml中方案2的配置,参考其中注释即可 @@ -177,13 +187,15 @@ docker-compose up ``` 3. ChatGPT + LLAMA + 盘古 + RWKV(需要熟悉Docker) +[![jittorllms](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-jittorllms.yml/badge.svg?branch=master)](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-jittorllms.yml) + ``` sh # 修改docker-compose.yml,保留方案3并删除其他方案。修改docker-compose.yml中方案3的配置,参考其中注释即可 docker-compose up ``` -## 安装-方法3:其他部署姿势 +### 安装方法III:其他部署姿势 1. 一键运行脚本。 完全不熟悉python环境的Windows用户可以下载[Release](https://github.com/binary-husky/gpt_academic/releases)中发布的一键运行脚本安装无本地模型的版本。 脚本的贡献来源是[oobabooga](https://github.com/oobabooga/one-click-installers)。 @@ -200,17 +212,17 @@ docker-compose up 5. 远程云服务器部署(需要云服务器知识与经验)。 请访问[部署wiki-1](https://github.com/binary-husky/gpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) -6. 使用WSL2(Windows Subsystem for Linux 子系统)。 +6. 使用Sealos[一键部署](https://github.com/binary-husky/gpt_academic/issues/993)。 + +7. 使用WSL2(Windows Subsystem for Linux 子系统)。 请访问[部署wiki-2](https://github.com/binary-husky/gpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) -7. 如何在二级网址(如`http://localhost/subpath`)下运行。 +8. 如何在二级网址(如`http://localhost/subpath`)下运行。 请访问[FastAPI运行说明](docs/WithFastapi.md) ---- -# Advanced Usage -## 自定义新的便捷按钮 / 自定义函数插件 -1. 自定义新的便捷按钮(学术快捷键) +# Advanced Usage +### I:自定义新的便捷按钮(学术快捷键) 任意文本编辑器打开`core_functional.py`,添加条目如下,然后重启程序即可。(如果按钮已经添加成功并可见,那么前缀、后缀都支持热修改,无需重启程序即可生效。) 例如 ``` @@ -226,15 +238,15 @@ docker-compose up -2. 自定义函数插件 +### II:自定义函数插件 编写强大的函数插件来执行任何你想得到的和想不到的任务。 本项目的插件编写、调试难度很低,只要您具备一定的python基础知识,就可以仿照我们提供的模板实现自己的插件功能。 详情请参考[函数插件指南](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97)。 ---- + # Latest Update -## 新功能动态 +### I:新功能动态 1. 对话保存功能。在函数插件区调用 `保存当前的对话` 即可将当前对话保存为可读+可复原的html文件, 另外在函数插件区(下拉菜单)调用 `载入对话历史存档` ,即可还原之前的会话。 @@ -293,10 +305,17 @@ Tip:不指定文件直接点击 `载入对话历史存档` 可以查看历史h +11. 语言、主题切换 +

+ +
-## 版本: +### II:版本: - version 3.5(Todo): 使用自然语言调用本项目的所有函数插件(高优先级) +- version 3.46: 支持完全脱手操作的实时语音对话 +- version 3.45: 支持自定义ChatGLM2微调模型 +- version 3.44: 正式支持Azure,优化界面易用性 - version 3.4: +arxiv论文翻译、latex论文批改功能 - version 3.3: +互联网信息综合功能 - version 3.2: 函数插件支持更多参数接口 (保存对话功能, 解读任意语言代码+同时询问任意的LLM组合) @@ -317,13 +336,18 @@ gpt_academic开发者QQ群-2:610599535 - 某些浏览器翻译插件干扰此软件前端的运行 - 官方Gradio目前有很多兼容性Bug,请务必使用`requirement.txt`安装Gradio -## 参考与学习 +### III:主题 +可以通过修改`THEME`选项(config.py)变更主题 +1. `Chuanhu-Small-and-Beautiful` [网址](https://github.com/GaiZhenbiao/ChuanhuChatGPT/) + + +### IV:参考与学习 ``` 代码中参考了很多其他优秀项目中的设计,顺序不分先后: -# 清华ChatGLM-6B: -https://github.com/THUDM/ChatGLM-6B +# 清华ChatGLM2-6B: +https://github.com/THUDM/ChatGLM2-6B # 清华JittorLLMs: https://github.com/Jittor/JittorLLMs diff --git a/app.py b/app.py index b4cd22bf5bd6c614411e8ae58bc5f739e6455071..e38af7df22f87e6941839ecced4f1e4782d60802 100644 --- a/app.py +++ b/app.py @@ -4,27 +4,30 @@ def main(): import subprocess, sys subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'gradio-stable-fork']) import gradio as gr - if gr.__version__ not in ['3.28.3','3.32.3']: assert False, "请用 pip install -r requirements.txt 安装依赖" + if gr.__version__ not in ['3.28.3','3.32.3']: assert False, "需要特殊依赖,请务必用 pip install -r requirements.txt 指令安装依赖,详情信息见requirements.txt" from request_llm.bridge_all import predict - from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf, ArgsGeneralWrapper, DummyWith + from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf, ArgsGeneralWrapper, load_chat_cookies, DummyWith # 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到 - proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, API_KEY, AVAIL_LLM_MODELS = \ - get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'API_KEY', 'AVAIL_LLM_MODELS') - + proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, AVAIL_LLM_MODELS, AUTO_CLEAR_TXT = \ + get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'AVAIL_LLM_MODELS', 'AUTO_CLEAR_TXT') + ENABLE_AUDIO, AUTO_CLEAR_TXT = get_conf('ENABLE_AUDIO', 'AUTO_CLEAR_TXT') # 如果WEB_PORT是-1, 则随机选取WEB端口 PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT if not AUTHENTICATION: AUTHENTICATION = None from check_proxy import get_current_version + from themes.theme import adjust_theme, advanced_css, theme_declaration initial_prompt = "Serve me as a writing and programming assistant." - title_html = f"

ChatGPT 学术优化 {get_current_version()}

" + title_html = f"

GPT 学术优化 {get_current_version()}

{theme_declaration}" description = """代码开源和更新[地址🚀](https://github.com/binary-husky/chatgpt_academic),感谢热情的[开发者们❤️](https://github.com/binary-husky/chatgpt_academic/graphs/contributors)""" # 问询记录, python 版本建议3.9+(越新越好) - import logging + import logging, uuid os.makedirs("gpt_log", exist_ok=True) - try:logging.basicConfig(filename="gpt_log/chat_secrets.log", level=logging.INFO, encoding="utf-8") - except:logging.basicConfig(filename="gpt_log/chat_secrets.log", level=logging.INFO) + try:logging.basicConfig(filename="gpt_log/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="gpt_log/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("所有问询记录将自动保存在本地目录./gpt_log/chat_secrets.log, 请注意自我隐私保护哦!") # 一些普通功能模块 @@ -39,7 +42,6 @@ def main(): gr.Chatbot.postprocess = format_io # 做一些外观色彩上的调整 - from theme import adjust_theme, advanced_css set_theme = adjust_theme() # 代理与自动更新 @@ -47,24 +49,24 @@ def main(): proxy_info = check_proxy(proxies) gr_L1 = lambda: gr.Row().style() - gr_L2 = lambda scale: gr.Column(scale=scale) + gr_L2 = lambda scale, elem_id: gr.Column(scale=scale, elem_id=elem_id) if LAYOUT == "TOP-DOWN": gr_L1 = lambda: DummyWith() - gr_L2 = lambda scale: gr.Row() + gr_L2 = lambda scale, elem_id: gr.Row() CHATBOT_HEIGHT /= 2 cancel_handles = [] - with gr.Blocks(title="ChatGPT 学术优化", 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 demo: gr.HTML(title_html) gr.HTML('''
Duplicate Space请您打开此页面后务必点击上方的“复制空间”(Duplicate Space)按钮!使用时,先在输入框填入API-KEY然后回车。
切忌在“复制空间”(Duplicate Space)之前填入API_KEY或进行提问,否则您的API_KEY将极可能被空间所有者攫取!
支持任意数量的OpenAI的密钥和API2D的密钥共存,例如输入"OpenAI密钥1,API2D密钥2",然后提交,即可同时使用两种模型接口。
''') - cookies = gr.State({'api_key': API_KEY, 'llm_model': LLM_MODEL}) + cookies = gr.State(load_chat_cookies()) with gr_L1(): - with gr_L2(scale=2): - chatbot = gr.Chatbot(label=f"当前模型:{LLM_MODEL}") - chatbot.style(height=CHATBOT_HEIGHT) + with gr_L2(scale=2, elem_id="gpt-chat"): + chatbot = gr.Chatbot(label=f"当前模型:{LLM_MODEL}", elem_id="gpt-chatbot") + if LAYOUT == "TOP-DOWN": chatbot.style(height=CHATBOT_HEIGHT) history = gr.State([]) - with gr_L2(scale=1): - with gr.Accordion("输入区", open=True) as area_input_primary: + with gr_L2(scale=1, elem_id="gpt-panel"): + with gr.Accordion("输入区", open=True, elem_id="input-panel") as area_input_primary: with gr.Row(): txt = gr.Textbox(show_label=False, lines=2, placeholder="输入问题或API密钥,输入多个密钥时,用英文逗号间隔。支持OpenAI密钥和API2D密钥共存。").style(container=False) with gr.Row(): @@ -73,17 +75,20 @@ def main(): resetBtn = gr.Button("重置", variant="secondary"); resetBtn.style(size="sm") stopBtn = gr.Button("停止", variant="secondary"); stopBtn.style(size="sm") clearBtn = gr.Button("清除", variant="secondary", visible=False); clearBtn.style(size="sm") + if ENABLE_AUDIO: + with gr.Row(): + audio_mic = gr.Audio(source="microphone", type="numpy", streaming=True, show_label=False).style(container=False) with gr.Row(): - status = gr.Markdown(f"Tip: 按Enter提交, 按Shift+Enter换行。当前模型: {LLM_MODEL} \n {proxy_info}") - with gr.Accordion("基础功能区", open=True) as area_basic_fn: + status = gr.Markdown(f"Tip: 按Enter提交, 按Shift+Enter换行。当前模型: {LLM_MODEL} \n {proxy_info}", elem_id="state-panel") + with gr.Accordion("基础功能区", open=True, elem_id="basic-panel") as area_basic_fn: with gr.Row(): for k in functional: if ("Visible" in functional[k]) and (not functional[k]["Visible"]): continue variant = functional[k]["Color"] if "Color" in functional[k] else "secondary" functional[k]["Button"] = gr.Button(k, variant=variant) - with gr.Accordion("函数插件区", open=True) as area_crazy_fn: + with gr.Accordion("函数插件区", open=True, elem_id="plugin-panel") as area_crazy_fn: with gr.Row(): - gr.Markdown("注意:以下“红颜色”标识的函数插件需从输入区读取路径作为参数.") + gr.Markdown("插件可读取“输入区”文本/路径作为参数(上传文件自动修正路径)") with gr.Row(): for k in crazy_fns: if not crazy_fns[k].get("AsButton", True): continue @@ -94,25 +99,25 @@ def main(): with gr.Accordion("更多函数插件", open=True): dropdown_fn_list = [k for k in crazy_fns.keys() if not crazy_fns[k].get("AsButton", True)] with gr.Row(): - dropdown = gr.Dropdown(dropdown_fn_list, value=r"打开插件列表", label="").style(container=False) + dropdown = gr.Dropdown(dropdown_fn_list, value=r"打开插件列表", label="", show_label=False).style(container=False) with gr.Row(): plugin_advanced_arg = gr.Textbox(show_label=True, label="高级参数输入区", visible=False, placeholder="这里是特殊函数插件的高级参数输入区").style(container=False) with gr.Row(): switchy_bt = gr.Button(r"请先从插件列表中选择", variant="secondary") with gr.Row(): - with gr.Accordion("点击展开“文件上传区”。上传本地文件可供红色函数插件调用。", open=False) as area_file_up: + with gr.Accordion("点击展开“文件上传区”。上传本地文件/压缩包供函数插件调用。", open=False) as area_file_up: file_upload = gr.Files(label="任何文件, 但推荐上传压缩文件(zip, tar)", file_count="multiple") - with gr.Accordion("更换模型 & SysPrompt & 交互界面布局", open=(LAYOUT == "TOP-DOWN")): + with gr.Accordion("更换模型 & SysPrompt & 交互界面布局", open=(LAYOUT == "TOP-DOWN"), elem_id="interact-panel"): system_prompt = gr.Textbox(show_label=True, placeholder=f"System Prompt", label="System prompt", value=initial_prompt) top_p = gr.Slider(minimum=-0, maximum=1.0, value=1.0, step=0.01,interactive=True, label="Top-p (nucleus sampling)",) temperature = gr.Slider(minimum=-0, maximum=2.0, value=1.0, step=0.01, interactive=True, label="Temperature",) - max_length_sl = gr.Slider(minimum=256, maximum=4096, value=512, step=1, interactive=True, label="Local LLM MaxLength",) + max_length_sl = gr.Slider(minimum=256, maximum=8192, value=4096, step=1, interactive=True, label="Local LLM MaxLength",) checkboxes = gr.CheckboxGroup(["基础功能区", "函数插件区", "底部输入区", "输入清除键", "插件参数区"], value=["基础功能区", "函数插件区"], label="显示/隐藏功能区") md_dropdown = gr.Dropdown(AVAIL_LLM_MODELS, value=LLM_MODEL, label="更换LLM模型/请求源").style(container=False) gr.Markdown(description) - with gr.Accordion("备选输入区", open=True, visible=False) as area_input_secondary: + with gr.Accordion("备选输入区", open=True, visible=False, elem_id="input-panel2") as area_input_secondary: with gr.Row(): txt2 = gr.Textbox(show_label=False, placeholder="Input question here.", label="输入区2").style(container=False) with gr.Row(): @@ -147,6 +152,11 @@ def main(): resetBtn2.click(lambda: ([], [], "已重置"), None, [chatbot, history, status]) clearBtn.click(lambda: ("",""), None, [txt, txt2]) clearBtn2.click(lambda: ("",""), None, [txt, txt2]) + if AUTO_CLEAR_TXT: + submitBtn.click(lambda: ("",""), None, [txt, txt2]) + submitBtn2.click(lambda: ("",""), None, [txt, txt2]) + txt.submit(lambda: ("",""), None, [txt, txt2]) + txt2.submit(lambda: ("",""), None, [txt, txt2]) # 基础功能区的回调函数注册 for k in functional: if ("Visible" in functional[k]) and (not functional[k]["Visible"]): continue @@ -174,16 +184,29 @@ def main(): return {chatbot: gr.update(label="当前模型:"+k)} md_dropdown.select(on_md_dropdown_changed, [md_dropdown], [chatbot] ) # 随变按钮的回调函数注册 - def route(k, *args, **kwargs): + def route(request: gr.Request, k, *args, **kwargs): if k in [r"打开插件列表", r"请先从插件列表中选择"]: return - yield from ArgsGeneralWrapper(crazy_fns[k]["Function"])(*args, **kwargs) + yield from ArgsGeneralWrapper(crazy_fns[k]["Function"])(request, *args, **kwargs) click_handle = switchy_bt.click(route,[switchy_bt, *input_combo, gr.State(PORT)], output_combo) click_handle.then(on_report_generated, [cookies, file_upload, chatbot], [cookies, file_upload, chatbot]) cancel_handles.append(click_handle) # 终止按钮的回调函数注册 stopBtn.click(fn=None, inputs=None, outputs=None, cancels=cancel_handles) stopBtn2.click(fn=None, inputs=None, outputs=None, cancels=cancel_handles) - + if ENABLE_AUDIO: + from crazy_functions.live_audio.audio_io import RealtimeAudioDistribution + rad = RealtimeAudioDistribution() + def deal_audio(audio, cookies): + rad.feed(cookies['uuid'].hex, audio) + audio_mic.stream(deal_audio, inputs=[audio_mic, cookies]) + + def init_cookie(cookies, chatbot): + # 为每一位访问的用户赋予一个独一无二的uuid编码 + cookies.update({'uuid': uuid.uuid4()}) + return cookies + demo.load(init_cookie, inputs=[cookies, chatbot], outputs=[cookies]) + demo.load(lambda: 0, inputs=None, outputs=None, _js='()=>{ChatBotHeight();}') + # gradio的inbrowser触发不太稳定,回滚代码到原始的浏览器打开函数 def auto_opentab_delay(): import threading, webbrowser, time diff --git a/check_proxy.py b/check_proxy.py index 977802db49babe079a191dbda6815c216e156548..474988c129d51e3f1a4fa59634f073cbda553c09 100644 --- a/check_proxy.py +++ b/check_proxy.py @@ -3,15 +3,20 @@ def check_proxy(proxies): import requests proxies_https = proxies['https'] if proxies is not None else '无' try: - response = requests.get("https://ipapi.co/json/", - proxies=proxies, timeout=4) + response = requests.get("https://ipapi.co/json/", proxies=proxies, timeout=4) data = response.json() print(f'查询代理的地理位置,返回的结果是{data}') if 'country_name' in data: country = data['country_name'] result = f"代理配置 {proxies_https}, 代理所在地:{country}" elif 'error' in data: - result = f"代理配置 {proxies_https}, 代理所在地:未知,IP查询频率受限" + alternative = _check_with_backup_source(proxies) + if alternative is None: + result = f"代理配置 {proxies_https}, 代理所在地:未知,IP查询频率受限" + else: + result = f"代理配置 {proxies_https}, 代理所在地:{alternative}" + else: + result = f"代理配置 {proxies_https}, 代理数据解析失败:{data}" print(result) return result except: @@ -19,6 +24,11 @@ def check_proxy(proxies): print(result) return result +def _check_with_backup_source(proxies): + import random, string, requests + random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=32)) + try: return requests.get(f"http://{random_string}.edns.ip-api.com/json", proxies=proxies, timeout=4).json()['dns']['geo'] + except: return None def backup_and_download(current_version, remote_version): """ @@ -115,7 +125,7 @@ def auto_update(raise_error=False): with open('./version', 'r', encoding='utf8') as f: current_version = f.read() current_version = json.loads(current_version)['version'] - if (remote_version - current_version) >= 0.01: + if (remote_version - current_version) >= 0.01-1e-5: from colorful import print亮黄 print亮黄( f'\n新版本可用。新版本:{remote_version},当前版本:{current_version}。{new_feature}') @@ -137,7 +147,7 @@ def auto_update(raise_error=False): else: return except: - msg = '自动更新程序:已禁用' + msg = '自动更新程序:已禁用。建议排查:代理网络配置。' if raise_error: from toolbox import trimmed_format_exc msg += trimmed_format_exc() diff --git a/config.py b/config.py index 350a99b7a405f663d9a633616adb880e9f45fd1e..21e77d50793a6a208ad952118648578d75625dae 100644 --- a/config.py +++ b/config.py @@ -1,17 +1,27 @@ -# [step 1]>> 例如: API_KEY = "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" (此key无效) -API_KEY = "sk-此处填API密钥" # 可同时填写多个API-KEY,用英文逗号分割,例如API_KEY = "sk-openaikey1,sk-openaikey2,fkxxxx-api2dkey1,fkxxxx-api2dkey2" +""" + 以下所有配置也都支持利用环境变量覆写,环境变量配置格式见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]>> API_KEY = "sk-123456789xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx123456789"。极少数情况下,还需要填写组织(格式如org-123456789abcdefghijklmno的),请向下翻,找 API_ORG 设置项 +API_KEY = "此处填API密钥" # 可同时填写多个API-KEY,用英文逗号分割,例如API_KEY = "sk-openaikey1,sk-openaikey2,fkxxxx-api2dkey3,azure-apikey4" # [step 2]>> 改为True应用代理,如果直接在海外服务器部署,此处不修改 USE_PROXY = False if USE_PROXY: - # 填写格式是 [协议]:// [地址] :[端口],填写之前不要忘记把USE_PROXY改成True,如果直接在海外服务器部署,此处不修改 - # 例如 "socks5h://localhost:11284" - # [协议] 常见协议无非socks5h/http; 例如 v2**y 和 ss* 的默认本地协议是socks5h; 而cl**h 的默认本地协议是http - # [地址] 懂的都懂,不懂就填localhost或者127.0.0.1肯定错不了(localhost意思是代理软件安装在本机上) - # [端口] 在代理软件的设置里找。虽然不同的代理软件界面不一样,但端口号都应该在最显眼的位置上 - - # 代理网络的地址,打开你的*学*网软件查看代理的协议(socks5/http)、地址(localhost)和端口(11284) + """ + 填写格式是 [协议]:// [地址] :[端口],填写之前不要忘记把USE_PROXY改成True,如果直接在海外服务器部署,此处不修改 + <配置教程&视频教程> https://github.com/binary-husky/gpt_academic/issues/1> + [协议] 常见协议无非socks5h/http; 例如 v2**y 和 ss* 的默认本地协议是socks5h; 而cl**h 的默认本地协议是http + [地址] 懂的都懂,不懂就填localhost或者127.0.0.1肯定错不了(localhost意思是代理软件安装在本机上) + [端口] 在代理软件的设置里找。虽然不同的代理软件界面不一样,但端口号都应该在最显眼的位置上 + """ + # 代理网络的地址,打开你的*学*网软件查看代理的协议(socks5h / http)、地址(localhost)和端口(11284) proxies = { # [协议]:// [地址] :[端口] "http": "socks5h://localhost:11284", # 再例如 "http": "http://127.0.0.1:7890", @@ -20,28 +30,40 @@ if USE_PROXY: else: proxies = None -# [step 3]>> 多线程函数插件中,默认允许多少路线程同时访问OpenAI。Free trial users的限制是每分钟3次,Pay-as-you-go users的限制是每分钟3500次 -# 一言以蔽之:免费用户填3,OpenAI绑了信用卡的用户可以填 16 或者更高。提高限制请查询:https://platform.openai.com/docs/guides/rate-limits/overview +# ------------------------------------ 以下配置可以优化体验, 但大部分场合下并不需要修改 ------------------------------------ + +# 重新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"} +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 -# [step 4]>> 以下配置可以优化体验,但大部分场合下并不需要修改 # 对话窗的高度 CHATBOT_HEIGHT = 1115 + # 代码高亮 CODE_HIGHLIGHT = True + # 窗口布局 -LAYOUT = "LEFT-RIGHT" # "LEFT-RIGHT"(左右布局) # "TOP-DOWN"(上下布局) -DARK_MODE = True # "LEFT-RIGHT"(左右布局) # "TOP-DOWN"(上下布局) +LAYOUT = "LEFT-RIGHT" # "LEFT-RIGHT"(左右布局) # "TOP-DOWN"(上下布局) +DARK_MODE = True # 暗色模式 / 亮色模式 + # 发送请求到OpenAI后,等待多久判定为超时 TIMEOUT_SECONDS = 30 + # 网页的端口, -1代表随机端口 WEB_PORT = -1 + # 如果OpenAI不响应(网络卡顿、代理失败、KEY失效),重试的次数限制 MAX_RETRY = 2 @@ -49,34 +71,43 @@ MAX_RETRY = 2 LLM_MODEL = "gpt-3.5-turbo" # 可选 "chatglm" AVAIL_LLM_MODELS = ["newbing-free", "gpt-3.5-turbo", "gpt-4", "api2d-gpt-4", "api2d-gpt-3.5-turbo"] +# ChatGLM(2) Finetune Model Path (如果使用ChatGLM2微调模型,需要把"chatglmft"加入AVAIL_LLM_MODELS中) +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 + + +# 色彩主体,可选 ["Default", "Chuanhu-Small-and-Beautiful"] +THEME = "Default" + + # 加一个live2d装饰 ADD_WAIFU = False + # 设置用户名和密码(不需要修改)(相关功能不稳定,与gradio版本和网络都相关,如果本地使用不建议加这个) # [("username", "password"), ("username2", "password2"), ...] AUTHENTICATION = [] -# 重新URL重新定向,实现更换API_URL的作用(常规情况下,不要修改!!) -# (高危设置!通过修改此设置,您将把您的API-KEY和对话隐私完全暴露给您设定的中间人!) -# 格式 {"https://api.openai.com/v1/chat/completions": "在这里填写重定向的api.openai.com的URL"} -# 例如 API_URL_REDIRECT = {"https://api.openai.com/v1/chat/completions": "https://ai.open.com/api/conversation"} -API_URL_REDIRECT = {} # 如果需要在二级路径下运行(常规情况下,不要修改!!)(需要配合修改main.py才能生效!) CUSTOM_PATH = "/" -# 如果需要使用newbing,把newbing的长长的cookie放到这里 -NEWBING_STYLE = "creative" # ["creative", "balanced", "precise"] -# 从现在起,如果您调用"newbing-free"模型,则无需填写NEWBING_COOKIES -NEWBING_COOKIES = """ -your bing cookies here -""" + +# 极少数情况下,openai的官方KEY需要伴随组织编码(格式如org-xxxxxxxxxxxxxxxxxxxxxxxx)使用 +API_ORG = "" + # 如果需要使用Slack Claude,使用教程详情见 request_llm/README.md SLACK_CLAUDE_BOT_ID = '' @@ -84,7 +115,35 @@ SLACK_CLAUDE_USER_TOKEN = '' # 如果需要使用AZURE 详情请见额外文档 docs\use_azure.md -AZURE_ENDPOINT = "https://你的api名称.openai.azure.com/" -AZURE_API_KEY = "填入azure openai api的密钥" -AZURE_API_VERSION = "填入api版本" -AZURE_ENGINE = "填入ENGINE" +AZURE_ENDPOINT = "https://你亲手写的api名称.openai.azure.com/" +AZURE_API_KEY = "填入azure openai api的密钥" # 建议直接在API_KEY处填写,该选项即将被弃用 +AZURE_ENGINE = "填入你亲手写的部署名" # 读 docs\use_azure.md + + +# 使用Newbing +NEWBING_STYLE = "creative" # ["creative", "balanced", "precise"] +NEWBING_COOKIES = """ +put your new bing cookies here +""" + + +# 阿里云实时语音识别 配置难度较高 仅建议高手用户使用 参考 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="" # (无需填写) + + +# 接入讯飞星火大模型 https://console.xfyun.cn/services/iat +XFYUN_APPID = "00000000" +XFYUN_API_SECRET = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" +XFYUN_API_KEY = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + +# Claude API KEY +ANTHROPIC_API_KEY = "" + + +# 自定义API KEY格式 +CUSTOM_API_KEY_PATTERN = "" diff --git a/core_functional.py b/core_functional.py index e126b5733a26b2c06668755fc44763efe3d30bac..b04e1e0df07ce20a9700307bc898934c3f1d90cc 100644 --- a/core_functional.py +++ b/core_functional.py @@ -1,20 +1,25 @@ # 'primary' 颜色对应 theme.py 中的 primary_hue # 'secondary' 颜色对应 theme.py 中的 neutral_hue # 'stop' 颜色对应 theme.py 中的 color_er -# 默认按钮颜色是 secondary +import importlib from toolbox import clear_line_break def get_core_functions(): return { "英语学术润色": { - # 前言 + # 前缀,会被加在你的输入之前。例如,用来描述你的要求,例如翻译、解释代码、润色等等 "Prefix": r"Below is a paragraph from an academic paper. Polish the writing to meet the academic style, " + r"improve the spelling, grammar, clarity, concision and overall readability. When necessary, rewrite the whole sentence. " + r"Furthermore, list all modification and explain the reasons to do so in markdown table." + "\n\n", - # 后语 + # 后缀,会被加在你的输入之后。例如,配合前缀可以把你的输入内容用引号圈起来 "Suffix": r"", - "Color": r"secondary", # 按钮颜色 + # 按钮颜色 (默认 secondary) + "Color": r"secondary", + # 按钮是否可见 (默认 True,即可见) + "Visible": True, + # 是否在触发时清除历史 (默认 False,即不处理之前的对话历史) + "AutoClearHistory": False }, "中文学术润色": { "Prefix": r"作为一名中文学术论文写作改进助理,你的任务是改进所提供文本的拼写、语法、清晰、简洁和整体可读性," + @@ -63,6 +68,7 @@ def get_core_functions(): "Prefix": r"我需要你找一张网络图片。使用Unsplash API(https://source.unsplash.com/960x640/?<英语关键词>)获取图片URL," + r"然后请使用Markdown格式封装,并且不要有反斜线,不要用代码块。现在,请按以下描述给我发送图片:" + "\n\n", "Suffix": r"", + "Visible": False, }, "解释代码": { "Prefix": r"请解释以下代码:" + "\n```\n", @@ -73,6 +79,16 @@ def get_core_functions(): r"Note that, reference styles maybe more than one kind, you should transform each item correctly." + r"Items need to be transformed:", "Suffix": r"", - "Visible": False, } } + + +def handle_core_functionality(additional_fn, inputs, history, chatbot): + import core_functional + importlib.reload(core_functional) # 热更新prompt + core_functional = core_functional.get_core_functions() + if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话) + inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] + if core_functional[additional_fn].get("AutoClearHistory", False): + history = [] + return inputs, history diff --git "a/crazy_functions/Langchain\347\237\245\350\257\206\345\272\223.py" "b/crazy_functions/Langchain\347\237\245\350\257\206\345\272\223.py" index 31c459aa1fe5ba35efb85988ff18528d4851f2e5..12735dfd733c345ebba80dc3481734c4282abb15 100644 --- "a/crazy_functions/Langchain\347\237\245\350\257\206\345\272\223.py" +++ "b/crazy_functions/Langchain\347\237\245\350\257\206\345\272\223.py" @@ -30,7 +30,7 @@ def 知识库问答(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_pro ) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 from .crazy_utils import try_install_deps - try_install_deps(['zh_langchain==0.2.1']) + try_install_deps(['zh_langchain==0.2.1', 'pypinyin']) # < --------------------读取参数--------------- > if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg") diff --git "a/crazy_functions/Latex\350\276\223\345\207\272PDF\347\273\223\346\236\234.py" "b/crazy_functions/Latex\350\276\223\345\207\272PDF\347\273\223\346\236\234.py" index 810d80247c60bc2a7ca8eb8d9943677092872561..e79cf8223826e74c31b4cfb0220a395f38b335b2 100644 --- "a/crazy_functions/Latex\350\276\223\345\207\272PDF\347\273\223\346\236\234.py" +++ "b/crazy_functions/Latex\350\276\223\345\207\272PDF\347\273\223\346\236\234.py" @@ -157,7 +157,7 @@ def Latex英文纠错加PDF对比(txt, llm_kwargs, plugin_kwargs, chatbot, histo try: import glob, os, time, subprocess subprocess.Popen(['pdflatex', '-version']) - from .latex_utils import Latex精细分解与转化, 编译Latex + from .latex_fns.latex_actions import Latex精细分解与转化, 编译Latex except Exception as e: chatbot.append([ f"解析项目: {txt}", f"尝试执行Latex指令失败。Latex没有安装, 或者不在环境变量PATH中。安装方法https://tug.org/texlive/。报错信息\n\n```\n\n{trimmed_format_exc()}\n\n```\n\n"]) @@ -234,7 +234,7 @@ def Latex翻译中文并重新编译PDF(txt, llm_kwargs, plugin_kwargs, chatbot, try: import glob, os, time, subprocess subprocess.Popen(['pdflatex', '-version']) - from .latex_utils import Latex精细分解与转化, 编译Latex + from .latex_fns.latex_actions import Latex精细分解与转化, 编译Latex except Exception as e: chatbot.append([ f"解析项目: {txt}", f"尝试执行Latex指令失败。Latex没有安装, 或者不在环境变量PATH中。安装方法https://tug.org/texlive/。报错信息\n\n```\n\n{trimmed_format_exc()}\n\n```\n\n"]) diff --git "a/crazy_functions/chatglm\345\276\256\350\260\203\345\267\245\345\205\267.py" "b/crazy_functions/chatglm\345\276\256\350\260\203\345\267\245\345\205\267.py" new file mode 100644 index 0000000000000000000000000000000000000000..336d7cfc85ac159841758123fa057bd20a0bbbec --- /dev/null +++ "b/crazy_functions/chatglm\345\276\256\350\260\203\345\267\245\345\205\267.py" @@ -0,0 +1,141 @@ +from toolbox import CatchException, update_ui, promote_file_to_downloadzone +from .crazy_utils import request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency +import datetime, json + +def fetch_items(list_of_items, batch_size): + for i in range(0, len(list_of_items), batch_size): + yield list_of_items[i:i + batch_size] + +def string_to_options(arguments): + import argparse + import shlex + + # Create an argparse.ArgumentParser instance + parser = argparse.ArgumentParser() + + # Add command-line arguments + parser.add_argument("--llm_to_learn", type=str, help="LLM model to learn", default="gpt-3.5-turbo") + parser.add_argument("--prompt_prefix", type=str, help="Prompt prefix", default='') + parser.add_argument("--system_prompt", type=str, help="System prompt", default='') + parser.add_argument("--batch", type=int, help="System prompt", default=50) + parser.add_argument("--pre_seq_len", type=int, help="pre_seq_len", default=50) + parser.add_argument("--learning_rate", type=float, help="learning_rate", default=2e-2) + parser.add_argument("--num_gpus", type=int, help="num_gpus", default=1) + parser.add_argument("--json_dataset", type=str, help="json_dataset", default="") + parser.add_argument("--ptuning_directory", type=str, help="ptuning_directory", default="") + + + + # Parse the arguments + args = parser.parse_args(shlex.split(arguments)) + + return args + +@CatchException +def 微调数据集生成(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + """ + txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径 + llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行 + plugin_kwargs 插件模型的参数 + chatbot 聊天显示框的句柄,用于显示给用户 + history 聊天历史,前情提要 + system_prompt 给gpt的静默提醒 + web_port 当前软件运行的端口号 + """ + history = [] # 清空历史,以免输入溢出 + chatbot.append(("这是什么功能?", "[Local Message] 微调数据集生成")) + if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg") + args = plugin_kwargs.get("advanced_arg", None) + if args is None: + chatbot.append(("没给定指令", "退出")) + yield from update_ui(chatbot=chatbot, history=history); return + else: + arguments = string_to_options(arguments=args) + + dat = [] + with open(txt, 'r', encoding='utf8') as f: + for line in f.readlines(): + json_dat = json.loads(line) + dat.append(json_dat["content"]) + + llm_kwargs['llm_model'] = arguments.llm_to_learn + for batch in fetch_items(dat, arguments.batch): + res = yield from request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency( + inputs_array=[f"{arguments.prompt_prefix}\n\n{b}" for b in (batch)], + inputs_show_user_array=[f"Show Nothing" for _ in (batch)], + llm_kwargs=llm_kwargs, + chatbot=chatbot, + history_array=[[] for _ in (batch)], + sys_prompt_array=[arguments.system_prompt for _ in (batch)], + max_workers=10 # OpenAI所允许的最大并行过载 + ) + + with open(txt+'.generated.json', 'a+', encoding='utf8') as f: + for b, r in zip(batch, res[1::2]): + f.write(json.dumps({"content":b, "summary":r}, ensure_ascii=False)+'\n') + + promote_file_to_downloadzone(txt+'.generated.json', rename_file='generated.json', chatbot=chatbot) + return + + + +@CatchException +def 启动微调(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + """ + txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径 + llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行 + plugin_kwargs 插件模型的参数 + chatbot 聊天显示框的句柄,用于显示给用户 + history 聊天历史,前情提要 + system_prompt 给gpt的静默提醒 + web_port 当前软件运行的端口号 + """ + import subprocess + history = [] # 清空历史,以免输入溢出 + chatbot.append(("这是什么功能?", "[Local Message] 微调数据集生成")) + if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg") + args = plugin_kwargs.get("advanced_arg", None) + if args is None: + chatbot.append(("没给定指令", "退出")) + yield from update_ui(chatbot=chatbot, history=history); return + else: + arguments = string_to_options(arguments=args) + + + + pre_seq_len = arguments.pre_seq_len # 128 + learning_rate = arguments.learning_rate # 2e-2 + num_gpus = arguments.num_gpus # 1 + json_dataset = arguments.json_dataset # 't_code.json' + ptuning_directory = arguments.ptuning_directory # '/home/hmp/ChatGLM2-6B/ptuning' + + command = f"torchrun --standalone --nnodes=1 --nproc-per-node={num_gpus} main.py \ + --do_train \ + --train_file AdvertiseGen/{json_dataset} \ + --validation_file AdvertiseGen/{json_dataset} \ + --preprocessing_num_workers 20 \ + --prompt_column content \ + --response_column summary \ + --overwrite_cache \ + --model_name_or_path THUDM/chatglm2-6b \ + --output_dir output/clothgen-chatglm2-6b-pt-{pre_seq_len}-{learning_rate} \ + --overwrite_output_dir \ + --max_source_length 256 \ + --max_target_length 256 \ + --per_device_train_batch_size 1 \ + --per_device_eval_batch_size 1 \ + --gradient_accumulation_steps 16 \ + --predict_with_generate \ + --max_steps 100 \ + --logging_steps 10 \ + --save_steps 20 \ + --learning_rate {learning_rate} \ + --pre_seq_len {pre_seq_len} \ + --quantization_bit 4" + + process = subprocess.Popen(command, shell=True, cwd=ptuning_directory) + try: + process.communicate(timeout=3600*24) + except subprocess.TimeoutExpired: + process.kill() + return diff --git a/crazy_functions/crazy_utils.py b/crazy_functions/crazy_utils.py index a1b1493ce7b196094b6b8ffdf08273bf392a4e30..ffe95e2be56e969c787f5d2895fa502540501660 100644 --- a/crazy_functions/crazy_utils.py +++ b/crazy_functions/crazy_utils.py @@ -130,6 +130,11 @@ def request_gpt_model_in_new_thread_with_ui_alive( yield from update_ui(chatbot=chatbot, history=[]) # 如果最后成功了,则删除报错信息 return final_result +def can_multi_process(llm): + if llm.startswith('gpt-'): return True + if llm.startswith('api2d-'): return True + if llm.startswith('azure-'): return True + return False def request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency( inputs_array, inputs_show_user_array, llm_kwargs, @@ -175,7 +180,7 @@ def request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency( except: max_workers = 8 if max_workers <= 0: max_workers = 3 # 屏蔽掉 chatglm的多线程,可能会导致严重卡顿 - if not (llm_kwargs['llm_model'].startswith('gpt-') or llm_kwargs['llm_model'].startswith('api2d-')): + if not can_multi_process(llm_kwargs['llm_model']): max_workers = 1 executor = ThreadPoolExecutor(max_workers=max_workers) diff --git a/crazy_functions/latex_fns/latex_actions.py b/crazy_functions/latex_fns/latex_actions.py new file mode 100644 index 0000000000000000000000000000000000000000..c59bc31d4b445f69ac58b1e84db789cc4bbe4b43 --- /dev/null +++ b/crazy_functions/latex_fns/latex_actions.py @@ -0,0 +1,447 @@ +from toolbox import update_ui, update_ui_lastest_msg # 刷新Gradio前端界面 +from toolbox import zip_folder, objdump, objload, promote_file_to_downloadzone +from .latex_toolbox import PRESERVE, TRANSFORM +from .latex_toolbox import set_forbidden_text, set_forbidden_text_begin_end, set_forbidden_text_careful_brace +from .latex_toolbox import reverse_forbidden_text_careful_brace, reverse_forbidden_text, convert_to_linklist, post_process +from .latex_toolbox import fix_content, find_main_tex_file, merge_tex_files, compile_latex_with_timeout + +import os, shutil +import re +import numpy as np + +pj = os.path.join + + +def split_subprocess(txt, project_folder, return_dict, opts): + """ + break down latex file to a linked list, + each node use a preserve flag to indicate whether it should + be proccessed by GPT. + """ + text = txt + mask = np.zeros(len(txt), dtype=np.uint8) + TRANSFORM + + # 吸收title与作者以上的部分 + text, mask = set_forbidden_text(text, mask, r"^(.*?)\\maketitle", re.DOTALL) + text, mask = set_forbidden_text(text, mask, r"^(.*?)\\begin{document}", re.DOTALL) + # 吸收iffalse注释 + text, mask = set_forbidden_text(text, mask, r"\\iffalse(.*?)\\fi", re.DOTALL) + # 吸收在42行以内的begin-end组合 + text, mask = set_forbidden_text_begin_end(text, mask, r"\\begin\{([a-z\*]*)\}(.*?)\\end\{\1\}", re.DOTALL, limit_n_lines=42) + # 吸收匿名公式 + text, mask = set_forbidden_text(text, mask, [ r"\$\$([^$]+)\$\$", r"\\\[.*?\\\]" ], re.DOTALL) + # 吸收其他杂项 + text, mask = set_forbidden_text(text, mask, [ r"\\section\{(.*?)\}", r"\\section\*\{(.*?)\}", r"\\subsection\{(.*?)\}", r"\\subsubsection\{(.*?)\}" ]) + text, mask = set_forbidden_text(text, mask, [ r"\\bibliography\{(.*?)\}", r"\\bibliographystyle\{(.*?)\}" ]) + text, mask = set_forbidden_text(text, mask, r"\\begin\{thebibliography\}.*?\\end\{thebibliography\}", re.DOTALL) + text, mask = set_forbidden_text(text, mask, r"\\begin\{lstlisting\}(.*?)\\end\{lstlisting\}", re.DOTALL) + text, mask = set_forbidden_text(text, mask, r"\\begin\{wraptable\}(.*?)\\end\{wraptable\}", re.DOTALL) + text, mask = set_forbidden_text(text, mask, r"\\begin\{algorithm\}(.*?)\\end\{algorithm\}", re.DOTALL) + text, mask = set_forbidden_text(text, mask, [r"\\begin\{wrapfigure\}(.*?)\\end\{wrapfigure\}", r"\\begin\{wrapfigure\*\}(.*?)\\end\{wrapfigure\*\}"], re.DOTALL) + text, mask = set_forbidden_text(text, mask, [r"\\begin\{figure\}(.*?)\\end\{figure\}", r"\\begin\{figure\*\}(.*?)\\end\{figure\*\}"], re.DOTALL) + text, mask = set_forbidden_text(text, mask, [r"\\begin\{multline\}(.*?)\\end\{multline\}", r"\\begin\{multline\*\}(.*?)\\end\{multline\*\}"], re.DOTALL) + text, mask = set_forbidden_text(text, mask, [r"\\begin\{table\}(.*?)\\end\{table\}", r"\\begin\{table\*\}(.*?)\\end\{table\*\}"], re.DOTALL) + text, mask = set_forbidden_text(text, mask, [r"\\begin\{minipage\}(.*?)\\end\{minipage\}", r"\\begin\{minipage\*\}(.*?)\\end\{minipage\*\}"], re.DOTALL) + text, mask = set_forbidden_text(text, mask, [r"\\begin\{align\*\}(.*?)\\end\{align\*\}", r"\\begin\{align\}(.*?)\\end\{align\}"], re.DOTALL) + text, mask = set_forbidden_text(text, mask, [r"\\begin\{equation\}(.*?)\\end\{equation\}", r"\\begin\{equation\*\}(.*?)\\end\{equation\*\}"], re.DOTALL) + text, mask = set_forbidden_text(text, mask, [r"\\includepdf\[(.*?)\]\{(.*?)\}", r"\\clearpage", r"\\newpage", r"\\appendix", r"\\tableofcontents", r"\\include\{(.*?)\}"]) + text, mask = set_forbidden_text(text, mask, [r"\\vspace\{(.*?)\}", r"\\hspace\{(.*?)\}", r"\\label\{(.*?)\}", r"\\begin\{(.*?)\}", r"\\end\{(.*?)\}", r"\\item "]) + text, mask = set_forbidden_text_careful_brace(text, mask, r"\\hl\{(.*?)\}", re.DOTALL) + # reverse 操作必须放在最后 + text, mask = reverse_forbidden_text_careful_brace(text, mask, r"\\caption\{(.*?)\}", re.DOTALL, forbid_wrapper=True) + text, mask = reverse_forbidden_text_careful_brace(text, mask, r"\\abstract\{(.*?)\}", re.DOTALL, forbid_wrapper=True) + text, mask = reverse_forbidden_text(text, mask, r"\\begin\{abstract\}(.*?)\\end\{abstract\}", re.DOTALL, forbid_wrapper=True) + root = convert_to_linklist(text, mask) + + # 最后一步处理,增强稳健性 + root = post_process(root) + + # 输出html调试文件,用红色标注处保留区(PRESERVE),用黑色标注转换区(TRANSFORM) + with open(pj(project_folder, 'debug_log.html'), 'w', encoding='utf8') as f: + segment_parts_for_gpt = [] + nodes = [] + node = root + while True: + nodes.append(node) + show_html = node.string.replace('\n','
') + if not node.preserve: + segment_parts_for_gpt.append(node.string) + f.write(f'

#{node.range}{show_html}#

') + else: + f.write(f'

{show_html}

') + node = node.next + if node is None: break + + for n in nodes: n.next = None # break + return_dict['nodes'] = nodes + return_dict['segment_parts_for_gpt'] = segment_parts_for_gpt + return return_dict + +class LatexPaperSplit(): + """ + break down latex file to a linked list, + each node use a preserve flag to indicate whether it should + be proccessed by GPT. + """ + def __init__(self) -> None: + self.nodes = None + self.msg = "*{\\scriptsize\\textbf{警告:该PDF由GPT-Academic开源项目调用大语言模型+Latex翻译插件一键生成," + \ + "版权归原文作者所有。翻译内容可靠性无保障,请仔细鉴别并以原文为准。" + \ + "项目Github地址 \\url{https://github.com/binary-husky/gpt_academic/}。" + # 请您不要删除或修改这行警告,除非您是论文的原作者(如果您是论文原作者,欢迎加REAME中的QQ联系开发者) + self.msg_declare = "为了防止大语言模型的意外谬误产生扩散影响,禁止移除或修改此警告。}}\\\\" + + + def merge_result(self, arr, mode, msg, buggy_lines=[], buggy_line_surgery_n_lines=10): + """ + Merge the result after the GPT process completed + """ + result_string = "" + node_cnt = 0 + line_cnt = 0 + + for node in self.nodes: + if node.preserve: + line_cnt += node.string.count('\n') + result_string += node.string + else: + translated_txt = fix_content(arr[node_cnt], node.string) + begin_line = line_cnt + end_line = line_cnt + translated_txt.count('\n') + + # reverse translation if any error + if any([begin_line-buggy_line_surgery_n_lines <= b_line <= end_line+buggy_line_surgery_n_lines for b_line in buggy_lines]): + translated_txt = node.string + + result_string += translated_txt + node_cnt += 1 + line_cnt += translated_txt.count('\n') + + if mode == 'translate_zh': + pattern = re.compile(r'\\begin\{abstract\}.*\n') + match = pattern.search(result_string) + if not match: + # match \abstract{xxxx} + pattern_compile = re.compile(r"\\abstract\{(.*?)\}", flags=re.DOTALL) + match = pattern_compile.search(result_string) + position = match.regs[1][0] + else: + # match \begin{abstract}xxxx\end{abstract} + position = match.end() + result_string = result_string[:position] + self.msg + msg + self.msg_declare + result_string[position:] + return result_string + + + def split(self, txt, project_folder, opts): + """ + break down latex file to a linked list, + each node use a preserve flag to indicate whether it should + be proccessed by GPT. + P.S. use multiprocessing to avoid timeout error + """ + import multiprocessing + manager = multiprocessing.Manager() + return_dict = manager.dict() + p = multiprocessing.Process( + target=split_subprocess, + args=(txt, project_folder, return_dict, opts)) + p.start() + p.join() + p.close() + self.nodes = return_dict['nodes'] + self.sp = return_dict['segment_parts_for_gpt'] + return self.sp + + +class LatexPaperFileGroup(): + """ + use tokenizer to break down text according to max_token_limit + """ + def __init__(self): + self.file_paths = [] + self.file_contents = [] + self.sp_file_contents = [] + self.sp_file_index = [] + self.sp_file_tag = [] + + # count_token + from request_llm.bridge_all import model_info + enc = model_info["gpt-3.5-turbo"]['tokenizer'] + def get_token_num(txt): return len(enc.encode(txt, disallowed_special=())) + self.get_token_num = get_token_num + + def run_file_split(self, max_token_limit=1900): + """ + use tokenizer to break down text according to max_token_limit + """ + for index, file_content in enumerate(self.file_contents): + if self.get_token_num(file_content) < max_token_limit: + self.sp_file_contents.append(file_content) + self.sp_file_index.append(index) + self.sp_file_tag.append(self.file_paths[index]) + else: + from ..crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf + segments = breakdown_txt_to_satisfy_token_limit_for_pdf(file_content, self.get_token_num, max_token_limit) + for j, segment in enumerate(segments): + self.sp_file_contents.append(segment) + self.sp_file_index.append(index) + self.sp_file_tag.append(self.file_paths[index] + f".part-{j}.tex") + print('Segmentation: done') + + def merge_result(self): + self.file_result = ["" for _ in range(len(self.file_paths))] + for r, k in zip(self.sp_file_result, self.sp_file_index): + self.file_result[k] += r + + def write_result(self): + manifest = [] + for path, res in zip(self.file_paths, self.file_result): + with open(path + '.polish.tex', 'w', encoding='utf8') as f: + manifest.append(path + '.polish.tex') + f.write(res) + return manifest + + +def Latex精细分解与转化(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, mode='proofread', switch_prompt=None, opts=[]): + import time, os, re + from ..crazy_utils import request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency + from .latex_actions import LatexPaperFileGroup, LatexPaperSplit + + # <-------- 寻找主tex文件 ----------> + maintex = find_main_tex_file(file_manifest, mode) + chatbot.append((f"定位主Latex文件", f'[Local Message] 分析结果:该项目的Latex主文件是{maintex}, 如果分析错误, 请立即终止程序, 删除或修改歧义文件, 然后重试。主程序即将开始, 请稍候。')) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + time.sleep(3) + + # <-------- 读取Latex文件, 将多文件tex工程融合为一个巨型tex ----------> + main_tex_basename = os.path.basename(maintex) + assert main_tex_basename.endswith('.tex') + main_tex_basename_bare = main_tex_basename[:-4] + may_exist_bbl = pj(project_folder, f'{main_tex_basename_bare}.bbl') + if os.path.exists(may_exist_bbl): + shutil.copyfile(may_exist_bbl, pj(project_folder, f'merge.bbl')) + shutil.copyfile(may_exist_bbl, pj(project_folder, f'merge_{mode}.bbl')) + shutil.copyfile(may_exist_bbl, pj(project_folder, f'merge_diff.bbl')) + + with open(maintex, 'r', encoding='utf-8', errors='replace') as f: + content = f.read() + merged_content = merge_tex_files(project_folder, content, mode) + + with open(project_folder + '/merge.tex', 'w', encoding='utf-8', errors='replace') as f: + f.write(merged_content) + + # <-------- 精细切分latex文件 ----------> + chatbot.append((f"Latex文件融合完成", f'[Local Message] 正在精细切分latex文件,这需要一段时间计算,文档越长耗时越长,请耐心等待。')) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + lps = LatexPaperSplit() + res = lps.split(merged_content, project_folder, opts) # 消耗时间的函数 + + # <-------- 拆分过长的latex片段 ----------> + pfg = LatexPaperFileGroup() + for index, r in enumerate(res): + pfg.file_paths.append('segment-' + str(index)) + pfg.file_contents.append(r) + + pfg.run_file_split(max_token_limit=1024) + n_split = len(pfg.sp_file_contents) + + # <-------- 根据需要切换prompt ----------> + inputs_array, sys_prompt_array = switch_prompt(pfg, mode) + inputs_show_user_array = [f"{mode} {f}" for f in pfg.sp_file_tag] + + if os.path.exists(pj(project_folder,'temp.pkl')): + + # <-------- 【仅调试】如果存在调试缓存文件,则跳过GPT请求环节 ----------> + pfg = objload(file=pj(project_folder,'temp.pkl')) + + else: + # <-------- gpt 多线程请求 ----------> + gpt_response_collection = yield from request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency( + inputs_array=inputs_array, + inputs_show_user_array=inputs_show_user_array, + llm_kwargs=llm_kwargs, + chatbot=chatbot, + history_array=[[""] for _ in range(n_split)], + sys_prompt_array=sys_prompt_array, + # max_workers=5, # 并行任务数量限制, 最多同时执行5个, 其他的排队等待 + scroller_max_len = 40 + ) + + # <-------- 文本碎片重组为完整的tex片段 ----------> + pfg.sp_file_result = [] + for i_say, gpt_say, orig_content in zip(gpt_response_collection[0::2], gpt_response_collection[1::2], pfg.sp_file_contents): + pfg.sp_file_result.append(gpt_say) + pfg.merge_result() + + # <-------- 临时存储用于调试 ----------> + pfg.get_token_num = None + objdump(pfg, file=pj(project_folder,'temp.pkl')) + + write_html(pfg.sp_file_contents, pfg.sp_file_result, chatbot=chatbot, project_folder=project_folder) + + # <-------- 写出文件 ----------> + msg = f"当前大语言模型: {llm_kwargs['llm_model']},当前语言模型温度设定: {llm_kwargs['temperature']}。" + final_tex = lps.merge_result(pfg.file_result, mode, msg) + objdump((lps, pfg.file_result, mode, msg), file=pj(project_folder,'merge_result.pkl')) + + with open(project_folder + f'/merge_{mode}.tex', 'w', encoding='utf-8', errors='replace') as f: + if mode != 'translate_zh' or "binary" in final_tex: f.write(final_tex) + + + # <-------- 整理结果, 退出 ----------> + chatbot.append((f"完成了吗?", 'GPT结果已输出, 即将编译PDF')) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + + # <-------- 返回 ----------> + return project_folder + f'/merge_{mode}.tex' + + +def remove_buggy_lines(file_path, log_path, tex_name, tex_name_pure, n_fix, work_folder_modified, fixed_line=[]): + try: + with open(log_path, 'r', encoding='utf-8', errors='replace') as f: + log = f.read() + import re + buggy_lines = re.findall(tex_name+':([0-9]{1,5}):', log) + buggy_lines = [int(l) for l in buggy_lines] + buggy_lines = sorted(buggy_lines) + buggy_line = buggy_lines[0]-1 + print("reversing tex line that has errors", buggy_line) + + # 重组,逆转出错的段落 + if buggy_line not in fixed_line: + fixed_line.append(buggy_line) + + lps, file_result, mode, msg = objload(file=pj(work_folder_modified,'merge_result.pkl')) + final_tex = lps.merge_result(file_result, mode, msg, buggy_lines=fixed_line, buggy_line_surgery_n_lines=5*n_fix) + + with open(pj(work_folder_modified, f"{tex_name_pure}_fix_{n_fix}.tex"), 'w', encoding='utf-8', errors='replace') as f: + f.write(final_tex) + + return True, f"{tex_name_pure}_fix_{n_fix}", buggy_lines + except: + print("Fatal error occurred, but we cannot identify error, please download zip, read latex log, and compile manually.") + return False, -1, [-1] + + +def 编译Latex(chatbot, history, main_file_original, main_file_modified, work_folder_original, work_folder_modified, work_folder, mode='default'): + import os, time + n_fix = 1 + fixed_line = [] + max_try = 32 + chatbot.append([f"正在编译PDF文档", f'编译已经开始。当前工作路径为{work_folder},如果程序停顿5分钟以上,请直接去该路径下取回翻译结果,或者重启之后再度尝试 ...']); yield from update_ui(chatbot=chatbot, history=history) + chatbot.append([f"正在编译PDF文档", '...']); yield from update_ui(chatbot=chatbot, history=history); time.sleep(1); chatbot[-1] = list(chatbot[-1]) # 刷新界面 + yield from update_ui_lastest_msg('编译已经开始...', chatbot, history) # 刷新Gradio前端界面 + + while True: + import os + may_exist_bbl = pj(work_folder_modified, f'merge.bbl') + target_bbl = pj(work_folder_modified, f'{main_file_modified}.bbl') + if os.path.exists(may_exist_bbl) and not os.path.exists(target_bbl): + shutil.copyfile(may_exist_bbl, target_bbl) + + # https://stackoverflow.com/questions/738755/dont-make-me-manually-abort-a-latex-compile-when-theres-an-error + yield from update_ui_lastest_msg(f'尝试第 {n_fix}/{max_try} 次编译, 编译原始PDF ...', chatbot, history) # 刷新Gradio前端界面 + ok = compile_latex_with_timeout(f'pdflatex -interaction=batchmode -file-line-error {main_file_original}.tex', work_folder_original) + + yield from update_ui_lastest_msg(f'尝试第 {n_fix}/{max_try} 次编译, 编译转化后的PDF ...', chatbot, history) # 刷新Gradio前端界面 + ok = compile_latex_with_timeout(f'pdflatex -interaction=batchmode -file-line-error {main_file_modified}.tex', work_folder_modified) + + if ok and os.path.exists(pj(work_folder_modified, f'{main_file_modified}.pdf')): + # 只有第二步成功,才能继续下面的步骤 + yield from update_ui_lastest_msg(f'尝试第 {n_fix}/{max_try} 次编译, 编译BibTex ...', chatbot, history) # 刷新Gradio前端界面 + if not os.path.exists(pj(work_folder_original, f'{main_file_original}.bbl')): + ok = compile_latex_with_timeout(f'bibtex {main_file_original}.aux', work_folder_original) + if not os.path.exists(pj(work_folder_modified, f'{main_file_modified}.bbl')): + ok = compile_latex_with_timeout(f'bibtex {main_file_modified}.aux', work_folder_modified) + + yield from update_ui_lastest_msg(f'尝试第 {n_fix}/{max_try} 次编译, 编译文献交叉引用 ...', chatbot, history) # 刷新Gradio前端界面 + ok = compile_latex_with_timeout(f'pdflatex -interaction=batchmode -file-line-error {main_file_original}.tex', work_folder_original) + ok = compile_latex_with_timeout(f'pdflatex -interaction=batchmode -file-line-error {main_file_modified}.tex', work_folder_modified) + ok = compile_latex_with_timeout(f'pdflatex -interaction=batchmode -file-line-error {main_file_original}.tex', work_folder_original) + ok = compile_latex_with_timeout(f'pdflatex -interaction=batchmode -file-line-error {main_file_modified}.tex', work_folder_modified) + + if mode!='translate_zh': + yield from update_ui_lastest_msg(f'尝试第 {n_fix}/{max_try} 次编译, 使用latexdiff生成论文转化前后对比 ...', chatbot, history) # 刷新Gradio前端界面 + print( f'latexdiff --encoding=utf8 --append-safecmd=subfile {work_folder_original}/{main_file_original}.tex {work_folder_modified}/{main_file_modified}.tex --flatten > {work_folder}/merge_diff.tex') + ok = compile_latex_with_timeout(f'latexdiff --encoding=utf8 --append-safecmd=subfile {work_folder_original}/{main_file_original}.tex {work_folder_modified}/{main_file_modified}.tex --flatten > {work_folder}/merge_diff.tex') + + yield from update_ui_lastest_msg(f'尝试第 {n_fix}/{max_try} 次编译, 正在编译对比PDF ...', chatbot, history) # 刷新Gradio前端界面 + ok = compile_latex_with_timeout(f'pdflatex -interaction=batchmode -file-line-error merge_diff.tex', work_folder) + ok = compile_latex_with_timeout(f'bibtex merge_diff.aux', work_folder) + ok = compile_latex_with_timeout(f'pdflatex -interaction=batchmode -file-line-error merge_diff.tex', work_folder) + ok = compile_latex_with_timeout(f'pdflatex -interaction=batchmode -file-line-error merge_diff.tex', work_folder) + + # <---------- 检查结果 -----------> + results_ = "" + original_pdf_success = os.path.exists(pj(work_folder_original, f'{main_file_original}.pdf')) + modified_pdf_success = os.path.exists(pj(work_folder_modified, f'{main_file_modified}.pdf')) + diff_pdf_success = os.path.exists(pj(work_folder, f'merge_diff.pdf')) + results_ += f"原始PDF编译是否成功: {original_pdf_success};" + results_ += f"转化PDF编译是否成功: {modified_pdf_success};" + results_ += f"对比PDF编译是否成功: {diff_pdf_success};" + yield from update_ui_lastest_msg(f'第{n_fix}编译结束:
{results_}...', chatbot, history) # 刷新Gradio前端界面 + + if diff_pdf_success: + result_pdf = pj(work_folder_modified, f'merge_diff.pdf') # get pdf path + promote_file_to_downloadzone(result_pdf, rename_file=None, chatbot=chatbot) # promote file to web UI + if modified_pdf_success: + yield from update_ui_lastest_msg(f'转化PDF编译已经成功, 即将退出 ...', chatbot, history) # 刷新Gradio前端界面 + result_pdf = pj(work_folder_modified, f'{main_file_modified}.pdf') # get pdf path + origin_pdf = pj(work_folder_original, f'{main_file_original}.pdf') # get pdf path + if os.path.exists(pj(work_folder, '..', 'translation')): + shutil.copyfile(result_pdf, pj(work_folder, '..', 'translation', 'translate_zh.pdf')) + promote_file_to_downloadzone(result_pdf, rename_file=None, chatbot=chatbot) # promote file to web UI + # 将两个PDF拼接 + if original_pdf_success: + try: + from .latex_toolbox import merge_pdfs + concat_pdf = pj(work_folder_modified, f'comparison.pdf') + merge_pdfs(origin_pdf, result_pdf, concat_pdf) + promote_file_to_downloadzone(concat_pdf, rename_file=None, chatbot=chatbot) # promote file to web UI + except Exception as e: + pass + return True # 成功啦 + else: + if n_fix>=max_try: break + n_fix += 1 + can_retry, main_file_modified, buggy_lines = remove_buggy_lines( + file_path=pj(work_folder_modified, f'{main_file_modified}.tex'), + log_path=pj(work_folder_modified, f'{main_file_modified}.log'), + tex_name=f'{main_file_modified}.tex', + tex_name_pure=f'{main_file_modified}', + n_fix=n_fix, + work_folder_modified=work_folder_modified, + fixed_line=fixed_line + ) + yield from update_ui_lastest_msg(f'由于最为关键的转化PDF编译失败, 将根据报错信息修正tex源文件并重试, 当前报错的latex代码处于第{buggy_lines}行 ...', chatbot, history) # 刷新Gradio前端界面 + if not can_retry: break + + return False # 失败啦 + + +def write_html(sp_file_contents, sp_file_result, chatbot, project_folder): + # write html + try: + import shutil + from ..crazy_utils import construct_html + from toolbox import gen_time_str + ch = construct_html() + orig = "" + trans = "" + final = [] + for c,r in zip(sp_file_contents, sp_file_result): + final.append(c) + final.append(r) + for i, k in enumerate(final): + if i%2==0: + orig = k + if i%2==1: + trans = k + ch.add_row(a=orig, b=trans) + create_report_file_name = f"{gen_time_str()}.trans.html" + ch.save_file(create_report_file_name) + shutil.copyfile(pj('./gpt_log/', create_report_file_name), pj(project_folder, create_report_file_name)) + promote_file_to_downloadzone(file=f'./gpt_log/{create_report_file_name}', chatbot=chatbot) + except: + from toolbox import trimmed_format_exc + print('writing html result failed:', trimmed_format_exc()) diff --git a/crazy_functions/latex_fns/latex_toolbox.py b/crazy_functions/latex_fns/latex_toolbox.py new file mode 100644 index 0000000000000000000000000000000000000000..a0c889a80867903efab84498fea71b4c7120fd21 --- /dev/null +++ b/crazy_functions/latex_fns/latex_toolbox.py @@ -0,0 +1,456 @@ +import os, shutil +import re +import numpy as np +PRESERVE = 0 +TRANSFORM = 1 + +pj = os.path.join + +class LinkedListNode(): + """ + Linked List Node + """ + def __init__(self, string, preserve=True) -> None: + self.string = string + self.preserve = preserve + self.next = None + self.range = None + # self.begin_line = 0 + # self.begin_char = 0 + +def convert_to_linklist(text, mask): + root = LinkedListNode("", preserve=True) + current_node = root + for c, m, i in zip(text, mask, range(len(text))): + if (m==PRESERVE and current_node.preserve) \ + or (m==TRANSFORM and not current_node.preserve): + # add + current_node.string += c + else: + current_node.next = LinkedListNode(c, preserve=(m==PRESERVE)) + current_node = current_node.next + return root + +def post_process(root): + # 修复括号 + node = root + while True: + string = node.string + if node.preserve: + node = node.next + if node is None: break + continue + def break_check(string): + str_stack = [""] # (lv, index) + for i, c in enumerate(string): + if c == '{': + str_stack.append('{') + elif c == '}': + if len(str_stack) == 1: + print('stack fix') + return i + str_stack.pop(-1) + else: + str_stack[-1] += c + return -1 + bp = break_check(string) + + if bp == -1: + pass + elif bp == 0: + node.string = string[:1] + q = LinkedListNode(string[1:], False) + q.next = node.next + node.next = q + else: + node.string = string[:bp] + q = LinkedListNode(string[bp:], False) + q.next = node.next + node.next = q + + node = node.next + if node is None: break + + # 屏蔽空行和太短的句子 + node = root + while True: + if len(node.string.strip('\n').strip(''))==0: node.preserve = True + if len(node.string.strip('\n').strip(''))<42: node.preserve = True + node = node.next + if node is None: break + node = root + while True: + if node.next and node.preserve and node.next.preserve: + node.string += node.next.string + node.next = node.next.next + node = node.next + if node is None: break + + # 将前后断行符脱离 + node = root + prev_node = None + while True: + if not node.preserve: + lstriped_ = node.string.lstrip().lstrip('\n') + if (prev_node is not None) and (prev_node.preserve) and (len(lstriped_)!=len(node.string)): + prev_node.string += node.string[:-len(lstriped_)] + node.string = lstriped_ + rstriped_ = node.string.rstrip().rstrip('\n') + if (node.next is not None) and (node.next.preserve) and (len(rstriped_)!=len(node.string)): + node.next.string = node.string[len(rstriped_):] + node.next.string + node.string = rstriped_ + # ===== + prev_node = node + node = node.next + if node is None: break + + # 标注节点的行数范围 + node = root + n_line = 0 + expansion = 2 + while True: + n_l = node.string.count('\n') + node.range = [n_line-expansion, n_line+n_l+expansion] # 失败时,扭转的范围 + n_line = n_line+n_l + node = node.next + if node is None: break + return root + + +""" +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +Latex segmentation with a binary mask (PRESERVE=0, TRANSFORM=1) +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +""" + + +def set_forbidden_text(text, mask, pattern, flags=0): + """ + Add a preserve text area in this paper + e.g. with pattern = r"\\begin\{algorithm\}(.*?)\\end\{algorithm\}" + you can mask out (mask = PRESERVE so that text become untouchable for GPT) + everything between "\begin{equation}" and "\end{equation}" + """ + if isinstance(pattern, list): pattern = '|'.join(pattern) + pattern_compile = re.compile(pattern, flags) + for res in pattern_compile.finditer(text): + mask[res.span()[0]:res.span()[1]] = PRESERVE + return text, mask + +def reverse_forbidden_text(text, mask, pattern, flags=0, forbid_wrapper=True): + """ + Move area out of preserve area (make text editable for GPT) + count the number of the braces so as to catch compelete text area. + e.g. + \begin{abstract} blablablablablabla. \end{abstract} + """ + if isinstance(pattern, list): pattern = '|'.join(pattern) + pattern_compile = re.compile(pattern, flags) + for res in pattern_compile.finditer(text): + if not forbid_wrapper: + mask[res.span()[0]:res.span()[1]] = TRANSFORM + else: + mask[res.regs[0][0]: res.regs[1][0]] = PRESERVE # '\\begin{abstract}' + mask[res.regs[1][0]: res.regs[1][1]] = TRANSFORM # abstract + mask[res.regs[1][1]: res.regs[0][1]] = PRESERVE # abstract + return text, mask + +def set_forbidden_text_careful_brace(text, mask, pattern, flags=0): + """ + Add a preserve text area in this paper (text become untouchable for GPT). + count the number of the braces so as to catch compelete text area. + e.g. + \caption{blablablablabla\texbf{blablabla}blablabla.} + """ + pattern_compile = re.compile(pattern, flags) + for res in pattern_compile.finditer(text): + brace_level = -1 + p = begin = end = res.regs[0][0] + for _ in range(1024*16): + if text[p] == '}' and brace_level == 0: break + elif text[p] == '}': brace_level -= 1 + elif text[p] == '{': brace_level += 1 + p += 1 + end = p+1 + mask[begin:end] = PRESERVE + return text, mask + +def reverse_forbidden_text_careful_brace(text, mask, pattern, flags=0, forbid_wrapper=True): + """ + Move area out of preserve area (make text editable for GPT) + count the number of the braces so as to catch compelete text area. + e.g. + \caption{blablablablabla\texbf{blablabla}blablabla.} + """ + pattern_compile = re.compile(pattern, flags) + for res in pattern_compile.finditer(text): + brace_level = 0 + p = begin = end = res.regs[1][0] + for _ in range(1024*16): + if text[p] == '}' and brace_level == 0: break + elif text[p] == '}': brace_level -= 1 + elif text[p] == '{': brace_level += 1 + p += 1 + end = p + mask[begin:end] = TRANSFORM + if forbid_wrapper: + mask[res.regs[0][0]:begin] = PRESERVE + mask[end:res.regs[0][1]] = PRESERVE + return text, mask + +def set_forbidden_text_begin_end(text, mask, pattern, flags=0, limit_n_lines=42): + """ + Find all \begin{} ... \end{} text block that with less than limit_n_lines lines. + Add it to preserve area + """ + pattern_compile = re.compile(pattern, flags) + def search_with_line_limit(text, mask): + for res in pattern_compile.finditer(text): + cmd = res.group(1) # begin{what} + this = res.group(2) # content between begin and end + this_mask = mask[res.regs[2][0]:res.regs[2][1]] + white_list = ['document', 'abstract', 'lemma', 'definition', 'sproof', + 'em', 'emph', 'textit', 'textbf', 'itemize', 'enumerate'] + if (cmd in white_list) or this.count('\n') >= limit_n_lines: # use a magical number 42 + this, this_mask = search_with_line_limit(this, this_mask) + mask[res.regs[2][0]:res.regs[2][1]] = this_mask + else: + mask[res.regs[0][0]:res.regs[0][1]] = PRESERVE + return text, mask + return search_with_line_limit(text, mask) + + + +""" +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +Latex Merge File +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +""" + +def find_main_tex_file(file_manifest, mode): + """ + 在多Tex文档中,寻找主文件,必须包含documentclass,返回找到的第一个。 + P.S. 但愿没人把latex模板放在里面传进来 (6.25 加入判定latex模板的代码) + """ + canidates = [] + for texf in file_manifest: + if os.path.basename(texf).startswith('merge'): + continue + with open(texf, 'r', encoding='utf8', errors='ignore') as f: + file_content = f.read() + if r'\documentclass' in file_content: + canidates.append(texf) + else: + continue + + if len(canidates) == 0: + raise RuntimeError('无法找到一个主Tex文件(包含documentclass关键字)') + elif len(canidates) == 1: + return canidates[0] + else: # if len(canidates) >= 2 通过一些Latex模板中常见(但通常不会出现在正文)的单词,对不同latex源文件扣分,取评分最高者返回 + canidates_score = [] + # 给出一些判定模板文档的词作为扣分项 + unexpected_words = ['\LaTeX', 'manuscript', 'Guidelines', 'font', 'citations', 'rejected', 'blind review', 'reviewers'] + expected_words = ['\input', '\ref', '\cite'] + for texf in canidates: + canidates_score.append(0) + with open(texf, 'r', encoding='utf8', errors='ignore') as f: + file_content = f.read() + for uw in unexpected_words: + if uw in file_content: + canidates_score[-1] -= 1 + for uw in expected_words: + if uw in file_content: + canidates_score[-1] += 1 + select = np.argmax(canidates_score) # 取评分最高者返回 + return canidates[select] + +def rm_comments(main_file): + new_file_remove_comment_lines = [] + for l in main_file.splitlines(): + # 删除整行的空注释 + if l.lstrip().startswith("%"): + pass + else: + new_file_remove_comment_lines.append(l) + main_file = '\n'.join(new_file_remove_comment_lines) + # main_file = re.sub(r"\\include{(.*?)}", r"\\input{\1}", main_file) # 将 \include 命令转换为 \input 命令 + main_file = re.sub(r'(? 0 and node_string.count('\_') > final_tex.count('\_'): + # walk and replace any _ without \ + final_tex = re.sub(r"(?{}".format(args)) + pass + + def test_on_close(self, *args): + self.aliyun_service_ok = False + pass + + def test_on_result_chg(self, message, *args): + # print("test_on_chg:{}".format(message)) + message = json.loads(message) + self.parsed_text = message['payload']['result'] + self.event_on_result_chg.set() + + def test_on_completed(self, message, *args): + # print("on_completed:args=>{} message=>{}".format(args, message)) + pass + + + def audio_convertion_thread(self, uuid): + # 在一个异步线程中采集音频 + import nls # pip install git+https://github.com/aliyun/alibabacloud-nls-python-sdk.git + import tempfile + from scipy import io + from toolbox import get_conf + from .audio_io import change_sample_rate + from .audio_io import RealtimeAudioDistribution + NEW_SAMPLERATE = 16000 + rad = RealtimeAudioDistribution() + rad.clean_up() + temp_folder = tempfile.gettempdir() + TOKEN, APPKEY = get_conf('ALIYUN_TOKEN', 'ALIYUN_APPKEY') + if len(TOKEN) == 0: + TOKEN = self.get_token() + self.aliyun_service_ok = True + URL="wss://nls-gateway.aliyuncs.com/ws/v1" + sr = nls.NlsSpeechTranscriber( + url=URL, + token=TOKEN, + appkey=APPKEY, + on_sentence_begin=self.test_on_sentence_begin, + on_sentence_end=self.test_on_sentence_end, + on_start=self.test_on_start, + on_result_changed=self.test_on_result_chg, + on_completed=self.test_on_completed, + on_error=self.test_on_error, + on_close=self.test_on_close, + callback_args=[uuid.hex] + ) + + r = sr.start(aformat="pcm", + enable_intermediate_result=True, + enable_punctuation_prediction=True, + enable_inverse_text_normalization=True) + + while not self.stop: + # time.sleep(self.capture_interval) + audio = rad.read(uuid.hex) + if audio is not None: + # convert to pcm file + temp_file = f'{temp_folder}/{uuid.hex}.pcm' # + dsdata = change_sample_rate(audio, rad.rate, NEW_SAMPLERATE) # 48000 --> 16000 + io.wavfile.write(temp_file, NEW_SAMPLERATE, dsdata) + # read pcm binary + with open(temp_file, "rb") as f: data = f.read() + # print('audio len:', len(audio), '\t ds len:', len(dsdata), '\t need n send:', len(data)//640) + slices = zip(*(iter(data),) * 640) # 640个字节为一组 + for i in slices: sr.send_audio(bytes(i)) + else: + time.sleep(0.1) + + if not self.aliyun_service_ok: + self.stop = True + self.stop_msg = 'Aliyun音频服务异常,请检查ALIYUN_TOKEN和ALIYUN_APPKEY是否过期。' + r = sr.stop() + + def get_token(self): + from toolbox import get_conf + import json + from aliyunsdkcore.request import CommonRequest + from aliyunsdkcore.client import AcsClient + AccessKey_ID, AccessKey_secret = get_conf('ALIYUN_ACCESSKEY', 'ALIYUN_SECRET') + + # 创建AcsClient实例 + client = AcsClient( + AccessKey_ID, + AccessKey_secret, + "cn-shanghai" + ) + + # 创建request,并设置参数。 + request = CommonRequest() + request.set_method('POST') + request.set_domain('nls-meta.cn-shanghai.aliyuncs.com') + request.set_version('2019-02-28') + request.set_action_name('CreateToken') + + try: + response = client.do_action_with_exception(request) + print(response) + jss = json.loads(response) + if 'Token' in jss and 'Id' in jss['Token']: + token = jss['Token']['Id'] + expireTime = jss['Token']['ExpireTime'] + print("token = " + token) + print("expireTime = " + str(expireTime)) + except Exception as e: + print(e) + + return token diff --git a/crazy_functions/live_audio/audio_io.py b/crazy_functions/live_audio/audio_io.py new file mode 100644 index 0000000000000000000000000000000000000000..3ff83a66e8d9f0bb15250f1c3c2b5ea36745ff55 --- /dev/null +++ b/crazy_functions/live_audio/audio_io.py @@ -0,0 +1,51 @@ +import numpy as np +from scipy import interpolate + +def Singleton(cls): + _instance = {} + + def _singleton(*args, **kargs): + if cls not in _instance: + _instance[cls] = cls(*args, **kargs) + return _instance[cls] + + return _singleton + + +@Singleton +class RealtimeAudioDistribution(): + def __init__(self) -> None: + self.data = {} + self.max_len = 1024*1024 + self.rate = 48000 # 只读,每秒采样数量 + + def clean_up(self): + self.data = {} + + def feed(self, uuid, audio): + self.rate, audio_ = audio + # print('feed', len(audio_), audio_[-25:]) + if uuid not in self.data: + self.data[uuid] = audio_ + else: + new_arr = np.concatenate((self.data[uuid], audio_)) + if len(new_arr) > self.max_len: new_arr = new_arr[-self.max_len:] + self.data[uuid] = new_arr + + def read(self, uuid): + if uuid in self.data: + res = self.data.pop(uuid) + print('\r read-', len(res), '-', max(res), end='', flush=True) + else: + res = None + return res + +def change_sample_rate(audio, old_sr, new_sr): + duration = audio.shape[0] / old_sr + + time_old = np.linspace(0, duration, audio.shape[0]) + time_new = np.linspace(0, duration, int(audio.shape[0] * new_sr / old_sr)) + + interpolator = interpolate.interp1d(time_old, audio.T) + new_audio = interpolator(time_new).T + return new_audio.astype(np.int16) \ No newline at end of file diff --git "a/crazy_functions/\344\270\213\350\275\275arxiv\350\256\272\346\226\207\347\277\273\350\257\221\346\221\230\350\246\201.py" "b/crazy_functions/\344\270\213\350\275\275arxiv\350\256\272\346\226\207\347\277\273\350\257\221\346\221\230\350\246\201.py" index 3da831fd07e361a532777c83bb02cff265b94abd..46275bf4fed59ca5692581ac9b354c4d4ad91d7c 100644 --- "a/crazy_functions/\344\270\213\350\275\275arxiv\350\256\272\346\226\207\347\277\273\350\257\221\346\221\230\350\246\201.py" +++ "b/crazy_functions/\344\270\213\350\275\275arxiv\350\256\272\346\226\207\347\277\273\350\257\221\346\221\230\350\246\201.py" @@ -144,11 +144,11 @@ def 下载arxiv论文并翻译摘要(txt, llm_kwargs, plugin_kwargs, chatbot, hi # 尝试导入依赖,如果缺少依赖,则给出安装建议 try: - import pdfminer, bs4 + import bs4 except: report_execption(chatbot, history, a = f"解析项目: {txt}", - b = f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade pdfminer beautifulsoup4```。") + b = f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade beautifulsoup4```。") yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 return diff --git "a/crazy_functions/\344\272\244\344\272\222\345\212\237\350\203\275\345\207\275\346\225\260\346\250\241\346\235\277.py" "b/crazy_functions/\344\272\244\344\272\222\345\212\237\350\203\275\345\207\275\346\225\260\346\250\241\346\235\277.py" new file mode 100644 index 0000000000000000000000000000000000000000..d57fc2b0f0fb604be1dc19f789815eb7833bef7f --- /dev/null +++ "b/crazy_functions/\344\272\244\344\272\222\345\212\237\350\203\275\345\207\275\346\225\260\346\250\241\346\235\277.py" @@ -0,0 +1,63 @@ +from toolbox import CatchException, update_ui +from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive + + +@CatchException +def 交互功能模板函数(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + """ + txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径 + llm_kwargs gpt模型参数, 如温度和top_p等, 一般原样传递下去就行 + plugin_kwargs 插件模型的参数, 如温度和top_p等, 一般原样传递下去就行 + chatbot 聊天显示框的句柄,用于显示给用户 + history 聊天历史,前情提要 + system_prompt 给gpt的静默提醒 + web_port 当前软件运行的端口号 + """ + history = [] # 清空历史,以免输入溢出 + chatbot.append(("这是什么功能?", "交互功能函数模板。在执行完成之后, 可以将自身的状态存储到cookie中, 等待用户的再次调用。")) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + + state = chatbot._cookies.get('plugin_state_0001', None) # 初始化插件状态 + + if state is None: + chatbot._cookies['lock_plugin'] = 'crazy_functions.交互功能函数模板->交互功能模板函数' # 赋予插件锁定 锁定插件回调路径,当下一次用户提交时,会直接转到该函数 + chatbot._cookies['plugin_state_0001'] = 'wait_user_keyword' # 赋予插件状态 + + chatbot.append(("第一次调用:", "请输入关键词, 我将为您查找相关壁纸, 建议使用英文单词, 插件锁定中,请直接提交即可。")) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + return + + if state == 'wait_user_keyword': + chatbot._cookies['lock_plugin'] = None # 解除插件锁定,避免遗忘导致死锁 + chatbot._cookies['plugin_state_0001'] = None # 解除插件状态,避免遗忘导致死锁 + + # 解除插件锁定 + chatbot.append((f"获取关键词:{txt}", "")) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + page_return = get_image_page_by_keyword(txt) + inputs=inputs_show_user=f"Extract all image urls in this html page, pick the first 5 images and show them with markdown format: \n\n {page_return}" + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( + inputs=inputs, inputs_show_user=inputs_show_user, + llm_kwargs=llm_kwargs, chatbot=chatbot, history=[], + sys_prompt="When you want to show an image, use markdown format. e.g. ![image_description](image_url). If there are no image url provided, answer 'no image url provided'" + ) + chatbot[-1] = [chatbot[-1][0], gpt_say] + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + return + + + +# --------------------------------------------------------------------------------- + +def get_image_page_by_keyword(keyword): + import requests + from bs4 import BeautifulSoup + response = requests.get(f'https://wallhaven.cc/search?q={keyword}', timeout=2) + res = "image urls: \n" + for image_element in BeautifulSoup(response.content, 'html.parser').findAll("img"): + try: + res += image_element["data-src"] + res += "\n" + except: + pass + return res diff --git "a/crazy_functions/\345\221\275\344\273\244\350\241\214\345\212\251\346\211\213.py" "b/crazy_functions/\345\221\275\344\273\244\350\241\214\345\212\251\346\211\213.py" new file mode 100644 index 0000000000000000000000000000000000000000..4cbc08471822f51e2b4bc01c8ebfad25c1032f49 --- /dev/null +++ "b/crazy_functions/\345\221\275\344\273\244\350\241\214\345\212\251\346\211\213.py" @@ -0,0 +1,31 @@ +from toolbox import CatchException, update_ui, gen_time_str +from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive +from .crazy_utils import input_clipping +import copy, json + +@CatchException +def 命令行助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + """ + txt 输入栏用户输入的文本, 例如需要翻译的一段话, 再例如一个包含了待处理文件的路径 + llm_kwargs gpt模型参数, 如温度和top_p等, 一般原样传递下去就行 + plugin_kwargs 插件模型的参数, 暂时没有用武之地 + chatbot 聊天显示框的句柄, 用于显示给用户 + history 聊天历史, 前情提要 + system_prompt 给gpt的静默提醒 + web_port 当前软件运行的端口号 + """ + # 清空历史, 以免输入溢出 + history = [] + + # 输入 + i_say = "请写bash命令实现以下功能:" + txt + # 开始 + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( + inputs=i_say, inputs_show_user=txt, + llm_kwargs=llm_kwargs, chatbot=chatbot, history=[], + sys_prompt="你是一个Linux大师级用户。注意,当我要求你写bash命令时,尽可能地仅用一行命令解决我的要求。" + ) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新 + + + diff --git "a/crazy_functions/\345\233\276\347\211\207\347\224\237\346\210\220.py" "b/crazy_functions/\345\233\276\347\211\207\347\224\237\346\210\220.py" index 5bf8bc4ba95864dc53f98b7335e654f58c4fed54..a1cc2441e2d4ed4f461323bec7e617f936dec2c8 100644 --- "a/crazy_functions/\345\233\276\347\211\207\347\224\237\346\210\220.py" +++ "b/crazy_functions/\345\233\276\347\211\207\347\224\237\346\210\220.py" @@ -27,8 +27,10 @@ def gen_image(llm_kwargs, prompt, resolution="256x256"): } response = requests.post(url, headers=headers, json=data, proxies=proxies) print(response.content) - image_url = json.loads(response.content.decode('utf8'))['data'][0]['url'] - + try: + image_url = json.loads(response.content.decode('utf8'))['data'][0]['url'] + except: + raise RuntimeError(response.content.decode()) # 文件保存到本地 r = requests.get(image_url, proxies=proxies) file_path = 'gpt_log/image_gen/' @@ -53,7 +55,7 @@ def 图片生成(prompt, llm_kwargs, plugin_kwargs, chatbot, history, system_pro web_port 当前软件运行的端口号 """ history = [] # 清空历史,以免输入溢出 - chatbot.append(("这是什么功能?", "[Local Message] 生成图像, 请先把模型切换至gpt-xxxx或者api2d-xxxx。如果中文效果不理想, 尝试Prompt。正在处理中 .....")) + chatbot.append(("这是什么功能?", "[Local Message] 生成图像, 请先把模型切换至gpt-*或者api2d-*。如果中文效果不理想, 请尝试英文Prompt。正在处理中 .....")) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新 if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg") resolution = plugin_kwargs.get("advanced_arg", '256x256') diff --git "a/crazy_functions/\345\257\271\350\257\235\345\216\206\345\217\262\345\255\230\346\241\243.py" "b/crazy_functions/\345\257\271\350\257\235\345\216\206\345\217\262\345\255\230\346\241\243.py" index fed0f8f267fbbd9bae39d8691548d7ff325e8dec..a0d0ac8ed99e97813231cbef5d7c2bea6538a5b1 100644 --- "a/crazy_functions/\345\257\271\350\257\235\345\216\206\345\217\262\345\255\230\346\241\243.py" +++ "b/crazy_functions/\345\257\271\350\257\235\345\216\206\345\217\262\345\255\230\346\241\243.py" @@ -12,7 +12,7 @@ def write_chat_to_file(chatbot, history=None, file_name=None): file_name = 'chatGPT对话历史' + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + '.html' os.makedirs('./gpt_log/', exist_ok=True) with open(f'./gpt_log/{file_name}', 'w', encoding='utf8') as f: - from theme import advanced_css + from themes.theme import advanced_css f.write(f'对话历史') for i, contents in enumerate(chatbot): for j, content in enumerate(contents): diff --git "a/crazy_functions/\346\200\273\347\273\223word\346\226\207\346\241\243.py" "b/crazy_functions/\346\200\273\347\273\223word\346\226\207\346\241\243.py" index eada69dc65587782125c0809381260a6bbdce225..5af696075fb6cb4d6bf1a7e1294678cf3dc0f018 100644 --- "a/crazy_functions/\346\200\273\347\273\223word\346\226\207\346\241\243.py" +++ "b/crazy_functions/\346\200\273\347\273\223word\346\226\207\346\241\243.py" @@ -14,17 +14,19 @@ def 解析docx(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot doc = Document(fp) file_content = "\n".join([para.text for para in doc.paragraphs]) else: - import win32com.client - word = win32com.client.Dispatch("Word.Application") - word.visible = False - # 打开文件 - print('fp', os.getcwd()) - doc = word.Documents.Open(os.getcwd() + '/' + fp) - # file_content = doc.Content.Text - doc = word.ActiveDocument - file_content = doc.Range().Text - doc.Close() - word.Quit() + try: + import win32com.client + word = win32com.client.Dispatch("Word.Application") + word.visible = False + # 打开文件 + doc = word.Documents.Open(os.getcwd() + '/' + fp) + # file_content = doc.Content.Text + doc = word.ActiveDocument + file_content = doc.Range().Text + doc.Close() + word.Quit() + except: + raise RuntimeError('请先将.doc文档转换为.docx文档。') print(file_content) # private_upload里面的文件名在解压zip后容易出现乱码(rar和7z格式正常),故可以只分析文章内容,不输入文件名 diff --git "a/crazy_functions/\346\211\271\351\207\217Markdown\347\277\273\350\257\221.py" "b/crazy_functions/\346\211\271\351\207\217Markdown\347\277\273\350\257\221.py" index 19381e5c27fb2aa4728a1b223fb5f86859e49623..ea8dee960b25e37ac061871cfca3592510157ac9 100644 --- "a/crazy_functions/\346\211\271\351\207\217Markdown\347\277\273\350\257\221.py" +++ "b/crazy_functions/\346\211\271\351\207\217Markdown\347\277\273\350\257\221.py" @@ -1,5 +1,7 @@ -from toolbox import update_ui, trimmed_format_exc, gen_time_str -from toolbox import CatchException, report_execption, write_results_to_file +import glob, time, os, re +from toolbox import update_ui, trimmed_format_exc, gen_time_str, disable_auto_promotion +from toolbox import CatchException, report_execption, write_history_to_file +from toolbox import promote_file_to_downloadzone, get_log_folder fast_debug = False class PaperFileGroup(): @@ -42,13 +44,13 @@ class PaperFileGroup(): def write_result(self, language): manifest = [] for path, res in zip(self.file_paths, self.file_result): - with open(path + f'.{gen_time_str()}.{language}.md', 'w', encoding='utf8') as f: - manifest.append(path + f'.{gen_time_str()}.{language}.md') + dst_file = os.path.join(get_log_folder(), f'{gen_time_str()}.md') + with open(dst_file, 'w', encoding='utf8') as f: + manifest.append(dst_file) f.write(res) return manifest def 多文件翻译(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, language='en'): - import time, os, re from .crazy_utils import request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency # <-------- 读取Markdown文件,删除其中的所有注释 ----------> @@ -102,28 +104,38 @@ def 多文件翻译(file_manifest, project_folder, llm_kwargs, plugin_kwargs, ch print(trimmed_format_exc()) # <-------- 整理结果,退出 ----------> - create_report_file_name = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + f"-chatgpt.polish.md" - res = write_results_to_file(gpt_response_collection, file_name=create_report_file_name) + create_report_file_name = gen_time_str() + f"-chatgpt.md" + res = write_history_to_file(gpt_response_collection, file_basename=create_report_file_name) + promote_file_to_downloadzone(res, chatbot=chatbot) history = gpt_response_collection chatbot.append((f"{fp}完成了吗?", res)) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 -def get_files_from_everything(txt): - import glob, os - +def get_files_from_everything(txt, preference=''): + if txt == "": return False, None, None success = True if txt.startswith('http'): - # 网络的远程文件 - txt = txt.replace("https://github.com/", "https://raw.githubusercontent.com/") - txt = txt.replace("/blob/", "/") import requests from toolbox import get_conf proxies, = get_conf('proxies') + # 网络的远程文件 + if preference == 'Github': + print('正在从github下载资源 ...') + if not txt.endswith('.md'): + # Make a request to the GitHub API to retrieve the repository information + url = txt.replace("https://github.com/", "https://api.github.com/repos/") + '/readme' + response = requests.get(url, proxies=proxies) + txt = response.json()['download_url'] + else: + txt = txt.replace("https://github.com/", "https://raw.githubusercontent.com/") + txt = txt.replace("/blob/", "/") + r = requests.get(txt, proxies=proxies) - with open('./gpt_log/temp.md', 'wb+') as f: f.write(r.content) - project_folder = './gpt_log/' - file_manifest = ['./gpt_log/temp.md'] + download_local = f'{get_log_folder(plugin_name="批量Markdown翻译")}/raw-readme-{gen_time_str()}.md' + project_folder = f'{get_log_folder(plugin_name="批量Markdown翻译")}' + with open(download_local, 'wb+') as f: f.write(r.content) + file_manifest = [download_local] elif txt.endswith('.md'): # 直接给定文件 file_manifest = [txt] @@ -145,11 +157,11 @@ def Markdown英译中(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_p "函数插件功能?", "对整个Markdown项目进行翻译。函数插件贡献者: Binary-Husky"]) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + disable_auto_promotion(chatbot) # 尝试导入依赖,如果缺少依赖,则给出安装建议 try: import tiktoken - import glob, os except: report_execption(chatbot, history, a=f"解析项目: {txt}", @@ -158,7 +170,7 @@ def Markdown英译中(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_p return history = [] # 清空历史,以免输入溢出 - success, file_manifest, project_folder = get_files_from_everything(txt) + success, file_manifest, project_folder = get_files_from_everything(txt, preference="Github") if not success: # 什么都没有 @@ -185,11 +197,11 @@ def Markdown中译英(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_p "函数插件功能?", "对整个Markdown项目进行翻译。函数插件贡献者: Binary-Husky"]) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + disable_auto_promotion(chatbot) # 尝试导入依赖,如果缺少依赖,则给出安装建议 try: import tiktoken - import glob, os except: report_execption(chatbot, history, a=f"解析项目: {txt}", @@ -218,11 +230,11 @@ def Markdown翻译指定语言(txt, llm_kwargs, plugin_kwargs, chatbot, history, "函数插件功能?", "对整个Markdown项目进行翻译。函数插件贡献者: Binary-Husky"]) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + disable_auto_promotion(chatbot) # 尝试导入依赖,如果缺少依赖,则给出安装建议 try: import tiktoken - import glob, os except: report_execption(chatbot, history, a=f"解析项目: {txt}", diff --git "a/crazy_functions/\346\211\271\351\207\217\346\200\273\347\273\223PDF\346\226\207\346\241\243.py" "b/crazy_functions/\346\211\271\351\207\217\346\200\273\347\273\223PDF\346\226\207\346\241\243.py" index cbda23b83d759e6a3a4da5847c37ddff662daab2..fc65f5c8e9337c91ae34d6ec1a98ad1accc1ea0c 100644 --- "a/crazy_functions/\346\211\271\351\207\217\346\200\273\347\273\223PDF\346\226\207\346\241\243.py" +++ "b/crazy_functions/\346\211\271\351\207\217\346\200\273\347\273\223PDF\346\226\207\346\241\243.py" @@ -1,121 +1,107 @@ -from toolbox import update_ui +from toolbox import update_ui, promote_file_to_downloadzone, gen_time_str from toolbox import CatchException, report_execption, write_results_to_file -import re -import unicodedata -fast_debug = False from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive +from .crazy_utils import read_and_clean_pdf_text +from .crazy_utils import input_clipping -def is_paragraph_break(match): - """ - 根据给定的匹配结果来判断换行符是否表示段落分隔。 - 如果换行符前为句子结束标志(句号,感叹号,问号),且下一个字符为大写字母,则换行符更有可能表示段落分隔。 - 也可以根据之前的内容长度来判断段落是否已经足够长。 - """ - prev_char, next_char = match.groups() - # 句子结束标志 - sentence_endings = ".!?" - - # 设定一个最小段落长度阈值 - min_paragraph_length = 140 - - if prev_char in sentence_endings and next_char.isupper() and len(match.string[:match.start(1)]) > min_paragraph_length: - return "\n\n" - else: - return " " - -def normalize_text(text): - """ - 通过把连字(ligatures)等文本特殊符号转换为其基本形式来对文本进行归一化处理。 - 例如,将连字 "fi" 转换为 "f" 和 "i"。 - """ - # 对文本进行归一化处理,分解连字 - normalized_text = unicodedata.normalize("NFKD", text) - - # 替换其他特殊字符 - cleaned_text = re.sub(r'[^\x00-\x7F]+', '', normalized_text) - - return cleaned_text - -def clean_text(raw_text): - """ - 对从 PDF 提取出的原始文本进行清洗和格式化处理。 - 1. 对原始文本进行归一化处理。 - 2. 替换跨行的连词 - 3. 根据 heuristic 规则判断换行符是否是段落分隔,并相应地进行替换 - """ - # 对文本进行归一化处理 - normalized_text = normalize_text(raw_text) - - # 替换跨行的连词 - text = re.sub(r'(\w+-\n\w+)', lambda m: m.group(1).replace('-\n', ''), normalized_text) - - # 根据前后相邻字符的特点,找到原文本中的换行符 - newlines = re.compile(r'(\S)\n(\S)') - - # 根据 heuristic 规则,用空格或段落分隔符替换原换行符 - final_text = re.sub(newlines, lambda m: m.group(1) + is_paragraph_break(m) + m.group(2), text) - - return final_text.strip() def 解析PDF(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt): - import time, glob, os, fitz - print('begin analysis on:', file_manifest) - for index, fp in enumerate(file_manifest): - with fitz.open(fp) as doc: - file_content = "" - for page in doc: - file_content += page.get_text() - file_content = clean_text(file_content) - print(file_content) - - prefix = "接下来请你逐文件分析下面的论文文件,概括其内容" if index==0 else "" - i_say = prefix + f'请对下面的文章片段用中文做一个概述,文件名是{os.path.relpath(fp, project_folder)},文章内容是 ```{file_content}```' - i_say_show_user = prefix + f'[{index}/{len(file_manifest)}] 请对下面的文章片段做一个概述: {os.path.abspath(fp)}' - chatbot.append((i_say_show_user, "[Local Message] waiting gpt response.")) - yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 - - if not fast_debug: - msg = '正常' - # ** gpt request ** - gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( - inputs=i_say, - inputs_show_user=i_say_show_user, - llm_kwargs=llm_kwargs, - chatbot=chatbot, - history=[], - sys_prompt="总结文章。" - ) # 带超时倒计时 - - - chatbot[-1] = (i_say_show_user, gpt_say) - history.append(i_say_show_user); history.append(gpt_say) - yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面 - if not fast_debug: time.sleep(2) - - all_file = ', '.join([os.path.relpath(fp, project_folder) for index, fp in enumerate(file_manifest)]) - i_say = f'根据以上你自己的分析,对全文进行概括,用学术性语言写一段中文摘要,然后再写一段英文摘要(包括{all_file})。' - chatbot.append((i_say, "[Local Message] waiting gpt response.")) - yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 - - if not fast_debug: - msg = '正常' - # ** gpt request ** + file_write_buffer = [] + for file_name in file_manifest: + print('begin analysis on:', file_name) + ############################## <第 0 步,切割PDF> ################################## + # 递归地切割PDF文件,每一块(尽量是完整的一个section,比如introduction,experiment等,必要时再进行切割) + # 的长度必须小于 2500 个 Token + file_content, page_one = read_and_clean_pdf_text(file_name) # (尝试)按照章节切割PDF + file_content = file_content.encode('utf-8', 'ignore').decode() # avoid reading non-utf8 chars + page_one = str(page_one).encode('utf-8', 'ignore').decode() # avoid reading non-utf8 chars + + TOKEN_LIMIT_PER_FRAGMENT = 2500 + + from .crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf + from request_llm.bridge_all import model_info + enc = model_info["gpt-3.5-turbo"]['tokenizer'] + def get_token_num(txt): return len(enc.encode(txt, disallowed_special=())) + paper_fragments = breakdown_txt_to_satisfy_token_limit_for_pdf( + txt=file_content, get_token_fn=get_token_num, limit=TOKEN_LIMIT_PER_FRAGMENT) + page_one_fragments = breakdown_txt_to_satisfy_token_limit_for_pdf( + txt=str(page_one), get_token_fn=get_token_num, limit=TOKEN_LIMIT_PER_FRAGMENT//4) + # 为了更好的效果,我们剥离Introduction之后的部分(如果有) + paper_meta = page_one_fragments[0].split('introduction')[0].split('Introduction')[0].split('INTRODUCTION')[0] + + ############################## <第 1 步,从摘要中提取高价值信息,放到history中> ################################## + final_results = [] + final_results.append(paper_meta) + + ############################## <第 2 步,迭代地历遍整个文章,提取精炼信息> ################################## + i_say_show_user = f'首先你在中文语境下通读整篇论文。'; gpt_say = "[Local Message] 收到。" # 用户提示 + chatbot.append([i_say_show_user, gpt_say]); yield from update_ui(chatbot=chatbot, history=[]) # 更新UI + + iteration_results = [] + last_iteration_result = paper_meta # 初始值是摘要 + MAX_WORD_TOTAL = 4096 * 0.7 + n_fragment = len(paper_fragments) + if n_fragment >= 20: print('文章极长,不能达到预期效果') + for i in range(n_fragment): + NUM_OF_WORD = MAX_WORD_TOTAL // n_fragment + i_say = f"Read this section, recapitulate the content of this section with less than {NUM_OF_WORD} Chinese characters: {paper_fragments[i]}" + i_say_show_user = f"[{i+1}/{n_fragment}] Read this section, recapitulate the content of this section with less than {NUM_OF_WORD} Chinese characters: {paper_fragments[i][:200]}" + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(i_say, i_say_show_user, # i_say=真正给chatgpt的提问, i_say_show_user=给用户看的提问 + llm_kwargs, chatbot, + history=["The main idea of the previous section is?", last_iteration_result], # 迭代上一次的结果 + sys_prompt="Extract the main idea of this section with Chinese." # 提示 + ) + iteration_results.append(gpt_say) + last_iteration_result = gpt_say + + ############################## <第 3 步,整理history,提取总结> ################################## + final_results.extend(iteration_results) + final_results.append(f'Please conclude this paper discussed above。') + # This prompt is from https://github.com/kaixindelele/ChatPaper/blob/main/chat_paper.py + NUM_OF_WORD = 1000 + i_say = """ +1. Mark the title of the paper (with Chinese translation) +2. list all the authors' names (use English) +3. mark the first author's affiliation (output Chinese translation only) +4. mark the keywords of this article (use English) +5. link to the paper, Github code link (if available, fill in Github:None if not) +6. summarize according to the following four points.Be sure to use Chinese answers (proper nouns need to be marked in English) + - (1):What is the research background of this article? + - (2):What are the past methods? What are the problems with them? Is the approach well motivated? + - (3):What is the research methodology proposed in this paper? + - (4):On what task and what performance is achieved by the methods in this paper? Can the performance support their goals? +Follow the format of the output that follows: +1. Title: xxx\n\n +2. Authors: xxx\n\n +3. Affiliation: xxx\n\n +4. Keywords: xxx\n\n +5. Urls: xxx or xxx , xxx \n\n +6. Summary: \n\n + - (1):xxx;\n + - (2):xxx;\n + - (3):xxx;\n + - (4):xxx.\n\n +Be sure to use Chinese answers (proper nouns need to be marked in English), statements as concise and academic as possible, +do not have too much repetitive information, numerical values using the original numbers. + """ + # This prompt is from https://github.com/kaixindelele/ChatPaper/blob/main/chat_paper.py + file_write_buffer.extend(final_results) + i_say, final_results = input_clipping(i_say, final_results, max_token_limit=2000) gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( - inputs=i_say, - inputs_show_user=i_say, - llm_kwargs=llm_kwargs, - chatbot=chatbot, - history=history, - sys_prompt="总结文章。" - ) # 带超时倒计时 - - chatbot[-1] = (i_say, gpt_say) - history.append(i_say); history.append(gpt_say) - yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面 - res = write_results_to_file(history) - chatbot.append(("完成了吗?", res)) - yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面 + inputs=i_say, inputs_show_user='开始最终总结', + llm_kwargs=llm_kwargs, chatbot=chatbot, history=final_results, + sys_prompt= f"Extract the main idea of this paper with less than {NUM_OF_WORD} Chinese characters" + ) + final_results.append(gpt_say) + file_write_buffer.extend([i_say, gpt_say]) + ############################## <第 4 步,设置一个token上限> ################################## + _, final_results = input_clipping("", final_results, max_token_limit=3200) + yield from update_ui(chatbot=chatbot, history=final_results) # 注意这里的历史记录被替代了 + + res = write_results_to_file(file_write_buffer, file_name=gen_time_str()) + promote_file_to_downloadzone(res.split('\t')[-1], chatbot=chatbot) + yield from update_ui(chatbot=chatbot, history=final_results) # 刷新界面 @CatchException @@ -151,10 +137,7 @@ def 批量总结PDF文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst return # 搜索需要处理的文件清单 - file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.pdf', recursive=True)] # + \ - # [f for f in glob.glob(f'{project_folder}/**/*.tex', recursive=True)] + \ - # [f for f in glob.glob(f'{project_folder}/**/*.cpp', recursive=True)] + \ - # [f for f in glob.glob(f'{project_folder}/**/*.c', recursive=True)] + file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.pdf', recursive=True)] # 如果没找到任何文件 if len(file_manifest) == 0: diff --git "a/crazy_functions/\346\211\271\351\207\217\347\277\273\350\257\221PDF\346\226\207\346\241\243_\345\244\232\347\272\277\347\250\213.py" "b/crazy_functions/\346\211\271\351\207\217\347\277\273\350\257\221PDF\346\226\207\346\241\243_\345\244\232\347\272\277\347\250\213.py" index 06d8a5a7f4459d9620f33fa2b96e28e8c27abbc7..0adac96638d0e68075a84f630d52bf8eb2ab3867 100644 --- "a/crazy_functions/\346\211\271\351\207\217\347\277\273\350\257\221PDF\346\226\207\346\241\243_\345\244\232\347\272\277\347\250\213.py" +++ "b/crazy_functions/\346\211\271\351\207\217\347\277\273\350\257\221PDF\346\226\207\346\241\243_\345\244\232\347\272\277\347\250\213.py" @@ -1,5 +1,5 @@ from toolbox import CatchException, report_execption, write_results_to_file -from toolbox import update_ui +from toolbox import update_ui, promote_file_to_downloadzone from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive from .crazy_utils import request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency from .crazy_utils import read_and_clean_pdf_text @@ -147,23 +147,14 @@ def 解析PDF(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, print('writing html result failed:', trimmed_format_exc()) # 准备文件的下载 - import shutil for pdf_path in generated_conclusion_files: # 重命名文件 - rename_file = f'./gpt_log/翻译-{os.path.basename(pdf_path)}' - if os.path.exists(rename_file): - os.remove(rename_file) - shutil.copyfile(pdf_path, rename_file) - if os.path.exists(pdf_path): - os.remove(pdf_path) + rename_file = f'翻译-{os.path.basename(pdf_path)}' + promote_file_to_downloadzone(pdf_path, rename_file=rename_file, chatbot=chatbot) for html_path in generated_html_files: # 重命名文件 - rename_file = f'./gpt_log/翻译-{os.path.basename(html_path)}' - if os.path.exists(rename_file): - os.remove(rename_file) - shutil.copyfile(html_path, rename_file) - if os.path.exists(html_path): - os.remove(html_path) + rename_file = f'翻译-{os.path.basename(html_path)}' + promote_file_to_downloadzone(html_path, rename_file=rename_file, chatbot=chatbot) chatbot.append(("给出输出文件清单", str(generated_conclusion_files + generated_html_files))) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 diff --git "a/crazy_functions/\350\231\232\347\251\272\347\273\210\347\253\257.py" "b/crazy_functions/\350\231\232\347\251\272\347\273\210\347\253\257.py" index fe71a46326cf0b8188f8d81fed99d89753b43f94..36667e90d67730d75d0ad17039920b7d535103ff 100644 --- "a/crazy_functions/\350\231\232\347\251\272\347\273\210\347\253\257.py" +++ "b/crazy_functions/\350\231\232\347\251\272\347\273\210\347\253\257.py" @@ -1,87 +1,70 @@ from toolbox import CatchException, update_ui, gen_time_str from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive from .crazy_utils import input_clipping +import copy, json - -prompt = """ -I have to achieve some functionalities by calling one of the functions below. -Your job is to find the correct funtion to use to satisfy my requirement, -and then write python code to call this function with correct parameters. - -These are functions you are allowed to choose from: -1. - 功能描述: 总结音视频内容 - 调用函数: ConcludeAudioContent(txt, llm_kwargs) - 参数说明: - txt: 音频文件的路径 - llm_kwargs: 模型参数, 永远给定None -2. - 功能描述: 将每次对话记录写入Markdown格式的文件中 - 调用函数: WriteMarkdown() -3. - 功能描述: 将指定目录下的PDF文件从英文翻译成中文 - 调用函数: BatchTranslatePDFDocuments_MultiThreaded(txt, llm_kwargs) - 参数说明: - txt: PDF文件所在的路径 - llm_kwargs: 模型参数, 永远给定None -4. - 功能描述: 根据文本使用GPT模型生成相应的图像 - 调用函数: ImageGeneration(txt, llm_kwargs) - 参数说明: - txt: 图像生成所用到的提示文本 - llm_kwargs: 模型参数, 永远给定None -5. - 功能描述: 对输入的word文档进行摘要生成 - 调用函数: SummarizingWordDocuments(input_path, output_path) - 参数说明: - input_path: 待处理的word文档路径 - output_path: 摘要生成后的文档路径 - - -You should always anwser with following format: ----------------- -Code: -``` -class AutoAcademic(object): - def __init__(self): - self.selected_function = "FILL_CORRECT_FUNCTION_HERE" # e.g., "GenerateImage" - self.txt = "FILL_MAIN_PARAMETER_HERE" # e.g., "荷叶上的蜻蜓" - self.llm_kwargs = None -``` -Explanation: -只有GenerateImage和生成图像相关, 因此选择GenerateImage函数。 ----------------- - -Now, this is my requirement: - -""" def get_fn_lib(): return { - "BatchTranslatePDFDocuments_MultiThreaded": ("crazy_functions.批量翻译PDF文档_多线程", "批量翻译PDF文档"), - "SummarizingWordDocuments": ("crazy_functions.总结word文档", "总结word文档"), - "ImageGeneration": ("crazy_functions.图片生成", "图片生成"), - "TranslateMarkdownFromEnglishToChinese": ("crazy_functions.批量Markdown翻译", "Markdown中译英"), - "SummaryAudioVideo": ("crazy_functions.总结音视频", "总结音视频"), + "BatchTranslatePDFDocuments_MultiThreaded": { + "module": "crazy_functions.批量翻译PDF文档_多线程", + "function": "批量翻译PDF文档", + "description": "Translate PDF Documents", + "arg_1_description": "A path containing pdf files.", + }, + "SummarizingWordDocuments": { + "module": "crazy_functions.总结word文档", + "function": "总结word文档", + "description": "Summarize Word Documents", + "arg_1_description": "A path containing Word files.", + }, + "ImageGeneration": { + "module": "crazy_functions.图片生成", + "function": "图片生成", + "description": "Generate a image that satisfies some description.", + "arg_1_description": "Descriptions about the image to be generated.", + }, + "TranslateMarkdownFromEnglishToChinese": { + "module": "crazy_functions.批量Markdown翻译", + "function": "Markdown中译英", + "description": "Translate Markdown Documents from English to Chinese.", + "arg_1_description": "A path containing Markdown files.", + }, + "SummaryAudioVideo": { + "module": "crazy_functions.总结音视频", + "function": "总结音视频", + "description": "Get text from a piece of audio and summarize this audio.", + "arg_1_description": "A path containing audio files.", + }, } +functions = [ + { + "name": k, + "description": v['description'], + "parameters": { + "type": "object", + "properties": { + "plugin_arg_1": { + "type": "string", + "description": v['arg_1_description'], + }, + }, + "required": ["plugin_arg_1"], + }, + } for k, v in get_fn_lib().items() +] + def inspect_dependency(chatbot, history): return True def eval_code(code, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): - import subprocess, sys, os, shutil, importlib - - with open('gpt_log/void_terminal_runtime.py', 'w', encoding='utf8') as f: - f.write(code) - + import importlib try: - AutoAcademic = getattr(importlib.import_module('gpt_log.void_terminal_runtime', 'AutoAcademic'), 'AutoAcademic') - # importlib.reload(AutoAcademic) - auto_dict = AutoAcademic() - selected_function = auto_dict.selected_function - txt = auto_dict.txt - fp, fn = get_fn_lib()[selected_function] + tmp = get_fn_lib()[code['name']] + fp, fn = tmp['module'], tmp['function'] fn_plugin = getattr(importlib.import_module(fp, fn), fn) - yield from fn_plugin(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port) + arg = json.loads(code['arguments'])['plugin_arg_1'] + yield from fn_plugin(arg, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port) except: from toolbox import trimmed_format_exc chatbot.append(["执行错误", f"\n```\n{trimmed_format_exc()}\n```\n"]) @@ -110,22 +93,27 @@ def 终端(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_ history = [] # 基本信息:功能、贡献者 - chatbot.append(["函数插件功能?", "根据自然语言执行插件命令, 作者: binary-husky, 插件初始化中 ..."]) + chatbot.append(["虚空终端插件的功能?", "根据自然语言的描述, 执行任意插件的命令."]) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 - - # # 尝试导入依赖, 如果缺少依赖, 则给出安装建议 - # dep_ok = yield from inspect_dependency(chatbot=chatbot, history=history) # 刷新界面 - # if not dep_ok: return # 输入 - i_say = prompt + txt + i_say = txt # 开始 + llm_kwargs_function_call = copy.deepcopy(llm_kwargs) + llm_kwargs_function_call['llm_model'] = 'gpt-call-fn' # 修改调用函数 gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( inputs=i_say, inputs_show_user=txt, - llm_kwargs=llm_kwargs, chatbot=chatbot, history=[], - sys_prompt="" + llm_kwargs=llm_kwargs_function_call, chatbot=chatbot, history=[], + sys_prompt=functions ) # 将代码转为动画 - code = get_code_block(gpt_say) - yield from eval_code(code, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port) + res = json.loads(gpt_say)['choices'][0] + if res['finish_reason'] == 'function_call': + code = json.loads(gpt_say)['choices'][0] + yield from eval_code(code['message']['function_call'], llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port) + else: + chatbot.append(["无法调用相关功能", res]) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + + diff --git "a/crazy_functions/\350\257\242\351\227\256\345\244\232\344\270\252\345\244\247\350\257\255\350\250\200\346\250\241\345\236\213.py" "b/crazy_functions/\350\257\242\351\227\256\345\244\232\344\270\252\345\244\247\350\257\255\350\250\200\346\250\241\345\236\213.py" index c1e5dadd142de683323463d3df260cbe6eefa6d8..8fdf5915d303a54cc7859e9df77ac9acf5311ced 100644 --- "a/crazy_functions/\350\257\242\351\227\256\345\244\232\344\270\252\345\244\247\350\257\255\350\250\200\346\250\241\345\236\213.py" +++ "b/crazy_functions/\350\257\242\351\227\256\345\244\232\344\270\252\345\244\247\350\257\255\350\250\200\346\250\241\345\236\213.py" @@ -6,7 +6,7 @@ def 同时问询(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt """ txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径 llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行 - plugin_kwargs 插件模型的参数,如温度和top_p等,一般原样传递下去就行 + plugin_kwargs 插件模型的参数,用于灵活调整复杂功能的各种参数 chatbot 聊天显示框的句柄,用于显示给用户 history 聊天历史,前情提要 system_prompt 给gpt的静默提醒 @@ -35,19 +35,21 @@ def 同时问询_指定模型(txt, llm_kwargs, plugin_kwargs, chatbot, history, """ txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径 llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行 - plugin_kwargs 插件模型的参数,如温度和top_p等,一般原样传递下去就行 + plugin_kwargs 插件模型的参数,用于灵活调整复杂功能的各种参数 chatbot 聊天显示框的句柄,用于显示给用户 history 聊天历史,前情提要 system_prompt 给gpt的静默提醒 web_port 当前软件运行的端口号 """ history = [] # 清空历史,以免输入溢出 - chatbot.append((txt, "正在同时咨询ChatGPT和ChatGLM……")) - yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新 if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg") # llm_kwargs['llm_model'] = 'chatglm&gpt-3.5-turbo&api2d-gpt-3.5-turbo' # 支持任意数量的llm接口,用&符号分隔 llm_kwargs['llm_model'] = plugin_kwargs.get("advanced_arg", 'chatglm&gpt-3.5-turbo') # 'chatglm&gpt-3.5-turbo' # 支持任意数量的llm接口,用&符号分隔 + + chatbot.append((txt, f"正在同时咨询{llm_kwargs['llm_model']}")) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新 + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( inputs=txt, inputs_show_user=txt, llm_kwargs=llm_kwargs, chatbot=chatbot, history=history, diff --git "a/crazy_functions/\350\257\255\351\237\263\345\212\251\346\211\213.py" "b/crazy_functions/\350\257\255\351\237\263\345\212\251\346\211\213.py" new file mode 100644 index 0000000000000000000000000000000000000000..6fe1afc0b61a0a09282f8314c5eceeeba5bf328e --- /dev/null +++ "b/crazy_functions/\350\257\255\351\237\263\345\212\251\346\211\213.py" @@ -0,0 +1,195 @@ +from toolbox import update_ui +from toolbox import CatchException, get_conf, markdown_convertion +from crazy_functions.crazy_utils import input_clipping +from request_llm.bridge_all import predict_no_ui_long_connection +import threading, time +import numpy as np +from .live_audio.aliyunASR import AliyunASR +import json + +class WatchDog(): + def __init__(self, timeout, bark_fn, interval=3, msg="") -> None: + self.last_feed = None + self.timeout = timeout + self.bark_fn = bark_fn + self.interval = interval + self.msg = msg + self.kill_dog = False + + def watch(self): + while True: + if self.kill_dog: break + if time.time() - self.last_feed > self.timeout: + if len(self.msg) > 0: print(self.msg) + self.bark_fn() + break + time.sleep(self.interval) + + def begin_watch(self): + self.last_feed = time.time() + th = threading.Thread(target=self.watch) + th.daemon = True + th.start() + + def feed(self): + self.last_feed = time.time() + +def chatbot2history(chatbot): + history = [] + for c in chatbot: + for q in c: + if q not in ["[请讲话]", "[等待GPT响应]", "[正在等您说完问题]"]: + history.append(q.strip('
').strip('
').strip('

').strip('

')) + return history + +class AsyncGptTask(): + def __init__(self) -> None: + self.observe_future = [] + self.observe_future_chatbot_index = [] + + def gpt_thread_worker(self, i_say, llm_kwargs, history, sys_prompt, observe_window, index): + try: + MAX_TOKEN_ALLO = 2560 + i_say, history = input_clipping(i_say, history, max_token_limit=MAX_TOKEN_ALLO) + gpt_say_partial = predict_no_ui_long_connection(inputs=i_say, llm_kwargs=llm_kwargs, history=history, sys_prompt=sys_prompt, + observe_window=observe_window[index], console_slience=True) + except ConnectionAbortedError as token_exceed_err: + print('至少一个线程任务Token溢出而失败', e) + except Exception as e: + print('至少一个线程任务意外失败', e) + + def add_async_gpt_task(self, i_say, chatbot_index, llm_kwargs, history, system_prompt): + self.observe_future.append([""]) + self.observe_future_chatbot_index.append(chatbot_index) + cur_index = len(self.observe_future)-1 + th_new = threading.Thread(target=self.gpt_thread_worker, args=(i_say, llm_kwargs, history, system_prompt, self.observe_future, cur_index)) + th_new.daemon = True + th_new.start() + + def update_chatbot(self, chatbot): + for of, ofci in zip(self.observe_future, self.observe_future_chatbot_index): + try: + chatbot[ofci] = list(chatbot[ofci]) + chatbot[ofci][1] = markdown_convertion(of[0]) + except: + self.observe_future = [] + self.observe_future_chatbot_index = [] + return chatbot + +class InterviewAssistant(AliyunASR): + def __init__(self): + self.capture_interval = 0.5 # second + self.stop = False + self.parsed_text = "" + self.parsed_sentence = "" + self.buffered_sentence = "" + self.event_on_result_chg = threading.Event() + self.event_on_entence_end = threading.Event() + self.event_on_commit_question = threading.Event() + + def __del__(self): + self.stop = True + self.stop_msg = "" + self.commit_wd.kill_dog = True + self.plugin_wd.kill_dog = True + + def init(self, chatbot): + # 初始化音频采集线程 + self.captured_audio = np.array([]) + self.keep_latest_n_second = 10 + self.commit_after_pause_n_second = 2.0 + self.ready_audio_flagment = None + self.stop = False + self.plugin_wd = WatchDog(timeout=5, bark_fn=self.__del__, msg="程序终止") + self.aut = threading.Thread(target=self.audio_convertion_thread, args=(chatbot._cookies['uuid'],)) + self.aut.daemon = True + self.aut.start() + # th2 = threading.Thread(target=self.audio2txt_thread, args=(chatbot._cookies['uuid'],)) + # th2.daemon = True + # th2.start() + + def no_audio_for_a_while(self): + if len(self.buffered_sentence) < 7: # 如果一句话小于7个字,暂不提交 + self.commit_wd.begin_watch() + else: + self.event_on_commit_question.set() + + def begin(self, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt): + # main plugin function + self.init(chatbot) + chatbot.append(["[请讲话]", "[正在等您说完问题]"]) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + self.plugin_wd.begin_watch() + self.agt = AsyncGptTask() + self.commit_wd = WatchDog(timeout=self.commit_after_pause_n_second, bark_fn=self.no_audio_for_a_while, interval=0.2) + self.commit_wd.begin_watch() + + while not self.stop: + self.event_on_result_chg.wait(timeout=0.25) # run once every 0.25 second + chatbot = self.agt.update_chatbot(chatbot) # 将子线程的gpt结果写入chatbot + history = chatbot2history(chatbot) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + self.plugin_wd.feed() + + if self.event_on_result_chg.is_set(): + # update audio decode result + self.event_on_result_chg.clear() + chatbot[-1] = list(chatbot[-1]) + chatbot[-1][0] = self.buffered_sentence + self.parsed_text + history = chatbot2history(chatbot) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + self.commit_wd.feed() + + if self.event_on_entence_end.is_set(): + # called when a sentence has ended + self.event_on_entence_end.clear() + self.parsed_text = self.parsed_sentence + self.buffered_sentence += self.parsed_sentence + + if self.event_on_commit_question.is_set(): + # called when a question should be commited + self.event_on_commit_question.clear() + if len(self.buffered_sentence) == 0: raise RuntimeError + + self.commit_wd.begin_watch() + chatbot[-1] = list(chatbot[-1]) + chatbot[-1] = [self.buffered_sentence, "[等待GPT响应]"] + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + # add gpt task 创建子线程请求gpt,避免线程阻塞 + history = chatbot2history(chatbot) + self.agt.add_async_gpt_task(self.buffered_sentence, len(chatbot)-1, llm_kwargs, history, system_prompt) + + self.buffered_sentence = "" + chatbot.append(["[请讲话]", "[正在等您说完问题]"]) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + + if len(self.stop_msg) != 0: + raise RuntimeError(self.stop_msg) + + + +@CatchException +def 语音助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + # pip install -U openai-whisper + chatbot.append(["对话助手函数插件:使用时,双手离开鼠标键盘吧", "音频助手, 正在听您讲话(点击“停止”键可终止程序)..."]) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + + # 尝试导入依赖,如果缺少依赖,则给出安装建议 + try: + import nls + from scipy import io + except: + chatbot.append(["导入依赖失败", "使用该模块需要额外依赖, 安装方法:```pip install --upgrade aliyun-python-sdk-core==2.13.3 pyOpenSSL scipy git+https://github.com/aliyun/alibabacloud-nls-python-sdk.git```"]) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + return + + APPKEY = get_conf('ALIYUN_APPKEY') + if APPKEY == "": + chatbot.append(["导入依赖失败", "没有阿里云语音识别APPKEY和TOKEN, 详情见https://help.aliyun.com/document_detail/450255.html"]) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + return + + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + ia = InterviewAssistant() + yield from ia.begin(llm_kwargs, plugin_kwargs, chatbot, history, system_prompt) + diff --git "a/crazy_functions/\350\260\267\346\255\214\346\243\200\347\264\242\345\260\217\345\212\251\346\211\213.py" "b/crazy_functions/\350\260\267\346\255\214\346\243\200\347\264\242\345\260\217\345\212\251\346\211\213.py" index 5a5dd93f6f9ca8c47c0de193b95e863e9bb82087..46c10de4f7148e2fa5de13b93183ab119f1af165 100644 --- "a/crazy_functions/\350\260\267\346\255\214\346\243\200\347\264\242\345\260\217\345\212\251\346\211\213.py" +++ "b/crazy_functions/\350\260\267\346\255\214\346\243\200\347\264\242\345\260\217\345\212\251\346\211\213.py" @@ -104,7 +104,7 @@ def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst meta_paper_info_list = meta_paper_info_list[batchsize:] chatbot.append(["状态?", - "已经全部完成,您可以试试让AI写一个Related Works,例如您可以继续输入Write an academic \"Related Works\" section about \"你搜索的研究领域\" for me."]) + "已经全部完成,您可以试试让AI写一个Related Works,例如您可以继续输入Write a \"Related Works\" section about \"你搜索的研究领域\" for me."]) msg = '正常' yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面 res = write_results_to_file(history) diff --git "a/crazy_functions/\350\276\205\345\212\251\345\233\236\347\255\224.py" "b/crazy_functions/\350\276\205\345\212\251\345\233\236\347\255\224.py" new file mode 100644 index 0000000000000000000000000000000000000000..b635f88b3183bbd310eca6449cd9e10c75ca7ca7 --- /dev/null +++ "b/crazy_functions/\350\276\205\345\212\251\345\233\236\347\255\224.py" @@ -0,0 +1,28 @@ +# encoding: utf-8 +# @Time : 2023/4/19 +# @Author : Spike +# @Descr : +from toolbox import update_ui +from toolbox import CatchException, report_execption, write_results_to_file +from crazy_functions.crazy_utils import request_gpt_model_in_new_thread_with_ui_alive + + +@CatchException +def 猜你想问(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + if txt: + show_say = txt + prompt = txt+'\n回答完问题后,再列出用户可能提出的三个问题。' + else: + prompt = history[-1]+"\n分析上述回答,再列出用户可能提出的三个问题。" + show_say = '分析上述回答,再列出用户可能提出的三个问题。' + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( + inputs=prompt, + inputs_show_user=show_say, + llm_kwargs=llm_kwargs, + chatbot=chatbot, + history=history, + sys_prompt=system_prompt + ) + chatbot[-1] = (show_say, gpt_say) + history.extend([show_say, gpt_say]) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 \ No newline at end of file diff --git "a/crazy_functions/\351\253\230\347\272\247\345\212\237\350\203\275\345\207\275\346\225\260\346\250\241\346\235\277.py" "b/crazy_functions/\351\253\230\347\272\247\345\212\237\350\203\275\345\207\275\346\225\260\346\250\241\346\235\277.py" index 73ae45f240f346fec6bb1ec87a2616055e481827..abcbbc6631fa4abdd0577c5a06bd12c5c2504b09 100644 --- "a/crazy_functions/\351\253\230\347\272\247\345\212\237\350\203\275\345\207\275\346\225\260\346\250\241\346\235\277.py" +++ "b/crazy_functions/\351\253\230\347\272\247\345\212\237\350\203\275\345\207\275\346\225\260\346\250\241\346\235\277.py" @@ -1,13 +1,12 @@ from toolbox import CatchException, update_ui from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive -import datetime, re - +import datetime @CatchException def 高阶功能模板函数(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): """ txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径 llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行 - plugin_kwargs 插件模型的参数,暂时没有用武之地 + plugin_kwargs 插件模型的参数,用于灵活调整复杂功能的各种参数 chatbot 聊天显示框的句柄,用于显示给用户 history 聊天历史,前情提要 system_prompt 给gpt的静默提醒 @@ -19,34 +18,12 @@ def 高阶功能模板函数(txt, llm_kwargs, plugin_kwargs, chatbot, history, s for i in range(5): currentMonth = (datetime.date.today() + datetime.timedelta(days=i)).month currentDay = (datetime.date.today() + datetime.timedelta(days=i)).day - i_say = f'历史中哪些事件发生在{currentMonth}月{currentDay}日?用中文列举两条,然后分别给出描述事件的两个英文单词。' + '当你给出关键词时,使用以下json格式:{"KeyWords":[EnglishKeyWord1,EnglishKeyWord2]}。' + i_say = f'历史中哪些事件发生在{currentMonth}月{currentDay}日?列举两条并发送相关图片。发送图片时,请使用Markdown,将Unsplash API中的PUT_YOUR_QUERY_HERE替换成描述该事件的一个最重要的单词。' gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( inputs=i_say, inputs_show_user=i_say, llm_kwargs=llm_kwargs, chatbot=chatbot, history=[], - sys_prompt='输出格式示例:1908年,美国消防救援事业发展的“美国消防协会”成立。关键词:{"KeyWords":["Fire","American"]}。' + sys_prompt="当你想发送一张照片时,请使用Markdown, 并且不要有反斜线, 不要用代码块。使用 Unsplash API (https://source.unsplash.com/1280x720/? < PUT_YOUR_QUERY_HERE >)。" ) - gpt_say = get_images(gpt_say) chatbot[-1] = (i_say, gpt_say) history.append(i_say);history.append(gpt_say) - yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新 - - -def get_images(gpt_say): - def get_image_by_keyword(keyword): - import requests - from bs4 import BeautifulSoup - response = requests.get(f'https://wallhaven.cc/search?q={keyword}', timeout=2) - for image_element in BeautifulSoup(response.content, 'html.parser').findAll("img"): - if "data-src" in image_element: break - return image_element["data-src"] - - for keywords in re.findall('{"KeyWords":\[(.*?)\]}', gpt_say): - keywords = [n.strip('"') for n in keywords.split(',')] - try: - description = keywords[0] - url = get_image_by_keyword(keywords[0]) - img_tag = f"\n\n![{description}]({url})" - gpt_say += img_tag - except: - continue - return gpt_say \ No newline at end of file + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 0a0dcda9545e170a67e0cc76ccf8ec4a48614fca..874bdc2162c04e13ce1b612a3cff3b099fb3823c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,7 @@ version: '3' services: gpt_academic_nolocalllms: - image: ghcr.io/binary-husky/gpt_academic_nolocal:master + image: ghcr.io/binary-husky/gpt_academic_nolocal:master # (Auto Built by Dockerfile: docs/GithubAction+NoLocal) environment: # 请查阅 `config.py` 以查看所有的配置信息 API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ' @@ -33,7 +33,7 @@ services: version: '3' services: gpt_academic_with_chatglm: - image: ghcr.io/binary-husky/gpt_academic_chatglm_moss:master + image: ghcr.io/binary-husky/gpt_academic_chatglm_moss:master # (Auto Built by Dockerfile: docs/Dockerfile+ChatGLM) environment: # 请查阅 `config.py` 以查看所有的配置信息 API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,fkxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ' @@ -63,7 +63,7 @@ services: version: '3' services: gpt_academic_with_rwkv: - image: fuqingxu/gpt_academic:jittorllms # [option 2] 如果需要运行ChatGLM本地模型 + image: ghcr.io/binary-husky/gpt_academic_jittorllms:master environment: # 请查阅 `config.py` 以查看所有的配置信息 API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,fkxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ' @@ -85,33 +85,18 @@ services: # 与宿主的网络融合 network_mode: "host" - # 使用代理网络拉取最新代码 - # command: > - # bash -c " truncate -s -1 /etc/proxychains.conf && - # echo \"socks5 127.0.0.1 10880\" >> /etc/proxychains.conf && - # echo '[gpt-academic] 正在从github拉取最新代码...' && - # proxychains git pull && - # echo '[jittorllms] 正在从github拉取最新代码...' && - # proxychains git --git-dir=request_llm/jittorllms/.git --work-tree=request_llm/jittorllms pull --force && - # python3 -u main.py" - # 不使用代理网络拉取最新代码 command: > - bash -c " echo '[gpt-academic] 正在从github拉取最新代码...' && - git pull && - pip install -r requirements.txt && - echo '[jittorllms] 正在从github拉取最新代码...' && - git --git-dir=request_llm/jittorllms/.git --work-tree=request_llm/jittorllms pull --force && - python3 -u main.py" + python3 -u main.py ## =================================================== -## 【方案四】 chatgpt + Latex +## 【方案四】 ChatGPT + Latex ## =================================================== version: '3' services: gpt_academic_with_latex: - image: ghcr.io/binary-husky/gpt_academic_with_latex:master + image: ghcr.io/binary-husky/gpt_academic_with_latex:master # (Auto Built by Dockerfile: docs/GithubAction+NoLocal+Latex) environment: # 请查阅 `config.py` 以查看所有的配置信息 API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ' @@ -130,3 +115,36 @@ services: command: > bash -c "python3 -u main.py" + +## =================================================== +## 【方案五】 ChatGPT + 语音助手 (请先阅读 docs/use_audio.md) +## =================================================== +version: '3' +services: + gpt_academic_with_audio: + image: ghcr.io/binary-husky/gpt_academic_audio_assistant:master + environment: + # 请查阅 `config.py` 以查看所有的配置信息 + API_KEY: ' fk195831-IdP0Pb3W6DCMUIbQwVX6MsSiyxwqybyS ' + USE_PROXY: ' False ' + proxies: ' None ' + LLM_MODEL: ' gpt-3.5-turbo ' + AVAIL_LLM_MODELS: ' ["gpt-3.5-turbo", "gpt-4"] ' + ENABLE_AUDIO: ' True ' + LOCAL_MODEL_DEVICE: ' cuda ' + DEFAULT_WORKER_NUM: ' 20 ' + WEB_PORT: ' 12343 ' + ADD_WAIFU: ' True ' + THEME: ' Chuanhu-Small-and-Beautiful ' + ALIYUN_APPKEY: ' RoP1ZrM84DnAFkZK ' + ALIYUN_TOKEN: ' f37f30e0f9934c34a992f6f64f7eba4f ' + # (无需填写) ALIYUN_ACCESSKEY: ' LTAI5q6BrFUzoRXVGUWnekh1 ' + # (无需填写) ALIYUN_SECRET: ' eHmI20AVWIaQZ0CiTD2bGQVsaP9i68 ' + + # 与宿主的网络融合 + network_mode: "host" + + # 不使用代理网络拉取最新代码 + command: > + bash -c "python3 -u main.py" + diff --git a/docs/Dockerfile+ChatGLM b/docs/Dockerfile+ChatGLM index 9e6db27b721a9265be8afd1a79dc74d2bb523959..75c1fa7479de516655f0e1166642f0eb37e1b1a9 100644 --- a/docs/Dockerfile+ChatGLM +++ b/docs/Dockerfile+ChatGLM @@ -26,8 +26,8 @@ RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.8 RUN $useProxyNetwork python3 -m pip install torch --extra-index-url https://download.pytorch.org/whl/cu113 # 下载分支 WORKDIR /gpt -RUN $useProxyNetwork git clone https://github.com/binary-husky/chatgpt_academic.git -WORKDIR /gpt/chatgpt_academic +RUN $useProxyNetwork git clone https://github.com/binary-husky/gpt_academic.git +WORKDIR /gpt/gpt_academic RUN $useProxyNetwork python3 -m pip install -r requirements.txt RUN $useProxyNetwork python3 -m pip install -r request_llm/requirements_chatglm.txt RUN $useProxyNetwork python3 -m pip install -r request_llm/requirements_newbing.txt diff --git a/docs/Dockerfile+JittorLLM b/docs/Dockerfile+JittorLLM index 62dae31ccf9b38256a8bf6d1b9ce3fba64c015c1..ea53402926b8a9529f3224d8e9b65c0a9476b5a5 100644 --- a/docs/Dockerfile+JittorLLM +++ b/docs/Dockerfile+JittorLLM @@ -26,8 +26,8 @@ RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.8 RUN $useProxyNetwork python3 -m pip install torch --extra-index-url https://download.pytorch.org/whl/cu113 # 下载分支 WORKDIR /gpt -RUN $useProxyNetwork git clone https://github.com/binary-husky/chatgpt_academic.git -b jittor -WORKDIR /gpt/chatgpt_academic +RUN $useProxyNetwork git clone https://github.com/binary-husky/gpt_academic.git +WORKDIR /gpt/gpt_academic RUN $useProxyNetwork python3 -m pip install -r requirements.txt RUN $useProxyNetwork python3 -m pip install -r request_llm/requirements_chatglm.txt RUN $useProxyNetwork python3 -m pip install -r request_llm/requirements_newbing.txt diff --git a/docs/GithubAction+ChatGLM+Moss b/docs/GithubAction+ChatGLM+Moss index ece19d64b055c90f0ea2b3275f99b8331cd364e9..ba3deae99671bd964550ec9923e42e4358b3c03e 100644 --- a/docs/GithubAction+ChatGLM+Moss +++ b/docs/GithubAction+ChatGLM+Moss @@ -13,8 +13,8 @@ RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.8 RUN python3 -m pip install torch --extra-index-url https://download.pytorch.org/whl/cu113 # 下载分支 WORKDIR /gpt -RUN git clone https://github.com/binary-husky/chatgpt_academic.git -WORKDIR /gpt/chatgpt_academic +RUN git clone --depth=1 https://github.com/binary-husky/gpt_academic.git +WORKDIR /gpt/gpt_academic RUN git clone https://github.com/OpenLMLab/MOSS.git request_llm/moss RUN python3 -m pip install -r requirements.txt RUN python3 -m pip install -r request_llm/requirements_moss.txt diff --git a/docs/GithubAction+JittorLLMs b/docs/GithubAction+JittorLLMs index 4f0e66ba86521f92caaaab34655a26bf75382fee..dc883bcfcc393dcafed8010e15894e53f4b6cfc2 100644 --- a/docs/GithubAction+JittorLLMs +++ b/docs/GithubAction+JittorLLMs @@ -13,8 +13,8 @@ RUN python3 -m pip install torch --extra-index-url https://download.pytorch.org/ # 下载分支 WORKDIR /gpt -RUN git clone https://github.com/binary-husky/chatgpt_academic.git -b jittor -WORKDIR /gpt/chatgpt_academic +RUN git clone --depth=1 https://github.com/binary-husky/gpt_academic.git +WORKDIR /gpt/gpt_academic RUN python3 -m pip install -r requirements.txt RUN python3 -m pip install -r request_llm/requirements_chatglm.txt RUN python3 -m pip install -r request_llm/requirements_newbing.txt diff --git a/docs/GithubAction+NoLocal+AudioAssistant b/docs/GithubAction+NoLocal+AudioAssistant new file mode 100644 index 0000000000000000000000000000000000000000..9ea1ea54636d698a452be7de98d5413551ee39af --- /dev/null +++ b/docs/GithubAction+NoLocal+AudioAssistant @@ -0,0 +1,22 @@ +# 此Dockerfile适用于“无本地模型”的环境构建,如果需要使用chatglm等本地模型,请参考 docs/Dockerfile+ChatGLM +# 如何构建: 先修改 `config.py`, 然后 docker build -t gpt-academic-nolocal -f docs/Dockerfile+NoLocal . +# 如何运行: docker run --rm -it --net=host gpt-academic-nolocal +FROM python:3.11 + +# 指定路径 +WORKDIR /gpt + +# 装载项目文件 +COPY . . + +# 安装依赖 +RUN pip3 install -r requirements.txt + +# 安装语音插件的额外依赖 +RUN pip3 install pyOpenSSL scipy git+https://github.com/aliyun/alibabacloud-nls-python-sdk.git + +# 可选步骤,用于预热模块 +RUN python3 -c 'from check_proxy import warm_up_modules; warm_up_modules()' + +# 启动 +CMD ["python3", "-u", "main.py"] diff --git a/docs/README.md.German.md b/docs/README.md.German.md index 0fe200cf690b6c9ff699e2e19bb53fd3cd60c201..d514de30f54bd8931568c029a3bbd3aa3eacdbb1 100644 --- a/docs/README.md.German.md +++ b/docs/README.md.German.md @@ -15,7 +15,7 @@ Um dieses Projekt in eine beliebige Sprache mit GPT zu übersetzen, lesen Sie `m > > 1. Beachten Sie bitte, dass nur Funktionserweiterungen (Schaltflächen) mit **roter Farbe** Dateien lesen können und einige Erweiterungen im **Dropdown-Menü** des Erweiterungsbereichs zu finden sind. Außerdem begrüßen wir jede neue Funktionserweiterung mit **höchster Priorität** und bearbeiten sie. > -> 2. Die Funktionalität jeder Datei in diesem Projekt wird in der Selbstanalyse [`self_analysis.md`](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) detailliert beschrieben. Mit der Weiterentwicklung der Versionen können Sie jederzeit die zugehörigen Funktions-Erweiterungen aufrufen, um durch Aufruf von GPT einen Selbstanalysebericht des Projekts zu erstellen. Häufig gestellte Fragen finden Sie in der [`Wiki`](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Installationsanweisungen](#Installation). +> 2. Die Funktionalität jeder Datei in diesem Projekt wird in der Selbstanalyse [`self_analysis.md`](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) detailliert beschrieben. Mit der Weiterentwicklung der Versionen können Sie jederzeit die zugehörigen Funktions-Erweiterungen aufrufen, um durch Aufruf von GPT einen Selbstanalysebericht des Projekts zu erstellen. Häufig gestellte Fragen finden Sie in der [`Wiki`](https://github.com/binary-husky/gpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Installationsanweisungen](#Installation). > > 3. Dieses Projekt ist kompatibel und fördert die Verwendung von inländischen Sprachmodellen wie ChatGLM und RWKV, Pangu, etc. Es unterstützt das Vorhandensein mehrerer api-keys, die in der Konfigurationsdatei wie folgt angegeben werden können: `API_KEY="openai-key1,openai-key2,api2d-key3"`. Wenn ein `API_KEY` temporär geändert werden muss, geben Sie den temporären `API_KEY` im Eingabebereich ein und drücken Sie dann die Eingabetaste, um ihn zu übernehmen.Funktion | Beschreibung --- | --- @@ -23,13 +23,13 @@ Ein-Klick-Polieren | Unterstützt ein-Klick-Polieren und ein-Klick-Suche nach gr Ein-Klick Chinesisch-Englisch Übersetzung | Ein-Klick Chinesisch-Englisch Übersetzung Ein-Klick-Code-Erklärung | Zeigt Code, erklärt Code, erzeugt Code und fügt Kommentare zum Code hinzu [Benutzerdefinierte Tastenkombinationen](https://www.bilibili.com/video/BV14s4y1E7jN) | Unterstützt benutzerdefinierte Tastenkombinationen -Modulare Gestaltung | Unterstützt leistungsstarke individuelle [Funktions-Plugins](https://github.com/binary-husky/chatgpt_academic/tree/master/crazy_functions). Plugins unterstützen [Hot-Updates](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) -[Selbstprogramm-Analyse](https://www.bilibili.com/video/BV1cj411A7VW) | [Funktions-Plugin] [Ein-Klick Verstehen](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) der Quellcode dieses Projekts +Modulare Gestaltung | Unterstützt leistungsstarke individuelle [Funktions-Plugins](https://github.com/binary-husky/gpt_academic/tree/master/crazy_functions). Plugins unterstützen [Hot-Updates](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) +[Selbstprogramm-Analyse](https://www.bilibili.com/video/BV1cj411A7VW) | [Funktions-Plugin] [Ein-Klick Verstehen](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) der Quellcode dieses Projekts [Programmanalyse](https://www.bilibili.com/video/BV1cj411A7VW) | [Funktions-Plugin] Ein-Klick-Analyse des Projektbaums anderer Python/C/C++/Java/Lua/...-Projekte Lesen von Papieren, [Übersetzen](https://www.bilibili.com/video/BV1KT411x7Wn) von Papieren | [Funktions-Plugin] Ein-Klick Erklärung des gesamten LaTeX/PDF-Artikels und Erstellung einer Zusammenfassung LaTeX-Volltext-Übersetzung und [Polieren](https://www.bilibili.com/video/BV1FT411H7c5/) | [Funktions-Plugin] Ein-Klick-Übersetzung oder-Polieren des LaTeX-Artikels Bulk-Kommentargenerierung | [Funktions-Plugin] Ein-Klick Massenerstellung von Funktionskommentaren -Markdown [Chinesisch-Englisch Übersetzung](https://www.bilibili.com/video/BV1yo4y157jV/) | [Funktions-Plugin] Haben Sie die [README](https://github.com/binary-husky/chatgpt_academic/blob/master/docs/README_EN.md) in den oben genannten 5 Sprachen gesehen? +Markdown [Chinesisch-Englisch Übersetzung](https://www.bilibili.com/video/BV1yo4y157jV/) | [Funktions-Plugin] Haben Sie die [README](https://github.com/binary-husky/gpt_academic/blob/master/docs/README_EN.md) in den oben genannten 5 Sprachen gesehen? Analyse-Berichtserstellung von chat | [Funktions-Plugin] Automatische Zusammenfassung nach der Ausführung [Funktion zur vollständigen Übersetzung von PDF-Artikeln](https://www.bilibili.com/video/BV1KT411x7Wn) | [Funktions-Plugin] Extrahiert Titel und Zusammenfassung der PDF-Artikel und übersetzt den gesamten Text (mehrere Threads) [Arxiv-Assistent](https://www.bilibili.com/video/BV1LM4y1279X) | [Funktions-Plugin] Geben Sie die Arxiv-Artikel-URL ein und klicken Sie auf Eine-Klick-Übersetzung-Zusammenfassung + PDF-Download @@ -37,7 +37,7 @@ Analyse-Berichtserstellung von chat | [Funktions-Plugin] Automatische Zusammenfa Internet-Informationen Aggregation + GPT | [Funktions-Plugin] Lassen Sie GPT eine Frage beantworten, indem es [zuerst Informationen aus dem Internet](https://www.bilibili.com/video/BV1om4y127ck/) sammelt und so die Informationen nie veralten Anzeige von Formeln / Bildern / Tabellen | Zeigt Formeln in beiden Formen, [TeX-Format und gerendeter Form](https://user-images.githubusercontent.com/96192199/230598842-1d7fcddd-815d-40ee-af60-baf488a199df.png), unterstützt Formeln und Code-Highlights Unterstützung von PlugIns mit mehreren Threads | Unterstützt den Aufruf mehrerer Threads in Chatgpt, um Text oder Programme [Batch zu verarbeiten](https://www.bilibili.com/video/BV1FT411H7c5/) -Starten Sie das dunkle Gradio-[Thema](https://github.com/binary-husky/chatgpt_academic/issues/173) | Fügen Sie ```/?__theme=dark``` an das Ende der Browser-URL an, um das dunkle Thema zu aktivieren +Starten Sie das dunkle Gradio-[Thema](https://github.com/binary-husky/gpt_academic/issues/173) | Fügen Sie ```/?__theme=dark``` an das Ende der Browser-URL an, um das dunkle Thema zu aktivieren [Unterstützung für mehrere LLM-Modelle](https://www.bilibili.com/video/BV1wT411p7yf), [API2D](https://api2d.com/) Interface-Unterstützung | Das Gefühl, gleichzeitig von GPT3.5, GPT4, [Tshinghua ChatGLM](https://github.com/THUDM/ChatGLM-6B), [Fudan MOSS](https://github.com/OpenLMLab/MOSS) bedient zu werden, muss toll sein, oder? Zugriff auf weitere LLM-Modelle, Unterstützung von [huggingface deployment](https://huggingface.co/spaces/qingxu98/gpt-academic) | Hinzufügen der Newbing-Schnittstelle (neues Bing), Einführung der Unterstützung von [Jittorllms](https://github.com/Jittor/JittorLLMs) der Tsinghua-Universität, [LLaMA](https://github.com/facebookresearch/llama), [RWKV](https://github.com/BlinkDL/ChatRWKV) und [Pangu alpha](https://openi.org.cn/pangu/) Weitere neue Funktionen (wie Bildgenerierung) …… | Siehe Ende dieses Dokuments …… @@ -76,8 +76,8 @@ Weitere neue Funktionen (wie Bildgenerierung) …… | Siehe Ende dieses Dokumen 1. Download the project ```sh -git clone https://github.com/binary-husky/chatgpt_academic.git -cd chatgpt_academic +git clone https://github.com/binary-husky/gpt_academic.git +cd gpt_academic ``` 2. Configure API_KEY @@ -133,8 +133,8 @@ python main.py 1. Only ChatGPT (Recommended for most people) ``` sh -git clone https://github.com/binary-husky/chatgpt_academic.git # Download the project -cd chatgpt_academic # Enter the path +git clone https://github.com/binary-husky/gpt_academic.git # Download the project +cd gpt_academic # Enter the path nano config.py # Edit config.py with any text editor, Configure "Proxy","API_KEY"and"WEB_PORT" (e.g 50923) etc. docker build -t gpt-academic . # Install @@ -164,10 +164,10 @@ docker-compose up Configure API_URL_REDIRECT according to the instructions in `config.py`. 2. Remote cloud server deployment (requires cloud server knowledge and experience) -Please visit [Deployment wiki-1](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) +Please visit [Deployment wiki-1](https://github.com/binary-husky/gpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) 3. Using WSL 2 (Windows subsystem for Linux) -Please visit [Deployment wiki-2](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) +Please visit [Deployment wiki-2](https://github.com/binary-husky/gpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) 4. How to run at a secondary URL (such as `http://localhost/subpath`) Please visit [FastAPI operating instructions](docs/WithFastapi.md) @@ -199,7 +199,7 @@ For example Write powerful function plugins to perform any task you want and can't think of. The difficulty of plugin writing and debugging is very low in this project. As long as you have a certain knowledge of Python, you can implement your own plugin functions by imitating the template we provided. -For more information, please refer to the [Function Plugin Guide](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). +For more information, please refer to the [Function Plugin Guide](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). --- # Latest Update diff --git a/docs/README.md.Italian.md b/docs/README.md.Italian.md index 301ce697dca4a150eb522b8522aa9bc3352ff4dd..76efe1857bc08b435583f7e3274a5d838eb48dba 100644 --- a/docs/README.md.Italian.md +++ b/docs/README.md.Italian.md @@ -13,7 +13,7 @@ Per tradurre questo progetto in qualsiasi lingua con GPT, leggere e eseguire [`m > > 1. Si prega di notare che solo i plugin (pulsanti) contrassegnati in **rosso** supportano la lettura di file, alcuni plugin sono posizionati nel **menu a discesa** nella zona dei plugin. Accettiamo e gestiamo PR per qualsiasi nuovo plugin con **massima priorità**! > -> 2. Le funzionalità di ogni file di questo progetto sono descritte dettagliatamente nella propria analisi di autotraduzione [`self_analysis.md`](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A). Con l'iterazione delle versioni, è possibile fare clic sui plugin funzionali correlati in qualsiasi momento per richiamare GPT e generare nuovamente il rapporto di analisi automatica del progetto. Le domande frequenti sono riassunte nella [`wiki`](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Metodo di installazione] (#installazione). +> 2. Le funzionalità di ogni file di questo progetto sono descritte dettagliatamente nella propria analisi di autotraduzione [`self_analysis.md`](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A). Con l'iterazione delle versioni, è possibile fare clic sui plugin funzionali correlati in qualsiasi momento per richiamare GPT e generare nuovamente il rapporto di analisi automatica del progetto. Le domande frequenti sono riassunte nella [`wiki`](https://github.com/binary-husky/gpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Metodo di installazione] (#installazione). > > 3. Questo progetto è compatibile e incoraggia l'utilizzo di grandi modelli di linguaggio di produzione nazionale come chatglm, RWKV, Pangu ecc. Supporta la coesistenza di più api-key e può essere compilato nel file di configurazione come `API_KEY="openai-key1,openai-key2,api2d-key3"`. Per sostituire temporaneamente `API_KEY`, inserire `API_KEY` temporaneo nell'area di input e premere Invio per renderlo effettivo. @@ -25,13 +25,13 @@ Correzione immediata | Supporta correzione immediata e ricerca degli errori di g Traduzione cinese-inglese immediata | Traduzione cinese-inglese immediata con un solo clic Spiegazione del codice immediata | Visualizzazione del codice, spiegazione del codice, generazione del codice, annotazione del codice con un solo clic [Scorciatoie personalizzate](https://www.bilibili.com/video/BV14s4y1E7jN) | Supporta scorciatoie personalizzate -Design modularizzato | Supporta potenti [plugin di funzioni](https://github.com/binary-husky/chatgpt_academic/tree/master/crazy_functions) personalizzati, i plugin supportano l'[aggiornamento in tempo reale](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) -[Auto-profiling del programma](https://www.bilibili.com/video/BV1cj411A7VW) | [Plugin di funzioni] [Comprensione immediata](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) del codice sorgente di questo progetto +Design modularizzato | Supporta potenti [plugin di funzioni](https://github.com/binary-husky/gpt_academic/tree/master/crazy_functions) personalizzati, i plugin supportano l'[aggiornamento in tempo reale](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) +[Auto-profiling del programma](https://www.bilibili.com/video/BV1cj411A7VW) | [Plugin di funzioni] [Comprensione immediata](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) del codice sorgente di questo progetto [Analisi del programma](https://www.bilibili.com/video/BV1cj411A7VW) | [Plugin di funzioni] Un clic può analizzare l'albero di altri progetti Python/C/C++/Java/Lua/... Lettura del documento, [traduzione](https://www.bilibili.com/video/BV1KT411x7Wn) del documento | [Plugin di funzioni] La lettura immediata dell'intero documento latex/pdf di un documento e la generazione di un riassunto Traduzione completa di un documento Latex, [correzione immediata](https://www.bilibili.com/video/BV1FT411H7c5/) | [Plugin di funzioni] Una traduzione o correzione immediata di un documento Latex Generazione di annotazioni in batch | [Plugin di funzioni] Generazione automatica delle annotazioni di funzione con un solo clic -[Traduzione cinese-inglese di Markdown](https://www.bilibili.com/video/BV1yo4y157jV/) | [Plugin di funzioni] Hai letto il [README](https://github.com/binary-husky/chatgpt_academic/blob/master/docs/README_EN.md) delle cinque lingue sopra? +[Traduzione cinese-inglese di Markdown](https://www.bilibili.com/video/BV1yo4y157jV/) | [Plugin di funzioni] Hai letto il [README](https://github.com/binary-husky/gpt_academic/blob/master/docs/README_EN.md) delle cinque lingue sopra? Generazione di report di analisi di chat | [Plugin di funzioni] Generazione automatica di un rapporto di sintesi dopo l'esecuzione [Funzione di traduzione di tutto il documento PDF](https://www.bilibili.com/video/BV1KT411x7Wn) | [Plugin di funzioni] Estrarre il titolo e il sommario dell'articolo PDF + tradurre l'intero testo (multithreading) [Assistente di Arxiv](https://www.bilibili.com/video/BV1LM4y1279X) | [Plugin di funzioni] Inserire l'URL dell'articolo di Arxiv e tradurre il sommario con un clic + scaricare il PDF @@ -39,7 +39,7 @@ Generazione di report di analisi di chat | [Plugin di funzioni] Generazione auto Aggregazione delle informazioni su Internet + GPT | [Plugin di funzioni] Fai in modo che GPT rilevi le informazioni su Internet prima di rispondere alle domande, senza mai diventare obsolete Visualizzazione di formule/img/tabelle | È possibile visualizzare un'equazione in forma [tex e render](https://user-images.githubusercontent.com/96192199/230598842-1d7fcddd-815d-40ee-af60-baf488a199df.png) contemporaneamente, supporta equazioni e evidenziazione del codice Supporto per plugin di funzioni multithreading | Supporto per chiamata multithreaded di chatgpt, elaborazione con un clic di grandi quantità di testo o di un programma -Avvia il tema di gradio [scuro](https://github.com/binary-husky/chatgpt_academic/issues/173) | Aggiungere ```/?__theme=dark``` dopo l'URL del browser per passare a un tema scuro +Avvia il tema di gradio [scuro](https://github.com/binary-husky/gpt_academic/issues/173) | Aggiungere ```/?__theme=dark``` dopo l'URL del browser per passare a un tema scuro Supporto per maggiori modelli LLM, supporto API2D | Sentirsi serviti simultaneamente da GPT3.5, GPT4, [Tsinghua ChatGLM](https://github.com/THUDM/ChatGLM-6B), [Fudan MOSS](https://github.com/OpenLMLab/MOSS) deve essere una grande sensazione, giusto? Ulteriori modelli LLM supportat,i supporto per l'implementazione di Huggingface | Aggiunta di un'interfaccia Newbing (Nuovo Bing), introdotta la compatibilità con Tsinghua [Jittorllms](https://github.com/Jittor/JittorLLMs), [LLaMA](https://github.com/facebookresearch/llama), [RWKV](https://github.com/BlinkDL/ChatRWKV) e [PanGu-α](https://openi.org.cn/pangu/) Ulteriori dimostrazioni di nuove funzionalità (generazione di immagini, ecc.)... | Vedere la fine di questo documento... @@ -82,8 +82,8 @@ Ulteriori dimostrazioni di nuove funzionalità (generazione di immagini, ecc.).. 1. Scarica il progetto ```sh -git clone https://github.com/binary-husky/chatgpt_academic.git -cd chatgpt_academic +git clone https://github.com/binary-husky/gpt_academic.git +cd gpt_academic ``` 2. Configura API_KEY @@ -139,8 +139,8 @@ python main.py 1. Solo ChatGPT (consigliato per la maggior parte delle persone) ``` sh -git clone https://github.com/binary-husky/chatgpt_academic.git # scarica il progetto -cd chatgpt_academic # entra nel percorso +git clone https://github.com/binary-husky/gpt_academic.git # scarica il progetto +cd gpt_academic # entra nel percorso nano config.py # con un qualsiasi editor di testo, modifica config.py configurando "Proxy", "API_KEY" e "WEB_PORT" (ad esempio 50923) docker build -t gpt-academic . # installa @@ -171,10 +171,10 @@ docker-compose up Configura API_URL_REDIRECT seguendo le istruzioni nel file `config.py`. 2. Distribuzione su un server cloud remoto (richiede conoscenze ed esperienza di server cloud) -Si prega di visitare [wiki di distribuzione-1] (https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) +Si prega di visitare [wiki di distribuzione-1] (https://github.com/binary-husky/gpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) 3. Utilizzo di WSL2 (Windows Subsystem for Linux) -Si prega di visitare [wiki di distribuzione-2] (https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) +Si prega di visitare [wiki di distribuzione-2] (https://github.com/binary-husky/gpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) 4. Come far funzionare ChatGPT all'interno di un sottodominio (ad es. `http://localhost/subpath`) Si prega di visitare [Istruzioni per l'esecuzione con FastAPI] (docs/WithFastapi.md) @@ -206,7 +206,7 @@ ad esempio 2. Plugin di funzione personalizzati Scrivi plugin di funzione personalizzati e esegui tutte le attività che desideri o non hai mai pensato di fare. -La difficoltà di scrittura e debug dei plugin del nostro progetto è molto bassa. Se si dispone di una certa conoscenza di base di Python, è possibile realizzare la propria funzione del plugin seguendo il nostro modello. Per maggiori dettagli, consultare la [guida al plugin per funzioni](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). +La difficoltà di scrittura e debug dei plugin del nostro progetto è molto bassa. Se si dispone di una certa conoscenza di base di Python, è possibile realizzare la propria funzione del plugin seguendo il nostro modello. Per maggiori dettagli, consultare la [guida al plugin per funzioni](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). --- # Ultimo aggiornamento diff --git a/docs/README.md.Korean.md b/docs/README.md.Korean.md index f15d477ae03f9e04f5ba41ec62fdedca4361869c..61b8e4a051b455514748363e62ac04fd27bd10e3 100644 --- a/docs/README.md.Korean.md +++ b/docs/README.md.Korean.md @@ -13,7 +13,7 @@ GPT를 이용하여 프로젝트를 임의의 언어로 번역하려면 [`multi_ > > 1. 파일을 읽기 위해 **빨간색**으로 표시된 기능 플러그인 (버튼) 만 지원됩니다. 일부 플러그인은 플러그인 영역의 **드롭다운 메뉴**에 있습니다. 또한 새로운 플러그인은 **가장 높은 우선순위**로 환영하며 처리합니다! > -> 2. 이 프로젝트의 각 파일의 기능을 [`self_analysis.md`](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)에서 자세히 설명합니다. 버전이 업데이트 됨에 따라 관련된 기능 플러그인을 클릭하고 GPT를 호출하여 프로젝트의 자체 분석 보고서를 다시 생성할 수도 있습니다. 자주 묻는 질문은 [`위키`](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)에서 볼 수 있습니다. [설치 방법](#installation). +> 2. 이 프로젝트의 각 파일의 기능을 [`self_analysis.md`](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)에서 자세히 설명합니다. 버전이 업데이트 됨에 따라 관련된 기능 플러그인을 클릭하고 GPT를 호출하여 프로젝트의 자체 분석 보고서를 다시 생성할 수도 있습니다. 자주 묻는 질문은 [`위키`](https://github.com/binary-husky/gpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)에서 볼 수 있습니다. [설치 방법](#installation). > > 3. 이 프로젝트는 국내 언어 모델 chatglm과 RWKV, 판고 등의 시도와 호환 가능합니다. 여러 개의 api-key를 지원하며 설정 파일에 "API_KEY="openai-key1,openai-key2,api2d-key3""와 같이 작성할 수 있습니다. `API_KEY`를 임시로 변경해야하는 경우 입력 영역에 임시 `API_KEY`를 입력 한 후 엔터 키를 누르면 즉시 적용됩니다. @@ -25,13 +25,13 @@ GPT를 이용하여 프로젝트를 임의의 언어로 번역하려면 [`multi_ 한-영 키워드 | 한-영 키워드 지원 코드 설명 | 코드 표시, 코드 설명, 코드 생성, 코드에 주석 추가 [사용자 정의 바로 가기 키](https://www.bilibili.com/video/BV14s4y1E7jN) | 사용자 정의 바로 가기 키 지원 -모듈식 설계 | 강력한[함수 플러그인](https://github.com/binary-husky/chatgpt_academic/tree/master/crazy_functions) 지원, 플러그인이 [램 업데이트](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97)를 지원합니다. +모듈식 설계 | 강력한[함수 플러그인](https://github.com/binary-husky/gpt_academic/tree/master/crazy_functions) 지원, 플러그인이 [램 업데이트](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97)를 지원합니다. [자체 프로그램 분석](https://www.bilibili.com/video/BV1cj411A7VW) | [함수 플러그인] [원 키 우드] 프로젝트 소스 코드의 내용을 이해하는 기능을 제공 [프로그램 분석](https://www.bilibili.com/video/BV1cj411A7VW) | [함수 플러그인] 프로젝트 트리를 분석할 수 있습니다 (Python/C/C++/Java/Lua/...) 논문 읽기, 번역 | [함수 플러그인] LaTex/PDF 논문의 전문을 읽고 요약을 생성합니다. LaTeX 텍스트[번역](https://www.bilibili.com/video/BV1nk4y1Y7Js/), [원 키워드](https://www.bilibili.com/video/BV1FT411H7c5/) | [함수 플러그인] LaTeX 논문의 번역 또는 개량을 위해 일련의 모드를 번역할 수 있습니다. 대량의 주석 생성 | [함수 플러그인] 함수 코멘트를 대량으로 생성할 수 있습니다. -Markdown 한-영 번역 | [함수 플러그인] 위의 5 종 언어의 [README](https://github.com/binary-husky/chatgpt_academic/blob/master/docs/README_EN.md)를 볼 수 있습니다. +Markdown 한-영 번역 | [함수 플러그인] 위의 5 종 언어의 [README](https://github.com/binary-husky/gpt_academic/blob/master/docs/README_EN.md)를 볼 수 있습니다. chat 분석 보고서 생성 | [함수 플러그인] 수행 후 요약 보고서를 자동으로 생성합니다. [PDF 논문 번역](https://www.bilibili.com/video/BV1KT411x7Wn) | [함수 플러그인] PDF 논문이 제목 및 요약을 추출한 후 번역됩니다. (멀티 스레드) [Arxiv 도우미](https://www.bilibili.com/video/BV1LM4y1279X) | [함수 플러그인] Arxiv 논문 URL을 입력하면 요약을 번역하고 PDF를 다운로드 할 수 있습니다. @@ -73,8 +73,8 @@ LLM 모델 추가 및[huggingface 배치](https://huggingface.co/spaces/qingxu98 1. 프로젝트 다운로드 ```sh -git clone https://github.com/binary-husky/chatgpt_academic.git -cd chatgpt_academic +git clone https://github.com/binary-husky/gpt_academic.git +cd gpt_academic ``` 2. API_KEY 구성 @@ -134,8 +134,8 @@ python main.py 1. ChatGPT 만 (대부분의 사람들이 선택하는 것을 권장합니다.) ``` sh -git clone https://github.com/binary-husky/chatgpt_academic.git # 다운로드 -cd chatgpt_academic # 경로 이동 +git clone https://github.com/binary-husky/gpt_academic.git # 다운로드 +cd gpt_academic # 경로 이동 nano config.py # 아무 텍스트 에디터로 config.py를 열고 "Proxy","API_KEY","WEB_PORT" (예 : 50923) 등을 구성합니다. docker build -t gpt-academic . # 설치 @@ -165,10 +165,10 @@ docker-compose up API_URL_REDIRECT를 `config.py`에 따라 구성하면됩니다. 2. 원격 클라우드 서버 배치 (클라우드 서버 지식과 경험이 필요합니다.) -[배치위키-1](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97)에 방문하십시오. +[배치위키-1](https://github.com/binary-husky/gpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97)에 방문하십시오. 3. WSL2 사용 (Windows Subsystem for Linux 하위 시스템) -[배치 위키-2](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2)에 방문하십시오. +[배치 위키-2](https://github.com/binary-husky/gpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2)에 방문하십시오. 4. 2 차 URL (예 : `http : //localhost/subpath`)에서 실행하는 방법 [FastAPI 실행 설명서] (docs / WithFastapi.md)를 참조하십시오. @@ -197,7 +197,7 @@ docker-compose.yml을 읽은 후 지시 사항에 따라 작업하십시오. 2. 사용자 지정 함수 플러그인 강력한 함수 플러그인을 작성하여 원하는 작업을 수행하십시오. -이 프로젝트의 플러그인 작성 및 디버깅 난이도는 매우 낮으며, 일부 파이썬 기본 지식만 있으면 제공된 템플릿을 모방하여 플러그인 기능을 구현할 수 있습니다. 자세한 내용은 [함수 플러그인 가이드]를 참조하십시오. (https://github.com/binary -husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E 4%BB%B6%E6%8C%87%E5%8D%97). +이 프로젝트의 플러그인 작성 및 디버깅 난이도는 매우 낮으며, 일부 파이썬 기본 지식만 있으면 제공된 템플릿을 모방하여 플러그인 기능을 구현할 수 있습니다. 자세한 내용은 [함수 플러그인 가이드]를 참조하십시오. (https://github.com/binary -husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E 4%BB%B6%E6%8C%87%E5%8D%97). --- # 최신 업데이트 ## 새로운 기능 동향1. 대화 저장 기능. diff --git a/docs/README.md.Portuguese.md b/docs/README.md.Portuguese.md index 98f6054303cb88d429aacc9edec1e39f4dd7af95..2347d5a74f7c7c90b670fd0368aa447ee2660113 100644 --- a/docs/README.md.Portuguese.md +++ b/docs/README.md.Portuguese.md @@ -14,7 +14,7 @@ Para traduzir este projeto para qualquer idioma com o GPT, leia e execute [`mult > > 1. Por favor, preste atenção que somente os plugins de funções (botões) com a cor **vermelha** podem ler arquivos. Alguns plugins estão localizados no **menu suspenso** na área de plugins. Além disso, nós damos as boas-vindas com a **maior prioridade** e gerenciamos quaisquer novos plugins PR! > -> 2. As funções de cada arquivo neste projeto são detalhadas em [`self_analysis.md`](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A), auto-análises do projeto geradas pelo GPT também estão podem ser chamadas a qualquer momento ao clicar nos plugins relacionados. As perguntas frequentes estão resumidas no [`wiki`](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Instruções de Instalação](#installation). +> 2. As funções de cada arquivo neste projeto são detalhadas em [`self_analysis.md`](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A), auto-análises do projeto geradas pelo GPT também estão podem ser chamadas a qualquer momento ao clicar nos plugins relacionados. As perguntas frequentes estão resumidas no [`wiki`](https://github.com/binary-husky/gpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Instruções de Instalação](#installation). > > 3. Este projeto é compatível com e incentiva o uso de modelos de linguagem nacionais, como chatglm e RWKV, Pangolin, etc. Suporta a coexistência de várias chaves de API e pode ser preenchido no arquivo de configuração como `API_KEY="openai-key1,openai-key2,api2d-key3"`. Quando precisar alterar temporariamente o `API_KEY`, basta digitar o `API_KEY` temporário na área de entrada e pressionar Enter para que ele entre em vigor. @@ -26,8 +26,8 @@ Um clique de polimento | Suporte a um clique polimento, um clique encontrar erro Tradução chinês-inglês de um clique | Tradução chinês-inglês de um clique Explicação de código de um único clique | Exibir código, explicar código, gerar código, adicionar comentários ao código [Teclas de atalho personalizadas](https://www.bilibili.com/video/BV14s4y1E7jN) | Suporte a atalhos personalizados -Projeto modular | Suporte para poderosos plugins[de função personalizada](https://github.com/binary-husky/chatgpt_academic/tree/master/crazy_functions), os plugins suportam[hot-reload](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) -[Análise automática do programa](https://www.bilibili.com/video/BV1cj411A7VW) | [Plugin de função][um clique para entender](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) o código-fonte do projeto +Projeto modular | Suporte para poderosos plugins[de função personalizada](https://github.com/binary-husky/gpt_academic/tree/master/crazy_functions), os plugins suportam[hot-reload](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) +[Análise automática do programa](https://www.bilibili.com/video/BV1cj411A7VW) | [Plugin de função][um clique para entender](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) o código-fonte do projeto [Análise do programa](https://www.bilibili.com/video/BV1cj411A7VW) | [Plugin de função] Um clique pode analisar a árvore de projetos do Python/C/C++/Java/Lua/... Leitura de artigos, [tradução](https://www.bilibili.com/video/BV1KT411x7Wn) de artigos | [Plugin de função] um clique para interpretar o resumo de artigos LaTeX/PDF e gerar resumo Tradução completa LATEX, polimento|[Plugin de função] Uma clique para traduzir ou polir um artigo LATEX @@ -91,8 +91,8 @@ Mais recursos novos mostrados (geração de imagens, etc.) ... | Consulte o fina 1. Download the project ```sh -git clone https://github.com/binary-husky/chatgpt_academic.git -cd chatgpt_academic +git clone https://github.com/binary-husky/gpt_academic.git +cd gpt_academic ``` 2. Configure the API KEY @@ -149,8 +149,8 @@ python main.py 1. Apenas ChatGPT (recomendado para a maioria das pessoas) ``` sh -git clone https://github.com/binary-husky/chatgpt_academic.git # Baixar o projeto -cd chatgpt_academic # Entrar no caminho +git clone https://github.com/binary-husky/gpt_academic.git # Baixar o projeto +cd gpt_academic # Entrar no caminho nano config.py # Editar config.py com qualquer editor de texto configurando "Proxy", "API_KEY" e "WEB_PORT" (por exemplo, 50923), etc. docker build -t gpt-academic . # Instale @@ -180,10 +180,10 @@ docker-compose up Basta configurar o API_URL_REDIRECT de acordo com as instruções em `config.py`. 2. Implantação em servidores em nuvem remotos (requer conhecimento e experiência de servidores em nuvem) -Acesse [Wiki de implementação remota do servidor em nuvem](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) +Acesse [Wiki de implementação remota do servidor em nuvem](https://github.com/binary-husky/gpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) 3. Usando a WSL2 (sub-sistema do Windows para Linux) -Acesse [Wiki da implantação da WSL2](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) +Acesse [Wiki da implantação da WSL2](https://github.com/binary-husky/gpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) 4. Como executar em um subdiretório (ex. `http://localhost/subpath`) Acesse [Instruções de execução FastAPI](docs/WithFastapi.md) @@ -214,7 +214,7 @@ Por exemplo, Escreva plug-ins de função poderosos para executar tarefas que você deseja e não pensava possível. A dificuldade geral de escrever e depurar plug-ins neste projeto é baixa e, se você tem algum conhecimento básico de python, pode implementar suas próprias funções sobre o modelo que fornecemos. -Para mais detalhes, consulte o [Guia do plug-in de função.](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). +Para mais detalhes, consulte o [Guia do plug-in de função.](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). --- # Última atualização diff --git a/docs/README_EN.md b/docs/README_EN.md index 65af23d7b2c989107a664d7bd3ef88cf7e55c7f7..02b8588c38f1b52228840b882e509064daecb3f0 100644 --- a/docs/README_EN.md +++ b/docs/README_EN.md @@ -14,7 +14,7 @@ To translate this project to arbitary language with GPT, read and run [`multi_la > Note: > > 1. Please note that only the function plugins (buttons) marked in **red** support reading files. Some plugins are in the **drop-down menu** in the plugin area. We welcome and process any new plugins with the **highest priority**! -> 2. The function of each file in this project is detailed in the self-translation analysis [`self_analysis.md`](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A). With version iteration, you can also click on related function plugins at any time to call GPT to regenerate the project's self-analysis report. Common questions are summarized in the [`wiki`](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Installation method](#installation). +> 2. The function of each file in this project is detailed in the self-translation analysis [`self_analysis.md`](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A). With version iteration, you can also click on related function plugins at any time to call GPT to regenerate the project's self-analysis report. Common questions are summarized in the [`wiki`](https://github.com/binary-husky/gpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Installation method](#installation). > 3. This project is compatible with and encourages trying domestic large language models such as chatglm, RWKV, Pangu, etc. Multiple API keys are supported and can be filled in the configuration file like `API_KEY="openai-key1,openai-key2,api2d-key3"`. When temporarily changing `API_KEY`, enter the temporary `API_KEY` in the input area and press enter to submit, which will take effect.
@@ -25,13 +25,13 @@ One-click polishing | Supports one-click polishing and one-click searching for g One-click Chinese-English translation | One-click Chinese-English translation. One-click code interpretation | Displays, explains, generates, and adds comments to code. [Custom shortcut keys](https://www.bilibili.com/video/BV14s4y1E7jN) | Supports custom shortcut keys. -Modular design | Supports custom powerful [function plug-ins](https://github.com/binary-husky/chatgpt_academic/tree/master/crazy_functions), plug-ins support [hot update](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). -[Self-program profiling](https://www.bilibili.com/video/BV1cj411A7VW) | [Function plug-in] [One-click understanding](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) of the source code of this project +Modular design | Supports custom powerful [function plug-ins](https://github.com/binary-husky/gpt_academic/tree/master/crazy_functions), plug-ins support [hot update](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). +[Self-program profiling](https://www.bilibili.com/video/BV1cj411A7VW) | [Function plug-in] [One-click understanding](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) of the source code of this project [Program profiling](https://www.bilibili.com/video/BV1cj411A7VW) | [Function plug-in] One-click profiling of other project trees in Python/C/C++/Java/Lua/... Reading papers, [translating](https://www.bilibili.com/video/BV1KT411x7Wn) papers | [Function Plug-in] One-click interpretation of latex/pdf full-text papers and generation of abstracts. Latex full-text [translation](https://www.bilibili.com/video/BV1nk4y1Y7Js/), [polishing](https://www.bilibili.com/video/BV1FT411H7c5/) | [Function plug-in] One-click translation or polishing of latex papers. Batch annotation generation | [Function plug-in] One-click batch generation of function annotations. -Markdown [Chinese-English translation](https://www.bilibili.com/video/BV1yo4y157jV/) | [Function plug-in] Have you seen the [README](https://github.com/binary-husky/chatgpt_academic/blob/master/docs/README_EN.md) in the five languages above? +Markdown [Chinese-English translation](https://www.bilibili.com/video/BV1yo4y157jV/) | [Function plug-in] Have you seen the [README](https://github.com/binary-husky/gpt_academic/blob/master/docs/README_EN.md) in the five languages above? Chat analysis report generation | [Function plug-in] Automatically generate summary reports after running. [PDF full-text translation function](https://www.bilibili.com/video/BV1KT411x7Wn) | [Function plug-in] PDF paper extract title & summary + translate full text (multi-threaded) [Arxiv Assistant](https://www.bilibili.com/video/BV1LM4y1279X) | [Function plug-in] Enter the arxiv article url and you can translate abstracts and download PDFs with one click. @@ -39,7 +39,7 @@ Chat analysis report generation | [Function plug-in] Automatically generate summ Internet information aggregation+GPT | [Function plug-in] One-click [let GPT get information from the Internet first](https://www.bilibili.com/video/BV1om4y127ck), then answer questions, and let the information never be outdated. Formula/image/table display | Can display formulas in both [tex form and render form](https://user-images.githubusercontent.com/96192199/230598842-1d7fcddd-815d-40ee-af60-baf488a199df.png), support formulas and code highlighting. Multi-threaded function plug-in support | Supports multi-threaded calling of chatgpt, and can process [massive text](https://www.bilibili.com/video/BV1FT411H7c5/) or programs with one click. -Start Dark Gradio [theme](https://github.com/binary-husky/chatgpt_academic/issues/173) | Add ```/?__theme=dark``` after the browser URL to switch to the dark theme. +Start Dark Gradio [theme](https://github.com/binary-husky/gpt_academic/issues/173) | Add ```/?__theme=dark``` after the browser URL to switch to the dark theme. [Multiple LLM models](https://www.bilibili.com/video/BV1wT411p7yf) support, [API2D](https://api2d.com/) interface support | The feeling of being served by GPT3.5, GPT4, [Tsinghua ChatGLM](https://github.com/THUDM/ChatGLM-6B), and [Fudan MOSS](https://github.com/OpenLMLab/MOSS) at the same time must be great, right? More LLM model access, support [huggingface deployment](https://huggingface.co/spaces/qingxu98/gpt-academic) | Add Newbing interface (New Bing), introduce Tsinghua [Jittorllms](https://github.com/Jittor/JittorLLMs) to support [LLaMA](https://github.com/facebookresearch/llama), [RWKV](https://github.com/BlinkDL/ChatRWKV) and [Panguα](https://openi.org.cn/pangu/) More new feature displays (image generation, etc.)…… | See the end of this document for more... @@ -79,8 +79,8 @@ More new feature displays (image generation, etc.)…… | See the end of this d 1. Download the project ```sh -git clone https://github.com/binary-husky/chatgpt_academic.git -cd chatgpt_academic +git clone https://github.com/binary-husky/gpt_academic.git +cd gpt_academic ``` 2. Configure the API_KEY @@ -136,8 +136,8 @@ python main.py 1. ChatGPT Only (Recommended for Most People) ``` sh -git clone https://github.com/binary-husky/chatgpt_academic.git # Download project -cd chatgpt_academic # Enter path +git clone https://github.com/binary-husky/gpt_academic.git # Download project +cd gpt_academic # Enter path nano config.py # Edit config.py with any text editor, configure "Proxy", "API_KEY" and "WEB_PORT" (e.g. 50923), etc. docker build -t gpt-academic . # Install @@ -167,10 +167,10 @@ docker-compose up Configure API_URL_REDIRECT according to the instructions in 'config.py'. 2. Deploy to a Remote Server (Requires Knowledge and Experience with Cloud Servers) -Please visit [Deployment Wiki-1](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) +Please visit [Deployment Wiki-1](https://github.com/binary-husky/gpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) 3. Using WSL2 (Windows Subsystem for Linux) -Please visit [Deployment Wiki-2](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) +Please visit [Deployment Wiki-2](https://github.com/binary-husky/gpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) 4. How to Run Under a Subdomain (e.g. `http://localhost/subpath`) Please visit [FastAPI Running Instructions](docs/WithFastapi.md) @@ -202,7 +202,7 @@ For example, Write powerful function plugins to perform any task you can think of, even those you cannot think of. The difficulty of plugin writing and debugging in this project is very low. As long as you have a certain knowledge of Python, you can implement your own plug-in functions based on the template we provide. -For details, please refer to the [Function Plugin Guide](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). +For details, please refer to the [Function Plugin Guide](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). --- # Latest Update diff --git a/docs/README_FR.md b/docs/README_FR.md index 3d96849740374357056fba1d0370167e9182fe71..af3bb42c7904361631ba0dff72e841a13047731b 100644 --- a/docs/README_FR.md +++ b/docs/README_FR.md @@ -16,7 +16,7 @@ Pour traduire ce projet dans une langue arbitraire avec GPT, lisez et exécutez > > 1. Veuillez noter que seuls les plugins de fonctions (boutons) **en rouge** prennent en charge la lecture de fichiers. Certains plugins se trouvent dans le **menu déroulant** de la zone de plugins. De plus, nous accueillons et traitons les nouvelles pull requests pour les plugins avec **la plus haute priorité**! > -> 2. Les fonctions de chaque fichier de ce projet sont expliquées en détail dans l'auto-analyse [`self_analysis.md`](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A). Avec l'itération des versions, vous pouvez également cliquer sur les plugins de fonctions pertinents et appeler GPT pour régénérer le rapport d'auto-analyse du projet à tout moment. Les FAQ sont résumées dans [le wiki](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Méthode d'installation](#installation). +> 2. Les fonctions de chaque fichier de ce projet sont expliquées en détail dans l'auto-analyse [`self_analysis.md`](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A). Avec l'itération des versions, vous pouvez également cliquer sur les plugins de fonctions pertinents et appeler GPT pour régénérer le rapport d'auto-analyse du projet à tout moment. Les FAQ sont résumées dans [le wiki](https://github.com/binary-husky/gpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Méthode d'installation](#installation). > > 3. Ce projet est compatible avec et encourage l'utilisation de grands modèles de langage nationaux tels que chatglm, RWKV, Pangu, etc. La coexistence de plusieurs clés API est prise en charge et peut être remplie dans le fichier de configuration, tel que `API_KEY="openai-key1,openai-key2,api2d-key3"`. Lorsque vous souhaitez remplacer temporairement `API_KEY`, saisissez temporairement `API_KEY` dans la zone de saisie, puis appuyez sur Entrée pour soumettre et activer. @@ -28,13 +28,13 @@ Révision en un clic | prend en charge la révision en un clic et la recherche d Traduction chinois-anglais en un clic | Traduction chinois-anglais en un clic Explication de code en un clic | Affichage, explication, génération et ajout de commentaires de code [Raccourcis personnalisés](https://www.bilibili.com/video/BV14s4y1E7jN) | prend en charge les raccourcis personnalisés -Conception modulaire | prend en charge de puissants plugins de fonction personnalisée, les plugins prennent en charge la [mise à jour à chaud](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) -[Autoscanner](https://www.bilibili.com/video/BV1cj411A7VW) | [Plug-in de fonction] [Compréhension instantanée](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) du code source de ce projet +Conception modulaire | prend en charge de puissants plugins de fonction personnalisée, les plugins prennent en charge la [mise à jour à chaud](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) +[Autoscanner](https://www.bilibili.com/video/BV1cj411A7VW) | [Plug-in de fonction] [Compréhension instantanée](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A) du code source de ce projet [Analyse de programme](https://www.bilibili.com/video/BV1cj411A7VW) | [Plug-in de fonction] Analyse en un clic de la structure d'autres projets Python / C / C ++ / Java / Lua / ... Lecture d'articles, [traduction](https://www.bilibili.com/video/BV1KT411x7Wn) d'articles | [Plug-in de fonction] Compréhension instantanée de l'article latex / pdf complet et génération de résumés [Traduction](https://www.bilibili.com/video/BV1nk4y1Y7Js/) et [révision](https://www.bilibili.com/video/BV1FT411H7c5/) complets en latex | [Plug-in de fonction] traduction ou révision en un clic d'articles en latex Génération de commentaires en masse | [Plug-in de fonction] Génération en un clic de commentaires de fonction en masse -Traduction [chinois-anglais](https://www.bilibili.com/video/BV1yo4y157jV/) en Markdown | [Plug-in de fonction] avez-vous vu la [README](https://github.com/binary-husky/chatgpt_academic/blob/master/docs/README_EN.md) pour les 5 langues ci-dessus? +Traduction [chinois-anglais](https://www.bilibili.com/video/BV1yo4y157jV/) en Markdown | [Plug-in de fonction] avez-vous vu la [README](https://github.com/binary-husky/gpt_academic/blob/master/docs/README_EN.md) pour les 5 langues ci-dessus? Génération de rapports d'analyse de chat | [Plug-in de fonction] Génère automatiquement un rapport de résumé après l'exécution [Traduction intégrale en pdf](https://www.bilibili.com/video/BV1KT411x7Wn) | [Plug-in de fonction] Extraction de titre et de résumé de l'article pdf + traduction intégrale (multi-thread) [Aide à arxiv](https://www.bilibili.com/video/BV1LM4y1279X) | [Plug-in de fonction] Entrer l'url de l'article arxiv pour traduire et télécharger le résumé en un clic @@ -84,8 +84,8 @@ Plus de nouvelles fonctionnalités (génération d'images, etc.) ... | Voir la f 1. Télécharger le projet ```sh -git clone https://github.com/binary-husky/chatgpt_academic.git -cd chatgpt_academic +git clone https://github.com/binary-husky/gpt_academic.git +cd gpt_academic ``` 2. Configuration de la clé API @@ -141,8 +141,8 @@ python main.py 1. ChatGPT uniquement (recommandé pour la plupart des gens) ``` sh -git clone https://github.com/binary-husky/chatgpt_academic.git # Télécharger le projet -cd chatgpt_academic # Accéder au chemin +git clone https://github.com/binary-husky/gpt_academic.git # Télécharger le projet +cd gpt_academic # Accéder au chemin nano config.py # Editez config.py avec n'importe quel éditeur de texte en configurant "Proxy", "API_KEY" et "WEB_PORT" (p. ex. 50923) docker build -t gpt-academic . # Installer @@ -172,10 +172,10 @@ docker-compose up Configurez simplement API_URL_REDIRECT selon les instructions de config.py. 2. Déploiement distant sur un serveur cloud (connaissance et expérience des serveurs cloud requises) -Veuillez consulter [Wiki de déploiement-1] (https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97). +Veuillez consulter [Wiki de déploiement-1] (https://github.com/binary-husky/gpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97). 3. Utilisation de WSL2 (sous-système Windows pour Linux) -Veuillez consulter [Wiki de déploiement-2] (https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2). +Veuillez consulter [Wiki de déploiement-2] (https://github.com/binary-husky/gpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2). 4. Comment exécuter sous un sous-répertoire (tel que `http://localhost/subpath`) Veuillez consulter les [instructions d'exécution de FastAPI] (docs/WithFastapi.md). @@ -206,7 +206,7 @@ Par exemple Écrivez des plugins de fonctions puissants pour effectuer toutes les tâches que vous souhaitez ou que vous ne pouvez pas imaginer. Les plugins de ce projet ont une difficulté de programmation et de débogage très faible. Si vous avez des connaissances de base en Python, vous pouvez simuler la fonctionnalité de votre propre plugin en suivant le modèle que nous avons fourni. -Veuillez consulter le [Guide du plugin de fonction] (https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) pour plus de détails. +Veuillez consulter le [Guide du plugin de fonction] (https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) pour plus de détails. --- # Latest Update diff --git a/docs/README_JP.md b/docs/README_JP.md index 1df2b0a9cf200ca5be348e9178dcf478558c7d0f..46145e1f9cb70c5f7a0fba4e845338b186159778 100644 --- a/docs/README_JP.md +++ b/docs/README_JP.md @@ -16,7 +16,7 @@ GPTを使った任意の言語にこのプロジェクトを翻訳するには > > 1. **赤色**で表示された関数プラグイン(ボタン)のみ、ファイルの読み取りをサポートしています。一部のプラグインは、プラグインエリアの**ドロップダウンメニュー**内にあります。また、私たちはどんな新しいプラグインのPRでも、**最優先**で歓迎し、処理します! > -> 2. このプロジェクトの各ファイルの機能は、自己解析の詳細説明書である[`self_analysis.md`](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)で説明されています。バージョンが進化するにつれて、関連する関数プラグインをいつでもクリックし、GPTを呼び出してプロジェクトの自己解析レポートを再生成することができます。よくある問題は[`wiki`](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)にまとめられています。[インストール方法](#installation)。 +> 2. このプロジェクトの各ファイルの機能は、自己解析の詳細説明書である[`self_analysis.md`](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)で説明されています。バージョンが進化するにつれて、関連する関数プラグインをいつでもクリックし、GPTを呼び出してプロジェクトの自己解析レポートを再生成することができます。よくある問題は[`wiki`](https://github.com/binary-husky/gpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98)にまとめられています。[インストール方法](#installation)。 > 3. このプロジェクトは、chatglmやRWKV、パンクなど、国内の大規模自然言語モデルを利用することをサポートし、試みることを奨励します。複数のAPIキーを共存することができ、設定ファイルに`API_KEY="openai-key1,openai-key2,api2d-key3"`のように記入することができます。`API_KEY`を一時的に変更する場合は、入力エリアに一時的な`API_KEY`を入力してEnterキーを押せば、それが有効になります。 @@ -29,13 +29,13 @@ GPTを使った任意の言語にこのプロジェクトを翻訳するには 一键中英翻訳 | 一键で中英翻訳可能 一键コード解説 | コードを表示し、解説し、生成し、コードに注釈をつけることができる [自分でカスタマイズ可能なショートカットキー](https://www.bilibili.com/video/BV14s4y1E7jN) | 自分でカスタマイズ可能なショートカットキーをサポートする -モジュール化された設計 | カスタマイズ可能な[強力な関数プラグイン](https://github.com/binary-husky/chatgpt_academic/tree/master/crazy_functions)をサポートし、プラグインは[ホットアップデート](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97)に対応している -[自己プログラム解析](https://www.bilibili.com/video/BV1cj411A7VW) | [関数プラグイン] [一键読解](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)このプロジェクトのソースコード +モジュール化された設計 | カスタマイズ可能な[強力な関数プラグイン](https://github.com/binary-husky/gpt_academic/tree/master/crazy_functions)をサポートし、プラグインは[ホットアップデート](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97)に対応している +[自己プログラム解析](https://www.bilibili.com/video/BV1cj411A7VW) | [関数プラグイン] [一键読解](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)このプロジェクトのソースコード プログラム解析 | [関数プラグイン] 一鍵で他のPython/C/C++/Java/Lua/...プロジェクトを分析できる 論文の読み、[翻訳](https://www.bilibili.com/video/BV1KT411x7Wn) | [関数プラグイン] LaTex/ PDF論文の全文を一鍵で読み解き、要約を生成することができる LaTex全文[翻訳](https://www.bilibili.com/video/BV1nk4y1Y7Js/)、[校正](https://www.bilibili.com/video/BV1FT411H7c5/) | [関数プラグイン] LaTex論文の翻訳または校正を一鍵で行うことができる 一括で注釈を生成 | [関数プラグイン] 一鍵で関数に注釈をつけることができる -Markdown[中英翻訳](https://www.bilibili.com/video/BV1yo4y157jV/) | [関数プラグイン] 上記の5種類の言語の[README](https://github.com/binary-husky/chatgpt_academic/blob/master/docs/README_EN.md)を見たことがありますか? +Markdown[中英翻訳](https://www.bilibili.com/video/BV1yo4y157jV/) | [関数プラグイン] 上記の5種類の言語の[README](https://github.com/binary-husky/gpt_academic/blob/master/docs/README_EN.md)を見たことがありますか? チャット分析レポート生成 | [関数プラグイン] 実行後、自動的に概要報告書を生成する [PDF論文全文翻訳機能](https://www.bilibili.com/video/BV1KT411x7Wn) | [関数プラグイン] PDF論文からタイトルと要約を抽出し、全文を翻訳する(マルチスレッド) [Arxivアシスタント](https://www.bilibili.com/video/BV1LM4y1279X) | [関数プラグイン] arxiv記事のURLを入力するだけで、要約を一鍵翻訳し、PDFをダウンロードできる @@ -43,7 +43,7 @@ Markdown[中英翻訳](https://www.bilibili.com/video/BV1yo4y157jV/) | [関数 インターネット情報収集+GPT | [関数プラグイン] まずGPTに[インターネットから情報を収集](https://www.bilibili.com/video/BV1om4y127ck)してから質問に回答させ、情報が常に最新であるようにする 数式/画像/表表示 | 数式の[tex形式とレンダリング形式](https://user-images.githubusercontent.com/96192199/230598842-1d7fcddd-815d-40ee-af60-baf488a199df.png)を同時に表示し、数式、コードハイライトをサポートしている マルチスレッド関数プラグインがサポートされている | chatgptをマルチスレッドで呼び出し、[大量のテキスト](https://www.bilibili.com/video/BV1FT411H7c5/)またはプログラムを一鍵で処理できる -ダークグラジオ[テーマの起動](https://github.com/binary-husky/chatgpt_academic/issues/173) | ブラウザのURLの後ろに```/?__theme=dark```を追加すると、ダークテーマを切り替えることができます。 +ダークグラジオ[テーマの起動](https://github.com/binary-husky/gpt_academic/issues/173) | ブラウザのURLの後ろに```/?__theme=dark```を追加すると、ダークテーマを切り替えることができます。 [多数のLLMモデル](https://www.bilibili.com/video/BV1wT411p7yf)がサポートされ、[API2D](https://api2d.com/)がサポートされている | 同時にGPT3.5、GPT4、[清華ChatGLM](https://github.com/THUDM/ChatGLM-6B)、[復旦MOSS](https://github.com/OpenLMLab/MOSS)に対応 より多くのLLMモデルが接続され、[huggingfaceデプロイ](https://huggingface.co/spaces/qingxu98/gpt-academic)がサポートされている | Newbingインターフェイス(Newbing)、清華大学の[Jittorllm](https://github.com/Jittor/JittorLLMs)のサポート[LLaMA](https://github.com/facebookresearch/llama), [RWKV](https://github.com/BlinkDL/ChatRWKV)と[盘古α](https://openi.org.cn/pangu/) さらに多くの新機能(画像生成など)を紹介する... | この文書の最後に示す... @@ -92,8 +92,8 @@ Markdown[中英翻訳](https://www.bilibili.com/video/BV1yo4y157jV/) | [関数 1. Download the project. ```sh -git clone https://github.com/binary-husky/chatgpt_academic.git -cd chatgpt_academic +git clone https://github.com/binary-husky/gpt_academic.git +cd gpt_academic ``` 2. Configure the API_KEY. @@ -151,8 +151,8 @@ python main.py 1. Only ChatGPT (recommended for most people) ``` sh -git clone https://github.com/binary-husky/chatgpt_academic.git # Download project -cd chatgpt_academic # Enter path +git clone https://github.com/binary-husky/gpt_academic.git # Download project +cd gpt_academic # Enter path nano config.py # Edit config.py with any text editor ‑ configure "Proxy," "API_KEY," "WEB_PORT" (e.g., 50923) and more docker build -t gpt-academic . # installation @@ -182,10 +182,10 @@ docker-compose up Configure API_URL_REDIRECT according to the instructions in `config.py`. 2. Remote Cloud Server Deployment (requires cloud server knowledge and experience) -Please visit [Deployment Wiki-1](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) +Please visit [Deployment Wiki-1](https://github.com/binary-husky/gpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) 3. Using WSL2 (Windows Subsystem for Linux Subsystem) -Please visit [Deployment Wiki-2](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) +Please visit [Deployment Wiki-2](https://github.com/binary-husky/gpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) 4. How to run on a secondary URL (such as `http://localhost/subpath`) Please visit [FastAPI Running Instructions](docs/WithFastapi.md) @@ -216,7 +216,7 @@ example: Write powerful function plugins to perform any task you can and cannot think of. The difficulty of writing and debugging plugins in this project is low, and as long as you have a certain amount of python basic knowledge, you can follow the template provided by us to achieve your own plugin functions. -For details, please refer to the [Function Plugin Guide](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). +For details, please refer to the [Function Plugin Guide](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97). --- # Latest Update diff --git a/docs/README_RS.md b/docs/README_RS.md index 5ba5fcccc30db520d38e21950e2f7cfc03d324c5..d4888a0522ff6731ec74a4782b15d49bc6c6dd2d 100644 --- a/docs/README_RS.md +++ b/docs/README_RS.md @@ -11,7 +11,7 @@ > > 1. Обратите внимание, что только функциональные плагины (кнопки), помеченные **красным цветом**, поддерживают чтение файлов, некоторые плагины находятся в **выпадающем меню** в области плагинов. Кроме того, мы с наивысшим приоритетом рады и обрабатываем pull requests для любых новых плагинов! > -> 2. В каждом файле проекта функциональность описана в документе самоанализа [`self_analysis.md`](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A). С каждой итерацией выполнения версии вы можете в любое время вызвать повторное создание отчета о самоанализе этого проекта, щелкнув соответствующий функциональный плагин и вызвав GPT. Вопросы сборки описаны в [`wiki`](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Метод установки](#installation). +> 2. В каждом файле проекта функциональность описана в документе самоанализа [`self_analysis.md`](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A). С каждой итерацией выполнения версии вы можете в любое время вызвать повторное создание отчета о самоанализе этого проекта, щелкнув соответствующий функциональный плагин и вызвав GPT. Вопросы сборки описаны в [`wiki`](https://github.com/binary-husky/gpt_academic/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98). [Метод установки](#installation). > > 3. Этот проект совместим и поощряет использование китайских языковых моделей chatglm и RWKV, пангу и т. Д. Поддержка нескольких api-key, которые могут существовать одновременно, может быть указан в файле конфигурации, например `API_KEY="openai-key1,openai-key2,api2d-key3"`. Если требуется временно изменить `API_KEY`, введите временный `API_KEY` в области ввода и нажмите клавишу Enter, чтобы он вступил в силу. @@ -33,13 +33,13 @@ Однокнопочный перевод на английский и китайский | Однокнопочный перевод на английский и китайский Однокнопочное объяснение кода | Показ кода, объяснение его, генерация кода, комментирование кода [Настройка быстрых клавиш](https://www.bilibili.com/video/BV14s4y1E7jN) | Поддержка настройки быстрых клавиш -Модульный дизайн | Поддержка пользовательских функциональных плагинов мощных [функциональных плагинов](https://github.com/binary-husky/chatgpt_academic/tree/master/crazy_functions), плагины поддерживают [горячую замену](https://github.com/binary-husky/chatgpt_academic/wiki/Function-Plug-in-Guide) -[Анализ своей программы](https://www.bilibili.com/video/BV1cj411A7VW) | [Функциональный плагин] [Однокнопочный просмотр](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academicProject-Self-analysis-Report) исходного кода этого проекта +Модульный дизайн | Поддержка пользовательских функциональных плагинов мощных [функциональных плагинов](https://github.com/binary-husky/gpt_academic/tree/master/crazy_functions), плагины поддерживают [горячую замену](https://github.com/binary-husky/gpt_academic/wiki/Function-Plug-in-Guide) +[Анализ своей программы](https://www.bilibili.com/video/BV1cj411A7VW) | [Функциональный плагин] [Однокнопочный просмотр](https://github.com/binary-husky/gpt_academic/wiki/chatgpt-academicProject-Self-analysis-Report) исходного кода этого проекта [Анализ программы](https://www.bilibili.com/video/BV1cj411A7VW) | [Функциональный плагин] Однокнопочный анализ дерева других проектов Python/C/C++/Java/Lua/... Чтение статей, [перевод](https://www.bilibili.com/video/BV1KT411x7Wn) статей | [Функциональный плагин] Однокнопочное чтение полного текста научных статей и генерация резюме Полный перевод [LaTeX](https://www.bilibili.com/video/BV1nk4y1Y7Js/) и совершенствование | [Функциональный плагин] Однокнопочный перевод или совершенствование LaTeX статьи Автоматическое комментирование | [Функциональный плагин] Однокнопочное автоматическое генерирование комментариев функций -[Перевод](https://www.bilibili.com/video/BV1yo4y157jV/) Markdown на английский и китайский | [Функциональный плагин] Вы видели обе версии файлов [README](https://github.com/binary-husky/chatgpt_academic/blob/master/docs/README_EN.md) для этих 5 языков? +[Перевод](https://www.bilibili.com/video/BV1yo4y157jV/) Markdown на английский и китайский | [Функциональный плагин] Вы видели обе версии файлов [README](https://github.com/binary-husky/gpt_academic/blob/master/docs/README_EN.md) для этих 5 языков? Отчет о чат-анализе | [Функциональный плагин] После запуска будет автоматически сгенерировано сводное извещение Функция перевода полного текста [PDF-статьи](https://www.bilibili.com/video/BV1KT411x7Wn) | [Функциональный плагин] Извлечение заголовка и резюме [PDF-статьи](https://www.bilibili.com/video/BV1KT411x7Wn) и перевод всего документа (многопоточность) [Arxiv Helper](https://www.bilibili.com/video/BV1LM4y1279X) | [Функциональный плагин] Введите URL статьи на arxiv и одним щелчком мыши переведите резюме и загрузите PDF @@ -81,8 +81,8 @@ 1. Download the project ```sh -git clone https://github.com/binary-husky/chatgpt_academic.git -cd chatgpt_academic +git clone https://github.com/binary-husky/gpt_academic.git +cd gpt_academic ``` 2. Configure API_KEY @@ -138,8 +138,8 @@ python main.py 1. ChatGPT only (recommended for most people) ``` sh -git clone https://github.com/binary-husky/chatgpt_academic.git # download the project -cd chatgpt_academic # enter the path +git clone https://github.com/binary-husky/gpt_academic.git # download the project +cd gpt_academic # enter the path nano config.py # edit config.py with any text editor to configure "Proxy", "API_KEY", and "WEB_PORT" (eg 50923) docker build -t gpt-academic . # install @@ -169,10 +169,10 @@ docker-compose up Configure API_URL_REDIRECT according to the instructions in `config.py`. 2. Remote Cloud Server Deployment (Requires Knowledge and Experience of Cloud Servers) -Please visit [Deployment Wiki-1](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) +Please visit [Deployment Wiki-1](https://github.com/binary-husky/gpt_academic/wiki/%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%BF%9C%E7%A8%8B%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97) 3. Using WSL2 (Windows Subsystem for Linux subsystem) -Please visit [Deployment Wiki-2](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) +Please visit [Deployment Wiki-2](https://github.com/binary-husky/gpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) 4. How to run at the secondary URL (such as `http://localhost/subpath`) Please visit [FastAPI Operation Instructions](docs/WithFastapi.md) @@ -204,7 +204,7 @@ For example: Write powerful function plugins to perform any task you can and can't imagine. The difficulty of debugging and writing plugins in this project is very low. As long as you have a certain knowledge of python, you can implement your own plugin function by imitating the template we provide. -Please refer to the [Function Plugin Guide](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) for details. +Please refer to the [Function Plugin Guide](https://github.com/binary-husky/gpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) for details. --- # Latest Update diff --git a/docs/translate_english.json b/docs/translate_english.json index 57e008b16716df994f9dde30cda7b06471c6a074..9721dcfa1572120ccc157d3445bb4dddc03d4790 100644 --- a/docs/translate_english.json +++ b/docs/translate_english.json @@ -1667,5 +1667,499 @@ "段音频的主要内容": "The main content of the segment audio is", "z$ 分别是空间直角坐标系中的三个坐标": "z$, respectively, are the three coordinates in the spatial rectangular coordinate system", "这个是怎么识别的呢我也不清楚": "I'm not sure how this is recognized", - "从现在起": "From now on" + "从现在起": "From now on", + "连接bing搜索回答问题": "ConnectBingSearchAnswerQuestion", + "联网的ChatGPT_bing版": "OnlineChatGPT_BingEdition", + "Markdown翻译指定语言": "TranslateMarkdownToSpecifiedLanguage", + "Langchain知识库": "LangchainKnowledgeBase", + "Latex英文纠错加PDF对比": "CorrectEnglishInLatexWithPDFComparison", + "Latex输出PDF结果": "OutputPDFFromLatex", + "Latex翻译中文并重新编译PDF": "TranslateChineseToEnglishInLatexAndRecompilePDF", + "sprint亮靛": "SprintIndigo", + "寻找Latex主文件": "FindLatexMainFile", + "专业词汇声明": "ProfessionalTerminologyDeclaration", + "Latex精细分解与转化": "DecomposeAndConvertLatex", + "编译Latex": "CompileLatex", + "如果您是论文原作者": "If you are the original author of the paper", + "正在编译对比PDF": "Compiling the comparison PDF", + "将 \\include 命令转换为 \\input 命令": "Converting the \\include command to the \\input command", + "取评分最高者返回": "Returning the highest-rated one", + "不要修改!! 高危设置!通过修改此设置": "Do not modify!! High-risk setting! By modifying this setting", + "Tex源文件缺失!": "Tex source file is missing!", + "6.25 加入判定latex模板的代码": "Added code to determine the latex template on June 25", + "正在精细切分latex文件": "Finely splitting the latex file", + "获取response失败": "Failed to get response", + "手动指定语言": "Manually specify the language", + "输入arxivID": "Enter arxivID", + "对输入的word文档进行摘要生成": "Generate a summary of the input word document", + "将指定目录下的PDF文件从英文翻译成中文": "Translate PDF files from English to Chinese in the specified directory", + "如果分析错误": "If the analysis is incorrect", + "尝试第": "Try the", + "用户填3": "User fills in 3", + "请在此处追加更细致的矫错指令": "Please append more detailed correction instructions here", + "为了防止大语言模型的意外谬误产生扩散影响": "To prevent the accidental spread of errors in large language models", + "前面是中文冒号": "The colon before is in Chinese", + "内含已经翻译的Tex文档": "Contains a Tex document that has been translated", + "成功啦": "Success!", + "刷新页面即可以退出UpdateKnowledgeArchive模式": "Refresh the page to exit UpdateKnowledgeArchive mode", + "或者不在环境变量PATH中": "Or not in the environment variable PATH", + "--读取文件": "--Read the file", + "才能继续下面的步骤": "To continue with the next steps", + "代理数据解析失败": "Proxy data parsing failed", + "详见项目主README.md": "See the main README.md of the project for details", + "临时存储用于调试": "Temporarily stored for debugging", + "屏蔽空行和太短的句子": "Filter out empty lines and sentences that are too short", + "gpt 多线程请求": "GPT multi-threaded request", + "编译已经开始": "Compilation has started", + "无法找到一个主Tex文件": "Cannot find a main Tex file", + "修复括号": "Fix parentheses", + "请您不要删除或修改这行警告": "Please do not delete or modify this warning", + "请登录OpenAI查看详情 https": "Please log in to OpenAI to view details at https", + "调用函数": "Call a function", + "请查看终端的输出或耐心等待": "Please check the output in the terminal or wait patiently", + "LatexEnglishCorrection+高亮修正位置": "Latex English correction + highlight correction position", + "行": "line", + "Newbing 请求失败": "Newbing request failed", + "转化PDF编译是否成功": "Check if the conversion to PDF and compilation were successful", + "建议更换代理协议": "Recommend changing the proxy protocol", + "========================================= 插件主程序1 =====================================================": "========================================= Plugin Main Program 1 =====================================================", + "终端": "terminal", + "请先上传文件素材": "Please upload file materials first", + "前面是中文逗号": "There is a Chinese comma in front", + "请尝试把以下指令复制到高级参数区": "Please try copying the following instructions to the advanced parameters section", + "翻译-": "Translation -", + "请耐心等待": "Please be patient", + "将前后断行符脱离": "Remove line breaks before and after", + "json等": "JSON, etc.", + "生成中文PDF": "Generate Chinese PDF", + "用红色标注处保留区": "Use red color to highlight the reserved area", + "对比PDF编译是否成功": "Compare if the PDF compilation was successful", + "回答完问题后": "After answering the question", + "其他操作系统表现未知": "Unknown performance on other operating systems", + "-构建知识库": "Build knowledge base", + "还原原文": "Restore original text", + "或者重启之后再度尝试": "Or try again after restarting", + "免费": "Free", + "仅在Windows系统进行了测试": "Tested only on Windows system", + "欢迎加REAME中的QQ联系开发者": "Feel free to contact the developer via QQ in REAME", + "当前知识库内的有效文件": "Valid files in the current knowledge base", + "您可以到Github Issue区": "You can go to the Github Issue area", + "刷新Gradio前端界面": "Refresh the Gradio frontend interface", + "吸收title与作者以上的部分": "Include the title and the above part of the author", + "给出一些判定模板文档的词作为扣分项": "Provide some words in the template document as deduction items", + "--读取参数": "-- Read parameters", + "然后进行问答": "And then perform question-answering", + "根据自然语言执行插件命令": "Execute plugin commands based on natural language", + "*{\\scriptsize\\textbf{警告": "*{\\scriptsize\\textbf{Warning", + "但请查收结果": "But please check the results", + "翻译内容可靠性无保障": "No guarantee of translation accuracy", + "寻找主文件": "Find the main file", + "消耗时间的函数": "Time-consuming function", + "当前语言模型温度设定": "Current language model temperature setting", + "这需要一段时间计算": "This requires some time to calculate", + "为啥chatgpt会把cite里面的逗号换成中文逗号呀": "Why does ChatGPT change commas inside 'cite' to Chinese commas?", + "发现已经存在翻译好的PDF文档": "Found an already translated PDF document", + "待提取的知识库名称id": "Knowledge base name ID to be extracted", + "文本碎片重组为完整的tex片段": "Reassemble text fragments into complete tex fragments", + "注意事项": "Notes", + "参数说明": "Parameter description", + "或代理节点": "Or proxy node", + "构建知识库": "Building knowledge base", + "报错信息如下. 如果是与网络相关的问题": "Error message as follows. If it is related to network issues", + "功能描述": "Function description", + "禁止移除或修改此警告": "Removal or modification of this warning is prohibited", + "Arixv翻译": "Arixv translation", + "读取优先级": "Read priority", + "包含documentclass关键字": "Contains the documentclass keyword", + "根据文本使用GPT模型生成相应的图像": "Generate corresponding images using GPT model based on the text", + "图像生成所用到的提示文本": "Prompt text used for image generation", + "Your account is not active. OpenAI以账户失效为由": "Your account is not active. OpenAI states that it is due to account expiration", + "快捷的调试函数": "Convenient debugging function", + "在多Tex文档中": "In multiple Tex documents", + "因此选择GenerateImage函数": "Therefore, choose the GenerateImage function", + "当前工作路径为": "The current working directory is", + "实际得到格式": "Obtained format in reality", + "这段代码定义了一个名为TempProxy的空上下文管理器": "This code defines an empty context manager named TempProxy", + "吸收其他杂项": "Absorb other miscellaneous items", + "请输入要翻译成哪种语言": "Please enter which language to translate into", + "的单词": "of the word", + "正在尝试自动安装": "Attempting automatic installation", + "如果有必要": "If necessary", + "开始下载": "Start downloading", + "项目Github地址 \\url{https": "Project GitHub address \\url{https", + "将根据报错信息修正tex源文件并重试": "The Tex source file will be corrected and retried based on the error message", + "发送至azure openai api": "Send to Azure OpenAI API", + "吸收匿名公式": "Absorb anonymous formulas", + "用该压缩包+ConversationHistoryArchive进行反馈": "Provide feedback using the compressed package + ConversationHistoryArchive", + "需要特殊依赖": "Requires special dependencies", + "还原部分原文": "Restore part of the original text", + "构建完成": "Build completed", + "解析arxiv网址失败": "Failed to parse arXiv URL", + "输入问题后点击该插件": "Click the plugin after entering the question", + "请求子进程": "Requesting subprocess", + "请务必用 pip install -r requirements.txt 指令安装依赖": "Please make sure to install the dependencies using the 'pip install -r requirements.txt' command", + "如果程序停顿5分钟以上": "If the program pauses for more than 5 minutes", + "转化PDF编译已经成功": "Conversion to PDF compilation was successful", + "虽然PDF生成失败了": "Although PDF generation failed", + "分析上述回答": "Analyze the above answer", + "吸收在42行以内的begin-end组合": "Absorb the begin-end combination within 42 lines", + "推荐http": "Recommend http", + "Latex没有安装": "Latex is not installed", + "用latex编译为PDF对修正处做高亮": "Compile to PDF using LaTeX and highlight the corrections", + "reverse 操作必须放在最后": "'reverse' operation must be placed at the end", + "AZURE OPENAI API拒绝了请求": "AZURE OPENAI API rejected the request", + "该项目的Latex主文件是": "The main LaTeX file of this project is", + "You are associated with a deactivated account. OpenAI以账户失效为由": "You are associated with a deactivated account. OpenAI considers it as an account expiration", + "它*必须*被包含在AVAIL_LLM_MODELS列表中": "It *must* be included in the AVAIL_LLM_MODELS list", + "未知指令": "Unknown command", + "尝试执行Latex指令失败": "Failed to execute the LaTeX command", + "摘要生成后的文档路径": "Path of the document after summary generation", + "GPT结果已输出": "GPT result has been outputted", + "使用Newbing": "Using Newbing", + "其他模型转化效果未知": "Unknown conversion effect of other models", + "P.S. 但愿没人把latex模板放在里面传进来": "P.S. Hopefully, no one passes a LaTeX template in it", + "定位主Latex文件": "Locate the main LaTeX file", + "后面是英文冒号": "English colon follows", + "文档越长耗时越长": "The longer the document, the longer it takes.", + "压缩包": "Compressed file", + "但通常不会出现在正文": "But usually does not appear in the body.", + "正在预热文本向量化模组": "Preheating text vectorization module", + "5刀": "5 dollars", + "提问吧! 但注意": "Ask questions! But be careful", + "发送至AZURE OPENAI API": "Send to AZURE OPENAI API", + "请仔细鉴别并以原文为准": "Please carefully verify and refer to the original text", + "如果需要使用AZURE 详情请见额外文档 docs\\use_azure.md": "If you need to use AZURE, please refer to the additional document docs\\use_azure.md for details", + "使用正则表达式查找半行注释": "Use regular expressions to find inline comments", + "只有第二步成功": "Only the second step is successful", + "P.S. 顺便把CTEX塞进去以支持中文": "P.S. By the way, include CTEX to support Chinese", + "安装方法https": "Installation method: https", + "则跳过GPT请求环节": "Then skip the GPT request process", + "请切换至“UpdateKnowledgeArchive”插件进行知识库访问": "Please switch to the 'UpdateKnowledgeArchive' plugin for knowledge base access", + "=================================== 工具函数 ===============================================": "=================================== Utility functions ===============================================", + "填入azure openai api的密钥": "Fill in the Azure OpenAI API key", + "上传Latex压缩包": "Upload LaTeX compressed file", + "远程云服务器部署": "Deploy to remote cloud server", + "用黑色标注转换区": "Use black color to annotate the conversion area", + "音频文件的路径": "Path to the audio file", + "必须包含documentclass": "Must include documentclass", + "再列出用户可能提出的三个问题": "List three more questions that the user might ask", + "根据需要切换prompt": "Switch the prompt as needed", + "将文件复制一份到下载区": "Make a copy of the file in the download area", + "次编译": "Second compilation", + "Latex文件融合完成": "LaTeX file merging completed", + "返回": "Return", + "后面是英文逗号": "Comma after this", + "对不同latex源文件扣分": "Deduct points for different LaTeX source files", + "失败啦": "Failed", + "编译BibTex": "Compile BibTeX", + "Linux下必须使用Docker安装": "Must install using Docker on Linux", + "报错信息": "Error message", + "删除或修改歧义文件": "Delete or modify ambiguous files", + "-预热文本向量化模组": "- Preheating text vectorization module", + "将每次对话记录写入Markdown格式的文件中": "Write each conversation record into a file in Markdown format", + "其他类型文献转化效果未知": "Unknown conversion effect for other types of literature", + "获取线程锁": "Acquire thread lock", + "使用英文": "Use English", + "如果存在调试缓存文件": "If there is a debug cache file", + "您需要首先调用构建知识库": "You need to call the knowledge base building first", + "原始PDF编译是否成功": "Whether the original PDF compilation is successful", + "生成 azure openai api请求": "Generate Azure OpenAI API requests", + "正在编译PDF": "Compiling PDF", + "仅调试": "Debug only", + "========================================= 插件主程序2 =====================================================": "========================================= Plugin Main Program 2 =====================================================", + "多线程翻译开始": "Multithreaded translation begins", + "出问题了": "There is a problem", + "版权归原文作者所有": "Copyright belongs to the original author", + "当前大语言模型": "Current large language model", + "目前对机器学习类文献转化效果最好": "Currently, the best conversion effect for machine learning literature", + "这个paper有个input命令文件名大小写错误!": "This paper has an input command with a filename case error!", + "期望格式例如": "Expected format, for example", + "解决部分词汇翻译不准确的问题": "Resolve the issue of inaccurate translation for some terms", + "待注入的知识库名称id": "Name/ID of the knowledge base to be injected", + "精细切分latex文件": "Fine-grained segmentation of LaTeX files", + "永远给定None": "Always given None", + "work_folder = Latex预处理": "work_folder = LaTeX preprocessing", + "请直接去该路径下取回翻译结果": "Please directly go to the path to retrieve the translation results", + "寻找主tex文件": "Finding the main .tex file", + "模型参数": "Model parameters", + "返回找到的第一个": "Return the first one found", + "编译转化后的PDF": "Compile the converted PDF", + "\\SEAFILE_LOCALŅ03047\\我的资料库\\music\\Akie秋绘-未来轮廓.mp3": "\\SEAFILE_LOCALŅ03047\\My Library\\music\\Akie秋绘-未来轮廓.mp3", + "拆分过长的latex片段": "Splitting overly long LaTeX fragments", + "没有找到任何可读取文件": "No readable files found", + "暗色模式 / 亮色模式": "Dark mode / Light mode", + "检测到arxiv文档连接": "Detected arXiv document link", + "此插件Windows支持最佳": "This plugin has best support for Windows", + "from crazy_functions.虚空终端 import 终端": "from crazy_functions.null_terminal import Terminal", + "本地论文翻译": "Local paper translation", + "输出html调试文件": "Output HTML debugging file", + "以下所有配置也都支持利用环境变量覆写": "All the following configurations can also be overridden using environment variables", + "PDF文件所在的路径": "Path of the PDF file", + "也是可读的": "It is also readable", + "将消耗较长时间下载中文向量化模型": "Downloading Chinese vectorization model will take a long time", + "环境变量配置格式见docker-compose.yml": "See docker-compose.yml for the format of environment variable configuration", + "编译文献交叉引用": "Compile bibliographic cross-references", + "默认为default": "Default is 'default'", + "或者使用此插件继续上传更多文件": "Or use this plugin to continue uploading more files", + "该PDF由GPT-Academic开源项目调用大语言模型+Latex翻译插件一键生成": "This PDF is generated by the GPT-Academic open-source project using a large language model + LaTeX translation plugin", + "使用latexdiff生成论文转化前后对比": "Use latexdiff to generate before and after comparison of paper transformation", + "正在编译PDF文档": "Compiling PDF document", + "读取config.py文件中关于AZURE OPENAI API的信息": "Read the information about AZURE OPENAI API from the config.py file", + "配置教程&视频教程": "Configuration tutorial & video tutorial", + "临时地启动代理网络": "Temporarily start proxy network", + "临时地激活代理网络": "Temporarily activate proxy network", + "功能尚不稳定": "Functionality is unstable", + "默认为Chinese": "Default is Chinese", + "请查收结果": "Please check the results", + "将 chatglm 直接对齐到 chatglm2": "Align chatglm directly to chatglm2", + "中读取数据构建知识库": "Build a knowledge base by reading data in", + "用于给一小段代码上代理": "Used to proxy a small piece of code", + "分析结果": "Analysis results", + "依赖不足": "Insufficient dependencies", + "Markdown翻译": "Markdown translation", + "除非您是论文的原作者": "Unless you are the original author of the paper", + "test_LangchainKnowledgeBase读取": "test_LangchainKnowledgeBase read", + "将多文件tex工程融合为一个巨型tex": "Merge multiple tex projects into one giant tex", + "吸收iffalse注释": "Absorb iffalser comments", + "您接下来不能再使用其他插件了": "You can no longer use other plugins next", + "正在构建知识库": "Building knowledge base", + "需Latex": "Requires Latex", + "即找不到": "That is not found", + "保证括号正确": "Ensure parentheses are correct", + "= 2 通过一些Latex模板中常见": "= 2 through some common Latex templates", + "请立即终止程序": "Please terminate the program immediately", + "解压失败! 需要安装pip install rarfile来解压rar文件": "Decompression failed! Install 'pip install rarfile' to decompress rar files", + "请在此处给出自定义翻译命令": "Please provide custom translation command here", + "解压失败! 需要安装pip install py7zr来解压7z文件": "Decompression failed! Install 'pip install py7zr' to decompress 7z files", + "执行错误": "Execution error", + "目前仅支持GPT3.5/GPT4": "Currently only supports GPT3.5/GPT4", + "P.S. 顺便把Latex的注释去除": "P.S. Also remove comments from Latex", + "写出文件": "Write out the file", + "当前报错的latex代码处于第": "The current error in the LaTeX code is on line", + "主程序即将开始": "Main program is about to start", + "详情信息见requirements.txt": "See details in requirements.txt", + "释放线程锁": "Release thread lock", + "由于最为关键的转化PDF编译失败": "Due to the critical failure of PDF conversion and compilation", + "即将退出": "Exiting soon", + "尝试下载": "Attempting to download", + "删除整行的空注释": "Remove empty comments from the entire line", + "也找不到": "Not found either", + "从一批文件": "From a batch of files", + "编译结束": "Compilation finished", + "调用缓存": "Calling cache", + "只有GenerateImage和生成图像相关": "Only GenerateImage and image generation related", + "待处理的word文档路径": "Path of the word document to be processed", + "是否在提交时自动清空输入框": "Whether to automatically clear the input box upon submission", + "检查结果": "Check the result", + "生成时间戳": "Generate a timestamp", + "编译原始PDF": "Compile the original PDF", + "填入ENGINE": "Fill in ENGINE", + "填入api版本": "Fill in the API version", + "中文Bing版": "Chinese Bing version", + "当前支持的格式包括": "Currently supported formats include", + "交互功能模板函数": "InteractiveFunctionTemplateFunction", + "交互功能函数模板": "InteractiveFunctionFunctionTemplate", + "语音助手": "VoiceAssistant", + "微调数据集生成": "FineTuneDatasetGeneration", + "chatglm微调工具": "ChatGLMFineTuningTool", + "启动微调": "StartFineTuning", + "请讲话": "Please speak", + "正在听您讲话": "Listening to you", + "对这个人外貌、身处的环境、内心世界、过去经历进行描写": "Describe the appearance, environment, inner world, and past experiences of this person", + "请向下翻": "Please scroll down", + "实时音频采集": "Real-time audio collection", + "找不到": "Not found", + "在一个异步线程中采集音频": "Collect audio in an asynchronous thread", + "azure和api2d请求源": "Azure and API2D request source", + "等待ChatGLMFT响应中": "Waiting for ChatGLMFT response", + "如果使用ChatGLM2微调模型": "If using ChatGLM2 fine-tuning model", + "把文件复制过去": "Copy the file over", + "可选": "Optional", + "ChatGLMFT响应异常": "ChatGLMFT response exception", + "上传本地文件/压缩包供函数插件调用": "Upload local files/compressed packages for function plugin calls", + "例如 f37f30e0f9934c34a992f6f64f7eba4f": "For example, f37f30e0f9934c34a992f6f64f7eba4f", + "正在等您说完问题": "Waiting for you to finish the question", + "解除插件状态": "Release plugin status", + "详情见https": "See details at https", + "避免线程阻塞": "Avoid thread blocking", + "先上传数据集": "Upload dataset first", + "请直接提交即可": "Submit directly", + "Call ChatGLMFT fail 不能正常加载ChatGLMFT的参数": "Call ChatGLMFT fail, cannot load ChatGLMFT parameters", + "插件可读取“输入区”文本/路径作为参数": "The plugin can read text/path in the input area as parameters", + "给出指令": "Give instructions", + "暂不提交": "Do not submit for now", + "如 绿帽子*深蓝色衬衫*黑色运动裤": "E.g. green hat * dark blue shirt * black sports pants", + "阿里云实时语音识别 配置难度较高 仅建议高手用户使用 参考 https": "Aliyun real-time speech recognition has high configuration difficulty and is only recommended for advanced users. Refer to https", + "ChatGLMFT尚未加载": "ChatGLMFT has not been loaded yet", + "输入 clear 以清空对话历史": "Enter 'clear' to clear the conversation history", + "可以将自身的状态存储到cookie中": "You can store your own status in cookies", + "填入你亲手写的部署名": "Fill in the deployment name you wrote by yourself", + "该选项即将被弃用": "This option will be deprecated soon", + "代理网络配置": "Proxy network configuration", + "每秒采样数量": "Number of samples per second", + "使用时": "When using", + "想象一个穿着者": "Imagine a wearer", + "如果已经存在": "If it already exists", + "例如您可以将以下命令复制到下方": "For example, you can copy the following command below", + "正在锁定插件": "Locking plugin", + "使用": "Use", + "读 docs\\use_azure.md": "Read docs\\use_azure.md", + "开始最终总结": "Start final summary", + "openai的官方KEY需要伴随组织编码": "Openai's official KEY needs to be accompanied by organizational code", + "将子线程的gpt结果写入chatbot": "Write the GPT result of the sub-thread into the chatbot", + "Arixv论文精细翻译": "Fine translation of Arixv paper", + "开始接收chatglmft的回复": "Start receiving replies from chatglmft", + "请先将.doc文档转换为.docx文档": "Please convert .doc documents to .docx documents first", + "避免多用户干扰": "Avoid multiple user interference", + "清空label": "Clear label", + "解除插件锁定": "Unlock plugin", + "请以以下方式load模型!!!": "Please load the model in the following way!!!", + "没给定指令": "No instruction given", + "100字以内": "Within 100 words", + "获取关键词": "Get keywords", + "欢迎使用 MOSS 人工智能助手!": "Welcome to use MOSS AI assistant!", + "音频助手": "Audio assistant", + "上传Latex项目": "Upload Latex project", + "对话助手函数插件": "Chat assistant function plugin", + "如果一句话小于7个字": "If a sentence is less than 7 words", + "640个字节为一组": "640 bytes per group", + "右下角更换模型菜单中可切换openai": "OpenAI can be switched in the model menu in the lower right corner", + "双手离开鼠标键盘吧": "Take your hands off the mouse and keyboard", + "先删除": "Delete first", + "如果要使用ChatGLMFT": "If you want to use ChatGLMFT", + "例如 RoPlZrM88DnAFkZK": "For example, RoPlZrM88DnAFkZK", + "提取总结": "Extract summary", + "ChatGLMFT消耗大量的内存": "ChatGLMFT consumes a lot of memory", + "格式如org-123456789abcdefghijklmno的": "In the format of org-123456789abcdefghijklmno", + "在执行完成之后": "After execution is complete", + "此处填API密钥": "Fill in the API key here", + "chatglmft 没有 sys_prompt 接口": "ChatGLMFT does not have a sys_prompt interface", + "用第二人称": "Use the second person", + "Chuanhu-Small-and-Beautiful主题": "Chuanhu-Small-and-Beautiful theme", + "请检查ALIYUN_TOKEN和ALIYUN_APPKEY是否过期": "Please check if ALIYUN_TOKEN and ALIYUN_APPKEY have expired", + "还需要填写组织": "You also need to fill in the organization", + "会直接转到该函数": "Will directly jump to the function", + "初始化插件状态": "Initializing plugin status", + "插件锁定中": "Plugin is locked", + "如果这里报错": "If there is an error here", + "本地Latex论文精细翻译": "Local Latex paper fine translation", + "极少数情况下": "In very few cases", + "首先你在中文语境下通读整篇论文": "First, read the entire paper in a Chinese context", + "点击“停止”键可终止程序": "Click the 'Stop' button to terminate the program", + "建议排查": "Suggested troubleshooting", + "没有阿里云语音识别APPKEY和TOKEN": "No Aliyun voice recognition APPKEY and TOKEN", + "避免遗忘导致死锁": "Avoid forgetting to cause deadlock", + "第一次调用": "First call", + "解决插件锁定时的界面显示问题": "Solve the interface display problem when the plugin is locked", + "初始化音频采集线程": "Initialize audio capture thread", + "找不到微调模型检查点": "Cannot find fine-tuning model checkpoint", + "色彩主体": "Color theme", + "上传文件自动修正路径": "Automatically correct the path when uploading files", + "将文件添加到chatbot cookie中": "Add files to chatbot cookie", + "正常状态": "Normal state", + "建议使用英文单词": "Suggest using English words", + "Aliyun音频服务异常": "Aliyun audio service exception", + "格式如org-xxxxxxxxxxxxxxxxxxxxxxxx": "Format like org-xxxxxxxxxxxxxxxxxxxxxxxx", + "GPT 学术优化": "GPT academic optimization", + "要求": "Requirement", + "赋予插件状态": "Assign plugin status", + "等待GPT响应": "Waiting for GPT response", + "MOSS can understand and communicate fluently in the language chosen by the user such as English and 中文. MOSS can perform any language-based tasks.": "MOSS can understand and communicate fluently in the language chosen by the user such as English and Chinese. MOSS can perform any language-based tasks.", + "我将为您查找相关壁纸": "I will search for related wallpapers for you", + "当下一次用户提交时": "When the next user submits", + "赋予插件锁定 锁定插件回调路径": "Assign plugin lock, lock plugin callback path", + "处理个别特殊插件的锁定状态": "Handle the lock status of individual special plugins", + "add gpt task 创建子线程请求gpt": "Add GPT task, create sub-thread to request GPT", + "等待用户的再次调用": "Waiting for the user to call again", + "只读": "Read-only", + "用于灵活调整复杂功能的各种参数": "Various parameters used to flexibly adjust complex functions", + "输入 stop 以终止对话": "Enter stop to terminate the conversation", + "缺少ChatGLMFT的依赖": "Missing dependency of ChatGLMFT", + "找 API_ORG 设置项": "Find API_ORG setting item", + "检查config中的AVAIL_LLM_MODELS选项": "Check the AVAIL_LLM_MODELS option in config", + "对这个人外貌、身处的环境、内心世界、人设进行描写": "Describe the appearance, environment, inner world, and character of this person.", + "请输入关键词": "Please enter a keyword.", + "!!!如果需要运行量化版本": "!!! If you need to run the quantitative version.", + "为每一位访问的用户赋予一个独一无二的uuid编码": "Assign a unique uuid code to each visiting user.", + "由于提问含不合规内容被Azure过滤": "Due to Azure filtering out questions containing non-compliant content.", + "欢迎使用 MOSS 人工智能助手!输入内容即可进行对话": "Welcome to use MOSS AI assistant! Enter the content to start the conversation.", + "记住当前的label": "Remember the current label.", + "不能正常加载ChatGLMFT的参数!": "Cannot load ChatGLMFT parameters normally!", + "建议直接在API_KEY处填写": "It is recommended to fill in directly at API_KEY.", + "创建request": "Create request", + "默认 secondary": "Default secondary", + "会被加在你的输入之前": "Will be added before your input", + "缺少": "Missing", + "前者是API2D的结束条件": "The former is the termination condition of API2D", + "无需填写": "No need to fill in", + "后缀": "Suffix", + "扭转的范围": "Range of twisting", + "是否在触发时清除历史": "Whether to clear history when triggered", + "⭐多线程方法": "⭐Multi-threaded method", + "消耗大量的内存": "Consumes a large amount of memory", + "重组": "Reorganize", + "高危设置! 常规情况下不要修改! 通过修改此设置": "High-risk setting! Do not modify under normal circumstances! Modify this setting", + "检查USE_PROXY": "Check USE_PROXY", + "标注节点的行数范围": "Range of line numbers for annotated nodes", + "即不处理之前的对话历史": "That is, do not process previous conversation history", + "即将编译PDF": "Compiling PDF", + "没有设置ANTHROPIC_API_KEY选项": "ANTHROPIC_API_KEY option is not set", + "非Openai官方接口返回了错误": "Non-Openai official interface returned an error", + "您的 API_KEY 不满足任何一种已知的密钥格式": "Your API_KEY does not meet any known key format", + "格式": "Format", + "不能正常加载": "Cannot load properly", + "🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行": "🏃‍♂️🏃‍♂️🏃‍♂️ Subprocess execution", + "前缀": "Prefix", + "创建AcsClient实例": "Create AcsClient instance", + "⭐主进程执行": "⭐Main process execution", + "增强稳健性": "Enhance robustness", + "用来描述你的要求": "Used to describe your requirements", + "举例": "For example", + "⭐单线程方法": "⭐Single-threaded method", + "后者是OPENAI的结束条件": "The latter is the termination condition of OPENAI", + "防止proxies单独起作用": "Prevent proxies from working alone", + "将两个PDF拼接": "Concatenate two PDFs", + "最后一步处理": "The last step processing", + "正在从github下载资源": "Downloading resources from github", + "失败时": "When failed", + "尚未加载": "Not loaded yet", + "配合前缀可以把你的输入内容用引号圈起来": "With the prefix, you can enclose your input content in quotation marks", + "我好!": "I'm good!", + "默认 False": "Default False", + "的依赖": "Dependencies of", + "并设置参数": "and set parameters", + "会被加在你的输入之后": "Will be added after your input", + "安装": "Installation", + "一个单实例装饰器": "Single instance decorator", + "自定义API KEY格式": "Customize API KEY format", + "的参数": "Parameters of", + "api2d等请求源": "api2d and other request sources", + "逆转出错的段落": "Reverse the wrong paragraph", + "没有设置ANTHROPIC_API_KEY": "ANTHROPIC_API_KEY is not set", + "默认 True": "Default True", + "本项目现已支持OpenAI和Azure的api-key": "This project now supports OpenAI and Azure's api-key", + "即可见": "Visible immediately", + "请问什么是质子": "What is a proton?", + "按钮是否可见": "Is the button visible?", + "调用": "Call", + "如果要使用": "If you want to use", + "的参数!": "parameters!", + "例如翻译、解释代码、润色等等": "such as translation, code interpretation, polishing, etc.", + "响应异常": "Response exception", + "响应中": "Responding", + "请尝试英文Prompt": "Try English Prompt", + "在运行过程中动态地修改多个配置": "Dynamically modify multiple configurations during runtime", + "无法调用相关功能": "Unable to invoke related functions", + "接驳虚空终端": "Connect to Void Terminal", + "虚空终端插件的功能": "Functionality of Void Terminal plugin", + "执行任意插件的命令": "Execute commands of any plugin", + "修改调用函数": "Modify calling function", + "获取简单聊天的默认参数": "Get default parameters for simple chat", + "根据自然语言的描述": "Based on natural language description", + "获取插件的句柄": "Get handle of plugin", + "第四部分": "Part Four", + "在运行过程中动态地修改配置": "Dynamically modify configurations during runtime", + "请先把模型切换至gpt-*或者api2d-*": "Please switch the model to gpt-* or api2d-* first", + "获取简单聊天的句柄": "Get handle of simple chat", + "获取插件的默认参数": "Get default parameters of plugin" } \ No newline at end of file diff --git a/docs/translate_japanese.json b/docs/translate_japanese.json index 9ea37c8eef6e6bee28b0da802eb693509e2f488e..15a4b31949485c4bfeafaf0851287bbea37bc9de 100644 --- a/docs/translate_japanese.json +++ b/docs/translate_japanese.json @@ -939,7 +939,6 @@ "以下は学術論文の基本情報です": "以下は学術論文の基本情報です", "出力が不完全になる原因となる": "出力が不完全になる原因となる", "ハイフンを使って": "ハイフンを使って", - "シングルスレッド": "シングルスレッド", "请先把模型切换至gpt-xxxx或者api2d-xxxx": "Please switch the model to gpt-xxxx or api2d-xxxx first.", "路径或网址": "Path or URL", "*代表通配符": "* represents a wildcard", @@ -1484,5 +1483,632 @@ "请提交新问题": "新しい問題を提出してください", "您正在调用一个": "あなたは呼び出しています", "请编辑以下文本": "以下のテキストを編集してください", - "常见协议无非socks5h/http": "一般的なプロトコルはsocks5h/http以外ありません" + "常见协议无非socks5h/http": "一般的なプロトコルはsocks5h/http以外ありません", + "Latex英文纠错": "LatexEnglishErrorCorrection", + "连接bing搜索回答问题": "ConnectBingSearchAnswerQuestion", + "联网的ChatGPT_bing版": "OnlineChatGPT_BingVersion", + "总结音视频": "SummarizeAudioVideo", + "动画生成": "GenerateAnimation", + "数学动画生成manim": "GenerateMathematicalAnimationManim", + "Markdown翻译指定语言": "TranslateMarkdownSpecifiedLanguage", + "知识库问答": "KnowledgeBaseQuestionAnswer", + "Langchain知识库": "LangchainKnowledgeBase", + "读取知识库作答": "ReadKnowledgeBaseAnswer", + "交互功能模板函数": "InteractiveFunctionTemplateFunction", + "交互功能函数模板": "InteractiveFunctionFunctionTemplate", + "Latex英文纠错加PDF对比": "LatexEnglishErrorCorrectionWithPDFComparison", + "Latex输出PDF结果": "LatexOutputPDFResult", + "Latex翻译中文并重新编译PDF": "TranslateChineseAndRecompilePDF", + "语音助手": "VoiceAssistant", + "微调数据集生成": "FineTuneDatasetGeneration", + "chatglm微调工具": "ChatGLMFineTuningTool", + "启动微调": "StartFineTuning", + "sprint亮靛": "SprintAzureIndigo", + "专业词汇声明": "ProfessionalVocabularyDeclaration", + "Latex精细分解与转化": "LatexDetailedDecompositionAndConversion", + "编译Latex": "CompileLatex", + "将代码转为动画": "コードをアニメーションに変換する", + "解析arxiv网址失败": "arxivのURLの解析に失敗しました", + "其他模型转化效果未知": "他のモデルの変換効果は不明です", + "把文件复制过去": "ファイルをコピーする", + "!!!如果需要运行量化版本": "!!!量子化バージョンを実行する必要がある場合", + "报错信息如下. 如果是与网络相关的问题": "エラーメッセージは次のとおりです。ネットワークに関連する問題の場合", + "请检查ALIYUN_TOKEN和ALIYUN_APPKEY是否过期": "ALIYUN_TOKENとALIYUN_APPKEYの有効期限を確認してください", + "编译结束": "コンパイル終了", + "只读": "読み取り専用", + "模型选择是": "モデルの選択は", + "正在从github下载资源": "GitHubからリソースをダウンロードしています", + "同时分解长句": "同時に長い文を分解する", + "寻找主tex文件": "メインのtexファイルを検索する", + "例如您可以将以下命令复制到下方": "たとえば、以下のコマンドを下にコピーできます", + "使用中文总结音频“": "中国語で音声を要約する", + "此处填API密钥": "ここにAPIキーを入力してください", + "裁剪输入": "入力をトリミングする", + "当前语言模型温度设定": "現在の言語モデルの温度設定", + "history 是之前的对话列表": "historyは以前の対話リストです", + "对输入的word文档进行摘要生成": "入力されたWord文書の要約を生成する", + "输入问题后点击该插件": "質問を入力した後、このプラグインをクリックします", + "仅在Windows系统进行了测试": "Windowsシステムでのみテストされています", + "reverse 操作必须放在最后": "reverse操作は最後に配置する必要があります", + "即将编译PDF": "PDFをコンパイルする予定です", + "执行错误": "エラーが発生しました", + "段音频完成了吗": "セグメントのオーディオは完了しましたか", + "然后重启程序": "それからプログラムを再起動してください", + "是所有LLM的通用接口": "これはすべてのLLMの共通インターフェースです", + "当前报错的latex代码处于第": "現在のエラーのあるLaTeXコードは第", + "🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行": "🏃‍♂️🏃‍♂️🏃‍♂️ サブプロセスの実行", + "用来描述你的要求": "要求を説明するために使用されます", + "原始PDF编译是否成功": "元のPDFのコンパイルは成功しましたか", + "本地Latex论文精细翻译": "ローカルのLaTeX論文の詳細な翻訳", + "设置OpenAI密钥和模型": "OpenAIキーとモデルの設定", + "如果使用ChatGLM2微调模型": "ChatGLM2ファインチューニングモデルを使用する場合", + "项目Github地址 \\url{https": "プロジェクトのGithubアドレス \\url{https", + "将前后断行符脱离": "前後の改行文字を削除します", + "该项目的Latex主文件是": "このプロジェクトのLaTeXメインファイルは", + "编译已经开始": "コンパイルが開始されました", + "*{\\scriptsize\\textbf{警告": "*{\\scriptsize\\textbf{警告", + "从一批文件": "一連のファイルから", + "等待用户的再次调用": "ユーザーの再呼び出しを待っています", + "目前仅支持GPT3.5/GPT4": "現在、GPT3.5/GPT4のみをサポートしています", + "如果一句话小于7个字": "1つの文が7文字未満の場合", + "目前对机器学习类文献转化效果最好": "現在、機械学習の文献変換効果が最も良いです", + "寻找主文件": "メインファイルを検索中", + "解除插件状态": "プラグインの状態を解除します", + "默认为Chinese": "デフォルトはChineseです", + "依赖不足": "不足の依存関係", + "编译文献交叉引用": "文献の相互参照をコンパイルする", + "对不同latex源文件扣分": "異なるLaTeXソースファイルに罰則を課す", + "再列出用户可能提出的三个问题": "ユーザーが提出する可能性のある3つの問題を再リスト化する", + "建议排查": "トラブルシューティングの提案", + "生成时间戳": "タイムスタンプの生成", + "检查config中的AVAIL_LLM_MODELS选项": "configのAVAIL_LLM_MODELSオプションを確認する", + "chatglmft 没有 sys_prompt 接口": "chatglmftにはsys_promptインターフェースがありません", + "在一个异步线程中采集音频": "非同期スレッドでオーディオを収集する", + "初始化插件状态": "プラグインの状態を初期化する", + "内含已经翻译的Tex文档": "翻訳済みのTexドキュメントが含まれています", + "请注意自我隐私保护哦!": "プライバシー保護に注意してください!", + "使用正则表达式查找半行注释": "正規表現を使用して半行コメントを検索する", + "不能正常加载ChatGLMFT的参数!": "ChatGLMFTのパラメータを正常にロードできません!", + "首先你在中文语境下通读整篇论文": "まず、中国語の文脈で論文全体を読んでください", + "如 绿帽子*深蓝色衬衫*黑色运动裤": "例えば、緑の帽子*濃い青のシャツ*黒のスポーツパンツ", + "默认为default": "デフォルトはdefaultです", + "将": "置き換える", + "使用 Unsplash API": "Unsplash APIを使用する", + "会被加在你的输入之前": "あなたの入力の前に追加されます", + "还需要填写组织": "組織を入力する必要があります", + "test_LangchainKnowledgeBase读取": "test_LangchainKnowledgeBaseの読み込み", + "目前不支持历史消息查询": "現在、過去のメッセージのクエリはサポートされていません", + "临时存储用于调试": "デバッグ用の一時的なストレージ", + "提取总结": "テキストの翻訳", + "每秒采样数量": "テキストの翻訳", + "但通常不会出现在正文": "テキストの翻訳", + "通过调用conversations_open方法打开一个频道": "テキストの翻訳", + "导致输出不完整": "テキストの翻訳", + "获取已打开频道的最新消息并返回消息列表": "テキストの翻訳", + "Tex源文件缺失!": "テキストの翻訳", + "如果需要使用Slack Claude": "テキストの翻訳", + "扭转的范围": "テキストの翻訳", + "使用latexdiff生成论文转化前后对比": "テキストの翻訳", + "--读取文件": "テキストの翻訳", + "调用openai api 使用whisper-1模型": "テキストの翻訳", + "避免遗忘导致死锁": "テキストの翻訳", + "在多Tex文档中": "テキストの翻訳", + "失败时": "テキストの翻訳", + "然后转移到指定的另一个路径中": "テキストの翻訳", + "使用Newbing": "テキストの翻訳", + "的参数": "テキストの翻訳", + "后者是OPENAI的结束条件": "テキストの翻訳", + "构建知识库": "テキストの翻訳", + "吸收匿名公式": "テキストの翻訳", + "前缀": "テキストの翻訳", + "会直接转到该函数": "テキストの翻訳", + "Claude失败": "テキストの翻訳", + "P.S. 但愿没人把latex模板放在里面传进来": "P.S. 但愿没人把latex模板放在里面传进来", + "临时地启动代理网络": "临时地启动代理网络", + "读取文件内容到内存": "読み込んだファイルの内容をメモリに保存する", + "总结音频": "音声をまとめる", + "没有找到任何可读取文件": "読み込み可能なファイルが見つかりません", + "获取Slack消息失败": "Slackメッセージの取得に失敗しました", + "用黑色标注转换区": "黒い注釈で変換エリアをマークする", + "此插件处于开发阶段": "このプラグインは開発中です", + "其他操作系统表现未知": "他のオペレーティングシステムの動作は不明です", + "返回找到的第一个": "最初に見つかったものを返す", + "发现已经存在翻译好的PDF文档": "翻訳済みのPDFドキュメントが既に存在することがわかりました", + "不包含任何可用于": "使用できるものは含まれていません", + "发送到openai音频解析终端": "openai音声解析端に送信する", + "========================================= 插件主程序2 =====================================================": "========================================= プラグインメインプログラム2 =====================================================", + "正在重试": "再試行中", + "从而更全面地理解项目的整体功能": "プロジェクトの全体的な機能をより理解するために", + "正在等您说完问题": "質問が完了するのをお待ちしています", + "使用教程详情见 request_llm/README.md": "使用方法の詳細については、request_llm/README.mdを参照してください", + "6.25 加入判定latex模板的代码": "6.25 テンプレートの判定コードを追加", + "找不到任何音频或视频文件": "音声またはビデオファイルが見つかりません", + "请求GPT模型的": "GPTモデルのリクエスト", + "行": "行", + "分析上述回答": "上記の回答を分析する", + "如果要使用ChatGLMFT": "ChatGLMFTを使用する場合", + "上传Latex项目": "Latexプロジェクトをアップロードする", + "如参考文献、脚注、图注等": "参考文献、脚注、図のキャプションなど", + "未配置": "設定されていません", + "请在此处给出自定义翻译命令": "カスタム翻訳コマンドをここに入力してください", + "第二部分": "第2部分", + "解压失败! 需要安装pip install py7zr来解压7z文件": "解凍に失敗しました!7zファイルを解凍するにはpip install py7zrをインストールする必要があります", + "吸收在42行以内的begin-end组合": "42行以内のbegin-endの組み合わせを取り込む", + "Latex文件融合完成": "Latexファイルの統合が完了しました", + "输出html调试文件": "HTMLデバッグファイルの出力", + "论文概况": "論文の概要", + "修复括号": "括弧の修復", + "赋予插件状态": "プラグインの状態を付与する", + "标注节点的行数范围": "ノードの行数範囲を注釈する", + "MOSS can understand and communicate fluently in the language chosen by the user such as English and 中文. MOSS can perform any language-based tasks.": "MOSSは、ユーザーが選択した言語(英語や中文など)でスムーズに理解し、コミュニケーションすることができます。MOSSは、言語に基づくさまざまなタスクを実行できます。", + "LLM_MODEL是默认选中的模型": "LLM_MODELはデフォルトで選択されたモデルです", + "配合前缀可以把你的输入内容用引号圈起来": "接頭辞と組み合わせて、入力内容を引用符で囲むことができます", + "获取关键词": "キーワードの取得", + "本项目现已支持OpenAI和Azure的api-key": "このプロジェクトは、OpenAIおよびAzureのAPIキーをサポートしています", + "欢迎使用 MOSS 人工智能助手!": "MOSS AIアシスタントをご利用いただきありがとうございます!", + "在执行完成之后": "実行が完了した後", + "正在听您讲话": "お話をお聞きしています", + "Claude回复的片段": "Claudeの返信の一部", + "返回": "戻る", + "期望格式例如": "期待される形式の例", + "gpt 多线程请求": "GPTマルチスレッドリクエスト", + "当前工作路径为": "現在の作業パスは", + "该PDF由GPT-Academic开源项目调用大语言模型+Latex翻译插件一键生成": "このPDFはGPT-Academicオープンソースプロジェクトによって大規模言語モデル+Latex翻訳プラグインを使用して一括生成されました", + "解决插件锁定时的界面显示问题": "プラグインのロック時のインターフェース表示の問題を解決する", + "默认 secondary": "デフォルトのセカンダリ", + "会把列表拆解": "リストを分解します", + "暂时不支持历史消息": "一時的に歴史メッセージはサポートされていません", + "或者重启之后再度尝试": "または再起動後に再試行してください", + "吸收其他杂项": "他の雑項を吸収する", + "双手离开鼠标键盘吧": "両手をマウスとキーボードから離してください", + "建议更换代理协议": "プロキシプロトコルの変更をお勧めします", + "音频助手": "オーディオアシスタント", + "请耐心等待": "お待ちください", + "翻译结果": "翻訳結果", + "请在此处追加更细致的矫错指令": "ここにより詳細なエラー修正命令を追加してください", + "编译原始PDF": "元のPDFをコンパイルする", + "-构建知识库": "-ナレッジベースの構築", + "删除中间文件夹": "中間フォルダを削除する", + "这段代码定义了一个名为TempProxy的空上下文管理器": "このコードはTempProxyという名前の空のコンテキストマネージャを定義しています", + "参数说明": "パラメータの説明", + "正在预热文本向量化模组": "テキストベクトル化モジュールのプリヒート中", + "函数插件": "関数プラグイン", + "右下角更换模型菜单中可切换openai": "右下のモデルメニューでopenaiを切り替えることができます", + "先上传数据集": "まずデータセットをアップロードしてください", + "LatexEnglishErrorCorrection+高亮修正位置": "テキストの翻訳", + "正在构建知识库": "テキストの翻訳", + "用红色标注处保留区": "テキストの翻訳", + "安装Claude的依赖": "テキストの翻訳", + "已禁用": "テキストの翻訳", + "是否在提交时自动清空输入框": "テキストの翻訳", + "GPT 学术优化": "テキストの翻訳", + "需要特殊依赖": "テキストの翻訳", + "test_联网回答问题": "テキストの翻訳", + "除非您是论文的原作者": "テキストの翻訳", + "即可见": "テキストの翻訳", + "解析为简体中文": "テキストの翻訳", + "解析整个Python项目": "テキストの翻訳", + "========================================= 插件主程序1 =====================================================": "テキストの翻訳", + "当前参数": "テキストの翻訳", + "处理个别特殊插件的锁定状态": "テキストの翻訳", + "已知某些代码的局部作用是": "テキストの翻訳", + "请务必用 pip install -r requirements.txt 指令安装依赖": "テキストの翻訳", + "安装": "テキストの翻訳", + "请登录OpenAI查看详情 https": "テキストの翻訳", + "必须包含documentclass": "テキストの翻訳", + "极少数情况下": "テキストの翻訳", + "并将返回的频道ID保存在属性CHANNEL_ID中": "テキストの翻訳", + "您的 API_KEY 不满足任何一种已知的密钥格式": "テキストの翻訳", + "-预热文本向量化模组": "テキストの翻訳", + "什么都没有": "テキストの翻訳", + "等待GPT响应": "テキストの翻訳", + "请尝试把以下指令复制到高级参数区": "テキストの翻訳", + "模型参数": "テキストの翻訳", + "先删除": "テキストの翻訳", + "响应中": "テキストの翻訳", + "开始接收chatglmft的回复": "テキストの翻訳", + "手动指定语言": "テキストの翻訳", + "获取线程锁": "テキストの翻訳", + "当前大语言模型": "テキストの翻訳", + "段音频的第": "テキストの翻訳", + "正在编译对比PDF": "テキストの翻訳", + "根据需要切换prompt": "テキストの翻訳", + "取评分最高者返回": "テキストの翻訳", + "如果您是论文原作者": "テキストの翻訳", + "段音频的主要内容": "テキストの翻訳", + "为啥chatgpt会把cite里面的逗号换成中文逗号呀": "テキストの翻訳", + "为每一位访问的用户赋予一个独一无二的uuid编码": "テキストの翻訳", + "将每次对话记录写入Markdown格式的文件中": "テキストの翻訳", + "ChatGLMFT尚未加载": "テキストの翻訳", + "切割音频文件": "テキストの翻訳", + "例如 f37f30e0f9934c34a992f6f64f7eba4f": "テキストの翻訳", + "work_folder = Latex预处理": "テキストの翻訳", + "出问题了": "問題が発生しました", + "等待Claude响应中": "Claudeの応答を待っています", + "增强稳健性": "信頼性を向上させる", + "赋予插件锁定 锁定插件回调路径": "プラグインにコールバックパスをロックする", + "将多文件tex工程融合为一个巨型tex": "複数のファイルのtexプロジェクトを1つの巨大なtexに統合する", + "参考文献转Bib": "参考文献をBibに変換する", + "由于提问含不合规内容被Azure过滤": "質問が規則に違反しているため、Azureによってフィルタリングされました", + "读取优先级": "優先度を読み取る", + "格式如org-xxxxxxxxxxxxxxxxxxxxxxxx": "形式はorg-xxxxxxxxxxxxxxxxxxxxxxxxのようです", + "辅助gpt生成代码": "GPTのコード生成を補助する", + "读取音频文件": "音声ファイルを読み取る", + "输入arxivID": "arxivIDを入力する", + "转化PDF编译是否成功": "PDFのコンパイルが成功したかどうかを変換する", + "Call ChatGLMFT fail 不能正常加载ChatGLMFT的参数": "ChatGLMFTのパラメータを正常にロードできませんでした", + "创建AcsClient实例": "AcsClientのインスタンスを作成する", + "将 chatglm 直接对齐到 chatglm2": "chatglmをchatglm2に直接整列させる", + "要求": "要求", + "子任务失败时的重试次数": "サブタスクが失敗した場合のリトライ回数", + "请求子进程": "サブプロセスを要求する", + "按钮是否可见": "ボタンが表示可能かどうか", + "将 \\include 命令转换为 \\input 命令": "\\includeコマンドを\\inputコマンドに変換する", + "用户填3": "ユーザーが3を入力する", + "后面是英文逗号": "後ろに英語のカンマがあります", + "吸收iffalse注释": "iffalseコメントを吸収する", + "请稍候": "お待ちください", + "摘要生成后的文档路径": "要約生成後のドキュメントのパス", + "主程序即将开始": "メインプログラムがすぐに開始されます", + "处理历史信息": "履歴情報の処理", + "根据给定的切割时长将音频文件切割成多个片段": "指定された分割時間に基づいてオーディオファイルを複数のセグメントに分割する", + "解决部分词汇翻译不准确的问题": "一部の用語の翻訳の不正確さを解決する", + "即将退出": "すぐに終了します", + "用于给一小段代码上代理": "一部のコードにプロキシを適用するために使用されます", + "提取文件扩展名": "ファイルの拡張子を抽出する", + "目前支持的格式": "現在サポートされている形式", + "第一次调用": "最初の呼び出し", + "异步方法": "非同期メソッド", + "P.S. 顺便把Latex的注释去除": "P.S. LaTeXのコメントを削除する", + "构建完成": "ビルドが完了しました", + "缺少": "不足しています", + "建议暂时不要使用": "一時的に使用しないことをお勧めします", + "对比PDF编译是否成功": "PDFのコンパイルが成功したかどうかを比較する", + "填入azure openai api的密钥": "Azure OpenAI APIのキーを入力してください", + "功能尚不稳定": "機能はまだ安定していません", + "则跳过GPT请求环节": "GPTリクエストのスキップ", + "即不处理之前的对话历史": "以前の対話履歴を処理しない", + "非Openai官方接口返回了错误": "非公式のOpenAI APIがエラーを返しました", + "其他类型文献转化效果未知": "他のタイプの文献の変換効果は不明です", + "给出一些判定模板文档的词作为扣分项": "テンプレートドキュメントの単語を減点項目として提供する", + "找 API_ORG 设置项": "API_ORGの設定項目を検索します", + "调用函数": "関数を呼び出します", + "需要手动安装新增的依赖库": "新しい依存ライブラリを手動でインストールする必要があります", + "或者使用此插件继续上传更多文件": "または、このプラグインを使用してさらにファイルをアップロードします", + "640个字节为一组": "640バイトごとにグループ化します", + "逆转出错的段落": "エラーのあるパラグラフを逆転させます", + "对话助手函数插件": "対話アシスタント関数プラグイン", + "前者是API2D的结束条件": "前者はAPI2Dの終了条件です", + "终端": "ターミナル", + "仅调试": "デバッグのみ", + "论文": "論文", + "想象一个穿着者": "着用者を想像してください", + "音频内容是": "音声の内容は", + "如果需要使用AZURE 详情请见额外文档 docs\\use_azure.md": "AZUREを使用する必要がある場合は、詳細については別のドキュメント docs\\use_azure.md を参照してください", + "请先将.doc文档转换为.docx文档": ".docドキュメントを.docxドキュメントに変換してください", + "请查看终端的输出或耐心等待": "ターミナルの出力を確認するか、お待ちください", + "初始化音频采集线程": "オーディオキャプチャスレッドを初期化します", + "用该压缩包+ConversationHistoryArchive进行反馈": "この圧縮ファイル+ConversationHistoryArchiveを使用してフィードバックします", + "阿里云实时语音识别 配置难度较高 仅建议高手用户使用 参考 https": "阿里云リアルタイム音声認識の設定は難しいため、上級ユーザーのみに推奨されます 参考 https", + "多线程翻译开始": "マルチスレッド翻訳が開始されました", + "只有GenerateImage和生成图像相关": "GenerateImageと関連する画像の生成のみ", + "代理数据解析失败": "プロキシデータの解析に失敗しました", + "建议使用英文单词": "英単語の使用をお勧めします", + "功能描述": "機能の説明", + "读 docs\\use_azure.md": "ドキュメントを読む", + "将消耗较长时间下载中文向量化模型": "中国語のベクトル化モデルをダウンロードするのに時間がかかります", + "表示频道ID": "チャネルIDを表示する", + "未知指令": "不明なコマンド", + "包含documentclass关键字": "documentclassキーワードを含む", + "中读取数据构建知识库": "データを読み取って知識ベースを構築する", + "远程云服务器部署": "リモートクラウドサーバーにデプロイする", + "输入部分太自由": "入力が自由すぎる", + "读取pdf文件": "PDFファイルを読み込む", + "将两个PDF拼接": "2つのPDFを結合する", + "默认值为1000": "デフォルト値は1000です", + "写出文件": "ファイルに書き出す", + "生成的视频文件路径": "生成されたビデオファイルのパス", + "Arixv论文精细翻译": "Arixv論文の詳細な翻訳", + "用latex编译为PDF对修正处做高亮": "LaTeXでコンパイルしてPDFに修正をハイライトする", + "点击“停止”键可终止程序": "「停止」ボタンをクリックしてプログラムを終了できます", + "否则将导致每个人的Claude问询历史互相渗透": "さもないと、各人のClaudeの問い合わせ履歴が相互に侵入します", + "音频文件名": "オーディオファイル名", + "的参数!": "のパラメータ!", + "对话历史": "対話履歴", + "当下一次用户提交时": "次のユーザーの提出時に", + "数学GenerateAnimation": "数学GenerateAnimation", + "如果要使用Claude": "Claudeを使用する場合は", + "请向下翻": "下にスクロールしてください", + "报告已经添加到右侧“文件上传区”": "報告は右側の「ファイルアップロードエリア」に追加されました", + "删除整行的空注释": "空のコメントを含む行を削除する", + "建议直接在API_KEY处填写": "API_KEYの場所に直接入力することをお勧めします", + "暗色模式 / 亮色模式": "ダークモード/ライトモード", + "做一些外观色彩上的调整": "外観の色調整を行う", + "请切换至“KnowledgeBaseQuestionAnswer”插件进行知识库访问": "ナレッジベースのアクセスには「KnowledgeBaseQuestionAnswer」プラグインに切り替えてください", + "它*必须*被包含在AVAIL_LLM_MODELS列表中": "それはAVAIL_LLM_MODELSリストに含まれている必要があります", + "并设置参数": "パラメータを設定する", + "待处理的word文档路径": "処理待ちのWord文書のパス", + "调用缓存": "キャッシュを呼び出す", + "片段": "フラグメント", + "否则结束循环": "それ以外の場合はループを終了する", + "请对下面的音频片段做概述": "以下のオーディオフラグメントについて概要を作成してください", + "高危设置! 常规情况下不要修改! 通过修改此设置": "高リスクの設定!通常は変更しないでください!この設定を変更することで", + "插件锁定中": "プラグインがロックされています", + "开始": "開始", + "但请查收结果": "結果を確認してください", + "刷新Gradio前端界面": "Gradioフロントエンドインターフェースをリフレッシュする", + "批量SummarizeAudioVideo": "オーディオビデオを一括要約する", + "一个单实例装饰器": "単一のインスタンスデコレータ", + "Claude响应异常": "Claudeの応答が異常です", + "但内部用stream的方法避免中途网线被掐": "ただし、途中でネットワーク接続が切断されることを避けるために、内部ではストリームを使用しています", + "检查USE_PROXY": "USE_PROXYを確認する", + "永远给定None": "常にNoneを指定する", + "报告如何远程获取": "報告のリモート取得方法", + "您可以到Github Issue区": "GithubのIssueエリアにアクセスできます", + "如果只询问1个大语言模型": "1つの大規模言語モデルにのみ質問する場合", + "为了防止大语言模型的意外谬误产生扩散影响": "大規模言語モデルの誤った結果が広がるのを防ぐために", + "编译BibTex": "BibTexのコンパイル", + "⭐多线程方法": "マルチスレッドの方法", + "推荐http": "httpをおすすめします", + "如果要使用": "使用する場合", + "的单词": "の単語", + "如果本地使用不建议加这个": "ローカルで使用する場合はお勧めしません", + "避免线程阻塞": "スレッドのブロックを回避する", + "吸收title与作者以上的部分": "タイトルと著者以上の部分を吸収する", + "作者": "著者", + "5刀": "5ドル", + "ChatGLMFT响应异常": "ChatGLMFTの応答異常", + "才能继续下面的步骤": "次の手順に進むために", + "对这个人外貌、身处的环境、内心世界、过去经历进行描写": "この人の外見、環境、内面世界、過去の経験について描写する", + "找不到微调模型检查点": "ファインチューニングモデルのチェックポイントが見つかりません", + "请仔细鉴别并以原文为准": "注意深く確認し、元のテキストを参照してください", + "计算文件总时长和切割点": "ファイルの総時間とカットポイントを計算する", + "我将为您查找相关壁纸": "関連する壁紙を検索します", + "此插件Windows支持最佳": "このプラグインはWindowsに最適です", + "请输入关键词": "キーワードを入力してください", + "以下所有配置也都支持利用环境变量覆写": "以下のすべての設定は環境変数を使用して上書きすることもサポートしています", + "尝试第": "第#", + "开始生成动画": "アニメーションの生成を開始します", + "免费": "無料", + "我好!": "私は元気です!", + "str类型": "strタイプ", + "生成数学动画": "数学アニメーションの生成", + "GPT结果已输出": "GPTの結果が出力されました", + "PDF文件所在的路径": "PDFファイルのパス", + "源码自译解": "ソースコードの自動翻訳解析", + "格式如org-123456789abcdefghijklmno的": "org-123456789abcdefghijklmnoの形式", + "请对这部分内容进行语法矫正": "この部分の内容に文法修正を行ってください", + "调用whisper模型音频转文字": "whisperモデルを使用して音声をテキストに変換する", + "编译转化后的PDF": "変換されたPDFをコンパイルする", + "将音频解析为简体中文": "音声を簡体字中国語に解析する", + "删除或修改歧义文件": "曖昧なファイルを削除または修正する", + "ChatGLMFT消耗大量的内存": "ChatGLMFTは大量のメモリを消費します", + "图像生成所用到的提示文本": "画像生成に使用されるヒントテキスト", + "如果已经存在": "既に存在する場合", + "以下是一篇学术论文的基础信息": "以下は学術論文の基本情報です", + "解压失败! 需要安装pip install rarfile来解压rar文件": "解凍に失敗しました!rarファイルを解凍するにはpip install rarfileをインストールする必要があります", + "一般是文本过长": "通常、テキストが長すぎます", + "单线程": "シングルスレッド", + "Linux下必须使用Docker安装": "LinuxではDockerを使用してインストールする必要があります", + "请先上传文件素材": "まずファイル素材をアップロードしてください", + "如果分析错误": "もし解析エラーがある場合", + "快捷的调试函数": "便利なデバッグ関数", + "欢迎使用 MOSS 人工智能助手!输入内容即可进行对话": "MOSS AIアシスタントをご利用いただきありがとうございます!入力内容を入力すると、対話ができます", + "json等": "jsonなど", + "--读取参数": "--パラメータの読み込み", + "⭐单线程方法": "⭐シングルスレッドメソッド", + "请用一句话概括这些文件的整体功能": "これらのファイルの全体的な機能を一文で要約してください", + "用于灵活调整复杂功能的各种参数": "複雑な機能を柔軟に調整するためのさまざまなパラメータ", + "默认 False": "デフォルトはFalseです", + "生成中文PDF": "中国語のPDFを生成する", + "正在处理": "処理中", + "需要被切割的音频文件名": "分割する必要のある音声ファイル名", + "根据文本使用GPT模型生成相应的图像": "テキストに基づいてGPTモデルを使用して対応する画像を生成する", + "可选": "オプション", + "Aliyun音频服务异常": "Aliyunオーディオサービスの異常", + "尝试下载": "ダウンロードを試みる", + "需Latex": "LaTeXが必要です", + "拆分过长的Markdown文件": "長すぎるMarkdownファイルを分割する", + "当前支持的格式包括": "現在サポートされている形式には", + "=================================== 工具函数 ===============================================": "=================================== ユーティリティ関数 ===============================================", + "所有音频都总结完成了吗": "すべてのオーディオが要約されましたか", + "没有设置ANTHROPIC_API_KEY": "ANTHROPIC_API_KEYが設定されていません", + "详见项目主README.md": "詳細はプロジェクトのメインREADME.mdを参照してください", + "使用": "使用する", + "P.S. 其他可用的模型还包括": "P.S. 其他可用的模型还包括", + "保证括号正确": "保证括号正确", + "或代理节点": "或代理节点", + "整理结果为压缩包": "整理结果为压缩包", + "实时音频采集": "实时音频采集", + "获取回复": "获取回复", + "插件可读取“输入区”文本/路径作为参数": "插件可读取“输入区”文本/路径作为参数", + "请讲话": "请讲话", + "将文件复制一份到下载区": "将文件复制一份到下载区", + "from crazy_functions.虚空终端 import 终端": "from crazy_functions.虚空终端 import 终端", + "这个paper有个input命令文件名大小写错误!": "这个paper有个input命令文件名大小写错误!", + "解除插件锁定": "解除插件锁定", + "不能加载Claude组件": "不能加载Claude组件", + "如果有必要": "如果有必要", + "禁止移除或修改此警告": "禁止移除或修改此警告", + "然后进行问答": "然后进行问答", + "响应异常": "响应异常", + "使用英文": "使用英文", + "add gpt task 创建子线程请求gpt": "add gpt task 创建子线程请求gpt", + "实际得到格式": "实际得到格式", + "请继续分析其他源代码": "请继续分析其他源代码", + "”的主要内容": "”的主要内容", + "防止proxies单独起作用": "防止proxies单独起作用", + "临时地激活代理网络": "临时地激活代理网络", + "屏蔽空行和太短的句子": "屏蔽空行和太短的句子", + "把某个路径下所有文件压缩": "把某个路径下所有文件压缩", + "您需要首先调用构建知识库": "您需要首先调用构建知识库", + "翻译-": "翻译-", + "Newbing 请求失败": "Newbing 请求失败", + "次编译": "次编译", + "后缀": "后缀", + "文本碎片重组为完整的tex片段": "文本碎片重组为完整的tex片段", + "待注入的知识库名称id": "待注入的知识库名称id", + "消耗时间的函数": "消耗时间的函数", + "You are associated with a deactivated account. OpenAI以账户失效为由": "You are associated with a deactivated account. OpenAI以账户失效为由", + "成功啦": "成功啦", + "音频文件的路径": "音频文件的路径", + "英文Latex项目全文纠错": "英文Latex项目全文纠错", + "将子线程的gpt结果写入chatbot": "将子线程的gpt结果写入chatbot", + "开始最终总结": "开始最终总结", + "调用": "调用", + "正在锁定插件": "正在锁定插件", + "记住当前的label": "记住当前的label", + "根据自然语言执行插件命令": "根据自然语言执行插件命令", + "response中会携带traceback报错信息": "response中会携带traceback报错信息", + "避免多用户干扰": "避免多用户干扰", + "顺利完成": "顺利完成", + "详情见https": "详情见https", + "清空label": "ラベルをクリアする", + "这需要一段时间计算": "これには時間がかかります", + "找不到": "見つかりません", + "消耗大量的内存": "大量のメモリを消費する", + "安装方法https": "インストール方法https", + "为发送请求做准备": "リクエストの準備をする", + "第1次尝试": "1回目の試み", + "检查结果": "結果をチェックする", + "精细切分latex文件": "LaTeXファイルを細かく分割する", + "api2d等请求源": "api2dなどのリクエストソース", + "填入你亲手写的部署名": "あなたが手書きしたデプロイ名を入力してください", + "给出指令": "指示を与える", + "请问什么是质子": "プロトンとは何ですか", + "请直接去该路径下取回翻译结果": "直接そのパスに移動して翻訳結果を取得してください", + "等待Claude回复的片段": "Claudeの返信を待っているフラグメント", + "Latex没有安装": "LaTeXがインストールされていません", + "文档越长耗时越长": "ドキュメントが長いほど時間がかかります", + "没有阿里云语音识别APPKEY和TOKEN": "阿里雲の音声認識のAPPKEYとTOKENがありません", + "分析结果": "結果を分析する", + "请立即终止程序": "プログラムを即座に終了してください", + "正在尝试自动安装": "自動インストールを試みています", + "请直接提交即可": "直接提出してください", + "将指定目录下的PDF文件从英文翻译成中文": "指定されたディレクトリ内のPDFファイルを英語から中国語に翻訳する", + "请查收结果": "結果を確認してください", + "上下布局": "上下布局", + "此处可以输入解析提示": "此处可以输入解析提示", + "前面是中文逗号": "前面是中文逗号", + "的依赖": "的依赖", + "材料如下": "材料如下", + "欢迎加REAME中的QQ联系开发者": "欢迎加REAME中的QQ联系开发者", + "开始下载": "開始ダウンロード", + "100字以内": "100文字以内", + "创建request": "リクエストの作成", + "创建存储切割音频的文件夹": "切り取られた音声を保存するフォルダの作成", + "⭐主进程执行": "⭐メインプロセスの実行", + "音频解析结果": "音声解析結果", + "Your account is not active. OpenAI以账户失效为由": "アカウントがアクティブではありません。OpenAIはアカウントの無効化を理由にしています", + "虽然PDF生成失败了": "PDFの生成に失敗しました", + "如果这里报错": "ここでエラーが発生した場合", + "前面是中文冒号": "前面は中国語のコロンです", + "SummarizeAudioVideo内容": "SummarizeAudioVideoの内容", + "openai的官方KEY需要伴随组织编码": "openaiの公式KEYは組織コードと一緒に必要です", + "是本次输入": "これは今回の入力です", + "色彩主体": "色彩の主体", + "Markdown翻译": "Markdownの翻訳", + "会被加在你的输入之后": "あなたの入力の後に追加されます", + "失败啦": "失敗しました", + "每个切割音频片段的时长": "各切り取り音声の長さ", + "拆分过长的latex片段": "原始文本", + "待提取的知识库名称id": "原始文本", + "在这里放一些网上搜集的demo": "原始文本", + "环境变量配置格式见docker-compose.yml": "原始文本", + "Claude组件初始化成功": "原始文本", + "尚未加载": "原始文本", + "等待Claude响应": "原始文本", + "重组": "原始文本", + "将文件添加到chatbot cookie中": "原始文本", + "回答完问题后": "原始文本", + "将根据报错信息修正tex源文件并重试": "原始文本", + "是否在触发时清除历史": "原始文本", + "尝试执行Latex指令失败": "原始文本", + "默认 True": "原始文本", + "文本碎片重组为完整的tex文件": "原始文本", + "注意事项": "原始文本", + "您接下来不能再使用其他插件了": "原始文本", + "属性": "原始文本", + "正在编译PDF文档": "原始文本", + "提取视频中的音频": "原始文本", + "正在同时咨询ChatGPT和ChatGLM……": "原始文本", + "Chuanhu-Small-and-Beautiful主题": "原始文本", + "版权归原文作者所有": "原始文本", + "如果程序停顿5分钟以上": "原始文本", + "请输入要翻译成哪种语言": "日本語", + "以秒为单位": "秒単位で", + "请以以下方式load模型!!!": "以下の方法でモデルをロードしてください!!!", + "使用时": "使用時", + "对这个人外貌、身处的环境、内心世界、人设进行描写": "この人の外見、環境、内面世界、キャラクターを描写する", + "例如翻译、解释代码、润色等等": "例えば翻訳、コードの説明、修正など", + "多线程Demo": "マルチスレッドデモ", + "不能正常加载": "正常にロードできません", + "还原部分原文": "一部の元のテキストを復元する", + "可以将自身的状态存储到cookie中": "自身の状態をcookieに保存することができます", + "释放线程锁": "スレッドロックを解放する", + "当前知识库内的有效文件": "現在のナレッジベース内の有効なファイル", + "也是可读的": "読み取り可能です", + "等待ChatGLMFT响应中": "ChatGLMFTの応答を待っています", + "输入 stop 以终止对话": "stopを入力して対話を終了します", + "对整个Latex项目进行纠错": "全体のLatexプロジェクトを修正する", + "报错信息": "エラーメッセージ", + "下载pdf文件未成功": "PDFファイルのダウンロードに失敗しました", + "正在加载Claude组件": "Claudeコンポーネントを読み込んでいます", + "格式": "フォーマット", + "Claude响应缓慢": "Claudeの応答が遅い", + "该选项即将被弃用": "このオプションはまもなく廃止されます", + "正常状态": "正常な状態", + "中文Bing版": "中国語Bing版", + "代理网络配置": "プロキシネットワークの設定", + "Openai 限制免费用户每分钟20次请求": "Openaiは無料ユーザーに対して1分間に20回のリクエスト制限を設けています", + "gpt写的": "gptで書かれた", + "向已打开的频道发送一条文本消息": "既に開いているチャンネルにテキストメッセージを送信する", + "缺少ChatGLMFT的依赖": "ChatGLMFTの依存関係が不足しています", + "注意目前不能多人同时调用Claude接口": "現在、複数の人が同時にClaudeインターフェースを呼び出すことはできません", + "或者不在环境变量PATH中": "または環境変数PATHに存在しません", + "提问吧! 但注意": "質問してください!ただし注意してください", + "因此选择GenerateImage函数": "したがって、GenerateImage関数を選択します", + "无法找到一个主Tex文件": "メインのTexファイルが見つかりません", + "转化PDF编译已经成功": "PDF変換コンパイルが成功しました", + "因为在同一个频道里存在多人使用时历史消息渗透问题": "同じチャンネルで複数の人が使用する場合、過去のメッセージが漏洩する問題があります", + "SlackClient类用于与Slack API进行交互": "SlackClientクラスはSlack APIとのインタラクションに使用されます", + "如果存在调试缓存文件": "デバッグキャッシュファイルが存在する場合", + "举例": "例を挙げる", + "无需填写": "記入する必要はありません", + "配置教程&视频教程": "設定チュートリアル&ビデオチュートリアル", + "最后一步处理": "最後のステップの処理", + "定位主Latex文件": "メインのLatexファイルを特定する", + "暂不提交": "一時的に提出しない", + "由于最为关键的转化PDF编译失败": "最も重要なPDF変換コンパイルが失敗したため", + "用第二人称": "第二人称を使用する", + "例如 RoPlZrM88DnAFkZK": "例えば RoPlZrM88DnAFkZK", + "没有设置ANTHROPIC_API_KEY选项": "ANTHROPIC_API_KEYオプションが設定されていません", + "找不到任何.tex文件": "テキストの翻訳", + "请您不要删除或修改这行警告": "テキストの翻訳", + "只有第二步成功": "テキストの翻訳", + "调用Claude时": "テキストの翻訳", + "输入 clear 以清空对话历史": "テキストの翻訳", + "= 2 通过一些Latex模板中常见": "テキストの翻訳", + "没给定指令": "テキストの翻訳", + "还原原文": "テキストの翻訳", + "自定义API KEY格式": "テキストの翻訳", + "防止丢失最后一条消息": "テキストの翻訳", + "方法": "テキストの翻訳", + "压缩包": "テキストの翻訳", + "对各个llm模型进行单元测试": "テキストの翻訳", + "导入依赖失败": "テキストの翻訳", + "详情信息见requirements.txt": "テキストの翻訳", + "翻译内容可靠性无保障": "テキストの翻訳", + "刷新页面即可以退出KnowledgeBaseQuestionAnswer模式": "テキストの翻訳", + "上传本地文件/压缩包供函数插件调用": "テキストの翻訳", + "循环监听已打开频道的消息": "テキストの翻訳", + "一个包含所有切割音频片段文件路径的列表": "テキストの翻訳", + "检测到arxiv文档连接": "テキストの翻訳", + "P.S. 顺便把CTEX塞进去以支持中文": "テキストの翻訳", + "后面是英文冒号": "テキストの翻訳", + "上传文件自动修正路径": "テキストの翻訳", + "实现消息发送、接收等功能": "メッセージの送受信などの機能を実現する", + "改变输入参数的顺序与结构": "入力パラメータの順序と構造を変更する", + "正在精细切分latex文件": "LaTeXファイルを細かく分割しています", + "读取文件": "ファイルを読み込んでいます" } \ No newline at end of file diff --git a/docs/translate_std.json b/docs/translate_std.json new file mode 100644 index 0000000000000000000000000000000000000000..8c47de9075d1e7f8f6fe550e4898ea1dc7e097f9 --- /dev/null +++ b/docs/translate_std.json @@ -0,0 +1,87 @@ +{ + "解析JupyterNotebook": "ParsingJupyterNotebook", + "Latex翻译中文并重新编译PDF": "TranslateChineseToEnglishInLatexAndRecompilePDF", + "联网的ChatGPT_bing版": "OnlineChatGPT_BingEdition", + "理解PDF文档内容标准文件输入": "UnderstandPdfDocumentContentStandardFileInput", + "Latex英文纠错加PDF对比": "CorrectEnglishInLatexWithPDFComparison", + "下载arxiv论文并翻译摘要": "DownloadArxivPaperAndTranslateAbstract", + "Markdown翻译指定语言": "TranslateMarkdownToSpecifiedLanguage", + "批量翻译PDF文档_多线程": "BatchTranslatePDFDocuments_MultiThreaded", + "下载arxiv论文翻译摘要": "DownloadArxivPaperTranslateAbstract", + "解析一个Python项目": "ParsePythonProject", + "解析一个Golang项目": "ParseGolangProject", + "代码重写为全英文_多线程": "RewriteCodeToEnglish_MultiThreaded", + "解析一个CSharp项目": "ParsingCSharpProject", + "删除所有本地对话历史记录": "DeleteAllLocalConversationHistoryRecords", + "批量Markdown翻译": "BatchTranslateMarkdown", + "连接bing搜索回答问题": "ConnectBingSearchAnswerQuestion", + "Langchain知识库": "LangchainKnowledgeBase", + "Latex输出PDF结果": "OutputPDFFromLatex", + "把字符太少的块清除为回车": "ClearBlocksWithTooFewCharactersToNewline", + "Latex精细分解与转化": "DecomposeAndConvertLatex", + "解析一个C项目的头文件": "ParseCProjectHeaderFiles", + "Markdown英译中": "TranslateMarkdownFromEnglishToChinese", + "Markdown中译英": "MarkdownChineseToEnglish", + "数学动画生成manim": "MathematicalAnimationGenerationManim", + "chatglm微调工具": "ChatGLMFineTuningTool", + "解析一个Rust项目": "ParseRustProject", + "解析一个Java项目": "ParseJavaProject", + "联网的ChatGPT": "ChatGPTConnectedToNetwork", + "解析任意code项目": "ParseAnyCodeProject", + "合并小写开头的段落块": "MergeLowercaseStartingParagraphBlocks", + "Latex英文润色": "EnglishProofreadingForLatex", + "Latex全文润色": "FullTextProofreadingForLatex", + "询问多个大语言模型": "InquiryMultipleLargeLanguageModels", + "解析一个Lua项目": "ParsingLuaProject", + "解析ipynb文件": "ParsingIpynbFiles", + "批量总结PDF文档": "BatchSummarizePDFDocuments", + "批量翻译PDF文档": "BatchTranslatePDFDocuments", + "理解PDF文档内容": "UnderstandPdfDocumentContent", + "Latex中文润色": "LatexChineseProofreading", + "Latex英文纠错": "LatexEnglishCorrection", + "Latex全文翻译": "LatexFullTextTranslation", + "同时问询_指定模型": "InquireSimultaneously_SpecifiedModel", + "批量生成函数注释": "BatchGenerateFunctionComments", + "解析一个前端项目": "ParseFrontendProject", + "高阶功能模板函数": "HighOrderFunctionTemplateFunctions", + "高级功能函数模板": "AdvancedFunctionTemplate", + "总结word文档": "SummarizingWordDocuments", + "载入对话历史存档": "LoadConversationHistoryArchive", + "Latex中译英": "LatexChineseToEnglish", + "Latex英译中": "LatexEnglishToChinese", + "连接网络回答问题": "ConnectToNetworkToAnswerQuestions", + "交互功能模板函数": "InteractiveFunctionTemplateFunction", + "交互功能函数模板": "InteractiveFunctionFunctionTemplate", + "sprint亮靛": "SprintIndigo", + "print亮黄": "PrintBrightYellow", + "print亮绿": "PrintBrightGreen", + "print亮红": "PrintBrightRed", + "解析项目源代码": "ParseProjectSourceCode", + "解析一个C项目": "ParseCProject", + "全项目切换英文": "SwitchToEnglishForTheWholeProject", + "谷歌检索小助手": "GoogleSearchAssistant", + "读取知识库作答": "ReadKnowledgeArchiveAnswerQuestions", + "print亮蓝": "PrintBrightBlue", + "微调数据集生成": "FineTuneDatasetGeneration", + "清理多余的空行": "CleanUpExcessBlankLines", + "编译Latex": "CompileLatex", + "解析Paper": "ParsePaper", + "ipynb解释": "IpynbExplanation", + "读文章写摘要": "ReadArticleWriteSummary", + "生成函数注释": "GenerateFunctionComments", + "解析项目本身": "ParseProjectItself", + "对话历史存档": "ConversationHistoryArchive", + "专业词汇声明": "ProfessionalTerminologyDeclaration", + "解析docx": "ParseDocx", + "解析源代码新": "ParsingSourceCodeNew", + "总结音视频": "SummaryAudioVideo", + "知识库问答": "UpdateKnowledgeArchive", + "多文件润色": "ProofreadMultipleFiles", + "多文件翻译": "TranslateMultipleFiles", + "解析PDF": "ParsePDF", + "同时问询": "SimultaneousInquiry", + "图片生成": "ImageGeneration", + "动画生成": "AnimationGeneration", + "语音助手": "VoiceAssistant", + "启动微调": "StartFineTuning" +} \ No newline at end of file diff --git a/docs/translate_traditionalchinese.json b/docs/translate_traditionalchinese.json index 0cc65d799fe9fcea3ae0861feaf64e86c879a187..cf12de1c006f04ef006ef0060a926e564bf14a45 100644 --- a/docs/translate_traditionalchinese.json +++ b/docs/translate_traditionalchinese.json @@ -150,26 +150,7 @@ "使用中文回答我的问题": "使用中文回答我的問題", "备份一个文件": "備份一個文件", "未知": "未知", - "如.md": "#", - "**输入参数说明**": "#", - "如果这裡拋出異常": "#", - "多線程操作已經開始": "#", - "備份和下載": "#", - "新版本可用": "#", - "將要忽略匹配的文件後綴": "#", - "可調節線程池的大小避免openai的流量限制錯誤": "#", - "使用Unsplash API": "#", - "ChatGPT綜合": "#", - "從摘要中提取高價值信息": "#", - "借助此參數": "#", - "知乎": "#", - "其他錯誤": "#", - "退出": "#", - "對話歷史寫入": "#", - "問詢記錄": "#", - "依次訪問網頁": "#", - "NewBing響應異常": "#", - "jittorllms尚未加載": "#", + "其他錯誤": "其他錯誤", "等待NewBing响应": "等待NewBing回應", "找不到任何CSharp文件": "找不到任何CSharp檔案", "插件demo": "插件範例", @@ -300,12 +281,12 @@ "上傳本地文件可供紅色函數插件調用": "上傳本地文件供紅色函數插件調用", "生成圖像": "生成圖像", "追加歷史": "追加歷史", - "網絡代理狀態": "網路代理狀態", + "網絡代理狀態": "網絡代理狀態", "不需要再次轉化": "不需要再次轉換", "帶超時倒計時": "帶有超時倒數計時", "保存當前對話": "儲存目前對話", "等待響應": "等待回應", - "依賴檢測通過": "依賴檢查通過", + "依賴檢測通過": "依賴檢測通過", "如果要使用ChatGLM": "如果要使用ChatGLM", "對IPynb文件進行解析": "對IPynb檔案進行解析", "先切換模型到openai或api2d": "先切換模型到openai或api2d", @@ -411,7 +392,7 @@ "中转网址预览": "中轉網址預覽", "自动截断": "自動截斷", "当無法用標點、空行分割時": "當無法用標點、空行分割時", - "意外Json結構": "意外的Json結構", + "意外Json結構": "意外Json結構", "需要讀取和清理文本的pdf文件路徑": "需要讀取和清理文本的pdf文件路徑", "HotReload的裝飾器函數": "HotReload的裝飾器函數", "chatGPT 分析報告": "chatGPT 分析報告", @@ -423,7 +404,7 @@ "這個bug沒找到觸發條件": "這個bug沒找到觸發條件", "喚起高級參數輸入區": "喚起高級參數輸入區", "但大部分場合下並不需要修改": "但大部分場合下並不需要修改", - "盡量是完整的一個section": "盡量是完整的一個section", + "盡量是完整的一個section": "盡量選擇完整的一個章節", "如果OpenAI不響應": "如果OpenAI不響應", "等文本特殊符號轉換為其基本形式來對文本進行歸一化處理": "等文本特殊符號轉換為其基本形式來對文本進行歸一化處理", "你的回答必須簡單明了": "你的回答必須簡單明了", @@ -517,7 +498,7 @@ "正在提取摘要並下載PDF文檔……": "正在提取摘要並下載PDF文件……", "1. 對原始文本進行歸一化處理": "1. 正規化原始文本", "問題": "問題", - "用於基礎的對話功能": "基本對話功能", + "用於基礎的對話功能": "用於基礎的對話功能", "獲取設置": "獲取設置", "如果缺少依賴": "如果缺少依賴項", "第6步": "第6步", @@ -1111,26 +1092,9 @@ "清理规则包括": "清理規則包括", "新版配置": "新版配置", "如果有": "如果有", - "高級參數輸入區": "#", - "您提供的api-key不滿足要求": "#", - "“喂狗”": "#", - "有線程鎖": "#", - "解析整個CSharp項目": "#", - "上下文管理器必須實現兩個方法": "#", - "Call MOSS fail 不能正常加載MOSS的參數": "#", - "獲取圖片URL": "#", - "輸入部分太自由": "#", - "Not enough point. API2D賬戶點數不足": "#", - "網絡錯誤": "#", - "請開始多線程操作": "#", - "authors獲取失敗": "#", - "、地址": "#", - "根據以上分析": "#", - "1、英文題目;2、中文題目翻譯;3、作者;4、arxiv公開": "#", - "一些普通功能模塊": "#", - "參數簡單": "#", - "具備以下功能": "#", - "優先級2. 獲取config_private中的配置": "#", + "Call MOSS fail 不能正常加載MOSS的參數": "Call MOSS fail 不能正常加載MOSS的參數", + "根據以上分析": "根據以上分析", + "一些普通功能模塊": "一些普通功能模塊", "汇总报告如何远程获取": "如何遠程獲取匯總報告", "热更新prompt": "熱更新提示", "插件调度异常": "插件調度異常", @@ -1191,26 +1155,9 @@ "函数插件区": "函數插件區", "*** API_KEY 导入成功": "*** API_KEY 導入成功", "请对下面的程序文件做一个概述文件名是": "請對下面的程序文件做一個概述文件名是", - "替換跨行的連詞": "#", - "內容太長了都會觸發token數量溢出的錯誤": "#", - "尚未完成全部響應": "#", - "生成帶有段落標籤的HTML代碼": "#", - "函數熱更新是指在不停止程序運行的情況下": "#", - "將Unsplash API中的PUT_YOUR_QUERY_HERE替換成描述該事件的一個最重要的單詞": "#", - "沒有提供高級參數功能說明": "#", - "條": "#", - "請刷新界面重試": "#", - "和openai的連接容易斷掉": "#", - "使用 Unsplash API": "#", - "完成情況": "#", - "迭代上一次的結果": "#", - "每個線程都要“餵狗”": "#", - "最多收納多少個網頁的結果": "#", - "日": "#", - "第4步": "#", - "找不到任何python文件": "#", - "經過充分測試": "#", - "缺少的依賴": "#", + "內容太長了都會觸發token數量溢出的錯誤": "內容太長了都會觸發token數量溢出的錯誤", + "沒有提供高級參數功能說明": "未提供高級參數功能說明", + "和openai的連接容易斷掉": "和openai的連接容易斷掉", "分组+迭代处理": "分組+迭代處理", "安装Newbing的依赖": "安裝Newbing的依賴", "批": "批", @@ -1511,5 +1458,821 @@ "包括": "包括", "或者": "或者", "并执行函数的新版本": "並執行函數的新版本", - "论文": "論文" + "论文": "論文", + "解析一个Golang项目": "ParseAGolangProject", + "Latex英文纠错": "LatexEnglishCorrection", + "连接bing搜索回答问题": "ConnectToBingSearchForAnswer", + "联网的ChatGPT_bing版": "ChatGPT_BingVersionOnline", + "总结音视频": "SummarizeAudioAndVideo", + "动画生成": "GenerateAnimations", + "数学动画生成manim": "GenerateMathematicalAnimationsWithManim", + "Markdown翻译指定语言": "TranslateMarkdownToSpecifiedLanguage", + "知识库问答": "KnowledgeBaseQA", + "Langchain知识库": "LangchainKnowledgeBase", + "读取知识库作答": "ReadKnowledgeBaseAndAnswerQuestions", + "交互功能模板函数": "InteractiveFunctionTemplateFunctions", + "交互功能函数模板": "InteractiveFunctionFunctionTemplates", + "Latex英文纠错加PDF对比": "LatexEnglishCorrectionWithPDFComparison", + "Latex输出PDF结果": "OutputPDFFromLatex", + "Latex翻译中文并重新编译PDF": "TranslateLatexToChineseAndRecompilePDF", + "语音助手": "VoiceAssistant", + "微调数据集生成": "FineTuneDatasetGeneration", + "chatglm微调工具": "ChatGLM_FineTuningTool", + "启动微调": "StartFineTuning", + "sprint亮靛": "SprintLiangDian", + "寻找Latex主文件": "FindLatexMainFile", + "专业词汇声明": "ProfessionalTerminologyDeclaration", + "Latex精细分解与转化": "LatexFineDecompositionAndConversion", + "编译Latex": "CompileLatex", + "正在等您说完问题": "正在等您說完問題", + "最多同时执行5个": "最多同時執行5個", + "将文件复制一份到下载区": "將檔案複製一份到下載區", + "您接下来不能再使用其他插件了": "您接下來不能再使用其他插件了", + "如 绿帽子*深蓝色衬衫*黑色运动裤": "如 綠帽子*深藍色襯衫*黑色運動褲", + "首先你在中文语境下通读整篇论文": "首先您在中文語境下通讀整篇論文", + "根据给定的切割时长将音频文件切割成多个片段": "根據給定的切割時長將音訊檔切割成多個片段", + "接下来两句话只显示在界面上": "接下來兩句話只顯示在介面上", + "清空label": "清空標籤", + "正在尝试自动安装": "正在嘗試自動安裝", + "MOSS消耗大量的内存": "MOSS消耗大量的記憶體", + "如果这里报错": "如果這裡報錯", + "其他类型文献转化效果未知": "其他類型文獻轉換效果未知", + "ChatGPT综合": "ChatGPT綜合", + "音频文件的路径": "音訊檔案的路徑", + "执行错误": "執行錯誤", + "因此选择GenerateImage函数": "因此選擇GenerateImage函數", + "从摘要中提取高价值信息": "從摘要中提取高價值資訊", + "使用英文": "使用英文", + "是否在提交时自动清空输入框": "是否在提交時自動清空輸入框", + "生成数学动画": "生成數學動畫", + "正在加载Claude组件": "正在載入Claude元件", + "参数说明": "參數說明", + "建议排查": "建議排查", + "将消耗较长时间下载中文向量化模型": "將消耗較長時間下載中文向量化模型", + "test_LangchainKnowledgeBase读取": "test_LangchainKnowledgeBase讀取", + "安装Claude的依赖": "安裝Claude的相依性", + "以下所有配置也都支持利用环境变量覆写": "以下所有配置也都支持利用環境變數覆寫", + "需要被切割的音频文件名": "需要被切割的音頻文件名", + "保存当前对话": "保存當前對話", + "功能、贡献者": "功能、貢獻者", + "Chuanhu-Small-and-Beautiful主题": "Chuanhu-小而美主題", + "等待Claude响应": "等待Claude響應", + "其他模型转化效果未知": "其他模型轉換效果未知", + "版权归原文作者所有": "版權歸原文作者所有", + "回答完问题后": "回答完問題後", + "请先上传文件素材": "請先上傳文件素材", + "上传本地文件/压缩包供函数插件调用": "上傳本地文件/壓縮包供函數插件調用", + "P.S. 顺便把Latex的注释去除": "P.S. 順便把Latex的註釋去除", + "您提供的api-key不满足要求": "您提供的api-key不滿足要求", + "切割音频文件": "切割音頻文件", + "对不同latex源文件扣分": "對不同latex源文件扣分", + "以下是一篇学术论文的基础信息": "以下是一篇學術論文的基礎信息", + "问题": "問題", + "待注入的知识库名称id": "待注入的知識庫名稱id", + "”的主要内容": "”的主要內容", + "获取设置": "獲取設置", + "str类型": "str類型", + "多线程": "多線程", + "尝试执行Latex指令失败": "嘗試執行Latex指令失敗", + "然后再写一段英文摘要": "然後再寫一段英文摘要", + "段音频的主要内容": "段音頻的主要內容", + "临时地激活代理网络": "臨時地激活代理網絡", + "网络的远程文件": "網絡的遠程文件", + "不能正常加载ChatGLMFT的参数!": "無法正常載入ChatGLMFT的參數!", + "正在编译PDF文档": "正在編譯PDF文件", + "等待ChatGLMFT响应中": "等待ChatGLMFT回應中", + "将": "將", + "片段": "片段", + "修复括号": "修復括號", + "条": "條", + "建议直接在API_KEY处填写": "建議直接在API_KEY處填寫", + "根据需要切换prompt": "根據需要切換prompt", + "使用": "使用", + "请输入要翻译成哪种语言": "請輸入要翻譯成哪種語言", + "实际得到格式": "實際得到格式", + "例如 f37f30e0f9934c34a992f6f64f7eba4f": "例如 f37f30e0f9934c34a992f6f64f7eba4f", + "请切换至“KnowledgeBaseQA”插件进行知识库访问": "請切換至“KnowledgeBaseQA”插件進行知識庫訪問", + "用户填3": "用戶填3", + "远程云服务器部署": "遠程雲服務器部署", + "未知指令": "未知指令", + "每个线程都要“喂狗”": "每個線程都要“喂狗”", + "该项目的Latex主文件是": "該項目的Latex主文件是", + "设置OpenAI密钥和模型": "設置OpenAI密鑰和模型", + "填入你亲手写的部署名": "填入你親手寫的部署名", + "仅调试": "僅調試", + "依赖不足": "依賴不足", + "右下角更换模型菜单中可切换openai": "右下角更換模型菜單中可切換openai", + "解析整个CSharp项目": "解析整個CSharp項目", + "唤起高级参数输入区": "喚起高級參數輸入區", + "这个bug没找到触发条件": "這個bug沒找到觸發條件", + "========================================= 插件主程序2 =====================================================": "========================================= 插件主程序2 =====================================================", + "经过充分测试": "經過充分測試", + "该文件中主要包含三个函数": "該文件中主要包含三個函數", + "您可以到Github Issue区": "您可以到Github Issue區", + "避免线程阻塞": "避免線程阻塞", + "吸收iffalse注释": "吸收iffalse註釋", + "from crazy_functions.虚空终端 import 终端": "from crazy_functions.虛空終端 import 終端", + "异步方法": "異步方法", + "块元提取": "塊元提取", + "Your account is not active. OpenAI以账户失效为由": "您的帳戶未啟用。OpenAI以帳戶失效為由", + "还原部分原文": "還原部分原文", + "如果要使用Claude": "如果要使用Claude", + "把文件复制过去": "把文件複製過去", + "解压失败! 需要安装pip install rarfile来解压rar文件": "解壓失敗!需要安裝pip install rarfile來解壓rar文件", + "正在锁定插件": "正在鎖定插件", + "输入 clear 以清空对话历史": "輸入 clear 以清空對話歷史", + "P.S. 但愿没人把latex模板放在里面传进来": "P.S. 但願沒人把latex模板放在裡面傳進來", + "实时音频采集": "實時音頻採集", + "开始最终总结": "開始最終總結", + "拒绝服务": "拒絕服務", + "配置教程&视频教程": "配置教程&視頻教程", + "所有音频都总结完成了吗": "所有音頻都總結完成了嗎", + "返回": "返回", + "避免不小心传github被别人看到": "避免不小心傳github被別人看到", + "否则将导致每个人的Claude问询历史互相渗透": "否則將導致每個人的Claude問詢歷史互相滲透", + "提问吧! 但注意": "提問吧!但注意", + "待处理的word文档路径": "待處理的word文檔路徑", + "欢迎加REAME中的QQ联系开发者": "歡迎加REAME中的QQ聯繫開發者", + "建议暂时不要使用": "建議暫時不要使用", + "Latex没有安装": "Latex沒有安裝", + "在这里放一些网上搜集的demo": "在這裡放一些網上搜集的demo", + "实现消息发送、接收等功能": "實現消息發送、接收等功能", + "用于与with语句一起使用": "用於與with語句一起使用", + "解压失败! 需要安装pip install py7zr来解压7z文件": "解壓失敗! 需要安裝pip install py7zr來解壓7z文件", + "借助此参数": "借助此參數", + "判定为数据流的结束": "判定為數據流的結束", + "提取文件扩展名": "提取文件擴展名", + "GPT结果已输出": "GPT結果已輸出", + "读取文件": "讀取文件", + "如果OpenAI不响应": "如果OpenAI不響應", + "输入部分太自由": "輸入部分太自由", + "用于给一小段代码上代理": "用於給一小段代碼上代理", + "输入 stop 以终止对话": "輸入 stop 以終止對話", + "这个paper有个input命令文件名大小写错误!": "這個paper有個input命令文件名大小寫錯誤!", + "等待Claude回复的片段": "等待Claude回復的片段", + "开始": "開始", + "将根据报错信息修正tex源文件并重试": "將根據報錯信息修正tex源文件並重試", + "建议更换代理协议": "建議更換代理協議", + "递归地切割PDF文件": "遞歸地切割PDF文件", + "读 docs\\use_azure.md": "讀 docs\\use_azure.md", + "参数": "參數", + "屏蔽空行和太短的句子": "屏蔽空行和太短的句子", + "分析上述回答": "分析上述回答", + "因为在同一个频道里存在多人使用时历史消息渗透问题": "因為在同一個頻道裡存在多人使用時歷史消息滲透問題", + "使用latexdiff生成論文轉化前後對比": "使用latexdiff生成論文轉化前後對比", + "檢查結果": "檢查結果", + "請在此處追加更細緻的校錯指令": "請在此處追加更細緻的校錯指令", + "報告如何遠程獲取": "報告如何遠程獲取", + "發現已經存在翻譯好的PDF文檔": "發現已經存在翻譯好的PDF文檔", + "插件鎖定中": "插件鎖定中", + "正在精細切分latex文件": "正在精細切分latex文件", + "數學GenerateAnimations": "數學GenerateAnimations", + "上傳文件自動修正路徑": "上傳文件自動修正路徑", + "請檢查ALIYUN_TOKEN和ALIYUN_APPKEY是否過期": "請檢查ALIYUN_TOKEN和ALIYUN_APPKEY是否過期", + "上傳Latex項目": "上傳LaTeX項目", + "Aliyun音頻服務異常": "Aliyun音頻服務異常", + "為了防止大語言模型的意外謬誤產生擴散影響": "為了防止大語言模型的意外謬誤產生擴散影響", + "調用Claude時": "調用Claude時", + "解除插件鎖定": "解除插件鎖定", + "暗色模式 / 亮色模式": "暗色模式 / 亮色模式", + "只有第二步成功": "只有第二步成功", + "分析结果": "分析結果", + "用第二人称": "使用第二人稱", + "详情见https": "詳情請見https", + "记住当前的label": "記住當前的標籤", + "当无法用标点、空行分割时": "當無法用標點符號、空行分割時", + "如果分析错误": "如果分析錯誤", + "如果有必要": "如果有必要", + "不要修改!! 高危设置!通过修改此设置": "不要修改!! 高危設置!通過修改此設置", + "ChatGLMFT消耗大量的内存": "ChatGLMFT消耗大量的內存", + "摘要生成后的文档路径": "摘要生成後的文件路徑", + "对全文进行概括": "對全文進行概述", + "LLM_MODEL是默认选中的模型": "LLM_MODEL是默認選中的模型", + "640个字节为一组": "640個字節為一組", + "获取关键词": "獲取關鍵詞", + "解析为简体中文": "解析為簡體中文", + "将 \\include 命令转换为 \\input 命令": "將 \\include 命令轉換為 \\input 命令", + "默认值为1000": "默認值為1000", + "手动指定语言": "手動指定語言", + "请登录OpenAI查看详情 https": "請登錄OpenAI查看詳情 https", + "尝试第": "嘗試第", + "每秒采样数量": "每秒採樣數量", + "加载失败!": "加載失敗!", + "方法": "方法", + "对这个人外貌、身处的环境、内心世界、过去经历进行描写": "對這個人外貌、身處的環境、內心世界、過去經歷進行描寫", + "请先将.doc文档转换为.docx文档": "請先將.doc文檔轉換為.docx文檔", + "定位主Latex文件": "定位主Latex文件", + "批量SummarizeAudioAndVideo": "批量摘要音视频", + "终端": "終端", + "即将退出": "即將退出", + "找不到": "找不到", + "正在听您讲话": "正在聆聽您講話", + "请您不要删除或修改这行警告": "請勿刪除或修改此警告", + "没有阿里云语音识别APPKEY和TOKEN": "沒有阿里雲語音識別APPKEY和TOKEN", + "临时地启动代理网络": "臨時啟動代理網絡", + "请尝试把以下指令复制到高级参数区": "請將以下指令複製到高級參數區", + "中文Bing版": "中文Bing版", + "计算文件总时长和切割点": "計算文件總時長和切割點", + "寻找主文件": "尋找主文件", + "jittorllms尚未加载": "jittorllms尚未加載", + "使用正则表达式查找半行注释": "使用正則表達式查找半行註釋", + "文档越长耗时越长": "文檔越長耗時越長", + "生成中文PDF": "生成中文PDF", + "写入文件": "寫入文件", + "第三组插件": "第三組插件", + "开始接收chatglmft的回复": "開始接收chatglmft的回覆", + "由于提问含不合规内容被Azure过滤": "由於提問含不合規內容被Azure過濾", + "安装方法https": "安裝方法https", + "是否自动处理token溢出的情况": "是否自動處理token溢出的情況", + "如果需要使用AZURE 详情请见额外文档 docs\\use_azure.md": "如果需要使用AZURE 詳情請見額外文檔 docs\\use_azure.md", + "将要忽略匹配的文件后缀": "將要忽略匹配的文件後綴", + "authors获取失败": "authors獲取失敗", + "发送到openai音频解析终端": "發送到openai音頻解析終端", + "请开始多线程操作": "請開始多線程操作", + "对这个人外貌、身处的环境、内心世界、人设进行描写": "對這個人外貌、身處的環境、內心世界、人設進行描寫", + "MOSS can understand and communicate fluently in the language chosen by the user such as English and 中文. MOSS can perform any language-based tasks.": "MOSS可以流利地理解和使用用戶選擇的語言,例如英語和中文。MOSS可以執行任何基於語言的任務。", + "work_folder = Latex預處理": "設置工作目錄為Latex預處理", + "然後轉移到指定的另一個路徑中": "然後轉移到指定的另一個路徑中", + "使用Newbing": "使用Newbing", + "詳情信息見requirements.txt": "詳細信息請參閱requirements.txt", + "開始下載": "開始下載", + "多線程翻譯開始": "多線程翻譯開始", + "當前大語言模型": "當前大語言模型", + "格式如org-123456789abcdefghijklmno的": "格式如org-123456789abcdefghijklmno的", + "當下一次用戶提交時": "當下一次用戶提交時", + "需要特殊依賴": "需要特殊依賴", + "次編譯": "次編譯", + "先上傳數據集": "先上傳數據集", + "gpt寫的": "gpt寫的", + "調用緩存": "調用緩存", + "优先级1. 获取环境变量作为配置": "優先級1. 獲取環境變量作為配置", + "检查config中的AVAIL_LLM_MODELS选项": "檢查config中的AVAIL_LLM_MODELS選項", + "并且对于网络上的文件": "並且對於網絡上的文件", + "根据文本使用GPT模型生成相应的图像": "根據文本使用GPT模型生成相應的圖像", + "功能描述": "功能描述", + "翻译结果": "翻譯結果", + "需要预先pip install rarfile": "需要預先pip install rarfile", + "等待响应": "等待響應", + "我们剥离Introduction之后的部分": "我們剝離Introduction之後的部分", + "函数插件-固定按钮区": "函數插件-固定按鈕區", + "临时存储用于调试": "臨時存儲用於調試", + "比正文字体小": "比正文字體小", + "会直接转到该函数": "會直接轉到該函數", + "请以以下方式load模型!!!": "請以以下方式load模型!!!", + "请输入关键词": "請輸入關鍵詞", + "返回找到的第一个": "返回找到的第一個", + "高级参数输入区": "高級參數輸入區", + "精细切分latex文件": "精細切分latex文件", + "赋予插件锁定 锁定插件回调路径": "賦予插件鎖定 鎖定插件回調路徑", + "尝试下载": "嘗試下載", + "包含documentclass关键字": "包含documentclass關鍵字", + "在一个异步线程中采集音频": "在一個異步線程中採集音頻", + "先删除": "先刪除", + "则跳过GPT请求环节": "則跳過GPT請求環節", + "Not enough point. API2D账户点数不足": "Not enough point. API2D帳戶點數不足", + "如果一句话小于7个字": "如果一句話小於7個字", + "具备以下功能": "具備以下功能", + "请查看终端的输出或耐心等待": "請查看終端的輸出或耐心等待", + "对输入的word文档进行摘要生成": "對輸入的word文檔進行摘要生成", + "只读": "只讀", + "文本碎片重组为完整的tex文件": "文本碎片重組為完整的tex文件", + "通过调用conversations_open方法打开一个频道": "通過調用conversations_open方法打開一個頻道", + "对话历史文件损坏!": "對話歷史文件損壞!", + "再失败就没办法了": "再失敗就沒辦法了", + "原始PDF编译是否成功": "原始PDF編譯是否成功", + "不能正常加载jittorllms的参数!": "不能正常加載jittorllms的參數!", + "正在编译对比PDF": "正在編譯對比PDF", + "找不到微调模型检查点": "找不到微調模型檢查點", + "将生成的报告自动投射到文件上传区": "將生成的報告自動投射到文件上傳區", + "请对这部分内容进行语法矫正": "請對這部分內容進行語法校正", + "编译已经开始": "編譯已經開始", + "需要读取和清理文本的pdf文件路径": "需要讀取和清理文本的pdf文件路徑", + "读取文件内容到内存": "讀取文件內容到內存", + "用&符号分隔": "用&符號分隔", + "输入arxivID": "輸入arxivID", + "找 API_ORG 设置项": "找API_ORG設置項", + "分析用户提供的谷歌学术": "分析用戶提供的谷歌學術", + "欢迎使用 MOSS 人工智能助手!输入内容即可进行对话": "歡迎使用 MOSS 人工智能助手!輸入內容即可進行對話", + "段音频的第": "段音頻的第", + "没有找到任何可读取文件": "沒有找到任何可讀取文件", + "目前仅支持GPT3.5/GPT4": "目前僅支持GPT3.5/GPT4", + "为每一位访问的用户赋予一个独一无二的uuid编码": "為每一位訪問的用戶賦予一個獨一無二的uuid編碼", + "内含已经翻译的Tex文档": "內含已經翻譯的Tex文檔", + "消耗时间的函数": "消耗時間的函數", + "成功啦": "成功啦", + "环境变量配置格式见docker-compose.yml": "環境變量配置格式見docker-compose.yml", + "将每次对话记录写入Markdown格式的文件中": "將每次對話記錄寫入Markdown格式的文件中", + "报告已经添加到右侧“文件上传区”": "報告已經添加到右側“文件上傳區”", + "此处可以输入解析提示": "此處可以輸入解析提示", + "缺少MOSS的依赖": "缺少MOSS的依賴", + "仅在Windows系统进行了测试": "僅在Windows系統進行了測試", + "然后重启程序": "然後重啟程序", + "此处不修改": "此處不修改", + "输出html调试文件": "輸出html調試文件", + "6.25 加入判定latex模板的代码": "6.25 加入判定latex模板的代碼", + "提取总结": "提取總結", + "要求": "要求", + "由于最为关键的转化PDF编译失败": "由於最為關鍵的轉化PDF編譯失敗", + "除非您是论文的原作者": "除非您是論文的原作者", + "输入问题后点击该插件": "輸入問題後點擊該插件", + "该选项即将被弃用": "該選項即將被棄用", + "再列出用户可能提出的三个问题": "再列出用戶可能提出的三個問題", + "所有文件都总结完成了吗": "所有文件都總結完成了嗎", + "请稍候": "請稍候", + "向chatbot中添加简单的意外错误信息": "向chatbot中添加簡單的意外錯誤信息", + "快捷的调试函数": "快捷的調試函數", + "LatexEnglishCorrection+高亮修正位置": "Latex英文校正+高亮修正位置", + "循环监听已打开频道的消息": "循環監聽已打開頻道的消息", + "将指定目录下的PDF文件从英文翻译成中文": "將指定目錄下的PDF文件從英文翻譯成中文", + "请对下面的音频片段做概述": "請對下面的音頻片段做概述", + "openai的官方KEY需要伴隨组织编码": "openai的官方KEY需要伴隨組織編碼", + "表示频道ID": "頻道ID", + "当前支持的格式包括": "目前支援的格式包括", + "只有GenerateImage和生成图像相关": "僅限GenerateImage和生成圖像相關", + "删除中间文件夹": "刪除中間資料夾", + "解除插件状态": "解除插件狀態", + "正在预热文本向量化模组": "正在預熱文本向量化模組", + "100字以内": "限制100字內", + "如果缺少依赖": "如果缺少相依性", + "寻找主tex文件": "尋找主要tex檔案", + "gpt 多线程请求": "gpt 多線程請求", + "已知某些代码的局部作用是": "已知某些程式碼的局部作用是", + "--读取文件": "--讀取檔案", + "前面是中文冒号": "前面是中文冒號", + "*{\\scriptsize\\textbf{警告": "*{\\scriptsize\\textbf{警告", + "OpenAI所允许的最大并行过载": "OpenAI所允許的最大並行過載", + "请直接去该路径下取回翻译结果": "請直接前往該路徑取回翻譯結果", + "以免输入溢出": "以免輸入溢出", + "把某个路径下所有文件压缩": "壓縮某個路徑下的所有檔案", + "问询记录": "詢問記錄", + "Tex源文件缺失!": "Tex原始檔案遺失!", + "当前参数": "目前參數", + "处理markdown文本格式的转变": "處理markdown文本格式的轉換", + "尝试加载": "嘗試載入", + "请在此处给出自定义翻译命令": "請在此處提供自訂翻譯命令", + "这需要一段时间计算": "這需要一段時間計算", + "-构建知识库": "-建立知識庫", + "还需要填写组织": "還需要填寫組織", + "当前知识库内的有效文件": "當前知識庫內的有效文件", + "第一次调用": "第一次調用", + "从一批文件": "從一批文件", + "json等": "json等", + "翻译-": "翻譯-", + "编译文献交叉引用": "編譯文獻交叉引用", + "优先级2. 获取config_private中的配置": "優先級2. 獲取config_private中的配置", + "可选": "可選", + "我们": "我們", + "编译结束": "編譯結束", + "或代理节点": "或代理節點", + "chatGPT 分析报告": "chatGPT 分析報告", + "调用openai api 使用whisper-1模型": "調用openai api 使用whisper-1模型", + "这段代码定义了一个名为TempProxy的空上下文管理器": "這段代碼定義了一個名為TempProxy的空上下文管理器", + "生成的视频文件路径": "生成的視頻文件路徑", + "请直接提交即可": "請直接提交即可", + "=================================== 工具函数 ===============================================": "=================================== 工具函數 ===============================================", + "报错信息如下. 如果是与网络相关的问题": "報錯信息如下. 如果是與網絡相關的問題", + "python 版本建议3.9+": "python 版本建議3.9+", + "多线程函数插件中": "多線程函數插件中", + "对话助手函数插件": "對話助手函數插件", + "或者重启之后再度尝试": "或者重啟之後再度嘗試", + "拆分过长的latex片段": "拆分過長的latex片段", + "调用whisper模型音频转文字": "調用whisper模型音頻轉文字", + "失败啦": "失敗啦", + "正在编译PDF": "正在編譯PDF", + "请刷新界面重试": "請刷新界面重試", + "模型参数": "模型參數", + "写出文件": "寫出文件", + "第二组插件": "第二組插件", + "在多Tex文档中": "在多Tex文檔中", + "有线程锁": "有線程鎖", + "释放线程锁": "釋放線程鎖", + "读取优先级": "讀取優先級", + "Linux下必须使用Docker安装": "Linux下必須使用Docker安裝", + "例如您可以将以下命令复制到下方": "例如您可以將以下命令複製到下方", + "导入依赖失败": "導入依賴失敗", + "给出一些判定模板文档的词作为扣分项": "給出一些判定模板文檔的詞作為扣分項", + "等待Claude响应中": "等待Claude響應中", + "Call ChatGLMFT fail 不能正常加载ChatGLMFT的参数": "Call ChatGLMFT fail 不能正常加載ChatGLMFT的參數", + "但本地存储了以下历史文件": "但本地存儲了以下歷史文件", + "如果存在调试缓存文件": "如果存在調試緩存文件", + "如果这里抛出异常": "如果這裡拋出異常", + "详见项目主README.md": "詳見項目主README.md", + "作者": "作者", + "现在您点击任意“红颜色”标识的函数插件时": "現在您點擊任意“紅顏色”標識的函數插件時", + "上下文管理器必须实现两个方法": "上下文管理器必須實現兩個方法", + "匹配^数字^": "匹配^數字^", + "也是可读的": "也是可讀的", + "将音频解析为简体中文": "將音頻解析為簡體中文", + "依次访问网页": "依次訪問網頁", + "P.S. 顺便把CTEX塞进去以支持中文": "P.S. 順便把CTEX塞進去以支持中文", + "NewBing响应异常": "NewBing響應異常", + "获取已打开频道的最新消息并返回消息列表": "獲取已打開頻道的最新消息並返回消息列表", + "请使用Markdown": "請使用Markdown", + "例如 RoPlZrM88DnAFkZK": "例如 RoPlZrM88DnAFkZK", + "编译BibTex": "編譯BibTex", + "Claude失败": "Claude失敗", + "请更换为API_URL_REDIRECT配置": "請更換為API_URL_REDIRECT配置", + "P.S. 其他可用的模型还包括": "P.S. 其他可用的模型還包括", + "色彩主体": "色彩主體", + "后面是英文逗号": "後面是英文逗號", + "下载pdf文件未成功": "下載pdf文件未成功", + "删除整行的空注释": "刪除整行的空注釋", + "吸收匿名公式": "吸收匿名公式", + "从而更全面地理解项目的整体功能": "從而更全面地理解項目的整體功能", + "不需要再次转化": "不需要再次轉化", + "可以将自身的状态存储到cookie中": "可以將自身的狀態存儲到cookie中", + "1、英文题目;2、中文题目翻译;3、作者;4、arxiv公开": "1、英文題目;2、中文題目翻譯;3、作者;4、arxiv公開", + "GPT 学术优化": "GPT 學術優化", + "解析整个Python项目": "解析整個Python項目", + "吸收其他杂项": "吸收其他雜項", + "-预热文本向量化模组": "-預熱文本向量化模組", + "Claude组件初始化成功": "Claude組件初始化成功", + "此处填API密钥": "此處填API密鑰", + "请继续分析其他源代码": "請繼續分析其他源代碼", + "质能方程式": "質能方程式", + "功能尚不稳定": "功能尚不穩定", + "使用教程详情见 request_llm/README.md": "使用教程詳情見 request_llm/README.md", + "从以上搜索结果中抽取信息": "從以上搜索結果中抽取信息", + "虽然PDF生成失败了": "雖然PDF生成失敗了", + "找图片": "尋找圖片", + "还原原文": "還原原文", + "可调节线程池的大小避免openai的流量限制错误": "可調整線程池大小以避免openai流量限制錯誤", + "正在提取摘要并下载PDF文档……": "正在提取摘要並下載PDF文件......", + "缺少ChatGLMFT的依赖": "缺少ChatGLMFT的依賴", + "不会实时显示在界面上": "不會即時顯示在界面上", + "解决部分词汇翻译不准确的问题": "解決部分詞彙翻譯不準確的問題", + "等待多线程操作": "等待多線程操作", + "吸收title与作者以上的部分": "吸收標題與作者以上的部分", + "如果需要使用Slack Claude": "如果需要使用Slack Claude", + "一、论文概况": "一、論文概況", + "默认为Chinese": "默認為中文", + "图像生成所用到的提示文本": "圖像生成所用到的提示文本", + "向已打开的频道发送一条文本消息": "向已打開的頻道發送一條文本消息", + "如果某个子任务出错": "如果某個子任務出錯", + "chatglmft 没有 sys_prompt 接口": "chatglmft沒有sys_prompt接口", + "对比PDF编译是否成功": "對比PDF編譯是否成功", + "免费": "免費", + "请讲话": "請講話", + "安装ChatGLM的依赖": "安裝ChatGLM的依賴", + "对IPynb文件进行解析": "對IPynb文件進行解析", + "文件路径列表": "文件路徑列表", + "或者使用此插件继续上传更多文件": "或者使用此插件繼續上傳更多文件", + "随机负载均衡": "隨機負載均衡", + "!!!如果需要运行量化版本": "!!!如果需要運行量化版本", + "注意目前不能多人同时调用Claude接口": "注意目前不能多人同時調用Claude接口", + "文件读取完成": "文件讀取完成", + "用于灵活调整复杂功能的各种参数": "用於靈活調整複雜功能的各種參數", + "**函数功能**": "**函數功能**", + "先切换模型到openai或api2d": "先切換模型到openai或api2d", + "You are associated with a deactivated account. OpenAI以账户失效为由": "您的帳戶已停用。OpenAI以帳戶失效為由", + "你的回答必须简单明了": "您的回答必須簡單明了", + "是否丢弃掉 不是正文的内容": "是否丟棄掉 不是正文的內容", + "但请查收结果": "但請查收結果", + "Claude响应缓慢": "Claude響應緩慢", + "需Latex": "需Latex", + "Claude回复的片段": "Claude回復的片段", + "如果要使用ChatGLMFT": "如果要使用ChatGLMFT", + "它*必须*被包含在AVAIL_LLM_MODELS列表中": "它*必須*被包含在AVAIL_LLM_MODELS列表中", + "前面是中文逗号": "前面是中文逗號", + "需要预先pip install py7zr": "需要預先pip install py7zr", + "将前后断行符脱离": "將前後斷行符脫離", + "防止丢失最后一条消息": "防止丟失最後一條消息", + "初始化插件状态": "初始化插件狀態", + "以秒为单位": "以秒為單位", + "中文Latex项目全文润色": "中文Latex項目全文潤色", + "对整个Latex项目进行纠错": "對整個Latex項目進行校對", + "NEWBING_COOKIES未填写或有格式错误": "NEWBING_COOKIES未填寫或有格式錯誤", + "函数插件作者": "函數插件作者", + "结束": "結束", + "追加历史": "追加歷史", + "您需要首先调用构建知识库": "您需要首先調用構建知識庫", + "如果程序停顿5分钟以上": "如果程序停頓5分鐘以上", + "ChatGLMFT响应异常": "ChatGLMFT響應異常", + "根据当前的模型类别": "根據當前的模型類別", + "才能继续下面的步骤": "才能繼續下面的步驟", + "并将返回的频道ID保存在属性CHANNEL_ID中": "並將返回的頻道ID保存在屬性CHANNEL_ID中", + "请查收结果": "請查收結果", + "解决插件锁定时的界面显示问题": "解決插件鎖定時的界面顯示問題", + "待提取的知识库名称id": "待提取的知識庫名稱id", + "Claude响应异常": "Claude響應異常", + "当前代理可用性": "當前代理可用性", + "代理网络配置": "代理網絡配置", + "我将为您查找相关壁纸": "我將為您查找相關壁紙", + "没给定指令": "沒給定指令", + "音频内容是": "音頻內容是", + "用该压缩包+ConversationHistoryArchive进行反馈": "用該壓縮包+ConversationHistoryArchive進行反饋", + "总结音频": "總結音頻", + "等待用户的再次调用": "等待用戶的再次調用", + "永远给定None": "永遠給定None", + "论文概况": "論文概況", + "建议使用英文单词": "建議使用英文單詞", + "刷新Gradio前端界面": "刷新Gradio前端界面", + "列表递归接龙": "列表遞歸接龍", + "赋予插件状态": "賦予插件狀態", + "构建完成": "構建完成", + "避免多用户干扰": "避免多用戶干擾", + "当前工作路径为": "當前工作路徑為", + "用黑色标注转换区": "用黑色標注轉換區", + "压缩包": "壓縮包", + "刷新页面即可以退出KnowledgeBaseQA模式": "刷新頁面即可以退出KnowledgeBaseQA模式", + "拆分过长的Markdown文件": "拆分過長的Markdown文件", + "生成时间戳": "生成時間戳", + "尚未完成全部响应": "尚未完成全部響應", + "HotReload的装饰器函数": "HotReload的裝飾器函數", + "请务必用 pip install -r requirements.txt 指令安装依赖": "請務必用 pip install -r requirements.txt 指令安裝依賴", + "TGUI不支持函数插件的实现": "TGUI不支持函數插件的實現", + "音频文件名": "音頻文件名", + "找不到任何音频或视频文件": "找不到任何音頻或視頻文件", + "音频解析结果": "音頻解析結果", + "如果使用ChatGLM2微调模型": "如果使用ChatGLM2微調模型", + "限制的3/4时": "限制的3/4時", + "获取回复": "獲取回復", + "对话历史写入": "對話歷史寫入", + "记录删除注释后的文本": "記錄刪除註釋後的文本", + "整理结果为压缩包": "整理結果為壓縮包", + "注意事项": "注意事項", + "请耐心等待": "請耐心等待", + "在执行完成之后": "在執行完成之後", + "参数简单": "參數簡單", + "Arixv论文精细翻译": "Arixv論文精細翻譯", + "备份和下载": "備份和下載", + "当前报错的latex代码处于第": "當前報錯的latex代碼處於第", + "Markdown翻译": "Markdown翻譯", + "英文Latex项目全文纠错": "英文Latex項目全文校對", + "获取预处理函数": "獲取預處理函數", + "add gpt task 创建子线程请求gpt": "add gpt task 創建子線程請求gpt", + "一个包含所有切割音频片段文件路径的列表": "一個包含所有切割音頻片段文件路徑的列表", + "解析arxiv网址失败": "解析arxiv網址失敗", + "PDF文件所在的路径": "PDF文件所在路徑", + "取评分最高者返回": "取評分最高者返回", + "此插件处于开发阶段": "此插件處於開發階段", + "如果已经存在": "如果已經存在", + "或者不在环境变量PATH中": "或者不在環境變量PATH中", + "目前支持的格式": "目前支持的格式", + "将多文件tex工程融合为一个巨型tex": "將多文件tex工程融合為一個巨型tex", + "暂不提交": "暫不提交", + "调用函数": "調用函數", + "编译转化后的PDF": "編譯轉化後的PDF", + "将代码转为动画": "將代碼轉為動畫", + "本地Latex论文精细翻译": "本地Latex論文精細翻譯", + "删除或修改歧义文件": "刪除或修改歧義文件", + "其他操作系统表现未知": "其他操作系統表現未知", + "此插件Windows支持最佳": "此插件Windows支持最佳", + "构建知识库": "構建知識庫", + "每个切割音频片段的时长": "每個切割音頻片段的時長", + "用latex编译为PDF对修正处做高亮": "用latex編譯為PDF對修正處做高亮", + "行": "行", + "= 2 通过一些Latex模板中常见": "= 2 通過一些Latex模板中常見", + "如参考文献、脚注、图注等": "如參考文獻、腳註、圖註等", + "期望格式例如": "期望格式例如", + "翻译内容可靠性无保障": "翻譯內容可靠性無保障", + "请用一句话概括这些文件的整体功能": "請用一句話概括這些文件的整體功能", + "段音频完成了吗": "段音頻完成了嗎", + "填入azure openai api的密钥": "填入azure openai api的密鑰", + "文本碎片重组为完整的tex片段": "文本碎片重組為完整的tex片段", + "吸收在42行以內的begin-end組合": "吸收在42行以內的begin-end組合", + "屬性": "屬性", + "必須包含documentclass": "必須包含documentclass", + "等待GPT響應": "等待GPT響應", + "當前語言模型溫度設定": "當前語言模型溫度設定", + "模型選擇是": "選擇的模型為", + "reverse 操作必須放在最後": "reverse 操作必須放在最後", + "將子線程的gpt結果寫入chatbot": "將子線程的gpt結果寫入chatbot", + "默認為default": "默認為default", + "目前對機器學習類文獻轉化效果最好": "目前對機器學習類文獻轉化效果最好", + "主程序即將開始": "主程序即將開始", + "點擊“停止”鍵可終止程序": "點擊“停止”鍵可終止程序", + "正在處理": "正在處理", + "請立即終止程序": "請立即停止程序", + "將 chatglm 直接對齊到 chatglm2": "將 chatglm 直接對齊到 chatglm2", + "音頻助手": "音頻助手", + "正在構建知識庫": "正在構建知識庫", + "請向下翻": "請向下滾動頁面", + "後面是英文冒號": "後面是英文冒號", + "無法找到一個主Tex文件": "無法找到一個主Tex文件", + "使用中文总结音频“": "使用中文總結音頻", + "该PDF由GPT-Academic开源项目调用大语言模型+Latex翻译插件一键生成": "該PDF由GPT-Academic開源項目調用大語言模型+Latex翻譯插件一鍵生成", + "开始生成动画": "開始生成動畫", + "完成情况": "完成情況", + "然后进行问答": "然後進行問答", + "为啥chatgpt会把cite里面的逗号换成中文逗号呀": "為啥chatgpt會把cite裡面的逗號換成中文逗號呀", + "暂时不支持历史消息": "暫時不支持歷史消息", + "项目Github地址 \\url{https": "項目Github地址 \\url{https", + "Newbing 请求失败": "Newbing 請求失敗", + "根据自然语言执行插件命令": "根據自然語言執行插件命令", + "迭代上一次的结果": "迭代上一次的結果", + "azure和api2d请求源": "azure和api2d請求源", + "格式如org-xxxxxxxxxxxxxxxxxxxxxxxx": "格式如org-xxxxxxxxxxxxxxxxxxxxxxxx", + "推荐http": "推薦http", + "将要匹配的模式": "將要匹配的模式", + "代理数据解析失败": "代理數據解析失敗", + "创建存储切割音频的文件夹": "創建存儲切割音頻的文件夾", + "用红色标注处保留区": "用紅色標注處保留區", + "至少一个线程任务Token溢出而失败": "至少一個線程任務Token溢出而失敗", + "获取Slack消息失败": "獲取Slack消息失敗", + "极少数情况下": "極少數情況下", + "辅助gpt生成代码": "輔助gpt生成代碼", + "生成图像": "生成圖像", + "最多收纳多少个网页的结果": "最多收納多少個網頁的結果", + "获取图片URL": "獲取圖片URL", + "正常状态": "正常狀態", + "编译原始PDF": "編譯原始PDF", + "SummarizeAudioAndVideo内容": "音視頻摘要內容", + "Latex文件融合完成": "Latex文件融合完成", + "获取线程锁": "獲取線程鎖", + "SlackClient类用于与Slack API进行交互": "SlackClient類用於與Slack API進行交互", + "检测到arxiv文档连接": "檢測到arxiv文檔連接", + "--读取参数": "--讀取參數", + "如果您是论文原作者": "如果您是論文原作者", + "5刀": "5美元", + "转化PDF编译是否成功": "轉換PDF編譯是否成功", + "生成带有段落标签的HTML代码": "生成帶有段落標籤的HTML代碼", + "目前不支持历史消息查询": "目前不支持歷史消息查詢", + "将文件添加到chatbot cookie中": "將文件添加到chatbot cookie中", + "多线程操作已经开始": "多線程操作已經開始", + "请求子进程": "請求子進程", + "将Unsplash API中的PUT_YOUR_QUERY_HERE替换成描述该事件的一个最重要的单词": "將Unsplash API中的PUT_YOUR_QUERY_HERE替換成描述該事件的一個最重要的單詞", + "不能加载Claude组件": "不能加載Claude組件", + "请仔细鉴别并以原文为准": "請仔細鑒別並以原文為準", + "否则结束循环": "否則結束循環", + "插件可读取“输入区”文本/路径作为参数": "插件可讀取“輸入區”文本/路徑作為參數", + "网络错误": "網絡錯誤", + "想象一个穿着者": "想像一個穿著者", + "避免遗忘导致死锁": "避免遺忘導致死鎖", + "保证括号正确": "保證括號正確", + "报错信息": "錯誤信息", + "提取视频中的音频": "提取視頻中的音頻", + "初始化音频采集线程": "初始化音頻採集線程", + "参考文献转Bib": "參考文獻轉Bib", + "阿里云实时语音识别 配置难度较高 仅建议高手用户使用 参考 https": "阿里云即時語音識別配置難度較高,僅建議高手用戶使用,參考 https", + "使用时": "使用時", + "处理个别特殊插件的锁定状态": "處理個別特殊插件的鎖定狀態", + "但通常不会出现在正文": "但通常不會出現在正文", + "此函数逐渐地搜索最长的条目进行剪辑": "此函數逐漸地搜索最長的條目進行剪輯", + "给出指令": "給出指令", + "读取音频文件": "讀取音頻文件", + "========================================= 插件主程序1 =====================================================": "========================================= 插件主程序1 =====================================================", + "带超时倒计时": "帶超時倒計時", + "禁止移除或修改此警告": "禁止移除或修改此警告", + "ChatGLMFT尚未加载": "ChatGLMFT尚未加載", + "双手离开鼠标键盘吧": "雙手離開鼠標鍵盤吧", + "缺少的依赖": "缺少的依賴", + "的单词": "的單詞", + "中读取数据构建知识库": "中讀取數據構建知識庫", + "函数热更新是指在不停止程序运行的情况下": "函數熱更新是指在不停止程序運行的情況下", + "建议低于1": "建議低於1", + "转化PDF编译已经成功": "轉換PDF編譯已經成功", + "出问题了": "出問題了", + "欢迎使用 MOSS 人工智能助手!": "歡迎使用 MOSS 人工智能助手!", + "正在精细切分latex文件": "正在精細切分LaTeX文件", + "”补上": "”補上", + "网络代理状态": "網路代理狀態", + "依赖检测通过": "依賴檢測通過", + "默认为default": "預設為default", + "Call MOSS fail 不能正常加载MOSS的参数": "呼叫MOSS失敗,無法正常載入MOSS參數", + "音频助手": "音頻助手", + "次编译": "次編譯", + "其他错误": "其他錯誤", + "属性": "屬性", + "主程序即将开始": "主程式即將開始", + "Aliyun音频服务异常": "Aliyun音頻服務異常", + "response中会携带traceback报错信息": "response中會攜帶traceback錯誤信息", + "一些普通功能模块": "一些普通功能模組", + "和openai的连接容易断掉": "和openai的連線容易斷掉", + "请检查ALIYUN_TOKEN和ALIYUN_APPKEY是否过期": "請檢查ALIYUN_TOKEN和ALIYUN_APPKEY是否過期", + "调用Claude时": "呼叫Claude時", + "插件锁定中": "插件鎖定中", + "将子线程的gpt结果写入chatbot": "將子線程的gpt結果寫入chatbot", + "当下一次用户提交时": "當下一次使用者提交時", + "先上传数据集": "先上傳資料集", + "请在此处追加更细致的矫错指令": "請在此處追加更細緻的矯錯指令", + "无法找到一个主Tex文件": "無法找到一個主Tex文件", + "gpt写的": "gpt寫的", + "预处理": "預處理", + "但大部分场合下并不需要修改": "但大部分場合下並不需要修改", + "正在构建知识库": "正在建構知識庫", + "开始请求": "開始請求", + "根据以上分析": "根據以上分析", + "需要特殊依赖": "需要特殊依賴", + "用于基础的对话功能": "用於基礎的對話功能", + "且没有代码段": "且沒有程式碼段", + "取决于": "取決於", + "openai的官方KEY需要伴隨組織編碼": "請填入組織編碼", + "等待newbing回覆的片段": "等待newbing回覆的片段", + "调用缓存": "呼叫快取", + "模型选择是": "模型選擇為", + "当前大语言模型": "當前大語言模型", + "然后转移到指定的另一个路径中": "然後轉移到指定的另一個路徑中", + "请向下翻": "請向下滾動", + "内容太长了都会触发token数量溢出的错误": "內容太長會觸發token數量溢出的錯誤", + "每一块": "每一塊", + "详情信息见requirements.txt": "詳細信息見requirements.txt", + "没有提供高级参数功能说明": "沒有提供高級參數功能說明", + "上传Latex项目": "上傳Latex項目", + "请立即终止程序": "請立即終止程式", + "解除插件锁定": "解除插件鎖定", + "意外Json结构": "意外Json結構", + "必须包含documentclass": "必須包含documentclass", + "10个文件为一组": "10個文件為一組", + "openai的官方KEY需要伴随组织编码": "openai的官方KEY需要伴隨組織編碼", + "重置文件的创建时间": "重置文件的創建時間", + "尽量是完整的一个section": "盡量是完整的一個section", + "报告如何远程获取": "報告如何遠程獲取", + "work_folder = Latex预处理": "work_folder = Latex預處理", + "吸收在42行以内的begin-end组合": "吸收在42行以內的begin-end組合", + "后面是英文冒号": "後面是英文冒號", + "使用latexdiff生成论文转化前后对比": "使用latexdiff生成論文轉化前後對比", + "首先你在英文语境下通读整篇论文": "首先你在英文語境下通讀整篇論文", + "为了防止大语言模型的意外谬误产生扩散影响": "為了防止大語言模型的意外謬誤產生擴散影響", + "发现已经存在翻译好的PDF文档": "發現已經存在翻譯好的PDF文檔", + "点击“停止”键可终止程序": "點擊“停止”鍵可終止程序", + "数学GenerateAnimations": "數學GenerateAnimations", + "随变按钮的回调函数注册": "隨變按鈕的回調函數註冊", + "history至少释放二分之一": "history至少釋放二分之一", + "当前语言模型温度设定": "當前語言模型溫度設定", + "等待GPT响应": "等待GPT響應", + "正在处理": "正在處理", + "多线程翻译开始": "多線程翻譯開始", + "reverse 操作必须放在最后": "reverse 操作必須放在最後", + "等待newbing回复的片段": "等待newbing回覆的片段", + "开始下载": "開始下載", + "将 chatglm 直接对齐到 chatglm2": "將 chatglm 直接對齊到 chatglm2", + "以上材料已经被写入": "以上材料已經被寫入", + "上传文件自动修正路径": "上傳文件自動修正路徑", + "然后请使用Markdown格式封装": "然後請使用Markdown格式封裝", + "目前对机器学习类文献转化效果最好": "目前對機器學習類文獻轉化效果最好", + "检查结果": "檢查結果", + "、地址": "地址", + "如.md": "如.md", + "使用Unsplash API": "使用Unsplash API", + "**输入参数说明**": "**輸入參數說明**", + "新版本可用": "新版本可用", + "找不到任何python文件": "找不到任何python文件", + "知乎": "知乎", + "日": "日", + "“喂狗”": "“喂狗”", + "第4步": "第4步", + "退出": "退出", + "使用 Unsplash API": "使用 Unsplash API", + "非Openai官方接口返回了错误": "非Openai官方接口返回了错误", + "用来描述你的要求": "用來描述你的要求", + "自定义API KEY格式": "自定義API KEY格式", + "前缀": "前綴", + "会被加在你的输入之前": "會被加在你的輸入之前", + "api2d等请求源": "api2d等請求源", + "高危设置! 常规情况下不要修改! 通过修改此设置": "高危設置!常規情況下不要修改!通過修改此設置", + "即将编译PDF": "即將編譯PDF", + "默认 secondary": "默認 secondary", + "正在从github下载资源": "正在從github下載資源", + "响应异常": "響應異常", + "我好!": "我好!", + "无需填写": "無需填寫", + "缺少": "缺少", + "请问什么是质子": "請問什麼是質子", + "如果要使用": "如果要使用", + "重组": "重組", + "一个单实例装饰器": "一個單實例裝飾器", + "的参数!": "的參數!", + "🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行": "🏃‍♂️🏃‍♂️🏃‍♂️ 子進程執行", + "失败时": "失敗時", + "没有设置ANTHROPIC_API_KEY选项": "沒有設置ANTHROPIC_API_KEY選項", + "并设置参数": "並設置參數", + "格式": "格式", + "按钮是否可见": "按鈕是否可見", + "即可见": "即可見", + "创建request": "創建request", + "的依赖": "的依賴", + "⭐主进程执行": "⭐主進程執行", + "最后一步处理": "最後一步處理", + "没有设置ANTHROPIC_API_KEY": "沒有設置ANTHROPIC_API_KEY", + "的参数": "的參數", + "逆转出错的段落": "逆轉出錯的段落", + "本项目现已支持OpenAI和Azure的api-key": "本項目現已支持OpenAI和Azure的api-key", + "前者是API2D的结束条件": "前者是API2D的結束條件", + "增强稳健性": "增強穩健性", + "消耗大量的内存": "消耗大量的內存", + "您的 API_KEY 不满足任何一种已知的密钥格式": "您的API_KEY不滿足任何一種已知的密鑰格式", + "⭐单线程方法": "⭐單線程方法", + "是否在触发时清除历史": "是否在觸發時清除歷史", + "⭐多线程方法": "多線程方法", + "不能正常加载": "無法正常加載", + "举例": "舉例", + "即不处理之前的对话历史": "即不處理之前的對話歷史", + "尚未加载": "尚未加載", + "防止proxies单独起作用": "防止proxies單獨起作用", + "默认 False": "默認 False", + "检查USE_PROXY": "檢查USE_PROXY", + "响应中": "響應中", + "扭转的范围": "扭轉的範圍", + "后缀": "後綴", + "调用": "調用", + "创建AcsClient实例": "創建AcsClient實例", + "安装": "安裝", + "会被加在你的输入之后": "會被加在你的輸入之後", + "配合前缀可以把你的输入内容用引号圈起来": "配合前綴可以把你的輸入內容用引號圈起來", + "例如翻译、解释代码、润色等等": "例如翻譯、解釋代碼、潤色等等", + "后者是OPENAI的结束条件": "後者是OPENAI的結束條件", + "标注节点的行数范围": "標註節點的行數範圍", + "默认 True": "默認 True", + "将两个PDF拼接": "將兩個PDF拼接" } \ No newline at end of file diff --git a/docs/use_audio.md b/docs/use_audio.md new file mode 100644 index 0000000000000000000000000000000000000000..b461f58ac78ae27b94ec8ad4ccacb81ed760b55b --- /dev/null +++ b/docs/use_audio.md @@ -0,0 +1,64 @@ +# 使用音频交互功能 + + +## 1. 安装额外依赖 +``` +pip install --upgrade pyOpenSSL scipy git+https://github.com/aliyun/alibabacloud-nls-python-sdk.git +``` + +如果因为特色网络问题导致上述命令无法执行: +1. git clone alibabacloud-nls-python-sdk这个项目(或者直接前往Github对应网址下载压缩包). +命令行输入: `git clone https://github.com/aliyun/alibabacloud-nls-python-sdk.git` +1. 进入alibabacloud-nls-python-sdk目录命令行输入:`python setup.py install` + + +## 2. 配置音频功能开关 和 阿里云APPKEY(config.py/config_private.py/环境变量) + +- 注册阿里云账号 +- 开通 智能语音交互 (有免费白嫖时长) +- 获取token和appkey +- 未来将逐步用其他更廉价的云服务取代阿里云 + +``` +ENABLE_AUDIO = True +ALIYUN_TOKEN = "554a50fcd0bb476c8d07bb630e94d20c" # 此token已经失效 +ALIYUN_APPKEY = "RoPlZrM88DnAFkZK" # 此appkey已经失效 +``` + +参考 https://help.aliyun.com/document_detail/450255.html +先有阿里云开发者账号,登录之后,需要开通 智能语音交互 的功能,可以免费获得一个token,然后在 全部项目 中,创建一个项目,可以获得一个appkey. + +- 进阶功能 +进一步填写ALIYUN_ACCESSKEY和ALIYUN_SECRET实现自动获取ALIYUN_TOKEN +``` +ALIYUN_APPKEY = "RoP1ZrM84DnAFkZK" +ALIYUN_TOKEN = "" +ALIYUN_ACCESSKEY = "LTAI5q6BrFUzoRXVGUWnekh1" +ALIYUN_SECRET = "eHmI20AVWIaQZ0CiTD2bGQVsaP9i68" +``` + + +## 3.启动 + +启动gpt-academic `python main.py` + +## 4.点击record from microphe,授权音频采集 + +I 如果需要监听自己说话(不监听电脑音频),直接在浏览器中选择对应的麦即可 + +II 如果需要监听电脑音频(不监听自己说话),需要安装`VB-Audio VoiceMeeter`,打开声音控制面板(sound control panel) +- 1 `[把电脑的所有外放声音用VoiceMeeter截留]` 在输出区(playback)选项卡,把VoiceMeeter Input虚拟设备set as default设为默认播放设备。 +- 2 `[把截留的声音释放到gpt-academic]` 打开gpt-academic主界面,授权音频采集后,在浏览器地址栏或者类似的地方会出现一个麦克风图标,打开后,按照浏览器的提示,选择VoiceMeeter虚拟麦克风。然后刷新页面,重新授权音频采集。 +- 3 `[把截留的声音同时释放到耳机或音响]` 完成第一步之后,您应处于听不到电脑声音的状态。为了在截获音频的同时,避免影响正常使用,请完成这最后一步配置。在声音控制面板(sound control panel)输入区(recording)选项卡,把VoiceMeeter Output虚拟设备set as default。双击进入VoiceMeeter Output虚拟设备的设置。 + - 3-1 进入VoiceMeeter Output虚拟设备子菜单,打开listen选项卡。 + - 3-2 勾选Listen to this device。 + - 3-3 在playback through this device下拉菜单中选择你的正常耳机或音响。 + +III `[把特殊软件(如腾讯会议)的外放声音用VoiceMeeter截留]` 在完成步骤II的基础上,在特殊软件(如腾讯会议)中,打开声音菜单,选择扬声器VoiceMeeter Input,选择麦克风为正常耳机麦。 + +VI 两种音频监听模式切换时,需要刷新页面才有效。 + +VII 非localhost运行+非https情况下无法打开录音功能的坑:https://blog.csdn.net/weixin_39461487/article/details/109594434 + +## 5.点击函数插件区“实时音频采集” 或者其他音频交互功能 + diff --git a/docs/use_azure.md b/docs/use_azure.md index f1c27ef3eab1ac393e37efa2dec34e6733bc070d..f7e7b77ea413f381fb00a700621974b3fc03fbad 100644 --- a/docs/use_azure.md +++ b/docs/use_azure.md @@ -90,62 +90,29 @@ 到现在为止,申请操作就完成了,需要记下来的有下面几个东西: -● 密钥(1或2都可以) +● 密钥(对应AZURE_API_KEY,1或2都可以) -● 终结点 +● 终结点 (对应AZURE_ENDPOINT) + +● 部署名(对应AZURE_ENGINE,不是模型名) -● 部署名(不是模型名) # 修改 config.py ``` -AZURE_ENDPOINT = "填入终结点" +LLM_MODEL = "azure-gpt-3.5" # 指定启动时的默认模型,当然事后从下拉菜单选也ok + +AZURE_ENDPOINT = "填入终结点" # 见上述图片 AZURE_API_KEY = "填入azure openai api的密钥" AZURE_API_VERSION = "2023-05-15" # 默认使用 2023-05-15 版本,无需修改 -AZURE_ENGINE = "填入部署名" - -``` -# API的使用 - -接下来就是具体怎么使用API了,还是可以参考官方文档:[快速入门 - 开始通过 Azure OpenAI 服务使用 ChatGPT 和 GPT-4 - Azure OpenAI Service | Microsoft Learn](https://learn.microsoft.com/zh-cn/azure/cognitive-services/openai/chatgpt-quickstart?pivots=programming-language-python) - -和openai自己的api调用有点类似,都需要安装openai库,不同的是调用方式 +AZURE_ENGINE = "填入部署名" # 见上述图片 ``` -import openai -openai.api_type = "azure" #固定格式,无需修改 -openai.api_base = os.getenv("AZURE_OPENAI_ENDPOINT") #这里填入“终结点” -openai.api_version = "2023-05-15" #固定格式,无需修改 -openai.api_key = os.getenv("AZURE_OPENAI_KEY") #这里填入“密钥1”或“密钥2” - -response = openai.ChatCompletion.create( - engine="gpt-35-turbo", #这里填入的不是模型名,是部署名 - messages=[ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "Does Azure OpenAI support customer managed keys?"}, - {"role": "assistant", "content": "Yes, customer managed keys are supported by Azure OpenAI."}, - {"role": "user", "content": "Do other Azure Cognitive Services support this too?"} - ] -) - -print(response) -print(response['choices'][0]['message']['content']) -``` - -需要注意的是: - -1.  engine那里填入的是部署名,不是模型名 - -2.  通过openai库获得的这个 response 和通过 request 库访问 url 获得的 response 不同,不需要 decode,已经是解析好的 json 了,直接根据键值读取即可。 - -更细节的使用方法,详见官方API文档。 # 关于费用 -Azure OpenAI API 还是需要一些费用的(免费订阅只有1个月有效期),费用如下: - -![image.png](https://note.youdao.com/yws/res/18095/WEBRESOURCEeba0ab6d3127b79e143ef2d5627c0e44) +Azure OpenAI API 还是需要一些费用的(免费订阅只有1个月有效期) 具体可以可以看这个网址 :[Azure OpenAI 服务 - 定价| Microsoft Azure](https://azure.microsoft.com/zh-cn/pricing/details/cognitive-services/openai-service/?cdn=disable) diff --git a/multi_language.py b/multi_language.py index 6c7259836e69d7bc5724a301883a9dbf1526589a..7786b8652486a60ca33ea793dbef921f1793b35e 100644 --- a/multi_language.py +++ b/multi_language.py @@ -3,16 +3,18 @@ Usage: - 1. modify LANG + 1. modify config.py, set your LLM_MODEL and API_KEY(s) to provide access to OPENAI (or any other LLM model provider) + + 2. modify LANG (below ↓) LANG = "English" - 2. modify TransPrompt + 3. modify TransPrompt (below ↓) TransPrompt = f"Replace each json value `#` with translated results in English, e.g., \"原始文本\":\"TranslatedText\". Keep Json format. Do not answer #." - 3. Run `python multi_language.py`. + 4. Run `python multi_language.py`. Note: You need to run it multiple times to increase translation coverage because GPT makes mistakes sometimes. - 4. Find the translated program in `multi-language\English\*` + 5. Find the translated program in `multi-language\English\*` P.S. @@ -33,7 +35,7 @@ import pickle import time CACHE_FOLDER = "gpt_log" -blacklist = ['multi-language', 'gpt_log', '.git', 'private_upload', 'multi_language.py'] +blacklist = ['multi-language', 'gpt_log', '.git', 'private_upload', 'multi_language.py', 'build', '.github', '.vscode', '__pycache__', 'venv'] # LANG = "TraditionalChinese" # TransPrompt = f"Replace each json value `#` with translated results in Traditional Chinese, e.g., \"原始文本\":\"翻譯後文字\". Keep Json format. Do not answer #." @@ -286,6 +288,7 @@ def trans_json(word_to_translate, language, special=False): def step_1_core_key_translate(): + LANG_STD = 'std' def extract_chinese_characters(file_path): syntax = [] with open(file_path, 'r', encoding='utf-8') as f: @@ -301,6 +304,7 @@ def step_1_core_key_translate(): elif isinstance(node, ast.ImportFrom): for n in node.names: if contains_chinese(n.name): syntax.append(n.name) + # if node.module is None: print(node.module) for k in node.module.split('.'): if contains_chinese(k): syntax.append(k) return syntax @@ -310,6 +314,7 @@ def step_1_core_key_translate(): for root, dirs, files in os.walk(directory_path): if any([b in root for b in blacklist]): continue + print(files) for file in files: if file.endswith('.py'): file_path = os.path.join(root, file) @@ -323,15 +328,15 @@ def step_1_core_key_translate(): for d in chinese_core_keys: if d not in chinese_core_keys_norepeat: chinese_core_keys_norepeat.append(d) need_translate = [] - cached_translation = read_map_from_json(language=LANG) + cached_translation = read_map_from_json(language=LANG_STD) cached_translation_keys = list(cached_translation.keys()) for d in chinese_core_keys_norepeat: if d not in cached_translation_keys: need_translate.append(d) - need_translate_mapping = trans(need_translate, language=LANG, special=True) - map_to_json(need_translate_mapping, language=LANG) - cached_translation = read_map_from_json(language=LANG) + need_translate_mapping = trans(need_translate, language=LANG_STD, special=True) + map_to_json(need_translate_mapping, language=LANG_STD) + cached_translation = read_map_from_json(language=LANG_STD) cached_translation = dict(sorted(cached_translation.items(), key=lambda x: -len(x[0]))) chinese_core_keys_norepeat_mapping = {} @@ -505,6 +510,6 @@ def step_2_core_key_translate(): with open(file_path_new, 'w', encoding='utf-8') as f: f.write(content) os.remove(file_path) - step_1_core_key_translate() step_2_core_key_translate() +print('Finished, checkout generated results at ./multi-language/') \ No newline at end of file diff --git a/request_llm/bridge_all.py b/request_llm/bridge_all.py index d33f161454534797a2b3f38b7389706bf05104ba..4c7f19d06c85d6604d8e0954aa02b849f664afc6 100644 --- a/request_llm/bridge_all.py +++ b/request_llm/bridge_all.py @@ -16,18 +16,9 @@ from toolbox import get_conf, trimmed_format_exc from .bridge_chatgpt import predict_no_ui_long_connection as chatgpt_noui from .bridge_chatgpt import predict as chatgpt_ui -from .bridge_azure_test import predict_no_ui_long_connection as azure_noui -from .bridge_azure_test import predict as azure_ui - from .bridge_chatglm import predict_no_ui_long_connection as chatglm_noui from .bridge_chatglm import predict as chatglm_ui -from .bridge_newbing import predict_no_ui_long_connection as newbing_noui -from .bridge_newbing import predict as newbing_ui - -# from .bridge_tgui import predict_no_ui_long_connection as tgui_noui -# from .bridge_tgui import predict as tgui_ui - colors = ['#FF00FF', '#00FFFF', '#FF0000', '#990099', '#009999', '#990044'] class LazyloadTiktoken(object): @@ -51,10 +42,11 @@ class LazyloadTiktoken(object): return encoder.decode(*args, **kwargs) # Endpoint 重定向 -API_URL_REDIRECT, = get_conf("API_URL_REDIRECT") +API_URL_REDIRECT, AZURE_ENDPOINT, AZURE_ENGINE = get_conf("API_URL_REDIRECT", "AZURE_ENDPOINT", "AZURE_ENGINE") openai_endpoint = "https://api.openai.com/v1/chat/completions" api2d_endpoint = "https://openai.api2d.net/v1/chat/completions" newbing_endpoint = "wss://sydney.bing.com/sydney/ChatHub" +azure_endpoint = AZURE_ENDPOINT + f'openai/deployments/{AZURE_ENGINE}/chat/completions?api-version=2023-05-15' # 兼容旧版的配置 try: API_URL, = get_conf("API_URL") @@ -76,6 +68,10 @@ get_token_num_gpt35 = lambda txt: len(tokenizer_gpt35.encode(txt, disallowed_spe get_token_num_gpt4 = lambda txt: len(tokenizer_gpt4.encode(txt, disallowed_special=())) +# 开始初始化模型 +AVAIL_LLM_MODELS, LLM_MODEL = get_conf("AVAIL_LLM_MODELS", "LLM_MODEL") +AVAIL_LLM_MODELS = AVAIL_LLM_MODELS + [LLM_MODEL] +# -=-=-=-=-=-=- 以下这部分是最早加入的最稳定的模型 -=-=-=-=-=-=- model_info = { # openai "gpt-3.5-turbo": { @@ -124,10 +120,10 @@ model_info = { }, # azure openai - "azure-gpt35":{ - "fn_with_ui": azure_ui, - "fn_without_ui": azure_noui, - "endpoint": get_conf("AZURE_ENDPOINT"), + "azure-gpt-3.5":{ + "fn_with_ui": chatgpt_ui, + "fn_without_ui": chatgpt_noui, + "endpoint": azure_endpoint, "max_token": 4096, "tokenizer": tokenizer_gpt35, "token_cnt": get_token_num_gpt35, @@ -169,21 +165,33 @@ model_info = { "tokenizer": tokenizer_gpt35, "token_cnt": get_token_num_gpt35, }, - - # newbing - "newbing": { - "fn_with_ui": newbing_ui, - "fn_without_ui": newbing_noui, - "endpoint": newbing_endpoint, - "max_token": 4096, - "tokenizer": tokenizer_gpt35, - "token_cnt": get_token_num_gpt35, - }, } - -AVAIL_LLM_MODELS, = get_conf("AVAIL_LLM_MODELS") +# -=-=-=-=-=-=- 以下部分是新加入的模型,可能附带额外依赖 -=-=-=-=-=-=- +if "claude-1-100k" in AVAIL_LLM_MODELS or "claude-2" in AVAIL_LLM_MODELS: + from .bridge_claude import predict_no_ui_long_connection as claude_noui + from .bridge_claude import predict as claude_ui + model_info.update({ + "claude-1-100k": { + "fn_with_ui": claude_ui, + "fn_without_ui": claude_noui, + "endpoint": None, + "max_token": 8196, + "tokenizer": tokenizer_gpt35, + "token_cnt": get_token_num_gpt35, + }, + }) + model_info.update({ + "claude-2": { + "fn_with_ui": claude_ui, + "fn_without_ui": claude_noui, + "endpoint": None, + "max_token": 8196, + "tokenizer": tokenizer_gpt35, + "token_cnt": get_token_num_gpt35, + }, + }) if "jittorllms_rwkv" in AVAIL_LLM_MODELS: from .bridge_jittorllms_rwkv import predict_no_ui_long_connection as rwkv_noui from .bridge_jittorllms_rwkv import predict as rwkv_ui @@ -239,7 +247,6 @@ if "moss" in AVAIL_LLM_MODELS: if "stack-claude" in AVAIL_LLM_MODELS: from .bridge_stackclaude import predict_no_ui_long_connection as claude_noui from .bridge_stackclaude import predict as claude_ui - # claude model_info.update({ "stack-claude": { "fn_with_ui": claude_ui, @@ -254,7 +261,6 @@ if "newbing-free" in AVAIL_LLM_MODELS: try: from .bridge_newbingfree import predict_no_ui_long_connection as newbingfree_noui from .bridge_newbingfree import predict as newbingfree_ui - # claude model_info.update({ "newbing-free": { "fn_with_ui": newbingfree_ui, @@ -267,6 +273,120 @@ if "newbing-free" in AVAIL_LLM_MODELS: }) except: print(trimmed_format_exc()) +if "newbing" in AVAIL_LLM_MODELS: # same with newbing-free + try: + from .bridge_newbingfree import predict_no_ui_long_connection as newbingfree_noui + from .bridge_newbingfree import predict as newbingfree_ui + model_info.update({ + "newbing": { + "fn_with_ui": newbingfree_ui, + "fn_without_ui": newbingfree_noui, + "endpoint": newbing_endpoint, + "max_token": 4096, + "tokenizer": tokenizer_gpt35, + "token_cnt": get_token_num_gpt35, + } + }) + except: + print(trimmed_format_exc()) +if "chatglmft" in AVAIL_LLM_MODELS: # same with newbing-free + try: + from .bridge_chatglmft import predict_no_ui_long_connection as chatglmft_noui + from .bridge_chatglmft import predict as chatglmft_ui + model_info.update({ + "chatglmft": { + "fn_with_ui": chatglmft_ui, + "fn_without_ui": chatglmft_noui, + "endpoint": None, + "max_token": 4096, + "tokenizer": tokenizer_gpt35, + "token_cnt": get_token_num_gpt35, + } + }) + except: + print(trimmed_format_exc()) +if "internlm" in AVAIL_LLM_MODELS: + try: + from .bridge_internlm import predict_no_ui_long_connection as internlm_noui + from .bridge_internlm import predict as internlm_ui + model_info.update({ + "internlm": { + "fn_with_ui": internlm_ui, + "fn_without_ui": internlm_noui, + "endpoint": None, + "max_token": 4096, + "tokenizer": tokenizer_gpt35, + "token_cnt": get_token_num_gpt35, + } + }) + except: + print(trimmed_format_exc()) +if "chatglm_onnx" in AVAIL_LLM_MODELS: + try: + from .bridge_chatglmonnx import predict_no_ui_long_connection as chatglm_onnx_noui + from .bridge_chatglmonnx import predict as chatglm_onnx_ui + model_info.update({ + "chatglm_onnx": { + "fn_with_ui": chatglm_onnx_ui, + "fn_without_ui": chatglm_onnx_noui, + "endpoint": None, + "max_token": 4096, + "tokenizer": tokenizer_gpt35, + "token_cnt": get_token_num_gpt35, + } + }) + except: + print(trimmed_format_exc()) +if "qwen" in AVAIL_LLM_MODELS: + try: + from .bridge_qwen import predict_no_ui_long_connection as qwen_noui + from .bridge_qwen import predict as qwen_ui + model_info.update({ + "qwen": { + "fn_with_ui": qwen_ui, + "fn_without_ui": qwen_noui, + "endpoint": None, + "max_token": 4096, + "tokenizer": tokenizer_gpt35, + "token_cnt": get_token_num_gpt35, + } + }) + except: + print(trimmed_format_exc()) +if "chatgpt_website" in AVAIL_LLM_MODELS: # 接入一些逆向工程https://github.com/acheong08/ChatGPT-to-API/ + try: + from .bridge_chatgpt_website import predict_no_ui_long_connection as chatgpt_website_noui + from .bridge_chatgpt_website import predict as chatgpt_website_ui + model_info.update({ + "chatgpt_website": { + "fn_with_ui": chatgpt_website_ui, + "fn_without_ui": chatgpt_website_noui, + "endpoint": None, + "max_token": 4096, + "tokenizer": tokenizer_gpt35, + "token_cnt": get_token_num_gpt35, + } + }) + except: + print(trimmed_format_exc()) +if "spark" in AVAIL_LLM_MODELS: # 讯飞星火认知大模型 + try: + from .bridge_spark import predict_no_ui_long_connection as spark_noui + from .bridge_spark import predict as spark_ui + model_info.update({ + "spark": { + "fn_with_ui": spark_ui, + "fn_without_ui": spark_noui, + "endpoint": None, + "max_token": 4096, + "tokenizer": tokenizer_gpt35, + "token_cnt": get_token_num_gpt35, + } + }) + except: + print(trimmed_format_exc()) + + def LLM_CATCH_EXCEPTION(f): """ @@ -307,7 +427,8 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, obser method = model_info[model]["fn_without_ui"] return method(inputs, llm_kwargs, history, sys_prompt, observe_window, console_slience) else: - # 如果同时询问多个大语言模型: + + # 如果同时询问多个大语言模型,这个稍微啰嗦一点,但思路相同,您不必读这个else分支 executor = ThreadPoolExecutor(max_workers=4) models = model.split('&') n_model = len(models) @@ -370,6 +491,6 @@ def predict(inputs, llm_kwargs, *args, **kwargs): additional_fn代表点击的哪个按钮,按钮见functional.py """ - method = model_info[llm_kwargs['llm_model']]["fn_with_ui"] + method = model_info[llm_kwargs['llm_model']]["fn_with_ui"] # 如果这里报错,检查config中的AVAIL_LLM_MODELS选项 yield from method(inputs, llm_kwargs, *args, **kwargs) diff --git a/request_llm/bridge_chatglm.py b/request_llm/bridge_chatglm.py index deaacd276cc53937bd68fd6e579e737375ef3582..6dac86395da134aa896da9d9a7c84ccd94e795d0 100644 --- a/request_llm/bridge_chatglm.py +++ b/request_llm/bridge_chatglm.py @@ -37,15 +37,23 @@ class GetGLMHandle(Process): # 子进程执行 # 第一次运行,加载参数 retry = 0 + LOCAL_MODEL_QUANT, device = get_conf('LOCAL_MODEL_QUANT', 'LOCAL_MODEL_DEVICE') + + if LOCAL_MODEL_QUANT == "INT4": # INT4 + _model_name_ = "THUDM/chatglm2-6b-int4" + elif LOCAL_MODEL_QUANT == "INT8": # INT8 + _model_name_ = "THUDM/chatglm2-6b-int8" + else: + _model_name_ = "THUDM/chatglm2-6b" # FP16 + while True: try: if self.chatglm_model is None: - self.chatglm_tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True) - device, = get_conf('LOCAL_MODEL_DEVICE') + self.chatglm_tokenizer = AutoTokenizer.from_pretrained(_model_name_, trust_remote_code=True) if device=='cpu': - self.chatglm_model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True).float() + self.chatglm_model = AutoModel.from_pretrained(_model_name_, trust_remote_code=True).float() else: - self.chatglm_model = AutoModel.from_pretrained("THUDM/chatglm2-6b", trust_remote_code=True).half().cuda() + self.chatglm_model = AutoModel.from_pretrained(_model_name_, trust_remote_code=True).half().cuda() self.chatglm_model = self.chatglm_model.eval() break else: @@ -136,11 +144,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp return if additional_fn is not None: - import core_functional - importlib.reload(core_functional) # 热更新prompt - core_functional = core_functional.get_core_functions() - if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话) - inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) # 处理历史信息 history_feedin = [] diff --git a/request_llm/bridge_chatglmft.py b/request_llm/bridge_chatglmft.py new file mode 100644 index 0000000000000000000000000000000000000000..4e21c989b75a463dc7ecd695d23d2c24202788e3 --- /dev/null +++ b/request_llm/bridge_chatglmft.py @@ -0,0 +1,207 @@ + +from transformers import AutoModel, AutoTokenizer +import time +import os +import json +import threading +import importlib +from toolbox import update_ui, get_conf +from multiprocessing import Process, Pipe + +load_message = "ChatGLMFT尚未加载,加载需要一段时间。注意,取决于`config.py`的配置,ChatGLMFT消耗大量的内存(CPU)或显存(GPU),也许会导致低配计算机卡死 ……" + +def string_to_options(arguments): + import argparse + import shlex + # Create an argparse.ArgumentParser instance + parser = argparse.ArgumentParser() + # Add command-line arguments + parser.add_argument("--llm_to_learn", type=str, help="LLM model to learn", default="gpt-3.5-turbo") + parser.add_argument("--prompt_prefix", type=str, help="Prompt prefix", default='') + parser.add_argument("--system_prompt", type=str, help="System prompt", default='') + parser.add_argument("--batch", type=int, help="System prompt", default=50) + # Parse the arguments + args = parser.parse_args(shlex.split(arguments)) + return args + + +################################################################################# +class GetGLMFTHandle(Process): + def __init__(self): + super().__init__(daemon=True) + self.parent, self.child = Pipe() + self.chatglmft_model = None + self.chatglmft_tokenizer = None + self.info = "" + self.success = True + self.check_dependency() + self.start() + self.threadLock = threading.Lock() + + def check_dependency(self): + try: + import sentencepiece + self.info = "依赖检测通过" + self.success = True + except: + self.info = "缺少ChatGLMFT的依赖,如果要使用ChatGLMFT,除了基础的pip依赖以外,您还需要运行`pip install -r request_llm/requirements_chatglm.txt`安装ChatGLM的依赖。" + self.success = False + + def ready(self): + return self.chatglmft_model is not None + + def run(self): + # 子进程执行 + # 第一次运行,加载参数 + retry = 0 + while True: + try: + if self.chatglmft_model is None: + from transformers import AutoConfig + import torch + # conf = 'request_llm/current_ptune_model.json' + # if not os.path.exists(conf): raise RuntimeError('找不到微调模型信息') + # with open(conf, 'r', encoding='utf8') as f: + # model_args = json.loads(f.read()) + ChatGLM_PTUNING_CHECKPOINT, = get_conf('ChatGLM_PTUNING_CHECKPOINT') + assert os.path.exists(ChatGLM_PTUNING_CHECKPOINT), "找不到微调模型检查点" + conf = os.path.join(ChatGLM_PTUNING_CHECKPOINT, "config.json") + with open(conf, 'r', encoding='utf8') as f: + model_args = json.loads(f.read()) + if 'model_name_or_path' not in model_args: + model_args['model_name_or_path'] = model_args['_name_or_path'] + self.chatglmft_tokenizer = AutoTokenizer.from_pretrained( + model_args['model_name_or_path'], trust_remote_code=True) + config = AutoConfig.from_pretrained( + model_args['model_name_or_path'], trust_remote_code=True) + + config.pre_seq_len = model_args['pre_seq_len'] + config.prefix_projection = model_args['prefix_projection'] + + print(f"Loading prefix_encoder weight from {ChatGLM_PTUNING_CHECKPOINT}") + model = AutoModel.from_pretrained(model_args['model_name_or_path'], config=config, trust_remote_code=True) + prefix_state_dict = torch.load(os.path.join(ChatGLM_PTUNING_CHECKPOINT, "pytorch_model.bin")) + new_prefix_state_dict = {} + for k, v in prefix_state_dict.items(): + if k.startswith("transformer.prefix_encoder."): + new_prefix_state_dict[k[len("transformer.prefix_encoder."):]] = v + model.transformer.prefix_encoder.load_state_dict(new_prefix_state_dict) + + if model_args['quantization_bit'] is not None: + print(f"Quantized to {model_args['quantization_bit']} bit") + model = model.quantize(model_args['quantization_bit']) + model = model.cuda() + if model_args['pre_seq_len'] is not None: + # P-tuning v2 + model.transformer.prefix_encoder.float() + self.chatglmft_model = model.eval() + + break + else: + break + except Exception as e: + retry += 1 + if retry > 3: + self.child.send('[Local Message] Call ChatGLMFT fail 不能正常加载ChatGLMFT的参数。') + raise RuntimeError("不能正常加载ChatGLMFT的参数!") + + while True: + # 进入任务等待状态 + kwargs = self.child.recv() + # 收到消息,开始请求 + try: + for response, history in self.chatglmft_model.stream_chat(self.chatglmft_tokenizer, **kwargs): + self.child.send(response) + # # 中途接收可能的终止指令(如果有的话) + # if self.child.poll(): + # command = self.child.recv() + # if command == '[Terminate]': break + except: + from toolbox import trimmed_format_exc + self.child.send('[Local Message] Call ChatGLMFT fail.' + '\n```\n' + trimmed_format_exc() + '\n```\n') + # 请求处理结束,开始下一个循环 + self.child.send('[Finish]') + + def stream_chat(self, **kwargs): + # 主进程执行 + self.threadLock.acquire() + self.parent.send(kwargs) + while True: + res = self.parent.recv() + if res != '[Finish]': + yield res + else: + break + self.threadLock.release() + +global glmft_handle +glmft_handle = None +################################################################################# +def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False): + """ + 多线程方法 + 函数的说明请见 request_llm/bridge_all.py + """ + global glmft_handle + if glmft_handle is None: + glmft_handle = GetGLMFTHandle() + if len(observe_window) >= 1: observe_window[0] = load_message + "\n\n" + glmft_handle.info + if not glmft_handle.success: + error = glmft_handle.info + glmft_handle = None + raise RuntimeError(error) + + # chatglmft 没有 sys_prompt 接口,因此把prompt加入 history + history_feedin = [] + history_feedin.append(["What can I do?", sys_prompt]) + for i in range(len(history)//2): + history_feedin.append([history[2*i], history[2*i+1]] ) + + watch_dog_patience = 5 # 看门狗 (watchdog) 的耐心, 设置5秒即可 + response = "" + for response in glmft_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']): + if len(observe_window) >= 1: observe_window[0] = response + if len(observe_window) >= 2: + if (time.time()-observe_window[1]) > watch_dog_patience: + raise RuntimeError("程序终止。") + return response + + + +def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None): + """ + 单线程方法 + 函数的说明请见 request_llm/bridge_all.py + """ + chatbot.append((inputs, "")) + + global glmft_handle + if glmft_handle is None: + glmft_handle = GetGLMFTHandle() + chatbot[-1] = (inputs, load_message + "\n\n" + glmft_handle.info) + yield from update_ui(chatbot=chatbot, history=[]) + if not glmft_handle.success: + glmft_handle = None + return + + if additional_fn is not None: + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) + + # 处理历史信息 + history_feedin = [] + history_feedin.append(["What can I do?", system_prompt] ) + for i in range(len(history)//2): + history_feedin.append([history[2*i], history[2*i+1]] ) + + # 开始接收chatglmft的回复 + response = "[Local Message]: 等待ChatGLMFT响应中 ..." + for response in glmft_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']): + chatbot[-1] = (inputs, response) + yield from update_ui(chatbot=chatbot, history=history) + + # 总结输出 + if response == "[Local Message]: 等待ChatGLMFT响应中 ...": + response = "[Local Message]: ChatGLMFT响应异常 ..." + history.extend([inputs, response]) + yield from update_ui(chatbot=chatbot, history=history) diff --git a/request_llm/bridge_chatglmonnx.py b/request_llm/bridge_chatglmonnx.py new file mode 100644 index 0000000000000000000000000000000000000000..594bcca15f04c7d9790da95fee2a1d51252c07d1 --- /dev/null +++ b/request_llm/bridge_chatglmonnx.py @@ -0,0 +1,73 @@ +model_name = "ChatGLM-ONNX" +cmd_to_install = "`pip install -r request_llm/requirements_chatglm_onnx.txt`" + + +from transformers import AutoModel, AutoTokenizer +import time +import threading +import importlib +from toolbox import update_ui, get_conf +from multiprocessing import Process, Pipe +from .local_llm_class import LocalLLMHandle, get_local_llm_predict_fns, SingletonLocalLLM + +from .chatglmoonx import ChatGLMModel, chat_template + + + +# ------------------------------------------------------------------------------------------------------------------------ +# 🔌💻 Local Model +# ------------------------------------------------------------------------------------------------------------------------ +@SingletonLocalLLM +class GetONNXGLMHandle(LocalLLMHandle): + + def load_model_info(self): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + self.model_name = model_name + self.cmd_to_install = cmd_to_install + + def load_model_and_tokenizer(self): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + import os, glob + if not len(glob.glob("./request_llm/ChatGLM-6b-onnx-u8s8/chatglm-6b-int8-onnx-merged/*.bin")) >= 7: # 该模型有七个 bin 文件 + from huggingface_hub import snapshot_download + snapshot_download(repo_id="K024/ChatGLM-6b-onnx-u8s8", local_dir="./request_llm/ChatGLM-6b-onnx-u8s8") + def create_model(): + return ChatGLMModel( + tokenizer_path = "./request_llm/ChatGLM-6b-onnx-u8s8/chatglm-6b-int8-onnx-merged/sentencepiece.model", + onnx_model_path = "./request_llm/ChatGLM-6b-onnx-u8s8/chatglm-6b-int8-onnx-merged/chatglm-6b-int8.onnx" + ) + self._model = create_model() + return self._model, None + + def llm_stream_generator(self, **kwargs): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + def adaptor(kwargs): + query = kwargs['query'] + max_length = kwargs['max_length'] + top_p = kwargs['top_p'] + temperature = kwargs['temperature'] + history = kwargs['history'] + return query, max_length, top_p, temperature, history + + query, max_length, top_p, temperature, history = adaptor(kwargs) + + prompt = chat_template(history, query) + for answer in self._model.generate_iterate( + prompt, + max_generated_tokens=max_length, + top_k=1, + top_p=top_p, + temperature=temperature, + ): + yield answer + + def try_to_import_special_deps(self, **kwargs): + # import something that will raise error if the user does not install requirement_*.txt + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + pass + + +# ------------------------------------------------------------------------------------------------------------------------ +# 🔌💻 GPT-Academic Interface +# ------------------------------------------------------------------------------------------------------------------------ +predict_no_ui_long_connection, predict = get_local_llm_predict_fns(GetONNXGLMHandle, model_name) \ No newline at end of file diff --git a/request_llm/bridge_chatgpt.py b/request_llm/bridge_chatgpt.py index eef8fbf0b43f30b915f770f4bc54120c84ebd092..ea48fbaffaaa6359705c0517a09e25925bab256b 100644 --- a/request_llm/bridge_chatgpt.py +++ b/request_llm/bridge_chatgpt.py @@ -22,8 +22,8 @@ import importlib # 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, trimmed_format_exc -proxies, API_KEY, TIMEOUT_SECONDS, MAX_RETRY = \ - get_conf('proxies', 'API_KEY', 'TIMEOUT_SECONDS', 'MAX_RETRY') +proxies, TIMEOUT_SECONDS, MAX_RETRY, API_ORG = \ + get_conf('proxies', 'TIMEOUT_SECONDS', 'MAX_RETRY', 'API_ORG') timeout_bot_msg = '[Local Message] Request timeout. Network error. Please check proxy settings in config.py.' + \ '网络错误,检查代理服务器是否可用,以及代理设置的格式是否正确,格式须是[协议]://[地址]:[端口],缺一不可。' @@ -101,6 +101,8 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", if (time.time()-observe_window[1]) > watch_dog_patience: raise RuntimeError("用户取消了程序。") else: raise RuntimeError("意外Json结构:"+delta) + if json_data['finish_reason'] == 'content_filter': + raise RuntimeError("由于提问含不合规内容被Azure过滤。") if json_data['finish_reason'] == 'length': raise ConnectionAbortedError("正常结束,但显示Token不足,导致输出不完整,请削减单次输入的文本量。") return result @@ -127,11 +129,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp return if additional_fn is not None: - import core_functional - importlib.reload(core_functional) # 热更新prompt - core_functional = core_functional.get_core_functions() - if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话) - inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] + 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}') @@ -172,9 +171,10 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp chunk = next(stream_response) except StopIteration: # 非OpenAI官方接口的出现这样的报错,OpenAI和API2D不会走这里 - 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.decode())}") - yield from update_ui(chatbot=chatbot, history=history, msg="远程返回错误:" + chunk.decode()) # 刷新界面 + 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="非Openai官方接口返回了错误:" + chunk.decode()) # 刷新界面 return # print(chunk.decode()[6:]) @@ -185,7 +185,7 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp if chunk: try: chunk_decoded = chunk.decode() - # 前者API2D的 + # 前者是API2D的结束条件,后者是OPENAI的结束条件 if ('data: [DONE]' in chunk_decoded) or (len(json.loads(chunk_decoded[6:])['choices'][0]["delta"]) == 0): # 判定为数据流的结束,gpt_replying_buffer也写完了 logging.info(f'[response] {gpt_replying_buffer}') @@ -198,36 +198,45 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp history[-1] = gpt_replying_buffer chatbot[-1] = (history[-2], history[-1]) yield from update_ui(chatbot=chatbot, history=history, msg=status_text) # 刷新界面 - except Exception as e: - traceback.print_exc() 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 - 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. 本次输入过长, 或历史数据过长. 历史缓存数据已部分释放, 您可以请再次尝试. (若再次失败则更可能是因为输入过长.)") - # history = [] # 清除历史 - 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. OpenAI以提供了不正确的API_KEY为由, 拒绝服务.") - elif "exceeded your current quota" in error_msg: - chatbot[-1] = (chatbot[-1][0], "[Local Message] You exceeded your current quota. OpenAI以账户额度不足为由, 拒绝服务.") - 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)}") + 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 + openai_website = ' 请登录OpenAI查看详情 https://platform.openai.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. 本次输入过长, 或历史数据过长. 历史缓存数据已部分释放, 您可以请再次尝试. (若再次失败则更可能是因为输入过长.)") + # history = [] # 清除历史 + 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. OpenAI以提供了不正确的API_KEY为由, 拒绝服务. " + openai_website) + elif "exceeded your current quota" in error_msg: + chatbot[-1] = (chatbot[-1][0], "[Local Message] You exceeded your current quota. OpenAI以账户额度不足为由, 拒绝服务." + openai_website) + elif "account is not active" in error_msg: + chatbot[-1] = (chatbot[-1][0], "[Local Message] Your account is not active. OpenAI以账户失效为由, 拒绝服务." + openai_website) + elif "associated with a deactivated account" in error_msg: + chatbot[-1] = (chatbot[-1][0], "[Local Message] You are associated with a deactivated account. OpenAI以账户失效为由, 拒绝服务." + openai_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请求,为发送请求做准备 @@ -241,6 +250,8 @@ def generate_payload(inputs, llm_kwargs, history, system_prompt, stream): "Content-Type": "application/json", "Authorization": f"Bearer {api_key}" } + if API_ORG.startswith('org-'): headers.update({"OpenAI-Organization": API_ORG}) + if llm_kwargs['llm_model'].startswith('azure-'): headers.update({"api-key": api_key}) conversation_cnt = len(history) // 2 diff --git a/request_llm/bridge_chatgpt_website.py b/request_llm/bridge_chatgpt_website.py new file mode 100644 index 0000000000000000000000000000000000000000..96af8332b2586de74fce5540a574c54f1d786763 --- /dev/null +++ b/request_llm/bridge_chatgpt_website.py @@ -0,0 +1,297 @@ +# 借鉴了 https://github.com/GaiZhenbiao/ChuanhuChatGPT 项目 + +""" + 该文件中主要包含三个函数 + + 不具备多线程能力的函数: + 1. predict: 正常对话时使用,具备完备的交互功能,不可多线程 + + 具备多线程调用能力的函数 + 2. predict_no_ui:高级实验性功能模块调用,不会实时显示在界面上,参数简单,可以多线程并行,方便实现复杂的功能逻辑 + 3. predict_no_ui_long_connection:在实验过程中发现调用predict_no_ui处理长文档时,和openai的连接容易断掉,这个函数用stream的方式解决这个问题,同样支持多线程 +""" + +import json +import time +import gradio as gr +import logging +import traceback +import requests +import importlib + +# 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, trimmed_format_exc +proxies, TIMEOUT_SECONDS, MAX_RETRY, API_ORG = \ + get_conf('proxies', 'TIMEOUT_SECONDS', 'MAX_RETRY', 'API_ORG') + +timeout_bot_msg = '[Local Message] Request timeout. Network error. Please check proxy settings in config.py.' + \ + '网络错误,检查代理服务器是否可用,以及代理设置的格式是否正确,格式须是[协议]://[地址]:[端口],缺一不可。' + +def get_full_error(chunk, stream_response): + """ + 获取完整的从Openai返回的报错 + """ + while True: + try: + chunk += next(stream_response) + except: + break + return chunk + + +def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=None, console_slience=False): + """ + 发送至chatGPT,等待回复,一次性完成,不显示中间过程。但内部用stream的方法避免中途网线被掐。 + inputs: + 是本次问询的输入 + sys_prompt: + 系统静默prompt + llm_kwargs: + chatGPT的内部调优参数 + 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 = 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 = '' + while True: + try: chunk = next(stream_response).decode() + except StopIteration: + break + except requests.exceptions.ConnectionError: + chunk = next(stream_response).decode() # 失败了,重试一次?再失败就没办法了。 + if len(chunk)==0: continue + if not chunk.startswith('data:'): + error_msg = get_full_error(chunk.encode('utf8'), stream_response).decode() + if "reduce the length" in error_msg: + raise ConnectionAbortedError("OpenAI拒绝了请求:" + error_msg) + else: + raise RuntimeError("OpenAI拒绝了请求:" + error_msg) + if ('data: [DONE]' in chunk): break # api2d 正常完成 + json_data = json.loads(chunk.lstrip('data:'))['choices'][0] + delta = json_data["delta"] + if len(delta) == 0: break + if "role" in delta: continue + if "content" in delta: + result += delta["content"] + if not console_slience: print(delta["content"], end='') + if observe_window is not None: + # 观测窗,把已经获取的数据显示出去 + if len(observe_window) >= 1: observe_window[0] += delta["content"] + # 看门狗,如果超过期限没有喂狗,则终止 + if len(observe_window) >= 2: + if (time.time()-observe_window[1]) > watch_dog_patience: + raise RuntimeError("用户取消了程序。") + else: raise RuntimeError("意外Json结构:"+delta) + if json_data['finish_reason'] == 'content_filter': + raise RuntimeError("由于提问含不合规内容被Azure过滤。") + if json_data['finish_reason'] == 'length': + raise ConnectionAbortedError("正常结束,但显示Token不足,导致输出不完整,请削减单次输入的文本量。") + return result + + +def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=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(("输入已识别为openai的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 + + 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="等待响应") # 刷新界面 + + 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 + + history.append(inputs); history.append("") + + retry = 0 + while True: + try: + # 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, 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: + # 非OpenAI官方接口的出现这样的报错,OpenAI和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="非Openai官方接口返回了错误:" + chunk.decode()) # 刷新界面 + return + + # print(chunk.decode()[6:]) + if is_head_of_the_stream and (r'"object":"error"' not in chunk.decode()): + # 数据流的第一帧不携带content + is_head_of_the_stream = False; continue + + if chunk: + try: + chunk_decoded = chunk.decode() + # 前者是API2D的结束条件,后者是OPENAI的结束条件 + if 'data: [DONE]' in chunk_decoded: + # 判定为数据流的结束,gpt_replying_buffer也写完了 + logging.info(f'[response] {gpt_replying_buffer}') + break + # 处理数据流的主体 + chunkjson = json.loads(chunk_decoded[6:]) + status_text = f"finish_reason: {chunkjson['choices'][0]['finish_reason']}" + delta = chunkjson['choices'][0]["delta"] + if "content" in delta: + gpt_replying_buffer = gpt_replying_buffer + delta["content"] + history[-1] = gpt_replying_buffer + chatbot[-1] = (history[-2], history[-1]) + yield from update_ui(chatbot=chatbot, history=history, msg=status_text) # 刷新界面 + 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 + openai_website = ' 请登录OpenAI查看详情 https://platform.openai.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. 本次输入过长, 或历史数据过长. 历史缓存数据已部分释放, 您可以请再次尝试. (若再次失败则更可能是因为输入过长.)") + # history = [] # 清除历史 + 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. OpenAI以提供了不正确的API_KEY为由, 拒绝服务. " + openai_website) + elif "exceeded your current quota" in error_msg: + chatbot[-1] = (chatbot[-1][0], "[Local Message] You exceeded your current quota. OpenAI以账户额度不足为由, 拒绝服务." + openai_website) + elif "account is not active" in error_msg: + chatbot[-1] = (chatbot[-1][0], "[Local Message] Your account is not active. OpenAI以账户失效为由, 拒绝服务." + openai_website) + elif "associated with a deactivated account" in error_msg: + chatbot[-1] = (chatbot[-1][0], "[Local Message] You are associated with a deactivated account. OpenAI以账户失效为由, 拒绝服务." + openai_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({"OpenAI-Organization": API_ORG}) + if llm_kwargs['llm_model'].startswith('azure-'): headers.update({"api-key": api_key}) + + conversation_cnt = len(history) // 2 + + messages = [{"role": "system", "content": 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["content"] = history[index] + what_gpt_answer = {} + what_gpt_answer["role"] = "assistant" + what_gpt_answer["content"] = history[index+1] + if what_i_have_asked["content"] != "": + if what_gpt_answer["content"] == "": continue + if what_gpt_answer["content"] == timeout_bot_msg: continue + messages.append(what_i_have_asked) + messages.append(what_gpt_answer) + else: + messages[-1]['content'] = what_gpt_answer['content'] + + what_i_ask_now = {} + what_i_ask_now["role"] = "user" + what_i_ask_now["content"] = inputs + messages.append(what_i_ask_now) + + payload = { + "model": llm_kwargs['llm_model'].strip('api2d-'), + "messages": 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, + } + try: + print(f" {llm_kwargs['llm_model']} : {conversation_cnt} : {inputs[:100]} ..........") + except: + print('输入中可能存在乱码。') + return headers,payload + + diff --git a/request_llm/bridge_claude.py b/request_llm/bridge_claude.py new file mode 100644 index 0000000000000000000000000000000000000000..6084b1f15c9832fd11a36bb58d8187f4e2a7a931 --- /dev/null +++ b/request_llm/bridge_claude.py @@ -0,0 +1,228 @@ +# 借鉴了 https://github.com/GaiZhenbiao/ChuanhuChatGPT 项目 + +""" + 该文件中主要包含2个函数 + + 不具备多线程能力的函数: + 1. predict: 正常对话时使用,具备完备的交互功能,不可多线程 + + 具备多线程调用能力的函数 + 2. predict_no_ui_long_connection:在实验过程中发现调用predict_no_ui处理长文档时,和openai的连接容易断掉,这个函数用stream的方式解决这个问题,同样支持多线程 +""" + +import os +import json +import time +import gradio as gr +import logging +import traceback +import requests +import importlib + +# config_private.py放自己的秘密如API和代理网址 +# 读取时首先看是否存在私密的config_private配置文件(不受git管控),如果有,则覆盖原config文件 +from toolbox import get_conf, update_ui, trimmed_format_exc, ProxyNetworkActivate +proxies, TIMEOUT_SECONDS, MAX_RETRY, ANTHROPIC_API_KEY = \ + get_conf('proxies', 'TIMEOUT_SECONDS', 'MAX_RETRY', 'ANTHROPIC_API_KEY') + +timeout_bot_msg = '[Local Message] Request timeout. Network error. Please check proxy settings in config.py.' + \ + '网络错误,检查代理服务器是否可用,以及代理设置的格式是否正确,格式须是[协议]://[地址]:[端口],缺一不可。' + +def get_full_error(chunk, stream_response): + """ + 获取完整的从Openai返回的报错 + """ + while True: + try: + chunk += next(stream_response) + except: + break + return chunk + + +def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=None, console_slience=False): + """ + 发送至chatGPT,等待回复,一次性完成,不显示中间过程。但内部用stream的方法避免中途网线被掐。 + inputs: + 是本次问询的输入 + sys_prompt: + 系统静默prompt + llm_kwargs: + chatGPT的内部调优参数 + history: + 是之前的对话列表 + observe_window = None: + 用于负责跨越线程传递已经输出的部分,大部分时候仅仅为了fancy的视觉效果,留空即可。observe_window[0]:观测窗。observe_window[1]:看门狗 + """ + from anthropic import Anthropic + watch_dog_patience = 5 # 看门狗的耐心, 设置5秒即可 + prompt = generate_payload(inputs, llm_kwargs, history, system_prompt=sys_prompt, stream=True) + retry = 0 + if len(ANTHROPIC_API_KEY) == 0: + raise RuntimeError("没有设置ANTHROPIC_API_KEY选项") + + while True: + try: + # make a POST request to the API endpoint, stream=False + from .bridge_all import model_info + anthropic = Anthropic(api_key=ANTHROPIC_API_KEY) + # endpoint = model_info[llm_kwargs['llm_model']]['endpoint'] + # with ProxyNetworkActivate() + stream = anthropic.completions.create( + prompt=prompt, + max_tokens_to_sample=4096, # The maximum number of tokens to generate before stopping. + model=llm_kwargs['llm_model'], + stream=True, + temperature = llm_kwargs['temperature'] + ) + break + except Exception as e: + retry += 1 + traceback.print_exc() + if retry > MAX_RETRY: raise TimeoutError + if MAX_RETRY!=0: print(f'请求超时,正在重试 ({retry}/{MAX_RETRY}) ……') + result = '' + try: + for completion in stream: + result += completion.completion + if not console_slience: print(completion.completion, end='') + if observe_window is not None: + # 观测窗,把已经获取的数据显示出去 + if len(observe_window) >= 1: observe_window[0] += completion.completion + # 看门狗,如果超过期限没有喂狗,则终止 + if len(observe_window) >= 2: + if (time.time()-observe_window[1]) > watch_dog_patience: + raise RuntimeError("用户取消了程序。") + except Exception as e: + traceback.print_exc() + + return result + + +def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None): + """ + 发送至chatGPT,流式获取输出。 + 用于基础的对话功能。 + inputs 是本次问询的输入 + top_p, temperature是chatGPT的内部调优参数 + history 是之前的对话列表(注意无论是inputs还是history,内容太长了都会触发token数量溢出的错误) + chatbot 为WebUI中显示的对话列表,修改它,然后yeild出去,可以直接修改对话界面内容 + additional_fn代表点击的哪个按钮,按钮见functional.py + """ + from anthropic import Anthropic + if len(ANTHROPIC_API_KEY) == 0: + chatbot.append((inputs, "没有设置ANTHROPIC_API_KEY")) + yield from update_ui(chatbot=chatbot, history=history, msg="等待响应") # 刷新界面 + return + + 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="等待响应") # 刷新界面 + + try: + prompt = 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 + + history.append(inputs); history.append("") + + retry = 0 + while True: + try: + # make a POST request to the API endpoint, stream=True + from .bridge_all import model_info + anthropic = Anthropic(api_key=ANTHROPIC_API_KEY) + # endpoint = model_info[llm_kwargs['llm_model']]['endpoint'] + # with ProxyNetworkActivate() + stream = anthropic.completions.create( + prompt=prompt, + max_tokens_to_sample=4096, # The maximum number of tokens to generate before stopping. + model=llm_kwargs['llm_model'], + stream=True, + temperature = llm_kwargs['temperature'] + ) + + 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 = "" + + for completion in stream: + try: + gpt_replying_buffer = gpt_replying_buffer + completion.completion + history[-1] = gpt_replying_buffer + chatbot[-1] = (history[-2], history[-1]) + yield from update_ui(chatbot=chatbot, history=history, msg='正常') # 刷新界面 + + except Exception as e: + 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}") + yield from update_ui(chatbot=chatbot, history=history, msg="Json异常" + tb_str) # 刷新界面 + return + + + + +# https://github.com/jtsang4/claude-to-chatgpt/blob/main/claude_to_chatgpt/adapter.py +def convert_messages_to_prompt(messages): + prompt = "" + role_map = { + "system": "Human", + "user": "Human", + "assistant": "Assistant", + } + for message in messages: + role = message["role"] + content = message["content"] + transformed_role = role_map[role] + prompt += f"\n\n{transformed_role.capitalize()}: {content}" + prompt += "\n\nAssistant: " + return prompt + +def generate_payload(inputs, llm_kwargs, history, system_prompt, stream): + """ + 整合所有信息,选择LLM模型,生成http请求,为发送请求做准备 + """ + from anthropic import Anthropic, HUMAN_PROMPT, AI_PROMPT + + conversation_cnt = len(history) // 2 + + messages = [{"role": "system", "content": 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["content"] = history[index] + what_gpt_answer = {} + what_gpt_answer["role"] = "assistant" + what_gpt_answer["content"] = history[index+1] + if what_i_have_asked["content"] != "": + if what_gpt_answer["content"] == "": continue + if what_gpt_answer["content"] == timeout_bot_msg: continue + messages.append(what_i_have_asked) + messages.append(what_gpt_answer) + else: + messages[-1]['content'] = what_gpt_answer['content'] + + what_i_ask_now = {} + what_i_ask_now["role"] = "user" + what_i_ask_now["content"] = inputs + messages.append(what_i_ask_now) + prompt = convert_messages_to_prompt(messages) + + return prompt + + diff --git a/request_llm/bridge_internlm.py b/request_llm/bridge_internlm.py new file mode 100644 index 0000000000000000000000000000000000000000..0ec65b641d366b572640f9d9690e1d9ab86ed40b --- /dev/null +++ b/request_llm/bridge_internlm.py @@ -0,0 +1,202 @@ +model_name = "InternLM" +cmd_to_install = "`pip install -r request_llm/requirements_chatglm.txt`" + +from transformers import AutoModel, AutoTokenizer +import time +import threading +import importlib +from toolbox import update_ui, get_conf +from multiprocessing import Process, Pipe +from .local_llm_class import LocalLLMHandle, get_local_llm_predict_fns, SingletonLocalLLM + + +# ------------------------------------------------------------------------------------------------------------------------ +# 🔌💻 Local Model Utils +# ------------------------------------------------------------------------------------------------------------------------ +def try_to_import_special_deps(): + import sentencepiece + +def combine_history(prompt, hist): + user_prompt = "<|User|>:{user}\n" + robot_prompt = "<|Bot|>:{robot}\n" + cur_query_prompt = "<|User|>:{user}\n<|Bot|>:" + messages = hist + total_prompt = "" + for message in messages: + cur_content = message + cur_prompt = user_prompt.replace("{user}", cur_content[0]) + total_prompt += cur_prompt + cur_prompt = robot_prompt.replace("{robot}", cur_content[1]) + total_prompt += cur_prompt + total_prompt = total_prompt + cur_query_prompt.replace("{user}", prompt) + return total_prompt + +# ------------------------------------------------------------------------------------------------------------------------ +# 🔌💻 Local Model +# ------------------------------------------------------------------------------------------------------------------------ +@SingletonLocalLLM +class GetInternlmHandle(LocalLLMHandle): + + def load_model_info(self): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + self.model_name = model_name + self.cmd_to_install = cmd_to_install + + def try_to_import_special_deps(self, **kwargs): + """ + import something that will raise error if the user does not install requirement_*.txt + """ + import sentencepiece + + def load_model_and_tokenizer(self): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + import torch + from transformers import AutoModelForCausalLM, AutoTokenizer + device, = get_conf('LOCAL_MODEL_DEVICE') + if self._model is None: + tokenizer = AutoTokenizer.from_pretrained("internlm/internlm-chat-7b", trust_remote_code=True) + if device=='cpu': + model = AutoModelForCausalLM.from_pretrained("internlm/internlm-chat-7b", trust_remote_code=True).to(torch.bfloat16) + else: + model = AutoModelForCausalLM.from_pretrained("internlm/internlm-chat-7b", trust_remote_code=True).to(torch.bfloat16).cuda() + + model = model.eval() + return model, tokenizer + + def llm_stream_generator(self, **kwargs): + import torch + import logging + import copy + import warnings + import torch.nn as nn + from transformers.generation.utils import LogitsProcessorList, StoppingCriteriaList, GenerationConfig + + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + def adaptor(): + model = self._model + tokenizer = self._tokenizer + prompt = kwargs['query'] + max_length = kwargs['max_length'] + top_p = kwargs['top_p'] + temperature = kwargs['temperature'] + history = kwargs['history'] + real_prompt = combine_history(prompt, history) + return model, tokenizer, real_prompt, max_length, top_p, temperature + + model, tokenizer, prompt, max_length, top_p, temperature = adaptor() + prefix_allowed_tokens_fn = None + logits_processor = None + stopping_criteria = None + additional_eos_token_id = 103028 + generation_config = None + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + # 🏃‍♂️🏃‍♂️🏃‍♂️ https://github.com/InternLM/InternLM/blob/efbf5335709a8c8faeac6eaf07193973ff1d56a1/web_demo.py#L25 + + inputs = tokenizer([prompt], padding=True, return_tensors="pt") + input_length = len(inputs["input_ids"][0]) + for k, v in inputs.items(): + inputs[k] = v.cuda() + input_ids = inputs["input_ids"] + batch_size, input_ids_seq_length = input_ids.shape[0], input_ids.shape[-1] + if generation_config is None: + generation_config = model.generation_config + generation_config = copy.deepcopy(generation_config) + model_kwargs = generation_config.update(**kwargs) + bos_token_id, eos_token_id = generation_config.bos_token_id, generation_config.eos_token_id + if isinstance(eos_token_id, int): + eos_token_id = [eos_token_id] + if additional_eos_token_id is not None: + eos_token_id.append(additional_eos_token_id) + has_default_max_length = kwargs.get("max_length") is None and generation_config.max_length is not None + if has_default_max_length and generation_config.max_new_tokens is None: + warnings.warn( + f"Using `max_length`'s default ({generation_config.max_length}) to control the generation length. " + "This behaviour is deprecated and will be removed from the config in v5 of Transformers -- we" + " recommend using `max_new_tokens` to control the maximum length of the generation.", + UserWarning, + ) + elif generation_config.max_new_tokens is not None: + generation_config.max_length = generation_config.max_new_tokens + input_ids_seq_length + if not has_default_max_length: + logging.warn( + f"Both `max_new_tokens` (={generation_config.max_new_tokens}) and `max_length`(=" + f"{generation_config.max_length}) seem to have been set. `max_new_tokens` will take precedence. " + "Please refer to the documentation for more information. " + "(https://huggingface.co/docs/transformers/main/en/main_classes/text_generation)", + UserWarning, + ) + + if input_ids_seq_length >= generation_config.max_length: + input_ids_string = "input_ids" + logging.warning( + f"Input length of {input_ids_string} is {input_ids_seq_length}, but `max_length` is set to" + f" {generation_config.max_length}. This can lead to unexpected behavior. You should consider" + " increasing `max_new_tokens`." + ) + + # 2. Set generation parameters if not already defined + logits_processor = logits_processor if logits_processor is not None else LogitsProcessorList() + stopping_criteria = stopping_criteria if stopping_criteria is not None else StoppingCriteriaList() + + logits_processor = model._get_logits_processor( + generation_config=generation_config, + input_ids_seq_length=input_ids_seq_length, + encoder_input_ids=input_ids, + prefix_allowed_tokens_fn=prefix_allowed_tokens_fn, + logits_processor=logits_processor, + ) + + stopping_criteria = model._get_stopping_criteria( + generation_config=generation_config, stopping_criteria=stopping_criteria + ) + logits_warper = model._get_logits_warper(generation_config) + + unfinished_sequences = input_ids.new(input_ids.shape[0]).fill_(1) + scores = None + while True: + model_inputs = model.prepare_inputs_for_generation(input_ids, **model_kwargs) + # forward pass to get next token + outputs = model( + **model_inputs, + return_dict=True, + output_attentions=False, + output_hidden_states=False, + ) + + next_token_logits = outputs.logits[:, -1, :] + + # pre-process distribution + next_token_scores = logits_processor(input_ids, next_token_logits) + next_token_scores = logits_warper(input_ids, next_token_scores) + + # sample + probs = nn.functional.softmax(next_token_scores, dim=-1) + if generation_config.do_sample: + next_tokens = torch.multinomial(probs, num_samples=1).squeeze(1) + else: + next_tokens = torch.argmax(probs, dim=-1) + + # update generated ids, model inputs, and length for next step + input_ids = torch.cat([input_ids, next_tokens[:, None]], dim=-1) + model_kwargs = model._update_model_kwargs_for_generation( + outputs, model_kwargs, is_encoder_decoder=False + ) + unfinished_sequences = unfinished_sequences.mul((min(next_tokens != i for i in eos_token_id)).long()) + + output_token_ids = input_ids[0].cpu().tolist() + output_token_ids = output_token_ids[input_length:] + for each_eos_token_id in eos_token_id: + if output_token_ids[-1] == each_eos_token_id: + output_token_ids = output_token_ids[:-1] + response = tokenizer.decode(output_token_ids) + + yield response + # stop when each sentence is finished, or if we exceed the maximum length + if unfinished_sequences.max() == 0 or stopping_criteria(input_ids, scores): + return + + +# ------------------------------------------------------------------------------------------------------------------------ +# 🔌💻 GPT-Academic Interface +# ------------------------------------------------------------------------------------------------------------------------ +predict_no_ui_long_connection, predict = get_local_llm_predict_fns(GetInternlmHandle, model_name) \ No newline at end of file diff --git a/request_llm/bridge_jittorllms_llama.py b/request_llm/bridge_jittorllms_llama.py index 6dfac681aeaa11a780304b9e645637cabd677688..d4853578fadff9f572c86f7f0fe79f9c8c8c1474 100644 --- a/request_llm/bridge_jittorllms_llama.py +++ b/request_llm/bridge_jittorllms_llama.py @@ -154,11 +154,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp return if additional_fn is not None: - import core_functional - importlib.reload(core_functional) # 热更新prompt - core_functional = core_functional.get_core_functions() - if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话) - inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) # 处理历史信息 history_feedin = [] diff --git a/request_llm/bridge_jittorllms_pangualpha.py b/request_llm/bridge_jittorllms_pangualpha.py index ad02565aef75ac056e0daa7396fb1c6ad7aae072..20a30213032e957113d6377d7c7f5a9912ea22b1 100644 --- a/request_llm/bridge_jittorllms_pangualpha.py +++ b/request_llm/bridge_jittorllms_pangualpha.py @@ -154,11 +154,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp return if additional_fn is not None: - import core_functional - importlib.reload(core_functional) # 热更新prompt - core_functional = core_functional.get_core_functions() - if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话) - inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) # 处理历史信息 history_feedin = [] diff --git a/request_llm/bridge_jittorllms_rwkv.py b/request_llm/bridge_jittorllms_rwkv.py index 1252eead89a44994241ec4407a1e693cbb170bf6..ee4f592f5a1a3e6022b41c899e342bd7e55ed44f 100644 --- a/request_llm/bridge_jittorllms_rwkv.py +++ b/request_llm/bridge_jittorllms_rwkv.py @@ -154,11 +154,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp return if additional_fn is not None: - import core_functional - importlib.reload(core_functional) # 热更新prompt - core_functional = core_functional.get_core_functions() - if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话) - inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) # 处理历史信息 history_feedin = [] diff --git a/request_llm/bridge_moss.py b/request_llm/bridge_moss.py index 7a1ab56d0933c931e5257879e96860e26d1660fb..3c6217d2b285c499490d81e9a744b2dd6f485e24 100644 --- a/request_llm/bridge_moss.py +++ b/request_llm/bridge_moss.py @@ -224,11 +224,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp yield from update_ui(chatbot=chatbot, history=history) if additional_fn is not None: - import core_functional - importlib.reload(core_functional) # 热更新prompt - core_functional = core_functional.get_core_functions() - if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话) - inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) # 处理历史信息 history_feedin = [] diff --git a/request_llm/bridge_newbingfree.py b/request_llm/bridge_newbingfree.py index 38d2eb9bf610ef95aa5e3f571b1dc7a30a6eada1..cc6e9b733b48fe255c15bc9fae3c9abd74f276ca 100644 --- a/request_llm/bridge_newbingfree.py +++ b/request_llm/bridge_newbingfree.py @@ -89,9 +89,6 @@ class NewBingHandle(Process): if a not in self.local_history: self.local_history.append(a) prompt += a + '\n' - # if b not in self.local_history: - # self.local_history.append(b) - # prompt += b + '\n' # 问题 prompt += question @@ -101,7 +98,7 @@ class NewBingHandle(Process): async for final, response in self.newbing_model.ask_stream( prompt=question, conversation_style=NEWBING_STYLE, # ["creative", "balanced", "precise"] - wss_link=endpoint, # "wss://sydney.bing.com/sydney/ChatHub" + wss_link=endpoint, # "wss://sydney.bing.com/sydney/ChatHub" ): if not final: print(response) @@ -121,14 +118,26 @@ class NewBingHandle(Process): self.local_history = [] if (self.newbing_model is None) or (not self.success): # 代理设置 - proxies, = get_conf('proxies') + proxies, NEWBING_COOKIES = get_conf('proxies', 'NEWBING_COOKIES') if proxies is None: self.proxies_https = None else: self.proxies_https = proxies['https'] + if (NEWBING_COOKIES is not None) and len(NEWBING_COOKIES) > 100: + try: + cookies = json.loads(NEWBING_COOKIES) + except: + self.success = False + tb_str = '\n```\n' + trimmed_format_exc() + '\n```\n' + self.child.send(f'[Local Message] NEWBING_COOKIES未填写或有格式错误。') + self.child.send('[Fail]'); self.child.send('[Finish]') + raise RuntimeError(f"NEWBING_COOKIES未填写或有格式错误。") + else: + cookies = None + try: - self.newbing_model = NewbingChatbot(proxy=self.proxies_https) + self.newbing_model = NewbingChatbot(proxy=self.proxies_https, cookies=cookies) except: self.success = False tb_str = '\n```\n' + trimmed_format_exc() + '\n```\n' @@ -143,7 +152,7 @@ class NewBingHandle(Process): asyncio.run(self.async_run()) except Exception: tb_str = '\n```\n' + trimmed_format_exc() + '\n```\n' - self.child.send(f'[Local Message] Newbing失败 {tb_str}.') + self.child.send(f'[Local Message] Newbing 请求失败,报错信息如下. 如果是与网络相关的问题,建议更换代理协议(推荐http)或代理节点 {tb_str}.') self.child.send('[Fail]') self.child.send('[Finish]') @@ -151,18 +160,14 @@ class NewBingHandle(Process): """ 这个函数运行在主进程 """ - self.threadLock.acquire() - self.parent.send(kwargs) # 发送请求到子进程 + self.threadLock.acquire() # 获取线程锁 + self.parent.send(kwargs) # 请求子进程 while True: - res = self.parent.recv() # 等待newbing回复的片段 - if res == '[Finish]': - break # 结束 - elif res == '[Fail]': - self.success = False - break - else: - yield res # newbing回复的片段 - self.threadLock.release() + res = self.parent.recv() # 等待newbing回复的片段 + if res == '[Finish]': break # 结束 + elif res == '[Fail]': self.success = False; break # 失败 + else: yield res # newbing回复的片段 + self.threadLock.release() # 释放线程锁 """ @@ -219,11 +224,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp return if additional_fn is not None: - import core_functional - importlib.reload(core_functional) # 热更新prompt - core_functional = core_functional.get_core_functions() - if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话) - inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) history_feedin = [] for i in range(len(history)//2): diff --git a/request_llm/bridge_qwen.py b/request_llm/bridge_qwen.py new file mode 100644 index 0000000000000000000000000000000000000000..07ed243feb25274213ccee90f862662080809f84 --- /dev/null +++ b/request_llm/bridge_qwen.py @@ -0,0 +1,68 @@ +model_name = "Qwen" +cmd_to_install = "`pip install -r request_llm/requirements_qwen.txt`" + + +from transformers import AutoModel, AutoTokenizer +import time +import threading +import importlib +from toolbox import update_ui, get_conf +from multiprocessing import Process, Pipe +from .local_llm_class import LocalLLMHandle, get_local_llm_predict_fns, SingletonLocalLLM + + + +# ------------------------------------------------------------------------------------------------------------------------ +# 🔌💻 Local Model +# ------------------------------------------------------------------------------------------------------------------------ +@SingletonLocalLLM +class GetONNXGLMHandle(LocalLLMHandle): + + def load_model_info(self): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + self.model_name = model_name + self.cmd_to_install = cmd_to_install + + def load_model_and_tokenizer(self): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + import os, glob + import os + import platform + from modelscope import AutoModelForCausalLM, AutoTokenizer, GenerationConfig + + model_id = 'qwen/Qwen-7B-Chat' + revision = 'v1.0.1' + self._tokenizer = AutoTokenizer.from_pretrained(model_id, revision=revision, trust_remote_code=True) + # use fp16 + model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", revision=revision, trust_remote_code=True, fp16=True).eval() + model.generation_config = GenerationConfig.from_pretrained(model_id, trust_remote_code=True) # 可指定不同的生成长度、top_p等相关超参 + self._model = model + + return self._model, self._tokenizer + + def llm_stream_generator(self, **kwargs): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + def adaptor(kwargs): + query = kwargs['query'] + max_length = kwargs['max_length'] + top_p = kwargs['top_p'] + temperature = kwargs['temperature'] + history = kwargs['history'] + return query, max_length, top_p, temperature, history + + query, max_length, top_p, temperature, history = adaptor(kwargs) + + for response in self._model.chat(self._tokenizer, query, history=history, stream=True): + yield response + + def try_to_import_special_deps(self, **kwargs): + # import something that will raise error if the user does not install requirement_*.txt + # 🏃‍♂️🏃‍♂️🏃‍♂️ 主进程执行 + import importlib + importlib.import_module('modelscope') + + +# ------------------------------------------------------------------------------------------------------------------------ +# 🔌💻 GPT-Academic Interface +# ------------------------------------------------------------------------------------------------------------------------ +predict_no_ui_long_connection, predict = get_local_llm_predict_fns(GetONNXGLMHandle, model_name) \ No newline at end of file diff --git a/request_llm/bridge_spark.py b/request_llm/bridge_spark.py new file mode 100644 index 0000000000000000000000000000000000000000..551b6f305daf2f904056e6090261b7609dae0512 --- /dev/null +++ b/request_llm/bridge_spark.py @@ -0,0 +1,49 @@ + +import time +import threading +import importlib +from toolbox import update_ui, get_conf +from multiprocessing import Process, Pipe + +model_name = '星火认知大模型' + +def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False): + """ + ⭐多线程方法 + 函数的说明请见 request_llm/bridge_all.py + """ + watch_dog_patience = 5 + response = "" + + from .com_sparkapi import SparkRequestInstance + sri = SparkRequestInstance() + for response in sri.generate(inputs, llm_kwargs, history, sys_prompt): + if len(observe_window) >= 1: + observe_window[0] = response + if len(observe_window) >= 2: + if (time.time()-observe_window[1]) > watch_dog_patience: raise RuntimeError("程序终止。") + return response + +def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None): + """ + ⭐单线程方法 + 函数的说明请见 request_llm/bridge_all.py + """ + chatbot.append((inputs, "")) + + if additional_fn is not None: + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) + + # 开始接收回复 + from .com_sparkapi import SparkRequestInstance + sri = SparkRequestInstance() + for response in sri.generate(inputs, llm_kwargs, history, system_prompt): + chatbot[-1] = (inputs, response) + yield from update_ui(chatbot=chatbot, history=history) + + # 总结输出 + if response == f"[Local Message]: 等待{model_name}响应中 ...": + response = f"[Local Message]: {model_name}响应异常 ..." + history.extend([inputs, response]) + yield from update_ui(chatbot=chatbot, history=history) \ No newline at end of file diff --git a/request_llm/bridge_stackclaude.py b/request_llm/bridge_stackclaude.py index c674a8bfe9d022b6e2b6359e5327b47596a53c68..3f2ee67428f9c8323eca0f7006ad4d4f767a6b58 100644 --- a/request_llm/bridge_stackclaude.py +++ b/request_llm/bridge_stackclaude.py @@ -1,4 +1,4 @@ -from .bridge_newbing import preprocess_newbing_out, preprocess_newbing_out_simple +from .bridge_newbingfree import preprocess_newbing_out, preprocess_newbing_out_simple from multiprocessing import Process, Pipe from toolbox import update_ui, get_conf, trimmed_format_exc import threading @@ -248,14 +248,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp return if additional_fn is not None: - import core_functional - importlib.reload(core_functional) # 热更新prompt - core_functional = core_functional.get_core_functions() - if "PreProcess" in core_functional[additional_fn]: - inputs = core_functional[additional_fn]["PreProcess"]( - inputs) # 获取预处理函数(如果有的话) - inputs = core_functional[additional_fn]["Prefix"] + \ - inputs + core_functional[additional_fn]["Suffix"] + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) history_feedin = [] for i in range(len(history)//2): diff --git a/request_llm/bridge_tgui.py b/request_llm/bridge_tgui.py index fcf852f0474892bd179843ece3f4a83110bd7756..3e03f7b39705664103c0d0df1dfec0a770e5285f 100644 --- a/request_llm/bridge_tgui.py +++ b/request_llm/bridge_tgui.py @@ -96,11 +96,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp additional_fn代表点击的哪个按钮,按钮见functional.py """ if additional_fn is not None: - import core_functional - importlib.reload(core_functional) # 热更新prompt - core_functional = core_functional.get_core_functions() - if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话) - inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) raw_input = "What I would like to say is the following: " + inputs history.extend([inputs, ""]) diff --git a/request_llm/chatglmoonx.py b/request_llm/chatglmoonx.py new file mode 100644 index 0000000000000000000000000000000000000000..444181e7d278363479ac9489112dae45f6aa1e1a --- /dev/null +++ b/request_llm/chatglmoonx.py @@ -0,0 +1,229 @@ + + + + + + + +# ------------------------------------------------------------------------------------------------------------------------ +# 🔌💻 Source Code From https://huggingface.co/K024/ChatGLM-6b-onnx-u8s8/blob/main/model.py +# ------------------------------------------------------------------------------------------------------------------------ +import re +import numpy as np +# import torch +from onnxruntime import InferenceSession, SessionOptions + + +# Currently `MatMulInteger` and `DynamicQuantizeLinear` are only supported on CPU, +# although they are documented as supported on CUDA. +providers = ["CPUExecutionProvider"] + +# if torch.cuda.is_available(): +# providers = ["CUDAExecutionProvider"] + providers + + +# Default paths +tokenizer_path = "chatglm-6b-int8-onnx-merged/sentencepiece.model" +onnx_model_path = "chatglm-6b-int8-onnx-merged/chatglm-6b-int8.onnx" + + +# input & output names +past_names = [f"past_{name}_{i}" for i in range(28) for name in ["key", "value"]] +present_names = [f"present_{name}_{i}" for i in range(28) for name in ["key", "value"]] +output_names = ["logits"] + present_names + + +# default kv_cache for first inference +default_past_key_values = { + k: np.zeros((1, 0, 32, 128), dtype=np.float32) for k in past_names +} + + +def chat_template(history: list[tuple[str, str]], current: str): + prompt = "" + chat_round = 0 + for question, answer in history: + prompt += f"[Round {chat_round}]\n问:{question}\n答:{answer}\n" + chat_round += 1 + prompt += f"[Round {chat_round}]\n问:{current}\n答:" + return prompt + + +def process_response(response: str): + response = response.strip() + response = response.replace("[[训练时间]]", "2023年") + punkts = [ + [",", ","], + ["!", "!"], + [":", ":"], + [";", ";"], + ["\?", "?"], + ] + for item in punkts: + response = re.sub(r"([\u4e00-\u9fff])%s" % item[0], r"\1%s" % item[1], response) + response = re.sub(r"%s([\u4e00-\u9fff])" % item[0], r"%s\1" % item[1], response) + return response + + +class ChatGLMModel(): + + def __init__(self, onnx_model_path=onnx_model_path, tokenizer_path=tokenizer_path, profile=False) -> None: + self.tokenizer = ChatGLMTokenizer(tokenizer_path) + options = SessionOptions() + options.enable_profiling = profile + self.session = InferenceSession(onnx_model_path, options, providers=providers) + self.eop_token_id = self.tokenizer[""] + + + def prepare_input(self, prompt: str): + input_ids, prefix_mask = self.tokenizer.encode(prompt) + + input_ids = np.array([input_ids], dtype=np.longlong) + prefix_mask = np.array([prefix_mask], dtype=np.longlong) + + return input_ids, prefix_mask, default_past_key_values + + + def sample_next_token(self, logits: np.ndarray, top_k=50, top_p=0.7, temperature=1): + # softmax with temperature + exp_logits = np.exp(logits / temperature) + probs = exp_logits / np.sum(exp_logits) + + # top k + top_k_idx = np.argsort(-probs)[:top_k] + top_k_probs = probs[top_k_idx] + + # top p + cumsum_probs = np.cumsum(top_k_probs) + top_k_probs[(cumsum_probs - top_k_probs) > top_p] = 0.0 + top_k_probs = top_k_probs / np.sum(top_k_probs) + + # sample + next_token = np.random.choice(top_k_idx, size=1, p=top_k_probs) + return next_token[0].item() + + + def generate_iterate(self, prompt: str, max_generated_tokens=100, top_k=50, top_p=0.7, temperature=1): + input_ids, prefix_mask, past_key_values = self.prepare_input(prompt) + output_tokens = [] + + while True: + inputs = { + "input_ids": input_ids, + "prefix_mask": prefix_mask, + "use_past": np.array(len(output_tokens) > 0), + } + inputs.update(past_key_values) + + logits, *past_key_values = self.session.run(output_names, inputs) + past_key_values = { k: v for k, v in zip(past_names, past_key_values) } + + next_token = self.sample_next_token(logits[0, -1], top_k=top_k, top_p=top_p, temperature=temperature) + + output_tokens += [next_token] + + if next_token == self.eop_token_id or len(output_tokens) > max_generated_tokens: + break + + input_ids = np.array([[next_token]], dtype=np.longlong) + prefix_mask = np.concatenate([prefix_mask, np.array([[0]], dtype=np.longlong)], axis=1) + + yield process_response(self.tokenizer.decode(output_tokens)) + + return process_response(self.tokenizer.decode(output_tokens)) + + + + + + + + + + + + + + +# ------------------------------------------------------------------------------------------------------------------------ +# 🔌💻 Source Code From https://huggingface.co/K024/ChatGLM-6b-onnx-u8s8/blob/main/tokenizer.py +# ------------------------------------------------------------------------------------------------------------------------ + +import re +from sentencepiece import SentencePieceProcessor + + +def replace_spaces_with_blank(match: re.Match[str]): + return f"<|blank_{len(match.group())}|>" + + +def replace_blank_with_spaces(match: re.Match[str]): + return " " * int(match.group(1)) + + +class ChatGLMTokenizer: + def __init__(self, vocab_file): + assert vocab_file is not None + self.vocab_file = vocab_file + self.special_tokens = ["[MASK]", "[gMASK]", "[sMASK]", "", "", "", "", ""] + self.text_tokenizer = SentencePieceProcessor(str(vocab_file)) + + def __len__(self): + return len(self.text_tokenizer) + + def __getitem__(self, key: str): + return self.text_tokenizer[key] + + + def preprocess(self, text: str, linebreak=True, whitespaces=True): + if linebreak: + text = text.replace("\n", "") + if whitespaces: + text = text.replace("\t", "<|tab|>") + text = re.sub(r" {2,80}", replace_spaces_with_blank, text) + return text + + + def encode( + self, text: str, text_pair: str = None, + linebreak=True, whitespaces=True, + add_dummy_prefix=True, special_tokens=True, + ) -> tuple[list[int], list[int]]: + """ + text: Text to encode. Bidirectional part with a [gMASK] and an for causal LM. + text_pair: causal LM part. + linebreak: Whether to encode newline (\n) in text. + whitespaces: Whether to encode multiple whitespaces or tab in text, useful for source code encoding. + special_tokens: Whether to encode special token ([MASK], [gMASK], etc.) in text. + add_dummy_prefix: Whether to add dummy blank space in the beginning. + """ + text = self.preprocess(text, linebreak, whitespaces) + if not add_dummy_prefix: + text = "" + text + + tokens = self.text_tokenizer.encode(text) + prefix_mask = [1] * len(tokens) + if special_tokens: + tokens += [self.text_tokenizer["[gMASK]"], self.text_tokenizer[""]] + prefix_mask += [1, 0] + + if text_pair is not None: + text_pair = self.preprocess(text_pair, linebreak, whitespaces) + pair_tokens = self.text_tokenizer.encode(text_pair) + tokens += pair_tokens + prefix_mask += [0] * len(pair_tokens) + if special_tokens: + tokens += [self.text_tokenizer[""]] + prefix_mask += [0] + + return (tokens if add_dummy_prefix else tokens[2:]), prefix_mask + + + def decode(self, text_ids: list[int]) -> str: + text = self.text_tokenizer.decode(text_ids) + text = text.replace("", "\n") + text = text.replace("<|tab|>", "\t") + text = re.sub(r"<\|blank_(\d\d?)\|>", replace_blank_with_spaces, text) + return text + + diff --git a/request_llm/com_sparkapi.py b/request_llm/com_sparkapi.py new file mode 100644 index 0000000000000000000000000000000000000000..c83710b22457ce5d496e1790d754f6d5d488823a --- /dev/null +++ b/request_llm/com_sparkapi.py @@ -0,0 +1,184 @@ +from toolbox import get_conf +import base64 +import datetime +import hashlib +import hmac +import json +from urllib.parse import urlparse +import ssl +from datetime import datetime +from time import mktime +from urllib.parse import urlencode +from wsgiref.handlers import format_date_time +import websocket +import threading, time + +timeout_bot_msg = '[Local Message] Request timeout. Network error.' + +class Ws_Param(object): + # 初始化 + def __init__(self, APPID, APIKey, APISecret, gpt_url): + self.APPID = APPID + self.APIKey = APIKey + self.APISecret = APISecret + self.host = urlparse(gpt_url).netloc + self.path = urlparse(gpt_url).path + self.gpt_url = gpt_url + + # 生成url + def create_url(self): + # 生成RFC1123格式的时间戳 + now = datetime.now() + date = format_date_time(mktime(now.timetuple())) + + # 拼接字符串 + signature_origin = "host: " + self.host + "\n" + signature_origin += "date: " + date + "\n" + signature_origin += "GET " + self.path + " HTTP/1.1" + + # 进行hmac-sha256进行加密 + signature_sha = hmac.new(self.APISecret.encode('utf-8'), signature_origin.encode('utf-8'), digestmod=hashlib.sha256).digest() + signature_sha_base64 = base64.b64encode(signature_sha).decode(encoding='utf-8') + authorization_origin = f'api_key="{self.APIKey}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha_base64}"' + authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8') + + # 将请求的鉴权参数组合为字典 + v = { + "authorization": authorization, + "date": date, + "host": self.host + } + # 拼接鉴权参数,生成url + url = self.gpt_url + '?' + urlencode(v) + # 此处打印出建立连接时候的url,参考本demo的时候可取消上方打印的注释,比对相同参数时生成的url与自己代码生成的url是否一致 + return url + + + +class SparkRequestInstance(): + def __init__(self): + XFYUN_APPID, XFYUN_API_SECRET, XFYUN_API_KEY = get_conf('XFYUN_APPID', 'XFYUN_API_SECRET', 'XFYUN_API_KEY') + + self.appid = XFYUN_APPID + self.api_secret = XFYUN_API_SECRET + self.api_key = XFYUN_API_KEY + self.gpt_url = "ws://spark-api.xf-yun.com/v1.1/chat" + self.time_to_yield_event = threading.Event() + self.time_to_exit_event = threading.Event() + + self.result_buf = "" + + def generate(self, inputs, llm_kwargs, history, system_prompt): + llm_kwargs = llm_kwargs + history = history + system_prompt = system_prompt + import _thread as thread + thread.start_new_thread(self.create_blocking_request, (inputs, llm_kwargs, history, system_prompt)) + while True: + self.time_to_yield_event.wait(timeout=1) + if self.time_to_yield_event.is_set(): + yield self.result_buf + if self.time_to_exit_event.is_set(): + return self.result_buf + + + def create_blocking_request(self, inputs, llm_kwargs, history, system_prompt): + wsParam = Ws_Param(self.appid, self.api_key, self.api_secret, self.gpt_url) + websocket.enableTrace(False) + wsUrl = wsParam.create_url() + + # 收到websocket连接建立的处理 + def on_open(ws): + import _thread as thread + thread.start_new_thread(run, (ws,)) + + def run(ws, *args): + data = json.dumps(gen_params(ws.appid, *ws.all_args)) + ws.send(data) + + # 收到websocket消息的处理 + def on_message(ws, message): + data = json.loads(message) + code = data['header']['code'] + if code != 0: + print(f'请求错误: {code}, {data}') + ws.close() + self.time_to_exit_event.set() + else: + choices = data["payload"]["choices"] + status = choices["status"] + content = choices["text"][0]["content"] + ws.content += content + self.result_buf += content + if status == 2: + ws.close() + self.time_to_exit_event.set() + self.time_to_yield_event.set() + + # 收到websocket错误的处理 + def on_error(ws, error): + print("error:", error) + self.time_to_exit_event.set() + + # 收到websocket关闭的处理 + def on_close(ws, *args): + self.time_to_exit_event.set() + + # websocket + ws = websocket.WebSocketApp(wsUrl, on_message=on_message, on_error=on_error, on_close=on_close, on_open=on_open) + ws.appid = self.appid + ws.content = "" + ws.all_args = (inputs, llm_kwargs, history, system_prompt) + ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE}) + +def generate_message_payload(inputs, llm_kwargs, history, system_prompt): + conversation_cnt = len(history) // 2 + messages = [{"role": "system", "content": 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["content"] = history[index] + what_gpt_answer = {} + what_gpt_answer["role"] = "assistant" + what_gpt_answer["content"] = history[index+1] + if what_i_have_asked["content"] != "": + if what_gpt_answer["content"] == "": continue + if what_gpt_answer["content"] == timeout_bot_msg: continue + messages.append(what_i_have_asked) + messages.append(what_gpt_answer) + else: + messages[-1]['content'] = what_gpt_answer['content'] + what_i_ask_now = {} + what_i_ask_now["role"] = "user" + what_i_ask_now["content"] = inputs + messages.append(what_i_ask_now) + return messages + + +def gen_params(appid, inputs, llm_kwargs, history, system_prompt): + """ + 通过appid和用户的提问来生成请参数 + """ + data = { + "header": { + "app_id": appid, + "uid": "1234" + }, + "parameter": { + "chat": { + "domain": "general", + "temperature": llm_kwargs["temperature"], + "random_threshold": 0.5, + "max_tokens": 4096, + "auditing": "default" + } + }, + "payload": { + "message": { + "text": generate_message_payload(inputs, llm_kwargs, history, system_prompt) + } + } + } + return data + diff --git a/request_llm/edge_gpt_free.py b/request_llm/edge_gpt_free.py index ef6187379c470b0f325d50d7642cfc95b933f1ef..22ff05272b634e8557ceb83501248cc238074366 100644 --- a/request_llm/edge_gpt_free.py +++ b/request_llm/edge_gpt_free.py @@ -447,6 +447,15 @@ class _ChatHub: """ Ask a question to the bot """ + req_header = HEADERS + if self.cookies is not None: + ws_cookies = [] + for cookie in self.cookies: + ws_cookies.append(f"{cookie['name']}={cookie['value']}") + req_header.update({ + 'Cookie': ';'.join(ws_cookies), + }) + timeout = aiohttp.ClientTimeout(total=30) self.session = aiohttp.ClientSession(timeout=timeout) @@ -455,7 +464,7 @@ class _ChatHub: # Check if websocket is closed self.wss = await self.session.ws_connect( wss_link, - headers=HEADERS, + headers=req_header, ssl=ssl_context, proxy=self.proxy, autoping=False, @@ -510,7 +519,11 @@ class _ChatHub: resp_txt_no_link = "" while not final: msg = await self.wss.receive() - objects = msg.data.split(DELIMITER) + try: + objects = msg.data.split(DELIMITER) + except : + continue + for obj in objects: if obj is None or not obj: continue @@ -1109,4 +1122,4 @@ class ImageQuery(Query): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/request_llm/local_llm_class.py b/request_llm/local_llm_class.py new file mode 100644 index 0000000000000000000000000000000000000000..3dd266fe77317d0b09e4eaa1cf5942717eed35d7 --- /dev/null +++ b/request_llm/local_llm_class.py @@ -0,0 +1,180 @@ +from transformers import AutoModel, AutoTokenizer +import time +import threading +import importlib +from toolbox import update_ui, get_conf, Singleton +from multiprocessing import Process, Pipe + +def SingletonLocalLLM(cls): + """ + 一个单实例装饰器 + """ + _instance = {} + def _singleton(*args, **kargs): + if cls not in _instance: + _instance[cls] = cls(*args, **kargs) + return _instance[cls] + elif _instance[cls].corrupted: + _instance[cls] = cls(*args, **kargs) + return _instance[cls] + else: + return _instance[cls] + return _singleton + +class LocalLLMHandle(Process): + def __init__(self): + # ⭐主进程执行 + super().__init__(daemon=True) + self.corrupted = False + self.load_model_info() + self.parent, self.child = Pipe() + self.running = True + self._model = None + self._tokenizer = None + self.info = "" + self.check_dependency() + self.start() + self.threadLock = threading.Lock() + + def load_model_info(self): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + raise NotImplementedError("Method not implemented yet") + self.model_name = "" + self.cmd_to_install = "" + + def load_model_and_tokenizer(self): + """ + This function should return the model and the tokenizer + """ + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + raise NotImplementedError("Method not implemented yet") + + def llm_stream_generator(self, **kwargs): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + raise NotImplementedError("Method not implemented yet") + + def try_to_import_special_deps(self, **kwargs): + """ + import something that will raise error if the user does not install requirement_*.txt + """ + # ⭐主进程执行 + raise NotImplementedError("Method not implemented yet") + + def check_dependency(self): + # ⭐主进程执行 + try: + self.try_to_import_special_deps() + self.info = "依赖检测通过" + self.running = True + except: + self.info = f"缺少{self.model_name}的依赖,如果要使用{self.model_name},除了基础的pip依赖以外,您还需要运行{self.cmd_to_install}安装{self.model_name}的依赖。" + self.running = False + + def run(self): + # 🏃‍♂️🏃‍♂️🏃‍♂️ 子进程执行 + # 第一次运行,加载参数 + try: + self._model, self._tokenizer = self.load_model_and_tokenizer() + except: + self.running = False + from toolbox import trimmed_format_exc + self.child.send(f'[Local Message] 不能正常加载{self.model_name}的参数.' + '\n```\n' + trimmed_format_exc() + '\n```\n') + self.child.send('[FinishBad]') + raise RuntimeError(f"不能正常加载{self.model_name}的参数!") + + while True: + # 进入任务等待状态 + kwargs = self.child.recv() + # 收到消息,开始请求 + try: + for response_full in self.llm_stream_generator(**kwargs): + self.child.send(response_full) + self.child.send('[Finish]') + # 请求处理结束,开始下一个循环 + except: + from toolbox import trimmed_format_exc + self.child.send(f'[Local Message] 调用{self.model_name}失败.' + '\n```\n' + trimmed_format_exc() + '\n```\n') + self.child.send('[Finish]') + + def stream_chat(self, **kwargs): + # ⭐主进程执行 + self.threadLock.acquire() + self.parent.send(kwargs) + while True: + res = self.parent.recv() + if res == '[Finish]': + break + if res == '[FinishBad]': + self.running = False + self.corrupted = True + break + else: + yield res + self.threadLock.release() + + + +def get_local_llm_predict_fns(LLMSingletonClass, model_name): + 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): + """ + ⭐多线程方法 + 函数的说明请见 request_llm/bridge_all.py + """ + _llm_handle = LLMSingletonClass() + if len(observe_window) >= 1: observe_window[0] = load_message + "\n\n" + _llm_handle.info + if not _llm_handle.running: raise RuntimeError(_llm_handle.info) + + # chatglm 没有 sys_prompt 接口,因此把prompt加入 history + history_feedin = [] + history_feedin.append(["What can I do?", sys_prompt]) + for i in range(len(history)//2): + history_feedin.append([history[2*i], history[2*i+1]] ) + + watch_dog_patience = 5 # 看门狗 (watchdog) 的耐心, 设置5秒即可 + response = "" + for response in _llm_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']): + if len(observe_window) >= 1: + observe_window[0] = response + if len(observe_window) >= 2: + if (time.time()-observe_window[1]) > watch_dog_patience: raise RuntimeError("程序终止。") + return response + + + + def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None): + """ + ⭐单线程方法 + 函数的说明请见 request_llm/bridge_all.py + """ + chatbot.append((inputs, "")) + + _llm_handle = LLMSingletonClass() + chatbot[-1] = (inputs, load_message + "\n\n" + _llm_handle.info) + yield from update_ui(chatbot=chatbot, history=[]) + if not _llm_handle.running: raise RuntimeError(_llm_handle.info) + + if additional_fn is not None: + from core_functional import handle_core_functionality + inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot) + + # 处理历史信息 + history_feedin = [] + history_feedin.append(["What can I do?", system_prompt] ) + for i in range(len(history)//2): + history_feedin.append([history[2*i], history[2*i+1]] ) + + # 开始接收回复 + response = f"[Local Message]: 等待{model_name}响应中 ..." + for response in _llm_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']): + chatbot[-1] = (inputs, response) + yield from update_ui(chatbot=chatbot, history=history) + + # 总结输出 + if response == f"[Local Message]: 等待{model_name}响应中 ...": + response = f"[Local Message]: {model_name}响应异常 ..." + history.extend([inputs, response]) + yield from update_ui(chatbot=chatbot, history=history) + + return predict_no_ui_long_connection, predict \ No newline at end of file diff --git a/request_llm/requirements_chatglm.txt b/request_llm/requirements_chatglm.txt index fa049cafa6bfdfd0734b8e3e2f01774ee846ac0e..b2629f83d9dc3e54589d59c02de585afa58772b4 100644 --- a/request_llm/requirements_chatglm.txt +++ b/request_llm/requirements_chatglm.txt @@ -1,5 +1,5 @@ protobuf -transformers==4.27.1 +transformers>=4.27.1 cpm_kernels torch>=1.10 mdtex2html diff --git a/request_llm/requirements_chatglm_onnx.txt b/request_llm/requirements_chatglm_onnx.txt new file mode 100644 index 0000000000000000000000000000000000000000..70ab6684a7c3472daa381154f276725ca91840fa --- /dev/null +++ b/request_llm/requirements_chatglm_onnx.txt @@ -0,0 +1,11 @@ +protobuf +transformers>=4.27.1 +cpm_kernels +torch>=1.10 +mdtex2html +sentencepiece +numpy +onnxruntime +sentencepiece +streamlit +streamlit-chat diff --git a/request_llm/requirements_qwen.txt b/request_llm/requirements_qwen.txt new file mode 100644 index 0000000000000000000000000000000000000000..3d7d62a05d2023abc94dbbe1c61ff49fc7796c41 --- /dev/null +++ b/request_llm/requirements_qwen.txt @@ -0,0 +1,2 @@ +modelscope +transformers_stream_generator \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 8ecfbc1b7a56ce89a8a6b92218e08e0d93f2328d..92dc4772a0ec984f5032df136c454192d86d4f90 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,5 @@ +./docs/gradio-3.32.2-py3-none-any.whl +pydantic==1.10.11 tiktoken>=0.3.3 requests[socks] transformers @@ -7,6 +9,7 @@ prompt_toolkit latex2mathml python-docx mdtex2html +anthropic colorama Markdown pygments @@ -15,3 +18,5 @@ openai numpy arxiv rich +websocket-client +pypdf2==2.12.1 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/test_llms.py b/tests/test_llms.py new file mode 100644 index 0000000000000000000000000000000000000000..75e230327eec6d1e8869dccd85a576b94fb51f26 --- /dev/null +++ b/tests/test_llms.py @@ -0,0 +1,32 @@ +# """ +# 对各个llm模型进行单元测试 +# """ +def validate_path(): + import os, sys + dir_name = os.path.dirname(__file__) + root_dir_assume = os.path.abspath(os.path.dirname(__file__) + '/..') + os.chdir(root_dir_assume) + sys.path.append(root_dir_assume) + +validate_path() # validate path so you can run from base directory +if __name__ == "__main__": + # from request_llm.bridge_newbingfree import predict_no_ui_long_connection + # from request_llm.bridge_moss import predict_no_ui_long_connection + # from request_llm.bridge_jittorllms_pangualpha import predict_no_ui_long_connection + # from request_llm.bridge_jittorllms_llama import predict_no_ui_long_connection + # from request_llm.bridge_claude import predict_no_ui_long_connection + # from request_llm.bridge_internlm import predict_no_ui_long_connection + # from request_llm.bridge_qwen import predict_no_ui_long_connection + from request_llm.bridge_spark 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) diff --git a/tests/test_plugins.py b/tests/test_plugins.py new file mode 100644 index 0000000000000000000000000000000000000000..53969bf53d58085a8683dbc7999e74f02fcb1d6d --- /dev/null +++ b/tests/test_plugins.py @@ -0,0 +1,52 @@ +""" +对项目中的各个插件进行测试。运行方法:直接运行 python tests/test_plugins.py +""" + + +import os, sys +def validate_path(): dir_name = os.path.dirname(__file__); root_dir_assume = os.path.abspath(dir_name + '/..'); os.chdir(root_dir_assume); sys.path.append(root_dir_assume) +validate_path() # 返回项目根路径 +from tests.test_utils import plugin_test + +if __name__ == "__main__": + plugin_test(plugin='crazy_functions.命令行助手->命令行助手', main_input='查看当前的docker容器列表') + + plugin_test(plugin='crazy_functions.解析项目源代码->解析一个Python项目', main_input="crazy_functions/test_project/python/dqn") + + # plugin_test(plugin='crazy_functions.解析项目源代码->解析一个C项目', main_input="crazy_functions/test_project/cpp/cppipc") + + # plugin_test(plugin='crazy_functions.Latex全文润色->Latex英文润色', main_input="crazy_functions/test_project/latex/attention") + + # plugin_test(plugin='crazy_functions.批量Markdown翻译->Markdown中译英', main_input="README.md") + + # plugin_test(plugin='crazy_functions.批量翻译PDF文档_多线程->批量翻译PDF文档', main_input="crazy_functions/test_project/pdf_and_word") + + # plugin_test(plugin='crazy_functions.谷歌检索小助手->谷歌检索小助手', main_input="https://scholar.google.com/scholar?hl=en&as_sdt=0%2C5&q=auto+reinforcement+learning&btnG=") + + # plugin_test(plugin='crazy_functions.总结word文档->总结word文档', main_input="crazy_functions/test_project/pdf_and_word") + + # plugin_test(plugin='crazy_functions.下载arxiv论文翻译摘要->下载arxiv论文并翻译摘要', main_input="1812.10695") + + # plugin_test(plugin='crazy_functions.联网的ChatGPT->连接网络回答问题', main_input="谁是应急食品?") + + # plugin_test(plugin='crazy_functions.解析JupyterNotebook->解析ipynb文件', main_input="crazy_functions/test_samples") + + # plugin_test(plugin='crazy_functions.数学动画生成manim->动画生成', main_input="A ball split into 2, and then split into 4, and finally split into 8.") + + # for lang in ["English", "French", "Japanese", "Korean", "Russian", "Italian", "German", "Portuguese", "Arabic"]: + # plugin_test(plugin='crazy_functions.批量Markdown翻译->Markdown翻译指定语言', main_input="README.md", advanced_arg={"advanced_arg": lang}) + + # plugin_test(plugin='crazy_functions.Langchain知识库->知识库问答', main_input="./") + + # plugin_test(plugin='crazy_functions.Langchain知识库->读取知识库作答', main_input="What is the installation method?") + + # plugin_test(plugin='crazy_functions.Langchain知识库->读取知识库作答', main_input="远程云服务器部署?") + + # plugin_test(plugin='crazy_functions.Latex输出PDF结果->Latex翻译中文并重新编译PDF', main_input="2210.03629") + + # advanced_arg = {"advanced_arg":"--llm_to_learn=gpt-3.5-turbo --prompt_prefix='根据下面的服装类型提示,想象一个穿着者,对这个人外貌、身处的环境、内心世界、人设进行描写。要求:100字以内,用第二人称。' --system_prompt=''" } + # plugin_test(plugin='crazy_functions.chatglm微调工具->微调数据集生成', main_input='build/dev.json', advanced_arg=advanced_arg) + + # advanced_arg = {"advanced_arg":"--pre_seq_len=128 --learning_rate=2e-2 --num_gpus=1 --json_dataset='t_code.json' --ptuning_directory='/home/hmp/ChatGLM2-6B/ptuning' " } + # plugin_test(plugin='crazy_functions.chatglm微调工具->启动微调', main_input='build/dev.json', advanced_arg=advanced_arg) + diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..682a96f6ac17b714c23b597ffeb2d047dda9da62 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,78 @@ +from toolbox import get_conf +from toolbox import set_conf +from toolbox import set_multi_conf +from toolbox import get_plugin_handle +from toolbox import get_plugin_default_kwargs +from toolbox import get_chat_handle +from toolbox import get_chat_default_kwargs +from functools import wraps +import sys +import os + +def chat_to_markdown_str(chat): + result = "" + for i, cc in enumerate(chat): + result += f'\n\n{cc[0]}\n\n{cc[1]}' + if i != len(chat)-1: + result += '\n\n---' + return result + +def silence_stdout(func): + @wraps(func) + def wrapper(*args, **kwargs): + _original_stdout = sys.stdout + sys.stdout = open(os.devnull, 'w') + for q in func(*args, **kwargs): + sys.stdout = _original_stdout + yield q + sys.stdout = open(os.devnull, 'w') + sys.stdout.close() + sys.stdout = _original_stdout + return wrapper + +def silence_stdout_fn(func): + @wraps(func) + def wrapper(*args, **kwargs): + _original_stdout = sys.stdout + sys.stdout = open(os.devnull, 'w') + result = func(*args, **kwargs) + sys.stdout.close() + sys.stdout = _original_stdout + return result + return wrapper + +class VoidTerminal(): + def __init__(self) -> None: + pass + +vt = VoidTerminal() +vt.get_conf = silence_stdout_fn(get_conf) +vt.set_conf = silence_stdout_fn(set_conf) +vt.set_multi_conf = silence_stdout_fn(set_multi_conf) +vt.get_plugin_handle = silence_stdout_fn(get_plugin_handle) +vt.get_plugin_default_kwargs = silence_stdout_fn(get_plugin_default_kwargs) +vt.get_chat_handle = silence_stdout_fn(get_chat_handle) +vt.get_chat_default_kwargs = silence_stdout_fn(get_chat_default_kwargs) +vt.chat_to_markdown_str = chat_to_markdown_str +proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, API_KEY = \ + vt.get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'API_KEY') + +def plugin_test(main_input, plugin, advanced_arg=None): + from rich.live import Live + from rich.markdown import Markdown + + vt.set_conf(key="API_KEY", value=API_KEY) + vt.set_conf(key="LLM_MODEL", value=LLM_MODEL) + + plugin = vt.get_plugin_handle(plugin) + plugin_kwargs = vt.get_plugin_default_kwargs() + plugin_kwargs['main_input'] = main_input + if advanced_arg is not None: + plugin_kwargs['plugin_kwargs'] = advanced_arg + my_working_plugin = silence_stdout(plugin)(**plugin_kwargs) + + with Live(Markdown(""), auto_refresh=False) as live: + for cookies, chat, hist, msg in my_working_plugin: + md_str = vt.chat_to_markdown_str(chat) + md = Markdown(md_str) + live.update(md, refresh=True) \ No newline at end of file diff --git a/themes/common.js b/themes/common.js new file mode 100644 index 0000000000000000000000000000000000000000..dcdeb50e2bbf508abb2d38624a5d60b057a27425 --- /dev/null +++ b/themes/common.js @@ -0,0 +1,47 @@ +function ChatBotHeight() { + function update_height(){ + var { panel_height_target, chatbot_height, chatbot } = get_elements(); + if (panel_height_target!=chatbot_height) + { + var pixelString = panel_height_target.toString() + 'px'; + chatbot.style.maxHeight = pixelString; chatbot.style.height = pixelString; + } + } + + function update_height_slow(){ + var { panel_height_target, chatbot_height, chatbot } = get_elements(); + if (panel_height_target!=chatbot_height) + { + new_panel_height = (panel_height_target - chatbot_height)*0.5 + chatbot_height; + if (Math.abs(new_panel_height - panel_height_target) < 10){ + new_panel_height = panel_height_target; + } + // console.log(chatbot_height, panel_height_target, new_panel_height); + var pixelString = new_panel_height.toString() + 'px'; + chatbot.style.maxHeight = pixelString; chatbot.style.height = pixelString; + } + } + + update_height(); + setInterval(function() { + update_height_slow() + }, 50); // 每100毫秒执行一次 +} + +function get_elements() { + var chatbot = document.querySelector('#gpt-chatbot > div.wrap.svelte-18telvq'); + if (!chatbot) { + chatbot = document.querySelector('#gpt-chatbot'); + } + const panel1 = document.querySelector('#input-panel'); + const panel2 = document.querySelector('#basic-panel'); + const panel3 = document.querySelector('#plugin-panel'); + const panel4 = document.querySelector('#interact-panel'); + const panel5 = document.querySelector('#input-panel2'); + const panel_active = document.querySelector('#state-panel'); + var panel_height_target = (20-panel_active.offsetHeight) + panel1.offsetHeight + panel2.offsetHeight + panel3.offsetHeight + panel4.offsetHeight + panel5.offsetHeight + 21; + var panel_height_target = parseInt(panel_height_target); + var chatbot_height = chatbot.style.height; + var chatbot_height = parseInt(chatbot_height); + return { panel_height_target, chatbot_height, chatbot }; +} \ No newline at end of file diff --git a/themes/default.css b/themes/default.css new file mode 100644 index 0000000000000000000000000000000000000000..07b5383c2b62b4150416b51a1b49b8ada70f1475 --- /dev/null +++ b/themes/default.css @@ -0,0 +1,252 @@ +.markdown-body table { + margin: 1em 0; + border-collapse: collapse; + empty-cells: show; +} + +.markdown-body th, .markdown-body td { + border: 1.2px solid var(--border-color-primary); + padding: 5px; +} + +.markdown-body thead { + background-color: rgba(175,184,193,0.2); +} + +.markdown-body thead th { + padding: .5em .2em; +} + +.markdown-body ol, .markdown-body ul { + padding-inline-start: 2em !important; +} + +/* chat box. */ +[class *= "message"] { + border-radius: var(--radius-xl) !important; + /* padding: var(--spacing-xl) !important; */ + /* font-size: var(--text-md) !important; */ + /* line-height: var(--line-md) !important; */ + /* min-height: calc(var(--text-md)*var(--line-md) + 2*var(--spacing-xl)); */ + /* min-width: calc(var(--text-md)*var(--line-md) + 2*var(--spacing-xl)); */ +} +[data-testid = "bot"] { + max-width: 95%; + /* width: auto !important; */ + border-bottom-left-radius: 0 !important; +} +[data-testid = "user"] { + max-width: 100%; + /* width: auto !important; */ + border-bottom-right-radius: 0 !important; +} + +/* linein code block. */ +.markdown-body code { + display: inline; + white-space: break-spaces; + border-radius: 6px; + margin: 0 2px 0 2px; + padding: .2em .4em .1em .4em; + background-color: rgba(13, 17, 23, 0.95); + color: #c9d1d9; +} + +.dark .markdown-body code { + display: inline; + white-space: break-spaces; + border-radius: 6px; + margin: 0 2px 0 2px; + padding: .2em .4em .1em .4em; + background-color: rgba(175,184,193,0.2); +} + +/* code block css */ +.markdown-body pre code { + display: block; + overflow: auto; + white-space: pre; + background-color: rgba(13, 17, 23, 0.95); + border-radius: 10px; + padding: 1em; + margin: 1em 2em 1em 0.5em; +} + +.dark .markdown-body pre code { + display: block; + overflow: auto; + white-space: pre; + background-color: rgba(175,184,193,0.2); + border-radius: 10px; + padding: 1em; + margin: 1em 2em 1em 0.5em; +} + +/* .mic-wrap.svelte-1thnwz { + +} */ +.block.svelte-mppz8v > .mic-wrap.svelte-1thnwz{ + justify-content: center; + display: flex; + padding: 0; + +} + +.codehilite .hll { background-color: #6e7681 } +.codehilite .c { color: #8b949e; font-style: italic } /* Comment */ +.codehilite .err { color: #f85149 } /* Error */ +.codehilite .esc { color: #c9d1d9 } /* Escape */ +.codehilite .g { color: #c9d1d9 } /* Generic */ +.codehilite .k { color: #ff7b72 } /* Keyword */ +.codehilite .l { color: #a5d6ff } /* Literal */ +.codehilite .n { color: #c9d1d9 } /* Name */ +.codehilite .o { color: #ff7b72; font-weight: bold } /* Operator */ +.codehilite .x { color: #c9d1d9 } /* Other */ +.codehilite .p { color: #c9d1d9 } /* Punctuation */ +.codehilite .ch { color: #8b949e; font-style: italic } /* Comment.Hashbang */ +.codehilite .cm { color: #8b949e; font-style: italic } /* Comment.Multiline */ +.codehilite .cp { color: #8b949e; font-weight: bold; font-style: italic } /* Comment.Preproc */ +.codehilite .cpf { color: #8b949e; font-style: italic } /* Comment.PreprocFile */ +.codehilite .c1 { color: #8b949e; font-style: italic } /* Comment.Single */ +.codehilite .cs { color: #8b949e; font-weight: bold; font-style: italic } /* Comment.Special */ +.codehilite .gd { color: #ffa198; background-color: #490202 } /* Generic.Deleted */ +.codehilite .ge { color: #c9d1d9; font-style: italic } /* Generic.Emph */ +.codehilite .gr { color: #ffa198 } /* Generic.Error */ +.codehilite .gh { color: #79c0ff; font-weight: bold } /* Generic.Heading */ +.codehilite .gi { color: #56d364; background-color: #0f5323 } /* Generic.Inserted */ +.codehilite .go { color: #8b949e } /* Generic.Output */ +.codehilite .gp { color: #8b949e } /* Generic.Prompt */ +.codehilite .gs { color: #c9d1d9; font-weight: bold } /* Generic.Strong */ +.codehilite .gu { color: #79c0ff } /* Generic.Subheading */ +.codehilite .gt { color: #ff7b72 } /* Generic.Traceback */ +.codehilite .g-Underline { color: #c9d1d9; text-decoration: underline } /* Generic.Underline */ +.codehilite .kc { color: #79c0ff } /* Keyword.Constant */ +.codehilite .kd { color: #ff7b72 } /* Keyword.Declaration */ +.codehilite .kn { color: #ff7b72 } /* Keyword.Namespace */ +.codehilite .kp { color: #79c0ff } /* Keyword.Pseudo */ +.codehilite .kr { color: #ff7b72 } /* Keyword.Reserved */ +.codehilite .kt { color: #ff7b72 } /* Keyword.Type */ +.codehilite .ld { color: #79c0ff } /* Literal.Date */ +.codehilite .m { color: #a5d6ff } /* Literal.Number */ +.codehilite .s { color: #a5d6ff } /* Literal.String */ +.codehilite .na { color: #c9d1d9 } /* Name.Attribute */ +.codehilite .nb { color: #c9d1d9 } /* Name.Builtin */ +.codehilite .nc { color: #f0883e; font-weight: bold } /* Name.Class */ +.codehilite .no { color: #79c0ff; font-weight: bold } /* Name.Constant */ +.codehilite .nd { color: #d2a8ff; font-weight: bold } /* Name.Decorator */ +.codehilite .ni { color: #ffa657 } /* Name.Entity */ +.codehilite .ne { color: #f0883e; font-weight: bold } /* Name.Exception */ +.codehilite .nf { color: #d2a8ff; font-weight: bold } /* Name.Function */ +.codehilite .nl { color: #79c0ff; font-weight: bold } /* Name.Label */ +.codehilite .nn { color: #ff7b72 } /* Name.Namespace */ +.codehilite .nx { color: #c9d1d9 } /* Name.Other */ +.codehilite .py { color: #79c0ff } /* Name.Property */ +.codehilite .nt { color: #7ee787 } /* Name.Tag */ +.codehilite .nv { color: #79c0ff } /* Name.Variable */ +.codehilite .ow { color: #ff7b72; font-weight: bold } /* Operator.Word */ +.codehilite .pm { color: #c9d1d9 } /* Punctuation.Marker */ +.codehilite .w { color: #6e7681 } /* Text.Whitespace */ +.codehilite .mb { color: #a5d6ff } /* Literal.Number.Bin */ +.codehilite .mf { color: #a5d6ff } /* Literal.Number.Float */ +.codehilite .mh { color: #a5d6ff } /* Literal.Number.Hex */ +.codehilite .mi { color: #a5d6ff } /* Literal.Number.Integer */ +.codehilite .mo { color: #a5d6ff } /* Literal.Number.Oct */ +.codehilite .sa { color: #79c0ff } /* Literal.String.Affix */ +.codehilite .sb { color: #a5d6ff } /* Literal.String.Backtick */ +.codehilite .sc { color: #a5d6ff } /* Literal.String.Char */ +.codehilite .dl { color: #79c0ff } /* Literal.String.Delimiter */ +.codehilite .sd { color: #a5d6ff } /* Literal.String.Doc */ +.codehilite .s2 { color: #a5d6ff } /* Literal.String.Double */ +.codehilite .se { color: #79c0ff } /* Literal.String.Escape */ +.codehilite .sh { color: #79c0ff } /* Literal.String.Heredoc */ +.codehilite .si { color: #a5d6ff } /* Literal.String.Interpol */ +.codehilite .sx { color: #a5d6ff } /* Literal.String.Other */ +.codehilite .sr { color: #79c0ff } /* Literal.String.Regex */ +.codehilite .s1 { color: #a5d6ff } /* Literal.String.Single */ +.codehilite .ss { color: #a5d6ff } /* Literal.String.Symbol */ +.codehilite .bp { color: #c9d1d9 } /* Name.Builtin.Pseudo */ +.codehilite .fm { color: #d2a8ff; font-weight: bold } /* Name.Function.Magic */ +.codehilite .vc { color: #79c0ff } /* Name.Variable.Class */ +.codehilite .vg { color: #79c0ff } /* Name.Variable.Global */ +.codehilite .vi { color: #79c0ff } /* Name.Variable.Instance */ +.codehilite .vm { color: #79c0ff } /* Name.Variable.Magic */ +.codehilite .il { color: #a5d6ff } /* Literal.Number.Integer.Long */ + +.dark .codehilite .hll { background-color: #2C3B41 } +.dark .codehilite .c { color: #79d618; font-style: italic } /* Comment */ +.dark .codehilite .err { color: #FF5370 } /* Error */ +.dark .codehilite .esc { color: #89DDFF } /* Escape */ +.dark .codehilite .g { color: #EEFFFF } /* Generic */ +.dark .codehilite .k { color: #BB80B3 } /* Keyword */ +.dark .codehilite .l { color: #C3E88D } /* Literal */ +.dark .codehilite .n { color: #EEFFFF } /* Name */ +.dark .codehilite .o { color: #89DDFF } /* Operator */ +.dark .codehilite .p { color: #89DDFF } /* Punctuation */ +.dark .codehilite .ch { color: #79d618; font-style: italic } /* Comment.Hashbang */ +.dark .codehilite .cm { color: #79d618; font-style: italic } /* Comment.Multiline */ +.dark .codehilite .cp { color: #79d618; font-style: italic } /* Comment.Preproc */ +.dark .codehilite .cpf { color: #79d618; font-style: italic } /* Comment.PreprocFile */ +.dark .codehilite .c1 { color: #79d618; font-style: italic } /* Comment.Single */ +.dark .codehilite .cs { color: #79d618; font-style: italic } /* Comment.Special */ +.dark .codehilite .gd { color: #FF5370 } /* Generic.Deleted */ +.dark .codehilite .ge { color: #89DDFF } /* Generic.Emph */ +.dark .codehilite .gr { color: #FF5370 } /* Generic.Error */ +.dark .codehilite .gh { color: #C3E88D } /* Generic.Heading */ +.dark .codehilite .gi { color: #C3E88D } /* Generic.Inserted */ +.dark .codehilite .go { color: #79d618 } /* Generic.Output */ +.dark .codehilite .gp { color: #FFCB6B } /* Generic.Prompt */ +.dark .codehilite .gs { color: #FF5370 } /* Generic.Strong */ +.dark .codehilite .gu { color: #89DDFF } /* Generic.Subheading */ +.dark .codehilite .gt { color: #FF5370 } /* Generic.Traceback */ +.dark .codehilite .kc { color: #89DDFF } /* Keyword.Constant */ +.dark .codehilite .kd { color: #BB80B3 } /* Keyword.Declaration */ +.dark .codehilite .kn { color: #89DDFF; font-style: italic } /* Keyword.Namespace */ +.dark .codehilite .kp { color: #89DDFF } /* Keyword.Pseudo */ +.dark .codehilite .kr { color: #BB80B3 } /* Keyword.Reserved */ +.dark .codehilite .kt { color: #BB80B3 } /* Keyword.Type */ +.dark .codehilite .ld { color: #C3E88D } /* Literal.Date */ +.dark .codehilite .m { color: #F78C6C } /* Literal.Number */ +.dark .codehilite .s { color: #C3E88D } /* Literal.String */ +.dark .codehilite .na { color: #BB80B3 } /* Name.Attribute */ +.dark .codehilite .nb { color: #82AAFF } /* Name.Builtin */ +.dark .codehilite .nc { color: #FFCB6B } /* Name.Class */ +.dark .codehilite .no { color: #EEFFFF } /* Name.Constant */ +.dark .codehilite .nd { color: #82AAFF } /* Name.Decorator */ +.dark .codehilite .ni { color: #89DDFF } /* Name.Entity */ +.dark .codehilite .ne { color: #FFCB6B } /* Name.Exception */ +.dark .codehilite .nf { color: #82AAFF } /* Name.Function */ +.dark .codehilite .nl { color: #82AAFF } /* Name.Label */ +.dark .codehilite .nn { color: #FFCB6B } /* Name.Namespace */ +.dark .codehilite .nx { color: #EEFFFF } /* Name.Other */ +.dark .codehilite .py { color: #FFCB6B } /* Name.Property */ +.dark .codehilite .nt { color: #FF5370 } /* Name.Tag */ +.dark .codehilite .nv { color: #89DDFF } /* Name.Variable */ +.dark .codehilite .ow { color: #89DDFF; font-style: italic } /* Operator.Word */ +.dark .codehilite .pm { color: #89DDFF } /* Punctuation.Marker */ +.dark .codehilite .w { color: #EEFFFF } /* Text.Whitespace */ +.dark .codehilite .mb { color: #F78C6C } /* Literal.Number.Bin */ +.dark .codehilite .mf { color: #F78C6C } /* Literal.Number.Float */ +.dark .codehilite .mh { color: #F78C6C } /* Literal.Number.Hex */ +.dark .codehilite .mi { color: #F78C6C } /* Literal.Number.Integer */ +.dark .codehilite .mo { color: #F78C6C } /* Literal.Number.Oct */ +.dark .codehilite .sa { color: #BB80B3 } /* Literal.String.Affix */ +.dark .codehilite .sb { color: #C3E88D } /* Literal.String.Backtick */ +.dark .codehilite .sc { color: #C3E88D } /* Literal.String.Char */ +.dark .codehilite .dl { color: #EEFFFF } /* Literal.String.Delimiter */ +.dark .codehilite .sd { color: #79d618; font-style: italic } /* Literal.String.Doc */ +.dark .codehilite .s2 { color: #C3E88D } /* Literal.String.Double */ +.dark .codehilite .se { color: #EEFFFF } /* Literal.String.Escape */ +.dark .codehilite .sh { color: #C3E88D } /* Literal.String.Heredoc */ +.dark .codehilite .si { color: #89DDFF } /* Literal.String.Interpol */ +.dark .codehilite .sx { color: #C3E88D } /* Literal.String.Other */ +.dark .codehilite .sr { color: #89DDFF } /* Literal.String.Regex */ +.dark .codehilite .s1 { color: #C3E88D } /* Literal.String.Single */ +.dark .codehilite .ss { color: #89DDFF } /* Literal.String.Symbol */ +.dark .codehilite .bp { color: #89DDFF } /* Name.Builtin.Pseudo */ +.dark .codehilite .fm { color: #82AAFF } /* Name.Function.Magic */ +.dark .codehilite .vc { color: #89DDFF } /* Name.Variable.Class */ +.dark .codehilite .vg { color: #89DDFF } /* Name.Variable.Global */ +.dark .codehilite .vi { color: #89DDFF } /* Name.Variable.Instance */ +.dark .codehilite .vm { color: #82AAFF } /* Name.Variable.Magic */ +.dark .codehilite .il { color: #F78C6C } /* Literal.Number.Integer.Long */ + diff --git a/themes/default.py b/themes/default.py new file mode 100644 index 0000000000000000000000000000000000000000..4efde5bd6f9334e3814743c35cb3bceb019bbea0 --- /dev/null +++ b/themes/default.py @@ -0,0 +1,86 @@ +import gradio as gr +from toolbox import get_conf +CODE_HIGHLIGHT, ADD_WAIFU, LAYOUT = get_conf('CODE_HIGHLIGHT', 'ADD_WAIFU', 'LAYOUT') + +def adjust_theme(): + + try: + color_er = gr.themes.utils.colors.fuchsia + set_theme = gr.themes.Default( + primary_hue=gr.themes.utils.colors.orange, + neutral_hue=gr.themes.utils.colors.gray, + font=["sans-serif", "Microsoft YaHei", "ui-sans-serif", "system-ui"], + font_mono=["ui-monospace", "Consolas", "monospace"]) + set_theme.set( + # Colors + input_background_fill_dark="*neutral_800", + # Transition + button_transition="none", + # Shadows + button_shadow="*shadow_drop", + button_shadow_hover="*shadow_drop_lg", + button_shadow_active="*shadow_inset", + input_shadow="0 0 0 *shadow_spread transparent, *shadow_inset", + input_shadow_focus="0 0 0 *shadow_spread *secondary_50, *shadow_inset", + input_shadow_focus_dark="0 0 0 *shadow_spread *neutral_700, *shadow_inset", + checkbox_label_shadow="*shadow_drop", + block_shadow="*shadow_drop", + form_gap_width="1px", + # Button borders + input_border_width="1px", + input_background_fill="white", + # Gradients + stat_background_fill="linear-gradient(to right, *primary_400, *primary_200)", + stat_background_fill_dark="linear-gradient(to right, *primary_400, *primary_600)", + error_background_fill=f"linear-gradient(to right, {color_er.c100}, *background_fill_secondary)", + error_background_fill_dark="*background_fill_primary", + checkbox_label_background_fill="linear-gradient(to top, *neutral_50, white)", + checkbox_label_background_fill_dark="linear-gradient(to top, *neutral_900, *neutral_800)", + checkbox_label_background_fill_hover="linear-gradient(to top, *neutral_100, white)", + checkbox_label_background_fill_hover_dark="linear-gradient(to top, *neutral_900, *neutral_800)", + button_primary_background_fill="linear-gradient(to bottom right, *primary_100, *primary_300)", + button_primary_background_fill_dark="linear-gradient(to bottom right, *primary_500, *primary_600)", + button_primary_background_fill_hover="linear-gradient(to bottom right, *primary_100, *primary_200)", + button_primary_background_fill_hover_dark="linear-gradient(to bottom right, *primary_500, *primary_500)", + button_primary_border_color_dark="*primary_500", + button_secondary_background_fill="linear-gradient(to bottom right, *neutral_100, *neutral_200)", + button_secondary_background_fill_dark="linear-gradient(to bottom right, *neutral_600, *neutral_700)", + button_secondary_background_fill_hover="linear-gradient(to bottom right, *neutral_100, *neutral_100)", + button_secondary_background_fill_hover_dark="linear-gradient(to bottom right, *neutral_600, *neutral_600)", + button_cancel_background_fill=f"linear-gradient(to bottom right, {color_er.c100}, {color_er.c200})", + button_cancel_background_fill_dark=f"linear-gradient(to bottom right, {color_er.c600}, {color_er.c700})", + button_cancel_background_fill_hover=f"linear-gradient(to bottom right, {color_er.c100}, {color_er.c100})", + button_cancel_background_fill_hover_dark=f"linear-gradient(to bottom right, {color_er.c600}, {color_er.c600})", + button_cancel_border_color=color_er.c200, + button_cancel_border_color_dark=color_er.c600, + button_cancel_text_color=color_er.c600, + button_cancel_text_color_dark="white", + ) + + if LAYOUT=="TOP-DOWN": + js = "" + else: + with open('themes/common.js', 'r', encoding='utf8') as f: + js = f"" + + # 添加一个萌萌的看板娘 + if ADD_WAIFU: + js += """ + + + + """ + gradio_original_template_fn = gr.routes.templates.TemplateResponse + def gradio_new_template_fn(*args, **kwargs): + res = gradio_original_template_fn(*args, **kwargs) + res.body = res.body.replace(b'', f'{js}'.encode("utf8")) + res.init_headers() + return res + gr.routes.templates.TemplateResponse = gradio_new_template_fn # override gradio template + except: + set_theme = None + print('gradio版本较旧, 不能自定义字体和颜色') + return set_theme + +with open("themes/default.css", "r", encoding="utf-8") as f: + advanced_css = f.read() \ No newline at end of file diff --git a/themes/green.css b/themes/green.css new file mode 100644 index 0000000000000000000000000000000000000000..950ac2e1feda07424a164c6b52facb6d740a2884 --- /dev/null +++ b/themes/green.css @@ -0,0 +1,827 @@ +:root { + --chatbot-color-light: #000000; + --chatbot-color-dark: #FFFFFF; + --chatbot-background-color-light: #F3F3F3; + --chatbot-background-color-dark: #121111; + --message-user-background-color-light: #95EC69; + --message-user-background-color-dark: #26B561; + --message-bot-background-color-light: #FFFFFF; + --message-bot-background-color-dark: #2C2C2C; +} +mspace { + display: block; +} +@media only screen and (max-width: 767px) { + #column_1 { + display: none !important; + } +} +@keyframes highlight { + 0%, 100% { + border: 2px solid transparent; + } + 50% { + border-color: yellow; + } +} + +#highlight_update { + animation-name: highlight; + animation-duration: 0.75s; + animation-iteration-count: 3; +} + +.table-wrap.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno { + border: 0px solid var(--border-color-primary) !important; +} + +#examples_col { + z-index: 2; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + margin-bottom: 30% !important; +} +#hide_examples { + z-index: 0; +} + +#debug_mes { + position: absolute; + display: flex; + bottom: 0; + left: 0; + z-index: 1; /* 设置更高的 z-index 值 */ + margin-bottom: -4px !important; + align-self: flex-end; +} +#chat_box { + display: flex; + flex-direction: column; + overflow-y: visible !important; + z-index: 3; + flex-grow: 1; /* 自动填充剩余空间 */ + position: absolute; + bottom: 0; + left: 0; + width: 100%; + margin-bottom: 30px !important; + border: 1px solid var(--border-color-primary); +} +.toast-body { + z-index: 5 !important; +} +.chat_input { + +} +.sm_btn { + position: relative; + bottom: 5px; + height: 10%; + border-radius: 20px!important; + min-width: min(10%,100%) !important; + overflow: hidden; +} +.sm_select { + position: relative !important; + z-index: 5 !important; + bottom: 5px; + min-width: min(20%,100%) !important; + border-radius: 20px!important; +} +.sm_checkbox { + position: relative !important; + z-index: 5 !important; + bottom: 5px; + padding: 0 !important; +} +.sm_select .wrap-inner.svelte-aqlk7e.svelte-aqlk7e.svelte-aqlk7e { + padding: 0 !important; +} +.sm_select .block.svelte-mppz8v { + width: 10% !important; +} + +button.sm { + padding: 6px 8px !important; +} + +/* usage_display */ +.insert_block { + position: relative; + bottom: 2px; + min-width: min(55px,100%) !important; +} + +.submit_btn { + flex-direction: column-reverse; + overflow-y: auto !important; + position: absolute; + bottom: 0; + right: 10px; + margin-bottom: 10px !important; + min-width: min(50px,100%) !important; +} + +textarea { + resize: none; + height: 100%; /* 填充父元素的高度 */ +} +/* #main_chatbot { + height: 75vh !important; + max-height: 75vh !important; + overflow: auto !important; + z-index: 2; + transform: translateZ(0) !important; + backface-visibility: hidden !important; + will-change: transform !important; +} */ +#prompt_result{ + height: 60vh !important; + max-height: 60vh !important; +} + +#app_title { + font-weight: var(--prose-header-text-weight); + font-size: var(--text-xxl); + line-height: 1.3; + text-align: left; + margin-top: 6px; + white-space: nowrap; +} +#description { + text-align: center; + margin: 32px 0 4px 0; +} + +/* gradio的页脚信息 */ +footer { + /* display: none !important; */ + margin-top: .2em !important; + font-size: 85%; +} +#footer { + text-align: center; +} +#footer div { + display: inline-block; +} +#footer .versions{ + font-size: 85%; + opacity: 0.60; +} +/* user_info */ + +#float_display { + position: absolute; + max-height: 30px; +} +/* user_info */ +#user_info { + white-space: nowrap; + position: absolute; left: 8em; top: .2em; + z-index: var(--layer-2); + box-shadow: var(--block-shadow); + border: none; border-radius: var(--block-label-radius); + background: var(--color-accent); + padding: var(--block-label-padding); + font-size: var(--block-label-text-size); line-height: var(--line-sm); + width: auto; min-height: 30px !important; + opacity: 1; + transition: opacity 0.3s ease-in-out; +} +textarea.svelte-1pie7s6 { + background: #e7e6e6 !important; + width: 96% !important; +} + +.dark textarea.svelte-1pie7s6 { + background: var(--input-background-fill) !important; + width: 96% !important; +} + +.dark input[type=number].svelte-1cl284s { + background: #393939 !important; + border: var(--input-border-width) solid var(--input-border-color) !important; +} +/* .dark input[type="range"] { + background: #393939 !important; +} */ +#user_info .wrap { + opacity: 0; +} +#user_info p { + color: white; + font-weight: var(--block-label-text-weight); +} +#user_info.hideK { + opacity: 0; + transition: opacity 1s ease-in-out; +} +[class *= "message"] { + gap: 7px !important; + border-radius: var(--radius-xl) !important +} +/* debug_mes */ +#debug_mes { + min-height: 2em; + align-items: flex-end; + justify-content: flex-end; +} +#debug_mes p { + font-size: .85em; + font-family: ui-monospace, "SF Mono", "SFMono-Regular", "Menlo", "Consolas", "Liberation Mono", "Microsoft Yahei UI", "Microsoft Yahei", monospace; + /* Windows下中文的monospace会fallback为新宋体,实在太丑,这里折中使用微软雅黑 */ + color: #000000; +} +.dark #debug_mes p { + color: #ee65ed; +} + +#debug_mes { + transition: all 0.6s; +} +#gpt-chatbot { + transition: height 0.3s ease; +} + +/* .wrap.svelte-18telvq.svelte-18telvq { + padding: var(--block-padding) !important; + height: 100% !important; + max-height: 95% !important; + overflow-y: auto !important; +}*/ +.app.svelte-1mya07g.svelte-1mya07g { + max-width: 100%; + position: relative; + padding: var(--size-4); + width: 100%; + height: 100%; +} + +.gradio-container-3-32-2 h1 { + font-weight: 700 !important; + font-size: 28px !important; +} + + +.gradio-container-3-32-2 h2 { + font-weight: 600 !important; + font-size: 24px !important; +} +.gradio-container-3-32-2 h3 { + font-weight: 500 !important; + font-size: 20px !important; +} +.gradio-container-3-32-2 h4 { + font-weight: 400 !important; + font-size: 16px !important; +} +.gradio-container-3-32-2 h5 { + font-weight: 300 !important; + font-size: 14px !important; +} +.gradio-container-3-32-2 h6 { + font-weight: 200 !important; + font-size: 12px !important; +} + + +#usage_display p, #usage_display span { + margin: 0; + font-size: .85em; + color: var(--body-text-color-subdued); +} +.progress-bar { + background-color: var(--input-background-fill);; + margin: .5em 0 !important; + height: 20px; + border-radius: 10px; + overflow: hidden; +} +.progress { + background-color: var(--block-title-background-fill); + height: 100%; + border-radius: 10px; + text-align: right; + transition: width 0.5s ease-in-out; +} +.progress-text { + /* color: white; */ + color: var(--color-accent) !important; + font-size: 1em !important; + font-weight: bold; + padding-right: 10px; + line-height: 20px; +} + +.apSwitch { + top: 2px; + display: inline-block; + height: 24px; + position: relative; + width: 48px; + border-radius: 12px; +} +.apSwitch input { + display: none !important; +} +.apSlider { + background-color: var(--neutral-200); + bottom: 0; + cursor: pointer; + left: 0; + position: absolute; + right: 0; + top: 0; + transition: .4s; + font-size: 18px; + border-radius: 7px; +} +.apSlider::before { + bottom: -1.5px; + left: 1px; + position: absolute; + transition: .4s; + content: "🌞"; +} +hr.append-display { + margin: 8px 0; + border: none; + height: 1px; + border-top-width: 0; + background-image: linear-gradient(to right, rgba(50,50,50, 0.1), rgba(150, 150, 150, 0.8), rgba(50,50,50, 0.1)); +} +.source-a { + font-size: 0.8em; + max-width: 100%; + margin: 0; + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + /* background-color: #dddddd88; */ + border-radius: 1.5rem; + padding: 0.2em; +} +.source-a a { + display: inline-block; + background-color: #aaaaaa50; + border-radius: 1rem; + padding: 0.5em; + text-align: center; + text-overflow: ellipsis; + overflow: hidden; + min-width: 20%; + white-space: nowrap; + margin: 0.2rem 0.1rem; + text-decoration: none !important; + flex: 1; + transition: flex 0.5s; +} +.source-a a:hover { + background-color: #aaaaaa20; + flex: 2; +} +input:checked + .apSlider { + background-color: var(--primary-600); +} +input:checked + .apSlider::before { + transform: translateX(23px); + content:"🌚"; +} + +/* Override Slider Styles (for webkit browsers like Safari and Chrome) + * 好希望这份提案能早日实现 https://github.com/w3c/csswg-drafts/issues/4410 + * 进度滑块在各个平台还是太不统一了 + */ +input[type="range"] { + -webkit-appearance: none; + height: 4px; + background: var(--input-background-fill); + border-radius: 5px; + background-image: linear-gradient(var(--primary-500),var(--primary-500)); + background-size: 0% 100%; + background-repeat: no-repeat; +} +input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 50%; + border: solid 0.5px #ddd; + background-color: white; + cursor: ew-resize; + box-shadow: var(--input-shadow); + transition: background-color .1s ease; +} +input[type="range"]::-webkit-slider-thumb:hover { + background: var(--neutral-50); +} +input[type="range"]::-webkit-slider-runnable-track { + -webkit-appearance: none; + box-shadow: none; + border: none; + background: transparent; +} + +.submit_btn, #cancel_btn { + height: 42px !important; +} +.submit_btn::before { + content: url("data:image/svg+xml, %3Csvg width='21px' height='20px' viewBox='0 0 21 20' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E %3Cg id='page' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E %3Cg id='send' transform='translate(0.435849, 0.088463)' fill='%23FFFFFF' fill-rule='nonzero'%3E %3Cpath d='M0.579148261,0.0428666046 C0.301105539,-0.0961547561 -0.036517765,0.122307382 0.0032026237,0.420210298 L1.4927172,18.1553639 C1.5125774,18.4334066 1.79062012,18.5922882 2.04880264,18.4929872 L8.24518329,15.8913017 L11.6412765,19.7441794 C11.8597387,19.9825018 12.2370824,19.8832008 12.3165231,19.5852979 L13.9450591,13.4882182 L19.7839562,11.0255541 C20.0619989,10.8865327 20.0818591,10.4694687 19.7839562,10.3105871 L0.579148261,0.0428666046 Z M11.6138902,17.0883151 L9.85385903,14.7195502 L0.718169621,0.618812241 L12.69945,12.9346347 L11.6138902,17.0883151 Z' id='shape'%3E%3C/path%3E %3C/g%3E %3C/g%3E %3C/svg%3E"); + height: 21px; +} + +#cancel_btn::before { + content: url("data:image/svg+xml,%3Csvg width='21px' height='21px' viewBox='0 0 21 21' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E %3Cg id='pg' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E %3Cpath d='M10.2072007,20.088463 C11.5727865,20.088463 12.8594566,19.8259823 14.067211,19.3010209 C15.2749653,18.7760595 16.3386126,18.0538087 17.2581528,17.1342685 C18.177693,16.2147282 18.8982283,15.1527965 19.4197586,13.9484733 C19.9412889,12.7441501 20.202054,11.4557644 20.202054,10.0833163 C20.202054,8.71773046 19.9395733,7.43106036 19.4146119,6.22330603 C18.8896505,5.01555169 18.1673997,3.95018885 17.2478595,3.0272175 C16.3283192,2.10424615 15.2646719,1.3837109 14.0569176,0.865611739 C12.8491633,0.34751258 11.5624932,0.088463 10.1969073,0.088463 C8.83132146,0.088463 7.54636692,0.34751258 6.34204371,0.865611739 C5.1377205,1.3837109 4.07407321,2.10424615 3.15110186,3.0272175 C2.22813051,3.95018885 1.5058797,5.01555169 0.984349419,6.22330603 C0.46281914,7.43106036 0.202054,8.71773046 0.202054,10.0833163 C0.202054,11.4557644 0.4645347,12.7441501 0.9894961,13.9484733 C1.5144575,15.1527965 2.23670831,16.2147282 3.15624854,17.1342685 C4.07578877,18.0538087 5.1377205,18.7760595 6.34204371,19.3010209 C7.54636692,19.8259823 8.83475258,20.088463 10.2072007,20.088463 Z M10.2072007,18.2562448 C9.07493099,18.2562448 8.01471483,18.0452309 7.0265522,17.6232031 C6.03838956,17.2011753 5.17031614,16.6161693 4.42233192,15.8681851 C3.6743477,15.1202009 3.09105726,14.2521274 2.67246059,13.2639648 C2.25386392,12.2758022 2.04456558,11.215586 2.04456558,10.0833163 C2.04456558,8.95104663 2.25386392,7.89083047 2.67246059,6.90266784 C3.09105726,5.9145052 3.6743477,5.04643178 4.42233192,4.29844756 C5.17031614,3.55046334 6.036674,2.9671729 7.02140552,2.54857623 C8.00613703,2.12997956 9.06463763,1.92068122 10.1969073,1.92068122 C11.329177,1.92068122 12.3911087,2.12997956 13.3827025,2.54857623 C14.3742962,2.9671729 15.2440852,3.55046334 15.9920694,4.29844756 C16.7400537,5.04643178 17.3233441,5.9145052 17.7419408,6.90266784 C18.1605374,7.89083047 18.3698358,8.95104663 18.3698358,10.0833163 C18.3698358,11.215586 18.1605374,12.2758022 17.7419408,13.2639648 C17.3233441,14.2521274 16.7400537,15.1202009 15.9920694,15.8681851 C15.2440852,16.6161693 14.3760118,17.2011753 13.3878492,17.6232031 C12.3996865,18.0452309 11.3394704,18.2562448 10.2072007,18.2562448 Z M7.65444721,13.6242324 L12.7496608,13.6242324 C13.0584616,13.6242324 13.3003556,13.5384544 13.4753427,13.3668984 C13.6503299,13.1953424 13.7378234,12.9585951 13.7378234,12.6566565 L13.7378234,7.49968276 C13.7378234,7.19774418 13.6503299,6.96099688 13.4753427,6.78944087 C13.3003556,6.61788486 13.0584616,6.53210685 12.7496608,6.53210685 L7.65444721,6.53210685 C7.33878414,6.53210685 7.09345904,6.61788486 6.91847191,6.78944087 C6.74348478,6.96099688 6.65599121,7.19774418 6.65599121,7.49968276 L6.65599121,12.6566565 C6.65599121,12.9585951 6.74348478,13.1953424 6.91847191,13.3668984 C7.09345904,13.5384544 7.33878414,13.6242324 7.65444721,13.6242324 Z' id='shape' fill='%23FF3B30' fill-rule='nonzero'%3E%3C/path%3E %3C/g%3E %3C/svg%3E"); + height: 21px; +} +/* list */ +ol:not(.options), ul:not(.options) { + padding-inline-start: 2em !important; +} + +/* 亮色(默认) */ +#gpt-chatbot { + background-color: var(--chatbot-background-color-light) !important; + color: var(--chatbot-color-light) !important; + box-shadow: 0 0 12px 4px rgba(0, 0, 0, 0.06); +} +/* 暗色 */ +.dark #gpt-chatbot { + background-color: var(--block-background-fill) !important; + color: var(--chatbot-color-dark) !important; + box-shadow: 0 0 12px 4px rgba(0, 0, 0, 0.2); +} + +#gpt-panel > div { + box-shadow: 0 0 12px 4px rgba(0, 0, 0, 0.06); +} +.dark #gpt-panel > div { + box-shadow: 0 0 12px 4px rgba(0, 0, 0, 0.2); +} + +/* 屏幕宽度大于等于500px的设备 */ +/* update on 2023.4.8: 高度的细致调整已写入JavaScript */ +/* @media screen and (min-width: 500px) { + #main_chatbot { + height: calc(100vh - 200px); + } + #main_chatbot .wrap { + max-height: calc(100vh - 200px - var(--line-sm)*1rem - 2*var(--block-label-margin) ); + } +} */ +/* 屏幕宽度小于500px的设备 */ +/* @media screen and (max-width: 499px) { + #main_chatbot { + height: calc(100vh - 140px); + } + #main_chatbot .wrap { + max-height: calc(100vh - 140px - var(--line-sm)*1rem - 2*var(--block-label-margin) ); + } + [data-testid = "bot"] { + max-width: 95% !important; + } + #app_title h1{ + letter-spacing: -1px; font-size: 22px; + } +} */ +#gpt-chatbot .wrap { + overflow-x: hidden +} +/* 对话气泡 */ +.message { + border-radius: var(--radius-xl) !important; + border: none; + padding: var(--spacing-xl) !important; + font-size: 15px !important; + line-height: var(--line-md) !important; + min-height: calc(var(--text-md)*var(--line-md) + 2*var(--spacing-xl)); + min-width: calc(var(--text-md)*var(--line-md) + 2*var(--spacing-xl)); +} +[data-testid = "bot"] { + max-width: 85%; + border-bottom-left-radius: 0 !important; + background-color: var(--message-bot-background-color-light) !important; +} +[data-testid = "user"] { + max-width: 85%; + width: auto !important; + border-bottom-right-radius: 0 !important; + background-color: var(--message-user-background-color-light) !important; +} +.dark [data-testid = "bot"] { + background-color: var(--message-bot-background-color-dark) !important; +} +.dark [data-testid = "user"] { + background-color: var(--message-user-background-color-dark) !important; +} + +.message p { + margin-top: 0.6em !important; + margin-bottom: 0.6em !important; +} +.message p:first-child { margin-top: 0 !important; } +.message p:last-of-type { margin-bottom: 0 !important; } + +.message .md-message { + display: block; + padding: 0 !important; +} +.message .raw-message { + display: block; + padding: 0 !important; + white-space: pre-wrap; +} +.raw-message.hideM, .md-message.hideM { + display: none; +} + +/* custom buttons */ +.chuanhu-btn { + border-radius: 5px; + /* background-color: #E6E6E6 !important; */ + color: rgba(120, 120, 120, 0.64) !important; + padding: 4px !important; + position: absolute; + right: -22px; + cursor: pointer !important; + transition: color .2s ease, background-color .2s ease; +} +.chuanhu-btn:hover { + background-color: rgba(167, 167, 167, 0.25) !important; + color: unset !important; +} +.chuanhu-btn:active { + background-color: rgba(167, 167, 167, 0.5) !important; +} +.chuanhu-btn:focus { + outline: none; +} +.copy-bot-btn { + /* top: 18px; */ + bottom: 0; +} +.toggle-md-btn { + /* top: 0; */ + bottom: 20px; +} +.copy-code-btn { + position: relative; + float: right; + font-size: 1em; + cursor: pointer; +} + +.message-wrap>div img{ + border-radius: 10px !important; +} + +/* history message */ +.wrap>.history-message { + padding: 10px !important; +} +.history-message { + /* padding: 0 !important; */ + opacity: 80%; + display: flex; + flex-direction: column; +} +.history-message>.history-message { + padding: 0 !important; +} +.history-message>.message-wrap { + padding: 0 !important; + margin-bottom: 16px; +} +.history-message>.message { + margin-bottom: 16px; +} +.wrap>.history-message::after { + content: ""; + display: block; + height: 2px; + background-color: var(--body-text-color-subdued); + margin-bottom: 10px; + margin-top: -10px; + clear: both; +} +.wrap>.history-message>:last-child::after { + content: "仅供查看"; + display: block; + text-align: center; + color: var(--body-text-color-subdued); + font-size: 0.8em; +} + +/* 表格 */ +table { + margin: 1em 0; + border-collapse: collapse; + empty-cells: show; +} +td,th { + border: 1.2px solid var(--border-color-primary) !important; + padding: 0.2em; +} +thead { + background-color: rgba(175,184,193,0.2); +} +thead th { + padding: .5em .2em; +} +/* 行内代码 */ +.message :not(pre) code { + display: inline; + white-space: break-spaces; + border-radius: 6px; + margin: 0 2px 0 2px; + padding: .2em .4em .1em .4em; + background-color: rgba(175,184,193,0.2); +} +/* 代码块 */ +.message pre code { + display: block; + overflow: auto; + white-space: pre; + background-color: hsla(0, 0%, 7%, 70%)!important; + border-radius: 10px; + padding: 1.2em 1em 0em .5em; + margin: 0.6em 2em 1em 0.2em; + color: #FFF; + box-shadow: 6px 6px 16px hsla(0, 0%, 0%, 0.2); +} +.dark .message pre code { + background-color: hsla(0, 0%, 20%, 300%)!important; +} +.message pre { + padding: 0 !important; +} +.message pre code div.highlight { + background-color: unset !important; +} + +button.copy-button { + display: none; +} + +/* 代码高亮样式 */ +.codehilite .hll { background-color: #6e7681 } +.codehilite .c { color: #8b949e; font-style: italic } /* Comment */ +.codehilite .err { color: #f85149 } /* Error */ +.codehilite .esc { color: #c9d1d9 } /* Escape */ +.codehilite .g { color: #c9d1d9 } /* Generic */ +.codehilite .k { color: #ff7b72 } /* Keyword */ +.codehilite .l { color: #a5d6ff } /* Literal */ +.codehilite .n { color: #c9d1d9 } /* Name */ +.codehilite .o { color: #ff7b72; font-weight: bold } /* Operator */ +.codehilite .x { color: #c9d1d9 } /* Other */ +.codehilite .p { color: #c9d1d9 } /* Punctuation */ +.codehilite .ch { color: #8b949e; font-style: italic } /* Comment.Hashbang */ +.codehilite .cm { color: #8b949e; font-style: italic } /* Comment.Multiline */ +.codehilite .cp { color: #8b949e; font-weight: bold; font-style: italic } /* Comment.Preproc */ +.codehilite .cpf { color: #8b949e; font-style: italic } /* Comment.PreprocFile */ +.codehilite .c1 { color: #8b949e; font-style: italic } /* Comment.Single */ +.codehilite .cs { color: #8b949e; font-weight: bold; font-style: italic } /* Comment.Special */ +.codehilite .gd { color: #ffa198; background-color: #490202 } /* Generic.Deleted */ +.codehilite .ge { color: #c9d1d9; font-style: italic } /* Generic.Emph */ +.codehilite .gr { color: #ffa198 } /* Generic.Error */ +.codehilite .gh { color: #79c0ff; font-weight: bold } /* Generic.Heading */ +.codehilite .gi { color: #56d364; background-color: #0f5323 } /* Generic.Inserted */ +.codehilite .go { color: #8b949e } /* Generic.Output */ +.codehilite .gp { color: #8b949e } /* Generic.Prompt */ +.codehilite .gs { color: #c9d1d9; font-weight: bold } /* Generic.Strong */ +.codehilite .gu { color: #79c0ff } /* Generic.Subheading */ +.codehilite .gt { color: #ff7b72 } /* Generic.Traceback */ +.codehilite .g-Underline { color: #c9d1d9; text-decoration: underline } /* Generic.Underline */ +.codehilite .kc { color: #79c0ff } /* Keyword.Constant */ +.codehilite .kd { color: #ff7b72 } /* Keyword.Declaration */ +.codehilite .kn { color: #ff7b72 } /* Keyword.Namespace */ +.codehilite .kp { color: #79c0ff } /* Keyword.Pseudo */ +.codehilite .kr { color: #ff7b72 } /* Keyword.Reserved */ +.codehilite .kt { color: #ff7b72 } /* Keyword.Type */ +.codehilite .ld { color: #79c0ff } /* Literal.Date */ +.codehilite .m { color: #a5d6ff } /* Literal.Number */ +.codehilite .s { color: #a5d6ff } /* Literal.String */ +.codehilite .na { color: #c9d1d9 } /* Name.Attribute */ +.codehilite .nb { color: #c9d1d9 } /* Name.Builtin */ +.codehilite .nc { color: #f0883e; font-weight: bold } /* Name.Class */ +.codehilite .no { color: #79c0ff; font-weight: bold } /* Name.Constant */ +.codehilite .nd { color: #d2a8ff; font-weight: bold } /* Name.Decorator */ +.codehilite .ni { color: #ffa657 } /* Name.Entity */ +.codehilite .ne { color: #f0883e; font-weight: bold } /* Name.Exception */ +.codehilite .nf { color: #d2a8ff; font-weight: bold } /* Name.Function */ +.codehilite .nl { color: #79c0ff; font-weight: bold } /* Name.Label */ +.codehilite .nn { color: #ff7b72 } /* Name.Namespace */ +.codehilite .nx { color: #c9d1d9 } /* Name.Other */ +.codehilite .py { color: #79c0ff } /* Name.Property */ +.codehilite .nt { color: #7ee787 } /* Name.Tag */ +.codehilite .nv { color: #79c0ff } /* Name.Variable */ +.codehilite .ow { color: #ff7b72; font-weight: bold } /* Operator.Word */ +.codehilite .pm { color: #c9d1d9 } /* Punctuation.Marker */ +.codehilite .w { color: #6e7681 } /* Text.Whitespace */ +.codehilite .mb { color: #a5d6ff } /* Literal.Number.Bin */ +.codehilite .mf { color: #a5d6ff } /* Literal.Number.Float */ +.codehilite .mh { color: #a5d6ff } /* Literal.Number.Hex */ +.codehilite .mi { color: #a5d6ff } /* Literal.Number.Integer */ +.codehilite .mo { color: #a5d6ff } /* Literal.Number.Oct */ +.codehilite .sa { color: #79c0ff } /* Literal.String.Affix */ +.codehilite .sb { color: #a5d6ff } /* Literal.String.Backtick */ +.codehilite .sc { color: #a5d6ff } /* Literal.String.Char */ +.codehilite .dl { color: #79c0ff } /* Literal.String.Delimiter */ +.codehilite .sd { color: #a5d6ff } /* Literal.String.Doc */ +.codehilite .s2 { color: #a5d6ff } /* Literal.String.Double */ +.codehilite .se { color: #79c0ff } /* Literal.String.Escape */ +.codehilite .sh { color: #79c0ff } /* Literal.String.Heredoc */ +.codehilite .si { color: #a5d6ff } /* Literal.String.Interpol */ +.codehilite .sx { color: #a5d6ff } /* Literal.String.Other */ +.codehilite .sr { color: #79c0ff } /* Literal.String.Regex */ +.codehilite .s1 { color: #a5d6ff } /* Literal.String.Single */ +.codehilite .ss { color: #a5d6ff } /* Literal.String.Symbol */ +.codehilite .bp { color: #c9d1d9 } /* Name.Builtin.Pseudo */ +.codehilite .fm { color: #d2a8ff; font-weight: bold } /* Name.Function.Magic */ +.codehilite .vc { color: #79c0ff } /* Name.Variable.Class */ +.codehilite .vg { color: #79c0ff } /* Name.Variable.Global */ +.codehilite .vi { color: #79c0ff } /* Name.Variable.Instance */ +.codehilite .vm { color: #79c0ff } /* Name.Variable.Magic */ +.codehilite .il { color: #a5d6ff } /* Literal.Number.Integer.Long */ + +.dark .codehilite .hll { background-color: #2C3B41 } +.dark .codehilite .c { color: #79d618; font-style: italic } /* Comment */ +.dark .codehilite .err { color: #FF5370 } /* Error */ +.dark .codehilite .esc { color: #89DDFF } /* Escape */ +.dark .codehilite .g { color: #EEFFFF } /* Generic */ +.dark .codehilite .k { color: #BB80B3 } /* Keyword */ +.dark .codehilite .l { color: #C3E88D } /* Literal */ +.dark .codehilite .n { color: #EEFFFF } /* Name */ +.dark .codehilite .o { color: #89DDFF } /* Operator */ +.dark .codehilite .p { color: #89DDFF } /* Punctuation */ +.dark .codehilite .ch { color: #79d618; font-style: italic } /* Comment.Hashbang */ +.dark .codehilite .cm { color: #79d618; font-style: italic } /* Comment.Multiline */ +.dark .codehilite .cp { color: #79d618; font-style: italic } /* Comment.Preproc */ +.dark .codehilite .cpf { color: #79d618; font-style: italic } /* Comment.PreprocFile */ +.dark .codehilite .c1 { color: #79d618; font-style: italic } /* Comment.Single */ +.dark .codehilite .cs { color: #79d618; font-style: italic } /* Comment.Special */ +.dark .codehilite .gd { color: #FF5370 } /* Generic.Deleted */ +.dark .codehilite .ge { color: #89DDFF } /* Generic.Emph */ +.dark .codehilite .gr { color: #FF5370 } /* Generic.Error */ +.dark .codehilite .gh { color: #C3E88D } /* Generic.Heading */ +.dark .codehilite .gi { color: #C3E88D } /* Generic.Inserted */ +.dark .codehilite .go { color: #79d618 } /* Generic.Output */ +.dark .codehilite .gp { color: #FFCB6B } /* Generic.Prompt */ +.dark .codehilite .gs { color: #FF5370 } /* Generic.Strong */ +.dark .codehilite .gu { color: #89DDFF } /* Generic.Subheading */ +.dark .codehilite .gt { color: #FF5370 } /* Generic.Traceback */ +.dark .codehilite .kc { color: #89DDFF } /* Keyword.Constant */ +.dark .codehilite .kd { color: #BB80B3 } /* Keyword.Declaration */ +.dark .codehilite .kn { color: #89DDFF; font-style: italic } /* Keyword.Namespace */ +.dark .codehilite .kp { color: #89DDFF } /* Keyword.Pseudo */ +.dark .codehilite .kr { color: #BB80B3 } /* Keyword.Reserved */ +.dark .codehilite .kt { color: #BB80B3 } /* Keyword.Type */ +.dark .codehilite .ld { color: #C3E88D } /* Literal.Date */ +.dark .codehilite .m { color: #F78C6C } /* Literal.Number */ +.dark .codehilite .s { color: #C3E88D } /* Literal.String */ +.dark .codehilite .na { color: #BB80B3 } /* Name.Attribute */ +.dark .codehilite .nb { color: #82AAFF } /* Name.Builtin */ +.dark .codehilite .nc { color: #FFCB6B } /* Name.Class */ +.dark .codehilite .no { color: #EEFFFF } /* Name.Constant */ +.dark .codehilite .nd { color: #82AAFF } /* Name.Decorator */ +.dark .codehilite .ni { color: #89DDFF } /* Name.Entity */ +.dark .codehilite .ne { color: #FFCB6B } /* Name.Exception */ +.dark .codehilite .nf { color: #82AAFF } /* Name.Function */ +.dark .codehilite .nl { color: #82AAFF } /* Name.Label */ +.dark .codehilite .nn { color: #FFCB6B } /* Name.Namespace */ +.dark .codehilite .nx { color: #EEFFFF } /* Name.Other */ +.dark .codehilite .py { color: #FFCB6B } /* Name.Property */ +.dark .codehilite .nt { color: #FF5370 } /* Name.Tag */ +.dark .codehilite .nv { color: #89DDFF } /* Name.Variable */ +.dark .codehilite .ow { color: #89DDFF; font-style: italic } /* Operator.Word */ +.dark .codehilite .pm { color: #89DDFF } /* Punctuation.Marker */ +.dark .codehilite .w { color: #EEFFFF } /* Text.Whitespace */ +.dark .codehilite .mb { color: #F78C6C } /* Literal.Number.Bin */ +.dark .codehilite .mf { color: #F78C6C } /* Literal.Number.Float */ +.dark .codehilite .mh { color: #F78C6C } /* Literal.Number.Hex */ +.dark .codehilite .mi { color: #F78C6C } /* Literal.Number.Integer */ +.dark .codehilite .mo { color: #F78C6C } /* Literal.Number.Oct */ +.dark .codehilite .sa { color: #BB80B3 } /* Literal.String.Affix */ +.dark .codehilite .sb { color: #C3E88D } /* Literal.String.Backtick */ +.dark .codehilite .sc { color: #C3E88D } /* Literal.String.Char */ +.dark .codehilite .dl { color: #EEFFFF } /* Literal.String.Delimiter */ +.dark .codehilite .sd { color: #79d618; font-style: italic } /* Literal.String.Doc */ +.dark .codehilite .s2 { color: #C3E88D } /* Literal.String.Double */ +.dark .codehilite .se { color: #EEFFFF } /* Literal.String.Escape */ +.dark .codehilite .sh { color: #C3E88D } /* Literal.String.Heredoc */ +.dark .codehilite .si { color: #89DDFF } /* Literal.String.Interpol */ +.dark .codehilite .sx { color: #C3E88D } /* Literal.String.Other */ +.dark .codehilite .sr { color: #89DDFF } /* Literal.String.Regex */ +.dark .codehilite .s1 { color: #C3E88D } /* Literal.String.Single */ +.dark .codehilite .ss { color: #89DDFF } /* Literal.String.Symbol */ +.dark .codehilite .bp { color: #89DDFF } /* Name.Builtin.Pseudo */ +.dark .codehilite .fm { color: #82AAFF } /* Name.Function.Magic */ +.dark .codehilite .vc { color: #89DDFF } /* Name.Variable.Class */ +.dark .codehilite .vg { color: #89DDFF } /* Name.Variable.Global */ +.dark .codehilite .vi { color: #89DDFF } /* Name.Variable.Instance */ +.dark .codehilite .vm { color: #82AAFF } /* Name.Variable.Magic */ +.dark .codehilite .il { color: #F78C6C } /* Literal.Number.Integer.Long */ diff --git a/themes/green.js b/themes/green.js new file mode 100644 index 0000000000000000000000000000000000000000..65948c0344e85c098a7f96e176fa8388575ca07a --- /dev/null +++ b/themes/green.js @@ -0,0 +1,41 @@ + +var academic_chat = null; + +var sliders = null; +var rangeInputs = null; +var numberInputs = null; + +function set_elements() { + academic_chat = document.querySelector('gradio-app'); + async function get_sliders() { + sliders = document.querySelectorAll('input[type="range"]'); + while (sliders.length == 0) { + await new Promise(r => setTimeout(r, 100)); + sliders = document.querySelectorAll('input[type="range"]'); + } + setSlider(); + } + get_sliders(); +} + +function setSlider() { + rangeInputs = document.querySelectorAll('input[type="range"]'); + numberInputs = document.querySelectorAll('input[type="number"]') + function setSliderRange() { + var range = document.querySelectorAll('input[type="range"]'); + range.forEach(range => { + range.style.backgroundSize = (range.value - range.min) / (range.max - range.min) * 100 + '% 100%'; + }); + } + setSliderRange(); + rangeInputs.forEach(rangeInput => { + rangeInput.addEventListener('input', setSliderRange); + }); + numberInputs.forEach(numberInput => { + numberInput.addEventListener('input', setSliderRange); + }) +} + +window.addEventListener("DOMContentLoaded", () => { + set_elements(); +}); \ No newline at end of file diff --git a/themes/green.py b/themes/green.py new file mode 100644 index 0000000000000000000000000000000000000000..e14f4b67706d194c1d0b087e4c7848af35116e58 --- /dev/null +++ b/themes/green.py @@ -0,0 +1,108 @@ +import gradio as gr +from toolbox import get_conf +CODE_HIGHLIGHT, ADD_WAIFU, LAYOUT = get_conf('CODE_HIGHLIGHT', 'ADD_WAIFU', 'LAYOUT') + +def adjust_theme(): + try: + set_theme = gr.themes.Soft( + primary_hue=gr.themes.Color( + c50="#EBFAF2", + c100="#CFF3E1", + c200="#A8EAC8", + c300="#77DEA9", + c400="#3FD086", + c500="#02C160", + c600="#06AE56", + c700="#05974E", + c800="#057F45", + c900="#04673D", + c950="#2E5541", + name="small_and_beautiful", + ), + secondary_hue=gr.themes.Color( + c50="#576b95", + c100="#576b95", + c200="#576b95", + c300="#576b95", + c400="#576b95", + c500="#576b95", + c600="#576b95", + c700="#576b95", + c800="#576b95", + c900="#576b95", + c950="#576b95", + ), + neutral_hue=gr.themes.Color( + name="gray", + c50="#f6f7f8", + # c100="#f3f4f6", + c100="#F2F2F2", + c200="#e5e7eb", + c300="#d1d5db", + c400="#B2B2B2", + c500="#808080", + c600="#636363", + c700="#515151", + c800="#393939", + # c900="#272727", + c900="#2B2B2B", + c950="#171717", + ), + + radius_size=gr.themes.sizes.radius_sm, + ).set( + button_primary_background_fill="*primary_500", + button_primary_background_fill_dark="*primary_600", + button_primary_background_fill_hover="*primary_400", + button_primary_border_color="*primary_500", + button_primary_border_color_dark="*primary_600", + button_primary_text_color="white", + button_primary_text_color_dark="white", + button_secondary_background_fill="*neutral_100", + button_secondary_background_fill_hover="*neutral_50", + button_secondary_background_fill_dark="*neutral_900", + button_secondary_text_color="*neutral_800", + button_secondary_text_color_dark="white", + background_fill_primary="*neutral_50", + background_fill_primary_dark="#1F1F1F", + block_title_text_color="*primary_500", + block_title_background_fill_dark="*primary_900", + block_label_background_fill_dark="*primary_900", + input_background_fill="#F6F6F6", + chatbot_code_background_color="*neutral_950", + chatbot_code_background_color_dark="*neutral_950", + ) + + js = '' + if LAYOUT=="TOP-DOWN": + js = "" + else: + with open('themes/common.js', 'r', encoding='utf8') as f: + js = f"" + + # 添加一个萌萌的看板娘 + if ADD_WAIFU: + js += """ + + + + """ + + with open('themes/green.js', 'r', encoding='utf8') as f: + js += f"" + + gradio_original_template_fn = gr.routes.templates.TemplateResponse + def gradio_new_template_fn(*args, **kwargs): + res = gradio_original_template_fn(*args, **kwargs) + res.body = res.body.replace(b'', f'{js}'.encode("utf8")) + res.init_headers() + return res + gr.routes.templates.TemplateResponse = gradio_new_template_fn # override gradio template + except: + set_theme = None + print('gradio版本较旧, 不能自定义字体和颜色') + return set_theme + + +with open("themes/green.css", "r", encoding="utf-8") as f: + advanced_css = f.read() diff --git a/themes/theme.py b/themes/theme.py new file mode 100644 index 0000000000000000000000000000000000000000..c08d9bb0f7b30cdb1c7679c2b8979ec3ab7e8977 --- /dev/null +++ b/themes/theme.py @@ -0,0 +1,12 @@ +import gradio as gr +from toolbox import get_conf +THEME, = get_conf('THEME') + +if THEME == 'Chuanhu-Small-and-Beautiful': + from .green import adjust_theme, advanced_css + theme_declaration = "

[Chuanhu-Small-and-Beautiful主题]

" +else: + from .default import adjust_theme, advanced_css + theme_declaration = "" + + diff --git a/toolbox.py b/toolbox.py index 56b6df49746e97e8fe7c66c84d713828e32c4893..73e3e8d664d38c5abdbd3ce327dd822d46a0d72a 100644 --- a/toolbox.py +++ b/toolbox.py @@ -4,6 +4,7 @@ import time import inspect import re import os +import gradio from latex2mathml.converter import convert as tex2mathml from functools import wraps, lru_cache pj = os.path.join @@ -40,7 +41,7 @@ def ArgsGeneralWrapper(f): """ 装饰器函数,用于重组输入参数,改变输入参数的顺序与结构。 """ - def decorated(cookies, max_length, llm_model, txt, txt2, top_p, temperature, chatbot, history, system_prompt, plugin_advanced_arg, *args): + def decorated(request: gradio.Request, cookies, max_length, llm_model, txt, txt2, top_p, temperature, chatbot, history, system_prompt, plugin_advanced_arg, *args): txt_passon = txt if txt == "" and txt2 != "": txt_passon = txt2 # 引入一个有cookie的chatbot @@ -54,13 +55,21 @@ def ArgsGeneralWrapper(f): 'top_p':top_p, 'max_length': max_length, 'temperature':temperature, + 'client_ip': request.client.host, } plugin_kwargs = { "advanced_arg": plugin_advanced_arg, } chatbot_with_cookie = ChatBotWithCookies(cookies) chatbot_with_cookie.write_list(chatbot) - yield from f(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, *args) + if cookies.get('lock_plugin', None) is None: + # 正常状态 + yield from f(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, *args) + else: + # 处理个别特殊插件的锁定状态 + module, fn_name = cookies['lock_plugin'].split('->') + f_hot_reload = getattr(importlib.import_module(module, fn_name), fn_name) + yield from f_hot_reload(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, *args) return decorated @@ -68,8 +77,21 @@ def update_ui(chatbot, history, msg='正常', **kwargs): # 刷新界面 """ 刷新用户界面 """ - assert isinstance(chatbot, ChatBotWithCookies), "在传递chatbot的过程中不要将其丢弃。必要时,可用clear将其清空,然后用for+append循环重新赋值。" - yield chatbot.get_cookies(), chatbot, history, msg + assert isinstance(chatbot, ChatBotWithCookies), "在传递chatbot的过程中不要将其丢弃。必要时, 可用clear将其清空, 然后用for+append循环重新赋值。" + cookies = chatbot.get_cookies() + + # 解决插件锁定时的界面显示问题 + if cookies.get('lock_plugin', None): + label = cookies.get('llm_model', "") + " | " + "正在锁定插件" + cookies.get('lock_plugin', None) + chatbot_gr = gradio.update(value=chatbot, label=label) + if cookies.get('label', "") != label: cookies['label'] = label # 记住当前的label + elif cookies.get('label', None): + chatbot_gr = gradio.update(value=chatbot, label=cookies.get('llm_model', "")) + cookies['label'] = None # 清空label + else: + chatbot_gr = chatbot + + yield cookies, chatbot_gr, history, msg def update_ui_lastest_msg(lastmsg, chatbot, history, delay=1): # 刷新界面 """ @@ -95,20 +117,20 @@ def CatchException(f): """ @wraps(f) - def decorated(txt, top_p, temperature, chatbot, history, systemPromptTxt, WEB_PORT=-1): + def decorated(main_input, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, *args, **kwargs): try: - yield from f(txt, top_p, temperature, chatbot, history, systemPromptTxt, WEB_PORT) + yield from f(main_input, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, *args, **kwargs) except Exception as e: from check_proxy import check_proxy from toolbox import get_conf proxies, = get_conf('proxies') tb_str = '```\n' + trimmed_format_exc() + '```' - if len(chatbot) == 0: - chatbot.clear() - chatbot.append(["插件调度异常", "异常原因"]) - chatbot[-1] = (chatbot[-1][0], + if len(chatbot_with_cookie) == 0: + chatbot_with_cookie.clear() + chatbot_with_cookie.append(["插件调度异常", "异常原因"]) + chatbot_with_cookie[-1] = (chatbot_with_cookie[-1][0], f"[Local Message] 实验性函数调用出错: \n\n{tb_str} \n\n当前代理可用性: \n\n{check_proxy(proxies)}") - yield from update_ui(chatbot=chatbot, history=history, msg=f'异常 {e}') # 刷新界面 + yield from update_ui(chatbot=chatbot_with_cookie, history=history, msg=f'异常 {e}') # 刷新界面 return decorated @@ -174,11 +196,10 @@ def write_results_to_file(history, file_name=None): import time if file_name is None: # file_name = time.strftime("chatGPT分析报告%Y-%m-%d-%H-%M-%S", time.localtime()) + '.md' - file_name = 'chatGPT分析报告' + \ - time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + '.md' + file_name = 'GPT-Report-' + gen_time_str() + '.md' os.makedirs('./gpt_log/', exist_ok=True) with open(f'./gpt_log/{file_name}', 'w', encoding='utf8') as f: - f.write('# chatGPT 分析报告\n') + f.write('# GPT-Academic Report\n') for i, content in enumerate(history): try: if type(content) != str: content = str(content) @@ -192,11 +213,42 @@ def write_results_to_file(history, file_name=None): # remove everything that cannot be handled by utf8 f.write(content.encode('utf-8', 'ignore').decode()) f.write('\n\n') - res = '以上材料已经被写入' + os.path.abspath(f'./gpt_log/{file_name}') + res = '以上材料已经被写入:\t' + os.path.abspath(f'./gpt_log/{file_name}') print(res) return res +def write_history_to_file(history, file_basename=None, file_fullname=None): + """ + 将对话记录history以Markdown格式写入文件中。如果没有指定文件名,则使用当前时间生成文件名。 + """ + import os + import time + if file_fullname is None: + if file_basename is not None: + file_fullname = os.path.join(get_log_folder(), file_basename) + else: + file_fullname = os.path.join(get_log_folder(), f'GPT-Academic-{gen_time_str()}.md') + os.makedirs(os.path.dirname(file_fullname), exist_ok=True) + with open(file_fullname, 'w', encoding='utf8') as f: + f.write('# GPT-Academic Report\n') + for i, content in enumerate(history): + try: + if type(content) != str: content = str(content) + except: + continue + if i % 2 == 0: + f.write('## ') + try: + f.write(content) + except: + # remove everything that cannot be handled by utf8 + f.write(content.encode('utf-8', 'ignore').decode()) + f.write('\n\n') + res = os.path.abspath(file_fullname) + return res + + def regular_txt_to_markdown(text): """ 将普通文本转换为Markdown格式的文本。 @@ -444,14 +496,21 @@ def promote_file_to_downloadzone(file, rename_file=None, chatbot=None): # 将文件复制一份到下载区 import shutil if rename_file is None: rename_file = f'{gen_time_str()}-{os.path.basename(file)}' - new_path = os.path.join(f'./gpt_log/', rename_file) + new_path = os.path.join(get_log_folder(), rename_file) + # 如果已经存在,先删除 if os.path.exists(new_path) and not os.path.samefile(new_path, file): os.remove(new_path) + # 把文件复制过去 if not os.path.exists(new_path): shutil.copyfile(file, new_path) + # 将文件添加到chatbot cookie中,避免多用户干扰 if chatbot: if 'file_to_promote' in chatbot._cookies: current = chatbot._cookies['file_to_promote'] else: current = [] chatbot._cookies.update({'file_to_promote': [new_path] + current}) +def disable_auto_promotion(chatbot): + chatbot._cookies.update({'file_to_promote': []}) + return + def on_file_uploaded(files, chatbot, txt, txt2, checkboxes): """ 当文件被上传时的回调函数 @@ -467,7 +526,7 @@ def on_file_uploaded(files, chatbot, txt, txt2, checkboxes): shutil.rmtree('./private_upload/') except: pass - time_tag = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + time_tag = gen_time_str() os.makedirs(f'private_upload/{time_tag}', exist_ok=True) err_msg = '' for file in files: @@ -505,16 +564,28 @@ def on_report_generated(cookies, files, chatbot): chatbot.append(['报告如何远程获取?', f'报告已经添加到右侧“文件上传区”(可能处于折叠状态),请查收。{file_links}']) return cookies, report_files, chatbot +def load_chat_cookies(): + API_KEY, LLM_MODEL, AZURE_API_KEY = get_conf('API_KEY', 'LLM_MODEL', 'AZURE_API_KEY') + if is_any_api_key(AZURE_API_KEY): + if is_any_api_key(API_KEY): API_KEY = API_KEY + ',' + AZURE_API_KEY + else: API_KEY = AZURE_API_KEY + return {'api_key': API_KEY, 'llm_model': LLM_MODEL} + def is_openai_api_key(key): - API_MATCH_ORIGINAL = re.match(r"sk-[a-zA-Z0-9]{48}$", key) + CUSTOM_API_KEY_PATTERN, = get_conf('CUSTOM_API_KEY_PATTERN') + if len(CUSTOM_API_KEY_PATTERN) != 0: + API_MATCH_ORIGINAL = re.match(CUSTOM_API_KEY_PATTERN, key) + else: + API_MATCH_ORIGINAL = re.match(r"sk-[a-zA-Z0-9]{48}$", key) + return bool(API_MATCH_ORIGINAL) + +def is_azure_api_key(key): API_MATCH_AZURE = re.match(r"[a-zA-Z0-9]{32}$", key) - return bool(API_MATCH_ORIGINAL) or bool(API_MATCH_AZURE) + return bool(API_MATCH_AZURE) def is_api2d_key(key): - if key.startswith('fk') and len(key) == 41: - return True - else: - return False + 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_any_api_key(key): if ',' in key: @@ -523,10 +594,10 @@ 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) + return is_openai_api_key(key) or is_api2d_key(key) or is_azure_api_key(key) def what_keys(keys): - avail_key_list = {'OpenAI Key':0, "API2D Key":0} + avail_key_list = {'OpenAI Key':0, "Azure Key":0, "API2D Key":0} key_list = keys.split(',') for k in key_list: @@ -537,7 +608,11 @@ def what_keys(keys): if is_api2d_key(k): avail_key_list['API2D Key'] += 1 - return f"检测到: OpenAI Key {avail_key_list['OpenAI Key']} 个,API2D Key {avail_key_list['API2D Key']} 个" + for k in key_list: + if is_azure_api_key(k): + avail_key_list['Azure Key'] += 1 + + return f"检测到: OpenAI Key {avail_key_list['OpenAI Key']} 个, Azure Key {avail_key_list['Azure Key']} 个, API2D Key {avail_key_list['API2D Key']} 个" def select_api_key(keys, llm_model): import random @@ -552,8 +627,12 @@ def select_api_key(keys, llm_model): for k in key_list: if is_api2d_key(k): avail_key_list.append(k) + if llm_model.startswith('azure-'): + for k in key_list: + if is_azure_api_key(k): avail_key_list.append(k) + if len(avail_key_list) == 0: - raise RuntimeError(f"您提供的api-key不满足要求,不包含任何可用于{llm_model}的api-key。您可能选择了错误的模型或请求源。") + raise RuntimeError(f"您提供的api-key不满足要求,不包含任何可用于{llm_model}的api-key。您可能选择了错误的模型或请求源(右下角更换模型菜单中可切换openai,azure,claude,api2d等请求源)。") api_key = random.choice(avail_key_list) # 随机负载均衡 return api_key @@ -629,13 +708,14 @@ def read_single_conf_with_lru_cache(arg): # 在读取API_KEY时,检查一下是不是忘了改config if arg == 'API_KEY': - print亮蓝(f"[API_KEY] 本项目现已支持OpenAI和API2D的api-key。也支持同时填写多个api-key,如API_KEY=\"openai-key1,openai-key2,api2d-key3\"") + print亮蓝(f"[API_KEY] 本项目现已支持OpenAI和Azure的api-key。也支持同时填写多个api-key,如API_KEY=\"openai-key1,openai-key2,azure-key3\"") print亮蓝(f"[API_KEY] 您既可以在config.py中修改api-key(s),也可以在问题输入区输入临时的api-key(s),然后回车键提交后即可生效。") if is_any_api_key(r): print亮绿(f"[API_KEY] 您的 API_KEY 是: {r[:15]}*** API_KEY 导入成功") else: - print亮红( "[API_KEY] 正确的 API_KEY 是'sk'开头的51位密钥(OpenAI),或者 'fk'开头的41位密钥,请在config文件中修改API密钥之后再运行。") + print亮红( "[API_KEY] 您的 API_KEY 不满足任何一种已知的密钥格式,请在config文件中修改API密钥之后再运行。") if arg == 'proxies': + if not read_single_conf_with_lru_cache('USE_PROXY'): r = None # 检查USE_PROXY,防止proxies单独起作用 if r is None: print亮红('[PROXY] 网络代理状态:未配置。无代理状态下很可能无法访问OpenAI家族的模型。建议:检查USE_PROXY选项是否修改。') else: @@ -644,6 +724,7 @@ def read_single_conf_with_lru_cache(arg): return r +@lru_cache(maxsize=128) def get_conf(*args): # 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到 res = [] @@ -802,8 +883,7 @@ def zip_folder(source_folder, dest_folder, zip_name): print(f"Zip file created at {zip_file}") def zip_result(folder): - import time - t = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + t = gen_time_str() zip_folder(folder, './gpt_log/', f'{t}-result.zip') return pj('./gpt_log/', f'{t}-result.zip') @@ -811,6 +891,11 @@ def gen_time_str(): import time return time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) +def get_log_folder(user='default', plugin_name='shared'): + _dir = os.path.join(os.path.dirname(__file__), 'gpt_log', user, plugin_name) + if not os.path.exists(_dir): os.makedirs(_dir) + return _dir + class ProxyNetworkActivate(): """ 这段代码定义了一个名为TempProxy的空上下文管理器, 用于给一小段代码上代理 @@ -843,3 +928,113 @@ def objload(file='objdump.tmp'): with open(file, 'rb') as f: return pickle.load(f) +def Singleton(cls): + """ + 一个单实例装饰器 + """ + _instance = {} + + def _singleton(*args, **kargs): + if cls not in _instance: + _instance[cls] = cls(*args, **kargs) + return _instance[cls] + + return _singleton + +""" +======================================================================== +第四部分 +接驳虚空终端: + - set_conf: 在运行过程中动态地修改配置 + - set_multi_conf: 在运行过程中动态地修改多个配置 + - get_plugin_handle: 获取插件的句柄 + - get_plugin_default_kwargs: 获取插件的默认参数 + - get_chat_handle: 获取简单聊天的句柄 + - get_chat_default_kwargs: 获取简单聊天的默认参数 +======================================================================== +""" + +def set_conf(key, value): + from toolbox import read_single_conf_with_lru_cache, get_conf + read_single_conf_with_lru_cache.cache_clear() + get_conf.cache_clear() + os.environ[key] = str(value) + altered, = get_conf(key) + return altered + +def set_multi_conf(dic): + for k, v in dic.items(): set_conf(k, v) + return + +def get_plugin_handle(plugin_name): + """ + e.g. plugin_name = 'crazy_functions.批量Markdown翻译->Markdown翻译指定语言' + """ + import importlib + assert '->' in plugin_name, \ + "Example of plugin_name: crazy_functions.批量Markdown翻译->Markdown翻译指定语言" + module, fn_name = plugin_name.split('->') + f_hot_reload = getattr(importlib.import_module(module, fn_name), fn_name) + return f_hot_reload + +def get_chat_handle(): + """ + """ + from request_llm.bridge_all import predict_no_ui_long_connection + return predict_no_ui_long_connection + +def get_plugin_default_kwargs(): + """ + """ + from toolbox import get_conf, ChatBotWithCookies + + WEB_PORT, LLM_MODEL, API_KEY = \ + get_conf('WEB_PORT', 'LLM_MODEL', 'API_KEY') + + llm_kwargs = { + 'api_key': API_KEY, + 'llm_model': LLM_MODEL, + 'top_p':1.0, + 'max_length': None, + 'temperature':1.0, + } + chatbot = ChatBotWithCookies(llm_kwargs) + + # txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port + default_plugin_kwargs = { + "main_input": "./README.md", + "llm_kwargs": llm_kwargs, + "plugin_kwargs": {}, + "chatbot_with_cookie": chatbot, + "history": [], + "system_prompt": "You are a good AI.", + "web_port": WEB_PORT + } + return default_plugin_kwargs + +def get_chat_default_kwargs(): + """ + """ + from toolbox import get_conf + + LLM_MODEL, API_KEY = get_conf('LLM_MODEL', 'API_KEY') + + llm_kwargs = { + 'api_key': API_KEY, + 'llm_model': LLM_MODEL, + 'top_p':1.0, + 'max_length': None, + 'temperature':1.0, + } + + default_chat_kwargs = { + "inputs": "Hello there, are you ready?", + "llm_kwargs": llm_kwargs, + "history": [], + "sys_prompt": "You are AI assistant", + "observe_window": None, + "console_slience": False, + } + + return default_chat_kwargs + diff --git a/version b/version index 6353b34117a890ca60792c9dcf3bce78d51bce52..900f168de0a348b607ff6f96d8571c00121cf50a 100644 --- a/version +++ b/version @@ -1,5 +1,5 @@ { - "version": 3.42, + "version": 3.48, "show_feature": true, - "new_feature": "完善本地Latex矫错和翻译功能 <-> 增加gpt-3.5-16k的支持 <-> 新增最强Arxiv论文翻译插件 <-> 修复gradio复制按钮BUG <-> 修复PDF翻译的BUG, 新增HTML中英双栏对照 <-> 添加了OpenAI图片生成插件 <-> 添加了OpenAI音频转文本总结插件 <-> 通过Slack添加对Claude的支持" + "new_feature": "接入阿里通义千问、讯飞星火、上海AI-Lab书生 <-> 优化一键升级 <-> 提高arxiv翻译速度和成功率 <-> 支持自定义APIKEY格式 <-> 临时修复theme的文件丢失问题 <-> 新增实时语音对话插件(自动断句,脱手对话) <-> 支持加载自定义的ChatGLM2微调模型 <-> 动态ChatBot窗口高度 <-> 修复Azure接口的BUG <-> 完善多语言模块 <-> 完善本地Latex矫错和翻译功能 <-> 增加gpt-3.5-16k的支持" }