镜像自地址
https://github.com/binary-husky/gpt_academic.git
已同步 2025-12-06 22:46:48 +00:00
比较提交
148 次代码提交
version3.5
...
version3.5
| 作者 | SHA1 | 提交日期 | |
|---|---|---|---|
|
|
32ddcd067a | ||
|
|
98ef658307 | ||
|
|
a4de91d000 | ||
|
|
1bb437a5d0 | ||
|
|
4421219c2b | ||
|
|
ea28db855d | ||
|
|
5aea7b3d09 | ||
|
|
5274117cf1 | ||
|
|
673faf8cef | ||
|
|
130ae31d55 | ||
|
|
c3abc46d4d | ||
|
|
4df75d49ad | ||
|
|
9ea0fe4de2 | ||
|
|
8698c5a80f | ||
|
|
383f7f4f77 | ||
|
|
34d784df79 | ||
|
|
662bebfc02 | ||
|
|
0c3b00fc6b | ||
|
|
b6e370e8c9 | ||
|
|
71ea8e584a | ||
|
|
a5491b9199 | ||
|
|
6f383c1dc8 | ||
|
|
500a0cbd16 | ||
|
|
1ef6730369 | ||
|
|
491174095a | ||
|
|
02c270410c | ||
|
|
89eec21f27 | ||
|
|
49cea97822 | ||
|
|
6310b65d70 | ||
|
|
93c76e1809 | ||
|
|
f64cf7a3d1 | ||
|
|
fdffbee1b0 | ||
|
|
87ccd1a89a | ||
|
|
87b9734986 | ||
|
|
d2d5665c37 | ||
|
|
0844b6e9cf | ||
|
|
9cb05e5724 | ||
|
|
80b209fa0c | ||
|
|
8d4cb05738 | ||
|
|
31f4069563 | ||
|
|
8ba6fc062e | ||
|
|
c0c2d14e3d | ||
|
|
f0a5c49a9c | ||
|
|
9333570ab7 | ||
|
|
d6eaaad962 | ||
|
|
e24f077b68 | ||
|
|
dc5bb9741a | ||
|
|
b383b45191 | ||
|
|
2d8f37baba | ||
|
|
409927ef8e | ||
|
|
5b231e0170 | ||
|
|
87f629bb37 | ||
|
|
3672c97a06 | ||
|
|
b6ee3e9807 | ||
|
|
d56bc280e9 | ||
|
|
d5fd00c15d | ||
|
|
5e647ff149 | ||
|
|
868faf00cc | ||
|
|
a0286c39b9 | ||
|
|
9cced321f1 | ||
|
|
3073935e24 | ||
|
|
ef6631b280 | ||
|
|
0801e4d881 | ||
|
|
ae08cfbcae | ||
|
|
1c0d5361ea | ||
|
|
278464bfb7 | ||
|
|
2a6996f5d0 | ||
|
|
84b11016c6 | ||
|
|
7e74d3d699 | ||
|
|
2cad8e2694 | ||
|
|
e765ec1223 | ||
|
|
471a369bb8 | ||
|
|
760ff1840c | ||
|
|
9905122fc2 | ||
|
|
abea0d07ac | ||
|
|
16ff5ddcdc | ||
|
|
1c4cb340ca | ||
|
|
5ba8ea27d1 | ||
|
|
567c6530d8 | ||
|
|
a3f36668a8 | ||
|
|
a1cc2f733c | ||
|
|
0937f37388 | ||
|
|
74f35e3401 | ||
|
|
ab7999c71a | ||
|
|
544771db9a | ||
|
|
ec9d030457 | ||
|
|
14de282302 | ||
|
|
fb5467b85b | ||
|
|
c4c6465927 | ||
|
|
99a1cd6f9f | ||
|
|
7e73a255f4 | ||
|
|
4b5f13bff2 | ||
|
|
d495b73456 | ||
|
|
e699b6b13f | ||
|
|
eb150987f0 | ||
|
|
34784333dc | ||
|
|
28d777a96b | ||
|
|
c45fa88684 | ||
|
|
ad9807dd14 | ||
|
|
2a51715075 | ||
|
|
7c307d8964 | ||
|
|
baaacc5a7b | ||
|
|
6faf5947c9 | ||
|
|
571335cbc4 | ||
|
|
7d5abb6d69 | ||
|
|
a0f592308a | ||
|
|
e512d99879 | ||
|
|
e70b636513 | ||
|
|
408b8403fe | ||
|
|
74f8cb3511 | ||
|
|
2202cf3701 | ||
|
|
cce69beee9 | ||
|
|
347124c967 | ||
|
|
77a6105a9a | ||
|
|
13c9606af7 | ||
|
|
bac6810e75 | ||
|
|
c176187d24 | ||
|
|
31d5ee6ccc | ||
|
|
5e0dc9b9ad | ||
|
|
4c6f3aa427 | ||
|
|
d7331befc1 | ||
|
|
63219baa21 | ||
|
|
97cb9a4adc | ||
|
|
24f41b0a75 | ||
|
|
bfec29e9bc | ||
|
|
dd9e624761 | ||
|
|
7855325ff9 | ||
|
|
2c039ff5c9 | ||
|
|
9a5ee86434 | ||
|
|
d6698db257 | ||
|
|
b2d03bf2a3 | ||
|
|
2f83b60fb3 | ||
|
|
d183e34461 | ||
|
|
fb78569335 | ||
|
|
12c8cd75ee | ||
|
|
0e21e3e2e7 | ||
|
|
fda1e87278 | ||
|
|
1092031d77 | ||
|
|
f0482d3bae | ||
|
|
b6ac3d0d6c | ||
|
|
3344ffcb8b | ||
|
|
82936f71b6 | ||
|
|
51e809c09e | ||
|
|
713df396dc | ||
|
|
23a42d93df | ||
|
|
0ef06683dc | ||
|
|
03164bcb6f | ||
|
|
d052d425af |
44
.github/workflows/build-with-all-capacity.yml
vendored
普通文件
44
.github/workflows/build-with-all-capacity.yml
vendored
普通文件
@@ -0,0 +1,44 @@
|
|||||||
|
# https://docs.github.com/en/actions/publishing-packages/publishing-docker-images#publishing-images-to-github-packages
|
||||||
|
name: build-with-all-capacity
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
IMAGE_NAME: ${{ github.repository }}_with_all_capacity
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Log in to the Container registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
file: docs/GithubAction+AllCapacity
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
25
.github/workflows/stale.yml
vendored
普通文件
25
.github/workflows/stale.yml
vendored
普通文件
@@ -0,0 +1,25 @@
|
|||||||
|
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
|
||||||
|
#
|
||||||
|
# You can adjust the behavior by modifying this file.
|
||||||
|
# For more information, see:
|
||||||
|
# https://github.com/actions/stale
|
||||||
|
|
||||||
|
name: 'Close stale issues and PRs'
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '*/5 * * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: read
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v8
|
||||||
|
with:
|
||||||
|
stale-issue-message: 'This issue is stale because it has been open 100 days with no activity. Remove stale label or comment or this will be closed in 1 days.'
|
||||||
|
days-before-stale: 100
|
||||||
|
days-before-close: 1
|
||||||
|
debug-only: true
|
||||||
@@ -17,7 +17,7 @@ WORKDIR /gpt
|
|||||||
|
|
||||||
# 安装大部分依赖,利用Docker缓存加速以后的构建
|
# 安装大部分依赖,利用Docker缓存加速以后的构建
|
||||||
COPY requirements.txt ./
|
COPY requirements.txt ./
|
||||||
COPY ./docs/gradio-3.32.2-py3-none-any.whl ./docs/gradio-3.32.2-py3-none-any.whl
|
COPY ./docs/gradio-3.32.6-py3-none-any.whl ./docs/gradio-3.32.6-py3-none-any.whl
|
||||||
RUN pip3 install -r requirements.txt
|
RUN pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
58
README.md
58
README.md
@@ -1,6 +1,6 @@
|
|||||||
> **Note**
|
> **Note**
|
||||||
>
|
>
|
||||||
> 2023.7.8: Gradio, Pydantic依赖调整,已修改 `requirements.txt`。请及时**更新代码**,安装依赖时,请严格选择`requirements.txt`中**指定的版本**
|
> 2023.10.8: Gradio, Pydantic依赖调整,已修改 `requirements.txt`。请及时**更新代码**,安装依赖时,请严格选择`requirements.txt`中**指定的版本**
|
||||||
>
|
>
|
||||||
> `pip install -r requirements.txt`
|
> `pip install -r requirements.txt`
|
||||||
|
|
||||||
@@ -10,13 +10,13 @@
|
|||||||
**如果喜欢这个项目,请给它一个Star;如果您发明了好用的快捷键或函数插件,欢迎发pull requests!**
|
**如果喜欢这个项目,请给它一个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.
|
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).
|
To translate this project to arbitrary language with GPT, read and run [`multi_language.py`](multi_language.py) (experimental).
|
||||||
|
|
||||||
> **Note**
|
> **Note**
|
||||||
>
|
>
|
||||||
> 1.请注意只有 **高亮(如红色)** 标识的函数插件(按钮)才支持读取文件,部分插件位于插件区的**下拉菜单**中。另外我们以**最高优先级**欢迎和处理任何新插件的PR。
|
> 1.请注意只有 **高亮** 标识的函数插件(按钮)才支持读取文件,部分插件位于插件区的**下拉菜单**中。另外我们以**最高优先级**欢迎和处理任何新插件的PR。
|
||||||
>
|
>
|
||||||
> 2.本项目中每个文件的功能都在[自译解报告`self_analysis.md`](https://github.com/binary-husky/gpt_academic/wiki/GPT‐Academic项目自译解报告)详细说明。随着版本的迭代,您也可以随时自行点击相关函数插件,调用GPT重新生成项目的自我解析报告。常见问题汇总在[`wiki`](https://github.com/binary-husky/gpt_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/GPT‐Academic项目自译解报告)详细说明。随着版本的迭代,您也可以随时自行点击相关函数插件,调用GPT重新生成项目的自我解析报告。常见问题[`wiki`](https://github.com/binary-husky/gpt_academic/wiki)。[安装方法](#installation) | [配置说明](https://github.com/binary-husky/gpt_academic/wiki/%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E)。
|
||||||
>
|
>
|
||||||
> 3.本项目兼容并鼓励尝试国产大语言模型ChatGLM和Moss等等。支持多个api-key共存,可在配置文件中填写如`API_KEY="openai-key1,openai-key2,azure-key3,api2d-key4"`。需要临时更换`API_KEY`时,在输入区输入临时的`API_KEY`然后回车键提交后即可生效。
|
> 3.本项目兼容并鼓励尝试国产大语言模型ChatGLM和Moss等等。支持多个api-key共存,可在配置文件中填写如`API_KEY="openai-key1,openai-key2,azure-key3,api2d-key4"`。需要临时更换`API_KEY`时,在输入区输入临时的`API_KEY`然后回车键提交后即可生效。
|
||||||
|
|
||||||
@@ -53,7 +53,8 @@ Latex论文一键校对 | [函数插件] 仿Grammarly对Latex文章进行语法
|
|||||||
[多LLM模型](https://www.bilibili.com/video/BV1wT411p7yf)支持 | 同时被GPT3.5、GPT4、[清华ChatGLM2](https://github.com/THUDM/ChatGLM2-6B)、[复旦MOSS](https://github.com/OpenLMLab/MOSS)同时伺候的感觉一定会很不错吧?
|
[多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微调辅助插件
|
⭐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/)
|
更多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中直接调用本项目的函数插件(开发中)
|
⭐[void-terminal](https://github.com/binary-husky/void-terminal) pip包 | 脱离GUI,在Python中直接调用本项目的所有函数插件(开发中)
|
||||||
|
⭐虚空终端插件 | [函数插件] 用自然语言,直接调度本项目其他插件
|
||||||
更多新功能展示 (图像生成等) …… | 见本文档结尾处 ……
|
更多新功能展示 (图像生成等) …… | 见本文档结尾处 ……
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -100,9 +101,11 @@ cd gpt_academic
|
|||||||
|
|
||||||
2. 配置API_KEY
|
2. 配置API_KEY
|
||||||
|
|
||||||
在`config.py`中,配置API KEY等设置,[点击查看特殊网络环境设置方法](https://github.com/binary-husky/gpt_academic/issues/1) 。
|
在`config.py`中,配置API KEY等设置,[点击查看特殊网络环境设置方法](https://github.com/binary-husky/gpt_academic/issues/1) 。[Wiki页面](https://github.com/binary-husky/gpt_academic/wiki/%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E)。
|
||||||
|
|
||||||
(P.S. 程序运行时会优先检查是否存在名为`config_private.py`的私密配置文件,并用其中的配置覆盖`config.py`的同名配置。因此,如果您能理解我们的配置读取逻辑,我们强烈建议您在`config.py`旁边创建一个名为`config_private.py`的新配置文件,并把`config.py`中的配置转移(复制)到`config_private.py`中(仅复制您修改过的配置条目即可)。`config_private.py`不受git管控,可以让您的隐私信息更加安全。P.S.项目同样支持通过`环境变量`配置大多数选项,环境变量的书写格式参考`docker-compose`文件。读取优先级: `环境变量` > `config_private.py` > `config.py`)
|
「 程序会优先检查是否存在名为`config_private.py`的私密配置文件,并用其中的配置覆盖`config.py`的同名配置。如您能理解该读取逻辑,我们强烈建议您在`config.py`旁边创建一个名为`config_private.py`的新配置文件,并把`config.py`中的配置转移(复制)到`config_private.py`中(仅复制您修改过的配置条目即可)。 」
|
||||||
|
|
||||||
|
「 支持通过`环境变量`配置项目,环境变量的书写格式参考`docker-compose.yml`文件或者我们的[Wiki页面](https://github.com/binary-husky/gpt_academic/wiki/%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E)。配置读取优先级: `环境变量` > `config_private.py` > `config.py`。 」
|
||||||
|
|
||||||
|
|
||||||
3. 安装依赖
|
3. 安装依赖
|
||||||
@@ -110,7 +113,7 @@ cd gpt_academic
|
|||||||
# (选择I: 如熟悉python)(python版本3.9以上,越新越好),备注:使用官方pip源或者阿里pip源,临时换源方法:python -m pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
|
# (选择I: 如熟悉python)(python版本3.9以上,越新越好),备注:使用官方pip源或者阿里pip源,临时换源方法:python -m pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
|
||||||
python -m pip install -r requirements.txt
|
python -m pip install -r requirements.txt
|
||||||
|
|
||||||
# (选择II: 如不熟悉python)使用anaconda,步骤也是类似的 (https://www.bilibili.com/video/BV1rc411W7Dr):
|
# (选择II: 使用Anaconda)步骤也是类似的 (https://www.bilibili.com/video/BV1rc411W7Dr):
|
||||||
conda create -n gptac_venv python=3.11 # 创建anaconda环境
|
conda create -n gptac_venv python=3.11 # 创建anaconda环境
|
||||||
conda activate gptac_venv # 激活anaconda环境
|
conda activate gptac_venv # 激活anaconda环境
|
||||||
python -m pip install -r requirements.txt # 这个步骤和pip安装一样的步骤
|
python -m pip install -r requirements.txt # 这个步骤和pip安装一样的步骤
|
||||||
@@ -148,23 +151,25 @@ python main.py
|
|||||||
|
|
||||||
### 安装方法II:使用Docker
|
### 安装方法II:使用Docker
|
||||||
|
|
||||||
1. 仅ChatGPT(推荐大多数人选择,等价于docker-compose方案1)
|
0. 部署项目的全部能力(这个是包含cuda和latex的大型镜像。如果您网速慢、硬盘小或没有显卡,则不推荐使用这个,建议使用方案1)(需要熟悉[Nvidia Docker](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#installing-on-ubuntu-and-debian)运行时)
|
||||||
|
[](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-audio-assistant.yml)
|
||||||
|
|
||||||
|
``` sh
|
||||||
|
# 修改docker-compose.yml,保留方案0并删除其他方案。修改docker-compose.yml中方案0的配置,参考其中注释即可
|
||||||
|
docker-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
1. 仅ChatGPT+文心一言+spark等在线模型(推荐大多数人选择)
|
||||||
[](https://github.com/binary-husky/gpt_academic/actions/workflows/build-without-local-llms.yml)
|
[](https://github.com/binary-husky/gpt_academic/actions/workflows/build-without-local-llms.yml)
|
||||||
[](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-latex.yml)
|
[](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-latex.yml)
|
||||||
[](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-audio-assistant.yml)
|
[](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-audio-assistant.yml)
|
||||||
|
|
||||||
``` sh
|
``` sh
|
||||||
git clone --depth=1 https://github.com/binary-husky/gpt_academic.git # 下载项目
|
# 修改docker-compose.yml,保留方案1并删除其他方案。修改docker-compose.yml中方案1的配置,参考其中注释即可
|
||||||
cd gpt_academic # 进入路径
|
docker-compose up
|
||||||
nano config.py # 用任意文本编辑器编辑config.py, 配置 “Proxy”, “API_KEY” 以及 “WEB_PORT” (例如50923) 等
|
|
||||||
docker build -t gpt-academic . # 安装
|
|
||||||
|
|
||||||
#(最后一步-Linux操作系统)用`--net=host`更方便快捷
|
|
||||||
docker run --rm -it --net=host gpt-academic
|
|
||||||
#(最后一步-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并删除其他方案)。
|
|
||||||
|
P.S. 如果需要依赖Latex的插件功能,请见Wiki。另外,您也可以直接使用方案4或者方案0获取Latex功能。
|
||||||
|
|
||||||
2. ChatGPT + ChatGLM2 + MOSS + LLAMA2 + 通义千问(需要熟悉[Nvidia Docker](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#installing-on-ubuntu-and-debian)运行时)
|
2. ChatGPT + ChatGLM2 + MOSS + LLAMA2 + 通义千问(需要熟悉[Nvidia Docker](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#installing-on-ubuntu-and-debian)运行时)
|
||||||
[](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-chatglm.yml)
|
[](https://github.com/binary-husky/gpt_academic/actions/workflows/build-with-chatglm.yml)
|
||||||
@@ -249,10 +254,13 @@ Tip:不指定文件直接点击 `载入对话历史存档` 可以查看历史h
|
|||||||
<img src="https://github.com/binary-husky/gpt_academic/assets/96192199/9fdcc391-f823-464f-9322-f8719677043b" height="250" >
|
<img src="https://github.com/binary-husky/gpt_academic/assets/96192199/9fdcc391-f823-464f-9322-f8719677043b" height="250" >
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
3. 生成报告。大部分插件都会在执行结束后,生成工作报告
|
3. 虚空终端(从自然语言输入中,理解用户意图+自动调用其他插件)
|
||||||
|
|
||||||
|
- 步骤一:输入 “ 请调用插件翻译PDF论文,地址为https://openreview.net/pdf?id=rJl0r3R9KX ”
|
||||||
|
- 步骤二:点击“虚空终端”
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<img src="https://user-images.githubusercontent.com/96192199/227503770-fe29ce2c-53fd-47b0-b0ff-93805f0c2ff4.png" height="250" >
|
<img src="https://github.com/binary-husky/gpt_academic/assets/96192199/66f1b044-e9ff-4eed-9126-5d4f3668f1ed" width="500" >
|
||||||
<img src="https://user-images.githubusercontent.com/96192199/227504617-7a497bb3-0a2a-4b50-9a8a-95ae60ea7afd.png" height="250" >
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
4. 模块化功能设计,简单的接口却能支持强大的功能
|
4. 模块化功能设计,简单的接口却能支持强大的功能
|
||||||
@@ -299,8 +307,12 @@ Tip:不指定文件直接点击 `载入对话历史存档` 可以查看历史h
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### II:版本:
|
### II:版本:
|
||||||
- version 3.60(todo): 优化虚空终端,引入code interpreter和更多插件
|
- version 3.60(todo): 优化虚空终端,引入code interpreter和更多插件
|
||||||
|
- version 3.55: 重构前端界面,引入悬浮窗口与菜单栏
|
||||||
|
- version 3.54: 新增动态代码解释器(Code Interpreter)(待完善)
|
||||||
|
- version 3.53: 支持动态选择不同界面主题,提高稳定性&解决多用户冲突问题
|
||||||
- version 3.50: 使用自然语言调用本项目的所有函数插件(虚空终端),支持插件分类,改进UI,设计新主题
|
- version 3.50: 使用自然语言调用本项目的所有函数插件(虚空终端),支持插件分类,改进UI,设计新主题
|
||||||
- version 3.49: 支持百度千帆平台和文心一言
|
- version 3.49: 支持百度千帆平台和文心一言
|
||||||
- version 3.48: 支持阿里达摩院通义千问,上海AI-Lab书生,讯飞星火
|
- version 3.48: 支持阿里达摩院通义千问,上海AI-Lab书生,讯飞星火
|
||||||
@@ -321,7 +333,7 @@ Tip:不指定文件直接点击 `载入对话历史存档` 可以查看历史h
|
|||||||
- version 2.0: 引入模块化函数插件
|
- version 2.0: 引入模块化函数插件
|
||||||
- version 1.0: 基础功能
|
- version 1.0: 基础功能
|
||||||
|
|
||||||
gpt_academic开发者QQ群-2:610599535
|
GPT Academic开发者QQ群:`610599535`
|
||||||
|
|
||||||
- 已知问题
|
- 已知问题
|
||||||
- 某些浏览器翻译插件干扰此软件前端的运行
|
- 某些浏览器翻译插件干扰此软件前端的运行
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ def check_proxy(proxies):
|
|||||||
try:
|
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()
|
data = response.json()
|
||||||
print(f'查询代理的地理位置,返回的结果是{data}')
|
# print(f'查询代理的地理位置,返回的结果是{data}')
|
||||||
if 'country_name' in data:
|
if 'country_name' in data:
|
||||||
country = data['country_name']
|
country = data['country_name']
|
||||||
result = f"代理配置 {proxies_https}, 代理所在地:{country}"
|
result = f"代理配置 {proxies_https}, 代理所在地:{country}"
|
||||||
@@ -155,11 +155,13 @@ def auto_update(raise_error=False):
|
|||||||
|
|
||||||
def warm_up_modules():
|
def warm_up_modules():
|
||||||
print('正在执行一些模块的预热...')
|
print('正在执行一些模块的预热...')
|
||||||
|
from toolbox import ProxyNetworkActivate
|
||||||
from request_llm.bridge_all import model_info
|
from request_llm.bridge_all import model_info
|
||||||
enc = model_info["gpt-3.5-turbo"]['tokenizer']
|
with ProxyNetworkActivate("Warmup_Modules"):
|
||||||
enc.encode("模块预热", disallowed_special=())
|
enc = model_info["gpt-3.5-turbo"]['tokenizer']
|
||||||
enc = model_info["gpt-4"]['tokenizer']
|
enc.encode("模块预热", disallowed_special=())
|
||||||
enc.encode("模块预热", disallowed_special=())
|
enc = model_info["gpt-4"]['tokenizer']
|
||||||
|
enc.encode("模块预热", disallowed_special=())
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import os
|
import os
|
||||||
|
|||||||
42
config.py
42
config.py
@@ -43,8 +43,10 @@ API_URL_REDIRECT = {}
|
|||||||
DEFAULT_WORKER_NUM = 3
|
DEFAULT_WORKER_NUM = 3
|
||||||
|
|
||||||
|
|
||||||
# 色彩主题,可选 ["Default", "Chuanhu-Small-and-Beautiful", "High-Contrast"]
|
# 色彩主题, 可选 ["Default", "Chuanhu-Small-and-Beautiful", "High-Contrast"]
|
||||||
|
# 更多主题, 请查阅Gradio主题商店: https://huggingface.co/spaces/gradio/theme-gallery 可选 ["Gstaff/Xkcd", "NoCrypt/Miku", ...]
|
||||||
THEME = "Default"
|
THEME = "Default"
|
||||||
|
AVAIL_THEMES = ["Default", "Chuanhu-Small-and-Beautiful", "High-Contrast", "Gstaff/Xkcd", "NoCrypt/Miku"]
|
||||||
|
|
||||||
|
|
||||||
# 对话窗的高度 (仅在LAYOUT="TOP-DOWN"时生效)
|
# 对话窗的高度 (仅在LAYOUT="TOP-DOWN"时生效)
|
||||||
@@ -57,7 +59,10 @@ CODE_HIGHLIGHT = True
|
|||||||
|
|
||||||
# 窗口布局
|
# 窗口布局
|
||||||
LAYOUT = "LEFT-RIGHT" # "LEFT-RIGHT"(左右布局) # "TOP-DOWN"(上下布局)
|
LAYOUT = "LEFT-RIGHT" # "LEFT-RIGHT"(左右布局) # "TOP-DOWN"(上下布局)
|
||||||
DARK_MODE = True # 暗色模式 / 亮色模式
|
|
||||||
|
|
||||||
|
# 暗色模式 / 亮色模式
|
||||||
|
DARK_MODE = True
|
||||||
|
|
||||||
|
|
||||||
# 发送请求到OpenAI后,等待多久判定为超时
|
# 发送请求到OpenAI后,等待多久判定为超时
|
||||||
@@ -73,14 +78,14 @@ MAX_RETRY = 2
|
|||||||
|
|
||||||
|
|
||||||
# 插件分类默认选项
|
# 插件分类默认选项
|
||||||
DEFAULT_FN_GROUPS = ['对话', '编程', '学术']
|
DEFAULT_FN_GROUPS = ['对话', '编程', '学术', '智能体']
|
||||||
|
|
||||||
|
|
||||||
# 模型选择是 (注意: LLM_MODEL是默认选中的模型, 它*必须*被包含在AVAIL_LLM_MODELS列表中 )
|
# 模型选择是 (注意: LLM_MODEL是默认选中的模型, 它*必须*被包含在AVAIL_LLM_MODELS列表中 )
|
||||||
LLM_MODEL = "gpt-3.5-turbo" # 可选 ↓↓↓
|
LLM_MODEL = "gpt-3.5-turbo" # 可选 ↓↓↓
|
||||||
AVAIL_LLM_MODELS = ["gpt-3.5-turbo-16k", "gpt-3.5-turbo", "azure-gpt-3.5", "api2d-gpt-3.5-turbo",
|
AVAIL_LLM_MODELS = ["gpt-3.5-turbo-16k", "gpt-3.5-turbo", "azure-gpt-3.5", "api2d-gpt-3.5-turbo",
|
||||||
"gpt-4", "api2d-gpt-4", "chatglm", "moss", "newbing", "stack-claude"]
|
"gpt-4", "gpt-4-32k", "azure-gpt-4", "api2d-gpt-4", "chatglm", "moss", "newbing", "stack-claude"]
|
||||||
# P.S. 其他可用的模型还包括 ["qianfan", "llama2", "qwen", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-16k-0613",
|
# P.S. 其他可用的模型还包括 ["qianfan", "llama2", "qwen", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-16k-0613", "gpt-3.5-random"
|
||||||
# "spark", "sparkv2", "chatglm_onnx", "claude-1-100k", "claude-2", "internlm", "jittorllms_pangualpha", "jittorllms_llama"]
|
# "spark", "sparkv2", "chatglm_onnx", "claude-1-100k", "claude-2", "internlm", "jittorllms_pangualpha", "jittorllms_llama"]
|
||||||
|
|
||||||
|
|
||||||
@@ -120,6 +125,11 @@ AUTHENTICATION = []
|
|||||||
CUSTOM_PATH = "/"
|
CUSTOM_PATH = "/"
|
||||||
|
|
||||||
|
|
||||||
|
# HTTPS 秘钥和证书(不需要修改)
|
||||||
|
SSL_KEYFILE = ""
|
||||||
|
SSL_CERTFILE = ""
|
||||||
|
|
||||||
|
|
||||||
# 极少数情况下,openai的官方KEY需要伴随组织编码(格式如org-xxxxxxxxxxxxxxxxxxxxxxxx)使用
|
# 极少数情况下,openai的官方KEY需要伴随组织编码(格式如org-xxxxxxxxxxxxxxxxxxxxxxxx)使用
|
||||||
API_ORG = ""
|
API_ORG = ""
|
||||||
|
|
||||||
@@ -135,7 +145,7 @@ AZURE_API_KEY = "填入azure openai api的密钥" # 建议直接在API_KEY处
|
|||||||
AZURE_ENGINE = "填入你亲手写的部署名" # 读 docs\use_azure.md
|
AZURE_ENGINE = "填入你亲手写的部署名" # 读 docs\use_azure.md
|
||||||
|
|
||||||
|
|
||||||
# 使用Newbing
|
# 使用Newbing (不推荐使用,未来将删除)
|
||||||
NEWBING_STYLE = "creative" # ["creative", "balanced", "precise"]
|
NEWBING_STYLE = "creative" # ["creative", "balanced", "precise"]
|
||||||
NEWBING_COOKIES = """
|
NEWBING_COOKIES = """
|
||||||
put your new bing cookies here
|
put your new bing cookies here
|
||||||
@@ -172,7 +182,8 @@ HUGGINGFACE_ACCESS_TOKEN = "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"
|
|||||||
# 获取方法:复制以下空间https://huggingface.co/spaces/qingxu98/grobid,设为public,然后GROBID_URL = "https://(你的hf用户名如qingxu98)-(你的填写的空间名如grobid).hf.space"
|
# 获取方法:复制以下空间https://huggingface.co/spaces/qingxu98/grobid,设为public,然后GROBID_URL = "https://(你的hf用户名如qingxu98)-(你的填写的空间名如grobid).hf.space"
|
||||||
GROBID_URLS = [
|
GROBID_URLS = [
|
||||||
"https://qingxu98-grobid.hf.space","https://qingxu98-grobid2.hf.space","https://qingxu98-grobid3.hf.space",
|
"https://qingxu98-grobid.hf.space","https://qingxu98-grobid2.hf.space","https://qingxu98-grobid3.hf.space",
|
||||||
"https://shaocongma-grobid.hf.space","https://FBR123-grobid.hf.space", "https://yeku-grobid.hf.space",
|
"https://qingxu98-grobid4.hf.space","https://qingxu98-grobid5.hf.space", "https://qingxu98-grobid6.hf.space",
|
||||||
|
"https://qingxu98-grobid7.hf.space", "https://qingxu98-grobid8.hf.space",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -180,6 +191,21 @@ GROBID_URLS = [
|
|||||||
ALLOW_RESET_CONFIG = False
|
ALLOW_RESET_CONFIG = False
|
||||||
|
|
||||||
|
|
||||||
|
# 临时的上传文件夹位置,请勿修改
|
||||||
|
PATH_PRIVATE_UPLOAD = "private_upload"
|
||||||
|
|
||||||
|
|
||||||
|
# 日志文件夹的位置,请勿修改
|
||||||
|
PATH_LOGGING = "gpt_log"
|
||||||
|
|
||||||
|
|
||||||
|
# 除了连接OpenAI之外,还有哪些场合允许使用代理,请勿修改
|
||||||
|
WHEN_TO_USE_PROXY = ["Download_LLM", "Download_Gradio_Theme", "Connect_Grobid", "Warmup_Modules"]
|
||||||
|
|
||||||
|
|
||||||
|
# 自定义按钮的最大数量限制
|
||||||
|
NUM_CUSTOM_BASIC_BTN = 4
|
||||||
|
|
||||||
"""
|
"""
|
||||||
在线大模型配置关联关系示意图
|
在线大模型配置关联关系示意图
|
||||||
│
|
│
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ def get_core_functions():
|
|||||||
# 前缀,会被加在你的输入之前。例如,用来描述你的要求,例如翻译、解释代码、润色等等
|
# 前缀,会被加在你的输入之前。例如,用来描述你的要求,例如翻译、解释代码、润色等等
|
||||||
"Prefix": r"Below is a paragraph from an academic paper. Polish the writing to meet the academic style, " +
|
"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"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",
|
r"Firstly, you should provide the polished paragraph. "
|
||||||
|
r"Secondly, you should list all your modification and explain the reasons to do so in markdown table." + "\n\n",
|
||||||
# 后缀,会被加在你的输入之后。例如,配合前缀可以把你的输入内容用引号圈起来
|
# 后缀,会被加在你的输入之后。例如,配合前缀可以把你的输入内容用引号圈起来
|
||||||
"Suffix": r"",
|
"Suffix": r"",
|
||||||
# 按钮颜色 (默认 secondary)
|
# 按钮颜色 (默认 secondary)
|
||||||
@@ -27,17 +28,18 @@ def get_core_functions():
|
|||||||
"Suffix": r"",
|
"Suffix": r"",
|
||||||
},
|
},
|
||||||
"查找语法错误": {
|
"查找语法错误": {
|
||||||
"Prefix": r"Can you help me ensure that the grammar and the spelling is correct? " +
|
"Prefix": r"Help me ensure that the grammar and the spelling is correct. "
|
||||||
r"Do not try to polish the text, if no mistake is found, tell me that this paragraph is good." +
|
r"Do not try to polish the text, if no mistake is found, tell me that this paragraph is good. "
|
||||||
r"If you find grammar or spelling mistakes, please list mistakes you find in a two-column markdown table, " +
|
r"If you find grammar or spelling mistakes, please list mistakes you find in a two-column markdown table, "
|
||||||
r"put the original text the first column, " +
|
r"put the original text the first column, "
|
||||||
r"put the corrected text in the second column and highlight the key words you fixed.""\n"
|
r"put the corrected text in the second column and highlight the key words you fixed. "
|
||||||
|
r"Finally, please provide the proofreaded text.""\n\n"
|
||||||
r"Example:""\n"
|
r"Example:""\n"
|
||||||
r"Paragraph: How is you? Do you knows what is it?""\n"
|
r"Paragraph: How is you? Do you knows what is it?""\n"
|
||||||
r"| Original sentence | Corrected sentence |""\n"
|
r"| Original sentence | Corrected sentence |""\n"
|
||||||
r"| :--- | :--- |""\n"
|
r"| :--- | :--- |""\n"
|
||||||
r"| How **is** you? | How **are** you? |""\n"
|
r"| How **is** you? | How **are** you? |""\n"
|
||||||
r"| Do you **knows** what **is** **it**? | Do you **know** what **it** **is** ? |""\n"
|
r"| Do you **knows** what **is** **it**? | Do you **know** what **it** **is** ? |""\n\n"
|
||||||
r"Below is a paragraph from an academic paper. "
|
r"Below is a paragraph from an academic paper. "
|
||||||
r"You need to report all grammar and spelling mistakes as the example before."
|
r"You need to report all grammar and spelling mistakes as the example before."
|
||||||
+ "\n\n",
|
+ "\n\n",
|
||||||
@@ -89,8 +91,15 @@ def handle_core_functionality(additional_fn, inputs, history, chatbot):
|
|||||||
import core_functional
|
import core_functional
|
||||||
importlib.reload(core_functional) # 热更新prompt
|
importlib.reload(core_functional) # 热更新prompt
|
||||||
core_functional = core_functional.get_core_functions()
|
core_functional = core_functional.get_core_functions()
|
||||||
if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话)
|
addition = chatbot._cookies['customize_fn_overwrite']
|
||||||
inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"]
|
if additional_fn in addition:
|
||||||
if core_functional[additional_fn].get("AutoClearHistory", False):
|
# 自定义功能
|
||||||
history = []
|
inputs = addition[additional_fn]["Prefix"] + inputs + addition[additional_fn]["Suffix"]
|
||||||
return inputs, history
|
return inputs, history
|
||||||
|
else:
|
||||||
|
# 预制功能
|
||||||
|
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
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ def get_crazy_functions():
|
|||||||
from crazy_functions.生成函数注释 import 批量生成函数注释
|
from crazy_functions.生成函数注释 import 批量生成函数注释
|
||||||
from crazy_functions.解析项目源代码 import 解析项目本身
|
from crazy_functions.解析项目源代码 import 解析项目本身
|
||||||
from crazy_functions.解析项目源代码 import 解析一个Python项目
|
from crazy_functions.解析项目源代码 import 解析一个Python项目
|
||||||
|
from crazy_functions.解析项目源代码 import 解析一个Matlab项目
|
||||||
from crazy_functions.解析项目源代码 import 解析一个C项目的头文件
|
from crazy_functions.解析项目源代码 import 解析一个C项目的头文件
|
||||||
from crazy_functions.解析项目源代码 import 解析一个C项目
|
from crazy_functions.解析项目源代码 import 解析一个C项目
|
||||||
from crazy_functions.解析项目源代码 import 解析一个Golang项目
|
from crazy_functions.解析项目源代码 import 解析一个Golang项目
|
||||||
@@ -13,7 +14,6 @@ def get_crazy_functions():
|
|||||||
from crazy_functions.解析项目源代码 import 解析一个Java项目
|
from crazy_functions.解析项目源代码 import 解析一个Java项目
|
||||||
from crazy_functions.解析项目源代码 import 解析一个前端项目
|
from crazy_functions.解析项目源代码 import 解析一个前端项目
|
||||||
from crazy_functions.高级功能函数模板 import 高阶功能模板函数
|
from crazy_functions.高级功能函数模板 import 高阶功能模板函数
|
||||||
from crazy_functions.代码重写为全英文_多线程 import 全项目切换英文
|
|
||||||
from crazy_functions.Latex全文润色 import Latex英文润色
|
from crazy_functions.Latex全文润色 import Latex英文润色
|
||||||
from crazy_functions.询问多个大语言模型 import 同时问询
|
from crazy_functions.询问多个大语言模型 import 同时问询
|
||||||
from crazy_functions.解析项目源代码 import 解析一个Lua项目
|
from crazy_functions.解析项目源代码 import 解析一个Lua项目
|
||||||
@@ -39,7 +39,7 @@ def get_crazy_functions():
|
|||||||
|
|
||||||
function_plugins = {
|
function_plugins = {
|
||||||
"虚空终端": {
|
"虚空终端": {
|
||||||
"Group": "对话|编程|学术",
|
"Group": "对话|编程|学术|智能体",
|
||||||
"Color": "stop",
|
"Color": "stop",
|
||||||
"AsButton": True,
|
"AsButton": True,
|
||||||
"Function": HotReload(虚空终端)
|
"Function": HotReload(虚空终端)
|
||||||
@@ -78,6 +78,13 @@ def get_crazy_functions():
|
|||||||
"Info": "批量总结word文档 | 输入参数为路径",
|
"Info": "批量总结word文档 | 输入参数为路径",
|
||||||
"Function": HotReload(总结word文档)
|
"Function": HotReload(总结word文档)
|
||||||
},
|
},
|
||||||
|
"解析整个Matlab项目": {
|
||||||
|
"Group": "编程",
|
||||||
|
"Color": "stop",
|
||||||
|
"AsButton": False,
|
||||||
|
"Info": "解析一个Matlab项目的所有源文件(.m) | 输入参数为路径",
|
||||||
|
"Function": HotReload(解析一个Matlab项目)
|
||||||
|
},
|
||||||
"解析整个C++项目头文件": {
|
"解析整个C++项目头文件": {
|
||||||
"Group": "编程",
|
"Group": "编程",
|
||||||
"Color": "stop",
|
"Color": "stop",
|
||||||
@@ -183,10 +190,10 @@ def get_crazy_functions():
|
|||||||
"Info": "多线程解析并翻译此项目的源码 | 不需要输入参数",
|
"Info": "多线程解析并翻译此项目的源码 | 不需要输入参数",
|
||||||
"Function": HotReload(解析项目本身)
|
"Function": HotReload(解析项目本身)
|
||||||
},
|
},
|
||||||
"[插件demo]历史上的今天": {
|
"历史上的今天": {
|
||||||
"Group": "对话",
|
"Group": "对话",
|
||||||
"AsButton": True,
|
"AsButton": True,
|
||||||
"Info": "查看历史上的今天事件 | 不需要输入参数",
|
"Info": "查看历史上的今天事件 (这是一个面向开发者的插件Demo) | 不需要输入参数",
|
||||||
"Function": HotReload(高阶功能模板函数)
|
"Function": HotReload(高阶功能模板函数)
|
||||||
},
|
},
|
||||||
"精准翻译PDF论文": {
|
"精准翻译PDF论文": {
|
||||||
@@ -244,20 +251,25 @@ def get_crazy_functions():
|
|||||||
"Info": "对中文Latex项目全文进行润色处理 | 输入参数为路径或上传压缩包",
|
"Info": "对中文Latex项目全文进行润色处理 | 输入参数为路径或上传压缩包",
|
||||||
"Function": HotReload(Latex中文润色)
|
"Function": HotReload(Latex中文润色)
|
||||||
},
|
},
|
||||||
"Latex项目全文中译英(输入路径或上传压缩包)": {
|
|
||||||
"Group": "学术",
|
# 已经被新插件取代
|
||||||
"Color": "stop",
|
# "Latex项目全文中译英(输入路径或上传压缩包)": {
|
||||||
"AsButton": False, # 加入下拉菜单中
|
# "Group": "学术",
|
||||||
"Info": "对Latex项目全文进行中译英处理 | 输入参数为路径或上传压缩包",
|
# "Color": "stop",
|
||||||
"Function": HotReload(Latex中译英)
|
# "AsButton": False, # 加入下拉菜单中
|
||||||
},
|
# "Info": "对Latex项目全文进行中译英处理 | 输入参数为路径或上传压缩包",
|
||||||
"Latex项目全文英译中(输入路径或上传压缩包)": {
|
# "Function": HotReload(Latex中译英)
|
||||||
"Group": "学术",
|
# },
|
||||||
"Color": "stop",
|
|
||||||
"AsButton": False, # 加入下拉菜单中
|
# 已经被新插件取代
|
||||||
"Info": "对Latex项目全文进行英译中处理 | 输入参数为路径或上传压缩包",
|
# "Latex项目全文英译中(输入路径或上传压缩包)": {
|
||||||
"Function": HotReload(Latex英译中)
|
# "Group": "学术",
|
||||||
},
|
# "Color": "stop",
|
||||||
|
# "AsButton": False, # 加入下拉菜单中
|
||||||
|
# "Info": "对Latex项目全文进行英译中处理 | 输入参数为路径或上传压缩包",
|
||||||
|
# "Function": HotReload(Latex英译中)
|
||||||
|
# },
|
||||||
|
|
||||||
"批量Markdown中译英(输入路径或上传压缩包)": {
|
"批量Markdown中译英(输入路径或上传压缩包)": {
|
||||||
"Group": "编程",
|
"Group": "编程",
|
||||||
"Color": "stop",
|
"Color": "stop",
|
||||||
@@ -385,7 +397,7 @@ def get_crazy_functions():
|
|||||||
try:
|
try:
|
||||||
from crazy_functions.批量Markdown翻译 import Markdown翻译指定语言
|
from crazy_functions.批量Markdown翻译 import Markdown翻译指定语言
|
||||||
function_plugins.update({
|
function_plugins.update({
|
||||||
"Markdown翻译(手动指定语言)": {
|
"Markdown翻译(指定翻译成何种语言)": {
|
||||||
"Group": "编程",
|
"Group": "编程",
|
||||||
"Color": "stop",
|
"Color": "stop",
|
||||||
"AsButton": False,
|
"AsButton": False,
|
||||||
@@ -400,12 +412,12 @@ def get_crazy_functions():
|
|||||||
try:
|
try:
|
||||||
from crazy_functions.Langchain知识库 import 知识库问答
|
from crazy_functions.Langchain知识库 import 知识库问答
|
||||||
function_plugins.update({
|
function_plugins.update({
|
||||||
"构建知识库(请先上传文件素材)": {
|
"构建知识库(先上传文件素材,再运行此插件)": {
|
||||||
"Group": "对话",
|
"Group": "对话",
|
||||||
"Color": "stop",
|
"Color": "stop",
|
||||||
"AsButton": False,
|
"AsButton": False,
|
||||||
"AdvancedArgs": True,
|
"AdvancedArgs": True,
|
||||||
"ArgsReminder": "待注入的知识库名称id, 默认为default",
|
"ArgsReminder": "此处待注入的知识库名称id, 默认为default。文件进入知识库后可长期保存。可以通过再次调用本插件的方式,向知识库追加更多文档。",
|
||||||
"Function": HotReload(知识库问答)
|
"Function": HotReload(知识库问答)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -415,12 +427,12 @@ def get_crazy_functions():
|
|||||||
try:
|
try:
|
||||||
from crazy_functions.Langchain知识库 import 读取知识库作答
|
from crazy_functions.Langchain知识库 import 读取知识库作答
|
||||||
function_plugins.update({
|
function_plugins.update({
|
||||||
"知识库问答": {
|
"知识库问答(构建知识库后,再运行此插件)": {
|
||||||
"Group": "对话",
|
"Group": "对话",
|
||||||
"Color": "stop",
|
"Color": "stop",
|
||||||
"AsButton": False,
|
"AsButton": False,
|
||||||
"AdvancedArgs": True,
|
"AdvancedArgs": True,
|
||||||
"ArgsReminder": "待提取的知识库名称id, 默认为default, 您需要首先调用构建知识库",
|
"ArgsReminder": "待提取的知识库名称id, 默认为default, 您需要构建知识库后再运行此插件。",
|
||||||
"Function": HotReload(读取知识库作答)
|
"Function": HotReload(读取知识库作答)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -430,7 +442,7 @@ def get_crazy_functions():
|
|||||||
try:
|
try:
|
||||||
from crazy_functions.交互功能函数模板 import 交互功能模板函数
|
from crazy_functions.交互功能函数模板 import 交互功能模板函数
|
||||||
function_plugins.update({
|
function_plugins.update({
|
||||||
"交互功能模板函数": {
|
"交互功能模板Demo函数(查找wallhaven.cc的壁纸)": {
|
||||||
"Group": "对话",
|
"Group": "对话",
|
||||||
"Color": "stop",
|
"Color": "stop",
|
||||||
"AsButton": False,
|
"AsButton": False,
|
||||||
@@ -490,17 +502,43 @@ def get_crazy_functions():
|
|||||||
if ENABLE_AUDIO:
|
if ENABLE_AUDIO:
|
||||||
from crazy_functions.语音助手 import 语音助手
|
from crazy_functions.语音助手 import 语音助手
|
||||||
function_plugins.update({
|
function_plugins.update({
|
||||||
"实时音频采集": {
|
"实时语音对话": {
|
||||||
"Group": "对话",
|
"Group": "对话",
|
||||||
"Color": "stop",
|
"Color": "stop",
|
||||||
"AsButton": True,
|
"AsButton": True,
|
||||||
"Info": "开始语言对话 | 没有输入参数",
|
"Info": "这是一个时刻聆听着的语音对话助手 | 没有输入参数",
|
||||||
"Function": HotReload(语音助手)
|
"Function": HotReload(语音助手)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
except:
|
except:
|
||||||
print('Load function plugin failed')
|
print('Load function plugin failed')
|
||||||
|
|
||||||
|
try:
|
||||||
|
from crazy_functions.批量翻译PDF文档_NOUGAT import 批量翻译PDF文档
|
||||||
|
function_plugins.update({
|
||||||
|
"精准翻译PDF文档(NOUGAT)": {
|
||||||
|
"Group": "学术",
|
||||||
|
"Color": "stop",
|
||||||
|
"AsButton": False,
|
||||||
|
"Function": HotReload(批量翻译PDF文档)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
except:
|
||||||
|
print('Load function plugin failed')
|
||||||
|
|
||||||
|
try:
|
||||||
|
from crazy_functions.函数动态生成 import 函数动态生成
|
||||||
|
function_plugins.update({
|
||||||
|
"动态代码解释器(CodeInterpreter)": {
|
||||||
|
"Group": "智能体",
|
||||||
|
"Color": "stop",
|
||||||
|
"AsButton": False,
|
||||||
|
"Function": HotReload(函数动态生成)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
except:
|
||||||
|
print('Load function plugin failed')
|
||||||
|
|
||||||
|
|
||||||
# try:
|
# try:
|
||||||
# from crazy_functions.chatglm微调工具 import 微调数据集生成
|
# from crazy_functions.chatglm微调工具 import 微调数据集生成
|
||||||
|
|||||||
232
crazy_functions/CodeInterpreter.py
普通文件
232
crazy_functions/CodeInterpreter.py
普通文件
@@ -0,0 +1,232 @@
|
|||||||
|
from collections.abc import Callable, Iterable, Mapping
|
||||||
|
from typing import Any
|
||||||
|
from toolbox import CatchException, update_ui, gen_time_str, trimmed_format_exc
|
||||||
|
from toolbox import promote_file_to_downloadzone, get_log_folder
|
||||||
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
|
from .crazy_utils import input_clipping, try_install_deps
|
||||||
|
from multiprocessing import Process, Pipe
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
templete = """
|
||||||
|
```python
|
||||||
|
import ... # Put dependencies here, e.g. import numpy as np
|
||||||
|
|
||||||
|
class TerminalFunction(object): # Do not change the name of the class, The name of the class must be `TerminalFunction`
|
||||||
|
|
||||||
|
def run(self, path): # The name of the function must be `run`, it takes only a positional argument.
|
||||||
|
# rewrite the function you have just written here
|
||||||
|
...
|
||||||
|
return generated_file_path
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
|
||||||
|
def inspect_dependency(chatbot, history):
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_code_block(reply):
|
||||||
|
import re
|
||||||
|
pattern = r"```([\s\S]*?)```" # regex pattern to match code blocks
|
||||||
|
matches = re.findall(pattern, reply) # find all code blocks in text
|
||||||
|
if len(matches) == 1:
|
||||||
|
return matches[0].strip('python') # code block
|
||||||
|
for match in matches:
|
||||||
|
if 'class TerminalFunction' in match:
|
||||||
|
return match.strip('python') # code block
|
||||||
|
raise RuntimeError("GPT is not generating proper code.")
|
||||||
|
|
||||||
|
def gpt_interact_multi_step(txt, file_type, llm_kwargs, chatbot, history):
|
||||||
|
# 输入
|
||||||
|
prompt_compose = [
|
||||||
|
f'Your job:\n'
|
||||||
|
f'1. write a single Python function, which takes a path of a `{file_type}` file as the only argument and returns a `string` containing the result of analysis or the path of generated files. \n',
|
||||||
|
f"2. You should write this function to perform following task: " + txt + "\n",
|
||||||
|
f"3. Wrap the output python function with markdown codeblock."
|
||||||
|
]
|
||||||
|
i_say = "".join(prompt_compose)
|
||||||
|
demo = []
|
||||||
|
|
||||||
|
# 第一步
|
||||||
|
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=demo,
|
||||||
|
sys_prompt= r"You are a programmer."
|
||||||
|
)
|
||||||
|
history.extend([i_say, gpt_say])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
|
||||||
|
|
||||||
|
# 第二步
|
||||||
|
prompt_compose = [
|
||||||
|
"If previous stage is successful, rewrite the function you have just written to satisfy following templete: \n",
|
||||||
|
templete
|
||||||
|
]
|
||||||
|
i_say = "".join(prompt_compose); inputs_show_user = "If previous stage is successful, rewrite the function you have just written to satisfy executable templete. "
|
||||||
|
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
||||||
|
inputs=i_say, inputs_show_user=inputs_show_user,
|
||||||
|
llm_kwargs=llm_kwargs, chatbot=chatbot, history=history,
|
||||||
|
sys_prompt= r"You are a programmer."
|
||||||
|
)
|
||||||
|
code_to_return = gpt_say
|
||||||
|
history.extend([i_say, gpt_say])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
|
||||||
|
|
||||||
|
# # 第三步
|
||||||
|
# i_say = "Please list to packages to install to run the code above. Then show me how to use `try_install_deps` function to install them."
|
||||||
|
# i_say += 'For instance. `try_install_deps(["opencv-python", "scipy", "numpy"])`'
|
||||||
|
# installation_advance = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
||||||
|
# inputs=i_say, inputs_show_user=inputs_show_user,
|
||||||
|
# llm_kwargs=llm_kwargs, chatbot=chatbot, history=history,
|
||||||
|
# sys_prompt= r"You are a programmer."
|
||||||
|
# )
|
||||||
|
# # # 第三步
|
||||||
|
# i_say = "Show me how to use `pip` to install packages to run the code above. "
|
||||||
|
# i_say += 'For instance. `pip install -r opencv-python scipy numpy`'
|
||||||
|
# installation_advance = 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= r"You are a programmer."
|
||||||
|
# )
|
||||||
|
installation_advance = ""
|
||||||
|
|
||||||
|
return code_to_return, installation_advance, txt, file_type, llm_kwargs, chatbot, history
|
||||||
|
|
||||||
|
def make_module(code):
|
||||||
|
module_file = 'gpt_fn_' + gen_time_str().replace('-','_')
|
||||||
|
with open(f'{get_log_folder()}/{module_file}.py', 'w', encoding='utf8') as f:
|
||||||
|
f.write(code)
|
||||||
|
|
||||||
|
def get_class_name(class_string):
|
||||||
|
import re
|
||||||
|
# Use regex to extract the class name
|
||||||
|
class_name = re.search(r'class (\w+)\(', class_string).group(1)
|
||||||
|
return class_name
|
||||||
|
|
||||||
|
class_name = get_class_name(code)
|
||||||
|
return f"{get_log_folder().replace('/', '.')}.{module_file}->{class_name}"
|
||||||
|
|
||||||
|
def init_module_instance(module):
|
||||||
|
import importlib
|
||||||
|
module_, class_ = module.split('->')
|
||||||
|
init_f = getattr(importlib.import_module(module_), class_)
|
||||||
|
return init_f()
|
||||||
|
|
||||||
|
def for_immediate_show_off_when_possible(file_type, fp, chatbot):
|
||||||
|
if file_type in ['png', 'jpg']:
|
||||||
|
image_path = os.path.abspath(fp)
|
||||||
|
chatbot.append(['这是一张图片, 展示如下:',
|
||||||
|
f'本地文件地址: <br/>`{image_path}`<br/>'+
|
||||||
|
f'本地文件预览: <br/><div align="center"><img src="file={image_path}"></div>'
|
||||||
|
])
|
||||||
|
return chatbot
|
||||||
|
|
||||||
|
def subprocess_worker(instance, file_path, return_dict):
|
||||||
|
return_dict['result'] = instance.run(file_path)
|
||||||
|
|
||||||
|
def have_any_recent_upload_files(chatbot):
|
||||||
|
_5min = 5 * 60
|
||||||
|
if not chatbot: return False # chatbot is None
|
||||||
|
most_recent_uploaded = chatbot._cookies.get("most_recent_uploaded", None)
|
||||||
|
if not most_recent_uploaded: return False # most_recent_uploaded is None
|
||||||
|
if time.time() - most_recent_uploaded["time"] < _5min: return True # most_recent_uploaded is new
|
||||||
|
else: return False # most_recent_uploaded is too old
|
||||||
|
|
||||||
|
def get_recent_file_prompt_support(chatbot):
|
||||||
|
most_recent_uploaded = chatbot._cookies.get("most_recent_uploaded", None)
|
||||||
|
path = most_recent_uploaded['path']
|
||||||
|
return path
|
||||||
|
|
||||||
|
@CatchException
|
||||||
|
def 虚空终端CodeInterpreter(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 当前软件运行的端口号
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# 清空历史,以免输入溢出
|
||||||
|
history = []; clear_file_downloadzone(chatbot)
|
||||||
|
|
||||||
|
# 基本信息:功能、贡献者
|
||||||
|
chatbot.append([
|
||||||
|
"函数插件功能?",
|
||||||
|
"CodeInterpreter开源版, 此插件处于开发阶段, 建议暂时不要使用, 插件初始化中 ..."
|
||||||
|
])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
if have_any_recent_upload_files(chatbot):
|
||||||
|
file_path = get_recent_file_prompt_support(chatbot)
|
||||||
|
else:
|
||||||
|
chatbot.append(["文件检索", "没有发现任何近期上传的文件。"])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
# 读取文件
|
||||||
|
if ("recently_uploaded_files" in plugin_kwargs) and (plugin_kwargs["recently_uploaded_files"] == ""): plugin_kwargs.pop("recently_uploaded_files")
|
||||||
|
recently_uploaded_files = plugin_kwargs.get("recently_uploaded_files", None)
|
||||||
|
file_path = recently_uploaded_files[-1]
|
||||||
|
file_type = file_path.split('.')[-1]
|
||||||
|
|
||||||
|
# 粗心检查
|
||||||
|
if is_the_upload_folder(txt):
|
||||||
|
chatbot.append([
|
||||||
|
"...",
|
||||||
|
f"请在输入框内填写需求,然后再次点击该插件(文件路径 {file_path} 已经被记忆)"
|
||||||
|
])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
return
|
||||||
|
|
||||||
|
# 开始干正事
|
||||||
|
for j in range(5): # 最多重试5次
|
||||||
|
try:
|
||||||
|
code, installation_advance, txt, file_type, llm_kwargs, chatbot, history = \
|
||||||
|
yield from gpt_interact_multi_step(txt, file_type, llm_kwargs, chatbot, history)
|
||||||
|
code = get_code_block(code)
|
||||||
|
res = make_module(code)
|
||||||
|
instance = init_module_instance(res)
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
chatbot.append([f"第{j}次代码生成尝试,失败了", f"错误追踪\n```\n{trimmed_format_exc()}\n```\n"])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
# 代码生成结束, 开始执行
|
||||||
|
try:
|
||||||
|
import multiprocessing
|
||||||
|
manager = multiprocessing.Manager()
|
||||||
|
return_dict = manager.dict()
|
||||||
|
|
||||||
|
p = multiprocessing.Process(target=subprocess_worker, args=(instance, file_path, return_dict))
|
||||||
|
# only has 10 seconds to run
|
||||||
|
p.start(); p.join(timeout=10)
|
||||||
|
if p.is_alive(): p.terminate(); p.join()
|
||||||
|
p.close()
|
||||||
|
res = return_dict['result']
|
||||||
|
# res = instance.run(file_path)
|
||||||
|
except Exception as e:
|
||||||
|
chatbot.append(["执行失败了", f"错误追踪\n```\n{trimmed_format_exc()}\n```\n"])
|
||||||
|
# chatbot.append(["如果是缺乏依赖,请参考以下建议", installation_advance])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
return
|
||||||
|
|
||||||
|
# 顺利完成,收尾
|
||||||
|
res = str(res)
|
||||||
|
if os.path.exists(res):
|
||||||
|
chatbot.append(["执行成功了,结果是一个有效文件", "结果:" + res])
|
||||||
|
new_file_path = promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
|
chatbot = for_immediate_show_off_when_possible(file_type, new_file_path, chatbot)
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
|
||||||
|
else:
|
||||||
|
chatbot.append(["执行成功了,结果是一个字符串", "结果:" + res])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
|
||||||
|
|
||||||
|
"""
|
||||||
|
测试:
|
||||||
|
裁剪图像,保留下半部分
|
||||||
|
交换图像的蓝色通道和红色通道
|
||||||
|
将图像转为灰度图像
|
||||||
|
将csv文件转excel表格
|
||||||
|
"""
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from toolbox import CatchException, update_ui, ProxyNetworkActivate
|
from toolbox import CatchException, update_ui, ProxyNetworkActivate, update_ui_lastest_msg
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive, get_files_from_everything
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive, get_files_from_everything
|
||||||
|
|
||||||
|
|
||||||
@@ -15,7 +15,12 @@ def 知识库问答(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_pro
|
|||||||
web_port 当前软件运行的端口号
|
web_port 当前软件运行的端口号
|
||||||
"""
|
"""
|
||||||
history = [] # 清空历史,以免输入溢出
|
history = [] # 清空历史,以免输入溢出
|
||||||
chatbot.append(("这是什么功能?", "[Local Message] 从一批文件(txt, md, tex)中读取数据构建知识库, 然后进行问答。"))
|
|
||||||
|
# < --------------------读取参数--------------- >
|
||||||
|
if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg")
|
||||||
|
kai_id = plugin_kwargs.get("advanced_arg", 'default')
|
||||||
|
|
||||||
|
chatbot.append((f"向`{kai_id}`知识库中添加文件。", "[Local Message] 从一批文件(txt, md, tex)中读取数据构建知识库, 然后进行问答。"))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
# resolve deps
|
# resolve deps
|
||||||
@@ -24,17 +29,12 @@ def 知识库问答(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_pro
|
|||||||
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
|
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
|
||||||
from .crazy_utils import knowledge_archive_interface
|
from .crazy_utils import knowledge_archive_interface
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
chatbot.append(
|
chatbot.append(["依赖不足", "导入依赖失败。正在尝试自动安装,请查看终端的输出或耐心等待..."])
|
||||||
["依赖不足",
|
|
||||||
"导入依赖失败。正在尝试自动安装,请查看终端的输出或耐心等待..."]
|
|
||||||
)
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
from .crazy_utils import try_install_deps
|
from .crazy_utils import try_install_deps
|
||||||
try_install_deps(['zh_langchain==0.2.1', 'pypinyin'])
|
try_install_deps(['zh_langchain==0.2.1', 'pypinyin'], reload_m=['pypinyin', 'zh_langchain'])
|
||||||
|
yield from update_ui_lastest_msg("安装完成,您可以再次重试。", chatbot, history)
|
||||||
# < --------------------读取参数--------------- >
|
return
|
||||||
if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg")
|
|
||||||
kai_id = plugin_kwargs.get("advanced_arg", 'default')
|
|
||||||
|
|
||||||
# < --------------------读取文件--------------- >
|
# < --------------------读取文件--------------- >
|
||||||
file_manifest = []
|
file_manifest = []
|
||||||
@@ -53,14 +53,14 @@ def 知识库问答(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_pro
|
|||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
print('Checking Text2vec ...')
|
print('Checking Text2vec ...')
|
||||||
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
|
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
|
||||||
with ProxyNetworkActivate(): # 临时地激活代理网络
|
with ProxyNetworkActivate('Download_LLM'): # 临时地激活代理网络
|
||||||
HuggingFaceEmbeddings(model_name="GanymedeNil/text2vec-large-chinese")
|
HuggingFaceEmbeddings(model_name="GanymedeNil/text2vec-large-chinese")
|
||||||
|
|
||||||
# < -------------------构建知识库--------------- >
|
# < -------------------构建知识库--------------- >
|
||||||
chatbot.append(['<br/>'.join(file_manifest), "正在构建知识库..."])
|
chatbot.append(['<br/>'.join(file_manifest), "正在构建知识库..."])
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
print('Establishing knowledge archive ...')
|
print('Establishing knowledge archive ...')
|
||||||
with ProxyNetworkActivate(): # 临时地激活代理网络
|
with ProxyNetworkActivate('Download_LLM'): # 临时地激活代理网络
|
||||||
kai = knowledge_archive_interface()
|
kai = knowledge_archive_interface()
|
||||||
kai.feed_archive(file_manifest=file_manifest, id=kai_id)
|
kai.feed_archive(file_manifest=file_manifest, id=kai_id)
|
||||||
kai_files = kai.get_loaded_file()
|
kai_files = kai.get_loaded_file()
|
||||||
@@ -84,19 +84,18 @@ def 读取知识库作答(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst
|
|||||||
chatbot.append(["依赖不足", "导入依赖失败。正在尝试自动安装,请查看终端的输出或耐心等待..."])
|
chatbot.append(["依赖不足", "导入依赖失败。正在尝试自动安装,请查看终端的输出或耐心等待..."])
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
from .crazy_utils import try_install_deps
|
from .crazy_utils import try_install_deps
|
||||||
try_install_deps(['zh_langchain==0.2.1'])
|
try_install_deps(['zh_langchain==0.2.1', 'pypinyin'], reload_m=['pypinyin', 'zh_langchain'])
|
||||||
|
yield from update_ui_lastest_msg("安装完成,您可以再次重试。", chatbot, history)
|
||||||
|
return
|
||||||
|
|
||||||
# < ------------------- --------------- >
|
# < ------------------- --------------- >
|
||||||
kai = knowledge_archive_interface()
|
kai = knowledge_archive_interface()
|
||||||
|
|
||||||
if 'langchain_plugin_embedding' in chatbot._cookies:
|
if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg")
|
||||||
resp, prompt = kai.answer_with_archive_by_id(txt, chatbot._cookies['langchain_plugin_embedding'])
|
kai_id = plugin_kwargs.get("advanced_arg", 'default')
|
||||||
else:
|
resp, prompt = kai.answer_with_archive_by_id(txt, kai_id)
|
||||||
if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg")
|
|
||||||
kai_id = plugin_kwargs.get("advanced_arg", 'default')
|
|
||||||
resp, prompt = kai.answer_with_archive_by_id(txt, kai_id)
|
|
||||||
|
|
||||||
chatbot.append((txt, '[Local Message] ' + prompt))
|
chatbot.append((txt, f'[知识库 {kai_id}] ' + prompt))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新
|
||||||
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
||||||
inputs=prompt, inputs_show_user=txt,
|
inputs=prompt, inputs_show_user=txt,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from toolbox import update_ui, trimmed_format_exc
|
from toolbox import update_ui, trimmed_format_exc, promote_file_to_downloadzone, get_log_folder
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file, zip_folder
|
from toolbox import CatchException, report_execption, write_history_to_file, zip_folder
|
||||||
|
|
||||||
|
|
||||||
class PaperFileGroup():
|
class PaperFileGroup():
|
||||||
@@ -51,7 +51,7 @@ class PaperFileGroup():
|
|||||||
import os, time
|
import os, time
|
||||||
folder = os.path.dirname(self.file_paths[0])
|
folder = os.path.dirname(self.file_paths[0])
|
||||||
t = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
t = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
||||||
zip_folder(folder, './gpt_log/', f'{t}-polished.zip')
|
zip_folder(folder, get_log_folder(), f'{t}-polished.zip')
|
||||||
|
|
||||||
|
|
||||||
def 多文件润色(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, language='en', mode='polish'):
|
def 多文件润色(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, language='en', mode='polish'):
|
||||||
@@ -126,7 +126,9 @@ def 多文件润色(file_manifest, project_folder, llm_kwargs, plugin_kwargs, ch
|
|||||||
|
|
||||||
# <-------- 整理结果,退出 ---------->
|
# <-------- 整理结果,退出 ---------->
|
||||||
create_report_file_name = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + f"-chatgpt.polish.md"
|
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)
|
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
|
history = gpt_response_collection
|
||||||
chatbot.append((f"{fp}完成了吗?", res))
|
chatbot.append((f"{fp}完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
@@ -137,7 +139,7 @@ def Latex英文润色(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_p
|
|||||||
# 基本信息:功能、贡献者
|
# 基本信息:功能、贡献者
|
||||||
chatbot.append([
|
chatbot.append([
|
||||||
"函数插件功能?",
|
"函数插件功能?",
|
||||||
"对整个Latex项目进行润色。函数插件贡献者: Binary-Husky"])
|
"对整个Latex项目进行润色。函数插件贡献者: Binary-Husky。(注意,此插件不调用Latex,如果有Latex环境,请使用“Latex英文纠错+高亮”插件)"])
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
# 尝试导入依赖,如果缺少依赖,则给出安装建议
|
# 尝试导入依赖,如果缺少依赖,则给出安装建议
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from toolbox import update_ui
|
from toolbox import update_ui, promote_file_to_downloadzone
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption, write_history_to_file
|
||||||
fast_debug = False
|
fast_debug = False
|
||||||
|
|
||||||
class PaperFileGroup():
|
class PaperFileGroup():
|
||||||
@@ -95,7 +95,8 @@ def 多文件翻译(file_manifest, project_folder, llm_kwargs, plugin_kwargs, ch
|
|||||||
|
|
||||||
# <-------- 整理结果,退出 ---------->
|
# <-------- 整理结果,退出 ---------->
|
||||||
create_report_file_name = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + f"-chatgpt.polish.md"
|
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)
|
res = write_history_to_file(gpt_response_collection, create_report_file_name)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
history = gpt_response_collection
|
history = gpt_response_collection
|
||||||
chatbot.append((f"{fp}完成了吗?", res))
|
chatbot.append((f"{fp}完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from toolbox import update_ui, trimmed_format_exc, get_conf, objdump, objload, promote_file_to_downloadzone
|
from toolbox import update_ui, trimmed_format_exc, get_conf, get_log_folder, promote_file_to_downloadzone
|
||||||
from toolbox import CatchException, report_execption, update_ui_lastest_msg, zip_result, gen_time_str
|
from toolbox import CatchException, report_execption, update_ui_lastest_msg, zip_result, gen_time_str
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import glob, os, requests, time
|
import glob, os, requests, time
|
||||||
@@ -65,7 +65,7 @@ def move_project(project_folder, arxiv_id=None):
|
|||||||
if arxiv_id is not None:
|
if arxiv_id is not None:
|
||||||
new_workfolder = pj(ARXIV_CACHE_DIR, arxiv_id, 'workfolder')
|
new_workfolder = pj(ARXIV_CACHE_DIR, arxiv_id, 'workfolder')
|
||||||
else:
|
else:
|
||||||
new_workfolder = f'gpt_log/{gen_time_str()}'
|
new_workfolder = f'{get_log_folder()}/{gen_time_str()}'
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(new_workfolder)
|
shutil.rmtree(new_workfolder)
|
||||||
except:
|
except:
|
||||||
@@ -79,7 +79,7 @@ def move_project(project_folder, arxiv_id=None):
|
|||||||
shutil.copytree(src=project_folder, dst=new_workfolder)
|
shutil.copytree(src=project_folder, dst=new_workfolder)
|
||||||
return new_workfolder
|
return new_workfolder
|
||||||
|
|
||||||
def arxiv_download(chatbot, history, txt):
|
def arxiv_download(chatbot, history, txt, allow_cache=True):
|
||||||
def check_cached_translation_pdf(arxiv_id):
|
def check_cached_translation_pdf(arxiv_id):
|
||||||
translation_dir = pj(ARXIV_CACHE_DIR, arxiv_id, 'translation')
|
translation_dir = pj(ARXIV_CACHE_DIR, arxiv_id, 'translation')
|
||||||
if not os.path.exists(translation_dir):
|
if not os.path.exists(translation_dir):
|
||||||
@@ -109,14 +109,14 @@ def arxiv_download(chatbot, history, txt):
|
|||||||
|
|
||||||
url_ = txt # https://arxiv.org/abs/1707.06690
|
url_ = txt # https://arxiv.org/abs/1707.06690
|
||||||
if not txt.startswith('https://arxiv.org/abs/'):
|
if not txt.startswith('https://arxiv.org/abs/'):
|
||||||
msg = f"解析arxiv网址失败, 期望格式例如: https://arxiv.org/abs/1707.06690。实际得到格式: {url_}"
|
msg = f"解析arxiv网址失败, 期望格式例如: https://arxiv.org/abs/1707.06690。实际得到格式: {url_}。"
|
||||||
yield from update_ui_lastest_msg(msg, chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui_lastest_msg(msg, chatbot=chatbot, history=history) # 刷新界面
|
||||||
return msg, None
|
return msg, None
|
||||||
# <-------------- set format ------------->
|
# <-------------- set format ------------->
|
||||||
arxiv_id = url_.split('/abs/')[-1]
|
arxiv_id = url_.split('/abs/')[-1]
|
||||||
if 'v' in arxiv_id: arxiv_id = arxiv_id[:10]
|
if 'v' in arxiv_id: arxiv_id = arxiv_id[:10]
|
||||||
cached_translation_pdf = check_cached_translation_pdf(arxiv_id)
|
cached_translation_pdf = check_cached_translation_pdf(arxiv_id)
|
||||||
if cached_translation_pdf: return cached_translation_pdf, arxiv_id
|
if cached_translation_pdf and allow_cache: return cached_translation_pdf, arxiv_id
|
||||||
|
|
||||||
url_tar = url_.replace('/abs/', '/e-print/')
|
url_tar = url_.replace('/abs/', '/e-print/')
|
||||||
translation_dir = pj(ARXIV_CACHE_DIR, arxiv_id, 'e-print')
|
translation_dir = pj(ARXIV_CACHE_DIR, arxiv_id, 'e-print')
|
||||||
@@ -228,6 +228,9 @@ def Latex翻译中文并重新编译PDF(txt, llm_kwargs, plugin_kwargs, chatbot,
|
|||||||
# <-------------- more requirements ------------->
|
# <-------------- more requirements ------------->
|
||||||
if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg")
|
if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg")
|
||||||
more_req = plugin_kwargs.get("advanced_arg", "")
|
more_req = plugin_kwargs.get("advanced_arg", "")
|
||||||
|
no_cache = more_req.startswith("--no-cache")
|
||||||
|
if no_cache: more_req.lstrip("--no-cache")
|
||||||
|
allow_cache = not no_cache
|
||||||
_switch_prompt_ = partial(switch_prompt, more_requirement=more_req)
|
_switch_prompt_ = partial(switch_prompt, more_requirement=more_req)
|
||||||
|
|
||||||
# <-------------- check deps ------------->
|
# <-------------- check deps ------------->
|
||||||
@@ -244,7 +247,7 @@ def Latex翻译中文并重新编译PDF(txt, llm_kwargs, plugin_kwargs, chatbot,
|
|||||||
|
|
||||||
# <-------------- clear history and read input ------------->
|
# <-------------- clear history and read input ------------->
|
||||||
history = []
|
history = []
|
||||||
txt, arxiv_id = yield from arxiv_download(chatbot, history, txt)
|
txt, arxiv_id = yield from arxiv_download(chatbot, history, txt, allow_cache)
|
||||||
if txt.endswith('.pdf'):
|
if txt.endswith('.pdf'):
|
||||||
report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"发现已经存在翻译好的PDF文档")
|
report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"发现已经存在翻译好的PDF文档")
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
@@ -255,7 +258,7 @@ def Latex翻译中文并重新编译PDF(txt, llm_kwargs, plugin_kwargs, chatbot,
|
|||||||
project_folder = txt
|
project_folder = txt
|
||||||
else:
|
else:
|
||||||
if txt == "": txt = '空空如也的输入栏'
|
if txt == "": txt = '空空如也的输入栏'
|
||||||
report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到本地项目或无权访问: {txt}")
|
report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到本地项目或无法处理: {txt}")
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
from toolbox import update_ui, get_conf, trimmed_format_exc
|
from toolbox import update_ui, get_conf, trimmed_format_exc, get_log_folder
|
||||||
import threading
|
import threading
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
def input_clipping(inputs, history, max_token_limit):
|
def input_clipping(inputs, history, max_token_limit):
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@@ -67,12 +69,15 @@ def request_gpt_model_in_new_thread_with_ui_alive(
|
|||||||
yield from update_ui(chatbot=chatbot, history=[]) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=[]) # 刷新界面
|
||||||
executor = ThreadPoolExecutor(max_workers=16)
|
executor = ThreadPoolExecutor(max_workers=16)
|
||||||
mutable = ["", time.time(), ""]
|
mutable = ["", time.time(), ""]
|
||||||
|
# 看门狗耐心
|
||||||
|
watch_dog_patience = 5
|
||||||
|
# 请求任务
|
||||||
def _req_gpt(inputs, history, sys_prompt):
|
def _req_gpt(inputs, history, sys_prompt):
|
||||||
retry_op = retry_times_at_unknown_error
|
retry_op = retry_times_at_unknown_error
|
||||||
exceeded_cnt = 0
|
exceeded_cnt = 0
|
||||||
while True:
|
while True:
|
||||||
# watchdog error
|
# watchdog error
|
||||||
if len(mutable) >= 2 and (time.time()-mutable[1]) > 5:
|
if len(mutable) >= 2 and (time.time()-mutable[1]) > watch_dog_patience:
|
||||||
raise RuntimeError("检测到程序终止。")
|
raise RuntimeError("检测到程序终止。")
|
||||||
try:
|
try:
|
||||||
# 【第一种情况】:顺利完成
|
# 【第一种情况】:顺利完成
|
||||||
@@ -191,6 +196,9 @@ def request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency(
|
|||||||
# 跨线程传递
|
# 跨线程传递
|
||||||
mutable = [["", time.time(), "等待中"] for _ in range(n_frag)]
|
mutable = [["", time.time(), "等待中"] for _ in range(n_frag)]
|
||||||
|
|
||||||
|
# 看门狗耐心
|
||||||
|
watch_dog_patience = 5
|
||||||
|
|
||||||
# 子线程任务
|
# 子线程任务
|
||||||
def _req_gpt(index, inputs, history, sys_prompt):
|
def _req_gpt(index, inputs, history, sys_prompt):
|
||||||
gpt_say = ""
|
gpt_say = ""
|
||||||
@@ -199,7 +207,7 @@ def request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency(
|
|||||||
mutable[index][2] = "执行中"
|
mutable[index][2] = "执行中"
|
||||||
while True:
|
while True:
|
||||||
# watchdog error
|
# watchdog error
|
||||||
if len(mutable[index]) >= 2 and (time.time()-mutable[index][1]) > 5:
|
if len(mutable[index]) >= 2 and (time.time()-mutable[index][1]) > watch_dog_patience:
|
||||||
raise RuntimeError("检测到程序终止。")
|
raise RuntimeError("检测到程序终止。")
|
||||||
try:
|
try:
|
||||||
# 【第一种情况】:顺利完成
|
# 【第一种情况】:顺利完成
|
||||||
@@ -273,7 +281,7 @@ def request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency(
|
|||||||
# 在前端打印些好玩的东西
|
# 在前端打印些好玩的东西
|
||||||
for thread_index, _ in enumerate(worker_done):
|
for thread_index, _ in enumerate(worker_done):
|
||||||
print_something_really_funny = "[ ...`"+mutable[thread_index][0][-scroller_max_len:].\
|
print_something_really_funny = "[ ...`"+mutable[thread_index][0][-scroller_max_len:].\
|
||||||
replace('\n', '').replace('```', '...').replace(
|
replace('\n', '').replace('`', '.').replace(
|
||||||
' ', '.').replace('<br/>', '.....').replace('$', '.')+"`... ]"
|
' ', '.').replace('<br/>', '.....').replace('$', '.')+"`... ]"
|
||||||
observe_win.append(print_something_really_funny)
|
observe_win.append(print_something_really_funny)
|
||||||
# 在前端打印些好玩的东西
|
# 在前端打印些好玩的东西
|
||||||
@@ -299,7 +307,7 @@ def request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency(
|
|||||||
gpt_res = f.result()
|
gpt_res = f.result()
|
||||||
chatbot.append([inputs_show_user, gpt_res])
|
chatbot.append([inputs_show_user, gpt_res])
|
||||||
yield from update_ui(chatbot=chatbot, history=[]) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=[]) # 刷新界面
|
||||||
time.sleep(0.3)
|
time.sleep(0.5)
|
||||||
return gpt_response_collection
|
return gpt_response_collection
|
||||||
|
|
||||||
|
|
||||||
@@ -469,14 +477,16 @@ def read_and_clean_pdf_text(fp):
|
|||||||
'- ', '') for t in text_areas['blocks'] if 'lines' in t]
|
'- ', '') for t in text_areas['blocks'] if 'lines' in t]
|
||||||
|
|
||||||
############################## <第 2 步,获取正文主字体> ##################################
|
############################## <第 2 步,获取正文主字体> ##################################
|
||||||
fsize_statiscs = {}
|
try:
|
||||||
for span in meta_span:
|
fsize_statiscs = {}
|
||||||
if span[1] not in fsize_statiscs: fsize_statiscs[span[1]] = 0
|
for span in meta_span:
|
||||||
fsize_statiscs[span[1]] += span[2]
|
if span[1] not in fsize_statiscs: fsize_statiscs[span[1]] = 0
|
||||||
main_fsize = max(fsize_statiscs, key=fsize_statiscs.get)
|
fsize_statiscs[span[1]] += span[2]
|
||||||
if REMOVE_FOOT_NOTE:
|
main_fsize = max(fsize_statiscs, key=fsize_statiscs.get)
|
||||||
give_up_fize_threshold = main_fsize * REMOVE_FOOT_FFSIZE_PERCENT
|
if REMOVE_FOOT_NOTE:
|
||||||
|
give_up_fize_threshold = main_fsize * REMOVE_FOOT_FFSIZE_PERCENT
|
||||||
|
except:
|
||||||
|
raise RuntimeError(f'抱歉, 我们暂时无法解析此PDF文档: {fp}。')
|
||||||
############################## <第 3 步,切分和重新整合> ##################################
|
############################## <第 3 步,切分和重新整合> ##################################
|
||||||
mega_sec = []
|
mega_sec = []
|
||||||
sec = []
|
sec = []
|
||||||
@@ -591,11 +601,16 @@ def get_files_from_everything(txt, type): # type='.md'
|
|||||||
# 网络的远程文件
|
# 网络的远程文件
|
||||||
import requests
|
import requests
|
||||||
from toolbox import get_conf
|
from toolbox import get_conf
|
||||||
|
from toolbox import get_log_folder, gen_time_str
|
||||||
proxies, = get_conf('proxies')
|
proxies, = get_conf('proxies')
|
||||||
r = requests.get(txt, proxies=proxies)
|
try:
|
||||||
with open('./gpt_log/temp'+type, 'wb+') as f: f.write(r.content)
|
r = requests.get(txt, proxies=proxies)
|
||||||
project_folder = './gpt_log/'
|
except:
|
||||||
file_manifest = ['./gpt_log/temp'+type]
|
raise ConnectionRefusedError(f"无法下载资源{txt},请检查。")
|
||||||
|
path = os.path.join(get_log_folder(plugin_name='web_download'), gen_time_str()+type)
|
||||||
|
with open(path, 'wb+') as f: f.write(r.content)
|
||||||
|
project_folder = get_log_folder(plugin_name='web_download')
|
||||||
|
file_manifest = [path]
|
||||||
elif txt.endswith(type):
|
elif txt.endswith(type):
|
||||||
# 直接给定文件
|
# 直接给定文件
|
||||||
file_manifest = [txt]
|
file_manifest = [txt]
|
||||||
@@ -642,7 +657,7 @@ class knowledge_archive_interface():
|
|||||||
from toolbox import ProxyNetworkActivate
|
from toolbox import ProxyNetworkActivate
|
||||||
print('Checking Text2vec ...')
|
print('Checking Text2vec ...')
|
||||||
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
|
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
|
||||||
with ProxyNetworkActivate(): # 临时地激活代理网络
|
with ProxyNetworkActivate('Download_LLM'): # 临时地激活代理网络
|
||||||
self.text2vec_large_chinese = HuggingFaceEmbeddings(model_name="GanymedeNil/text2vec-large-chinese")
|
self.text2vec_large_chinese = HuggingFaceEmbeddings(model_name="GanymedeNil/text2vec-large-chinese")
|
||||||
|
|
||||||
return self.text2vec_large_chinese
|
return self.text2vec_large_chinese
|
||||||
@@ -698,49 +713,96 @@ class knowledge_archive_interface():
|
|||||||
)
|
)
|
||||||
self.threadLock.release()
|
self.threadLock.release()
|
||||||
return resp, prompt
|
return resp, prompt
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class nougat_interface():
|
||||||
|
def __init__(self):
|
||||||
|
self.threadLock = threading.Lock()
|
||||||
|
|
||||||
def try_install_deps(deps):
|
def nougat_with_timeout(self, command, cwd, timeout=3600):
|
||||||
|
import subprocess
|
||||||
|
logging.info(f'正在执行命令 {command}')
|
||||||
|
process = subprocess.Popen(command, shell=True, cwd=cwd)
|
||||||
|
try:
|
||||||
|
stdout, stderr = process.communicate(timeout=timeout)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
process.kill()
|
||||||
|
stdout, stderr = process.communicate()
|
||||||
|
print("Process timed out!")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def NOUGAT_parse_pdf(self, fp, chatbot, history):
|
||||||
|
from toolbox import update_ui_lastest_msg
|
||||||
|
|
||||||
|
yield from update_ui_lastest_msg("正在解析论文, 请稍候。进度:正在排队, 等待线程锁...",
|
||||||
|
chatbot=chatbot, history=history, delay=0)
|
||||||
|
self.threadLock.acquire()
|
||||||
|
import glob, threading, os
|
||||||
|
from toolbox import get_log_folder, gen_time_str
|
||||||
|
dst = os.path.join(get_log_folder(plugin_name='nougat'), gen_time_str())
|
||||||
|
os.makedirs(dst)
|
||||||
|
|
||||||
|
yield from update_ui_lastest_msg("正在解析论文, 请稍候。进度:正在加载NOUGAT... (提示:首次运行需要花费较长时间下载NOUGAT参数)",
|
||||||
|
chatbot=chatbot, history=history, delay=0)
|
||||||
|
self.nougat_with_timeout(f'nougat --out "{os.path.abspath(dst)}" "{os.path.abspath(fp)}"', os.getcwd(), timeout=3600)
|
||||||
|
res = glob.glob(os.path.join(dst,'*.mmd'))
|
||||||
|
if len(res) == 0:
|
||||||
|
self.threadLock.release()
|
||||||
|
raise RuntimeError("Nougat解析论文失败。")
|
||||||
|
self.threadLock.release()
|
||||||
|
return res[0]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def try_install_deps(deps, reload_m=[]):
|
||||||
|
import subprocess, sys, importlib
|
||||||
for dep in deps:
|
for dep in deps:
|
||||||
import subprocess, sys
|
|
||||||
subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--user', dep])
|
subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--user', dep])
|
||||||
|
import site
|
||||||
|
importlib.reload(site)
|
||||||
|
for m in reload_m:
|
||||||
|
importlib.reload(__import__(m))
|
||||||
|
|
||||||
|
|
||||||
class construct_html():
|
HTML_CSS = """
|
||||||
def __init__(self) -> None:
|
|
||||||
self.css = """
|
|
||||||
.row {
|
.row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column {
|
.column {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-header {
|
.table-header {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border-bottom: 1px solid black;
|
border-bottom: 1px solid black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-row {
|
.table-row {
|
||||||
border-bottom: 1px solid lightgray;
|
border-bottom: 1px solid lightgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-cell {
|
.table-cell {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
self.html_string = f'<!DOCTYPE html><head><meta charset="utf-8"><title>翻译结果</title><style>{self.css}</style></head>'
|
|
||||||
|
|
||||||
|
TABLE_CSS = """
|
||||||
def add_row(self, a, b):
|
|
||||||
tmp = """
|
|
||||||
<div class="row table-row">
|
<div class="row table-row">
|
||||||
<div class="column table-cell">REPLACE_A</div>
|
<div class="column table-cell">REPLACE_A</div>
|
||||||
<div class="column table-cell">REPLACE_B</div>
|
<div class="column table-cell">REPLACE_B</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
class construct_html():
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.css = HTML_CSS
|
||||||
|
self.html_string = f'<!DOCTYPE html><head><meta charset="utf-8"><title>翻译结果</title><style>{self.css}</style></head>'
|
||||||
|
|
||||||
|
|
||||||
|
def add_row(self, a, b):
|
||||||
|
tmp = TABLE_CSS
|
||||||
from toolbox import markdown_convertion
|
from toolbox import markdown_convertion
|
||||||
tmp = tmp.replace('REPLACE_A', markdown_convertion(a))
|
tmp = tmp.replace('REPLACE_A', markdown_convertion(a))
|
||||||
tmp = tmp.replace('REPLACE_B', markdown_convertion(b))
|
tmp = tmp.replace('REPLACE_B', markdown_convertion(b))
|
||||||
@@ -748,6 +810,13 @@ class construct_html():
|
|||||||
|
|
||||||
|
|
||||||
def save_file(self, file_name):
|
def save_file(self, file_name):
|
||||||
with open(f'./gpt_log/{file_name}', 'w', encoding='utf8') as f:
|
with open(os.path.join(get_log_folder(), file_name), 'w', encoding='utf8') as f:
|
||||||
f.write(self.html_string.encode('utf-8', 'ignore').decode())
|
f.write(self.html_string.encode('utf-8', 'ignore').decode())
|
||||||
|
return os.path.join(get_log_folder(), file_name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_plugin_arg(plugin_kwargs, key, default):
|
||||||
|
# 如果参数是空的
|
||||||
|
if (key in plugin_kwargs) and (plugin_kwargs[key] == ""): plugin_kwargs.pop(key)
|
||||||
|
# 正常情况
|
||||||
|
return plugin_kwargs.get(key, default)
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import time
|
||||||
|
import importlib
|
||||||
|
from toolbox import trimmed_format_exc, gen_time_str, get_log_folder
|
||||||
|
from toolbox import CatchException, update_ui, gen_time_str, trimmed_format_exc, is_the_upload_folder
|
||||||
|
from toolbox import promote_file_to_downloadzone, get_log_folder, update_ui_lastest_msg
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
def get_class_name(class_string):
|
||||||
|
import re
|
||||||
|
# Use regex to extract the class name
|
||||||
|
class_name = re.search(r'class (\w+)\(', class_string).group(1)
|
||||||
|
return class_name
|
||||||
|
|
||||||
|
def try_make_module(code, chatbot):
|
||||||
|
module_file = 'gpt_fn_' + gen_time_str().replace('-','_')
|
||||||
|
fn_path = f'{get_log_folder(plugin_name="gen_plugin_verify")}/{module_file}.py'
|
||||||
|
with open(fn_path, 'w', encoding='utf8') as f: f.write(code)
|
||||||
|
promote_file_to_downloadzone(fn_path, chatbot=chatbot)
|
||||||
|
class_name = get_class_name(code)
|
||||||
|
manager = multiprocessing.Manager()
|
||||||
|
return_dict = manager.dict()
|
||||||
|
p = multiprocessing.Process(target=is_function_successfully_generated, args=(fn_path, class_name, return_dict))
|
||||||
|
# only has 10 seconds to run
|
||||||
|
p.start(); p.join(timeout=10)
|
||||||
|
if p.is_alive(): p.terminate(); p.join()
|
||||||
|
p.close()
|
||||||
|
return return_dict["success"], return_dict['traceback']
|
||||||
|
|
||||||
|
# check is_function_successfully_generated
|
||||||
|
def is_function_successfully_generated(fn_path, class_name, return_dict):
|
||||||
|
return_dict['success'] = False
|
||||||
|
return_dict['traceback'] = ""
|
||||||
|
try:
|
||||||
|
# Create a spec for the module
|
||||||
|
module_spec = importlib.util.spec_from_file_location('example_module', fn_path)
|
||||||
|
# Load the module
|
||||||
|
example_module = importlib.util.module_from_spec(module_spec)
|
||||||
|
module_spec.loader.exec_module(example_module)
|
||||||
|
# Now you can use the module
|
||||||
|
some_class = getattr(example_module, class_name)
|
||||||
|
# Now you can create an instance of the class
|
||||||
|
instance = some_class()
|
||||||
|
return_dict['success'] = True
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
return_dict['traceback'] = trimmed_format_exc()
|
||||||
|
return
|
||||||
|
|
||||||
|
def subprocess_worker(code, file_path, return_dict):
|
||||||
|
return_dict['result'] = None
|
||||||
|
return_dict['success'] = False
|
||||||
|
return_dict['traceback'] = ""
|
||||||
|
try:
|
||||||
|
module_file = 'gpt_fn_' + gen_time_str().replace('-','_')
|
||||||
|
fn_path = f'{get_log_folder(plugin_name="gen_plugin_run")}/{module_file}.py'
|
||||||
|
with open(fn_path, 'w', encoding='utf8') as f: f.write(code)
|
||||||
|
class_name = get_class_name(code)
|
||||||
|
# Create a spec for the module
|
||||||
|
module_spec = importlib.util.spec_from_file_location('example_module', fn_path)
|
||||||
|
# Load the module
|
||||||
|
example_module = importlib.util.module_from_spec(module_spec)
|
||||||
|
module_spec.loader.exec_module(example_module)
|
||||||
|
# Now you can use the module
|
||||||
|
some_class = getattr(example_module, class_name)
|
||||||
|
# Now you can create an instance of the class
|
||||||
|
instance = some_class()
|
||||||
|
return_dict['result'] = instance.run(file_path)
|
||||||
|
return_dict['success'] = True
|
||||||
|
except:
|
||||||
|
return_dict['traceback'] = trimmed_format_exc()
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from toolbox import update_ui, update_ui_lastest_msg # 刷新Gradio前端界面
|
from toolbox import update_ui, update_ui_lastest_msg, get_log_folder
|
||||||
from toolbox import zip_folder, objdump, objload, promote_file_to_downloadzone
|
from toolbox import zip_folder, objdump, objload, promote_file_to_downloadzone
|
||||||
from .latex_toolbox import PRESERVE, TRANSFORM
|
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 set_forbidden_text, set_forbidden_text_begin_end, set_forbidden_text_careful_brace
|
||||||
@@ -363,7 +363,7 @@ def 编译Latex(chatbot, history, main_file_original, main_file_modified, work_f
|
|||||||
if mode!='translate_zh':
|
if mode!='translate_zh':
|
||||||
yield from update_ui_lastest_msg(f'尝试第 {n_fix}/{max_try} 次编译, 使用latexdiff生成论文转化前后对比 ...', chatbot, history) # 刷新Gradio前端界面
|
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')
|
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')
|
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', os.getcwd())
|
||||||
|
|
||||||
yield from update_ui_lastest_msg(f'尝试第 {n_fix}/{max_try} 次编译, 正在编译对比PDF ...', chatbot, history) # 刷新Gradio前端界面
|
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'pdflatex -interaction=batchmode -file-line-error merge_diff.tex', work_folder)
|
||||||
@@ -439,9 +439,9 @@ def write_html(sp_file_contents, sp_file_result, chatbot, project_folder):
|
|||||||
trans = k
|
trans = k
|
||||||
ch.add_row(a=orig, b=trans)
|
ch.add_row(a=orig, b=trans)
|
||||||
create_report_file_name = f"{gen_time_str()}.trans.html"
|
create_report_file_name = f"{gen_time_str()}.trans.html"
|
||||||
ch.save_file(create_report_file_name)
|
res = ch.save_file(create_report_file_name)
|
||||||
shutil.copyfile(pj('./gpt_log/', create_report_file_name), pj(project_folder, create_report_file_name))
|
shutil.copyfile(res, pj(project_folder, create_report_file_name))
|
||||||
promote_file_to_downloadzone(file=f'./gpt_log/{create_report_file_name}', chatbot=chatbot)
|
promote_file_to_downloadzone(file=res, chatbot=chatbot)
|
||||||
except:
|
except:
|
||||||
from toolbox import trimmed_format_exc
|
from toolbox import trimmed_format_exc
|
||||||
print('writing html result failed:', trimmed_format_exc())
|
print('writing html result failed:', trimmed_format_exc())
|
||||||
|
|||||||
@@ -256,6 +256,7 @@ def find_main_tex_file(file_manifest, mode):
|
|||||||
canidates_score.append(0)
|
canidates_score.append(0)
|
||||||
with open(texf, 'r', encoding='utf8', errors='ignore') as f:
|
with open(texf, 'r', encoding='utf8', errors='ignore') as f:
|
||||||
file_content = f.read()
|
file_content = f.read()
|
||||||
|
file_content = rm_comments(file_content)
|
||||||
for uw in unexpected_words:
|
for uw in unexpected_words:
|
||||||
if uw in file_content:
|
if uw in file_content:
|
||||||
canidates_score[-1] -= 1
|
canidates_score[-1] -= 1
|
||||||
@@ -290,7 +291,11 @@ def find_tex_file_ignore_case(fp):
|
|||||||
import glob
|
import glob
|
||||||
for f in glob.glob(dir_name+'/*.tex'):
|
for f in glob.glob(dir_name+'/*.tex'):
|
||||||
base_name_s = os.path.basename(fp)
|
base_name_s = os.path.basename(fp)
|
||||||
if base_name_s.lower() == base_name.lower(): return f
|
base_name_f = os.path.basename(f)
|
||||||
|
if base_name_s.lower() == base_name_f.lower(): return f
|
||||||
|
# 试着加上.tex后缀试试
|
||||||
|
if not base_name_s.endswith('.tex'): base_name_s+='.tex'
|
||||||
|
if base_name_s.lower() == base_name_f.lower(): return f
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def merge_tex_files_(project_foler, main_file, mode):
|
def merge_tex_files_(project_foler, main_file, mode):
|
||||||
@@ -301,9 +306,9 @@ def merge_tex_files_(project_foler, main_file, mode):
|
|||||||
for s in reversed([q for q in re.finditer(r"\\input\{(.*?)\}", main_file, re.M)]):
|
for s in reversed([q for q in re.finditer(r"\\input\{(.*?)\}", main_file, re.M)]):
|
||||||
f = s.group(1)
|
f = s.group(1)
|
||||||
fp = os.path.join(project_foler, f)
|
fp = os.path.join(project_foler, f)
|
||||||
fp = find_tex_file_ignore_case(fp)
|
fp_ = find_tex_file_ignore_case(fp)
|
||||||
if fp:
|
if fp_:
|
||||||
with open(fp, 'r', encoding='utf-8', errors='replace') as fx: c = fx.read()
|
with open(fp_, 'r', encoding='utf-8', errors='replace') as fx: c = fx.read()
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f'找不到{fp},Tex源文件缺失!')
|
raise RuntimeError(f'找不到{fp},Tex源文件缺失!')
|
||||||
c = merge_tex_files_(project_foler, c, mode)
|
c = merge_tex_files_(project_foler, c, mode)
|
||||||
@@ -337,10 +342,33 @@ def merge_tex_files(project_foler, main_file, mode):
|
|||||||
pattern_opt2 = re.compile(r"\\abstract\{(.*?)\}", flags=re.DOTALL)
|
pattern_opt2 = re.compile(r"\\abstract\{(.*?)\}", flags=re.DOTALL)
|
||||||
match_opt1 = pattern_opt1.search(main_file)
|
match_opt1 = pattern_opt1.search(main_file)
|
||||||
match_opt2 = pattern_opt2.search(main_file)
|
match_opt2 = pattern_opt2.search(main_file)
|
||||||
|
if (match_opt1 is None) and (match_opt2 is None):
|
||||||
|
# "Cannot find paper abstract section!"
|
||||||
|
main_file = insert_abstract(main_file)
|
||||||
|
match_opt1 = pattern_opt1.search(main_file)
|
||||||
|
match_opt2 = pattern_opt2.search(main_file)
|
||||||
assert (match_opt1 is not None) or (match_opt2 is not None), "Cannot find paper abstract section!"
|
assert (match_opt1 is not None) or (match_opt2 is not None), "Cannot find paper abstract section!"
|
||||||
return main_file
|
return main_file
|
||||||
|
|
||||||
|
|
||||||
|
insert_missing_abs_str = r"""
|
||||||
|
\begin{abstract}
|
||||||
|
The GPT-Academic program cannot find abstract section in this paper.
|
||||||
|
\end{abstract}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def insert_abstract(tex_content):
|
||||||
|
if "\\maketitle" in tex_content:
|
||||||
|
# find the position of "\maketitle"
|
||||||
|
find_index = tex_content.index("\\maketitle")
|
||||||
|
# find the nearest ending line
|
||||||
|
end_line_index = tex_content.find("\n", find_index)
|
||||||
|
# insert "abs_str" on the next line
|
||||||
|
modified_tex = tex_content[:end_line_index+1] + '\n\n' + insert_missing_abs_str + '\n\n' + tex_content[end_line_index+1:]
|
||||||
|
return modified_tex
|
||||||
|
else:
|
||||||
|
return tex_content
|
||||||
|
|
||||||
"""
|
"""
|
||||||
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
Post process
|
Post process
|
||||||
@@ -423,7 +451,7 @@ def compile_latex_with_timeout(command, cwd, timeout=60):
|
|||||||
|
|
||||||
def merge_pdfs(pdf1_path, pdf2_path, output_path):
|
def merge_pdfs(pdf1_path, pdf2_path, output_path):
|
||||||
import PyPDF2
|
import PyPDF2
|
||||||
Percent = 0.8
|
Percent = 0.95
|
||||||
# Open the first PDF file
|
# Open the first PDF file
|
||||||
with open(pdf1_path, 'rb') as pdf1_file:
|
with open(pdf1_path, 'rb') as pdf1_file:
|
||||||
pdf1_reader = PyPDF2.PdfFileReader(pdf1_file)
|
pdf1_reader = PyPDF2.PdfFileReader(pdf1_file)
|
||||||
|
|||||||
@@ -1,4 +1,106 @@
|
|||||||
import time, threading, json
|
import time, logging, json, sys, struct
|
||||||
|
import numpy as np
|
||||||
|
from scipy.io.wavfile import WAVE_FORMAT
|
||||||
|
|
||||||
|
def write_numpy_to_wave(filename, rate, data, add_header=False):
|
||||||
|
"""
|
||||||
|
Write a NumPy array as a WAV file.
|
||||||
|
"""
|
||||||
|
def _array_tofile(fid, data):
|
||||||
|
# ravel gives a c-contiguous buffer
|
||||||
|
fid.write(data.ravel().view('b').data)
|
||||||
|
|
||||||
|
if hasattr(filename, 'write'):
|
||||||
|
fid = filename
|
||||||
|
else:
|
||||||
|
fid = open(filename, 'wb')
|
||||||
|
|
||||||
|
fs = rate
|
||||||
|
|
||||||
|
try:
|
||||||
|
dkind = data.dtype.kind
|
||||||
|
if not (dkind == 'i' or dkind == 'f' or (dkind == 'u' and
|
||||||
|
data.dtype.itemsize == 1)):
|
||||||
|
raise ValueError("Unsupported data type '%s'" % data.dtype)
|
||||||
|
|
||||||
|
header_data = b''
|
||||||
|
|
||||||
|
header_data += b'RIFF'
|
||||||
|
header_data += b'\x00\x00\x00\x00'
|
||||||
|
header_data += b'WAVE'
|
||||||
|
|
||||||
|
# fmt chunk
|
||||||
|
header_data += b'fmt '
|
||||||
|
if dkind == 'f':
|
||||||
|
format_tag = WAVE_FORMAT.IEEE_FLOAT
|
||||||
|
else:
|
||||||
|
format_tag = WAVE_FORMAT.PCM
|
||||||
|
if data.ndim == 1:
|
||||||
|
channels = 1
|
||||||
|
else:
|
||||||
|
channels = data.shape[1]
|
||||||
|
bit_depth = data.dtype.itemsize * 8
|
||||||
|
bytes_per_second = fs*(bit_depth // 8)*channels
|
||||||
|
block_align = channels * (bit_depth // 8)
|
||||||
|
|
||||||
|
fmt_chunk_data = struct.pack('<HHIIHH', format_tag, channels, fs,
|
||||||
|
bytes_per_second, block_align, bit_depth)
|
||||||
|
if not (dkind == 'i' or dkind == 'u'):
|
||||||
|
# add cbSize field for non-PCM files
|
||||||
|
fmt_chunk_data += b'\x00\x00'
|
||||||
|
|
||||||
|
header_data += struct.pack('<I', len(fmt_chunk_data))
|
||||||
|
header_data += fmt_chunk_data
|
||||||
|
|
||||||
|
# fact chunk (non-PCM files)
|
||||||
|
if not (dkind == 'i' or dkind == 'u'):
|
||||||
|
header_data += b'fact'
|
||||||
|
header_data += struct.pack('<II', 4, data.shape[0])
|
||||||
|
|
||||||
|
# check data size (needs to be immediately before the data chunk)
|
||||||
|
if ((len(header_data)-4-4) + (4+4+data.nbytes)) > 0xFFFFFFFF:
|
||||||
|
raise ValueError("Data exceeds wave file size limit")
|
||||||
|
if add_header:
|
||||||
|
fid.write(header_data)
|
||||||
|
# data chunk
|
||||||
|
fid.write(b'data')
|
||||||
|
fid.write(struct.pack('<I', data.nbytes))
|
||||||
|
if data.dtype.byteorder == '>' or (data.dtype.byteorder == '=' and
|
||||||
|
sys.byteorder == 'big'):
|
||||||
|
data = data.byteswap()
|
||||||
|
_array_tofile(fid, data)
|
||||||
|
|
||||||
|
if add_header:
|
||||||
|
# Determine file size and place it in correct
|
||||||
|
# position at start of the file.
|
||||||
|
size = fid.tell()
|
||||||
|
fid.seek(4)
|
||||||
|
fid.write(struct.pack('<I', size-8))
|
||||||
|
|
||||||
|
finally:
|
||||||
|
if not hasattr(filename, 'write'):
|
||||||
|
fid.close()
|
||||||
|
else:
|
||||||
|
fid.seek(0)
|
||||||
|
|
||||||
|
def is_speaker_speaking(vad, data, sample_rate):
|
||||||
|
# Function to detect if the speaker is speaking
|
||||||
|
# The WebRTC VAD only accepts 16-bit mono PCM audio,
|
||||||
|
# sampled at 8000, 16000, 32000 or 48000 Hz.
|
||||||
|
# A frame must be either 10, 20, or 30 ms in duration:
|
||||||
|
frame_duration = 30
|
||||||
|
n_bit_each = int(sample_rate * frame_duration / 1000)*2 # x2 because audio is 16 bit (2 bytes)
|
||||||
|
res_list = []
|
||||||
|
for t in range(len(data)):
|
||||||
|
if t!=0 and t % n_bit_each == 0:
|
||||||
|
res_list.append(vad.is_speech(data[t-n_bit_each:t], sample_rate))
|
||||||
|
|
||||||
|
info = ''.join(['^' if r else '.' for r in res_list])
|
||||||
|
info = info[:10]
|
||||||
|
if any(res_list):
|
||||||
|
return True, info
|
||||||
|
else:
|
||||||
|
return False, info
|
||||||
|
|
||||||
|
|
||||||
class AliyunASR():
|
class AliyunASR():
|
||||||
@@ -12,14 +114,14 @@ class AliyunASR():
|
|||||||
message = json.loads(message)
|
message = json.loads(message)
|
||||||
self.parsed_sentence = message['payload']['result']
|
self.parsed_sentence = message['payload']['result']
|
||||||
self.event_on_entence_end.set()
|
self.event_on_entence_end.set()
|
||||||
print(self.parsed_sentence)
|
# print(self.parsed_sentence)
|
||||||
|
|
||||||
def test_on_start(self, message, *args):
|
def test_on_start(self, message, *args):
|
||||||
# print("test_on_start:{}".format(message))
|
# print("test_on_start:{}".format(message))
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_on_error(self, message, *args):
|
def test_on_error(self, message, *args):
|
||||||
print("on_error args=>{}".format(args))
|
logging.error("on_error args=>{}".format(args))
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_on_close(self, *args):
|
def test_on_close(self, *args):
|
||||||
@@ -36,7 +138,6 @@ class AliyunASR():
|
|||||||
# print("on_completed:args=>{} message=>{}".format(args, message))
|
# print("on_completed:args=>{} message=>{}".format(args, message))
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def audio_convertion_thread(self, uuid):
|
def audio_convertion_thread(self, uuid):
|
||||||
# 在一个异步线程中采集音频
|
# 在一个异步线程中采集音频
|
||||||
import nls # pip install git+https://github.com/aliyun/alibabacloud-nls-python-sdk.git
|
import nls # pip install git+https://github.com/aliyun/alibabacloud-nls-python-sdk.git
|
||||||
@@ -67,12 +168,22 @@ class AliyunASR():
|
|||||||
on_close=self.test_on_close,
|
on_close=self.test_on_close,
|
||||||
callback_args=[uuid.hex]
|
callback_args=[uuid.hex]
|
||||||
)
|
)
|
||||||
|
timeout_limit_second = 20
|
||||||
r = sr.start(aformat="pcm",
|
r = sr.start(aformat="pcm",
|
||||||
|
timeout=timeout_limit_second,
|
||||||
enable_intermediate_result=True,
|
enable_intermediate_result=True,
|
||||||
enable_punctuation_prediction=True,
|
enable_punctuation_prediction=True,
|
||||||
enable_inverse_text_normalization=True)
|
enable_inverse_text_normalization=True)
|
||||||
|
|
||||||
|
import webrtcvad
|
||||||
|
vad = webrtcvad.Vad()
|
||||||
|
vad.set_mode(1)
|
||||||
|
|
||||||
|
is_previous_frame_transmitted = False # 上一帧是否有人说话
|
||||||
|
previous_frame_data = None
|
||||||
|
echo_cnt = 0 # 在没有声音之后,继续向服务器发送n次音频数据
|
||||||
|
echo_cnt_max = 4 # 在没有声音之后,继续向服务器发送n次音频数据
|
||||||
|
keep_alive_last_send_time = time.time()
|
||||||
while not self.stop:
|
while not self.stop:
|
||||||
# time.sleep(self.capture_interval)
|
# time.sleep(self.capture_interval)
|
||||||
audio = rad.read(uuid.hex)
|
audio = rad.read(uuid.hex)
|
||||||
@@ -80,12 +191,32 @@ class AliyunASR():
|
|||||||
# convert to pcm file
|
# convert to pcm file
|
||||||
temp_file = f'{temp_folder}/{uuid.hex}.pcm' #
|
temp_file = f'{temp_folder}/{uuid.hex}.pcm' #
|
||||||
dsdata = change_sample_rate(audio, rad.rate, NEW_SAMPLERATE) # 48000 --> 16000
|
dsdata = change_sample_rate(audio, rad.rate, NEW_SAMPLERATE) # 48000 --> 16000
|
||||||
io.wavfile.write(temp_file, NEW_SAMPLERATE, dsdata)
|
write_numpy_to_wave(temp_file, NEW_SAMPLERATE, dsdata)
|
||||||
# read pcm binary
|
# read pcm binary
|
||||||
with open(temp_file, "rb") as f: data = f.read()
|
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)
|
is_speaking, info = is_speaker_speaking(vad, data, NEW_SAMPLERATE)
|
||||||
slices = zip(*(iter(data),) * 640) # 640个字节为一组
|
|
||||||
for i in slices: sr.send_audio(bytes(i))
|
if is_speaking or echo_cnt > 0:
|
||||||
|
# 如果话筒激活 / 如果处于回声收尾阶段
|
||||||
|
echo_cnt -= 1
|
||||||
|
if not is_previous_frame_transmitted: # 上一帧没有人声,但是我们把上一帧同样加上
|
||||||
|
if previous_frame_data is not None: data = previous_frame_data + data
|
||||||
|
if is_speaking:
|
||||||
|
echo_cnt = echo_cnt_max
|
||||||
|
slices = zip(*(iter(data),) * 640) # 640个字节为一组
|
||||||
|
for i in slices: sr.send_audio(bytes(i))
|
||||||
|
keep_alive_last_send_time = time.time()
|
||||||
|
is_previous_frame_transmitted = True
|
||||||
|
else:
|
||||||
|
is_previous_frame_transmitted = False
|
||||||
|
echo_cnt = 0
|
||||||
|
# 保持链接激活,即使没有声音,也根据时间间隔,发送一些音频片段给服务器
|
||||||
|
if time.time() - keep_alive_last_send_time > timeout_limit_second/2:
|
||||||
|
slices = zip(*(iter(data),) * 640) # 640个字节为一组
|
||||||
|
for i in slices: sr.send_audio(bytes(i))
|
||||||
|
keep_alive_last_send_time = time.time()
|
||||||
|
is_previous_frame_transmitted = True
|
||||||
|
self.audio_shape = info
|
||||||
else:
|
else:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class RealtimeAudioDistribution():
|
|||||||
def read(self, uuid):
|
def read(self, uuid):
|
||||||
if uuid in self.data:
|
if uuid in self.data:
|
||||||
res = self.data.pop(uuid)
|
res = self.data.pop(uuid)
|
||||||
print('\r read-', len(res), '-', max(res), end='', flush=True)
|
# print('\r read-', len(res), '-', max(res), end='', flush=True)
|
||||||
else:
|
else:
|
||||||
res = None
|
res = None
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -1,16 +1,26 @@
|
|||||||
|
from functools import lru_cache
|
||||||
|
from toolbox import gen_time_str
|
||||||
|
from toolbox import promote_file_to_downloadzone
|
||||||
|
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||||
|
from toolbox import get_conf
|
||||||
|
from toolbox import ProxyNetworkActivate
|
||||||
|
from colorful import *
|
||||||
import requests
|
import requests
|
||||||
import random
|
import random
|
||||||
from functools import lru_cache
|
import copy
|
||||||
|
import os
|
||||||
|
import math
|
||||||
|
|
||||||
class GROBID_OFFLINE_EXCEPTION(Exception): pass
|
class GROBID_OFFLINE_EXCEPTION(Exception): pass
|
||||||
|
|
||||||
def get_avail_grobid_url():
|
def get_avail_grobid_url():
|
||||||
from toolbox import get_conf
|
|
||||||
GROBID_URLS, = get_conf('GROBID_URLS')
|
GROBID_URLS, = get_conf('GROBID_URLS')
|
||||||
if len(GROBID_URLS) == 0: return None
|
if len(GROBID_URLS) == 0: return None
|
||||||
try:
|
try:
|
||||||
_grobid_url = random.choice(GROBID_URLS) # 随机负载均衡
|
_grobid_url = random.choice(GROBID_URLS) # 随机负载均衡
|
||||||
if _grobid_url.endswith('/'): _grobid_url = _grobid_url.rstrip('/')
|
if _grobid_url.endswith('/'): _grobid_url = _grobid_url.rstrip('/')
|
||||||
res = requests.get(_grobid_url+'/api/isalive')
|
with ProxyNetworkActivate('Connect_Grobid'):
|
||||||
|
res = requests.get(_grobid_url+'/api/isalive')
|
||||||
if res.text=='true': return _grobid_url
|
if res.text=='true': return _grobid_url
|
||||||
else: return None
|
else: return None
|
||||||
except:
|
except:
|
||||||
@@ -20,6 +30,142 @@ def get_avail_grobid_url():
|
|||||||
def parse_pdf(pdf_path, grobid_url):
|
def parse_pdf(pdf_path, grobid_url):
|
||||||
import scipdf # pip install scipdf_parser
|
import scipdf # pip install scipdf_parser
|
||||||
if grobid_url.endswith('/'): grobid_url = grobid_url.rstrip('/')
|
if grobid_url.endswith('/'): grobid_url = grobid_url.rstrip('/')
|
||||||
article_dict = scipdf.parse_pdf_to_dict(pdf_path, grobid_url=grobid_url)
|
try:
|
||||||
|
with ProxyNetworkActivate('Connect_Grobid'):
|
||||||
|
article_dict = scipdf.parse_pdf_to_dict(pdf_path, grobid_url=grobid_url)
|
||||||
|
except GROBID_OFFLINE_EXCEPTION:
|
||||||
|
raise GROBID_OFFLINE_EXCEPTION("GROBID服务不可用,请修改config中的GROBID_URL,可修改成本地GROBID服务。")
|
||||||
|
except:
|
||||||
|
raise RuntimeError("解析PDF失败,请检查PDF是否损坏。")
|
||||||
return article_dict
|
return article_dict
|
||||||
|
|
||||||
|
|
||||||
|
def produce_report_markdown(gpt_response_collection, meta, paper_meta_info, chatbot, fp, generated_conclusion_files):
|
||||||
|
# -=-=-=-=-=-=-=-= 写出第1个文件:翻译前后混合 -=-=-=-=-=-=-=-=
|
||||||
|
res_path = write_history_to_file(meta + ["# Meta Translation" , paper_meta_info] + gpt_response_collection, file_basename=f"{gen_time_str()}translated_and_original.md", file_fullname=None)
|
||||||
|
promote_file_to_downloadzone(res_path, rename_file=os.path.basename(res_path)+'.md', chatbot=chatbot)
|
||||||
|
generated_conclusion_files.append(res_path)
|
||||||
|
|
||||||
|
# -=-=-=-=-=-=-=-= 写出第2个文件:仅翻译后的文本 -=-=-=-=-=-=-=-=
|
||||||
|
translated_res_array = []
|
||||||
|
# 记录当前的大章节标题:
|
||||||
|
last_section_name = ""
|
||||||
|
for index, value in enumerate(gpt_response_collection):
|
||||||
|
# 先挑选偶数序列号:
|
||||||
|
if index % 2 != 0:
|
||||||
|
# 先提取当前英文标题:
|
||||||
|
cur_section_name = gpt_response_collection[index-1].split('\n')[0].split(" Part")[0]
|
||||||
|
# 如果index是1的话,则直接使用first section name:
|
||||||
|
if cur_section_name != last_section_name:
|
||||||
|
cur_value = cur_section_name + '\n'
|
||||||
|
last_section_name = copy.deepcopy(cur_section_name)
|
||||||
|
else:
|
||||||
|
cur_value = ""
|
||||||
|
# 再做一个小修改:重新修改当前part的标题,默认用英文的
|
||||||
|
cur_value += value
|
||||||
|
translated_res_array.append(cur_value)
|
||||||
|
res_path = write_history_to_file(meta + ["# Meta Translation" , paper_meta_info] + translated_res_array,
|
||||||
|
file_basename = f"{gen_time_str()}-translated_only.md",
|
||||||
|
file_fullname = None,
|
||||||
|
auto_caption = False)
|
||||||
|
promote_file_to_downloadzone(res_path, rename_file=os.path.basename(res_path)+'.md', chatbot=chatbot)
|
||||||
|
generated_conclusion_files.append(res_path)
|
||||||
|
return res_path
|
||||||
|
|
||||||
|
def translate_pdf(article_dict, llm_kwargs, chatbot, fp, generated_conclusion_files, TOKEN_LIMIT_PER_FRAGMENT, DST_LANG):
|
||||||
|
from crazy_functions.crazy_utils import construct_html
|
||||||
|
from crazy_functions.crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf
|
||||||
|
from crazy_functions.crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
|
from crazy_functions.crazy_utils import request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency
|
||||||
|
|
||||||
|
prompt = "以下是一篇学术论文的基本信息:\n"
|
||||||
|
# title
|
||||||
|
title = article_dict.get('title', '无法获取 title'); prompt += f'title:{title}\n\n'
|
||||||
|
# authors
|
||||||
|
authors = article_dict.get('authors', '无法获取 authors'); prompt += f'authors:{authors}\n\n'
|
||||||
|
# abstract
|
||||||
|
abstract = article_dict.get('abstract', '无法获取 abstract'); prompt += f'abstract:{abstract}\n\n'
|
||||||
|
# command
|
||||||
|
prompt += f"请将题目和摘要翻译为{DST_LANG}。"
|
||||||
|
meta = [f'# Title:\n\n', title, f'# Abstract:\n\n', abstract ]
|
||||||
|
|
||||||
|
# 单线,获取文章meta信息
|
||||||
|
paper_meta_info = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
||||||
|
inputs=prompt,
|
||||||
|
inputs_show_user=prompt,
|
||||||
|
llm_kwargs=llm_kwargs,
|
||||||
|
chatbot=chatbot, history=[],
|
||||||
|
sys_prompt="You are an academic paper reader。",
|
||||||
|
)
|
||||||
|
|
||||||
|
# 多线,翻译
|
||||||
|
inputs_array = []
|
||||||
|
inputs_show_user_array = []
|
||||||
|
|
||||||
|
# get_token_num
|
||||||
|
from request_llm.bridge_all import model_info
|
||||||
|
enc = model_info[llm_kwargs['llm_model']]['tokenizer']
|
||||||
|
def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
|
||||||
|
|
||||||
|
def break_down(txt):
|
||||||
|
raw_token_num = get_token_num(txt)
|
||||||
|
if raw_token_num <= TOKEN_LIMIT_PER_FRAGMENT:
|
||||||
|
return [txt]
|
||||||
|
else:
|
||||||
|
# raw_token_num > TOKEN_LIMIT_PER_FRAGMENT
|
||||||
|
# find a smooth token limit to achieve even seperation
|
||||||
|
count = int(math.ceil(raw_token_num / TOKEN_LIMIT_PER_FRAGMENT))
|
||||||
|
token_limit_smooth = raw_token_num // count + count
|
||||||
|
return breakdown_txt_to_satisfy_token_limit_for_pdf(txt, get_token_fn=get_token_num, limit=token_limit_smooth)
|
||||||
|
|
||||||
|
for section in article_dict.get('sections'):
|
||||||
|
if len(section['text']) == 0: continue
|
||||||
|
section_frags = break_down(section['text'])
|
||||||
|
for i, fragment in enumerate(section_frags):
|
||||||
|
heading = section['heading']
|
||||||
|
if len(section_frags) > 1: heading += f' Part-{i+1}'
|
||||||
|
inputs_array.append(
|
||||||
|
f"你需要翻译{heading}章节,内容如下: \n\n{fragment}"
|
||||||
|
)
|
||||||
|
inputs_show_user_array.append(
|
||||||
|
f"# {heading}\n\n{fragment}"
|
||||||
|
)
|
||||||
|
|
||||||
|
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=[meta for _ in inputs_array],
|
||||||
|
sys_prompt_array=[
|
||||||
|
"请你作为一个学术翻译,负责把学术论文准确翻译成中文。注意文章中的每一句话都要翻译。" for _ in inputs_array],
|
||||||
|
)
|
||||||
|
# -=-=-=-=-=-=-=-= 写出Markdown文件 -=-=-=-=-=-=-=-=
|
||||||
|
produce_report_markdown(gpt_response_collection, meta, paper_meta_info, chatbot, fp, generated_conclusion_files)
|
||||||
|
|
||||||
|
# -=-=-=-=-=-=-=-= 写出HTML文件 -=-=-=-=-=-=-=-=
|
||||||
|
ch = construct_html()
|
||||||
|
orig = ""
|
||||||
|
trans = ""
|
||||||
|
gpt_response_collection_html = copy.deepcopy(gpt_response_collection)
|
||||||
|
for i,k in enumerate(gpt_response_collection_html):
|
||||||
|
if i%2==0:
|
||||||
|
gpt_response_collection_html[i] = inputs_show_user_array[i//2]
|
||||||
|
else:
|
||||||
|
# 先提取当前英文标题:
|
||||||
|
cur_section_name = gpt_response_collection[i-1].split('\n')[0].split(" Part")[0]
|
||||||
|
cur_value = cur_section_name + "\n" + gpt_response_collection_html[i]
|
||||||
|
gpt_response_collection_html[i] = cur_value
|
||||||
|
|
||||||
|
final = ["", "", "一、论文概况", "", "Abstract", paper_meta_info, "二、论文翻译", ""]
|
||||||
|
final.extend(gpt_response_collection_html)
|
||||||
|
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"{os.path.basename(fp)}.trans.html"
|
||||||
|
html_file = ch.save_file(create_report_file_name)
|
||||||
|
generated_conclusion_files.append(html_file)
|
||||||
|
promote_file_to_downloadzone(html_file, rename_file=os.path.basename(html_file), chatbot=chatbot)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from toolbox import update_ui
|
from toolbox import update_ui, get_log_folder
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file, get_conf
|
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||||
|
from toolbox import CatchException, report_execption, get_conf
|
||||||
import re, requests, unicodedata, os
|
import re, requests, unicodedata, os
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
def download_arxiv_(url_pdf):
|
def download_arxiv_(url_pdf):
|
||||||
@@ -28,7 +29,7 @@ def download_arxiv_(url_pdf):
|
|||||||
if k in other_info['comment']:
|
if k in other_info['comment']:
|
||||||
title = k + ' ' + title
|
title = k + ' ' + title
|
||||||
|
|
||||||
download_dir = './gpt_log/arxiv/'
|
download_dir = get_log_folder(plugin_name='arxiv')
|
||||||
os.makedirs(download_dir, exist_ok=True)
|
os.makedirs(download_dir, exist_ok=True)
|
||||||
|
|
||||||
title_str = title.replace('?', '?')\
|
title_str = title.replace('?', '?')\
|
||||||
@@ -40,9 +41,6 @@ def download_arxiv_(url_pdf):
|
|||||||
|
|
||||||
requests_pdf_url = url_pdf
|
requests_pdf_url = url_pdf
|
||||||
file_path = download_dir+title_str
|
file_path = download_dir+title_str
|
||||||
# if os.path.exists(file_path):
|
|
||||||
# print('返回缓存文件')
|
|
||||||
# return './gpt_log/arxiv/'+title_str
|
|
||||||
|
|
||||||
print('下载中')
|
print('下载中')
|
||||||
proxies, = get_conf('proxies')
|
proxies, = get_conf('proxies')
|
||||||
@@ -61,7 +59,7 @@ def download_arxiv_(url_pdf):
|
|||||||
.replace('\n', '')\
|
.replace('\n', '')\
|
||||||
.replace(' ', ' ')\
|
.replace(' ', ' ')\
|
||||||
.replace(' ', ' ')
|
.replace(' ', ' ')
|
||||||
return './gpt_log/arxiv/'+title_str, other_info
|
return file_path, other_info
|
||||||
|
|
||||||
|
|
||||||
def get_name(_url_):
|
def get_name(_url_):
|
||||||
@@ -184,11 +182,10 @@ def 下载arxiv论文并翻译摘要(txt, llm_kwargs, plugin_kwargs, chatbot, hi
|
|||||||
chatbot[-1] = (i_say_show_user, gpt_say)
|
chatbot[-1] = (i_say_show_user, gpt_say)
|
||||||
history.append(i_say_show_user); history.append(gpt_say)
|
history.append(i_say_show_user); history.append(gpt_say)
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
||||||
# 写入文件
|
res = write_history_to_file(history)
|
||||||
import shutil
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
# 重置文件的创建时间
|
promote_file_to_downloadzone(pdf_path, chatbot=chatbot)
|
||||||
shutil.copyfile(pdf_path, f'./gpt_log/{os.path.basename(pdf_path)}'); os.remove(pdf_path)
|
|
||||||
res = write_results_to_file(history)
|
|
||||||
chatbot.append(("完成了吗?", res + "\n\nPDF文件也已经下载"))
|
chatbot.append(("完成了吗?", res + "\n\nPDF文件也已经下载"))
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
||||||
|
|
||||||
|
|||||||
@@ -1,138 +0,0 @@
|
|||||||
import threading
|
|
||||||
from request_llm.bridge_all import predict_no_ui_long_connection
|
|
||||||
from toolbox import update_ui
|
|
||||||
from toolbox import CatchException, write_results_to_file, report_execption
|
|
||||||
from .crazy_utils import breakdown_txt_to_satisfy_token_limit
|
|
||||||
|
|
||||||
def extract_code_block_carefully(txt):
|
|
||||||
splitted = txt.split('```')
|
|
||||||
n_code_block_seg = len(splitted) - 1
|
|
||||||
if n_code_block_seg <= 1: return txt
|
|
||||||
# 剩下的情况都开头除去 ``` 结尾除去一次 ```
|
|
||||||
txt_out = '```'.join(splitted[1:-1])
|
|
||||||
return txt_out
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def break_txt_into_half_at_some_linebreak(txt):
|
|
||||||
lines = txt.split('\n')
|
|
||||||
n_lines = len(lines)
|
|
||||||
pre = lines[:(n_lines//2)]
|
|
||||||
post = lines[(n_lines//2):]
|
|
||||||
return "\n".join(pre), "\n".join(post)
|
|
||||||
|
|
||||||
|
|
||||||
@CatchException
|
|
||||||
def 全项目切换英文(txt, llm_kwargs, plugin_kwargs, chatbot, history, sys_prompt, web_port):
|
|
||||||
# 第1步:清空历史,以免输入溢出
|
|
||||||
history = []
|
|
||||||
|
|
||||||
# 第2步:尝试导入依赖,如果缺少依赖,则给出安装建议
|
|
||||||
try:
|
|
||||||
import tiktoken
|
|
||||||
except:
|
|
||||||
report_execption(chatbot, history,
|
|
||||||
a = f"解析项目: {txt}",
|
|
||||||
b = f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade tiktoken```。")
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
|
||||||
return
|
|
||||||
|
|
||||||
# 第3步:集合文件
|
|
||||||
import time, glob, os, shutil, re
|
|
||||||
os.makedirs('gpt_log/generated_english_version', exist_ok=True)
|
|
||||||
os.makedirs('gpt_log/generated_english_version/crazy_functions', exist_ok=True)
|
|
||||||
file_manifest = [f for f in glob.glob('./*.py') if ('test_project' not in f) and ('gpt_log' not in f)] + \
|
|
||||||
[f for f in glob.glob('./crazy_functions/*.py') if ('test_project' not in f) and ('gpt_log' not in f)]
|
|
||||||
# file_manifest = ['./toolbox.py']
|
|
||||||
i_say_show_user_buffer = []
|
|
||||||
|
|
||||||
# 第4步:随便显示点什么防止卡顿的感觉
|
|
||||||
for index, fp in enumerate(file_manifest):
|
|
||||||
# if 'test_project' in fp: continue
|
|
||||||
with open(fp, 'r', encoding='utf-8', errors='replace') as f:
|
|
||||||
file_content = f.read()
|
|
||||||
i_say_show_user =f'[{index}/{len(file_manifest)}] 接下来请将以下代码中包含的所有中文转化为英文,只输出转化后的英文代码,请用代码块输出代码: {os.path.abspath(fp)}'
|
|
||||||
i_say_show_user_buffer.append(i_say_show_user)
|
|
||||||
chatbot.append((i_say_show_user, "[Local Message] 等待多线程操作,中间过程不予显示."))
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
|
||||||
|
|
||||||
|
|
||||||
# 第5步:Token限制下的截断与处理
|
|
||||||
MAX_TOKEN = 3000
|
|
||||||
from request_llm.bridge_all import model_info
|
|
||||||
enc = model_info["gpt-3.5-turbo"]['tokenizer']
|
|
||||||
def get_token_fn(txt): return len(enc.encode(txt, disallowed_special=()))
|
|
||||||
|
|
||||||
|
|
||||||
# 第6步:任务函数
|
|
||||||
mutable_return = [None for _ in file_manifest]
|
|
||||||
observe_window = [[""] for _ in file_manifest]
|
|
||||||
def thread_worker(fp,index):
|
|
||||||
if index > 10:
|
|
||||||
time.sleep(60)
|
|
||||||
print('Openai 限制免费用户每分钟20次请求,降低请求频率中。')
|
|
||||||
with open(fp, 'r', encoding='utf-8', errors='replace') as f:
|
|
||||||
file_content = f.read()
|
|
||||||
i_say_template = lambda fp, file_content: f'接下来请将以下代码中包含的所有中文转化为英文,只输出代码,文件名是{fp},文件代码是 ```{file_content}```'
|
|
||||||
try:
|
|
||||||
gpt_say = ""
|
|
||||||
# 分解代码文件
|
|
||||||
file_content_breakdown = breakdown_txt_to_satisfy_token_limit(file_content, get_token_fn, MAX_TOKEN)
|
|
||||||
for file_content_partial in file_content_breakdown:
|
|
||||||
i_say = i_say_template(fp, file_content_partial)
|
|
||||||
# # ** gpt request **
|
|
||||||
gpt_say_partial = predict_no_ui_long_connection(inputs=i_say, llm_kwargs=llm_kwargs, history=[], sys_prompt=sys_prompt, observe_window=observe_window[index])
|
|
||||||
gpt_say_partial = extract_code_block_carefully(gpt_say_partial)
|
|
||||||
gpt_say += gpt_say_partial
|
|
||||||
mutable_return[index] = gpt_say
|
|
||||||
except ConnectionAbortedError as token_exceed_err:
|
|
||||||
print('至少一个线程任务Token溢出而失败', e)
|
|
||||||
except Exception as e:
|
|
||||||
print('至少一个线程任务意外失败', e)
|
|
||||||
|
|
||||||
# 第7步:所有线程同时开始执行任务函数
|
|
||||||
handles = [threading.Thread(target=thread_worker, args=(fp,index)) for index, fp in enumerate(file_manifest)]
|
|
||||||
for h in handles:
|
|
||||||
h.daemon = True
|
|
||||||
h.start()
|
|
||||||
chatbot.append(('开始了吗?', f'多线程操作已经开始'))
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
|
||||||
|
|
||||||
# 第8步:循环轮询各个线程是否执行完毕
|
|
||||||
cnt = 0
|
|
||||||
while True:
|
|
||||||
cnt += 1
|
|
||||||
time.sleep(0.2)
|
|
||||||
th_alive = [h.is_alive() for h in handles]
|
|
||||||
if not any(th_alive): break
|
|
||||||
# 更好的UI视觉效果
|
|
||||||
observe_win = []
|
|
||||||
for thread_index, alive in enumerate(th_alive):
|
|
||||||
observe_win.append("[ ..."+observe_window[thread_index][0][-60:].replace('\n','').replace('```','...').replace(' ','.').replace('<br/>','.....').replace('$','.')+"... ]")
|
|
||||||
stat = [f'执行中: {obs}\n\n' if alive else '已完成\n\n' for alive, obs in zip(th_alive, observe_win)]
|
|
||||||
stat_str = ''.join(stat)
|
|
||||||
chatbot[-1] = (chatbot[-1][0], f'多线程操作已经开始,完成情况: \n\n{stat_str}' + ''.join(['.']*(cnt%10+1)))
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
|
||||||
|
|
||||||
# 第9步:把结果写入文件
|
|
||||||
for index, h in enumerate(handles):
|
|
||||||
h.join() # 这里其实不需要join了,肯定已经都结束了
|
|
||||||
fp = file_manifest[index]
|
|
||||||
gpt_say = mutable_return[index]
|
|
||||||
i_say_show_user = i_say_show_user_buffer[index]
|
|
||||||
|
|
||||||
where_to_relocate = f'gpt_log/generated_english_version/{fp}'
|
|
||||||
if gpt_say is not None:
|
|
||||||
with open(where_to_relocate, 'w+', encoding='utf-8') as f:
|
|
||||||
f.write(gpt_say)
|
|
||||||
else: # 失败
|
|
||||||
shutil.copyfile(file_manifest[index], where_to_relocate)
|
|
||||||
chatbot.append((i_say_show_user, f'[Local Message] 已完成{os.path.abspath(fp)}的转化,\n\n存入{os.path.abspath(where_to_relocate)}'))
|
|
||||||
history.append(i_say_show_user); history.append(gpt_say)
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
# 第10步:备份一个文件
|
|
||||||
res = write_results_to_file(history)
|
|
||||||
chatbot.append(("生成一份任务执行报告", res))
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
|
||||||
252
crazy_functions/函数动态生成.py
普通文件
252
crazy_functions/函数动态生成.py
普通文件
@@ -0,0 +1,252 @@
|
|||||||
|
# 本源代码中, ⭐ = 关键步骤
|
||||||
|
"""
|
||||||
|
测试:
|
||||||
|
- 裁剪图像,保留下半部分
|
||||||
|
- 交换图像的蓝色通道和红色通道
|
||||||
|
- 将图像转为灰度图像
|
||||||
|
- 将csv文件转excel表格
|
||||||
|
|
||||||
|
Testing:
|
||||||
|
- Crop the image, keeping the bottom half.
|
||||||
|
- Swap the blue channel and red channel of the image.
|
||||||
|
- Convert the image to grayscale.
|
||||||
|
- Convert the CSV file to an Excel spreadsheet.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from toolbox import CatchException, update_ui, gen_time_str, trimmed_format_exc, is_the_upload_folder
|
||||||
|
from toolbox import promote_file_to_downloadzone, get_log_folder, update_ui_lastest_msg
|
||||||
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive, get_plugin_arg
|
||||||
|
from .crazy_utils import input_clipping, try_install_deps
|
||||||
|
from crazy_functions.gen_fns.gen_fns_shared import is_function_successfully_generated
|
||||||
|
from crazy_functions.gen_fns.gen_fns_shared import get_class_name
|
||||||
|
from crazy_functions.gen_fns.gen_fns_shared import subprocess_worker
|
||||||
|
from crazy_functions.gen_fns.gen_fns_shared import try_make_module
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import glob
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
templete = """
|
||||||
|
```python
|
||||||
|
import ... # Put dependencies here, e.g. import numpy as np.
|
||||||
|
|
||||||
|
class TerminalFunction(object): # Do not change the name of the class, The name of the class must be `TerminalFunction`
|
||||||
|
|
||||||
|
def run(self, path): # The name of the function must be `run`, it takes only a positional argument.
|
||||||
|
# rewrite the function you have just written here
|
||||||
|
...
|
||||||
|
return generated_file_path
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
|
||||||
|
def inspect_dependency(chatbot, history):
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_code_block(reply):
|
||||||
|
import re
|
||||||
|
pattern = r"```([\s\S]*?)```" # regex pattern to match code blocks
|
||||||
|
matches = re.findall(pattern, reply) # find all code blocks in text
|
||||||
|
if len(matches) == 1:
|
||||||
|
return matches[0].strip('python') # code block
|
||||||
|
for match in matches:
|
||||||
|
if 'class TerminalFunction' in match:
|
||||||
|
return match.strip('python') # code block
|
||||||
|
raise RuntimeError("GPT is not generating proper code.")
|
||||||
|
|
||||||
|
def gpt_interact_multi_step(txt, file_type, llm_kwargs, chatbot, history):
|
||||||
|
# 输入
|
||||||
|
prompt_compose = [
|
||||||
|
f'Your job:\n'
|
||||||
|
f'1. write a single Python function, which takes a path of a `{file_type}` file as the only argument and returns a `string` containing the result of analysis or the path of generated files. \n',
|
||||||
|
f"2. You should write this function to perform following task: " + txt + "\n",
|
||||||
|
f"3. Wrap the output python function with markdown codeblock."
|
||||||
|
]
|
||||||
|
i_say = "".join(prompt_compose)
|
||||||
|
demo = []
|
||||||
|
|
||||||
|
# 第一步
|
||||||
|
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=demo,
|
||||||
|
sys_prompt= r"You are a world-class programmer."
|
||||||
|
)
|
||||||
|
history.extend([i_say, gpt_say])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
|
||||||
|
|
||||||
|
# 第二步
|
||||||
|
prompt_compose = [
|
||||||
|
"If previous stage is successful, rewrite the function you have just written to satisfy following templete: \n",
|
||||||
|
templete
|
||||||
|
]
|
||||||
|
i_say = "".join(prompt_compose); inputs_show_user = "If previous stage is successful, rewrite the function you have just written to satisfy executable templete. "
|
||||||
|
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
||||||
|
inputs=i_say, inputs_show_user=inputs_show_user,
|
||||||
|
llm_kwargs=llm_kwargs, chatbot=chatbot, history=history,
|
||||||
|
sys_prompt= r"You are a programmer. You need to replace `...` with valid packages, do not give `...` in your answer!"
|
||||||
|
)
|
||||||
|
code_to_return = gpt_say
|
||||||
|
history.extend([i_say, gpt_say])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
|
||||||
|
|
||||||
|
# # 第三步
|
||||||
|
# i_say = "Please list to packages to install to run the code above. Then show me how to use `try_install_deps` function to install them."
|
||||||
|
# i_say += 'For instance. `try_install_deps(["opencv-python", "scipy", "numpy"])`'
|
||||||
|
# installation_advance = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
||||||
|
# inputs=i_say, inputs_show_user=inputs_show_user,
|
||||||
|
# llm_kwargs=llm_kwargs, chatbot=chatbot, history=history,
|
||||||
|
# sys_prompt= r"You are a programmer."
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # # 第三步
|
||||||
|
# i_say = "Show me how to use `pip` to install packages to run the code above. "
|
||||||
|
# i_say += 'For instance. `pip install -r opencv-python scipy numpy`'
|
||||||
|
# installation_advance = 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= r"You are a programmer."
|
||||||
|
# )
|
||||||
|
installation_advance = ""
|
||||||
|
|
||||||
|
return code_to_return, installation_advance, txt, file_type, llm_kwargs, chatbot, history
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def for_immediate_show_off_when_possible(file_type, fp, chatbot):
|
||||||
|
if file_type in ['png', 'jpg']:
|
||||||
|
image_path = os.path.abspath(fp)
|
||||||
|
chatbot.append(['这是一张图片, 展示如下:',
|
||||||
|
f'本地文件地址: <br/>`{image_path}`<br/>'+
|
||||||
|
f'本地文件预览: <br/><div align="center"><img src="file={image_path}"></div>'
|
||||||
|
])
|
||||||
|
return chatbot
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def have_any_recent_upload_files(chatbot):
|
||||||
|
_5min = 5 * 60
|
||||||
|
if not chatbot: return False # chatbot is None
|
||||||
|
most_recent_uploaded = chatbot._cookies.get("most_recent_uploaded", None)
|
||||||
|
if not most_recent_uploaded: return False # most_recent_uploaded is None
|
||||||
|
if time.time() - most_recent_uploaded["time"] < _5min: return True # most_recent_uploaded is new
|
||||||
|
else: return False # most_recent_uploaded is too old
|
||||||
|
|
||||||
|
def get_recent_file_prompt_support(chatbot):
|
||||||
|
most_recent_uploaded = chatbot._cookies.get("most_recent_uploaded", None)
|
||||||
|
path = most_recent_uploaded['path']
|
||||||
|
return path
|
||||||
|
|
||||||
|
@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(["正在启动: 插件动态生成插件", "插件动态生成, 执行开始, 作者Binary-Husky."])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
# ⭐ 文件上传区是否有东西
|
||||||
|
# 1. 如果有文件: 作为函数参数
|
||||||
|
# 2. 如果没有文件:需要用GPT提取参数 (太懒了,以后再写,虚空终端已经实现了类似的代码)
|
||||||
|
file_list = []
|
||||||
|
if get_plugin_arg(plugin_kwargs, key="file_path_arg", default=False):
|
||||||
|
file_path = get_plugin_arg(plugin_kwargs, key="file_path_arg", default=None)
|
||||||
|
file_list.append(file_path)
|
||||||
|
yield from update_ui_lastest_msg(f"当前文件: {file_path}", chatbot, history, 1)
|
||||||
|
elif have_any_recent_upload_files(chatbot):
|
||||||
|
file_dir = get_recent_file_prompt_support(chatbot)
|
||||||
|
file_list = glob.glob(os.path.join(file_dir, '**/*'), recursive=True)
|
||||||
|
yield from update_ui_lastest_msg(f"当前文件处理列表: {file_list}", chatbot, history, 1)
|
||||||
|
else:
|
||||||
|
chatbot.append(["文件检索", "没有发现任何近期上传的文件。"])
|
||||||
|
yield from update_ui_lastest_msg("没有发现任何近期上传的文件。", chatbot, history, 1)
|
||||||
|
return # 2. 如果没有文件
|
||||||
|
if len(file_list) == 0:
|
||||||
|
chatbot.append(["文件检索", "没有发现任何近期上传的文件。"])
|
||||||
|
yield from update_ui_lastest_msg("没有发现任何近期上传的文件。", chatbot, history, 1)
|
||||||
|
return # 2. 如果没有文件
|
||||||
|
|
||||||
|
# 读取文件
|
||||||
|
file_type = file_list[0].split('.')[-1]
|
||||||
|
|
||||||
|
# 粗心检查
|
||||||
|
if is_the_upload_folder(txt):
|
||||||
|
yield from update_ui_lastest_msg(f"请在输入框内填写需求, 然后再次点击该插件! 至于您的文件,不用担心, 文件路径 {txt} 已经被记忆. ", chatbot, history, 1)
|
||||||
|
return
|
||||||
|
|
||||||
|
# 开始干正事
|
||||||
|
MAX_TRY = 3
|
||||||
|
for j in range(MAX_TRY): # 最多重试5次
|
||||||
|
traceback = ""
|
||||||
|
try:
|
||||||
|
# ⭐ 开始啦 !
|
||||||
|
code, installation_advance, txt, file_type, llm_kwargs, chatbot, history = \
|
||||||
|
yield from gpt_interact_multi_step(txt, file_type, llm_kwargs, chatbot, history)
|
||||||
|
chatbot.append(["代码生成阶段结束", ""])
|
||||||
|
yield from update_ui_lastest_msg(f"正在验证上述代码的有效性 ...", chatbot, history, 1)
|
||||||
|
# ⭐ 分离代码块
|
||||||
|
code = get_code_block(code)
|
||||||
|
# ⭐ 检查模块
|
||||||
|
ok, traceback = try_make_module(code, chatbot)
|
||||||
|
# 搞定代码生成
|
||||||
|
if ok: break
|
||||||
|
except Exception as e:
|
||||||
|
if not traceback: traceback = trimmed_format_exc()
|
||||||
|
# 处理异常
|
||||||
|
if not traceback: traceback = trimmed_format_exc()
|
||||||
|
yield from update_ui_lastest_msg(f"第 {j+1}/{MAX_TRY} 次代码生成尝试, 失败了~ 别担心, 我们5秒后再试一次... \n\n此次我们的错误追踪是\n```\n{traceback}\n```\n", chatbot, history, 5)
|
||||||
|
|
||||||
|
# 代码生成结束, 开始执行
|
||||||
|
TIME_LIMIT = 15
|
||||||
|
yield from update_ui_lastest_msg(f"开始创建新进程并执行代码! 时间限制 {TIME_LIMIT} 秒. 请等待任务完成... ", chatbot, history, 1)
|
||||||
|
manager = multiprocessing.Manager()
|
||||||
|
return_dict = manager.dict()
|
||||||
|
|
||||||
|
# ⭐ 到最后一步了,开始逐个文件进行处理
|
||||||
|
for file_path in file_list:
|
||||||
|
if os.path.exists(file_path):
|
||||||
|
chatbot.append([f"正在处理文件: {file_path}", f"请稍等..."])
|
||||||
|
chatbot = for_immediate_show_off_when_possible(file_type, file_path, chatbot)
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# ⭐⭐⭐ subprocess_worker ⭐⭐⭐
|
||||||
|
p = multiprocessing.Process(target=subprocess_worker, args=(code, file_path, return_dict))
|
||||||
|
# ⭐ 开始执行,时间限制TIME_LIMIT
|
||||||
|
p.start(); p.join(timeout=TIME_LIMIT)
|
||||||
|
if p.is_alive(): p.terminate(); p.join()
|
||||||
|
p.close()
|
||||||
|
res = return_dict['result']
|
||||||
|
success = return_dict['success']
|
||||||
|
traceback = return_dict['traceback']
|
||||||
|
if not success:
|
||||||
|
if not traceback: traceback = trimmed_format_exc()
|
||||||
|
chatbot.append(["执行失败了", f"错误追踪\n```\n{trimmed_format_exc()}\n```\n"])
|
||||||
|
# chatbot.append(["如果是缺乏依赖,请参考以下建议", installation_advance])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
return
|
||||||
|
|
||||||
|
# 顺利完成,收尾
|
||||||
|
res = str(res)
|
||||||
|
if os.path.exists(res):
|
||||||
|
chatbot.append(["执行成功了,结果是一个有效文件", "结果:" + res])
|
||||||
|
new_file_path = promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
|
chatbot = for_immediate_show_off_when_possible(file_type, new_file_path, chatbot)
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
|
||||||
|
else:
|
||||||
|
chatbot.append(["执行成功了,结果是一个字符串", "结果:" + res])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from toolbox import CatchException, update_ui, get_conf, select_api_key
|
from toolbox import CatchException, update_ui, get_conf, select_api_key, get_log_folder
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ def gen_image(llm_kwargs, prompt, resolution="256x256"):
|
|||||||
raise RuntimeError(response.content.decode())
|
raise RuntimeError(response.content.decode())
|
||||||
# 文件保存到本地
|
# 文件保存到本地
|
||||||
r = requests.get(image_url, proxies=proxies)
|
r = requests.get(image_url, proxies=proxies)
|
||||||
file_path = 'gpt_log/image_gen/'
|
file_path = f'{get_log_folder()}/image_gen/'
|
||||||
os.makedirs(file_path, exist_ok=True)
|
os.makedirs(file_path, exist_ok=True)
|
||||||
file_name = 'Image' + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + '.png'
|
file_name = 'Image' + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + '.png'
|
||||||
with open(file_path+file_name, 'wb+') as f: f.write(r.content)
|
with open(file_path+file_name, 'wb+') as f: f.write(r.content)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from toolbox import CatchException, update_ui, promote_file_to_downloadzone
|
from toolbox import CatchException, update_ui, promote_file_to_downloadzone, get_log_folder
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@@ -10,8 +10,8 @@ def write_chat_to_file(chatbot, history=None, file_name=None):
|
|||||||
import time
|
import time
|
||||||
if file_name is None:
|
if file_name is None:
|
||||||
file_name = 'chatGPT对话历史' + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + '.html'
|
file_name = 'chatGPT对话历史' + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + '.html'
|
||||||
os.makedirs('./gpt_log/', exist_ok=True)
|
fp = os.path.join(get_log_folder(), file_name)
|
||||||
with open(f'./gpt_log/{file_name}', 'w', encoding='utf8') as f:
|
with open(fp, 'w', encoding='utf8') as f:
|
||||||
from themes.theme import advanced_css
|
from themes.theme import advanced_css
|
||||||
f.write(f'<!DOCTYPE html><head><meta charset="utf-8"><title>对话历史</title><style>{advanced_css}</style></head>')
|
f.write(f'<!DOCTYPE html><head><meta charset="utf-8"><title>对话历史</title><style>{advanced_css}</style></head>')
|
||||||
for i, contents in enumerate(chatbot):
|
for i, contents in enumerate(chatbot):
|
||||||
@@ -29,8 +29,8 @@ def write_chat_to_file(chatbot, history=None, file_name=None):
|
|||||||
for h in history:
|
for h in history:
|
||||||
f.write("\n>>>" + h)
|
f.write("\n>>>" + h)
|
||||||
f.write('</code>')
|
f.write('</code>')
|
||||||
promote_file_to_downloadzone(f'./gpt_log/{file_name}', rename_file=file_name, chatbot=chatbot)
|
promote_file_to_downloadzone(fp, rename_file=file_name, chatbot=chatbot)
|
||||||
return '对话历史写入:' + os.path.abspath(f'./gpt_log/{file_name}')
|
return '对话历史写入:' + fp
|
||||||
|
|
||||||
def gen_file_preview(file_name):
|
def gen_file_preview(file_name):
|
||||||
try:
|
try:
|
||||||
@@ -106,7 +106,7 @@ def 载入对话历史存档(txt, llm_kwargs, plugin_kwargs, chatbot, history, s
|
|||||||
if not success:
|
if not success:
|
||||||
if txt == "": txt = '空空如也的输入栏'
|
if txt == "": txt = '空空如也的输入栏'
|
||||||
import glob
|
import glob
|
||||||
local_history = "<br/>".join(["`"+hide_cwd(f)+f" ({gen_file_preview(f)})"+"`" for f in glob.glob(f'gpt_log/**/chatGPT对话历史*.html', recursive=True)])
|
local_history = "<br/>".join(["`"+hide_cwd(f)+f" ({gen_file_preview(f)})"+"`" for f in glob.glob(f'{get_log_folder()}/**/chatGPT对话历史*.html', recursive=True)])
|
||||||
chatbot.append([f"正在查找对话历史文件(html格式): {txt}", f"找不到任何html文件: {txt}。但本地存储了以下历史文件,您可以将任意一个文件路径粘贴到输入区,然后重试:<br/>{local_history}"])
|
chatbot.append([f"正在查找对话历史文件(html格式): {txt}", f"找不到任何html文件: {txt}。但本地存储了以下历史文件,您可以将任意一个文件路径粘贴到输入区,然后重试:<br/>{local_history}"])
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
return
|
return
|
||||||
@@ -132,8 +132,8 @@ def 删除所有本地对话历史记录(txt, llm_kwargs, plugin_kwargs, chatbot
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import glob, os
|
import glob, os
|
||||||
local_history = "<br/>".join(["`"+hide_cwd(f)+"`" for f in glob.glob(f'gpt_log/**/chatGPT对话历史*.html', recursive=True)])
|
local_history = "<br/>".join(["`"+hide_cwd(f)+"`" for f in glob.glob(f'{get_log_folder()}/**/chatGPT对话历史*.html', recursive=True)])
|
||||||
for f in glob.glob(f'gpt_log/**/chatGPT对话历史*.html', recursive=True):
|
for f in glob.glob(f'{get_log_folder()}/**/chatGPT对话历史*.html', recursive=True):
|
||||||
os.remove(f)
|
os.remove(f)
|
||||||
chatbot.append([f"删除所有历史对话文件", f"已删除<br/>{local_history}"])
|
chatbot.append([f"删除所有历史对话文件", f"已删除<br/>{local_history}"])
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from toolbox import update_ui
|
from toolbox import update_ui
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption
|
||||||
|
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
fast_debug = False
|
fast_debug = False
|
||||||
|
|
||||||
@@ -71,11 +72,13 @@ def 解析docx(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot
|
|||||||
history.extend([i_say,gpt_say])
|
history.extend([i_say,gpt_say])
|
||||||
this_paper_history.extend([i_say,gpt_say])
|
this_paper_history.extend([i_say,gpt_say])
|
||||||
|
|
||||||
res = write_results_to_file(history)
|
res = write_history_to_file(history)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
chatbot.append(("完成了吗?", res))
|
chatbot.append(("完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
res = write_results_to_file(history)
|
res = write_history_to_file(history)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
chatbot.append(("所有文件都总结完成了吗?", res))
|
chatbot.append(("所有文件都总结完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from toolbox import CatchException, report_execption, select_api_key, update_ui, write_results_to_file, get_conf
|
from toolbox import CatchException, report_execption, select_api_key, update_ui, get_conf
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
|
from toolbox import write_history_to_file, promote_file_to_downloadzone, get_log_folder
|
||||||
|
|
||||||
def split_audio_file(filename, split_duration=1000):
|
def split_audio_file(filename, split_duration=1000):
|
||||||
"""
|
"""
|
||||||
@@ -15,7 +16,7 @@ def split_audio_file(filename, split_duration=1000):
|
|||||||
"""
|
"""
|
||||||
from moviepy.editor import AudioFileClip
|
from moviepy.editor import AudioFileClip
|
||||||
import os
|
import os
|
||||||
os.makedirs('gpt_log/mp3/cut/', exist_ok=True) # 创建存储切割音频的文件夹
|
os.makedirs(f"{get_log_folder(plugin_name='audio')}/mp3/cut/", exist_ok=True) # 创建存储切割音频的文件夹
|
||||||
|
|
||||||
# 读取音频文件
|
# 读取音频文件
|
||||||
audio = AudioFileClip(filename)
|
audio = AudioFileClip(filename)
|
||||||
@@ -31,8 +32,8 @@ def split_audio_file(filename, split_duration=1000):
|
|||||||
start_time = split_points[i]
|
start_time = split_points[i]
|
||||||
end_time = split_points[i + 1]
|
end_time = split_points[i + 1]
|
||||||
split_audio = audio.subclip(start_time, end_time)
|
split_audio = audio.subclip(start_time, end_time)
|
||||||
split_audio.write_audiofile(f"gpt_log/mp3/cut/{filename[0]}_{i}.mp3")
|
split_audio.write_audiofile(f"{get_log_folder(plugin_name='audio')}/mp3/cut/{filename[0]}_{i}.mp3")
|
||||||
filelist.append(f"gpt_log/mp3/cut/{filename[0]}_{i}.mp3")
|
filelist.append(f"{get_log_folder(plugin_name='audio')}/mp3/cut/{filename[0]}_{i}.mp3")
|
||||||
|
|
||||||
audio.close()
|
audio.close()
|
||||||
return filelist
|
return filelist
|
||||||
@@ -52,7 +53,7 @@ def AnalyAudio(parse_prompt, file_manifest, llm_kwargs, chatbot, history):
|
|||||||
'Authorization': f"Bearer {api_key}"
|
'Authorization': f"Bearer {api_key}"
|
||||||
}
|
}
|
||||||
|
|
||||||
os.makedirs('gpt_log/mp3/', exist_ok=True)
|
os.makedirs(f"{get_log_folder(plugin_name='audio')}/mp3/", exist_ok=True)
|
||||||
for index, fp in enumerate(file_manifest):
|
for index, fp in enumerate(file_manifest):
|
||||||
audio_history = []
|
audio_history = []
|
||||||
# 提取文件扩展名
|
# 提取文件扩展名
|
||||||
@@ -60,8 +61,8 @@ def AnalyAudio(parse_prompt, file_manifest, llm_kwargs, chatbot, history):
|
|||||||
# 提取视频中的音频
|
# 提取视频中的音频
|
||||||
if ext not in [".mp3", ".wav", ".m4a", ".mpga"]:
|
if ext not in [".mp3", ".wav", ".m4a", ".mpga"]:
|
||||||
audio_clip = AudioFileClip(fp)
|
audio_clip = AudioFileClip(fp)
|
||||||
audio_clip.write_audiofile(f'gpt_log/mp3/output{index}.mp3')
|
audio_clip.write_audiofile(f"{get_log_folder(plugin_name='audio')}/mp3/output{index}.mp3")
|
||||||
fp = f'gpt_log/mp3/output{index}.mp3'
|
fp = f"{get_log_folder(plugin_name='audio')}/mp3/output{index}.mp3"
|
||||||
# 调用whisper模型音频转文字
|
# 调用whisper模型音频转文字
|
||||||
voice = split_audio_file(fp)
|
voice = split_audio_file(fp)
|
||||||
for j, i in enumerate(voice):
|
for j, i in enumerate(voice):
|
||||||
@@ -113,18 +114,19 @@ def AnalyAudio(parse_prompt, file_manifest, llm_kwargs, chatbot, history):
|
|||||||
history=audio_history,
|
history=audio_history,
|
||||||
sys_prompt="总结文章。"
|
sys_prompt="总结文章。"
|
||||||
)
|
)
|
||||||
|
|
||||||
history.extend([i_say, gpt_say])
|
history.extend([i_say, gpt_say])
|
||||||
audio_history.extend([i_say, gpt_say])
|
audio_history.extend([i_say, gpt_say])
|
||||||
|
|
||||||
res = write_results_to_file(history)
|
res = write_history_to_file(history)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
chatbot.append((f"第{index + 1}段音频完成了吗?", res))
|
chatbot.append((f"第{index + 1}段音频完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
# 删除中间文件夹
|
# 删除中间文件夹
|
||||||
import shutil
|
import shutil
|
||||||
shutil.rmtree('gpt_log/mp3')
|
shutil.rmtree(f"{get_log_folder(plugin_name='audio')}/mp3")
|
||||||
res = write_results_to_file(history)
|
res = write_history_to_file(history)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
chatbot.append(("所有音频都总结完成了吗?", res))
|
chatbot.append(("所有音频都总结完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history)
|
yield from update_ui(chatbot=chatbot, history=history)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import glob, time, os, re
|
import glob, time, os, re, logging
|
||||||
from toolbox import update_ui, trimmed_format_exc, gen_time_str, disable_auto_promotion
|
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 CatchException, report_execption, get_log_folder
|
||||||
from toolbox import promote_file_to_downloadzone, get_log_folder
|
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||||
fast_debug = False
|
fast_debug = False
|
||||||
|
|
||||||
class PaperFileGroup():
|
class PaperFileGroup():
|
||||||
@@ -34,7 +34,7 @@ class PaperFileGroup():
|
|||||||
self.sp_file_contents.append(segment)
|
self.sp_file_contents.append(segment)
|
||||||
self.sp_file_index.append(index)
|
self.sp_file_index.append(index)
|
||||||
self.sp_file_tag.append(self.file_paths[index] + f".part-{j}.md")
|
self.sp_file_tag.append(self.file_paths[index] + f".part-{j}.md")
|
||||||
print('Segmentation: done')
|
logging.info('Segmentation: done')
|
||||||
|
|
||||||
def merge_result(self):
|
def merge_result(self):
|
||||||
self.file_result = ["" for _ in range(len(self.file_paths))]
|
self.file_result = ["" for _ in range(len(self.file_paths))]
|
||||||
@@ -101,7 +101,7 @@ def 多文件翻译(file_manifest, project_folder, llm_kwargs, plugin_kwargs, ch
|
|||||||
pfg.merge_result()
|
pfg.merge_result()
|
||||||
pfg.write_result(language)
|
pfg.write_result(language)
|
||||||
except:
|
except:
|
||||||
print(trimmed_format_exc())
|
logging.error(trimmed_format_exc())
|
||||||
|
|
||||||
# <-------- 整理结果,退出 ---------->
|
# <-------- 整理结果,退出 ---------->
|
||||||
create_report_file_name = gen_time_str() + f"-chatgpt.md"
|
create_report_file_name = gen_time_str() + f"-chatgpt.md"
|
||||||
@@ -121,7 +121,7 @@ def get_files_from_everything(txt, preference=''):
|
|||||||
proxies, = get_conf('proxies')
|
proxies, = get_conf('proxies')
|
||||||
# 网络的远程文件
|
# 网络的远程文件
|
||||||
if preference == 'Github':
|
if preference == 'Github':
|
||||||
print('正在从github下载资源 ...')
|
logging.info('正在从github下载资源 ...')
|
||||||
if not txt.endswith('.md'):
|
if not txt.endswith('.md'):
|
||||||
# Make a request to the GitHub API to retrieve the repository information
|
# Make a request to the GitHub API to retrieve the repository information
|
||||||
url = txt.replace("https://github.com/", "https://api.github.com/repos/") + '/readme'
|
url = txt.replace("https://github.com/", "https://api.github.com/repos/") + '/readme'
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from toolbox import update_ui, promote_file_to_downloadzone, gen_time_str
|
from toolbox import update_ui, promote_file_to_downloadzone, gen_time_str
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption
|
||||||
|
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
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 read_and_clean_pdf_text
|
||||||
from .crazy_utils import input_clipping
|
from .crazy_utils import input_clipping
|
||||||
@@ -99,8 +100,8 @@ do not have too much repetitive information, numerical values using the original
|
|||||||
_, final_results = input_clipping("", final_results, max_token_limit=3200)
|
_, final_results = input_clipping("", final_results, max_token_limit=3200)
|
||||||
yield from update_ui(chatbot=chatbot, history=final_results) # 注意这里的历史记录被替代了
|
yield from update_ui(chatbot=chatbot, history=final_results) # 注意这里的历史记录被替代了
|
||||||
|
|
||||||
res = write_results_to_file(file_write_buffer, file_name=gen_time_str())
|
res = write_history_to_file(file_write_buffer)
|
||||||
promote_file_to_downloadzone(res.split('\t')[-1], chatbot=chatbot)
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
yield from update_ui(chatbot=chatbot, history=final_results) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=final_results) # 刷新界面
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from toolbox import update_ui
|
from toolbox import update_ui
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
|
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||||
|
|
||||||
fast_debug = False
|
fast_debug = False
|
||||||
|
|
||||||
@@ -115,7 +116,8 @@ def 解析Paper(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbo
|
|||||||
chatbot[-1] = (i_say, gpt_say)
|
chatbot[-1] = (i_say, gpt_say)
|
||||||
history.append(i_say); history.append(gpt_say)
|
history.append(i_say); history.append(gpt_say)
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
||||||
res = write_results_to_file(history)
|
res = write_history_to_file(history)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
chatbot.append(("完成了吗?", res))
|
chatbot.append(("完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
||||||
|
|
||||||
|
|||||||
115
crazy_functions/批量翻译PDF文档_NOUGAT.py
普通文件
115
crazy_functions/批量翻译PDF文档_NOUGAT.py
普通文件
@@ -0,0 +1,115 @@
|
|||||||
|
from toolbox import CatchException, report_execption, get_log_folder, gen_time_str
|
||||||
|
from toolbox import update_ui, promote_file_to_downloadzone, update_ui_lastest_msg, disable_auto_promotion
|
||||||
|
from toolbox import write_history_to_file, 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
|
||||||
|
from .pdf_fns.parse_pdf import parse_pdf, get_avail_grobid_url, translate_pdf
|
||||||
|
from colorful import *
|
||||||
|
import copy
|
||||||
|
import os
|
||||||
|
import math
|
||||||
|
import logging
|
||||||
|
|
||||||
|
def markdown_to_dict(article_content):
|
||||||
|
import markdown
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
cur_t = ""
|
||||||
|
cur_c = ""
|
||||||
|
results = {}
|
||||||
|
for line in article_content:
|
||||||
|
if line.startswith('#'):
|
||||||
|
if cur_t!="":
|
||||||
|
if cur_t not in results:
|
||||||
|
results.update({cur_t:cur_c.lstrip('\n')})
|
||||||
|
else:
|
||||||
|
# 处理重名的章节
|
||||||
|
results.update({cur_t + " " + gen_time_str():cur_c.lstrip('\n')})
|
||||||
|
cur_t = line.rstrip('\n')
|
||||||
|
cur_c = ""
|
||||||
|
else:
|
||||||
|
cur_c += line
|
||||||
|
results_final = {}
|
||||||
|
for k in list(results.keys()):
|
||||||
|
if k.startswith('# '):
|
||||||
|
results_final['title'] = k.split('# ')[-1]
|
||||||
|
results_final['authors'] = results.pop(k).lstrip('\n')
|
||||||
|
if k.startswith('###### Abstract'):
|
||||||
|
results_final['abstract'] = results.pop(k).lstrip('\n')
|
||||||
|
|
||||||
|
results_final_sections = []
|
||||||
|
for k,v in results.items():
|
||||||
|
results_final_sections.append({
|
||||||
|
'heading':k.lstrip("# "),
|
||||||
|
'text':v if len(v) > 0 else f"The beginning of {k.lstrip('# ')} section."
|
||||||
|
})
|
||||||
|
results_final['sections'] = results_final_sections
|
||||||
|
return results_final
|
||||||
|
|
||||||
|
|
||||||
|
@CatchException
|
||||||
|
def 批量翻译PDF文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
|
|
||||||
|
disable_auto_promotion(chatbot)
|
||||||
|
# 基本信息:功能、贡献者
|
||||||
|
chatbot.append([
|
||||||
|
"函数插件功能?",
|
||||||
|
"批量翻译PDF文档。函数插件贡献者: Binary-Husky"])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
# 尝试导入依赖,如果缺少依赖,则给出安装建议
|
||||||
|
try:
|
||||||
|
import nougat
|
||||||
|
import tiktoken
|
||||||
|
except:
|
||||||
|
report_execption(chatbot, history,
|
||||||
|
a=f"解析项目: {txt}",
|
||||||
|
b=f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade nougat-ocr tiktoken```。")
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
return
|
||||||
|
|
||||||
|
# 清空历史,以免输入溢出
|
||||||
|
history = []
|
||||||
|
|
||||||
|
from .crazy_utils import get_files_from_everything
|
||||||
|
success, file_manifest, project_folder = get_files_from_everything(txt, type='.pdf')
|
||||||
|
# 检测输入参数,如没有给定输入参数,直接退出
|
||||||
|
if not success:
|
||||||
|
if txt == "": txt = '空空如也的输入栏'
|
||||||
|
|
||||||
|
# 如果没找到任何文件
|
||||||
|
if len(file_manifest) == 0:
|
||||||
|
report_execption(chatbot, history,
|
||||||
|
a=f"解析项目: {txt}", b=f"找不到任何.tex或.pdf文件: {txt}")
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
return
|
||||||
|
|
||||||
|
# 开始正式执行任务
|
||||||
|
yield from 解析PDF_基于NOUGAT(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def 解析PDF_基于NOUGAT(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
||||||
|
import copy
|
||||||
|
import tiktoken
|
||||||
|
TOKEN_LIMIT_PER_FRAGMENT = 1024
|
||||||
|
generated_conclusion_files = []
|
||||||
|
generated_html_files = []
|
||||||
|
DST_LANG = "中文"
|
||||||
|
from crazy_functions.crazy_utils import nougat_interface, construct_html
|
||||||
|
nougat_handle = nougat_interface()
|
||||||
|
for index, fp in enumerate(file_manifest):
|
||||||
|
chatbot.append(["当前进度:", f"正在解析论文,请稍候。(第一次运行时,需要花费较长时间下载NOUGAT参数)"]); yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
fpp = yield from nougat_handle.NOUGAT_parse_pdf(fp, chatbot, history)
|
||||||
|
promote_file_to_downloadzone(fpp, rename_file=os.path.basename(fpp)+'.nougat.mmd', chatbot=chatbot)
|
||||||
|
with open(fpp, 'r', encoding='utf8') as f:
|
||||||
|
article_content = f.readlines()
|
||||||
|
article_dict = markdown_to_dict(article_content)
|
||||||
|
logging.info(article_dict)
|
||||||
|
yield from translate_pdf(article_dict, llm_kwargs, chatbot, fp, generated_conclusion_files, TOKEN_LIMIT_PER_FRAGMENT, DST_LANG)
|
||||||
|
|
||||||
|
chatbot.append(("给出输出文件清单", str(generated_conclusion_files + generated_html_files)))
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption, get_log_folder, gen_time_str
|
||||||
from toolbox import update_ui, promote_file_to_downloadzone, update_ui_lastest_msg, disable_auto_promotion
|
from toolbox import update_ui, promote_file_to_downloadzone, update_ui_lastest_msg, disable_auto_promotion
|
||||||
from toolbox import write_history_to_file, get_log_folder
|
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
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 request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency
|
||||||
from .crazy_utils import read_and_clean_pdf_text
|
from .crazy_utils import read_and_clean_pdf_text
|
||||||
from .pdf_fns.parse_pdf import parse_pdf, get_avail_grobid_url
|
from .pdf_fns.parse_pdf import parse_pdf, get_avail_grobid_url, translate_pdf
|
||||||
from colorful import *
|
from colorful import *
|
||||||
import glob
|
import copy
|
||||||
import os
|
import os
|
||||||
import math
|
import math
|
||||||
|
|
||||||
@@ -24,10 +24,11 @@ def 批量翻译PDF文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst
|
|||||||
try:
|
try:
|
||||||
import fitz
|
import fitz
|
||||||
import tiktoken
|
import tiktoken
|
||||||
|
import scipdf
|
||||||
except:
|
except:
|
||||||
report_execption(chatbot, history,
|
report_execption(chatbot, history,
|
||||||
a=f"解析项目: {txt}",
|
a=f"解析项目: {txt}",
|
||||||
b=f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade pymupdf tiktoken```。")
|
b=f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade pymupdf tiktoken scipdf_parser```。")
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -57,115 +58,35 @@ def 批量翻译PDF文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst
|
|||||||
|
|
||||||
|
|
||||||
def 解析PDF_基于GROBID(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, grobid_url):
|
def 解析PDF_基于GROBID(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, grobid_url):
|
||||||
import copy
|
import copy, json
|
||||||
import tiktoken
|
TOKEN_LIMIT_PER_FRAGMENT = 1024
|
||||||
TOKEN_LIMIT_PER_FRAGMENT = 1280
|
|
||||||
generated_conclusion_files = []
|
generated_conclusion_files = []
|
||||||
generated_html_files = []
|
generated_html_files = []
|
||||||
DST_LANG = "中文"
|
DST_LANG = "中文"
|
||||||
|
from crazy_functions.crazy_utils import construct_html
|
||||||
for index, fp in enumerate(file_manifest):
|
for index, fp in enumerate(file_manifest):
|
||||||
chatbot.append(["当前进度:", f"正在连接GROBID服务,请稍候: {grobid_url}\n如果等待时间过长,请修改config中的GROBID_URL,可修改成本地GROBID服务。"]); yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
chatbot.append(["当前进度:", f"正在连接GROBID服务,请稍候: {grobid_url}\n如果等待时间过长,请修改config中的GROBID_URL,可修改成本地GROBID服务。"]); yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
article_dict = parse_pdf(fp, grobid_url)
|
article_dict = parse_pdf(fp, grobid_url)
|
||||||
print(article_dict)
|
grobid_json_res = os.path.join(get_log_folder(), gen_time_str() + "grobid.json")
|
||||||
prompt = "以下是一篇学术论文的基本信息:\n"
|
with open(grobid_json_res, 'w+', encoding='utf8') as f:
|
||||||
# title
|
f.write(json.dumps(article_dict, indent=4, ensure_ascii=False))
|
||||||
title = article_dict.get('title', '无法获取 title'); prompt += f'title:{title}\n\n'
|
promote_file_to_downloadzone(grobid_json_res, chatbot=chatbot)
|
||||||
# authors
|
|
||||||
authors = article_dict.get('authors', '无法获取 authors'); prompt += f'authors:{authors}\n\n'
|
if article_dict is None: raise RuntimeError("解析PDF失败,请检查PDF是否损坏。")
|
||||||
# abstract
|
yield from translate_pdf(article_dict, llm_kwargs, chatbot, fp, generated_conclusion_files, TOKEN_LIMIT_PER_FRAGMENT, DST_LANG)
|
||||||
abstract = article_dict.get('abstract', '无法获取 abstract'); prompt += f'abstract:{abstract}\n\n'
|
|
||||||
# command
|
|
||||||
prompt += f"请将题目和摘要翻译为{DST_LANG}。"
|
|
||||||
meta = [f'# Title:\n\n', title, f'# Abstract:\n\n', abstract ]
|
|
||||||
|
|
||||||
# 单线,获取文章meta信息
|
|
||||||
paper_meta_info = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
|
||||||
inputs=prompt,
|
|
||||||
inputs_show_user=prompt,
|
|
||||||
llm_kwargs=llm_kwargs,
|
|
||||||
chatbot=chatbot, history=[],
|
|
||||||
sys_prompt="You are an academic paper reader。",
|
|
||||||
)
|
|
||||||
|
|
||||||
# 多线,翻译
|
|
||||||
inputs_array = []
|
|
||||||
inputs_show_user_array = []
|
|
||||||
|
|
||||||
# get_token_num
|
|
||||||
from request_llm.bridge_all import model_info
|
|
||||||
enc = model_info[llm_kwargs['llm_model']]['tokenizer']
|
|
||||||
def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
|
|
||||||
from .crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf
|
|
||||||
|
|
||||||
def break_down(txt):
|
|
||||||
raw_token_num = get_token_num(txt)
|
|
||||||
if raw_token_num <= TOKEN_LIMIT_PER_FRAGMENT:
|
|
||||||
return [txt]
|
|
||||||
else:
|
|
||||||
# raw_token_num > TOKEN_LIMIT_PER_FRAGMENT
|
|
||||||
# find a smooth token limit to achieve even seperation
|
|
||||||
count = int(math.ceil(raw_token_num / TOKEN_LIMIT_PER_FRAGMENT))
|
|
||||||
token_limit_smooth = raw_token_num // count + count
|
|
||||||
return breakdown_txt_to_satisfy_token_limit_for_pdf(txt, get_token_fn=get_token_num, limit=token_limit_smooth)
|
|
||||||
|
|
||||||
for section in article_dict.get('sections'):
|
|
||||||
if len(section['text']) == 0: continue
|
|
||||||
section_frags = break_down(section['text'])
|
|
||||||
for i, fragment in enumerate(section_frags):
|
|
||||||
heading = section['heading']
|
|
||||||
if len(section_frags) > 1: heading += f' Part-{i+1}'
|
|
||||||
inputs_array.append(
|
|
||||||
f"你需要翻译{heading}章节,内容如下: \n\n{fragment}"
|
|
||||||
)
|
|
||||||
inputs_show_user_array.append(
|
|
||||||
f"# {heading}\n\n{fragment}"
|
|
||||||
)
|
|
||||||
|
|
||||||
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=[meta for _ in inputs_array],
|
|
||||||
sys_prompt_array=[
|
|
||||||
"请你作为一个学术翻译,负责把学术论文准确翻译成中文。注意文章中的每一句话都要翻译。" for _ in inputs_array],
|
|
||||||
)
|
|
||||||
res_path = write_history_to_file(meta + ["# Meta Translation" , paper_meta_info] + gpt_response_collection, file_basename=None, file_fullname=None)
|
|
||||||
promote_file_to_downloadzone(res_path, rename_file=os.path.basename(fp)+'.md', chatbot=chatbot)
|
|
||||||
generated_conclusion_files.append(res_path)
|
|
||||||
|
|
||||||
ch = construct_html()
|
|
||||||
orig = ""
|
|
||||||
trans = ""
|
|
||||||
gpt_response_collection_html = copy.deepcopy(gpt_response_collection)
|
|
||||||
for i,k in enumerate(gpt_response_collection_html):
|
|
||||||
if i%2==0:
|
|
||||||
gpt_response_collection_html[i] = inputs_show_user_array[i//2]
|
|
||||||
else:
|
|
||||||
gpt_response_collection_html[i] = gpt_response_collection_html[i]
|
|
||||||
|
|
||||||
final = ["", "", "一、论文概况", "", "Abstract", paper_meta_info, "二、论文翻译", ""]
|
|
||||||
final.extend(gpt_response_collection_html)
|
|
||||||
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"{os.path.basename(fp)}.trans.html"
|
|
||||||
html_file = ch.save_file(create_report_file_name)
|
|
||||||
generated_html_files.append(html_file)
|
|
||||||
promote_file_to_downloadzone(html_file, rename_file=os.path.basename(html_file), chatbot=chatbot)
|
|
||||||
|
|
||||||
chatbot.append(("给出输出文件清单", str(generated_conclusion_files + generated_html_files)))
|
chatbot.append(("给出输出文件清单", str(generated_conclusion_files + generated_html_files)))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
|
||||||
def 解析PDF(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
def 解析PDF(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
||||||
|
"""
|
||||||
|
此函数已经弃用
|
||||||
|
"""
|
||||||
import copy
|
import copy
|
||||||
TOKEN_LIMIT_PER_FRAGMENT = 1280
|
TOKEN_LIMIT_PER_FRAGMENT = 1024
|
||||||
generated_conclusion_files = []
|
generated_conclusion_files = []
|
||||||
generated_html_files = []
|
generated_html_files = []
|
||||||
|
from crazy_functions.crazy_utils import construct_html
|
||||||
for index, fp in enumerate(file_manifest):
|
for index, fp in enumerate(file_manifest):
|
||||||
# 读取PDF文件
|
# 读取PDF文件
|
||||||
file_content, page_one = read_and_clean_pdf_text(fp)
|
file_content, page_one = read_and_clean_pdf_text(fp)
|
||||||
@@ -216,10 +137,11 @@ def 解析PDF(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot,
|
|||||||
final = ["一、论文概况\n\n---\n\n", paper_meta_info.replace('# ', '### ') + '\n\n---\n\n', "二、论文翻译", ""]
|
final = ["一、论文概况\n\n---\n\n", paper_meta_info.replace('# ', '### ') + '\n\n---\n\n', "二、论文翻译", ""]
|
||||||
final.extend(gpt_response_collection_md)
|
final.extend(gpt_response_collection_md)
|
||||||
create_report_file_name = f"{os.path.basename(fp)}.trans.md"
|
create_report_file_name = f"{os.path.basename(fp)}.trans.md"
|
||||||
res = write_results_to_file(final, file_name=create_report_file_name)
|
res = write_history_to_file(final, create_report_file_name)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
|
|
||||||
# 更新UI
|
# 更新UI
|
||||||
generated_conclusion_files.append(f'./gpt_log/{create_report_file_name}')
|
generated_conclusion_files.append(f'{get_log_folder()}/{create_report_file_name}')
|
||||||
chatbot.append((f"{fp}完成了吗?", res))
|
chatbot.append((f"{fp}完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
@@ -261,49 +183,3 @@ def 解析PDF(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot,
|
|||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
|
||||||
class construct_html():
|
|
||||||
def __init__(self) -> None:
|
|
||||||
self.css = """
|
|
||||||
.row {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column {
|
|
||||||
flex: 1;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
font-weight: bold;
|
|
||||||
border-bottom: 1px solid black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
border-bottom: 1px solid lightgray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-cell {
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
self.html_string = f'<!DOCTYPE html><head><meta charset="utf-8"><title>翻译结果</title><style>{self.css}</style></head>'
|
|
||||||
|
|
||||||
|
|
||||||
def add_row(self, a, b):
|
|
||||||
tmp = """
|
|
||||||
<div class="row table-row">
|
|
||||||
<div class="column table-cell">REPLACE_A</div>
|
|
||||||
<div class="column table-cell">REPLACE_B</div>
|
|
||||||
</div>
|
|
||||||
"""
|
|
||||||
from toolbox import markdown_convertion
|
|
||||||
tmp = tmp.replace('REPLACE_A', markdown_convertion(a))
|
|
||||||
tmp = tmp.replace('REPLACE_B', markdown_convertion(b))
|
|
||||||
self.html_string += tmp
|
|
||||||
|
|
||||||
|
|
||||||
def save_file(self, file_name):
|
|
||||||
with open(os.path.join(get_log_folder(), file_name), 'w', encoding='utf8') as f:
|
|
||||||
f.write(self.html_string.encode('utf-8', 'ignore').decode())
|
|
||||||
return os.path.join(get_log_folder(), file_name)
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from toolbox import update_ui
|
from toolbox import update_ui
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption
|
||||||
|
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
fast_debug = False
|
fast_debug = False
|
||||||
|
|
||||||
@@ -27,7 +28,8 @@ def 生成函数注释(file_manifest, project_folder, llm_kwargs, plugin_kwargs,
|
|||||||
if not fast_debug: time.sleep(2)
|
if not fast_debug: time.sleep(2)
|
||||||
|
|
||||||
if not fast_debug:
|
if not fast_debug:
|
||||||
res = write_results_to_file(history)
|
res = write_history_to_file(history)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
chatbot.append(("完成了吗?", res))
|
chatbot.append(("完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,11 @@ def 连接网络回答问题(txt, llm_kwargs, plugin_kwargs, chatbot, history, s
|
|||||||
proxies, = get_conf('proxies')
|
proxies, = get_conf('proxies')
|
||||||
urls = google(txt, proxies)
|
urls = google(txt, proxies)
|
||||||
history = []
|
history = []
|
||||||
|
if len(urls) == 0:
|
||||||
|
chatbot.append((f"结论:{txt}",
|
||||||
|
"[Local Message] 受到google限制,无法从google获取信息!"))
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新
|
||||||
|
return
|
||||||
# ------------- < 第2步:依次访问网页 > -------------
|
# ------------- < 第2步:依次访问网页 > -------------
|
||||||
max_search_result = 5 # 最多收纳多少个网页的结果
|
max_search_result = 5 # 最多收纳多少个网页的结果
|
||||||
for index, url in enumerate(urls[:max_search_result]):
|
for index, url in enumerate(urls[:max_search_result]):
|
||||||
|
|||||||
@@ -75,7 +75,11 @@ def 连接bing搜索回答问题(txt, llm_kwargs, plugin_kwargs, chatbot, histor
|
|||||||
proxies, = get_conf('proxies')
|
proxies, = get_conf('proxies')
|
||||||
urls = bing_search(txt, proxies)
|
urls = bing_search(txt, proxies)
|
||||||
history = []
|
history = []
|
||||||
|
if len(urls) == 0:
|
||||||
|
chatbot.append((f"结论:{txt}",
|
||||||
|
"[Local Message] 受到bing限制,无法从bing获取信息!"))
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新
|
||||||
|
return
|
||||||
# ------------- < 第2步:依次访问网页 > -------------
|
# ------------- < 第2步:依次访问网页 > -------------
|
||||||
max_search_result = 8 # 最多收纳多少个网页的结果
|
max_search_result = 8 # 最多收纳多少个网页的结果
|
||||||
for index, url in enumerate(urls[:max_search_result]):
|
for index, url in enumerate(urls[:max_search_result]):
|
||||||
|
|||||||
@@ -24,12 +24,13 @@ explain_msg = """
|
|||||||
## 虚空终端插件说明:
|
## 虚空终端插件说明:
|
||||||
|
|
||||||
1. 请用**自然语言**描述您需要做什么。例如:
|
1. 请用**自然语言**描述您需要做什么。例如:
|
||||||
- 「请调用插件,为我翻译PDF论文,论文我刚刚放到上传区了。」
|
- 「请调用插件,为我翻译PDF论文,论文我刚刚放到上传区了」
|
||||||
- 「请调用插件翻译PDF论文,地址为https://www.nature.com/articles/s41586-019-1724-z.pdf」
|
- 「请调用插件翻译PDF论文,地址为https://openreview.net/pdf?id=rJl0r3R9KX」
|
||||||
- 「生成一张图片,图中鲜花怒放,绿草如茵,用插件实现。」
|
- 「把Arxiv论文翻译成中文PDF,arxiv论文的ID是1812.10695,记得用插件!」
|
||||||
|
- 「生成一张图片,图中鲜花怒放,绿草如茵,用插件实现」
|
||||||
- 「用插件翻译README,Github网址是https://github.com/facebookresearch/co-tracker」
|
- 「用插件翻译README,Github网址是https://github.com/facebookresearch/co-tracker」
|
||||||
- 「给爷翻译Arxiv论文,arxiv论文的ID是1812.10695,记得用插件,不要自己瞎搞!」
|
- 「我不喜欢当前的界面颜色,修改配置,把主题THEME更换为THEME="High-Contrast"」
|
||||||
- 「我不喜欢当前的界面颜色,修改配置,把主题THEME更换为THEME="High-Contrast"。」
|
- 「请调用插件,解析python源代码项目,代码我刚刚打包拖到上传区了」
|
||||||
- 「请问Transformer网络的结构是怎样的?」
|
- 「请问Transformer网络的结构是怎样的?」
|
||||||
|
|
||||||
2. 您可以打开插件下拉菜单以了解本项目的各种能力。
|
2. 您可以打开插件下拉菜单以了解本项目的各种能力。
|
||||||
@@ -45,7 +46,7 @@ explain_msg = """
|
|||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
from typing import List
|
from typing import List
|
||||||
from toolbox import CatchException, update_ui, gen_time_str
|
from toolbox import CatchException, update_ui, is_the_upload_folder
|
||||||
from toolbox import update_ui_lastest_msg, disable_auto_promotion
|
from toolbox import update_ui_lastest_msg, disable_auto_promotion
|
||||||
from request_llm.bridge_all import predict_no_ui_long_connection
|
from request_llm.bridge_all import predict_no_ui_long_connection
|
||||||
from crazy_functions.crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from crazy_functions.crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
@@ -111,7 +112,7 @@ def 虚空终端(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt
|
|||||||
|
|
||||||
# 用简单的关键词检测用户意图
|
# 用简单的关键词检测用户意图
|
||||||
is_certain, _ = analyze_intention_with_simple_rules(txt)
|
is_certain, _ = analyze_intention_with_simple_rules(txt)
|
||||||
if txt.startswith('private_upload/') and len(txt) == 34:
|
if is_the_upload_folder(txt):
|
||||||
state.set_state(chatbot=chatbot, key='has_provided_explaination', value=False)
|
state.set_state(chatbot=chatbot, key='has_provided_explaination', value=False)
|
||||||
appendix_msg = "\n\n**很好,您已经上传了文件**,现在请您描述您的需求。"
|
appendix_msg = "\n\n**很好,您已经上传了文件**,现在请您描述您的需求。"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from toolbox import update_ui
|
from toolbox import update_ui
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption
|
||||||
|
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||||
fast_debug = True
|
fast_debug = True
|
||||||
|
|
||||||
|
|
||||||
@@ -110,7 +111,8 @@ def ipynb解释(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbo
|
|||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
# <-------- 写入文件,退出 ---------->
|
# <-------- 写入文件,退出 ---------->
|
||||||
res = write_results_to_file(history)
|
res = write_history_to_file(history)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
chatbot.append(("完成了吗?", res))
|
chatbot.append(("完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
from toolbox import update_ui
|
from toolbox import update_ui, promote_file_to_downloadzone, disable_auto_promotion
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption, write_history_to_file
|
||||||
from .crazy_utils import input_clipping
|
from .crazy_utils import input_clipping
|
||||||
|
|
||||||
def 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
def 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
||||||
import os, copy
|
import os, copy
|
||||||
from .crazy_utils import request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency
|
from .crazy_utils import request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
msg = '正常'
|
disable_auto_promotion(chatbot=chatbot)
|
||||||
|
|
||||||
summary_batch_isolation = True
|
summary_batch_isolation = True
|
||||||
inputs_array = []
|
inputs_array = []
|
||||||
inputs_show_user_array = []
|
inputs_show_user_array = []
|
||||||
@@ -22,7 +23,7 @@ def 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs,
|
|||||||
file_content = f.read()
|
file_content = f.read()
|
||||||
prefix = "接下来请你逐文件分析下面的工程" if index==0 else ""
|
prefix = "接下来请你逐文件分析下面的工程" if index==0 else ""
|
||||||
i_say = prefix + f'请对下面的程序文件做一个概述文件名是{os.path.relpath(fp, project_folder)},文件代码是 ```{file_content}```'
|
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)}'
|
i_say_show_user = prefix + f'[{index}/{len(file_manifest)}] 请对下面的程序文件做一个概述: {fp}'
|
||||||
# 装载请求内容
|
# 装载请求内容
|
||||||
inputs_array.append(i_say)
|
inputs_array.append(i_say)
|
||||||
inputs_show_user_array.append(i_say_show_user)
|
inputs_show_user_array.append(i_say_show_user)
|
||||||
@@ -43,7 +44,8 @@ def 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs,
|
|||||||
# 全部文件解析完成,结果写入文件,准备对工程源代码进行汇总分析
|
# 全部文件解析完成,结果写入文件,准备对工程源代码进行汇总分析
|
||||||
report_part_1 = copy.deepcopy(gpt_response_collection)
|
report_part_1 = copy.deepcopy(gpt_response_collection)
|
||||||
history_to_return = report_part_1
|
history_to_return = report_part_1
|
||||||
res = write_results_to_file(report_part_1)
|
res = write_history_to_file(report_part_1)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
chatbot.append(("完成?", "逐个文件分析已完成。" + res + "\n\n正在开始汇总。"))
|
chatbot.append(("完成?", "逐个文件分析已完成。" + res + "\n\n正在开始汇总。"))
|
||||||
yield from update_ui(chatbot=chatbot, history=history_to_return) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history_to_return) # 刷新界面
|
||||||
|
|
||||||
@@ -97,7 +99,8 @@ def 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs,
|
|||||||
|
|
||||||
############################## <END> ##################################
|
############################## <END> ##################################
|
||||||
history_to_return.extend(report_part_2)
|
history_to_return.extend(report_part_2)
|
||||||
res = write_results_to_file(history_to_return)
|
res = write_history_to_file(history_to_return)
|
||||||
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
chatbot.append(("完成了吗?", res))
|
chatbot.append(("完成了吗?", res))
|
||||||
yield from update_ui(chatbot=chatbot, history=history_to_return) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history_to_return) # 刷新界面
|
||||||
|
|
||||||
@@ -106,9 +109,8 @@ def 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs,
|
|||||||
def 解析项目本身(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
def 解析项目本身(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
history = [] # 清空历史,以免输入溢出
|
history = [] # 清空历史,以免输入溢出
|
||||||
import glob
|
import glob
|
||||||
file_manifest = [f for f in glob.glob('./*.py') if ('test_project' not in f) and ('gpt_log' not in f)] + \
|
file_manifest = [f for f in glob.glob('./*.py')] + \
|
||||||
[f for f in glob.glob('./crazy_functions/*.py') if ('test_project' not in f) and ('gpt_log' not in f)]+ \
|
[f for f in glob.glob('./*/*.py')]
|
||||||
[f for f in glob.glob('./request_llm/*.py') if ('test_project' not in f) and ('gpt_log' not in f)]
|
|
||||||
project_folder = './'
|
project_folder = './'
|
||||||
if len(file_manifest) == 0:
|
if len(file_manifest) == 0:
|
||||||
report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到任何python文件: {txt}")
|
report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到任何python文件: {txt}")
|
||||||
@@ -134,6 +136,23 @@ def 解析一个Python项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, s
|
|||||||
return
|
return
|
||||||
yield from 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt)
|
yield from 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt)
|
||||||
|
|
||||||
|
@CatchException
|
||||||
|
def 解析一个Matlab项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
|
history = [] # 清空历史,以免输入溢出
|
||||||
|
import glob, os
|
||||||
|
if os.path.exists(txt):
|
||||||
|
project_folder = txt
|
||||||
|
else:
|
||||||
|
if txt == "": txt = '空空如也的输入栏'
|
||||||
|
report_execption(chatbot, history, a = f"解析Matlab项目: {txt}", b = f"找不到本地项目或无权访问: {txt}")
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
return
|
||||||
|
file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.m', recursive=True)]
|
||||||
|
if len(file_manifest) == 0:
|
||||||
|
report_execption(chatbot, history, a = f"解析Matlab项目: {txt}", b = f"找不到任何`.m`源文件: {txt}")
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
return
|
||||||
|
yield from 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt)
|
||||||
|
|
||||||
@CatchException
|
@CatchException
|
||||||
def 解析一个C项目的头文件(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
def 解析一个C项目的头文件(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import threading, time
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from .live_audio.aliyunASR import AliyunASR
|
from .live_audio.aliyunASR import AliyunASR
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
|
|
||||||
class WatchDog():
|
class WatchDog():
|
||||||
def __init__(self, timeout, bark_fn, interval=3, msg="") -> None:
|
def __init__(self, timeout, bark_fn, interval=3, msg="") -> None:
|
||||||
@@ -38,10 +39,22 @@ def chatbot2history(chatbot):
|
|||||||
history = []
|
history = []
|
||||||
for c in chatbot:
|
for c in chatbot:
|
||||||
for q in c:
|
for q in c:
|
||||||
if q not in ["[请讲话]", "[等待GPT响应]", "[正在等您说完问题]"]:
|
if q in ["[ 请讲话 ]", "[ 等待GPT响应 ]", "[ 正在等您说完问题 ]"]:
|
||||||
|
continue
|
||||||
|
elif q.startswith("[ 正在等您说完问题 ]"):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
history.append(q.strip('<div class="markdown-body">').strip('</div>').strip('<p>').strip('</p>'))
|
history.append(q.strip('<div class="markdown-body">').strip('</div>').strip('<p>').strip('</p>'))
|
||||||
return history
|
return history
|
||||||
|
|
||||||
|
def visualize_audio(chatbot, audio_shape):
|
||||||
|
if len(chatbot) == 0: chatbot.append(["[ 请讲话 ]", "[ 正在等您说完问题 ]"])
|
||||||
|
chatbot[-1] = list(chatbot[-1])
|
||||||
|
p1 = '「'
|
||||||
|
p2 = '」'
|
||||||
|
chatbot[-1][-1] = re.sub(p1+r'(.*)'+p2, '', chatbot[-1][-1])
|
||||||
|
chatbot[-1][-1] += (p1+f"`{audio_shape}`"+p2)
|
||||||
|
|
||||||
class AsyncGptTask():
|
class AsyncGptTask():
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.observe_future = []
|
self.observe_future = []
|
||||||
@@ -80,9 +93,10 @@ class InterviewAssistant(AliyunASR):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.capture_interval = 0.5 # second
|
self.capture_interval = 0.5 # second
|
||||||
self.stop = False
|
self.stop = False
|
||||||
self.parsed_text = ""
|
self.parsed_text = "" # 下个句子中已经说完的部分, 由 test_on_result_chg() 写入
|
||||||
self.parsed_sentence = ""
|
self.parsed_sentence = "" # 某段话的整个句子, 由 test_on_sentence_end() 写入
|
||||||
self.buffered_sentence = ""
|
self.buffered_sentence = "" #
|
||||||
|
self.audio_shape = "" # 音频的可视化表现, 由 audio_convertion_thread() 写入
|
||||||
self.event_on_result_chg = threading.Event()
|
self.event_on_result_chg = threading.Event()
|
||||||
self.event_on_entence_end = threading.Event()
|
self.event_on_entence_end = threading.Event()
|
||||||
self.event_on_commit_question = threading.Event()
|
self.event_on_commit_question = threading.Event()
|
||||||
@@ -117,7 +131,7 @@ class InterviewAssistant(AliyunASR):
|
|||||||
def begin(self, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
def begin(self, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
||||||
# main plugin function
|
# main plugin function
|
||||||
self.init(chatbot)
|
self.init(chatbot)
|
||||||
chatbot.append(["[请讲话]", "[正在等您说完问题]"])
|
chatbot.append(["[ 请讲话 ]", "[ 正在等您说完问题 ]"])
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
self.plugin_wd.begin_watch()
|
self.plugin_wd.begin_watch()
|
||||||
self.agt = AsyncGptTask()
|
self.agt = AsyncGptTask()
|
||||||
@@ -132,7 +146,7 @@ class InterviewAssistant(AliyunASR):
|
|||||||
self.plugin_wd.feed()
|
self.plugin_wd.feed()
|
||||||
|
|
||||||
if self.event_on_result_chg.is_set():
|
if self.event_on_result_chg.is_set():
|
||||||
# update audio decode result
|
# called when some words have finished
|
||||||
self.event_on_result_chg.clear()
|
self.event_on_result_chg.clear()
|
||||||
chatbot[-1] = list(chatbot[-1])
|
chatbot[-1] = list(chatbot[-1])
|
||||||
chatbot[-1][0] = self.buffered_sentence + self.parsed_text
|
chatbot[-1][0] = self.buffered_sentence + self.parsed_text
|
||||||
@@ -144,7 +158,11 @@ class InterviewAssistant(AliyunASR):
|
|||||||
# called when a sentence has ended
|
# called when a sentence has ended
|
||||||
self.event_on_entence_end.clear()
|
self.event_on_entence_end.clear()
|
||||||
self.parsed_text = self.parsed_sentence
|
self.parsed_text = self.parsed_sentence
|
||||||
self.buffered_sentence += self.parsed_sentence
|
self.buffered_sentence += self.parsed_text
|
||||||
|
chatbot[-1] = list(chatbot[-1])
|
||||||
|
chatbot[-1][0] = self.buffered_sentence
|
||||||
|
history = chatbot2history(chatbot)
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
if self.event_on_commit_question.is_set():
|
if self.event_on_commit_question.is_set():
|
||||||
# called when a question should be commited
|
# called when a question should be commited
|
||||||
@@ -153,14 +171,18 @@ class InterviewAssistant(AliyunASR):
|
|||||||
|
|
||||||
self.commit_wd.begin_watch()
|
self.commit_wd.begin_watch()
|
||||||
chatbot[-1] = list(chatbot[-1])
|
chatbot[-1] = list(chatbot[-1])
|
||||||
chatbot[-1] = [self.buffered_sentence, "[等待GPT响应]"]
|
chatbot[-1] = [self.buffered_sentence, "[ 等待GPT响应 ]"]
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
# add gpt task 创建子线程请求gpt,避免线程阻塞
|
# add gpt task 创建子线程请求gpt,避免线程阻塞
|
||||||
history = chatbot2history(chatbot)
|
history = chatbot2history(chatbot)
|
||||||
self.agt.add_async_gpt_task(self.buffered_sentence, len(chatbot)-1, llm_kwargs, history, system_prompt)
|
self.agt.add_async_gpt_task(self.buffered_sentence, len(chatbot)-1, llm_kwargs, history, system_prompt)
|
||||||
|
|
||||||
self.buffered_sentence = ""
|
self.buffered_sentence = ""
|
||||||
chatbot.append(["[请讲话]", "[正在等您说完问题]"])
|
chatbot.append(["[ 请讲话 ]", "[ 正在等您说完问题 ]"])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
|
if not self.event_on_result_chg.is_set() and not self.event_on_entence_end.is_set() and not self.event_on_commit_question.is_set():
|
||||||
|
visualize_audio(chatbot, self.audio_shape)
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
if len(self.stop_msg) != 0:
|
if len(self.stop_msg) != 0:
|
||||||
@@ -179,7 +201,7 @@ def 语音助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt
|
|||||||
import nls
|
import nls
|
||||||
from scipy import io
|
from scipy import io
|
||||||
except:
|
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```"])
|
chatbot.append(["导入依赖失败", "使用该模块需要额外依赖, 安装方法:```pip install --upgrade aliyun-python-sdk-core==2.13.3 pyOpenSSL webrtcvad scipy git+https://github.com/aliyun/alibabacloud-nls-python-sdk.git```"])
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from toolbox import update_ui
|
from toolbox import update_ui
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption
|
||||||
|
from toolbox import write_history_to_file, promote_file_to_downloadzone
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
fast_debug = False
|
|
||||||
|
|
||||||
|
|
||||||
def 解析Paper(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
def 解析Paper(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
||||||
@@ -17,32 +17,29 @@ def 解析Paper(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbo
|
|||||||
chatbot.append((i_say_show_user, "[Local Message] waiting gpt response."))
|
chatbot.append((i_say_show_user, "[Local Message] waiting gpt response."))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
if not fast_debug:
|
msg = '正常'
|
||||||
msg = '正常'
|
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(i_say, i_say_show_user, llm_kwargs, chatbot, history=[], sys_prompt=system_prompt) # 带超时倒计时
|
||||||
# ** gpt request **
|
chatbot[-1] = (i_say_show_user, gpt_say)
|
||||||
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(i_say, i_say_show_user, llm_kwargs, chatbot, history=[], sys_prompt=system_prompt) # 带超时倒计时
|
history.append(i_say_show_user); history.append(gpt_say)
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
||||||
chatbot[-1] = (i_say_show_user, gpt_say)
|
time.sleep(2)
|
||||||
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)])
|
all_file = ', '.join([os.path.relpath(fp, project_folder) for index, fp in enumerate(file_manifest)])
|
||||||
i_say = f'根据以上你自己的分析,对全文进行概括,用学术性语言写一段中文摘要,然后再写一段英文摘要(包括{all_file})。'
|
i_say = f'根据以上你自己的分析,对全文进行概括,用学术性语言写一段中文摘要,然后再写一段英文摘要(包括{all_file})。'
|
||||||
chatbot.append((i_say, "[Local Message] waiting gpt response."))
|
chatbot.append((i_say, "[Local Message] waiting gpt response."))
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
if not fast_debug:
|
msg = '正常'
|
||||||
msg = '正常'
|
# ** gpt request **
|
||||||
# ** gpt request **
|
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(i_say, i_say, llm_kwargs, chatbot, history=history, sys_prompt=system_prompt) # 带超时倒计时
|
||||||
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(i_say, i_say, llm_kwargs, chatbot, history=history, sys_prompt=system_prompt) # 带超时倒计时
|
|
||||||
|
|
||||||
chatbot[-1] = (i_say, gpt_say)
|
chatbot[-1] = (i_say, gpt_say)
|
||||||
history.append(i_say); history.append(gpt_say)
|
history.append(i_say); history.append(gpt_say)
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
||||||
res = write_results_to_file(history)
|
res = write_history_to_file(history)
|
||||||
chatbot.append(("完成了吗?", res))
|
promote_file_to_downloadzone(res, chatbot=chatbot)
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
chatbot.append(("完成了吗?", res))
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,81 @@
|
|||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption, promote_file_to_downloadzone
|
||||||
from toolbox import update_ui
|
from toolbox import update_ui, update_ui_lastest_msg, disable_auto_promotion, write_history_to_file
|
||||||
|
import logging
|
||||||
|
import requests
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
|
||||||
|
ENABLE_ALL_VERSION_SEARCH = True
|
||||||
|
|
||||||
def get_meta_information(url, chatbot, history):
|
def get_meta_information(url, chatbot, history):
|
||||||
import requests
|
|
||||||
import arxiv
|
import arxiv
|
||||||
import difflib
|
import difflib
|
||||||
|
import re
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from toolbox import get_conf
|
from toolbox import get_conf
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
session = requests.session()
|
||||||
|
|
||||||
proxies, = get_conf('proxies')
|
proxies, = get_conf('proxies')
|
||||||
headers = {
|
headers = {
|
||||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
|
||||||
|
'Accept-Encoding': 'gzip, deflate, br',
|
||||||
|
'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7',
|
||||||
|
'Cache-Control':'max-age=0',
|
||||||
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
||||||
|
'Connection': 'keep-alive'
|
||||||
}
|
}
|
||||||
# 发送 GET 请求
|
try:
|
||||||
response = requests.get(url, proxies=proxies, headers=headers)
|
session.proxies.update(proxies)
|
||||||
|
except:
|
||||||
|
report_execption(chatbot, history,
|
||||||
|
a=f"获取代理失败 无代理状态下很可能无法访问OpenAI家族的模型及谷歌学术 建议:检查USE_PROXY选项是否修改。",
|
||||||
|
b=f"尝试直接连接")
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
session.headers.update(headers)
|
||||||
|
|
||||||
|
response = session.get(url)
|
||||||
# 解析网页内容
|
# 解析网页内容
|
||||||
soup = BeautifulSoup(response.text, "html.parser")
|
soup = BeautifulSoup(response.text, "html.parser")
|
||||||
|
|
||||||
def string_similar(s1, s2):
|
def string_similar(s1, s2):
|
||||||
return difflib.SequenceMatcher(None, s1, s2).quick_ratio()
|
return difflib.SequenceMatcher(None, s1, s2).quick_ratio()
|
||||||
|
|
||||||
|
if ENABLE_ALL_VERSION_SEARCH:
|
||||||
|
def search_all_version(url):
|
||||||
|
time.sleep(random.randint(1,5)) # 睡一会防止触发google反爬虫
|
||||||
|
response = session.get(url)
|
||||||
|
soup = BeautifulSoup(response.text, "html.parser")
|
||||||
|
|
||||||
|
for result in soup.select(".gs_ri"):
|
||||||
|
try:
|
||||||
|
url = result.select_one(".gs_rt").a['href']
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
arxiv_id = extract_arxiv_id(url)
|
||||||
|
if not arxiv_id:
|
||||||
|
continue
|
||||||
|
search = arxiv.Search(
|
||||||
|
id_list=[arxiv_id],
|
||||||
|
max_results=1,
|
||||||
|
sort_by=arxiv.SortCriterion.Relevance,
|
||||||
|
)
|
||||||
|
try: paper = next(search.results())
|
||||||
|
except: paper = None
|
||||||
|
return paper
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def extract_arxiv_id(url):
|
||||||
|
# 返回给定的url解析出的arxiv_id,如url未成功匹配返回None
|
||||||
|
pattern = r'arxiv.org/abs/([^/]+)'
|
||||||
|
match = re.search(pattern, url)
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
profile = []
|
profile = []
|
||||||
# 获取所有文章的标题和作者
|
# 获取所有文章的标题和作者
|
||||||
for result in soup.select(".gs_ri"):
|
for result in soup.select(".gs_ri"):
|
||||||
@@ -31,32 +86,45 @@ def get_meta_information(url, chatbot, history):
|
|||||||
except:
|
except:
|
||||||
citation = 'cited by 0'
|
citation = 'cited by 0'
|
||||||
abstract = result.select_one(".gs_rs").text.strip() # 摘要在 .gs_rs 中的文本,需要清除首尾空格
|
abstract = result.select_one(".gs_rs").text.strip() # 摘要在 .gs_rs 中的文本,需要清除首尾空格
|
||||||
|
|
||||||
|
# 首先在arxiv上搜索,获取文章摘要
|
||||||
search = arxiv.Search(
|
search = arxiv.Search(
|
||||||
query = title,
|
query = title,
|
||||||
max_results = 1,
|
max_results = 1,
|
||||||
sort_by = arxiv.SortCriterion.Relevance,
|
sort_by = arxiv.SortCriterion.Relevance,
|
||||||
)
|
)
|
||||||
try:
|
try: paper = next(search.results())
|
||||||
paper = next(search.results())
|
except: paper = None
|
||||||
if string_similar(title, paper.title) > 0.90: # same paper
|
|
||||||
abstract = paper.summary.replace('\n', ' ')
|
is_match = paper is not None and string_similar(title, paper.title) > 0.90
|
||||||
is_paper_in_arxiv = True
|
|
||||||
else: # different paper
|
# 如果在Arxiv上匹配失败,检索文章的历史版本的题目
|
||||||
abstract = abstract
|
if not is_match and ENABLE_ALL_VERSION_SEARCH:
|
||||||
is_paper_in_arxiv = False
|
other_versions_page_url = [tag['href'] for tag in result.select_one('.gs_flb').select('.gs_nph') if 'cluster' in tag['href']]
|
||||||
paper = next(search.results())
|
if len(other_versions_page_url) > 0:
|
||||||
except:
|
other_versions_page_url = other_versions_page_url[0]
|
||||||
|
paper = search_all_version('http://' + urlparse(url).netloc + other_versions_page_url)
|
||||||
|
is_match = paper is not None and string_similar(title, paper.title) > 0.90
|
||||||
|
|
||||||
|
if is_match:
|
||||||
|
# same paper
|
||||||
|
abstract = paper.summary.replace('\n', ' ')
|
||||||
|
is_paper_in_arxiv = True
|
||||||
|
else:
|
||||||
|
# different paper
|
||||||
abstract = abstract
|
abstract = abstract
|
||||||
is_paper_in_arxiv = False
|
is_paper_in_arxiv = False
|
||||||
print(title)
|
|
||||||
print(author)
|
logging.info('[title]:' + title)
|
||||||
print(citation)
|
logging.info('[author]:' + author)
|
||||||
|
logging.info('[citation]:' + citation)
|
||||||
|
|
||||||
profile.append({
|
profile.append({
|
||||||
'title':title,
|
'title': title,
|
||||||
'author':author,
|
'author': author,
|
||||||
'citation':citation,
|
'citation': citation,
|
||||||
'abstract':abstract,
|
'abstract': abstract,
|
||||||
'is_paper_in_arxiv':is_paper_in_arxiv,
|
'is_paper_in_arxiv': is_paper_in_arxiv,
|
||||||
})
|
})
|
||||||
|
|
||||||
chatbot[-1] = [chatbot[-1][0], title + f'\n\n是否在arxiv中(不在arxiv中无法获取完整摘要):{is_paper_in_arxiv}\n\n' + abstract]
|
chatbot[-1] = [chatbot[-1][0], title + f'\n\n是否在arxiv中(不在arxiv中无法获取完整摘要):{is_paper_in_arxiv}\n\n' + abstract]
|
||||||
@@ -65,6 +133,7 @@ def get_meta_information(url, chatbot, history):
|
|||||||
|
|
||||||
@CatchException
|
@CatchException
|
||||||
def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
|
disable_auto_promotion(chatbot=chatbot)
|
||||||
# 基本信息:功能、贡献者
|
# 基本信息:功能、贡献者
|
||||||
chatbot.append([
|
chatbot.append([
|
||||||
"函数插件功能?",
|
"函数插件功能?",
|
||||||
@@ -86,6 +155,9 @@ def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst
|
|||||||
# 清空历史,以免输入溢出
|
# 清空历史,以免输入溢出
|
||||||
history = []
|
history = []
|
||||||
meta_paper_info_list = yield from get_meta_information(txt, chatbot, history)
|
meta_paper_info_list = yield from get_meta_information(txt, chatbot, history)
|
||||||
|
if len(meta_paper_info_list) == 0:
|
||||||
|
yield from update_ui_lastest_msg(lastmsg='获取文献失败,可能触发了google反爬虫机制。',chatbot=chatbot, history=history, delay=0)
|
||||||
|
return
|
||||||
batchsize = 5
|
batchsize = 5
|
||||||
for batch in range(math.ceil(len(meta_paper_info_list)/batchsize)):
|
for batch in range(math.ceil(len(meta_paper_info_list)/batchsize)):
|
||||||
if len(meta_paper_info_list[:batchsize]) > 0:
|
if len(meta_paper_info_list[:batchsize]) > 0:
|
||||||
@@ -107,6 +179,7 @@ def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst
|
|||||||
"已经全部完成,您可以试试让AI写一个Related Works,例如您可以继续输入Write a \"Related Works\" section about \"你搜索的研究领域\" for me."])
|
"已经全部完成,您可以试试让AI写一个Related Works,例如您可以继续输入Write a \"Related Works\" section about \"你搜索的研究领域\" for me."])
|
||||||
msg = '正常'
|
msg = '正常'
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
||||||
res = write_results_to_file(history)
|
path = write_history_to_file(history)
|
||||||
chatbot.append(("完成了吗?", res));
|
promote_file_to_downloadzone(path, chatbot=chatbot)
|
||||||
|
chatbot.append(("完成了吗?", path));
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
# @Time : 2023/4/19
|
# @Time : 2023/4/19
|
||||||
# @Author : Spike
|
# @Author : Spike
|
||||||
# @Descr :
|
# @Descr :
|
||||||
from toolbox import update_ui
|
from toolbox import update_ui, get_conf
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file, get_log_folder
|
from toolbox import CatchException
|
||||||
from crazy_functions.crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from crazy_functions.crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
|
|
||||||
|
|
||||||
@@ -30,14 +30,13 @@ def 猜你想问(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt
|
|||||||
|
|
||||||
@CatchException
|
@CatchException
|
||||||
def 清除缓存(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
def 清除缓存(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
chatbot.append(['清除本地缓存数据', '执行中. 删除 gpt_log & private_upload'])
|
chatbot.append(['清除本地缓存数据', '执行中. 删除数据'])
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
|
|
||||||
import shutil, os
|
import shutil, os
|
||||||
gpt_log_dir = os.path.join(os.path.dirname(__file__), '..', 'gpt_log')
|
PATH_PRIVATE_UPLOAD, PATH_LOGGING = get_conf('PATH_PRIVATE_UPLOAD', 'PATH_LOGGING')
|
||||||
private_upload_dir = os.path.join(os.path.dirname(__file__), '..', 'private_upload')
|
shutil.rmtree(PATH_LOGGING, ignore_errors=True)
|
||||||
shutil.rmtree(gpt_log_dir, ignore_errors=True)
|
shutil.rmtree(PATH_PRIVATE_UPLOAD, ignore_errors=True)
|
||||||
shutil.rmtree(private_upload_dir, ignore_errors=True)
|
|
||||||
|
|
||||||
chatbot.append(['清除本地缓存数据', '执行完成'])
|
chatbot.append(['清除本地缓存数据', '执行完成'])
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||||
@@ -1,7 +1,84 @@
|
|||||||
#【请修改完参数后,删除此行】请在以下方案中选择一种,然后删除其他的方案,最后docker-compose up运行 | Please choose from one of these options below, delete other options as well as This Line
|
## ===================================================
|
||||||
|
# docker-compose.yml
|
||||||
|
## ===================================================
|
||||||
|
# 1. 请在以下方案中选择任意一种,然后删除其他的方案
|
||||||
|
# 2. 修改你选择的方案中的environment环境变量,详情请见github wiki或者config.py
|
||||||
|
# 3. 选择一种暴露服务端口的方法,并对相应的配置做出修改:
|
||||||
|
# 【方法1: 适用于Linux,很方便,可惜windows不支持】与宿主的网络融合为一体,这个是默认配置
|
||||||
|
# network_mode: "host"
|
||||||
|
# 【方法2: 适用于所有系统包括Windows和MacOS】端口映射,把容器的端口映射到宿主的端口(注意您需要先删除network_mode: "host",再追加以下内容)
|
||||||
|
# ports:
|
||||||
|
# - "12345:12345" # 注意!12345必须与WEB_PORT环境变量相互对应
|
||||||
|
# 4. 最后`docker-compose up`运行
|
||||||
|
# 5. 如果希望使用显卡,请关注 LOCAL_MODEL_DEVICE 和 英伟达显卡运行时 选项
|
||||||
|
## ===================================================
|
||||||
|
# 1. Please choose one of the following options and delete the others.
|
||||||
|
# 2. Modify the environment variables in the selected option, see GitHub wiki or config.py for more details.
|
||||||
|
# 3. Choose a method to expose the server port and make the corresponding configuration changes:
|
||||||
|
# [Method 1: Suitable for Linux, convenient, but not supported for Windows] Fusion with the host network, this is the default configuration
|
||||||
|
# network_mode: "host"
|
||||||
|
# [Method 2: Suitable for all systems including Windows and MacOS] Port mapping, mapping the container port to the host port (note that you need to delete network_mode: "host" first, and then add the following content)
|
||||||
|
# ports:
|
||||||
|
# - "12345: 12345" # Note! 12345 must correspond to the WEB_PORT environment variable.
|
||||||
|
# 4. Finally, run `docker-compose up`.
|
||||||
|
# 5. If you want to use a graphics card, pay attention to the LOCAL_MODEL_DEVICE and Nvidia GPU runtime options.
|
||||||
|
## ===================================================
|
||||||
|
|
||||||
## ===================================================
|
## ===================================================
|
||||||
## 【方案一】 如果不需要运行本地模型(仅chatgpt,newbing类远程服务)
|
## 【方案零】 部署项目的全部能力(这个是包含cuda和latex的大型镜像。如果您网速慢、硬盘小或没有显卡,则不推荐使用这个)
|
||||||
|
## ===================================================
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
gpt_academic_full_capability:
|
||||||
|
image: ghcr.io/binary-husky/gpt_academic_with_all_capacity:master
|
||||||
|
environment:
|
||||||
|
# 请查阅 `config.py`或者 github wiki 以查看所有的配置信息
|
||||||
|
API_KEY: ' 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 '
|
||||||
|
# USE_PROXY: ' True '
|
||||||
|
# proxies: ' { "http": "http://localhost:10881", "https": "http://localhost:10881", } '
|
||||||
|
LLM_MODEL: ' gpt-3.5-turbo '
|
||||||
|
AVAIL_LLM_MODELS: ' ["gpt-3.5-turbo", "gpt-4", "qianfan", "sparkv2", "spark", "chatglm"] '
|
||||||
|
BAIDU_CLOUD_API_KEY : ' bTUtwEAveBrQipEowUvDwYWq '
|
||||||
|
BAIDU_CLOUD_SECRET_KEY : ' jqXtLvXiVw6UNdjliATTS61rllG8Iuni '
|
||||||
|
XFYUN_APPID: ' 53a8d816 '
|
||||||
|
XFYUN_API_SECRET: ' MjMxNDQ4NDE4MzM0OSNlNjQ2NTlhMTkx '
|
||||||
|
XFYUN_API_KEY: ' 95ccdec285364869d17b33e75ee96447 '
|
||||||
|
ENABLE_AUDIO: ' False '
|
||||||
|
DEFAULT_WORKER_NUM: ' 20 '
|
||||||
|
WEB_PORT: ' 12345 '
|
||||||
|
ADD_WAIFU: ' False '
|
||||||
|
ALIYUN_APPKEY: ' RxPlZrM88DnAFkZK '
|
||||||
|
THEME: ' Chuanhu-Small-and-Beautiful '
|
||||||
|
ALIYUN_ACCESSKEY: ' LTAI5t6BrFUzxRXVGUWnekh1 '
|
||||||
|
ALIYUN_SECRET: ' eHmI20SVWIwQZxCiTD2bGQVspP9i68 '
|
||||||
|
# LOCAL_MODEL_DEVICE: ' cuda '
|
||||||
|
|
||||||
|
# 加载英伟达显卡运行时
|
||||||
|
# runtime: nvidia
|
||||||
|
# deploy:
|
||||||
|
# resources:
|
||||||
|
# reservations:
|
||||||
|
# devices:
|
||||||
|
# - driver: nvidia
|
||||||
|
# count: 1
|
||||||
|
# capabilities: [gpu]
|
||||||
|
|
||||||
|
# 【WEB_PORT暴露方法1: 适用于Linux】与宿主的网络融合
|
||||||
|
network_mode: "host"
|
||||||
|
|
||||||
|
# 【WEB_PORT暴露方法2: 适用于所有系统】端口映射
|
||||||
|
# ports:
|
||||||
|
# - "12345:12345" # 12345必须与WEB_PORT相互对应
|
||||||
|
|
||||||
|
# 启动容器后,运行main.py主程序
|
||||||
|
command: >
|
||||||
|
bash -c "python3 -u main.py"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## ===================================================
|
||||||
|
## 【方案一】 如果不需要运行本地模型(仅 chatgpt, azure, 星火, 千帆, claude 等在线大模型服务)
|
||||||
## ===================================================
|
## ===================================================
|
||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
@@ -13,7 +90,7 @@ services:
|
|||||||
USE_PROXY: ' True '
|
USE_PROXY: ' True '
|
||||||
proxies: ' { "http": "socks5h://localhost:10880", "https": "socks5h://localhost:10880", } '
|
proxies: ' { "http": "socks5h://localhost:10880", "https": "socks5h://localhost:10880", } '
|
||||||
LLM_MODEL: ' gpt-3.5-turbo '
|
LLM_MODEL: ' gpt-3.5-turbo '
|
||||||
AVAIL_LLM_MODELS: ' ["gpt-3.5-turbo", "api2d-gpt-3.5-turbo", "gpt-4", "api2d-gpt-4", "newbing"] '
|
AVAIL_LLM_MODELS: ' ["gpt-3.5-turbo", "api2d-gpt-3.5-turbo", "gpt-4", "api2d-gpt-4", "sparkv2", "qianfan"] '
|
||||||
WEB_PORT: ' 22303 '
|
WEB_PORT: ' 22303 '
|
||||||
ADD_WAIFU: ' True '
|
ADD_WAIFU: ' True '
|
||||||
# THEME: ' Chuanhu-Small-and-Beautiful '
|
# THEME: ' Chuanhu-Small-and-Beautiful '
|
||||||
|
|||||||
@@ -1,62 +1,2 @@
|
|||||||
# How to build | 如何构建: docker build -t gpt-academic --network=host -f Dockerfile+ChatGLM .
|
# 此Dockerfile不再维护,请前往docs/GithubAction+ChatGLM+Moss
|
||||||
# How to run | (1) 我想直接一键运行(选择0号GPU): docker run --rm -it --net=host --gpus \"device=0\" gpt-academic
|
|
||||||
# How to run | (2) 我想运行之前进容器做一些调整(选择1号GPU): docker run --rm -it --net=host --gpus \"device=1\" gpt-academic bash
|
|
||||||
|
|
||||||
# 从NVIDIA源,从而支持显卡运损(检查宿主的nvidia-smi中的cuda版本必须>=11.3)
|
|
||||||
FROM nvidia/cuda:11.3.1-runtime-ubuntu20.04
|
|
||||||
ARG useProxyNetwork=''
|
|
||||||
RUN apt-get update
|
|
||||||
RUN apt-get install -y curl proxychains curl
|
|
||||||
RUN apt-get install -y git python python3 python-dev python3-dev --fix-missing
|
|
||||||
|
|
||||||
# 配置代理网络(构建Docker镜像时使用)
|
|
||||||
# # comment out below if you do not need proxy network | 如果不需要翻墙 - 从此行向下删除
|
|
||||||
RUN $useProxyNetwork curl cip.cc
|
|
||||||
RUN sed -i '$ d' /etc/proxychains.conf
|
|
||||||
RUN sed -i '$ d' /etc/proxychains.conf
|
|
||||||
# 在这里填写主机的代理协议(用于从github拉取代码)
|
|
||||||
RUN echo "socks5 127.0.0.1 10880" >> /etc/proxychains.conf
|
|
||||||
ARG useProxyNetwork=proxychains
|
|
||||||
# # comment out above if you do not need proxy network | 如果不需要翻墙 - 从此行向上删除
|
|
||||||
|
|
||||||
|
|
||||||
# use python3 as the system default python
|
|
||||||
RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.8
|
|
||||||
# 下载pytorch
|
|
||||||
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/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
|
|
||||||
|
|
||||||
# 预热CHATGLM参数(非必要 可选步骤)
|
|
||||||
RUN echo ' \n\
|
|
||||||
from transformers import AutoModel, AutoTokenizer \n\
|
|
||||||
chatglm_tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True) \n\
|
|
||||||
chatglm_model = AutoModel.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True).float() ' >> warm_up_chatglm.py
|
|
||||||
RUN python3 -u warm_up_chatglm.py
|
|
||||||
|
|
||||||
# 禁用缓存,确保更新代码
|
|
||||||
ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" skipcache
|
|
||||||
RUN $useProxyNetwork git pull
|
|
||||||
|
|
||||||
# 预热Tiktoken模块
|
|
||||||
RUN python3 -c 'from check_proxy import warm_up_modules; warm_up_modules()'
|
|
||||||
|
|
||||||
# 为chatgpt-academic配置代理和API-KEY (非必要 可选步骤)
|
|
||||||
# 可同时填写多个API-KEY,支持openai的key和api2d的key共存,用英文逗号分割,例如API_KEY = "sk-openaikey1,fkxxxx-api2dkey2,........"
|
|
||||||
# LLM_MODEL 是选择初始的模型
|
|
||||||
# LOCAL_MODEL_DEVICE 是选择chatglm等本地模型运行的设备,可选 cpu 和 cuda
|
|
||||||
# [说明: 以下内容与`config.py`一一对应,请查阅config.py来完成一下配置的填写]
|
|
||||||
RUN echo ' \n\
|
|
||||||
API_KEY = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,fkxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \n\
|
|
||||||
USE_PROXY = True \n\
|
|
||||||
LLM_MODEL = "chatglm" \n\
|
|
||||||
LOCAL_MODEL_DEVICE = "cuda" \n\
|
|
||||||
proxies = { "http": "socks5h://localhost:10880", "https": "socks5h://localhost:10880", } ' >> config_private.py
|
|
||||||
|
|
||||||
# 启动
|
|
||||||
CMD ["python3", "-u", "main.py"]
|
|
||||||
|
|||||||
@@ -1,59 +1 @@
|
|||||||
# How to build | 如何构建: docker build -t gpt-academic-jittor --network=host -f Dockerfile+ChatGLM .
|
# 此Dockerfile不再维护,请前往docs/GithubAction+JittorLLMs
|
||||||
# How to run | (1) 我想直接一键运行(选择0号GPU): docker run --rm -it --net=host --gpus \"device=0\" gpt-academic-jittor bash
|
|
||||||
# How to run | (2) 我想运行之前进容器做一些调整(选择1号GPU): docker run --rm -it --net=host --gpus \"device=1\" gpt-academic-jittor bash
|
|
||||||
|
|
||||||
# 从NVIDIA源,从而支持显卡运损(检查宿主的nvidia-smi中的cuda版本必须>=11.3)
|
|
||||||
FROM nvidia/cuda:11.3.1-runtime-ubuntu20.04
|
|
||||||
ARG useProxyNetwork=''
|
|
||||||
RUN apt-get update
|
|
||||||
RUN apt-get install -y curl proxychains curl g++
|
|
||||||
RUN apt-get install -y git python python3 python-dev python3-dev --fix-missing
|
|
||||||
|
|
||||||
# 配置代理网络(构建Docker镜像时使用)
|
|
||||||
# # comment out below if you do not need proxy network | 如果不需要翻墙 - 从此行向下删除
|
|
||||||
RUN $useProxyNetwork curl cip.cc
|
|
||||||
RUN sed -i '$ d' /etc/proxychains.conf
|
|
||||||
RUN sed -i '$ d' /etc/proxychains.conf
|
|
||||||
# 在这里填写主机的代理协议(用于从github拉取代码)
|
|
||||||
RUN echo "socks5 127.0.0.1 10880" >> /etc/proxychains.conf
|
|
||||||
ARG useProxyNetwork=proxychains
|
|
||||||
# # comment out above if you do not need proxy network | 如果不需要翻墙 - 从此行向上删除
|
|
||||||
|
|
||||||
|
|
||||||
# use python3 as the system default python
|
|
||||||
RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.8
|
|
||||||
# 下载pytorch
|
|
||||||
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/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
|
|
||||||
RUN $useProxyNetwork python3 -m pip install -r request_llm/requirements_jittorllms.txt -i https://pypi.jittor.org/simple -I
|
|
||||||
|
|
||||||
# 下载JittorLLMs
|
|
||||||
RUN $useProxyNetwork git clone https://github.com/binary-husky/JittorLLMs.git --depth 1 request_llm/jittorllms
|
|
||||||
|
|
||||||
# 禁用缓存,确保更新代码
|
|
||||||
ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" skipcache
|
|
||||||
RUN $useProxyNetwork git pull
|
|
||||||
|
|
||||||
# 预热Tiktoken模块
|
|
||||||
RUN python3 -c 'from check_proxy import warm_up_modules; warm_up_modules()'
|
|
||||||
|
|
||||||
# 为chatgpt-academic配置代理和API-KEY (非必要 可选步骤)
|
|
||||||
# 可同时填写多个API-KEY,支持openai的key和api2d的key共存,用英文逗号分割,例如API_KEY = "sk-openaikey1,fkxxxx-api2dkey2,........"
|
|
||||||
# LLM_MODEL 是选择初始的模型
|
|
||||||
# LOCAL_MODEL_DEVICE 是选择chatglm等本地模型运行的设备,可选 cpu 和 cuda
|
|
||||||
# [说明: 以下内容与`config.py`一一对应,请查阅config.py来完成一下配置的填写]
|
|
||||||
RUN echo ' \n\
|
|
||||||
API_KEY = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,fkxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \n\
|
|
||||||
USE_PROXY = True \n\
|
|
||||||
LLM_MODEL = "chatglm" \n\
|
|
||||||
LOCAL_MODEL_DEVICE = "cuda" \n\
|
|
||||||
proxies = { "http": "socks5h://localhost:10880", "https": "socks5h://localhost:10880", } ' >> config_private.py
|
|
||||||
|
|
||||||
# 启动
|
|
||||||
CMD ["python3", "-u", "main.py"]
|
|
||||||
@@ -1,27 +1 @@
|
|||||||
# 此Dockerfile适用于“无本地模型”的环境构建,如果需要使用chatglm等本地模型,请参考 docs/Dockerfile+ChatGLM
|
# 此Dockerfile不再维护,请前往docs/GithubAction+NoLocal+Latex
|
||||||
# - 1 修改 `config.py`
|
|
||||||
# - 2 构建 docker build -t gpt-academic-nolocal-latex -f docs/Dockerfile+NoLocal+Latex .
|
|
||||||
# - 3 运行 docker run -v /home/fuqingxu/arxiv_cache:/root/arxiv_cache --rm -it --net=host gpt-academic-nolocal-latex
|
|
||||||
|
|
||||||
FROM fuqingxu/python311_texlive_ctex:latest
|
|
||||||
|
|
||||||
# 指定路径
|
|
||||||
WORKDIR /gpt
|
|
||||||
|
|
||||||
ARG useProxyNetwork=''
|
|
||||||
|
|
||||||
RUN $useProxyNetwork pip3 install gradio openai numpy arxiv rich -i https://pypi.douban.com/simple/
|
|
||||||
RUN $useProxyNetwork pip3 install colorama Markdown pygments pymupdf -i https://pypi.douban.com/simple/
|
|
||||||
|
|
||||||
# 装载项目文件
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
|
|
||||||
# 安装依赖
|
|
||||||
RUN $useProxyNetwork pip3 install -r requirements.txt -i https://pypi.douban.com/simple/
|
|
||||||
|
|
||||||
# 可选步骤,用于预热模块
|
|
||||||
RUN python3 -c 'from check_proxy import warm_up_modules; warm_up_modules()'
|
|
||||||
|
|
||||||
# 启动
|
|
||||||
CMD ["python3", "-u", "main.py"]
|
|
||||||
|
|||||||
36
docs/GithubAction+AllCapacity
普通文件
36
docs/GithubAction+AllCapacity
普通文件
@@ -0,0 +1,36 @@
|
|||||||
|
# docker build -t gpt-academic-all-capacity -f docs/GithubAction+AllCapacity --network=host --build-arg http_proxy=http://localhost:10881 --build-arg https_proxy=http://localhost:10881 .
|
||||||
|
|
||||||
|
# 从NVIDIA源,从而支持显卡(检查宿主的nvidia-smi中的cuda版本必须>=11.3)
|
||||||
|
FROM fuqingxu/11.3.1-runtime-ubuntu20.04-with-texlive:latest
|
||||||
|
|
||||||
|
# use python3 as the system default python
|
||||||
|
WORKDIR /gpt
|
||||||
|
RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.8
|
||||||
|
# 下载pytorch
|
||||||
|
RUN python3 -m pip install torch --extra-index-url https://download.pytorch.org/whl/cu113
|
||||||
|
# 准备pip依赖
|
||||||
|
RUN python3 -m pip install openai numpy arxiv rich
|
||||||
|
RUN python3 -m pip install colorama Markdown pygments pymupdf
|
||||||
|
RUN python3 -m pip install python-docx moviepy pdfminer
|
||||||
|
RUN python3 -m pip install zh_langchain==0.2.1 pypinyin
|
||||||
|
RUN python3 -m pip install rarfile py7zr
|
||||||
|
RUN python3 -m pip install aliyun-python-sdk-core==2.13.3 pyOpenSSL webrtcvad scipy git+https://github.com/aliyun/alibabacloud-nls-python-sdk.git
|
||||||
|
# 下载分支
|
||||||
|
WORKDIR /gpt
|
||||||
|
RUN git clone --depth=1 https://github.com/binary-husky/gpt_academic.git
|
||||||
|
WORKDIR /gpt/gpt_academic
|
||||||
|
RUN git clone --depth=1 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
|
||||||
|
RUN python3 -m pip install -r request_llm/requirements_qwen.txt
|
||||||
|
RUN python3 -m pip install -r request_llm/requirements_chatglm.txt
|
||||||
|
RUN python3 -m pip install -r request_llm/requirements_newbing.txt
|
||||||
|
RUN python3 -m pip install nougat-ocr
|
||||||
|
|
||||||
|
|
||||||
|
# 预热Tiktoken模块
|
||||||
|
RUN python3 -c 'from check_proxy import warm_up_modules; warm_up_modules()'
|
||||||
|
|
||||||
|
# 启动
|
||||||
|
CMD ["python3", "-u", "main.py"]
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
# 从NVIDIA源,从而支持显卡运损(检查宿主的nvidia-smi中的cuda版本必须>=11.3)
|
# 从NVIDIA源,从而支持显卡运损(检查宿主的nvidia-smi中的cuda版本必须>=11.3)
|
||||||
FROM nvidia/cuda:11.3.1-runtime-ubuntu20.04
|
FROM nvidia/cuda:11.3.1-runtime-ubuntu20.04
|
||||||
ARG useProxyNetwork=''
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get install -y curl proxychains curl gcc
|
RUN apt-get install -y curl proxychains curl gcc
|
||||||
RUN apt-get install -y git python python3 python-dev python3-dev --fix-missing
|
RUN apt-get install -y git python python3 python-dev python3-dev --fix-missing
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
# 此Dockerfile适用于“无本地模型”的环境构建,如果需要使用chatglm等本地模型,请参考 docs/Dockerfile+ChatGLM
|
# 此Dockerfile适用于“无本地模型”的环境构建,如果需要使用chatglm等本地模型,请参考 docs/Dockerfile+ChatGLM
|
||||||
# - 1 修改 `config.py`
|
# - 1 修改 `config.py`
|
||||||
# - 2 构建 docker build -t gpt-academic-nolocal-latex -f docs/Dockerfile+NoLocal+Latex .
|
# - 2 构建 docker build -t gpt-academic-nolocal-latex -f docs/GithubAction+NoLocal+Latex .
|
||||||
# - 3 运行 docker run -v /home/fuqingxu/arxiv_cache:/root/arxiv_cache --rm -it --net=host gpt-academic-nolocal-latex
|
# - 3 运行 docker run -v /home/fuqingxu/arxiv_cache:/root/arxiv_cache --rm -it --net=host gpt-academic-nolocal-latex
|
||||||
|
|
||||||
FROM fuqingxu/python311_texlive_ctex:latest
|
FROM fuqingxu/python311_texlive_ctex:latest
|
||||||
|
|
||||||
|
# 删除文档文件以节约空间
|
||||||
|
rm -rf /usr/local/texlive/2023/texmf-dist/doc
|
||||||
|
|
||||||
# 指定路径
|
# 指定路径
|
||||||
WORKDIR /gpt
|
WORKDIR /gpt
|
||||||
|
|
||||||
RUN pip3 install gradio openai numpy arxiv rich
|
RUN pip3 install openai numpy arxiv rich
|
||||||
RUN pip3 install colorama Markdown pygments pymupdf
|
RUN pip3 install colorama Markdown pygments pymupdf
|
||||||
|
RUN pip3 install python-docx pdfminer
|
||||||
|
RUN pip3 install nougat-ocr
|
||||||
|
|
||||||
# 装载项目文件
|
# 装载项目文件
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|||||||
@@ -299,7 +299,6 @@
|
|||||||
"地址🚀": "Address 🚀",
|
"地址🚀": "Address 🚀",
|
||||||
"感谢热情的": "Thanks to the enthusiastic",
|
"感谢热情的": "Thanks to the enthusiastic",
|
||||||
"开发者们❤️": "Developers ❤️",
|
"开发者们❤️": "Developers ❤️",
|
||||||
"所有问询记录将自动保存在本地目录./gpt_log/chat_secrets.log": "All inquiry records will be automatically saved in the local directory ./gpt_log/chat_secrets.log",
|
|
||||||
"请注意自我隐私保护哦!": "Please pay attention to self-privacy protection!",
|
"请注意自我隐私保护哦!": "Please pay attention to self-privacy protection!",
|
||||||
"当前模型": "Current model",
|
"当前模型": "Current model",
|
||||||
"输入区": "Input area",
|
"输入区": "Input area",
|
||||||
@@ -323,7 +322,7 @@
|
|||||||
"任何文件": "Any file",
|
"任何文件": "Any file",
|
||||||
"但推荐上传压缩文件": "But it is recommended to upload compressed files",
|
"但推荐上传压缩文件": "But it is recommended to upload compressed files",
|
||||||
"更换模型 & SysPrompt & 交互界面布局": "Change model & SysPrompt & interactive interface layout",
|
"更换模型 & SysPrompt & 交互界面布局": "Change model & SysPrompt & interactive interface layout",
|
||||||
"底部输入区": "Bottom input area",
|
"浮动输入区": "Floating input area",
|
||||||
"输入清除键": "Input clear key",
|
"输入清除键": "Input clear key",
|
||||||
"插件参数区": "Plugin parameter area",
|
"插件参数区": "Plugin parameter area",
|
||||||
"显示/隐藏功能区": "Show/hide function area",
|
"显示/隐藏功能区": "Show/hide function area",
|
||||||
@@ -892,7 +891,6 @@
|
|||||||
"保存当前对话": "Save current conversation",
|
"保存当前对话": "Save current conversation",
|
||||||
"您可以调用“LoadConversationHistoryArchive”还原当下的对话": "You can call 'LoadConversationHistoryArchive' to restore the current conversation",
|
"您可以调用“LoadConversationHistoryArchive”还原当下的对话": "You can call 'LoadConversationHistoryArchive' to restore the current conversation",
|
||||||
"警告!被保存的对话历史可以被使用该系统的任何人查阅": "Warning! The saved conversation history can be viewed by anyone using this system",
|
"警告!被保存的对话历史可以被使用该系统的任何人查阅": "Warning! The saved conversation history can be viewed by anyone using this system",
|
||||||
"gpt_log/**/chatGPT对话历史*.html": "gpt_log/**/chatGPT conversation history *.html",
|
|
||||||
"正在查找对话历史文件": "Looking for conversation history file",
|
"正在查找对话历史文件": "Looking for conversation history file",
|
||||||
"html格式": "HTML format",
|
"html格式": "HTML format",
|
||||||
"找不到任何html文件": "No HTML files found",
|
"找不到任何html文件": "No HTML files found",
|
||||||
@@ -908,7 +906,6 @@
|
|||||||
"pip install pywin32 用于doc格式": "pip install pywin32 for doc format",
|
"pip install pywin32 用于doc格式": "pip install pywin32 for doc format",
|
||||||
"仅支持Win平台": "Only supports Win platform",
|
"仅支持Win平台": "Only supports Win platform",
|
||||||
"打开文件": "Open file",
|
"打开文件": "Open file",
|
||||||
"private_upload里面的文件名在解压zip后容易出现乱码": "The file name in private_upload is prone to garbled characters after unzipping",
|
|
||||||
"rar和7z格式正常": "RAR and 7z formats are normal",
|
"rar和7z格式正常": "RAR and 7z formats are normal",
|
||||||
"故可以只分析文章内容": "So you can only analyze the content of the article",
|
"故可以只分析文章内容": "So you can only analyze the content of the article",
|
||||||
"不输入文件名": "Do not enter the file name",
|
"不输入文件名": "Do not enter the file name",
|
||||||
@@ -1364,7 +1361,6 @@
|
|||||||
"注意文章中的每一句话都要翻译": "Please translate every sentence in the article",
|
"注意文章中的每一句话都要翻译": "Please translate every sentence in the article",
|
||||||
"一、论文概况": "I. Overview of the paper",
|
"一、论文概况": "I. Overview of the paper",
|
||||||
"二、论文翻译": "II. Translation of the paper",
|
"二、论文翻译": "II. Translation of the paper",
|
||||||
"/gpt_log/总结论文-": "/gpt_log/Summary of the paper-",
|
|
||||||
"给出输出文件清单": "Provide a list of output files",
|
"给出输出文件清单": "Provide a list of output files",
|
||||||
"第 0 步": "Step 0",
|
"第 0 步": "Step 0",
|
||||||
"切割PDF": "Split PDF",
|
"切割PDF": "Split PDF",
|
||||||
@@ -1564,7 +1560,6 @@
|
|||||||
"广义速度": "Generalized velocity",
|
"广义速度": "Generalized velocity",
|
||||||
"粒子的固有": "Intrinsic of particle",
|
"粒子的固有": "Intrinsic of particle",
|
||||||
"一个包含所有切割音频片段文件路径的列表": "A list containing the file paths of all segmented audio clips",
|
"一个包含所有切割音频片段文件路径的列表": "A list containing the file paths of all segmented audio clips",
|
||||||
"/gpt_log/翻译-": "Translation log-",
|
|
||||||
"计算文件总时长和切割点": "Calculate total duration and cutting points of the file",
|
"计算文件总时长和切割点": "Calculate total duration and cutting points of the file",
|
||||||
"总结音频": "Summarize audio",
|
"总结音频": "Summarize audio",
|
||||||
"作者": "Author",
|
"作者": "Author",
|
||||||
@@ -2161,5 +2156,498 @@
|
|||||||
"在运行过程中动态地修改配置": "Dynamically modify configurations during runtime",
|
"在运行过程中动态地修改配置": "Dynamically modify configurations during runtime",
|
||||||
"请先把模型切换至gpt-*或者api2d-*": "Please switch the model to gpt-* or api2d-* first",
|
"请先把模型切换至gpt-*或者api2d-*": "Please switch the model to gpt-* or api2d-* first",
|
||||||
"获取简单聊天的句柄": "Get handle of simple chat",
|
"获取简单聊天的句柄": "Get handle of simple chat",
|
||||||
"获取插件的默认参数": "Get default parameters of plugin"
|
"获取插件的默认参数": "Get default parameters of plugin",
|
||||||
|
"GROBID服务不可用": "GROBID service is unavailable",
|
||||||
|
"请问": "May I ask",
|
||||||
|
"如果等待时间过长": "If the waiting time is too long",
|
||||||
|
"编程": "programming",
|
||||||
|
"5. 现在": "5. Now",
|
||||||
|
"您不必读这个else分支": "You don't have to read this else branch",
|
||||||
|
"用插件实现": "Implement with plugins",
|
||||||
|
"插件分类默认选项": "Default options for plugin classification",
|
||||||
|
"填写多个可以均衡负载": "Filling in multiple can balance the load",
|
||||||
|
"色彩主题": "Color theme",
|
||||||
|
"可能附带额外依赖 -=-=-=-=-=-=-": "May come with additional dependencies -=-=-=-=-=-=-",
|
||||||
|
"讯飞星火认知大模型": "Xunfei Xinghuo cognitive model",
|
||||||
|
"ParsingLuaProject的所有源文件 | 输入参数为路径": "All source files of ParsingLuaProject | Input parameter is path",
|
||||||
|
"复制以下空间https": "Copy the following space https",
|
||||||
|
"如果意图明确": "If the intention is clear",
|
||||||
|
"如系统是Linux": "If the system is Linux",
|
||||||
|
"├── 语音功能": "├── Voice function",
|
||||||
|
"见Github wiki": "See Github wiki",
|
||||||
|
"⭐ ⭐ ⭐ 立即应用配置": "⭐ ⭐ ⭐ Apply configuration immediately",
|
||||||
|
"现在您只需要再次重复一次您的指令即可": "Now you just need to repeat your command again",
|
||||||
|
"没辙了": "No way",
|
||||||
|
"解析Jupyter Notebook文件 | 输入参数为路径": "Parse Jupyter Notebook file | Input parameter is path",
|
||||||
|
"⭐ ⭐ ⭐ 确认插件参数": "⭐ ⭐ ⭐ Confirm plugin parameters",
|
||||||
|
"找不到合适插件执行该任务": "Cannot find a suitable plugin to perform this task",
|
||||||
|
"接驳VoidTerminal": "Connect to VoidTerminal",
|
||||||
|
"**很好": "**Very good",
|
||||||
|
"对话|编程": "Conversation|Programming",
|
||||||
|
"对话|编程|学术": "Conversation|Programming|Academic",
|
||||||
|
"4. 建议使用 GPT3.5 或更强的模型": "4. It is recommended to use GPT3.5 or a stronger model",
|
||||||
|
"「请调用插件翻译PDF论文": "Please call the plugin to translate the PDF paper",
|
||||||
|
"3. 如果您使用「调用插件xxx」、「修改配置xxx」、「请问」等关键词": "3. If you use keywords such as 'call plugin xxx', 'modify configuration xxx', 'please', etc.",
|
||||||
|
"以下是一篇学术论文的基本信息": "The following is the basic information of an academic paper",
|
||||||
|
"GROBID服务器地址": "GROBID server address",
|
||||||
|
"修改配置": "Modify configuration",
|
||||||
|
"理解PDF文档的内容并进行回答 | 输入参数为路径": "Understand the content of the PDF document and answer | Input parameter is path",
|
||||||
|
"对于需要高级参数的插件": "For plugins that require advanced parameters",
|
||||||
|
"🏃♂️🏃♂️🏃♂️ 主进程执行": "Main process execution 🏃♂️🏃♂️🏃♂️",
|
||||||
|
"没有填写 HUGGINGFACE_ACCESS_TOKEN": "HUGGINGFACE_ACCESS_TOKEN not filled in",
|
||||||
|
"调度插件": "Scheduling plugin",
|
||||||
|
"语言模型": "Language model",
|
||||||
|
"├── ADD_WAIFU 加一个live2d装饰": "├── ADD_WAIFU Add a live2d decoration",
|
||||||
|
"初始化": "Initialization",
|
||||||
|
"选择了不存在的插件": "Selected a non-existent plugin",
|
||||||
|
"修改本项目的配置": "Modify the configuration of this project",
|
||||||
|
"如果输入的文件路径是正确的": "If the input file path is correct",
|
||||||
|
"2. 您可以打开插件下拉菜单以了解本项目的各种能力": "2. You can open the plugin dropdown menu to learn about various capabilities of this project",
|
||||||
|
"VoidTerminal插件说明": "VoidTerminal plugin description",
|
||||||
|
"无法理解您的需求": "Unable to understand your requirements",
|
||||||
|
"默认 AdvancedArgs = False": "Default AdvancedArgs = False",
|
||||||
|
"「请问Transformer网络的结构是怎样的": "What is the structure of the Transformer network?",
|
||||||
|
"比如1812.10695": "For example, 1812.10695",
|
||||||
|
"翻译README或MD": "Translate README or MD",
|
||||||
|
"读取新配置中": "Reading new configuration",
|
||||||
|
"假如偏离了您的要求": "If it deviates from your requirements",
|
||||||
|
"├── THEME 色彩主题": "├── THEME color theme",
|
||||||
|
"如果还找不到": "If still not found",
|
||||||
|
"问": "Ask",
|
||||||
|
"请检查系统字体": "Please check system fonts",
|
||||||
|
"如果错误": "If there is an error",
|
||||||
|
"作为替代": "As an alternative",
|
||||||
|
"ParseJavaProject的所有源文件 | 输入参数为路径": "All source files of ParseJavaProject | Input parameter is path",
|
||||||
|
"比对相同参数时生成的url与自己代码生成的url是否一致": "Check if the generated URL matches the one generated by your code when comparing the same parameters",
|
||||||
|
"清除本地缓存数据": "Clear local cache data",
|
||||||
|
"使用谷歌学术检索助手搜索指定URL的结果 | 输入参数为谷歌学术搜索页的URL": "Use Google Scholar search assistant to search for results of a specific URL | Input parameter is the URL of Google Scholar search page",
|
||||||
|
"运行方法": "Running method",
|
||||||
|
"您已经上传了文件**": "You have uploaded the file **",
|
||||||
|
"「给爷翻译Arxiv论文": "Translate Arxiv papers for me",
|
||||||
|
"请修改config中的GROBID_URL": "Please modify GROBID_URL in the config",
|
||||||
|
"处理特殊情况": "Handling special cases",
|
||||||
|
"不要自己瞎搞!」": "Don't mess around by yourself!",
|
||||||
|
"LoadConversationHistoryArchive | 输入参数为路径": "LoadConversationHistoryArchive | Input parameter is a path",
|
||||||
|
"| 输入参数是一个问题": "| Input parameter is a question",
|
||||||
|
"├── CHATBOT_HEIGHT 对话窗的高度": "├── CHATBOT_HEIGHT Height of the chat window",
|
||||||
|
"对C": "To C",
|
||||||
|
"默认关闭": "Default closed",
|
||||||
|
"当前进度": "Current progress",
|
||||||
|
"HUGGINGFACE的TOKEN": "HUGGINGFACE's TOKEN",
|
||||||
|
"查找可用插件中": "Searching for available plugins",
|
||||||
|
"下载LLAMA时起作用 https": "Works when downloading LLAMA https",
|
||||||
|
"使用 AK": "Using AK",
|
||||||
|
"正在执行任务": "Executing task",
|
||||||
|
"保存当前的对话 | 不需要输入参数": "Save current conversation | No input parameters required",
|
||||||
|
"对话": "Conversation",
|
||||||
|
"图中鲜花怒放": "Flowers blooming in the picture",
|
||||||
|
"批量将Markdown文件中文翻译为英文 | 输入参数为路径或上传压缩包": "Batch translate Chinese to English in Markdown files | Input parameter is a path or upload a compressed package",
|
||||||
|
"ParsingCSharpProject的所有源文件 | 输入参数为路径": "ParsingCSharpProject's all source files | Input parameter is a path",
|
||||||
|
"为我翻译PDF论文": "Translate PDF papers for me",
|
||||||
|
"聊天对话": "Chat conversation",
|
||||||
|
"拼接鉴权参数": "Concatenate authentication parameters",
|
||||||
|
"请检查config中的GROBID_URL": "Please check the GROBID_URL in the config",
|
||||||
|
"拼接字符串": "Concatenate strings",
|
||||||
|
"您的意图可以被识别的更准确": "Your intent can be recognized more accurately",
|
||||||
|
"该模型有七个 bin 文件": "The model has seven bin files",
|
||||||
|
"但思路相同": "But the idea is the same",
|
||||||
|
"你需要翻译": "You need to translate",
|
||||||
|
"或者描述文件所在的路径": "Or the path of the description file",
|
||||||
|
"请您上传文件": "Please upload the file",
|
||||||
|
"不常用": "Not commonly used",
|
||||||
|
"尚未充分测试的实验性插件 & 需要额外依赖的插件 -=--=-": "Experimental plugins that have not been fully tested & plugins that require additional dependencies -=--=-",
|
||||||
|
"⭐ ⭐ ⭐ 选择插件": "⭐ ⭐ ⭐ Select plugin",
|
||||||
|
"当前配置不允许被修改!如需激活本功能": "The current configuration does not allow modification! To activate this feature",
|
||||||
|
"正在连接GROBID服务": "Connecting to GROBID service",
|
||||||
|
"用户图形界面布局依赖关系示意图": "Diagram of user interface layout dependencies",
|
||||||
|
"是否允许通过自然语言描述修改本页的配置": "Allow modifying the configuration of this page through natural language description",
|
||||||
|
"self.chatbot被序列化": "self.chatbot is serialized",
|
||||||
|
"本地Latex论文精细翻译 | 输入参数是路径": "Locally translate Latex papers with fine-grained translation | Input parameter is the path",
|
||||||
|
"抱歉": "Sorry",
|
||||||
|
"以下这部分是最早加入的最稳定的模型 -=-=-=-=-=-=-": "The following section is the earliest and most stable model added",
|
||||||
|
"「用插件翻译README": "Translate README with plugins",
|
||||||
|
"如果不正确": "If incorrect",
|
||||||
|
"⭐ ⭐ ⭐ 读取可配置项目条目": "⭐ ⭐ ⭐ Read configurable project entries",
|
||||||
|
"开始语言对话 | 没有输入参数": "Start language conversation | No input parameters",
|
||||||
|
"谨慎操作 | 不需要输入参数": "Handle with caution | No input parameters required",
|
||||||
|
"对英文Latex项目全文进行纠错处理 | 输入参数为路径或上传压缩包": "Correct the entire English Latex project | Input parameter is the path or upload compressed package",
|
||||||
|
"如果需要处理文件": "If file processing is required",
|
||||||
|
"提供图像的内容": "Provide the content of the image",
|
||||||
|
"查看历史上的今天事件 | 不需要输入参数": "View historical events of today | No input parameters required",
|
||||||
|
"这个稍微啰嗦一点": "This is a bit verbose",
|
||||||
|
"多线程解析并翻译此项目的源码 | 不需要输入参数": "Parse and translate the source code of this project in multi-threading | No input parameters required",
|
||||||
|
"此处打印出建立连接时候的url": "Print the URL when establishing the connection here",
|
||||||
|
"精准翻译PDF论文为中文 | 输入参数为路径": "Translate PDF papers accurately into Chinese | Input parameter is the path",
|
||||||
|
"检测到操作错误!当您上传文档之后": "Operation error detected! After you upload the document",
|
||||||
|
"在线大模型配置关联关系示意图": "Online large model configuration relationship diagram",
|
||||||
|
"你的填写的空间名如grobid": "Your filled space name such as grobid",
|
||||||
|
"获取方法": "Get method",
|
||||||
|
"| 输入参数为路径": "| Input parameter is the path",
|
||||||
|
"⭐ ⭐ ⭐ 执行插件": "⭐ ⭐ ⭐ Execute plugin",
|
||||||
|
"├── ALLOW_RESET_CONFIG 是否允许通过自然语言描述修改本页的配置": "├── ALLOW_RESET_CONFIG Whether to allow modifying the configuration of this page through natural language description",
|
||||||
|
"重新页面即可生效": "Refresh the page to take effect",
|
||||||
|
"设为public": "Set as public",
|
||||||
|
"并在此处指定模型路径": "And specify the model path here",
|
||||||
|
"分析用户意图中": "Analyzing user intent",
|
||||||
|
"刷新下拉列表": "Refresh the drop-down list",
|
||||||
|
"失败 当前语言模型": "Failed current language model",
|
||||||
|
"1. 请用**自然语言**描述您需要做什么": "1. Please describe what you need to do in **natural language**",
|
||||||
|
"对Latex项目全文进行中译英处理 | 输入参数为路径或上传压缩包": "Translate the full text of Latex projects from Chinese to English | Input parameter is the path or upload a compressed package",
|
||||||
|
"没有配置BAIDU_CLOUD_API_KEY": "No configuration for BAIDU_CLOUD_API_KEY",
|
||||||
|
"设置默认值": "Set default value",
|
||||||
|
"如果太多了会导致gpt无法理解": "If there are too many, it will cause GPT to be unable to understand",
|
||||||
|
"绿草如茵": "Green grass",
|
||||||
|
"├── LAYOUT 窗口布局": "├── LAYOUT window layout",
|
||||||
|
"用户意图理解": "User intent understanding",
|
||||||
|
"生成RFC1123格式的时间戳": "Generate RFC1123 formatted timestamp",
|
||||||
|
"欢迎您前往Github反馈问题": "Welcome to go to Github to provide feedback",
|
||||||
|
"排除已经是按钮的插件": "Exclude plugins that are already buttons",
|
||||||
|
"亦在下拉菜单中显示": "Also displayed in the dropdown menu",
|
||||||
|
"导致无法反序列化": "Causing deserialization failure",
|
||||||
|
"意图=": "Intent =",
|
||||||
|
"章节": "Chapter",
|
||||||
|
"调用插件": "Invoke plugin",
|
||||||
|
"ParseRustProject的所有源文件 | 输入参数为路径": "All source files of ParseRustProject | Input parameter is path",
|
||||||
|
"需要点击“函数插件区”按钮进行处理": "Need to click the 'Function Plugin Area' button for processing",
|
||||||
|
"默认 AsButton = True": "Default AsButton = True",
|
||||||
|
"收到websocket错误的处理": "Handling websocket errors",
|
||||||
|
"用插件": "Use Plugin",
|
||||||
|
"没有选择任何插件组": "No plugin group selected",
|
||||||
|
"答": "Answer",
|
||||||
|
"可修改成本地GROBID服务": "Can modify to local GROBID service",
|
||||||
|
"用户意图": "User intent",
|
||||||
|
"对英文Latex项目全文进行润色处理 | 输入参数为路径或上传压缩包": "Polish the full text of English Latex projects | Input parameters are paths or uploaded compressed packages",
|
||||||
|
"「我不喜欢当前的界面颜色": "I don't like the current interface color",
|
||||||
|
"「请调用插件": "Please call the plugin",
|
||||||
|
"VoidTerminal状态": "VoidTerminal status",
|
||||||
|
"新配置": "New configuration",
|
||||||
|
"支持Github链接": "Support Github links",
|
||||||
|
"没有配置BAIDU_CLOUD_SECRET_KEY": "No BAIDU_CLOUD_SECRET_KEY configured",
|
||||||
|
"获取当前VoidTerminal状态": "Get the current VoidTerminal status",
|
||||||
|
"刷新按钮": "Refresh button",
|
||||||
|
"为了防止pickle.dumps": "To prevent pickle.dumps",
|
||||||
|
"放弃治疗": "Give up treatment",
|
||||||
|
"可指定不同的生成长度、top_p等相关超参": "Can specify different generation lengths, top_p and other related hyperparameters",
|
||||||
|
"请将题目和摘要翻译为": "Translate the title and abstract",
|
||||||
|
"通过appid和用户的提问来生成请参数": "Generate request parameters through appid and user's question",
|
||||||
|
"ImageGeneration | 输入参数字符串": "ImageGeneration | Input parameter string",
|
||||||
|
"将文件拖动到文件上传区": "Drag and drop the file to the file upload area",
|
||||||
|
"如果意图模糊": "If the intent is ambiguous",
|
||||||
|
"星火认知大模型": "Spark Cognitive Big Model",
|
||||||
|
"默认 Color = secondary": "Default Color = secondary",
|
||||||
|
"此处也不需要修改": "No modification is needed here",
|
||||||
|
"⭐ ⭐ ⭐ 分析用户意图": "⭐ ⭐ ⭐ Analyze user intent",
|
||||||
|
"再试一次": "Try again",
|
||||||
|
"请写bash命令实现以下功能": "Please write a bash command to implement the following function",
|
||||||
|
"批量SummarizingWordDocuments | 输入参数为路径": "Batch SummarizingWordDocuments | Input parameter is the path",
|
||||||
|
"/Users/fuqingxu/Desktop/旧文件/gpt/chatgpt_academic/crazy_functions/latex_fns中的python文件进行解析": "Parse the python file in /Users/fuqingxu/Desktop/旧文件/gpt/chatgpt_academic/crazy_functions/latex_fns",
|
||||||
|
"当我要求你写bash命令时": "When I ask you to write a bash command",
|
||||||
|
"├── AUTO_CLEAR_TXT 是否在提交时自动清空输入框": "├── AUTO_CLEAR_TXT Whether to automatically clear the input box when submitting",
|
||||||
|
"按停止键终止": "Press the stop key to terminate",
|
||||||
|
"文心一言": "Original text",
|
||||||
|
"不能理解您的意图": "Cannot understand your intention",
|
||||||
|
"用简单的关键词检测用户意图": "Detect user intention with simple keywords",
|
||||||
|
"中文": "Chinese",
|
||||||
|
"解析一个C++项目的所有源文件": "Parse all source files of a C++ project",
|
||||||
|
"请求的Prompt为": "Requested prompt is",
|
||||||
|
"参考本demo的时候可取消上方打印的注释": "You can remove the comments above when referring to this demo",
|
||||||
|
"开始接收回复": "Start receiving replies",
|
||||||
|
"接入讯飞星火大模型 https": "Access to Xunfei Xinghuo large model https",
|
||||||
|
"用该压缩包进行反馈": "Use this compressed package for feedback",
|
||||||
|
"翻译Markdown或README": "Translate Markdown or README",
|
||||||
|
"SK 生成鉴权签名": "SK generates authentication signature",
|
||||||
|
"插件参数": "Plugin parameters",
|
||||||
|
"需要访问中文Bing": "Need to access Chinese Bing",
|
||||||
|
"ParseFrontendProject的所有源文件": "Parse all source files of ParseFrontendProject",
|
||||||
|
"现在将执行效果稍差的旧版代码": "Now execute the older version code with slightly worse performance",
|
||||||
|
"您需要明确说明并在指令中提到它": "You need to specify and mention it in the command",
|
||||||
|
"请在config.py中设置ALLOW_RESET_CONFIG=True后重启软件": "Please set ALLOW_RESET_CONFIG=True in config.py and restart the software",
|
||||||
|
"按照自然语言描述生成一个动画 | 输入参数是一段话": "Generate an animation based on natural language description | Input parameter is a sentence",
|
||||||
|
"你的hf用户名如qingxu98": "Your hf username is qingxu98",
|
||||||
|
"Arixv论文精细翻译 | 输入参数arxiv论文的ID": "Fine translation of Arixv paper | Input parameter is the ID of arxiv paper",
|
||||||
|
"无法获取 abstract": "Unable to retrieve abstract",
|
||||||
|
"尽可能地仅用一行命令解决我的要求": "Try to solve my request using only one command",
|
||||||
|
"提取插件参数": "Extract plugin parameters",
|
||||||
|
"配置修改完成": "Configuration modification completed",
|
||||||
|
"正在修改配置中": "Modifying configuration",
|
||||||
|
"ParsePythonProject的所有源文件": "All source files of ParsePythonProject",
|
||||||
|
"请求错误": "Request error",
|
||||||
|
"精准翻译PDF论文": "Accurate translation of PDF paper",
|
||||||
|
"无法获取 authors": "Unable to retrieve authors",
|
||||||
|
"该插件诞生时间不长": "This plugin has not been around for long",
|
||||||
|
"返回项目根路径": "Return project root path",
|
||||||
|
"BatchSummarizePDFDocuments的内容 | 输入参数为路径": "Content of BatchSummarizePDFDocuments | Input parameter is a path",
|
||||||
|
"百度千帆": "Baidu Qianfan",
|
||||||
|
"解析一个C++项目的所有头文件": "Parse all header files of a C++ project",
|
||||||
|
"现在请您描述您的需求": "Now please describe your requirements",
|
||||||
|
"该功能具有一定的危险性": "This feature has a certain level of danger",
|
||||||
|
"收到websocket关闭的处理": "Processing when receiving websocket closure",
|
||||||
|
"读取Tex论文并写摘要 | 输入参数为路径": "Read Tex paper and write abstract | Input parameter is the path",
|
||||||
|
"地址为https": "The address is https",
|
||||||
|
"限制最多前10个配置项": "Limit up to 10 configuration items",
|
||||||
|
"6. 如果不需要上传文件": "6. If file upload is not needed",
|
||||||
|
"默认 Group = 对话": "Default Group = Conversation",
|
||||||
|
"五秒后即将重启!若出现报错请无视即可": "Restarting in five seconds! Please ignore if there is an error",
|
||||||
|
"收到websocket连接建立的处理": "Processing when receiving websocket connection establishment",
|
||||||
|
"批量生成函数的注释 | 输入参数为路径": "Batch generate function comments | Input parameter is the path",
|
||||||
|
"聊天": "Chat",
|
||||||
|
"但您可以尝试再试一次": "But you can try again",
|
||||||
|
"千帆大模型平台": "Qianfan Big Model Platform",
|
||||||
|
"直接运行 python tests/test_plugins.py": "Run python tests/test_plugins.py directly",
|
||||||
|
"或是None": "Or None",
|
||||||
|
"进行hmac-sha256进行加密": "Perform encryption using hmac-sha256",
|
||||||
|
"批量总结音频或视频 | 输入参数为路径": "Batch summarize audio or video | Input parameter is path",
|
||||||
|
"插件在线服务配置依赖关系示意图": "Plugin online service configuration dependency diagram",
|
||||||
|
"开始初始化模型": "Start initializing model",
|
||||||
|
"弱模型可能无法理解您的想法": "Weak model may not understand your ideas",
|
||||||
|
"解除大小写限制": "Remove case sensitivity restriction",
|
||||||
|
"跳过提示环节": "Skip prompt section",
|
||||||
|
"接入一些逆向工程https": "Access some reverse engineering https",
|
||||||
|
"执行完成": "Execution completed",
|
||||||
|
"如果需要配置": "If configuration is needed",
|
||||||
|
"此处不修改;如果使用本地或无地域限制的大模型时": "Do not modify here; if using local or region-unrestricted large models",
|
||||||
|
"你是一个Linux大师级用户": "You are a Linux master-level user",
|
||||||
|
"arxiv论文的ID是1812.10695": "The ID of the arxiv paper is 1812.10695",
|
||||||
|
"而不是点击“提交”按钮": "Instead of clicking the 'Submit' button",
|
||||||
|
"解析一个Go项目的所有源文件 | 输入参数为路径": "Parse all source files of a Go project | Input parameter is path",
|
||||||
|
"对中文Latex项目全文进行润色处理 | 输入参数为路径或上传压缩包": "Polish the entire text of a Chinese Latex project | Input parameter is path or upload compressed package",
|
||||||
|
"「生成一张图片": "Generate an image",
|
||||||
|
"将Markdown或README翻译为中文 | 输入参数为路径或URL": "Translate Markdown or README to Chinese | Input parameters are path or URL",
|
||||||
|
"训练时间": "Training time",
|
||||||
|
"将请求的鉴权参数组合为字典": "Combine the requested authentication parameters into a dictionary",
|
||||||
|
"对Latex项目全文进行英译中处理 | 输入参数为路径或上传压缩包": "Translate the entire text of Latex project from English to Chinese | Input parameters are path or uploaded compressed package",
|
||||||
|
"内容如下": "The content is as follows",
|
||||||
|
"用于高质量地读取PDF文档": "Used for high-quality reading of PDF documents",
|
||||||
|
"上下文太长导致 token 溢出": "The context is too long, causing token overflow",
|
||||||
|
"├── DARK_MODE 暗色模式 / 亮色模式": "├── DARK_MODE Dark mode / Light mode",
|
||||||
|
"语言模型回复为": "The language model replies as",
|
||||||
|
"from crazy_functions.chatglm微调工具 import 微调数据集生成": "from crazy_functions.chatglm fine-tuning tool import fine-tuning dataset generation",
|
||||||
|
"为您选择了插件": "Selected plugin for you",
|
||||||
|
"无法获取 title": "Unable to get title",
|
||||||
|
"收到websocket消息的处理": "Processing of received websocket messages",
|
||||||
|
"2023年": "2023",
|
||||||
|
"清除所有缓存文件": "Clear all cache files",
|
||||||
|
"├── PDF文档精准解析": "├── Accurate parsing of PDF documents",
|
||||||
|
"论文我刚刚放到上传区了": "I just put the paper in the upload area",
|
||||||
|
"生成url": "Generate URL",
|
||||||
|
"以下部分是新加入的模型": "The following section is the newly added model",
|
||||||
|
"学术": "Academic",
|
||||||
|
"├── DEFAULT_FN_GROUPS 插件分类默认选项": "├── DEFAULT_FN_GROUPS Plugin classification default options",
|
||||||
|
"不推荐使用": "Not recommended for use",
|
||||||
|
"正在同时咨询": "Consulting simultaneously",
|
||||||
|
"将Markdown翻译为中文 | 输入参数为路径或URL": "Translate Markdown to Chinese | Input parameters are path or URL",
|
||||||
|
"Github网址是https": "The Github URL is https",
|
||||||
|
"试着加上.tex后缀试试": "Try adding the .tex suffix",
|
||||||
|
"对项目中的各个插件进行测试": "Test each plugin in the project",
|
||||||
|
"插件说明": "Plugin description",
|
||||||
|
"├── CODE_HIGHLIGHT 代码高亮": "├── CODE_HIGHLIGHT Code highlighting",
|
||||||
|
"记得用插件": "Remember to use the plugin",
|
||||||
|
"谨慎操作": "Handle with caution",
|
||||||
|
"private_upload里面的文件名在解压zip后容易出现乱码": "The file name inside private_upload is prone to garbled characters after unzipping",
|
||||||
|
"直接返回报错": "Direct return error",
|
||||||
|
"临时的上传文件夹位置": "Temporary upload folder location",
|
||||||
|
"使用latex格式 测试3 写出麦克斯韦方程组": "Write Maxwell's equations using latex format for test 3",
|
||||||
|
"这是一张图片": "This is an image",
|
||||||
|
"没有发现任何近期上传的文件": "No recent uploaded files found",
|
||||||
|
"如url未成功匹配返回None": "Return None if the URL does not match successfully",
|
||||||
|
"如果有Latex环境": "If there is a Latex environment",
|
||||||
|
"第一次运行时": "When running for the first time",
|
||||||
|
"创建工作路径": "Create a working directory",
|
||||||
|
"向": "To",
|
||||||
|
"执行中. 删除数据": "Executing. Deleting data",
|
||||||
|
"CodeInterpreter开源版": "CodeInterpreter open source version",
|
||||||
|
"建议选择更稳定的接口": "It is recommended to choose a more stable interface",
|
||||||
|
"现在您点击任意函数插件时": "Now when you click on any function plugin",
|
||||||
|
"请使用“LatexEnglishCorrection+高亮”插件": "Please use the 'LatexEnglishCorrection+Highlight' plugin",
|
||||||
|
"安装完成": "Installation completed",
|
||||||
|
"记得用插件!」": "Remember to use the plugin!",
|
||||||
|
"结论": "Conclusion",
|
||||||
|
"无法下载资源": "Unable to download resources",
|
||||||
|
"首先排除一个one-api没有done数据包的第三方Bug情形": "First exclude a third-party bug where one-api does not have a done data package",
|
||||||
|
"知识库中添加文件": "Add files to the knowledge base",
|
||||||
|
"处理重名的章节": "Handling duplicate chapter names",
|
||||||
|
"先上传文件素材": "Upload file materials first",
|
||||||
|
"无法从google获取信息!": "Unable to retrieve information from Google!",
|
||||||
|
"展示如下": "Display as follows",
|
||||||
|
"「把Arxiv论文翻译成中文PDF": "Translate Arxiv papers into Chinese PDF",
|
||||||
|
"论文我刚刚放到上传区了」": "I just put the paper in the upload area",
|
||||||
|
"正在下载Gradio主题": "Downloading Gradio themes",
|
||||||
|
"再运行此插件": "Run this plugin again",
|
||||||
|
"记录近期文件": "Record recent files",
|
||||||
|
"粗心检查": "Careful check",
|
||||||
|
"更多主题": "More themes",
|
||||||
|
"//huggingface.co/spaces/gradio/theme-gallery 可选": "//huggingface.co/spaces/gradio/theme-gallery optional",
|
||||||
|
"由 test_on_result_chg": "By test_on_result_chg",
|
||||||
|
"所有问询记录将自动保存在本地目录./": "All inquiry records will be automatically saved in the local directory ./",
|
||||||
|
"正在解析论文": "Analyzing the paper",
|
||||||
|
"逐个文件转移到目标路径": "Move each file to the target path",
|
||||||
|
"最多重试5次": "Retry up to 5 times",
|
||||||
|
"日志文件夹的位置": "Location of the log folder",
|
||||||
|
"我们暂时无法解析此PDF文档": "We are temporarily unable to parse this PDF document",
|
||||||
|
"文件检索": "File retrieval",
|
||||||
|
"/**/chatGPT对话历史*.html": "/**/chatGPT conversation history*.html",
|
||||||
|
"非OpenAI官方接口返回了错误": "Non-OpenAI official interface returned an error",
|
||||||
|
"如果在Arxiv上匹配失败": "If the match fails on Arxiv",
|
||||||
|
"文件进入知识库后可长期保存": "Files can be saved for a long time after entering the knowledge base",
|
||||||
|
"您可以再次重试": "You can try again",
|
||||||
|
"整理文件集合": "Organize file collection",
|
||||||
|
"检测到有缺陷的非OpenAI官方接口": "Detected defective non-OpenAI official interface",
|
||||||
|
"此插件不调用Latex": "This plugin does not call Latex",
|
||||||
|
"移除过时的旧文件从而节省空间&保护隐私": "Remove outdated old files to save space & protect privacy",
|
||||||
|
"代码我刚刚打包拖到上传区了」": "I just packed the code and dragged it to the upload area",
|
||||||
|
"将图像转为灰度图像": "Convert the image to grayscale",
|
||||||
|
"待排除": "To be excluded",
|
||||||
|
"请勿修改": "Please do not modify",
|
||||||
|
"crazy_functions/代码重写为全英文_多线程.py": "crazy_functions/code rewritten to all English_multi-threading.py",
|
||||||
|
"开发中": "Under development",
|
||||||
|
"请查阅Gradio主题商店": "Please refer to the Gradio theme store",
|
||||||
|
"输出消息": "Output message",
|
||||||
|
"其他情况": "Other situations",
|
||||||
|
"获取文献失败": "Failed to retrieve literature",
|
||||||
|
"可以通过再次调用本插件的方式": "You can use this plugin again by calling it",
|
||||||
|
"保留下半部分": "Keep the lower half",
|
||||||
|
"排除问题": "Exclude the problem",
|
||||||
|
"知识库": "Knowledge base",
|
||||||
|
"ParsePDF失败": "ParsePDF failed",
|
||||||
|
"向知识库追加更多文档": "Append more documents to the knowledge base",
|
||||||
|
"此处待注入的知识库名称id": "The knowledge base name ID to be injected here",
|
||||||
|
"您需要构建知识库后再运行此插件": "You need to build the knowledge base before running this plugin",
|
||||||
|
"判定是否为公式 | 测试1 写出洛伦兹定律": "Determine whether it is a formula | Test 1 write out the Lorentz law",
|
||||||
|
"构建知识库后": "After building the knowledge base",
|
||||||
|
"找不到本地项目或无法处理": "Unable to find local project or unable to process",
|
||||||
|
"再做一个小修改": "Make another small modification",
|
||||||
|
"解析整个Matlab项目": "Parse the entire Matlab project",
|
||||||
|
"需要用GPT提取参数": "Need to extract parameters using GPT",
|
||||||
|
"文件路径": "File path",
|
||||||
|
"正在排队": "In queue",
|
||||||
|
"-=-=-=-=-=-=-=-= 写出第1个文件": "-=-=-=-=-=-=-=-= Write the first file",
|
||||||
|
"仅翻译后的文本 -=-=-=-=-=-=-=-=": "Translated text only -=-=-=-=-=-=-=-=",
|
||||||
|
"对话通道": "Conversation channel",
|
||||||
|
"找不到任何": "Unable to find any",
|
||||||
|
"正在启动": "Starting",
|
||||||
|
"开始创建新进程并执行代码! 时间限制": "Start creating a new process and executing the code! Time limit",
|
||||||
|
"解析Matlab项目": "Parse Matlab project",
|
||||||
|
"更换UI主题": "Change UI theme",
|
||||||
|
"⭐ 开始啦 !": "⭐ Let's start!",
|
||||||
|
"先提取当前英文标题": "First extract the current English title",
|
||||||
|
"睡一会防止触发google反爬虫": "Sleep for a while to prevent triggering Google anti-crawler",
|
||||||
|
"测试": "Test",
|
||||||
|
"-=-=-=-=-=-=-=-= 写出Markdown文件 -=-=-=-=-=-=-=-=": "-=-=-=-=-=-=-=-= Write out Markdown file",
|
||||||
|
"如果index是1的话": "If the index is 1",
|
||||||
|
"VoidTerminal已经实现了类似的代码": "VoidTerminal has already implemented similar code",
|
||||||
|
"等待线程锁": "Waiting for thread lock",
|
||||||
|
"那么我们默认代理生效": "Then we default to proxy",
|
||||||
|
"结果是一个有效文件": "The result is a valid file",
|
||||||
|
"⭐ 检查模块": "⭐ Check module",
|
||||||
|
"备份一份History作为记录": "Backup a copy of History as a record",
|
||||||
|
"作者Binary-Husky": "Author Binary-Husky",
|
||||||
|
"将csv文件转excel表格": "Convert CSV file to Excel table",
|
||||||
|
"获取文章摘要": "Get article summary",
|
||||||
|
"次代码生成尝试": "Attempt to generate code",
|
||||||
|
"如果参数是空的": "If the parameter is empty",
|
||||||
|
"请配置讯飞星火大模型的XFYUN_APPID": "Please configure XFYUN_APPID for the Xunfei Starfire model",
|
||||||
|
"-=-=-=-=-=-=-=-= 写出第2个文件": "Write the second file",
|
||||||
|
"代码生成阶段结束": "Code generation phase completed",
|
||||||
|
"则进行提醒": "Then remind",
|
||||||
|
"处理异常": "Handle exception",
|
||||||
|
"可能触发了google反爬虫机制": "May have triggered Google anti-crawler mechanism",
|
||||||
|
"AnalyzeAMatlabProject的所有源文件": "All source files of AnalyzeAMatlabProject",
|
||||||
|
"写入": "Write",
|
||||||
|
"我们5秒后再试一次...": "Let's try again in 5 seconds...",
|
||||||
|
"判断一下用户是否错误地通过对话通道进入": "Check if the user entered through the dialogue channel by mistake",
|
||||||
|
"结果": "Result",
|
||||||
|
"2. 如果没有文件": "2. If there is no file",
|
||||||
|
"由 test_on_sentence_end": "By test_on_sentence_end",
|
||||||
|
"则直接使用first section name": "Then directly use the first section name",
|
||||||
|
"太懒了": "Too lazy",
|
||||||
|
"记录当前的大章节标题": "Record the current chapter title",
|
||||||
|
"然后再次点击该插件! 至于您的文件": "Then click the plugin again! As for your file",
|
||||||
|
"此次我们的错误追踪是": "This time our error tracking is",
|
||||||
|
"首先在arxiv上搜索": "First search on arxiv",
|
||||||
|
"被新插件取代": "Replaced by a new plugin",
|
||||||
|
"正在处理文件": "Processing file",
|
||||||
|
"除了连接OpenAI之外": "In addition to connecting OpenAI",
|
||||||
|
"我们检查一下": "Let's check",
|
||||||
|
"进度": "Progress",
|
||||||
|
"处理少数情况下的特殊插件的锁定状态": "Handle the locked state of special plugins in a few cases",
|
||||||
|
"⭐ 开始执行": "⭐ Start execution",
|
||||||
|
"正常情况": "Normal situation",
|
||||||
|
"下个句子中已经说完的部分": "The part that has already been said in the next sentence",
|
||||||
|
"首次运行需要花费较长时间下载NOUGAT参数": "The first run takes a long time to download NOUGAT parameters",
|
||||||
|
"使用tex格式公式 测试2 给出柯西不等式": "Use the tex format formula to test 2 and give the Cauchy inequality",
|
||||||
|
"无法从bing获取信息!": "Unable to retrieve information from Bing!",
|
||||||
|
"秒. 请等待任务完成": "Wait for the task to complete",
|
||||||
|
"开始干正事": "Start doing real work",
|
||||||
|
"需要花费较长时间下载NOUGAT参数": "It takes a long time to download NOUGAT parameters",
|
||||||
|
"然后再次点击该插件": "Then click the plugin again",
|
||||||
|
"受到bing限制": "Restricted by Bing",
|
||||||
|
"检索文章的历史版本的题目": "Retrieve the titles of historical versions of the article",
|
||||||
|
"收尾": "Wrap up",
|
||||||
|
"给定了task": "Given a task",
|
||||||
|
"某段话的整个句子": "The whole sentence of a paragraph",
|
||||||
|
"-=-=-=-=-=-=-=-= 写出HTML文件 -=-=-=-=-=-=-=-=": "-=-=-=-=-=-=-=-= Write out HTML file -=-=-=-=-=-=-=-=",
|
||||||
|
"当前文件": "Current file",
|
||||||
|
"请在输入框内填写需求": "Please fill in the requirements in the input box",
|
||||||
|
"结果是一个字符串": "The result is a string",
|
||||||
|
"用插件实现」": "Implemented with a plugin",
|
||||||
|
"⭐ 到最后一步了": "⭐ Reached the final step",
|
||||||
|
"重新修改当前part的标题": "Modify the title of the current part again",
|
||||||
|
"请勿点击“提交”按钮或者“基础功能区”按钮": "Do not click the 'Submit' button or the 'Basic Function Area' button",
|
||||||
|
"正在执行命令": "Executing command",
|
||||||
|
"检测到**滞留的缓存文档**": "Detected **stuck cache document**",
|
||||||
|
"第三步": "Step three",
|
||||||
|
"失败了~ 别担心": "Failed~ Don't worry",
|
||||||
|
"动态代码解释器": "Dynamic code interpreter",
|
||||||
|
"开始执行": "Start executing",
|
||||||
|
"不给定task": "No task given",
|
||||||
|
"正在加载NOUGAT...": "Loading NOUGAT...",
|
||||||
|
"精准翻译PDF文档": "Accurate translation of PDF documents",
|
||||||
|
"时间限制TIME_LIMIT": "Time limit TIME_LIMIT",
|
||||||
|
"翻译前后混合 -=-=-=-=-=-=-=-=": "Mixed translation before and after -=-=-=-=-=-=-=-=",
|
||||||
|
"搞定代码生成": "Code generation is done",
|
||||||
|
"插件通道": "Plugin channel",
|
||||||
|
"智能体": "Intelligent agent",
|
||||||
|
"切换界面明暗 ☀": "Switch interface brightness ☀",
|
||||||
|
"交换图像的蓝色通道和红色通道": "Swap blue channel and red channel of the image",
|
||||||
|
"作为函数参数": "As a function parameter",
|
||||||
|
"先挑选偶数序列号": "First select even serial numbers",
|
||||||
|
"仅供测试": "For testing only",
|
||||||
|
"执行成功了": "Execution succeeded",
|
||||||
|
"开始逐个文件进行处理": "Start processing files one by one",
|
||||||
|
"当前文件处理列表": "Current file processing list",
|
||||||
|
"执行失败了": "Execution failed",
|
||||||
|
"请及时处理": "Please handle it in time",
|
||||||
|
"源文件": "Source file",
|
||||||
|
"裁剪图像": "Crop image",
|
||||||
|
"插件动态生成插件": "Dynamic generation of plugins",
|
||||||
|
"正在验证上述代码的有效性": "Validating the above code",
|
||||||
|
"⭐ = 关键步骤": "⭐ = Key step",
|
||||||
|
"!= 0 代表“提交”键对话通道": "!= 0 represents the 'Submit' key dialogue channel",
|
||||||
|
"解析python源代码项目": "Parsing Python source code project",
|
||||||
|
"请检查PDF是否损坏": "Please check if the PDF is damaged",
|
||||||
|
"插件动态生成": "Dynamic generation of plugins",
|
||||||
|
"⭐ 分离代码块": "⭐ Separating code blocks",
|
||||||
|
"已经被记忆": "Already memorized",
|
||||||
|
"默认用英文的": "Default to English",
|
||||||
|
"错误追踪": "Error tracking",
|
||||||
|
"对话|编程|学术|智能体": "Dialogue|Programming|Academic|Intelligent agent",
|
||||||
|
"请检查": "Please check",
|
||||||
|
"检测到被滞留的缓存文档": "Detected cached documents being left behind",
|
||||||
|
"还有哪些场合允许使用代理": "What other occasions allow the use of proxies",
|
||||||
|
"1. 如果有文件": "1. If there is a file",
|
||||||
|
"执行开始": "Execution starts",
|
||||||
|
"代码生成结束": "Code generation ends",
|
||||||
|
"请及时点击“**保存当前对话**”获取所有滞留文档": "Please click '**Save Current Dialogue**' in time to obtain all cached documents",
|
||||||
|
"需点击“**函数插件区**”按钮进行处理": "Click the '**Function Plugin Area**' button for processing",
|
||||||
|
"此函数已经弃用": "This function has been deprecated",
|
||||||
|
"以后再写": "Write it later",
|
||||||
|
"返回给定的url解析出的arxiv_id": "Return the arxiv_id parsed from the given URL",
|
||||||
|
"⭐ 文件上传区是否有东西": "⭐ Is there anything in the file upload area",
|
||||||
|
"Nougat解析论文失败": "Nougat failed to parse the paper",
|
||||||
|
"本源代码中": "In this source code",
|
||||||
|
"或者基础功能通道": "Or the basic function channel",
|
||||||
|
"使用zip压缩格式": "Using zip compression format",
|
||||||
|
"受到google限制": "Restricted by Google",
|
||||||
|
"如果是": "If it is",
|
||||||
|
"不用担心": "don't worry"
|
||||||
}
|
}
|
||||||
@@ -301,7 +301,6 @@
|
|||||||
"缺少的依赖": "不足している依存関係",
|
"缺少的依赖": "不足している依存関係",
|
||||||
"紫色": "紫色",
|
"紫色": "紫色",
|
||||||
"唤起高级参数输入区": "高度なパラメータ入力エリアを呼び出す",
|
"唤起高级参数输入区": "高度なパラメータ入力エリアを呼び出す",
|
||||||
"所有问询记录将自动保存在本地目录./gpt_log/chat_secrets.log": "すべての問い合わせ記録は自動的にローカルディレクトリ./gpt_log/chat_secrets.logに保存されます",
|
|
||||||
"则换行符更有可能表示段落分隔": "したがって、改行記号は段落の区切りを表す可能性がより高いです",
|
"则换行符更有可能表示段落分隔": "したがって、改行記号は段落の区切りを表す可能性がより高いです",
|
||||||
";4、引用数量": ";4、引用数量",
|
";4、引用数量": ";4、引用数量",
|
||||||
"中转网址预览": "中継ウェブサイトのプレビュー",
|
"中转网址预览": "中継ウェブサイトのプレビュー",
|
||||||
@@ -448,7 +447,6 @@
|
|||||||
"表示函数是否成功执行": "関数が正常に実行されたかどうかを示す",
|
"表示函数是否成功执行": "関数が正常に実行されたかどうかを示す",
|
||||||
"一般原样传递下去就行": "通常はそのまま渡すだけでよい",
|
"一般原样传递下去就行": "通常はそのまま渡すだけでよい",
|
||||||
"琥珀色": "琥珀色",
|
"琥珀色": "琥珀色",
|
||||||
"gpt_log/**/chatGPT对话历史*.html": "gpt_log/**/chatGPT対話履歴*.html",
|
|
||||||
"jittorllms 没有 sys_prompt 接口": "jittorllmsにはsys_promptインターフェースがありません",
|
"jittorllms 没有 sys_prompt 接口": "jittorllmsにはsys_promptインターフェースがありません",
|
||||||
"清除": "クリア",
|
"清除": "クリア",
|
||||||
"小于正文的": "本文より小さい",
|
"小于正文的": "本文より小さい",
|
||||||
@@ -1009,7 +1007,6 @@
|
|||||||
"第一部分": "第1部分",
|
"第一部分": "第1部分",
|
||||||
"的分析如下": "の分析は以下の通りです",
|
"的分析如下": "の分析は以下の通りです",
|
||||||
"解决一个mdx_math的bug": "mdx_mathのバグを解決する",
|
"解决一个mdx_math的bug": "mdx_mathのバグを解決する",
|
||||||
"底部输入区": "下部の入力エリア",
|
|
||||||
"函数插件输入输出接驳区": "関数プラグインの入出力接続エリア",
|
"函数插件输入输出接驳区": "関数プラグインの入出力接続エリア",
|
||||||
"打开浏览器": "ブラウザを開く",
|
"打开浏览器": "ブラウザを開く",
|
||||||
"免费用户填3": "無料ユーザーは3を入力してください",
|
"免费用户填3": "無料ユーザーは3を入力してください",
|
||||||
@@ -1234,7 +1231,6 @@
|
|||||||
"找不到任何前端相关文件": "No frontend-related files can be found",
|
"找不到任何前端相关文件": "No frontend-related files can be found",
|
||||||
"Not enough point. API2D账户点数不足": "Not enough points. API2D account points are insufficient",
|
"Not enough point. API2D账户点数不足": "Not enough points. API2D account points are insufficient",
|
||||||
"当前版本": "Current version",
|
"当前版本": "Current version",
|
||||||
"/gpt_log/总结论文-": "/gpt_log/Summary paper-",
|
|
||||||
"1. 临时解决方案": "1. Temporary solution",
|
"1. 临时解决方案": "1. Temporary solution",
|
||||||
"第8步": "Step 8",
|
"第8步": "Step 8",
|
||||||
"历史": "History",
|
"历史": "History",
|
||||||
|
|||||||
@@ -83,5 +83,14 @@
|
|||||||
"图片生成": "ImageGeneration",
|
"图片生成": "ImageGeneration",
|
||||||
"动画生成": "AnimationGeneration",
|
"动画生成": "AnimationGeneration",
|
||||||
"语音助手": "VoiceAssistant",
|
"语音助手": "VoiceAssistant",
|
||||||
"启动微调": "StartFineTuning"
|
"启动微调": "StartFineTuning",
|
||||||
|
"清除缓存": "ClearCache",
|
||||||
|
"辅助功能": "Accessibility",
|
||||||
|
"虚空终端": "VoidTerminal",
|
||||||
|
"解析PDF_基于GROBID": "ParsePDF_BasedOnGROBID",
|
||||||
|
"虚空终端主路由": "VoidTerminalMainRoute",
|
||||||
|
"批量翻译PDF文档_NOUGAT": "BatchTranslatePDFDocuments_NOUGAT",
|
||||||
|
"解析PDF_基于NOUGAT": "ParsePDF_NOUGAT",
|
||||||
|
"解析一个Matlab项目": "AnalyzeAMatlabProject",
|
||||||
|
"函数动态生成": "DynamicFunctionGeneration"
|
||||||
}
|
}
|
||||||
@@ -314,7 +314,6 @@
|
|||||||
"请用markdown格式输出": "請用 Markdown 格式輸出",
|
"请用markdown格式输出": "請用 Markdown 格式輸出",
|
||||||
"模仿ChatPDF": "模仿 ChatPDF",
|
"模仿ChatPDF": "模仿 ChatPDF",
|
||||||
"等待多久判定为超时": "等待多久判定為超時",
|
"等待多久判定为超时": "等待多久判定為超時",
|
||||||
"/gpt_log/总结论文-": "/gpt_log/總結論文-",
|
|
||||||
"请结合互联网信息回答以下问题": "請結合互聯網信息回答以下問題",
|
"请结合互联网信息回答以下问题": "請結合互聯網信息回答以下問題",
|
||||||
"IP查询频率受限": "IP查詢頻率受限",
|
"IP查询频率受限": "IP查詢頻率受限",
|
||||||
"高级参数输入区的显示提示": "高級參數輸入區的顯示提示",
|
"高级参数输入区的显示提示": "高級參數輸入區的顯示提示",
|
||||||
@@ -347,7 +346,6 @@
|
|||||||
"情况会好转": "情況會好轉",
|
"情况会好转": "情況會好轉",
|
||||||
"超过512个": "超過512個",
|
"超过512个": "超過512個",
|
||||||
"多线": "多線",
|
"多线": "多線",
|
||||||
"底部输入区": "底部輸入區",
|
|
||||||
"合并小写字母开头的段落块并替换为空格": "合併小寫字母開頭的段落塊並替換為空格",
|
"合并小写字母开头的段落块并替换为空格": "合併小寫字母開頭的段落塊並替換為空格",
|
||||||
"暗色主题": "暗色主題",
|
"暗色主题": "暗色主題",
|
||||||
"提高限制请查询": "提高限制請查詢",
|
"提高限制请查询": "提高限制請查詢",
|
||||||
@@ -511,7 +509,6 @@
|
|||||||
"將生成的報告自動投射到文件上傳區": "將生成的報告自動上傳到文件區",
|
"將生成的報告自動投射到文件上傳區": "將生成的報告自動上傳到文件區",
|
||||||
"函數插件作者": "函數插件作者",
|
"函數插件作者": "函數插件作者",
|
||||||
"將要匹配的模式": "將要匹配的模式",
|
"將要匹配的模式": "將要匹配的模式",
|
||||||
"所有问询记录将自动保存在本地目录./gpt_log/chat_secrets.log": "所有詢問記錄將自動保存在本地目錄./gpt_log/chat_secrets.log",
|
|
||||||
"正在分析一个项目的源代码": "正在分析一個專案的源代碼",
|
"正在分析一个项目的源代码": "正在分析一個專案的源代碼",
|
||||||
"使每个段落之间有两个换行符分隔": "使每個段落之間有兩個換行符分隔",
|
"使每个段落之间有两个换行符分隔": "使每個段落之間有兩個換行符分隔",
|
||||||
"并在被装饰的函数上执行": "並在被裝飾的函數上執行",
|
"并在被装饰的函数上执行": "並在被裝飾的函數上執行",
|
||||||
@@ -1059,7 +1056,6 @@
|
|||||||
"重试中": "重試中",
|
"重试中": "重試中",
|
||||||
"月": "月份",
|
"月": "月份",
|
||||||
"localhost意思是代理软件安装在本机上": "localhost意思是代理軟體安裝在本機上",
|
"localhost意思是代理软件安装在本机上": "localhost意思是代理軟體安裝在本機上",
|
||||||
"gpt_log/**/chatGPT对话历史*.html": "gpt_log/**/chatGPT對話歷史*.html",
|
|
||||||
"的长度必须小于 2500 个 Token": "長度必須小於 2500 個 Token",
|
"的长度必须小于 2500 个 Token": "長度必須小於 2500 個 Token",
|
||||||
"抽取可用的api-key": "提取可用的api-key",
|
"抽取可用的api-key": "提取可用的api-key",
|
||||||
"增强报告的可读性": "增強報告的可讀性",
|
"增强报告的可读性": "增強報告的可讀性",
|
||||||
|
|||||||
@@ -107,6 +107,12 @@ AZURE_API_KEY = "填入azure openai api的密钥"
|
|||||||
AZURE_API_VERSION = "2023-05-15" # 默认使用 2023-05-15 版本,无需修改
|
AZURE_API_VERSION = "2023-05-15" # 默认使用 2023-05-15 版本,无需修改
|
||||||
AZURE_ENGINE = "填入部署名" # 见上述图片
|
AZURE_ENGINE = "填入部署名" # 见上述图片
|
||||||
|
|
||||||
|
|
||||||
|
# 例如
|
||||||
|
API_KEY = '6424e9d19e674092815cea1cb35e67a5'
|
||||||
|
AZURE_ENDPOINT = 'https://rhtjjjjjj.openai.azure.com/'
|
||||||
|
AZURE_ENGINE = 'qqwe'
|
||||||
|
LLM_MODEL = "azure-gpt-3.5" # 可选 ↓↓↓
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
278
main.py
278
main.py
@@ -1,32 +1,46 @@
|
|||||||
import os; os.environ['no_proxy'] = '*' # 避免代理网络产生意外污染
|
import os; os.environ['no_proxy'] = '*' # 避免代理网络产生意外污染
|
||||||
|
import pickle
|
||||||
|
import codecs
|
||||||
|
import base64
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
import gradio as gr
|
import gradio as gr
|
||||||
if gr.__version__ not in ['3.28.3','3.32.2']: assert False, "需要特殊依赖,请务必用 pip install -r requirements.txt 指令安装依赖,详情信息见requirements.txt"
|
if gr.__version__ not in ['3.32.6']:
|
||||||
|
raise ModuleNotFoundError("使用项目内置Gradio获取最优体验! 请运行 `pip install -r requirements.txt` 指令安装内置Gradio及其他依赖, 详情信息见requirements.txt.")
|
||||||
from request_llm.bridge_all import predict
|
from request_llm.bridge_all import predict
|
||||||
from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf, ArgsGeneralWrapper, load_chat_cookies, 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被别人看到
|
# 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到
|
||||||
proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION = get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION')
|
proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION = get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION')
|
||||||
CHATBOT_HEIGHT, LAYOUT, AVAIL_LLM_MODELS, AUTO_CLEAR_TXT = get_conf('CHATBOT_HEIGHT', 'LAYOUT', 'AVAIL_LLM_MODELS', 'AUTO_CLEAR_TXT')
|
CHATBOT_HEIGHT, LAYOUT, AVAIL_LLM_MODELS, AUTO_CLEAR_TXT = get_conf('CHATBOT_HEIGHT', 'LAYOUT', 'AVAIL_LLM_MODELS', 'AUTO_CLEAR_TXT')
|
||||||
ENABLE_AUDIO, AUTO_CLEAR_TXT = get_conf('ENABLE_AUDIO', 'AUTO_CLEAR_TXT')
|
ENABLE_AUDIO, AUTO_CLEAR_TXT, PATH_LOGGING, AVAIL_THEMES, THEME = get_conf('ENABLE_AUDIO', 'AUTO_CLEAR_TXT', 'PATH_LOGGING', 'AVAIL_THEMES', 'THEME')
|
||||||
|
DARK_MODE, NUM_CUSTOM_BASIC_BTN, SSL_KEYFILE, SSL_CERTFILE = get_conf('DARK_MODE', 'NUM_CUSTOM_BASIC_BTN', 'SSL_KEYFILE', 'SSL_CERTFILE')
|
||||||
|
|
||||||
# 如果WEB_PORT是-1, 则随机选取WEB端口
|
# 如果WEB_PORT是-1, 则随机选取WEB端口
|
||||||
PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT
|
PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT
|
||||||
from check_proxy import get_current_version
|
from check_proxy import get_current_version
|
||||||
from themes.theme import adjust_theme, advanced_css, theme_declaration
|
from themes.theme import adjust_theme, advanced_css, theme_declaration, load_dynamic_theme
|
||||||
|
|
||||||
initial_prompt = "Serve me as a writing and programming assistant."
|
initial_prompt = "Serve me as a writing and programming assistant."
|
||||||
title_html = f"<h1 align=\"center\">GPT 学术优化 {get_current_version()}</h1>{theme_declaration}"
|
title_html = f"<h1 align=\"center\">GPT 学术优化 {get_current_version()}</h1>{theme_declaration}"
|
||||||
description = "代码开源和更新[地址🚀](https://github.com/binary-husky/gpt_academic),"
|
description = "Github源代码开源和更新[地址🚀](https://github.com/binary-husky/gpt_academic), "
|
||||||
description += "感谢热情的[开发者们❤️](https://github.com/binary-husky/gpt_academic/graphs/contributors)"
|
description += "感谢热情的[开发者们❤️](https://github.com/binary-husky/gpt_academic/graphs/contributors)."
|
||||||
|
description += "</br></br>常见问题请查阅[项目Wiki](https://github.com/binary-husky/gpt_academic/wiki), "
|
||||||
|
description += "如遇到Bug请前往[Bug反馈](https://github.com/binary-husky/gpt_academic/issues)."
|
||||||
|
description += "</br></br>普通对话使用说明: 1. 输入问题; 2. 点击提交"
|
||||||
|
description += "</br></br>基础功能区使用说明: 1. 输入文本; 2. 点击任意基础功能区按钮"
|
||||||
|
description += "</br></br>函数插件区使用说明: 1. 输入路径/问题, 或者上传文件; 2. 点击任意函数插件区按钮"
|
||||||
|
description += "</br></br>虚空终端使用说明: 点击虚空终端, 然后根据提示输入指令, 再次点击虚空终端"
|
||||||
|
description += "</br></br>如何保存对话: 点击保存当前的对话按钮"
|
||||||
|
description += "</br></br>如何语音对话: 请阅读Wiki"
|
||||||
|
|
||||||
# 问询记录, python 版本建议3.9+(越新越好)
|
# 问询记录, python 版本建议3.9+(越新越好)
|
||||||
import logging, uuid
|
import logging, uuid
|
||||||
os.makedirs("gpt_log", exist_ok=True)
|
os.makedirs(PATH_LOGGING, exist_ok=True)
|
||||||
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")
|
try:logging.basicConfig(filename=f"{PATH_LOGGING}/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")
|
except:logging.basicConfig(filename=f"{PATH_LOGGING}/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
|
# Disable logging output from the 'httpx' logger
|
||||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||||
print("所有问询记录将自动保存在本地目录./gpt_log/chat_secrets.log, 请注意自我隐私保护哦!")
|
print(f"所有问询记录将自动保存在本地目录./{PATH_LOGGING}/chat_secrets.log, 请注意自我隐私保护哦!")
|
||||||
|
|
||||||
# 一些普通功能模块
|
# 一些普通功能模块
|
||||||
from core_functional import get_core_functions
|
from core_functional import get_core_functions
|
||||||
@@ -57,8 +71,11 @@ def main():
|
|||||||
CHATBOT_HEIGHT /= 2
|
CHATBOT_HEIGHT /= 2
|
||||||
|
|
||||||
cancel_handles = []
|
cancel_handles = []
|
||||||
|
customize_btns = {}
|
||||||
|
predefined_btns = {}
|
||||||
with gr.Blocks(title="GPT 学术优化", theme=set_theme, analytics_enabled=False, css=advanced_css) as demo:
|
with gr.Blocks(title="GPT 学术优化", theme=set_theme, analytics_enabled=False, css=advanced_css) as demo:
|
||||||
gr.HTML(title_html)
|
gr.HTML(title_html)
|
||||||
|
secret_css, dark_mode, persistent_cookie = gr.Textbox(visible=False), gr.Textbox(DARK_MODE, visible=False), gr.Textbox(visible=False)
|
||||||
cookies = gr.State(load_chat_cookies())
|
cookies = gr.State(load_chat_cookies())
|
||||||
with gr_L1():
|
with gr_L1():
|
||||||
with gr_L2(scale=2, elem_id="gpt-chat"):
|
with gr_L2(scale=2, elem_id="gpt-chat"):
|
||||||
@@ -70,11 +87,11 @@ def main():
|
|||||||
with gr.Row():
|
with gr.Row():
|
||||||
txt = gr.Textbox(show_label=False, placeholder="Input question here.").style(container=False)
|
txt = gr.Textbox(show_label=False, placeholder="Input question here.").style(container=False)
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
submitBtn = gr.Button("提交", variant="primary")
|
submitBtn = gr.Button("提交", elem_id="elem_submit", variant="primary")
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
resetBtn = gr.Button("重置", variant="secondary"); resetBtn.style(size="sm")
|
resetBtn = gr.Button("重置", elem_id="elem_reset", variant="secondary"); resetBtn.style(size="sm")
|
||||||
stopBtn = gr.Button("停止", variant="secondary"); stopBtn.style(size="sm")
|
stopBtn = gr.Button("停止", elem_id="elem_stop", variant="secondary"); stopBtn.style(size="sm")
|
||||||
clearBtn = gr.Button("清除", variant="secondary", visible=False); clearBtn.style(size="sm")
|
clearBtn = gr.Button("清除", elem_id="elem_clear", variant="secondary", visible=False); clearBtn.style(size="sm")
|
||||||
if ENABLE_AUDIO:
|
if ENABLE_AUDIO:
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
audio_mic = gr.Audio(source="microphone", type="numpy", streaming=True, show_label=False).style(container=False)
|
audio_mic = gr.Audio(source="microphone", type="numpy", streaming=True, show_label=False).style(container=False)
|
||||||
@@ -82,11 +99,16 @@ def main():
|
|||||||
status = gr.Markdown(f"Tip: 按Enter提交, 按Shift+Enter换行。当前模型: {LLM_MODEL} \n {proxy_info}", elem_id="state-panel")
|
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.Accordion("基础功能区", open=True, elem_id="basic-panel") as area_basic_fn:
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
|
for k in range(NUM_CUSTOM_BASIC_BTN):
|
||||||
|
customize_btn = gr.Button("自定义按钮" + str(k+1), visible=False, variant="secondary", info_str=f'基础功能区: 自定义按钮')
|
||||||
|
customize_btn.style(size="sm")
|
||||||
|
customize_btns.update({"自定义按钮" + str(k+1): customize_btn})
|
||||||
for k in functional:
|
for k in functional:
|
||||||
if ("Visible" in functional[k]) and (not functional[k]["Visible"]): continue
|
if ("Visible" in functional[k]) and (not functional[k]["Visible"]): continue
|
||||||
variant = functional[k]["Color"] if "Color" in functional[k] else "secondary"
|
variant = functional[k]["Color"] if "Color" in functional[k] else "secondary"
|
||||||
functional[k]["Button"] = gr.Button(k, variant=variant)
|
functional[k]["Button"] = gr.Button(k, variant=variant, info_str=f'基础功能区: {k}')
|
||||||
functional[k]["Button"].style(size="sm")
|
functional[k]["Button"].style(size="sm")
|
||||||
|
predefined_btns.update({k: functional[k]["Button"]})
|
||||||
with gr.Accordion("函数插件区", open=True, elem_id="plugin-panel") as area_crazy_fn:
|
with gr.Accordion("函数插件区", open=True, elem_id="plugin-panel") as area_crazy_fn:
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
gr.Markdown("插件可读取“输入区”文本/路径作为参数(上传文件自动修正路径)")
|
gr.Markdown("插件可读取“输入区”文本/路径作为参数(上传文件自动修正路径)")
|
||||||
@@ -98,7 +120,9 @@ def main():
|
|||||||
if not plugin.get("AsButton", True): continue
|
if not plugin.get("AsButton", True): continue
|
||||||
visible = True if match_group(plugin['Group'], DEFAULT_FN_GROUPS) else False
|
visible = True if match_group(plugin['Group'], DEFAULT_FN_GROUPS) else False
|
||||||
variant = plugins[k]["Color"] if "Color" in plugin else "secondary"
|
variant = plugins[k]["Color"] if "Color" in plugin else "secondary"
|
||||||
plugin['Button'] = plugins[k]['Button'] = gr.Button(k, variant=variant, visible=visible).style(size="sm")
|
info = plugins[k].get("Info", k)
|
||||||
|
plugin['Button'] = plugins[k]['Button'] = gr.Button(k, variant=variant,
|
||||||
|
visible=visible, info_str=f'函数插件区: {info}').style(size="sm")
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
with gr.Accordion("更多函数插件", open=True):
|
with gr.Accordion("更多函数插件", open=True):
|
||||||
dropdown_fn_list = []
|
dropdown_fn_list = []
|
||||||
@@ -115,42 +139,148 @@ def main():
|
|||||||
switchy_bt = gr.Button(r"请先从插件列表中选择", variant="secondary").style(size="sm")
|
switchy_bt = gr.Button(r"请先从插件列表中选择", variant="secondary").style(size="sm")
|
||||||
with gr.Row():
|
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")
|
file_upload = gr.Files(label="任何文件, 推荐上传压缩文件(zip, tar)", file_count="multiple", elem_id="elem_upload")
|
||||||
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)
|
|
||||||
|
with gr.Floating(init_x="0%", init_y="0%", visible=True, width=None, drag="forbidden"):
|
||||||
|
with gr.Row():
|
||||||
|
with gr.Tab("上传文件", elem_id="interact-panel"):
|
||||||
|
gr.Markdown("请上传本地文件/压缩包供“函数插件区”功能调用。请注意: 上传文件后会自动把输入区修改为相应路径。")
|
||||||
|
file_upload_2 = gr.Files(label="任何文件, 推荐上传压缩文件(zip, tar)", file_count="multiple")
|
||||||
|
|
||||||
|
with gr.Tab("更换模型 & Prompt", elem_id="interact-panel"):
|
||||||
|
md_dropdown = gr.Dropdown(AVAIL_LLM_MODELS, value=LLM_MODEL, label="更换LLM模型/请求源").style(container=False)
|
||||||
top_p = gr.Slider(minimum=-0, maximum=1.0, value=1.0, step=0.01,interactive=True, label="Top-p (nucleus sampling)",)
|
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",)
|
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=8192, value=4096, step=1, interactive=True, label="Local LLM MaxLength",)
|
max_length_sl = gr.Slider(minimum=256, maximum=1024*32, value=4096, step=128, interactive=True, label="Local LLM MaxLength",)
|
||||||
checkboxes = gr.CheckboxGroup(["基础功能区", "函数插件区", "底部输入区", "输入清除键", "插件参数区"], value=["基础功能区", "函数插件区"], label="显示/隐藏功能区")
|
system_prompt = gr.Textbox(show_label=True, lines=2, placeholder=f"System Prompt", label="System prompt", value=initial_prompt)
|
||||||
md_dropdown = gr.Dropdown(AVAIL_LLM_MODELS, value=LLM_MODEL, label="更换LLM模型/请求源").style(container=False)
|
|
||||||
|
with gr.Tab("界面外观", elem_id="interact-panel"):
|
||||||
|
theme_dropdown = gr.Dropdown(AVAIL_THEMES, value=THEME, label="更换UI主题").style(container=False)
|
||||||
|
checkboxes = gr.CheckboxGroup(["基础功能区", "函数插件区", "浮动输入区", "输入清除键", "插件参数区"],
|
||||||
|
value=["基础功能区", "函数插件区"], label="显示/隐藏功能区", elem_id='cbs').style(container=False)
|
||||||
|
checkboxes_2 = gr.CheckboxGroup(["自定义菜单"],
|
||||||
|
value=[], label="显示/隐藏自定义菜单", elem_id='cbs').style(container=False)
|
||||||
|
dark_mode_btn = gr.Button("切换界面明暗 ☀", variant="secondary").style(size="sm")
|
||||||
|
dark_mode_btn.click(None, None, None, _js="""() => {
|
||||||
|
if (document.querySelectorAll('.dark').length) {
|
||||||
|
document.querySelectorAll('.dark').forEach(el => el.classList.remove('dark'));
|
||||||
|
} else {
|
||||||
|
document.querySelector('body').classList.add('dark');
|
||||||
|
}
|
||||||
|
}""",
|
||||||
|
)
|
||||||
|
with gr.Tab("帮助", elem_id="interact-panel"):
|
||||||
gr.Markdown(description)
|
gr.Markdown(description)
|
||||||
with gr.Accordion("备选输入区", open=True, visible=False, elem_id="input-panel2") as area_input_secondary:
|
|
||||||
with gr.Row():
|
with gr.Floating(init_x="20%", init_y="50%", visible=False, width="40%", drag="top") as area_input_secondary:
|
||||||
txt2 = gr.Textbox(show_label=False, placeholder="Input question here.", label="输入区2").style(container=False)
|
with gr.Accordion("浮动输入区", open=True, elem_id="input-panel2"):
|
||||||
with gr.Row():
|
with gr.Row() as row:
|
||||||
submitBtn2 = gr.Button("提交", variant="primary")
|
row.style(equal_height=True)
|
||||||
with gr.Row():
|
with gr.Column(scale=10):
|
||||||
|
txt2 = gr.Textbox(show_label=False, placeholder="Input question here.", lines=8, label="输入区2").style(container=False)
|
||||||
|
with gr.Column(scale=1, min_width=40):
|
||||||
|
submitBtn2 = gr.Button("提交", variant="primary"); submitBtn2.style(size="sm")
|
||||||
resetBtn2 = gr.Button("重置", variant="secondary"); resetBtn2.style(size="sm")
|
resetBtn2 = gr.Button("重置", variant="secondary"); resetBtn2.style(size="sm")
|
||||||
stopBtn2 = gr.Button("停止", variant="secondary"); stopBtn2.style(size="sm")
|
stopBtn2 = gr.Button("停止", variant="secondary"); stopBtn2.style(size="sm")
|
||||||
clearBtn2 = gr.Button("清除", variant="secondary", visible=False); clearBtn2.style(size="sm")
|
clearBtn2 = gr.Button("清除", variant="secondary", visible=False); clearBtn2.style(size="sm")
|
||||||
|
|
||||||
|
def to_cookie_str(d):
|
||||||
|
# Pickle the dictionary and encode it as a string
|
||||||
|
pickled_dict = pickle.dumps(d)
|
||||||
|
cookie_value = base64.b64encode(pickled_dict).decode('utf-8')
|
||||||
|
return cookie_value
|
||||||
|
|
||||||
|
def from_cookie_str(c):
|
||||||
|
# Decode the base64-encoded string and unpickle it into a dictionary
|
||||||
|
pickled_dict = base64.b64decode(c.encode('utf-8'))
|
||||||
|
return pickle.loads(pickled_dict)
|
||||||
|
|
||||||
|
with gr.Floating(init_x="20%", init_y="50%", visible=False, width="40%", drag="top") as area_customize:
|
||||||
|
with gr.Accordion("自定义菜单", open=True, elem_id="edit-panel"):
|
||||||
|
with gr.Row() as row:
|
||||||
|
with gr.Column(scale=10):
|
||||||
|
AVAIL_BTN = [btn for btn in customize_btns.keys()] + [k for k in functional]
|
||||||
|
basic_btn_dropdown = gr.Dropdown(AVAIL_BTN, value="自定义按钮1", label="选择一个需要自定义基础功能区按钮").style(container=False)
|
||||||
|
basic_fn_title = gr.Textbox(show_label=False, placeholder="输入新按钮名称", lines=1).style(container=False)
|
||||||
|
basic_fn_prefix = gr.Textbox(show_label=False, placeholder="输入新提示前缀", lines=4).style(container=False)
|
||||||
|
basic_fn_suffix = gr.Textbox(show_label=False, placeholder="输入新提示后缀", lines=4).style(container=False)
|
||||||
|
with gr.Column(scale=1, min_width=70):
|
||||||
|
basic_fn_confirm = gr.Button("确认并保存", variant="primary"); basic_fn_confirm.style(size="sm")
|
||||||
|
basic_fn_load = gr.Button("加载已保存", variant="primary"); basic_fn_load.style(size="sm")
|
||||||
|
def assign_btn(persistent_cookie_, cookies_, basic_btn_dropdown_, basic_fn_title, basic_fn_prefix, basic_fn_suffix):
|
||||||
|
ret = {}
|
||||||
|
customize_fn_overwrite_ = cookies_['customize_fn_overwrite']
|
||||||
|
customize_fn_overwrite_.update({
|
||||||
|
basic_btn_dropdown_:
|
||||||
|
{
|
||||||
|
"Title":basic_fn_title,
|
||||||
|
"Prefix":basic_fn_prefix,
|
||||||
|
"Suffix":basic_fn_suffix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cookies_.update(customize_fn_overwrite_)
|
||||||
|
if basic_btn_dropdown_ in customize_btns:
|
||||||
|
ret.update({customize_btns[basic_btn_dropdown_]: gr.update(visible=True, value=basic_fn_title)})
|
||||||
|
else:
|
||||||
|
ret.update({predefined_btns[basic_btn_dropdown_]: gr.update(visible=True, value=basic_fn_title)})
|
||||||
|
ret.update({cookies: cookies_})
|
||||||
|
try: persistent_cookie_ = from_cookie_str(persistent_cookie_) # persistent cookie to dict
|
||||||
|
except: persistent_cookie_ = {}
|
||||||
|
persistent_cookie_["custom_bnt"] = customize_fn_overwrite_ # dict update new value
|
||||||
|
persistent_cookie_ = to_cookie_str(persistent_cookie_) # persistent cookie to dict
|
||||||
|
ret.update({persistent_cookie: persistent_cookie_}) # write persistent cookie
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def reflesh_btn(persistent_cookie_, cookies_):
|
||||||
|
ret = {}
|
||||||
|
for k in customize_btns:
|
||||||
|
ret.update({customize_btns[k]: gr.update(visible=False, value="")})
|
||||||
|
|
||||||
|
try: persistent_cookie_ = from_cookie_str(persistent_cookie_) # persistent cookie to dict
|
||||||
|
except: return ret
|
||||||
|
|
||||||
|
customize_fn_overwrite_ = persistent_cookie_.get("custom_bnt", {})
|
||||||
|
cookies_['customize_fn_overwrite'] = customize_fn_overwrite_
|
||||||
|
ret.update({cookies: cookies_})
|
||||||
|
|
||||||
|
for k,v in persistent_cookie_["custom_bnt"].items():
|
||||||
|
if v['Title'] == "": continue
|
||||||
|
if k in customize_btns: ret.update({customize_btns[k]: gr.update(visible=True, value=v['Title'])})
|
||||||
|
else: ret.update({predefined_btns[k]: gr.update(visible=True, value=v['Title'])})
|
||||||
|
return ret
|
||||||
|
|
||||||
|
basic_fn_load.click(reflesh_btn, [persistent_cookie, cookies],[cookies, *customize_btns.values(), *predefined_btns.values()])
|
||||||
|
h = basic_fn_confirm.click(assign_btn, [persistent_cookie, cookies, basic_btn_dropdown, basic_fn_title, basic_fn_prefix, basic_fn_suffix],
|
||||||
|
[persistent_cookie, cookies, *customize_btns.values(), *predefined_btns.values()])
|
||||||
|
h.then(None, [persistent_cookie], None, _js="""(persistent_cookie)=>{setCookie("persistent_cookie", persistent_cookie, 5);}""") # save persistent cookie
|
||||||
|
|
||||||
# 功能区显示开关与功能区的互动
|
# 功能区显示开关与功能区的互动
|
||||||
def fn_area_visibility(a):
|
def fn_area_visibility(a):
|
||||||
ret = {}
|
ret = {}
|
||||||
ret.update({area_basic_fn: gr.update(visible=("基础功能区" in a))})
|
ret.update({area_basic_fn: gr.update(visible=("基础功能区" in a))})
|
||||||
ret.update({area_crazy_fn: gr.update(visible=("函数插件区" in a))})
|
ret.update({area_crazy_fn: gr.update(visible=("函数插件区" in a))})
|
||||||
ret.update({area_input_primary: gr.update(visible=("底部输入区" not in a))})
|
ret.update({area_input_primary: gr.update(visible=("浮动输入区" not in a))})
|
||||||
ret.update({area_input_secondary: gr.update(visible=("底部输入区" in a))})
|
ret.update({area_input_secondary: gr.update(visible=("浮动输入区" in a))})
|
||||||
ret.update({clearBtn: gr.update(visible=("输入清除键" in a))})
|
ret.update({clearBtn: gr.update(visible=("输入清除键" in a))})
|
||||||
ret.update({clearBtn2: gr.update(visible=("输入清除键" in a))})
|
ret.update({clearBtn2: gr.update(visible=("输入清除键" in a))})
|
||||||
ret.update({plugin_advanced_arg: gr.update(visible=("插件参数区" in a))})
|
ret.update({plugin_advanced_arg: gr.update(visible=("插件参数区" in a))})
|
||||||
if "底部输入区" in a: ret.update({txt: gr.update(value="")})
|
if "浮动输入区" in a: ret.update({txt: gr.update(value="")})
|
||||||
return ret
|
return ret
|
||||||
checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn, area_input_primary, area_input_secondary, txt, txt2, clearBtn, clearBtn2, plugin_advanced_arg] )
|
checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn, area_input_primary, area_input_secondary, txt, txt2, clearBtn, clearBtn2, plugin_advanced_arg] )
|
||||||
|
|
||||||
|
# 功能区显示开关与功能区的互动
|
||||||
|
def fn_area_visibility_2(a):
|
||||||
|
ret = {}
|
||||||
|
ret.update({area_customize: gr.update(visible=("自定义菜单" in a))})
|
||||||
|
return ret
|
||||||
|
checkboxes_2.select(fn_area_visibility_2, [checkboxes_2], [area_customize] )
|
||||||
|
|
||||||
# 整理反复出现的控件句柄组合
|
# 整理反复出现的控件句柄组合
|
||||||
input_combo = [cookies, max_length_sl, md_dropdown, txt, txt2, top_p, temperature, chatbot, history, system_prompt, plugin_advanced_arg]
|
input_combo = [cookies, max_length_sl, md_dropdown, txt, txt2, top_p, temperature, chatbot, history, system_prompt, plugin_advanced_arg]
|
||||||
output_combo = [cookies, chatbot, history, status]
|
output_combo = [cookies, chatbot, history, status]
|
||||||
predict_args = dict(fn=ArgsGeneralWrapper(predict), inputs=input_combo, outputs=output_combo)
|
predict_args = dict(fn=ArgsGeneralWrapper(predict), inputs=[*input_combo, gr.State(True)], outputs=output_combo)
|
||||||
# 提交按钮、重置按钮
|
# 提交按钮、重置按钮
|
||||||
cancel_handles.append(txt.submit(**predict_args))
|
cancel_handles.append(txt.submit(**predict_args))
|
||||||
cancel_handles.append(txt2.submit(**predict_args))
|
cancel_handles.append(txt2.submit(**predict_args))
|
||||||
@@ -170,32 +300,65 @@ def main():
|
|||||||
if ("Visible" in functional[k]) and (not functional[k]["Visible"]): continue
|
if ("Visible" in functional[k]) and (not functional[k]["Visible"]): continue
|
||||||
click_handle = functional[k]["Button"].click(fn=ArgsGeneralWrapper(predict), inputs=[*input_combo, gr.State(True), gr.State(k)], outputs=output_combo)
|
click_handle = functional[k]["Button"].click(fn=ArgsGeneralWrapper(predict), inputs=[*input_combo, gr.State(True), gr.State(k)], outputs=output_combo)
|
||||||
cancel_handles.append(click_handle)
|
cancel_handles.append(click_handle)
|
||||||
|
for btn in customize_btns.values():
|
||||||
|
click_handle = btn.click(fn=ArgsGeneralWrapper(predict), inputs=[*input_combo, gr.State(True), gr.State(btn.value)], outputs=output_combo)
|
||||||
|
cancel_handles.append(click_handle)
|
||||||
# 文件上传区,接收文件后与chatbot的互动
|
# 文件上传区,接收文件后与chatbot的互动
|
||||||
file_upload.upload(on_file_uploaded, [file_upload, chatbot, txt, txt2, checkboxes, cookies], [chatbot, txt, txt2, cookies])
|
file_upload.upload(on_file_uploaded, [file_upload, chatbot, txt, txt2, checkboxes, cookies], [chatbot, txt, txt2, cookies])
|
||||||
|
file_upload_2.upload(on_file_uploaded, [file_upload_2, chatbot, txt, txt2, checkboxes, cookies], [chatbot, txt, txt2, cookies])
|
||||||
# 函数插件-固定按钮区
|
# 函数插件-固定按钮区
|
||||||
for k in plugins:
|
for k in plugins:
|
||||||
if not plugins[k].get("AsButton", True): continue
|
if not plugins[k].get("AsButton", True): continue
|
||||||
click_handle = plugins[k]["Button"].click(ArgsGeneralWrapper(plugins[k]["Function"]), [*input_combo, gr.State(PORT)], output_combo)
|
click_handle = plugins[k]["Button"].click(ArgsGeneralWrapper(plugins[k]["Function"]), [*input_combo], output_combo)
|
||||||
click_handle.then(on_report_generated, [cookies, file_upload, chatbot], [cookies, file_upload, chatbot])
|
click_handle.then(on_report_generated, [cookies, file_upload, chatbot], [cookies, file_upload, chatbot])
|
||||||
cancel_handles.append(click_handle)
|
cancel_handles.append(click_handle)
|
||||||
# 函数插件-下拉菜单与随变按钮的互动
|
# 函数插件-下拉菜单与随变按钮的互动
|
||||||
def on_dropdown_changed(k):
|
def on_dropdown_changed(k):
|
||||||
variant = plugins[k]["Color"] if "Color" in plugins[k] else "secondary"
|
variant = plugins[k]["Color"] if "Color" in plugins[k] else "secondary"
|
||||||
ret = {switchy_bt: gr.update(value=k, variant=variant)}
|
info = plugins[k].get("Info", k)
|
||||||
|
ret = {switchy_bt: gr.update(value=k, variant=variant, info_str=f'函数插件区: {info}')}
|
||||||
if plugins[k].get("AdvancedArgs", False): # 是否唤起高级插件参数区
|
if plugins[k].get("AdvancedArgs", False): # 是否唤起高级插件参数区
|
||||||
ret.update({plugin_advanced_arg: gr.update(visible=True, label=f"插件[{k}]的高级参数说明:" + plugins[k].get("ArgsReminder", [f"没有提供高级参数功能说明"]))})
|
ret.update({plugin_advanced_arg: gr.update(visible=True, label=f"插件[{k}]的高级参数说明:" + plugins[k].get("ArgsReminder", [f"没有提供高级参数功能说明"]))})
|
||||||
else:
|
else:
|
||||||
ret.update({plugin_advanced_arg: gr.update(visible=False, label=f"插件[{k}]不需要高级参数。")})
|
ret.update({plugin_advanced_arg: gr.update(visible=False, label=f"插件[{k}]不需要高级参数。")})
|
||||||
return ret
|
return ret
|
||||||
dropdown.select(on_dropdown_changed, [dropdown], [switchy_bt, plugin_advanced_arg] )
|
dropdown.select(on_dropdown_changed, [dropdown], [switchy_bt, plugin_advanced_arg] )
|
||||||
|
|
||||||
def on_md_dropdown_changed(k):
|
def on_md_dropdown_changed(k):
|
||||||
return {chatbot: gr.update(label="当前模型:"+k)}
|
return {chatbot: gr.update(label="当前模型:"+k)}
|
||||||
md_dropdown.select(on_md_dropdown_changed, [md_dropdown], [chatbot] )
|
md_dropdown.select(on_md_dropdown_changed, [md_dropdown], [chatbot] )
|
||||||
|
|
||||||
|
def on_theme_dropdown_changed(theme, secret_css):
|
||||||
|
adjust_theme, css_part1, _, adjust_dynamic_theme = load_dynamic_theme(theme)
|
||||||
|
if adjust_dynamic_theme:
|
||||||
|
css_part2 = adjust_dynamic_theme._get_theme_css()
|
||||||
|
else:
|
||||||
|
css_part2 = adjust_theme()._get_theme_css()
|
||||||
|
return css_part2 + css_part1
|
||||||
|
|
||||||
|
theme_handle = theme_dropdown.select(on_theme_dropdown_changed, [theme_dropdown, secret_css], [secret_css])
|
||||||
|
theme_handle.then(
|
||||||
|
None,
|
||||||
|
[secret_css],
|
||||||
|
None,
|
||||||
|
_js="""(css) => {
|
||||||
|
var existingStyles = document.querySelectorAll("style[data-loaded-css]");
|
||||||
|
for (var i = 0; i < existingStyles.length; i++) {
|
||||||
|
var style = existingStyles[i];
|
||||||
|
style.parentNode.removeChild(style);
|
||||||
|
}
|
||||||
|
var styleElement = document.createElement('style');
|
||||||
|
styleElement.setAttribute('data-loaded-css', css);
|
||||||
|
styleElement.innerHTML = css;
|
||||||
|
document.head.appendChild(styleElement);
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
# 随变按钮的回调函数注册
|
# 随变按钮的回调函数注册
|
||||||
def route(request: gr.Request, k, *args, **kwargs):
|
def route(request: gr.Request, k, *args, **kwargs):
|
||||||
if k in [r"打开插件列表", r"请先从插件列表中选择"]: return
|
if k in [r"打开插件列表", r"请先从插件列表中选择"]: return
|
||||||
yield from ArgsGeneralWrapper(plugins[k]["Function"])(request, *args, **kwargs)
|
yield from ArgsGeneralWrapper(plugins[k]["Function"])(request, *args, **kwargs)
|
||||||
click_handle = switchy_bt.click(route,[switchy_bt, *input_combo, gr.State(PORT)], output_combo)
|
click_handle = switchy_bt.click(route,[switchy_bt, *input_combo], output_combo)
|
||||||
click_handle.then(on_report_generated, [cookies, file_upload, chatbot], [cookies, file_upload, chatbot])
|
click_handle.then(on_report_generated, [cookies, file_upload, chatbot], [cookies, file_upload, chatbot])
|
||||||
cancel_handles.append(click_handle)
|
cancel_handles.append(click_handle)
|
||||||
# 终止按钮的回调函数注册
|
# 终止按钮的回调函数注册
|
||||||
@@ -226,26 +389,47 @@ def main():
|
|||||||
cookies.update({'uuid': uuid.uuid4()})
|
cookies.update({'uuid': uuid.uuid4()})
|
||||||
return cookies
|
return cookies
|
||||||
demo.load(init_cookie, inputs=[cookies, chatbot], outputs=[cookies])
|
demo.load(init_cookie, inputs=[cookies, chatbot], outputs=[cookies])
|
||||||
demo.load(lambda: 0, inputs=None, outputs=None, _js='()=>{ChatBotHeight();}')
|
darkmode_js = """(dark) => {
|
||||||
|
dark = dark == "True";
|
||||||
|
if (document.querySelectorAll('.dark').length) {
|
||||||
|
if (!dark){
|
||||||
|
document.querySelectorAll('.dark').forEach(el => el.classList.remove('dark'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dark){
|
||||||
|
document.querySelector('body').classList.add('dark');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
load_cookie_js = """(persistent_cookie) => {
|
||||||
|
return getCookie("persistent_cookie");
|
||||||
|
}"""
|
||||||
|
demo.load(None, inputs=None, outputs=[persistent_cookie], _js=load_cookie_js)
|
||||||
|
demo.load(None, inputs=[dark_mode], outputs=None, _js=darkmode_js) # 配置暗色主题或亮色主题
|
||||||
|
demo.load(None, inputs=[gr.Textbox(LAYOUT, visible=False)], outputs=None, _js='(LAYOUT)=>{GptAcademicJavaScriptInit(LAYOUT);}')
|
||||||
|
|
||||||
# gradio的inbrowser触发不太稳定,回滚代码到原始的浏览器打开函数
|
# gradio的inbrowser触发不太稳定,回滚代码到原始的浏览器打开函数
|
||||||
def auto_opentab_delay():
|
def run_delayed_tasks():
|
||||||
import threading, webbrowser, time
|
import threading, webbrowser, time
|
||||||
print(f"如果浏览器没有自动打开,请复制并转到以下URL:")
|
print(f"如果浏览器没有自动打开,请复制并转到以下URL:")
|
||||||
print(f"\t(亮色主题): http://localhost:{PORT}")
|
if DARK_MODE: print(f"\t「暗色主题已启用(支持动态切换主题)」: http://localhost:{PORT}")
|
||||||
print(f"\t(暗色主题): http://localhost:{PORT}/?__theme=dark")
|
else: print(f"\t「亮色主题已启用(支持动态切换主题)」: http://localhost:{PORT}")
|
||||||
def open():
|
|
||||||
time.sleep(2) # 打开浏览器
|
|
||||||
DARK_MODE, = get_conf('DARK_MODE')
|
|
||||||
if DARK_MODE: webbrowser.open_new_tab(f"http://localhost:{PORT}/?__theme=dark")
|
|
||||||
else: webbrowser.open_new_tab(f"http://localhost:{PORT}")
|
|
||||||
threading.Thread(target=open, name="open-browser", daemon=True).start()
|
|
||||||
threading.Thread(target=auto_update, name="self-upgrade", daemon=True).start()
|
|
||||||
threading.Thread(target=warm_up_modules, name="warm-up", daemon=True).start()
|
|
||||||
|
|
||||||
auto_opentab_delay()
|
def auto_updates(): time.sleep(0); auto_update()
|
||||||
|
def open_browser(): time.sleep(2); webbrowser.open_new_tab(f"http://localhost:{PORT}")
|
||||||
|
def warm_up_mods(): time.sleep(4); warm_up_modules()
|
||||||
|
|
||||||
|
threading.Thread(target=auto_updates, name="self-upgrade", daemon=True).start() # 查看自动更新
|
||||||
|
threading.Thread(target=open_browser, name="open-browser", daemon=True).start() # 打开浏览器页面
|
||||||
|
threading.Thread(target=warm_up_mods, name="warm-up", daemon=True).start() # 预热tiktoken模块
|
||||||
|
|
||||||
|
run_delayed_tasks()
|
||||||
demo.queue(concurrency_count=CONCURRENT_COUNT).launch(
|
demo.queue(concurrency_count=CONCURRENT_COUNT).launch(
|
||||||
|
quiet=True,
|
||||||
server_name="0.0.0.0",
|
server_name="0.0.0.0",
|
||||||
|
ssl_keyfile=None if SSL_KEYFILE == "" else SSL_KEYFILE,
|
||||||
|
ssl_certfile=None if SSL_CERTFILE == "" else SSL_CERTFILE,
|
||||||
|
ssl_verify=False,
|
||||||
server_port=PORT,
|
server_port=PORT,
|
||||||
favicon_path="docs/logo.png",
|
favicon_path="docs/logo.png",
|
||||||
auth=AUTHENTICATION if len(AUTHENTICATION) != 0 else None,
|
auth=AUTHENTICATION if len(AUTHENTICATION) != 0 else None,
|
||||||
|
|||||||
@@ -33,9 +33,11 @@ import functools
|
|||||||
import re
|
import re
|
||||||
import pickle
|
import pickle
|
||||||
import time
|
import time
|
||||||
|
from toolbox import get_conf
|
||||||
|
|
||||||
CACHE_FOLDER = "gpt_log"
|
CACHE_FOLDER, = get_conf('PATH_LOGGING')
|
||||||
blacklist = ['multi-language', 'gpt_log', '.git', 'private_upload', 'multi_language.py', 'build', '.github', '.vscode', '__pycache__', 'venv']
|
|
||||||
|
blacklist = ['multi-language', CACHE_FOLDER, '.git', 'private_upload', 'multi_language.py', 'build', '.github', '.vscode', '__pycache__', 'venv']
|
||||||
|
|
||||||
# LANG = "TraditionalChinese"
|
# LANG = "TraditionalChinese"
|
||||||
# TransPrompt = f"Replace each json value `#` with translated results in Traditional Chinese, e.g., \"原始文本\":\"翻譯後文字\". Keep Json format. Do not answer #."
|
# TransPrompt = f"Replace each json value `#` with translated results in Traditional Chinese, e.g., \"原始文本\":\"翻譯後文字\". Keep Json format. Do not answer #."
|
||||||
@@ -478,6 +480,8 @@ def step_2_core_key_translate():
|
|||||||
up = trans_json(need_translate, language=LANG, special=False)
|
up = trans_json(need_translate, language=LANG, special=False)
|
||||||
map_to_json(up, language=LANG)
|
map_to_json(up, language=LANG)
|
||||||
cached_translation = read_map_from_json(language=LANG)
|
cached_translation = read_map_from_json(language=LANG)
|
||||||
|
LANG_STD = 'std'
|
||||||
|
cached_translation.update(read_map_from_json(language=LANG_STD))
|
||||||
cached_translation = dict(sorted(cached_translation.items(), key=lambda x: -len(x[0])))
|
cached_translation = dict(sorted(cached_translation.items(), key=lambda x: -len(x[0])))
|
||||||
|
|
||||||
# ===============================================
|
# ===============================================
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ API_URL_REDIRECT, AZURE_ENDPOINT, AZURE_ENGINE = get_conf("API_URL_REDIRECT", "A
|
|||||||
openai_endpoint = "https://api.openai.com/v1/chat/completions"
|
openai_endpoint = "https://api.openai.com/v1/chat/completions"
|
||||||
api2d_endpoint = "https://openai.api2d.net/v1/chat/completions"
|
api2d_endpoint = "https://openai.api2d.net/v1/chat/completions"
|
||||||
newbing_endpoint = "wss://sydney.bing.com/sydney/ChatHub"
|
newbing_endpoint = "wss://sydney.bing.com/sydney/ChatHub"
|
||||||
|
if not AZURE_ENDPOINT.endswith('/'): AZURE_ENDPOINT += '/'
|
||||||
azure_endpoint = AZURE_ENDPOINT + f'openai/deployments/{AZURE_ENGINE}/chat/completions?api-version=2023-05-15'
|
azure_endpoint = AZURE_ENDPOINT + f'openai/deployments/{AZURE_ENGINE}/chat/completions?api-version=2023-05-15'
|
||||||
# 兼容旧版的配置
|
# 兼容旧版的配置
|
||||||
try:
|
try:
|
||||||
@@ -125,6 +126,24 @@ model_info = {
|
|||||||
"token_cnt": get_token_num_gpt4,
|
"token_cnt": get_token_num_gpt4,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"gpt-4-32k": {
|
||||||
|
"fn_with_ui": chatgpt_ui,
|
||||||
|
"fn_without_ui": chatgpt_noui,
|
||||||
|
"endpoint": openai_endpoint,
|
||||||
|
"max_token": 32768,
|
||||||
|
"tokenizer": tokenizer_gpt4,
|
||||||
|
"token_cnt": get_token_num_gpt4,
|
||||||
|
},
|
||||||
|
|
||||||
|
"gpt-3.5-random": {
|
||||||
|
"fn_with_ui": chatgpt_ui,
|
||||||
|
"fn_without_ui": chatgpt_noui,
|
||||||
|
"endpoint": openai_endpoint,
|
||||||
|
"max_token": 4096,
|
||||||
|
"tokenizer": tokenizer_gpt4,
|
||||||
|
"token_cnt": get_token_num_gpt4,
|
||||||
|
},
|
||||||
|
|
||||||
# azure openai
|
# azure openai
|
||||||
"azure-gpt-3.5":{
|
"azure-gpt-3.5":{
|
||||||
"fn_with_ui": chatgpt_ui,
|
"fn_with_ui": chatgpt_ui,
|
||||||
@@ -135,6 +154,15 @@ model_info = {
|
|||||||
"token_cnt": get_token_num_gpt35,
|
"token_cnt": get_token_num_gpt35,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"azure-gpt-4":{
|
||||||
|
"fn_with_ui": chatgpt_ui,
|
||||||
|
"fn_without_ui": chatgpt_noui,
|
||||||
|
"endpoint": azure_endpoint,
|
||||||
|
"max_token": 8192,
|
||||||
|
"tokenizer": tokenizer_gpt35,
|
||||||
|
"token_cnt": get_token_num_gpt35,
|
||||||
|
},
|
||||||
|
|
||||||
# api_2d
|
# api_2d
|
||||||
"api2d-gpt-3.5-turbo": {
|
"api2d-gpt-3.5-turbo": {
|
||||||
"fn_with_ui": chatgpt_ui,
|
"fn_with_ui": chatgpt_ui,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from transformers import AutoModel, AutoTokenizer
|
|||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
import importlib
|
import importlib
|
||||||
from toolbox import update_ui, get_conf
|
from toolbox import update_ui, get_conf, ProxyNetworkActivate
|
||||||
from multiprocessing import Process, Pipe
|
from multiprocessing import Process, Pipe
|
||||||
|
|
||||||
load_message = "ChatGLM尚未加载,加载需要一段时间。注意,取决于`config.py`的配置,ChatGLM消耗大量的内存(CPU)或显存(GPU),也许会导致低配计算机卡死 ……"
|
load_message = "ChatGLM尚未加载,加载需要一段时间。注意,取决于`config.py`的配置,ChatGLM消耗大量的内存(CPU)或显存(GPU),也许会导致低配计算机卡死 ……"
|
||||||
@@ -48,16 +48,17 @@ class GetGLMHandle(Process):
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
if self.chatglm_model is None:
|
with ProxyNetworkActivate('Download_LLM'):
|
||||||
self.chatglm_tokenizer = AutoTokenizer.from_pretrained(_model_name_, trust_remote_code=True)
|
if self.chatglm_model is None:
|
||||||
if device=='cpu':
|
self.chatglm_tokenizer = AutoTokenizer.from_pretrained(_model_name_, trust_remote_code=True)
|
||||||
self.chatglm_model = AutoModel.from_pretrained(_model_name_, trust_remote_code=True).float()
|
if device=='cpu':
|
||||||
|
self.chatglm_model = AutoModel.from_pretrained(_model_name_, trust_remote_code=True).float()
|
||||||
|
else:
|
||||||
|
self.chatglm_model = AutoModel.from_pretrained(_model_name_, trust_remote_code=True).half().cuda()
|
||||||
|
self.chatglm_model = self.chatglm_model.eval()
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
self.chatglm_model = AutoModel.from_pretrained(_model_name_, trust_remote_code=True).half().cuda()
|
break
|
||||||
self.chatglm_model = self.chatglm_model.eval()
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
except:
|
except:
|
||||||
retry += 1
|
retry += 1
|
||||||
if retry > 3:
|
if retry > 3:
|
||||||
|
|||||||
@@ -18,10 +18,11 @@ import logging
|
|||||||
import traceback
|
import traceback
|
||||||
import requests
|
import requests
|
||||||
import importlib
|
import importlib
|
||||||
|
import random
|
||||||
|
|
||||||
# config_private.py放自己的秘密如API和代理网址
|
# config_private.py放自己的秘密如API和代理网址
|
||||||
# 读取时首先看是否存在私密的config_private配置文件(不受git管控),如果有,则覆盖原config文件
|
# 读取时首先看是否存在私密的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
|
from toolbox import get_conf, update_ui, is_any_api_key, select_api_key, what_keys, clip_history, trimmed_format_exc, is_the_upload_folder
|
||||||
proxies, TIMEOUT_SECONDS, MAX_RETRY, API_ORG = \
|
proxies, TIMEOUT_SECONDS, MAX_RETRY, API_ORG = \
|
||||||
get_conf('proxies', 'TIMEOUT_SECONDS', 'MAX_RETRY', 'API_ORG')
|
get_conf('proxies', 'TIMEOUT_SECONDS', 'MAX_RETRY', 'API_ORG')
|
||||||
|
|
||||||
@@ -39,6 +40,21 @@ def get_full_error(chunk, stream_response):
|
|||||||
break
|
break
|
||||||
return chunk
|
return chunk
|
||||||
|
|
||||||
|
def decode_chunk(chunk):
|
||||||
|
# 提前读取一些信息 (用于判断异常)
|
||||||
|
chunk_decoded = chunk.decode()
|
||||||
|
chunkjson = None
|
||||||
|
has_choices = False
|
||||||
|
has_content = False
|
||||||
|
has_role = False
|
||||||
|
try:
|
||||||
|
chunkjson = json.loads(chunk_decoded[6:])
|
||||||
|
has_choices = 'choices' in chunkjson
|
||||||
|
if has_choices: has_content = "content" in chunkjson['choices'][0]["delta"]
|
||||||
|
if has_choices: has_role = "role" in chunkjson['choices'][0]["delta"]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return chunk_decoded, chunkjson, has_choices, has_content, has_role
|
||||||
|
|
||||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=None, console_slience=False):
|
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=None, console_slience=False):
|
||||||
"""
|
"""
|
||||||
@@ -72,6 +88,7 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
|
|||||||
|
|
||||||
stream_response = response.iter_lines()
|
stream_response = response.iter_lines()
|
||||||
result = ''
|
result = ''
|
||||||
|
json_data = None
|
||||||
while True:
|
while True:
|
||||||
try: chunk = next(stream_response).decode()
|
try: chunk = next(stream_response).decode()
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
@@ -90,20 +107,21 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
|
|||||||
delta = json_data["delta"]
|
delta = json_data["delta"]
|
||||||
if len(delta) == 0: break
|
if len(delta) == 0: break
|
||||||
if "role" in delta: continue
|
if "role" in delta: continue
|
||||||
if "content" in delta:
|
if "content" in delta:
|
||||||
result += delta["content"]
|
result += delta["content"]
|
||||||
if not console_slience: print(delta["content"], end='')
|
if not console_slience: print(delta["content"], end='')
|
||||||
if observe_window is not None:
|
if observe_window is not None:
|
||||||
# 观测窗,把已经获取的数据显示出去
|
# 观测窗,把已经获取的数据显示出去
|
||||||
if len(observe_window) >= 1: observe_window[0] += delta["content"]
|
if len(observe_window) >= 1:
|
||||||
|
observe_window[0] += delta["content"]
|
||||||
# 看门狗,如果超过期限没有喂狗,则终止
|
# 看门狗,如果超过期限没有喂狗,则终止
|
||||||
if len(observe_window) >= 2:
|
if len(observe_window) >= 2:
|
||||||
if (time.time()-observe_window[1]) > watch_dog_patience:
|
if (time.time()-observe_window[1]) > watch_dog_patience:
|
||||||
raise RuntimeError("用户取消了程序。")
|
raise RuntimeError("用户取消了程序。")
|
||||||
else: raise RuntimeError("意外Json结构:"+delta)
|
else: raise RuntimeError("意外Json结构:"+delta)
|
||||||
if json_data['finish_reason'] == 'content_filter':
|
if json_data and json_data['finish_reason'] == 'content_filter':
|
||||||
raise RuntimeError("由于提问含不合规内容被Azure过滤。")
|
raise RuntimeError("由于提问含不合规内容被Azure过滤。")
|
||||||
if json_data['finish_reason'] == 'length':
|
if json_data and json_data['finish_reason'] == 'length':
|
||||||
raise ConnectionAbortedError("正常结束,但显示Token不足,导致输出不完整,请削减单次输入的文本量。")
|
raise ConnectionAbortedError("正常结束,但显示Token不足,导致输出不完整,请削减单次输入的文本量。")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -128,6 +146,7 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
|
|||||||
yield from update_ui(chatbot=chatbot, history=history, msg="缺少api_key") # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg="缺少api_key") # 刷新界面
|
||||||
return
|
return
|
||||||
|
|
||||||
|
user_input = inputs
|
||||||
if additional_fn is not None:
|
if additional_fn is not None:
|
||||||
from core_functional import handle_core_functionality
|
from core_functional import handle_core_functionality
|
||||||
inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot)
|
inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot)
|
||||||
@@ -138,8 +157,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
|
|||||||
yield from update_ui(chatbot=chatbot, history=history, msg="等待响应") # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg="等待响应") # 刷新界面
|
||||||
|
|
||||||
# check mis-behavior
|
# check mis-behavior
|
||||||
if raw_input.startswith('private_upload/') and len(raw_input) == 34:
|
if is_the_upload_folder(user_input):
|
||||||
chatbot[-1] = (inputs, f"[Local Message] 检测到操作错误!当您上传文档之后,需要点击“函数插件区”按钮进行处理,而不是点击“提交”按钮。")
|
chatbot[-1] = (inputs, f"[Local Message] 检测到操作错误!当您上传文档之后,需点击“**函数插件区**”按钮进行处理,请勿点击“提交”按钮或者“基础功能区”按钮。")
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg="正常") # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg="正常") # 刷新界面
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
@@ -179,11 +198,18 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
|
|||||||
# 非OpenAI官方接口的出现这样的报错,OpenAI和API2D不会走这里
|
# 非OpenAI官方接口的出现这样的报错,OpenAI和API2D不会走这里
|
||||||
chunk_decoded = chunk.decode()
|
chunk_decoded = chunk.decode()
|
||||||
error_msg = chunk_decoded
|
error_msg = chunk_decoded
|
||||||
|
# 首先排除一个one-api没有done数据包的第三方Bug情形
|
||||||
|
if len(gpt_replying_buffer.strip()) > 0 and len(error_msg) == 0:
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history, msg="检测到有缺陷的非OpenAI官方接口,建议选择更稳定的接口。")
|
||||||
|
break
|
||||||
|
# 其他情况,直接返回报错
|
||||||
chatbot, history = handle_error(inputs, llm_kwargs, chatbot, history, chunk_decoded, error_msg)
|
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()) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg="非OpenAI官方接口返回了错误:" + chunk.decode()) # 刷新界面
|
||||||
return
|
return
|
||||||
|
|
||||||
chunk_decoded = chunk.decode()
|
# 提前读取一些信息 (用于判断异常)
|
||||||
|
chunk_decoded, chunkjson, has_choices, has_content, has_role = decode_chunk(chunk)
|
||||||
|
|
||||||
if is_head_of_the_stream and (r'"object":"error"' not in chunk_decoded) and (r"content" not in chunk_decoded):
|
if is_head_of_the_stream and (r'"object":"error"' not in chunk_decoded) and (r"content" not in chunk_decoded):
|
||||||
# 数据流的第一帧不携带content
|
# 数据流的第一帧不携带content
|
||||||
is_head_of_the_stream = False; continue
|
is_head_of_the_stream = False; continue
|
||||||
@@ -191,15 +217,23 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
|
|||||||
if chunk:
|
if chunk:
|
||||||
try:
|
try:
|
||||||
# 前者是API2D的结束条件,后者是OPENAI的结束条件
|
# 前者是API2D的结束条件,后者是OPENAI的结束条件
|
||||||
if ('data: [DONE]' in chunk_decoded) or (len(json.loads(chunk_decoded[6:])['choices'][0]["delta"]) == 0):
|
if ('data: [DONE]' in chunk_decoded) or (len(chunkjson['choices'][0]["delta"]) == 0):
|
||||||
# 判定为数据流的结束,gpt_replying_buffer也写完了
|
# 判定为数据流的结束,gpt_replying_buffer也写完了
|
||||||
logging.info(f'[response] {gpt_replying_buffer}')
|
logging.info(f'[response] {gpt_replying_buffer}')
|
||||||
break
|
break
|
||||||
# 处理数据流的主体
|
# 处理数据流的主体
|
||||||
chunkjson = json.loads(chunk_decoded[6:])
|
|
||||||
status_text = f"finish_reason: {chunkjson['choices'][0].get('finish_reason', 'null')}"
|
status_text = f"finish_reason: {chunkjson['choices'][0].get('finish_reason', 'null')}"
|
||||||
# 如果这里抛出异常,一般是文本过长,详情见get_full_error的输出
|
# 如果这里抛出异常,一般是文本过长,详情见get_full_error的输出
|
||||||
gpt_replying_buffer = gpt_replying_buffer + json.loads(chunk_decoded[6:])['choices'][0]["delta"]["content"]
|
if has_content:
|
||||||
|
# 正常情况
|
||||||
|
gpt_replying_buffer = gpt_replying_buffer + chunkjson['choices'][0]["delta"]["content"]
|
||||||
|
elif has_role:
|
||||||
|
# 一些第三方接口的出现这样的错误,兼容一下吧
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
# 一些垃圾第三方接口的出现这样的错误
|
||||||
|
gpt_replying_buffer = gpt_replying_buffer + chunkjson['choices'][0]["delta"]["content"]
|
||||||
|
|
||||||
history[-1] = gpt_replying_buffer
|
history[-1] = gpt_replying_buffer
|
||||||
chatbot[-1] = (history[-2], history[-1])
|
chatbot[-1] = (history[-2], history[-1])
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=status_text) # 刷新界面
|
yield from update_ui(chatbot=chatbot, history=history, msg=status_text) # 刷新界面
|
||||||
@@ -280,9 +314,19 @@ def generate_payload(inputs, llm_kwargs, history, system_prompt, stream):
|
|||||||
what_i_ask_now["role"] = "user"
|
what_i_ask_now["role"] = "user"
|
||||||
what_i_ask_now["content"] = inputs
|
what_i_ask_now["content"] = inputs
|
||||||
messages.append(what_i_ask_now)
|
messages.append(what_i_ask_now)
|
||||||
|
model = llm_kwargs['llm_model'].strip('api2d-')
|
||||||
|
if model == "gpt-3.5-random": # 随机选择, 绕过openai访问频率限制
|
||||||
|
model = random.choice([
|
||||||
|
"gpt-3.5-turbo",
|
||||||
|
"gpt-3.5-turbo-16k",
|
||||||
|
"gpt-3.5-turbo-0613",
|
||||||
|
"gpt-3.5-turbo-16k-0613",
|
||||||
|
"gpt-3.5-turbo-0301",
|
||||||
|
])
|
||||||
|
logging.info("Random select model:" + model)
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
"model": llm_kwargs['llm_model'].strip('api2d-'),
|
"model": model,
|
||||||
"messages": messages,
|
"messages": messages,
|
||||||
"temperature": llm_kwargs['temperature'], # 1.0,
|
"temperature": llm_kwargs['temperature'], # 1.0,
|
||||||
"top_p": llm_kwargs['top_p'], # 1.0,
|
"top_p": llm_kwargs['top_p'], # 1.0,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class GetONNXGLMHandle(LocalLLMHandle):
|
|||||||
with open(os.path.expanduser('~/.cache/huggingface/token'), 'w') as f:
|
with open(os.path.expanduser('~/.cache/huggingface/token'), 'w') as f:
|
||||||
f.write(huggingface_token)
|
f.write(huggingface_token)
|
||||||
model_id = 'meta-llama/Llama-2-7b-chat-hf'
|
model_id = 'meta-llama/Llama-2-7b-chat-hf'
|
||||||
with ProxyNetworkActivate():
|
with ProxyNetworkActivate('Download_LLM'):
|
||||||
self._tokenizer = AutoTokenizer.from_pretrained(model_id, use_auth_token=huggingface_token)
|
self._tokenizer = AutoTokenizer.from_pretrained(model_id, use_auth_token=huggingface_token)
|
||||||
# use fp16
|
# use fp16
|
||||||
model = AutoModelForCausalLM.from_pretrained(model_id, use_auth_token=huggingface_token).eval()
|
model = AutoModelForCausalLM.from_pretrained(model_id, use_auth_token=huggingface_token).eval()
|
||||||
|
|||||||
@@ -2,11 +2,17 @@
|
|||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
import importlib
|
import importlib
|
||||||
from toolbox import update_ui, get_conf
|
from toolbox import update_ui, get_conf, update_ui_lastest_msg
|
||||||
from multiprocessing import Process, Pipe
|
from multiprocessing import Process, Pipe
|
||||||
|
|
||||||
model_name = '星火认知大模型'
|
model_name = '星火认知大模型'
|
||||||
|
|
||||||
|
def validate_key():
|
||||||
|
XFYUN_APPID, = get_conf('XFYUN_APPID', )
|
||||||
|
if XFYUN_APPID == '00000000' or XFYUN_APPID == '':
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||||
"""
|
"""
|
||||||
⭐多线程方法
|
⭐多线程方法
|
||||||
@@ -15,6 +21,9 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
|
|||||||
watch_dog_patience = 5
|
watch_dog_patience = 5
|
||||||
response = ""
|
response = ""
|
||||||
|
|
||||||
|
if validate_key() is False:
|
||||||
|
raise RuntimeError('请配置讯飞星火大模型的XFYUN_APPID, XFYUN_API_KEY, XFYUN_API_SECRET')
|
||||||
|
|
||||||
from .com_sparkapi import SparkRequestInstance
|
from .com_sparkapi import SparkRequestInstance
|
||||||
sri = SparkRequestInstance()
|
sri = SparkRequestInstance()
|
||||||
for response in sri.generate(inputs, llm_kwargs, history, sys_prompt):
|
for response in sri.generate(inputs, llm_kwargs, history, sys_prompt):
|
||||||
@@ -32,6 +41,10 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
|
|||||||
chatbot.append((inputs, ""))
|
chatbot.append((inputs, ""))
|
||||||
yield from update_ui(chatbot=chatbot, history=history)
|
yield from update_ui(chatbot=chatbot, history=history)
|
||||||
|
|
||||||
|
if validate_key() is False:
|
||||||
|
yield from update_ui_lastest_msg(lastmsg="[Local Message]: 请配置讯飞星火大模型的XFYUN_APPID, XFYUN_API_KEY, XFYUN_API_SECRET", chatbot=chatbot, history=history, delay=0)
|
||||||
|
return
|
||||||
|
|
||||||
if additional_fn is not None:
|
if additional_fn is not None:
|
||||||
from core_functional import handle_core_functionality
|
from core_functional import handle_core_functionality
|
||||||
inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot)
|
inputs, history = handle_core_functionality(additional_fn, inputs, history, chatbot)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class Ws_Param(object):
|
|||||||
class SparkRequestInstance():
|
class SparkRequestInstance():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
XFYUN_APPID, XFYUN_API_SECRET, XFYUN_API_KEY = get_conf('XFYUN_APPID', 'XFYUN_API_SECRET', 'XFYUN_API_KEY')
|
XFYUN_APPID, XFYUN_API_SECRET, XFYUN_API_KEY = get_conf('XFYUN_APPID', 'XFYUN_API_SECRET', 'XFYUN_API_KEY')
|
||||||
|
if XFYUN_APPID == '00000000' or XFYUN_APPID == '': raise RuntimeError('请配置讯飞星火大模型的XFYUN_APPID, XFYUN_API_KEY, XFYUN_API_SECRET')
|
||||||
self.appid = XFYUN_APPID
|
self.appid = XFYUN_APPID
|
||||||
self.api_secret = XFYUN_API_SECRET
|
self.api_secret = XFYUN_API_SECRET
|
||||||
self.api_key = XFYUN_API_KEY
|
self.api_key = XFYUN_API_KEY
|
||||||
@@ -109,6 +109,7 @@ class SparkRequestInstance():
|
|||||||
code = data['header']['code']
|
code = data['header']['code']
|
||||||
if code != 0:
|
if code != 0:
|
||||||
print(f'请求错误: {code}, {data}')
|
print(f'请求错误: {code}, {data}')
|
||||||
|
self.result_buf += str(data)
|
||||||
ws.close()
|
ws.close()
|
||||||
self.time_to_exit_event.set()
|
self.time_to_exit_event.set()
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
protobuf
|
protobuf
|
||||||
transformers>=4.27.1
|
|
||||||
cpm_kernels
|
cpm_kernels
|
||||||
torch>=1.10
|
torch>=1.10
|
||||||
mdtex2html
|
mdtex2html
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
protobuf
|
protobuf
|
||||||
transformers>=4.27.1
|
|
||||||
cpm_kernels
|
cpm_kernels
|
||||||
torch>=1.10
|
torch>=1.10
|
||||||
mdtex2html
|
mdtex2html
|
||||||
|
|||||||
@@ -2,6 +2,5 @@ jittor >= 1.3.7.9
|
|||||||
jtorch >= 0.1.3
|
jtorch >= 0.1.3
|
||||||
torch
|
torch
|
||||||
torchvision
|
torchvision
|
||||||
transformers==4.26.1
|
|
||||||
pandas
|
pandas
|
||||||
jieba
|
jieba
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
torch
|
torch
|
||||||
transformers==4.25.1
|
|
||||||
sentencepiece
|
sentencepiece
|
||||||
datasets
|
datasets
|
||||||
accelerate
|
accelerate
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
./docs/gradio-3.32.2-py3-none-any.whl
|
./docs/gradio-3.32.6-py3-none-any.whl
|
||||||
pydantic==1.10.11
|
pydantic==1.10.11
|
||||||
tiktoken>=0.3.3
|
tiktoken>=0.3.3
|
||||||
requests[socks]
|
requests[socks]
|
||||||
transformers
|
transformers>=4.27.1
|
||||||
python-markdown-math
|
python-markdown-math
|
||||||
beautifulsoup4
|
beautifulsoup4
|
||||||
prompt_toolkit
|
prompt_toolkit
|
||||||
@@ -20,4 +20,4 @@ arxiv
|
|||||||
rich
|
rich
|
||||||
pypdf2==2.12.1
|
pypdf2==2.12.1
|
||||||
websocket-client
|
websocket-client
|
||||||
scipdf_parser==0.3
|
scipdf_parser>=0.3
|
||||||
|
|||||||
@@ -6,12 +6,18 @@
|
|||||||
import os, sys
|
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)
|
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() # 返回项目根路径
|
validate_path() # 返回项目根路径
|
||||||
from tests.test_utils import plugin_test
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
from tests.test_utils import plugin_test
|
||||||
|
# plugin_test(plugin='crazy_functions.函数动态生成->函数动态生成', main_input='交换图像的蓝色通道和红色通道', advanced_arg={"file_path_arg": "./build/ants.jpg"})
|
||||||
|
|
||||||
|
plugin_test(plugin='crazy_functions.Latex输出PDF结果->Latex翻译中文并重新编译PDF', main_input="2307.07522")
|
||||||
|
|
||||||
# plugin_test(plugin='crazy_functions.虚空终端->虚空终端', main_input='修改api-key为sk-jhoejriotherjep')
|
# plugin_test(plugin='crazy_functions.虚空终端->虚空终端', main_input='修改api-key为sk-jhoejriotherjep')
|
||||||
|
|
||||||
plugin_test(plugin='crazy_functions.虚空终端->虚空终端', main_input='调用插件,对C:/Users/fuqingxu/Desktop/旧文件/gpt/chatgpt_academic/crazy_functions/latex_fns中的python文件进行解析')
|
# plugin_test(plugin='crazy_functions.批量翻译PDF文档_NOUGAT->批量翻译PDF文档', main_input='crazy_functions/test_project/pdf_and_word/aaai.pdf')
|
||||||
|
|
||||||
|
# plugin_test(plugin='crazy_functions.虚空终端->虚空终端', main_input='调用插件,对C:/Users/fuqingxu/Desktop/旧文件/gpt/chatgpt_academic/crazy_functions/latex_fns中的python文件进行解析')
|
||||||
|
|
||||||
# plugin_test(plugin='crazy_functions.命令行助手->命令行助手', main_input='查看当前的docker容器列表')
|
# plugin_test(plugin='crazy_functions.命令行助手->命令行助手', main_input='查看当前的docker容器列表')
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ def plugin_test(main_input, plugin, advanced_arg=None):
|
|||||||
plugin_kwargs['plugin_kwargs'] = advanced_arg
|
plugin_kwargs['plugin_kwargs'] = advanced_arg
|
||||||
my_working_plugin = silence_stdout(plugin)(**plugin_kwargs)
|
my_working_plugin = silence_stdout(plugin)(**plugin_kwargs)
|
||||||
|
|
||||||
with Live(Markdown(""), auto_refresh=False) as live:
|
with Live(Markdown(""), auto_refresh=False, vertical_overflow="visible") as live:
|
||||||
for cookies, chat, hist, msg in my_working_plugin:
|
for cookies, chat, hist, msg in my_working_plugin:
|
||||||
md_str = vt.chat_to_markdown_str(chat)
|
md_str = vt.chat_to_markdown_str(chat)
|
||||||
md = Markdown(md_str)
|
md = Markdown(md_str)
|
||||||
|
|||||||
@@ -9,6 +9,11 @@
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#input-plugin-group .secondary-wrap.svelte-aqlk7e.svelte-aqlk7e.svelte-aqlk7e {
|
||||||
|
border: none;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* hide selector label */
|
/* hide selector label */
|
||||||
#input-plugin-group .svelte-1gfkn6j {
|
#input-plugin-group .svelte-1gfkn6j {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
@@ -19,3 +24,91 @@
|
|||||||
.wrap.svelte-xwlu1w {
|
.wrap.svelte-xwlu1w {
|
||||||
min-height: var(--size-32);
|
min-height: var(--size-32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* status bar height */
|
||||||
|
.min.svelte-1yrv54 {
|
||||||
|
min-height: var(--size-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy btn */
|
||||||
|
.message-btn-row {
|
||||||
|
width: 19px;
|
||||||
|
height: 19px;
|
||||||
|
position: absolute;
|
||||||
|
left: calc(100% + 3px);
|
||||||
|
top: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
/* .message-btn-row-leading, .message-btn-row-trailing {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 4px;
|
||||||
|
} */
|
||||||
|
.message-btn-row button {
|
||||||
|
font-size: 18px;
|
||||||
|
align-self: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 4px;
|
||||||
|
padding-block: 2px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Scrollbar Width */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scrollbar Track */
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: #f1f1f1;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scrollbar Handle */
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #888;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scrollbar Handle on hover */
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* input btns: clear, reset, stop */
|
||||||
|
#input-panel button {
|
||||||
|
min-width: min(80px, 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* input btns: clear, reset, stop */
|
||||||
|
#input-panel2 button {
|
||||||
|
min-width: min(80px, 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#cbs {
|
||||||
|
background-color: var(--block-background-fill) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#interact-panel .form {
|
||||||
|
border: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.drag-area {
|
||||||
|
border: solid;
|
||||||
|
border-width: thin;
|
||||||
|
user-select: none;
|
||||||
|
padding-left: 2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-component #input-panel2 {
|
||||||
|
border-top-left-radius: 0px;
|
||||||
|
border-top-right-radius: 0px;
|
||||||
|
border: solid;
|
||||||
|
border-width: thin;
|
||||||
|
border-top-width: 0;
|
||||||
|
}
|
||||||
116
themes/common.js
116
themes/common.js
@@ -1,4 +1,105 @@
|
|||||||
function ChatBotHeight() {
|
function gradioApp() {
|
||||||
|
// https://github.com/GaiZhenbiao/ChuanhuChatGPT/tree/main/web_assets/javascript
|
||||||
|
const elems = document.getElementsByTagName('gradio-app');
|
||||||
|
const elem = elems.length == 0 ? document : elems[0];
|
||||||
|
if (elem !== document) {
|
||||||
|
elem.getElementById = function(id) {
|
||||||
|
return document.getElementById(id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return elem.shadowRoot ? elem.shadowRoot : elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCookie(name, value, days) {
|
||||||
|
var expires = "";
|
||||||
|
|
||||||
|
if (days) {
|
||||||
|
var date = new Date();
|
||||||
|
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||||
|
expires = "; expires=" + date.toUTCString();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.cookie = name + "=" + value + expires + "; path=/";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCookie(name) {
|
||||||
|
var decodedCookie = decodeURIComponent(document.cookie);
|
||||||
|
var cookies = decodedCookie.split(';');
|
||||||
|
|
||||||
|
for (var i = 0; i < cookies.length; i++) {
|
||||||
|
var cookie = cookies[i].trim();
|
||||||
|
|
||||||
|
if (cookie.indexOf(name + "=") === 0) {
|
||||||
|
return cookie.substring(name.length + 1, cookie.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCopyButton(botElement) {
|
||||||
|
// https://github.com/GaiZhenbiao/ChuanhuChatGPT/tree/main/web_assets/javascript
|
||||||
|
// Copy bot button
|
||||||
|
const copiedIcon = '<span><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height=".8em" width=".8em" xmlns="http://www.w3.org/2000/svg"><polyline points="20 6 9 17 4 12"></polyline></svg></span>';
|
||||||
|
const copyIcon = '<span><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height=".8em" width=".8em" xmlns="http://www.w3.org/2000/svg"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></span>';
|
||||||
|
|
||||||
|
const messageBtnColumnElement = botElement.querySelector('.message-btn-row');
|
||||||
|
if (messageBtnColumnElement) {
|
||||||
|
// Do something if .message-btn-column exists, for example, remove it
|
||||||
|
// messageBtnColumnElement.remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var copyButton = document.createElement('button');
|
||||||
|
copyButton.classList.add('copy-bot-btn');
|
||||||
|
copyButton.setAttribute('aria-label', 'Copy');
|
||||||
|
copyButton.innerHTML = copyIcon;
|
||||||
|
copyButton.addEventListener('click', async () => {
|
||||||
|
const textToCopy = botElement.innerText;
|
||||||
|
try {
|
||||||
|
if ("clipboard" in navigator) {
|
||||||
|
await navigator.clipboard.writeText(textToCopy);
|
||||||
|
copyButton.innerHTML = copiedIcon;
|
||||||
|
setTimeout(() => {
|
||||||
|
copyButton.innerHTML = copyIcon;
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
const textArea = document.createElement("textarea");
|
||||||
|
textArea.value = textToCopy;
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.select();
|
||||||
|
try {
|
||||||
|
document.execCommand('copy');
|
||||||
|
copyButton.innerHTML = copiedIcon;
|
||||||
|
setTimeout(() => {
|
||||||
|
copyButton.innerHTML = copyIcon;
|
||||||
|
}, 1500);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Copy failed: ", error);
|
||||||
|
}
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Copy failed: ", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var messageBtnColumn = document.createElement('div');
|
||||||
|
messageBtnColumn.classList.add('message-btn-row');
|
||||||
|
messageBtnColumn.appendChild(copyButton);
|
||||||
|
botElement.appendChild(messageBtnColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
function chatbotContentChanged(attempt = 1, force = false) {
|
||||||
|
// https://github.com/GaiZhenbiao/ChuanhuChatGPT/tree/main/web_assets/javascript
|
||||||
|
for (var i = 0; i < attempt; i++) {
|
||||||
|
setTimeout(() => {
|
||||||
|
gradioApp().querySelectorAll('#gpt-chatbot .message-wrap .message.bot').forEach(addCopyButton);
|
||||||
|
}, i === 0 ? 0 : 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function chatbotAutoHeight(){
|
||||||
|
// 自动调整高度
|
||||||
function update_height(){
|
function update_height(){
|
||||||
var { panel_height_target, chatbot_height, chatbot } = get_elements(true);
|
var { panel_height_target, chatbot_height, chatbot } = get_elements(true);
|
||||||
if (panel_height_target!=chatbot_height)
|
if (panel_height_target!=chatbot_height)
|
||||||
@@ -28,6 +129,15 @@ function ChatBotHeight() {
|
|||||||
}, 50); // 每100毫秒执行一次
|
}, 50); // 每100毫秒执行一次
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function GptAcademicJavaScriptInit(LAYOUT = "LEFT-RIGHT") {
|
||||||
|
chatbotIndicator = gradioApp().querySelector('#gpt-chatbot > div.wrap');
|
||||||
|
var chatbotObserver = new MutationObserver(() => {
|
||||||
|
chatbotContentChanged(1);
|
||||||
|
});
|
||||||
|
chatbotObserver.observe(chatbotIndicator, { attributes: true, childList: true, subtree: true });
|
||||||
|
if (LAYOUT === "LEFT-RIGHT") {chatbotAutoHeight();}
|
||||||
|
}
|
||||||
|
|
||||||
function get_elements(consider_state_panel=false) {
|
function get_elements(consider_state_panel=false) {
|
||||||
var chatbot = document.querySelector('#gpt-chatbot > div.wrap.svelte-18telvq');
|
var chatbot = document.querySelector('#gpt-chatbot > div.wrap.svelte-18telvq');
|
||||||
if (!chatbot) {
|
if (!chatbot) {
|
||||||
@@ -36,14 +146,14 @@ function get_elements(consider_state_panel=false) {
|
|||||||
const panel1 = document.querySelector('#input-panel').getBoundingClientRect();
|
const panel1 = document.querySelector('#input-panel').getBoundingClientRect();
|
||||||
const panel2 = document.querySelector('#basic-panel').getBoundingClientRect()
|
const panel2 = document.querySelector('#basic-panel').getBoundingClientRect()
|
||||||
const panel3 = document.querySelector('#plugin-panel').getBoundingClientRect();
|
const panel3 = document.querySelector('#plugin-panel').getBoundingClientRect();
|
||||||
const panel4 = document.querySelector('#interact-panel').getBoundingClientRect();
|
// const panel4 = document.querySelector('#interact-panel').getBoundingClientRect();
|
||||||
const panel5 = document.querySelector('#input-panel2').getBoundingClientRect();
|
const panel5 = document.querySelector('#input-panel2').getBoundingClientRect();
|
||||||
const panel_active = document.querySelector('#state-panel').getBoundingClientRect();
|
const panel_active = document.querySelector('#state-panel').getBoundingClientRect();
|
||||||
if (consider_state_panel || panel_active.height < 25){
|
if (consider_state_panel || panel_active.height < 25){
|
||||||
document.state_panel_height = panel_active.height;
|
document.state_panel_height = panel_active.height;
|
||||||
}
|
}
|
||||||
// 25 是chatbot的label高度, 16 是右侧的gap
|
// 25 是chatbot的label高度, 16 是右侧的gap
|
||||||
var panel_height_target = panel1.height + panel2.height + panel3.height + panel4.height + panel5.height - 25 + 16*3;
|
var panel_height_target = panel1.height + panel2.height + panel3.height + 0 + 0 - 25 + 16*2;
|
||||||
// 禁止动态的state-panel高度影响
|
// 禁止动态的state-panel高度影响
|
||||||
panel_height_target = panel_height_target + (document.state_panel_height-panel_active.height)
|
panel_height_target = panel_height_target + (document.state_panel_height-panel_active.height)
|
||||||
var panel_height_target = parseInt(panel_height_target);
|
var panel_height_target = parseInt(panel_height_target);
|
||||||
|
|||||||
@@ -198,7 +198,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 小按钮 */
|
/* 小按钮 */
|
||||||
.sm.svelte-1ipelgc {
|
.sm {
|
||||||
font-family: "Microsoft YaHei UI", "Helvetica", "Microsoft YaHei", "ui-sans-serif", "sans-serif", "system-ui";
|
font-family: "Microsoft YaHei UI", "Helvetica", "Microsoft YaHei", "ui-sans-serif", "sans-serif", "system-ui";
|
||||||
--button-small-text-weight: 600;
|
--button-small-text-weight: 600;
|
||||||
--button-small-text-size: 16px;
|
--button-small-text-size: 16px;
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
border-top-left-radius: 0px;
|
border-top-left-radius: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#plugin-panel .sm.svelte-1ipelgc {
|
#plugin-panel .sm {
|
||||||
font-family: "Microsoft YaHei UI", "Helvetica", "Microsoft YaHei", "ui-sans-serif", "sans-serif", "system-ui";
|
font-family: "Microsoft YaHei UI", "Helvetica", "Microsoft YaHei", "ui-sans-serif", "sans-serif", "system-ui";
|
||||||
--button-small-text-weight: 400;
|
--button-small-text-weight: 400;
|
||||||
--button-small-text-size: 14px;
|
--button-small-text-size: 14px;
|
||||||
|
|||||||
@@ -57,12 +57,9 @@ def adjust_theme():
|
|||||||
button_cancel_text_color_dark="white",
|
button_cancel_text_color_dark="white",
|
||||||
)
|
)
|
||||||
|
|
||||||
if LAYOUT=="TOP-DOWN":
|
with open('themes/common.js', 'r', encoding='utf8') as f:
|
||||||
js = ""
|
js = f"<script>{f.read()}</script>"
|
||||||
else:
|
|
||||||
with open('themes/common.js', 'r', encoding='utf8') as f:
|
|
||||||
js = f"<script>{f.read()}</script>"
|
|
||||||
|
|
||||||
# 添加一个萌萌的看板娘
|
# 添加一个萌萌的看板娘
|
||||||
if ADD_WAIFU:
|
if ADD_WAIFU:
|
||||||
js += """
|
js += """
|
||||||
|
|||||||
@@ -9,15 +9,15 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#plugin-panel .dropdown-arrow.svelte-p5edak {
|
#plugin-panel .dropdown-arrow {
|
||||||
width: 50px;
|
width: 25px;
|
||||||
}
|
}
|
||||||
#plugin-panel input.svelte-aqlk7e.svelte-aqlk7e.svelte-aqlk7e {
|
#plugin-panel input.svelte-aqlk7e.svelte-aqlk7e.svelte-aqlk7e {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 小按钮 */
|
/* 小按钮 */
|
||||||
.sm.svelte-1ipelgc {
|
#basic-panel .sm {
|
||||||
font-family: "Microsoft YaHei UI", "Helvetica", "Microsoft YaHei", "ui-sans-serif", "sans-serif", "system-ui";
|
font-family: "Microsoft YaHei UI", "Helvetica", "Microsoft YaHei", "ui-sans-serif", "sans-serif", "system-ui";
|
||||||
--button-small-text-weight: 600;
|
--button-small-text-weight: 600;
|
||||||
--button-small-text-size: 16px;
|
--button-small-text-size: 16px;
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
border-top-left-radius: 6px;
|
border-top-left-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#plugin-panel .sm.svelte-1ipelgc {
|
#plugin-panel .sm {
|
||||||
font-family: "Microsoft YaHei UI", "Helvetica", "Microsoft YaHei", "ui-sans-serif", "sans-serif", "system-ui";
|
font-family: "Microsoft YaHei UI", "Helvetica", "Microsoft YaHei", "ui-sans-serif", "sans-serif", "system-ui";
|
||||||
--button-small-text-weight: 400;
|
--button-small-text-weight: 400;
|
||||||
--button-small-text-size: 14px;
|
--button-small-text-size: 14px;
|
||||||
|
|||||||
@@ -57,11 +57,8 @@ def adjust_theme():
|
|||||||
button_cancel_text_color_dark="white",
|
button_cancel_text_color_dark="white",
|
||||||
)
|
)
|
||||||
|
|
||||||
if LAYOUT=="TOP-DOWN":
|
with open('themes/common.js', 'r', encoding='utf8') as f:
|
||||||
js = ""
|
js = f"<script>{f.read()}</script>"
|
||||||
else:
|
|
||||||
with open('themes/common.js', 'r', encoding='utf8') as f:
|
|
||||||
js = f"<script>{f.read()}</script>"
|
|
||||||
|
|
||||||
# 添加一个萌萌的看板娘
|
# 添加一个萌萌的看板娘
|
||||||
if ADD_WAIFU:
|
if ADD_WAIFU:
|
||||||
|
|||||||
52
themes/gradios.py
普通文件
52
themes/gradios.py
普通文件
@@ -0,0 +1,52 @@
|
|||||||
|
import gradio as gr
|
||||||
|
import logging
|
||||||
|
from toolbox import get_conf, ProxyNetworkActivate
|
||||||
|
CODE_HIGHLIGHT, ADD_WAIFU, LAYOUT = get_conf('CODE_HIGHLIGHT', 'ADD_WAIFU', 'LAYOUT')
|
||||||
|
|
||||||
|
def dynamic_set_theme(THEME):
|
||||||
|
set_theme = gr.themes.ThemeClass()
|
||||||
|
with ProxyNetworkActivate('Download_Gradio_Theme'):
|
||||||
|
logging.info('正在下载Gradio主题,请稍等。')
|
||||||
|
if THEME.startswith('Huggingface-'): THEME = THEME.lstrip('Huggingface-')
|
||||||
|
if THEME.startswith('huggingface-'): THEME = THEME.lstrip('huggingface-')
|
||||||
|
set_theme = set_theme.from_hub(THEME.lower())
|
||||||
|
return set_theme
|
||||||
|
|
||||||
|
def adjust_theme():
|
||||||
|
|
||||||
|
try:
|
||||||
|
set_theme = gr.themes.ThemeClass()
|
||||||
|
with ProxyNetworkActivate('Download_Gradio_Theme'):
|
||||||
|
logging.info('正在下载Gradio主题,请稍等。')
|
||||||
|
THEME, = get_conf('THEME')
|
||||||
|
if THEME.startswith('Huggingface-'): THEME = THEME.lstrip('Huggingface-')
|
||||||
|
if THEME.startswith('huggingface-'): THEME = THEME.lstrip('huggingface-')
|
||||||
|
set_theme = set_theme.from_hub(THEME.lower())
|
||||||
|
|
||||||
|
with open('themes/common.js', 'r', encoding='utf8') as f:
|
||||||
|
js = f"<script>{f.read()}</script>"
|
||||||
|
|
||||||
|
# 添加一个萌萌的看板娘
|
||||||
|
if ADD_WAIFU:
|
||||||
|
js += """
|
||||||
|
<script src="file=docs/waifu_plugin/jquery.min.js"></script>
|
||||||
|
<script src="file=docs/waifu_plugin/jquery-ui.min.js"></script>
|
||||||
|
<script src="file=docs/waifu_plugin/autoload.js"></script>
|
||||||
|
"""
|
||||||
|
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'</html>', f'{js}</html>'.encode("utf8"))
|
||||||
|
res.init_headers()
|
||||||
|
return res
|
||||||
|
gr.routes.templates.TemplateResponse = gradio_new_template_fn # override gradio template
|
||||||
|
except Exception as e:
|
||||||
|
set_theme = None
|
||||||
|
from toolbox import trimmed_format_exc
|
||||||
|
logging.error('gradio版本较旧, 不能自定义字体和颜色:', trimmed_format_exc())
|
||||||
|
return set_theme
|
||||||
|
|
||||||
|
# with open("themes/default.css", "r", encoding="utf-8") as f:
|
||||||
|
# advanced_css = f.read()
|
||||||
|
with open("themes/common.css", "r", encoding="utf-8") as f:
|
||||||
|
advanced_css = f.read()
|
||||||
@@ -73,12 +73,8 @@ def adjust_theme():
|
|||||||
chatbot_code_background_color_dark="*neutral_950",
|
chatbot_code_background_color_dark="*neutral_950",
|
||||||
)
|
)
|
||||||
|
|
||||||
js = ''
|
with open('themes/common.js', 'r', encoding='utf8') as f:
|
||||||
if LAYOUT=="TOP-DOWN":
|
js = f"<script>{f.read()}</script>"
|
||||||
js = ""
|
|
||||||
else:
|
|
||||||
with open('themes/common.js', 'r', encoding='utf8') as f:
|
|
||||||
js = f"<script>{f.read()}</script>"
|
|
||||||
|
|
||||||
# 添加一个萌萌的看板娘
|
# 添加一个萌萌的看板娘
|
||||||
if ADD_WAIFU:
|
if ADD_WAIFU:
|
||||||
|
|||||||
@@ -2,14 +2,22 @@ import gradio as gr
|
|||||||
from toolbox import get_conf
|
from toolbox import get_conf
|
||||||
THEME, = get_conf('THEME')
|
THEME, = get_conf('THEME')
|
||||||
|
|
||||||
if THEME == 'Chuanhu-Small-and-Beautiful':
|
def load_dynamic_theme(THEME):
|
||||||
from .green import adjust_theme, advanced_css
|
adjust_dynamic_theme = None
|
||||||
theme_declaration = "<h2 align=\"center\" class=\"small\">[Chuanhu-Small-and-Beautiful主题]</h2>"
|
if THEME == 'Chuanhu-Small-and-Beautiful':
|
||||||
elif THEME == 'High-Contrast':
|
from .green import adjust_theme, advanced_css
|
||||||
from .contrast import adjust_theme, advanced_css
|
theme_declaration = "<h2 align=\"center\" class=\"small\">[Chuanhu-Small-and-Beautiful主题]</h2>"
|
||||||
theme_declaration = ""
|
elif THEME == 'High-Contrast':
|
||||||
else:
|
from .contrast import adjust_theme, advanced_css
|
||||||
from .default import adjust_theme, advanced_css
|
theme_declaration = ""
|
||||||
theme_declaration = ""
|
elif '/' in THEME:
|
||||||
|
from .gradios import adjust_theme, advanced_css
|
||||||
|
from .gradios import dynamic_set_theme
|
||||||
|
adjust_dynamic_theme = dynamic_set_theme(THEME)
|
||||||
|
theme_declaration = ""
|
||||||
|
else:
|
||||||
|
from .default import adjust_theme, advanced_css
|
||||||
|
theme_declaration = ""
|
||||||
|
return adjust_theme, advanced_css, theme_declaration, adjust_dynamic_theme
|
||||||
|
|
||||||
|
adjust_theme, advanced_css, theme_declaration, _ = load_dynamic_theme(THEME)
|
||||||
230
toolbox.py
230
toolbox.py
@@ -5,6 +5,8 @@ import inspect
|
|||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import gradio
|
import gradio
|
||||||
|
import shutil
|
||||||
|
import glob
|
||||||
from latex2mathml.converter import convert as tex2mathml
|
from latex2mathml.converter import convert as tex2mathml
|
||||||
from functools import wraps, lru_cache
|
from functools import wraps, lru_cache
|
||||||
pj = os.path.join
|
pj = os.path.join
|
||||||
@@ -77,14 +79,24 @@ def ArgsGeneralWrapper(f):
|
|||||||
}
|
}
|
||||||
chatbot_with_cookie = ChatBotWithCookies(cookies)
|
chatbot_with_cookie = ChatBotWithCookies(cookies)
|
||||||
chatbot_with_cookie.write_list(chatbot)
|
chatbot_with_cookie.write_list(chatbot)
|
||||||
|
|
||||||
if cookies.get('lock_plugin', None) is None:
|
if cookies.get('lock_plugin', None) is None:
|
||||||
# 正常状态
|
# 正常状态
|
||||||
yield from f(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, *args)
|
if len(args) == 0: # 插件通道
|
||||||
|
yield from f(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, request)
|
||||||
|
else: # 对话通道,或者基础功能通道
|
||||||
|
yield from f(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, *args)
|
||||||
else:
|
else:
|
||||||
# 处理个别特殊插件的锁定状态
|
# 处理少数情况下的特殊插件的锁定状态
|
||||||
module, fn_name = cookies['lock_plugin'].split('->')
|
module, fn_name = cookies['lock_plugin'].split('->')
|
||||||
f_hot_reload = getattr(importlib.import_module(module, fn_name), fn_name)
|
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, request)
|
yield from f_hot_reload(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, request)
|
||||||
|
# 判断一下用户是否错误地通过对话通道进入,如果是,则进行提醒
|
||||||
|
final_cookies = chatbot_with_cookie.get_cookies()
|
||||||
|
# len(args) != 0 代表“提交”键对话通道,或者基础功能通道
|
||||||
|
if len(args) != 0 and 'files_to_promote' in final_cookies and len(final_cookies['files_to_promote']) > 0:
|
||||||
|
chatbot_with_cookie.append(["检测到**滞留的缓存文档**,请及时处理。", "请及时点击“**保存当前对话**”获取所有滞留文档。"])
|
||||||
|
yield from update_ui(chatbot_with_cookie, final_cookies['history'], msg="检测到被滞留的缓存文档")
|
||||||
return decorated
|
return decorated
|
||||||
|
|
||||||
|
|
||||||
@@ -94,7 +106,8 @@ def update_ui(chatbot, history, msg='正常', **kwargs): # 刷新界面
|
|||||||
"""
|
"""
|
||||||
assert isinstance(chatbot, ChatBotWithCookies), "在传递chatbot的过程中不要将其丢弃。必要时, 可用clear将其清空, 然后用for+append循环重新赋值。"
|
assert isinstance(chatbot, ChatBotWithCookies), "在传递chatbot的过程中不要将其丢弃。必要时, 可用clear将其清空, 然后用for+append循环重新赋值。"
|
||||||
cookies = chatbot.get_cookies()
|
cookies = chatbot.get_cookies()
|
||||||
|
# 备份一份History作为记录
|
||||||
|
cookies.update({'history': history})
|
||||||
# 解决插件锁定时的界面显示问题
|
# 解决插件锁定时的界面显示问题
|
||||||
if cookies.get('lock_plugin', None):
|
if cookies.get('lock_plugin', None):
|
||||||
label = cookies.get('llm_model', "") + " | " + "正在锁定插件" + cookies.get('lock_plugin', None)
|
label = cookies.get('llm_model', "") + " | " + "正在锁定插件" + cookies.get('lock_plugin', None)
|
||||||
@@ -171,7 +184,7 @@ def HotReload(f):
|
|||||||
========================================================================
|
========================================================================
|
||||||
第二部分
|
第二部分
|
||||||
其他小工具:
|
其他小工具:
|
||||||
- write_results_to_file: 将结果写入markdown文件中
|
- write_history_to_file: 将结果写入markdown文件中
|
||||||
- regular_txt_to_markdown: 将普通文本转换为Markdown格式的文本。
|
- regular_txt_to_markdown: 将普通文本转换为Markdown格式的文本。
|
||||||
- report_execption: 向chatbot中添加简单的意外错误信息
|
- report_execption: 向chatbot中添加简单的意外错误信息
|
||||||
- text_divide_paragraph: 将文本按照段落分隔符分割开,生成带有段落标签的HTML代码。
|
- text_divide_paragraph: 将文本按照段落分隔符分割开,生成带有段落标签的HTML代码。
|
||||||
@@ -203,37 +216,7 @@ def get_reduce_token_percent(text):
|
|||||||
return 0.5, '不详'
|
return 0.5, '不详'
|
||||||
|
|
||||||
|
|
||||||
def write_results_to_file(history, file_name=None):
|
def write_history_to_file(history, file_basename=None, file_fullname=None, auto_caption=True):
|
||||||
"""
|
|
||||||
将对话记录history以Markdown格式写入文件中。如果没有指定文件名,则使用当前时间生成文件名。
|
|
||||||
"""
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
if file_name is None:
|
|
||||||
# file_name = time.strftime("chatGPT分析报告%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('# 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 = '以上材料已经被写入:\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格式写入文件中。如果没有指定文件名,则使用当前时间生成文件名。
|
将对话记录history以Markdown格式写入文件中。如果没有指定文件名,则使用当前时间生成文件名。
|
||||||
"""
|
"""
|
||||||
@@ -241,9 +224,9 @@ def write_history_to_file(history, file_basename=None, file_fullname=None):
|
|||||||
import time
|
import time
|
||||||
if file_fullname is None:
|
if file_fullname is None:
|
||||||
if file_basename is not None:
|
if file_basename is not None:
|
||||||
file_fullname = os.path.join(get_log_folder(), file_basename)
|
file_fullname = pj(get_log_folder(), file_basename)
|
||||||
else:
|
else:
|
||||||
file_fullname = os.path.join(get_log_folder(), f'GPT-Academic-{gen_time_str()}.md')
|
file_fullname = pj(get_log_folder(), f'GPT-Academic-{gen_time_str()}.md')
|
||||||
os.makedirs(os.path.dirname(file_fullname), exist_ok=True)
|
os.makedirs(os.path.dirname(file_fullname), exist_ok=True)
|
||||||
with open(file_fullname, 'w', encoding='utf8') as f:
|
with open(file_fullname, 'w', encoding='utf8') as f:
|
||||||
f.write('# GPT-Academic Report\n')
|
f.write('# GPT-Academic Report\n')
|
||||||
@@ -252,7 +235,7 @@ def write_history_to_file(history, file_basename=None, file_fullname=None):
|
|||||||
if type(content) != str: content = str(content)
|
if type(content) != str: content = str(content)
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
if i % 2 == 0:
|
if i % 2 == 0 and auto_caption:
|
||||||
f.write('## ')
|
f.write('## ')
|
||||||
try:
|
try:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
@@ -281,8 +264,7 @@ def report_execption(chatbot, history, a, b):
|
|||||||
向chatbot中添加错误信息
|
向chatbot中添加错误信息
|
||||||
"""
|
"""
|
||||||
chatbot.append((a, b))
|
chatbot.append((a, b))
|
||||||
history.append(a)
|
history.extend([a, b])
|
||||||
history.append(b)
|
|
||||||
|
|
||||||
|
|
||||||
def text_divide_paragraph(text):
|
def text_divide_paragraph(text):
|
||||||
@@ -305,6 +287,7 @@ def text_divide_paragraph(text):
|
|||||||
text = "</br>".join(lines)
|
text = "</br>".join(lines)
|
||||||
return pre + text + suf
|
return pre + text + suf
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=128) # 使用 lru缓存 加快转换速度
|
@lru_cache(maxsize=128) # 使用 lru缓存 加快转换速度
|
||||||
def markdown_convertion(txt):
|
def markdown_convertion(txt):
|
||||||
"""
|
"""
|
||||||
@@ -359,19 +342,41 @@ def markdown_convertion(txt):
|
|||||||
content = content.replace('</script>\n</script>', '</script>')
|
content = content.replace('</script>\n</script>', '</script>')
|
||||||
return content
|
return content
|
||||||
|
|
||||||
def no_code(txt):
|
def is_equation(txt):
|
||||||
if '```' not in txt:
|
"""
|
||||||
return True
|
判定是否为公式 | 测试1 写出洛伦兹定律,使用tex格式公式 测试2 给出柯西不等式,使用latex格式 测试3 写出麦克斯韦方程组
|
||||||
else:
|
"""
|
||||||
if '```reference' in txt: return True # newbing
|
if '```' in txt and '```reference' not in txt: return False
|
||||||
else: return False
|
if '$' not in txt and '\\[' not in txt: return False
|
||||||
|
mathpatterns = {
|
||||||
|
r'(?<!\\|\$)(\$)([^\$]+)(\$)': {'allow_multi_lines': False}, # $...$
|
||||||
|
r'(?<!\\)(\$\$)([^\$]+)(\$\$)': {'allow_multi_lines': True}, # $$...$$
|
||||||
|
r'(?<!\\)(\\\[)(.+?)(\\\])': {'allow_multi_lines': False}, # \[...\]
|
||||||
|
# r'(?<!\\)(\\\()(.+?)(\\\))': {'allow_multi_lines': False}, # \(...\)
|
||||||
|
# r'(?<!\\)(\\begin{([a-z]+?\*?)})(.+?)(\\end{\2})': {'allow_multi_lines': True}, # \begin...\end
|
||||||
|
# r'(?<!\\)(\$`)([^`]+)(`\$)': {'allow_multi_lines': False}, # $`...`$
|
||||||
|
}
|
||||||
|
matches = []
|
||||||
|
for pattern, property in mathpatterns.items():
|
||||||
|
flags = re.ASCII|re.DOTALL if property['allow_multi_lines'] else re.ASCII
|
||||||
|
matches.extend(re.findall(pattern, txt, flags))
|
||||||
|
if len(matches) == 0: return False
|
||||||
|
contain_any_eq = False
|
||||||
|
illegal_pattern = re.compile(r'[^\x00-\x7F]|echo')
|
||||||
|
for match in matches:
|
||||||
|
if len(match) != 3: return False
|
||||||
|
eq_canidate = match[1]
|
||||||
|
if illegal_pattern.search(eq_canidate):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
contain_any_eq = True
|
||||||
|
return contain_any_eq
|
||||||
|
|
||||||
if ('$' in txt) and no_code(txt): # 有$标识的公式符号,且没有代码段```的标识
|
if is_equation(txt): # 有$标识的公式符号,且没有代码段```的标识
|
||||||
# convert everything to html format
|
# convert everything to html format
|
||||||
split = markdown.markdown(text='---')
|
split = markdown.markdown(text='---')
|
||||||
convert_stage_1 = markdown.markdown(text=txt, extensions=['mdx_math', 'fenced_code', 'tables', 'sane_lists'], extension_configs=markdown_extension_configs)
|
convert_stage_1 = markdown.markdown(text=txt, extensions=['sane_lists', 'tables', 'mdx_math', 'fenced_code'], extension_configs=markdown_extension_configs)
|
||||||
convert_stage_1 = markdown_bug_hunt(convert_stage_1)
|
convert_stage_1 = markdown_bug_hunt(convert_stage_1)
|
||||||
# re.DOTALL: Make the '.' special character match any character at all, including a newline; without this flag, '.' will match anything except a newline. Corresponds to the inline flag (?s).
|
|
||||||
# 1. convert to easy-to-copy tex (do not render math)
|
# 1. convert to easy-to-copy tex (do not render math)
|
||||||
convert_stage_2_1, n = re.subn(find_equation_pattern, replace_math_no_render, convert_stage_1, flags=re.DOTALL)
|
convert_stage_2_1, n = re.subn(find_equation_pattern, replace_math_no_render, convert_stage_1, flags=re.DOTALL)
|
||||||
# 2. convert to rendered equation
|
# 2. convert to rendered equation
|
||||||
@@ -379,7 +384,7 @@ def markdown_convertion(txt):
|
|||||||
# cat them together
|
# cat them together
|
||||||
return pre + convert_stage_2_1 + f'{split}' + convert_stage_2_2 + suf
|
return pre + convert_stage_2_1 + f'{split}' + convert_stage_2_2 + suf
|
||||||
else:
|
else:
|
||||||
return pre + markdown.markdown(txt, extensions=['fenced_code', 'codehilite', 'tables', 'sane_lists']) + suf
|
return pre + markdown.markdown(txt, extensions=['sane_lists', 'tables', 'fenced_code', 'codehilite']) + suf
|
||||||
|
|
||||||
|
|
||||||
def close_up_code_segment_during_stream(gpt_reply):
|
def close_up_code_segment_during_stream(gpt_reply):
|
||||||
@@ -467,7 +472,7 @@ def extract_archive(file_path, dest_dir):
|
|||||||
print("Successfully extracted rar archive to {}".format(dest_dir))
|
print("Successfully extracted rar archive to {}".format(dest_dir))
|
||||||
except:
|
except:
|
||||||
print("Rar format requires additional dependencies to install")
|
print("Rar format requires additional dependencies to install")
|
||||||
return '\n\n解压失败! 需要安装pip install rarfile来解压rar文件'
|
return '\n\n解压失败! 需要安装pip install rarfile来解压rar文件。建议:使用zip压缩格式。'
|
||||||
|
|
||||||
# 第三方库,需要预先pip install py7zr
|
# 第三方库,需要预先pip install py7zr
|
||||||
elif file_extension == '.7z':
|
elif file_extension == '.7z':
|
||||||
@@ -497,7 +502,7 @@ def find_recent_files(directory):
|
|||||||
if not os.path.exists(directory):
|
if not os.path.exists(directory):
|
||||||
os.makedirs(directory, exist_ok=True)
|
os.makedirs(directory, exist_ok=True)
|
||||||
for filename in os.listdir(directory):
|
for filename in os.listdir(directory):
|
||||||
file_path = os.path.join(directory, filename)
|
file_path = pj(directory, filename)
|
||||||
if file_path.endswith('.log'):
|
if file_path.endswith('.log'):
|
||||||
continue
|
continue
|
||||||
created_time = os.path.getmtime(file_path)
|
created_time = os.path.getmtime(file_path)
|
||||||
@@ -512,59 +517,86 @@ def promote_file_to_downloadzone(file, rename_file=None, chatbot=None):
|
|||||||
# 将文件复制一份到下载区
|
# 将文件复制一份到下载区
|
||||||
import shutil
|
import shutil
|
||||||
if rename_file is None: rename_file = f'{gen_time_str()}-{os.path.basename(file)}'
|
if rename_file is None: rename_file = f'{gen_time_str()}-{os.path.basename(file)}'
|
||||||
new_path = os.path.join(get_log_folder(), rename_file)
|
new_path = pj(get_log_folder(), rename_file)
|
||||||
# 如果已经存在,先删除
|
# 如果已经存在,先删除
|
||||||
if os.path.exists(new_path) and not os.path.samefile(new_path, file): os.remove(new_path)
|
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)
|
if not os.path.exists(new_path): shutil.copyfile(file, new_path)
|
||||||
# 将文件添加到chatbot cookie中,避免多用户干扰
|
# 将文件添加到chatbot cookie中,避免多用户干扰
|
||||||
if chatbot:
|
if chatbot is not None:
|
||||||
if 'files_to_promote' in chatbot._cookies: current = chatbot._cookies['files_to_promote']
|
if 'files_to_promote' in chatbot._cookies: current = chatbot._cookies['files_to_promote']
|
||||||
else: current = []
|
else: current = []
|
||||||
chatbot._cookies.update({'files_to_promote': [new_path] + current})
|
chatbot._cookies.update({'files_to_promote': [new_path] + current})
|
||||||
|
return new_path
|
||||||
|
|
||||||
def disable_auto_promotion(chatbot):
|
def disable_auto_promotion(chatbot):
|
||||||
chatbot._cookies.update({'files_to_promote': []})
|
chatbot._cookies.update({'files_to_promote': []})
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_file_uploaded(files, chatbot, txt, txt2, checkboxes, cookies):
|
def is_the_upload_folder(string):
|
||||||
|
PATH_PRIVATE_UPLOAD, = get_conf('PATH_PRIVATE_UPLOAD')
|
||||||
|
pattern = r'^PATH_PRIVATE_UPLOAD/[A-Za-z0-9_-]+/\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}$'
|
||||||
|
pattern = pattern.replace('PATH_PRIVATE_UPLOAD', PATH_PRIVATE_UPLOAD)
|
||||||
|
if re.match(pattern, string): return True
|
||||||
|
else: return False
|
||||||
|
|
||||||
|
def del_outdated_uploads(outdate_time_seconds):
|
||||||
|
PATH_PRIVATE_UPLOAD, = get_conf('PATH_PRIVATE_UPLOAD')
|
||||||
|
current_time = time.time()
|
||||||
|
one_hour_ago = current_time - outdate_time_seconds
|
||||||
|
# Get a list of all subdirectories in the PATH_PRIVATE_UPLOAD folder
|
||||||
|
# Remove subdirectories that are older than one hour
|
||||||
|
for subdirectory in glob.glob(f'{PATH_PRIVATE_UPLOAD}/*/*'):
|
||||||
|
subdirectory_time = os.path.getmtime(subdirectory)
|
||||||
|
if subdirectory_time < one_hour_ago:
|
||||||
|
try: shutil.rmtree(subdirectory)
|
||||||
|
except: pass
|
||||||
|
return
|
||||||
|
|
||||||
|
def on_file_uploaded(request: gradio.Request, files, chatbot, txt, txt2, checkboxes, cookies):
|
||||||
"""
|
"""
|
||||||
当文件被上传时的回调函数
|
当文件被上传时的回调函数
|
||||||
"""
|
"""
|
||||||
if len(files) == 0:
|
if len(files) == 0:
|
||||||
return chatbot, txt
|
return chatbot, txt
|
||||||
import shutil
|
|
||||||
import os
|
# 移除过时的旧文件从而节省空间&保护隐私
|
||||||
import time
|
outdate_time_seconds = 60
|
||||||
import glob
|
del_outdated_uploads(outdate_time_seconds)
|
||||||
from toolbox import extract_archive
|
|
||||||
try:
|
# 创建工作路径
|
||||||
shutil.rmtree('./private_upload/')
|
user_name = "default" if not request.username else request.username
|
||||||
except:
|
|
||||||
pass
|
|
||||||
time_tag = gen_time_str()
|
time_tag = gen_time_str()
|
||||||
os.makedirs(f'private_upload/{time_tag}', exist_ok=True)
|
PATH_PRIVATE_UPLOAD, = get_conf('PATH_PRIVATE_UPLOAD')
|
||||||
err_msg = ''
|
target_path_base = pj(PATH_PRIVATE_UPLOAD, user_name, time_tag)
|
||||||
|
os.makedirs(target_path_base, exist_ok=True)
|
||||||
|
|
||||||
|
# 逐个文件转移到目标路径
|
||||||
|
upload_msg = ''
|
||||||
for file in files:
|
for file in files:
|
||||||
file_origin_name = os.path.basename(file.orig_name)
|
file_origin_name = os.path.basename(file.orig_name)
|
||||||
shutil.copy(file.name, f'private_upload/{time_tag}/{file_origin_name}')
|
this_file_path = pj(target_path_base, file_origin_name)
|
||||||
err_msg += extract_archive(f'private_upload/{time_tag}/{file_origin_name}',
|
shutil.move(file.name, this_file_path)
|
||||||
dest_dir=f'private_upload/{time_tag}/{file_origin_name}.extract')
|
upload_msg += extract_archive(file_path=this_file_path, dest_dir=this_file_path+'.extract')
|
||||||
moved_files = [fp for fp in glob.glob('private_upload/**/*', recursive=True)]
|
|
||||||
if "底部输入区" in checkboxes:
|
# 整理文件集合
|
||||||
txt = ""
|
moved_files = [fp for fp in glob.glob(f'{target_path_base}/**/*', recursive=True)]
|
||||||
txt2 = f'private_upload/{time_tag}'
|
if "浮动输入区" in checkboxes:
|
||||||
|
txt, txt2 = "", target_path_base
|
||||||
else:
|
else:
|
||||||
txt = f'private_upload/{time_tag}'
|
txt, txt2 = target_path_base, ""
|
||||||
txt2 = ""
|
|
||||||
|
# 输出消息
|
||||||
moved_files_str = '\t\n\n'.join(moved_files)
|
moved_files_str = '\t\n\n'.join(moved_files)
|
||||||
chatbot.append(['我上传了文件,请查收',
|
chatbot.append(['我上传了文件,请查收',
|
||||||
f'[Local Message] 收到以下文件: \n\n{moved_files_str}' +
|
f'[Local Message] 收到以下文件: \n\n{moved_files_str}' +
|
||||||
f'\n\n调用路径参数已自动修正到: \n\n{txt}' +
|
f'\n\n调用路径参数已自动修正到: \n\n{txt}' +
|
||||||
f'\n\n现在您点击任意“红颜色”标识的函数插件时,以上文件将被作为输入参数'+err_msg])
|
f'\n\n现在您点击任意函数插件时,以上文件将被作为输入参数'+upload_msg])
|
||||||
|
|
||||||
|
# 记录近期文件
|
||||||
cookies.update({
|
cookies.update({
|
||||||
'most_recent_uploaded': {
|
'most_recent_uploaded': {
|
||||||
'path': f'private_upload/{time_tag}',
|
'path': target_path_base,
|
||||||
'time': time.time(),
|
'time': time.time(),
|
||||||
'time_str': time_tag
|
'time_str': time_tag
|
||||||
}})
|
}})
|
||||||
@@ -573,11 +605,12 @@ def on_file_uploaded(files, chatbot, txt, txt2, checkboxes, cookies):
|
|||||||
|
|
||||||
def on_report_generated(cookies, files, chatbot):
|
def on_report_generated(cookies, files, chatbot):
|
||||||
from toolbox import find_recent_files
|
from toolbox import find_recent_files
|
||||||
|
PATH_LOGGING, = get_conf('PATH_LOGGING')
|
||||||
if 'files_to_promote' in cookies:
|
if 'files_to_promote' in cookies:
|
||||||
report_files = cookies['files_to_promote']
|
report_files = cookies['files_to_promote']
|
||||||
cookies.pop('files_to_promote')
|
cookies.pop('files_to_promote')
|
||||||
else:
|
else:
|
||||||
report_files = find_recent_files('gpt_log')
|
report_files = find_recent_files(PATH_LOGGING)
|
||||||
if len(report_files) == 0:
|
if len(report_files) == 0:
|
||||||
return cookies, None, chatbot
|
return cookies, None, chatbot
|
||||||
# files.extend(report_files)
|
# files.extend(report_files)
|
||||||
@@ -588,10 +621,20 @@ def on_report_generated(cookies, files, chatbot):
|
|||||||
|
|
||||||
def load_chat_cookies():
|
def load_chat_cookies():
|
||||||
API_KEY, LLM_MODEL, AZURE_API_KEY = get_conf('API_KEY', 'LLM_MODEL', 'AZURE_API_KEY')
|
API_KEY, LLM_MODEL, AZURE_API_KEY = get_conf('API_KEY', 'LLM_MODEL', 'AZURE_API_KEY')
|
||||||
|
DARK_MODE, NUM_CUSTOM_BASIC_BTN = get_conf('DARK_MODE', 'NUM_CUSTOM_BASIC_BTN')
|
||||||
if is_any_api_key(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
|
if is_any_api_key(API_KEY): API_KEY = API_KEY + ',' + AZURE_API_KEY
|
||||||
else: API_KEY = AZURE_API_KEY
|
else: API_KEY = AZURE_API_KEY
|
||||||
return {'api_key': API_KEY, 'llm_model': LLM_MODEL}
|
customize_fn_overwrite_ = {}
|
||||||
|
for k in range(NUM_CUSTOM_BASIC_BTN):
|
||||||
|
customize_fn_overwrite_.update({
|
||||||
|
"自定义按钮" + str(k+1):{
|
||||||
|
"Title": r"",
|
||||||
|
"Prefix": r"请在自定义菜单中定义提示词前缀.",
|
||||||
|
"Suffix": r"请在自定义菜单中定义提示词后缀",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return {'api_key': API_KEY, 'llm_model': LLM_MODEL, 'customize_fn_overwrite': customize_fn_overwrite_}
|
||||||
|
|
||||||
def is_openai_api_key(key):
|
def is_openai_api_key(key):
|
||||||
CUSTOM_API_KEY_PATTERN, = get_conf('CUSTOM_API_KEY_PATTERN')
|
CUSTOM_API_KEY_PATTERN, = get_conf('CUSTOM_API_KEY_PATTERN')
|
||||||
@@ -887,34 +930,35 @@ def zip_folder(source_folder, dest_folder, zip_name):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Create the name for the zip file
|
# Create the name for the zip file
|
||||||
zip_file = os.path.join(dest_folder, zip_name)
|
zip_file = pj(dest_folder, zip_name)
|
||||||
|
|
||||||
# Create a ZipFile object
|
# Create a ZipFile object
|
||||||
with zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
with zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
||||||
# Walk through the source folder and add files to the zip file
|
# Walk through the source folder and add files to the zip file
|
||||||
for foldername, subfolders, filenames in os.walk(source_folder):
|
for foldername, subfolders, filenames in os.walk(source_folder):
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
filepath = os.path.join(foldername, filename)
|
filepath = pj(foldername, filename)
|
||||||
zipf.write(filepath, arcname=os.path.relpath(filepath, source_folder))
|
zipf.write(filepath, arcname=os.path.relpath(filepath, source_folder))
|
||||||
|
|
||||||
# Move the zip file to the destination folder (if it wasn't already there)
|
# Move the zip file to the destination folder (if it wasn't already there)
|
||||||
if os.path.dirname(zip_file) != dest_folder:
|
if os.path.dirname(zip_file) != dest_folder:
|
||||||
os.rename(zip_file, os.path.join(dest_folder, os.path.basename(zip_file)))
|
os.rename(zip_file, pj(dest_folder, os.path.basename(zip_file)))
|
||||||
zip_file = os.path.join(dest_folder, os.path.basename(zip_file))
|
zip_file = pj(dest_folder, os.path.basename(zip_file))
|
||||||
|
|
||||||
print(f"Zip file created at {zip_file}")
|
print(f"Zip file created at {zip_file}")
|
||||||
|
|
||||||
def zip_result(folder):
|
def zip_result(folder):
|
||||||
t = gen_time_str()
|
t = gen_time_str()
|
||||||
zip_folder(folder, './gpt_log/', f'{t}-result.zip')
|
zip_folder(folder, get_log_folder(), f'{t}-result.zip')
|
||||||
return pj('./gpt_log/', f'{t}-result.zip')
|
return pj(get_log_folder(), f'{t}-result.zip')
|
||||||
|
|
||||||
def gen_time_str():
|
def gen_time_str():
|
||||||
import time
|
import time
|
||||||
return time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
return time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
|
||||||
|
|
||||||
def get_log_folder(user='default', plugin_name='shared'):
|
def get_log_folder(user='default', plugin_name='shared'):
|
||||||
_dir = os.path.join(os.path.dirname(__file__), 'gpt_log', user, plugin_name)
|
PATH_LOGGING, = get_conf('PATH_LOGGING')
|
||||||
|
_dir = pj(PATH_LOGGING, user, plugin_name)
|
||||||
if not os.path.exists(_dir): os.makedirs(_dir)
|
if not os.path.exists(_dir): os.makedirs(_dir)
|
||||||
return _dir
|
return _dir
|
||||||
|
|
||||||
@@ -922,7 +966,19 @@ class ProxyNetworkActivate():
|
|||||||
"""
|
"""
|
||||||
这段代码定义了一个名为TempProxy的空上下文管理器, 用于给一小段代码上代理
|
这段代码定义了一个名为TempProxy的空上下文管理器, 用于给一小段代码上代理
|
||||||
"""
|
"""
|
||||||
|
def __init__(self, task=None) -> None:
|
||||||
|
self.task = task
|
||||||
|
if not task:
|
||||||
|
# 不给定task, 那么我们默认代理生效
|
||||||
|
self.valid = True
|
||||||
|
else:
|
||||||
|
# 给定了task, 我们检查一下
|
||||||
|
from toolbox import get_conf
|
||||||
|
WHEN_TO_USE_PROXY, = get_conf('WHEN_TO_USE_PROXY')
|
||||||
|
self.valid = (task in WHEN_TO_USE_PROXY)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
|
if not self.valid: return self
|
||||||
from toolbox import get_conf
|
from toolbox import get_conf
|
||||||
proxies, = get_conf('proxies')
|
proxies, = get_conf('proxies')
|
||||||
if 'no_proxy' in os.environ: os.environ.pop('no_proxy')
|
if 'no_proxy' in os.environ: os.environ.pop('no_proxy')
|
||||||
|
|||||||
4
version
4
version
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": 3.50,
|
"version": 3.55,
|
||||||
"show_feature": true,
|
"show_feature": true,
|
||||||
"new_feature": "支持插件分类! <-> 支持用户使用自然语言调度各个插件(虚空终端) ! <-> 改进UI,设计新主题 <-> 支持借助GROBID实现PDF高精度翻译 <-> 接入百度千帆平台和文心一言 <-> 接入阿里通义千问、讯飞星火、上海AI-Lab书生 <-> 优化一键升级 <-> 提高arxiv翻译速度和成功率"
|
"new_feature": "重新编译Gradio优化使用体验 <-> 新增动态代码解释器(CodeInterpreter) <-> 增加文本回答复制按钮 <-> 细分代理场合 <-> 支持动态选择不同界面主题 <-> 提高稳定性&解决多用户冲突问题 <-> 支持插件分类和更多UI皮肤外观 <-> 支持用户使用自然语言调度各个插件(虚空终端) ! <-> 改进UI,设计新主题 <-> 支持借助GROBID实现PDF高精度翻译 <-> 接入百度千帆平台和文心一言 <-> 接入阿里通义千问、讯飞星火、上海AI-Lab书生 <-> 优化一键升级 <-> 提高arxiv翻译速度和成功率"
|
||||||
}
|
}
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户