Compare commits
9 Commits
version3.4
...
version3.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d364df1cd6 | ||
|
|
f51bc03686 | ||
|
|
c010d50716 | ||
|
|
7ce4192c52 | ||
|
|
c06aafb642 | ||
|
|
b298c5416c | ||
|
|
94abf302cb | ||
|
|
fcc5534e66 | ||
|
|
56c0e4d575 |
@@ -43,6 +43,7 @@ Markdown[中英互译](https://www.bilibili.com/video/BV1yo4y157jV/) | [函数
|
|||||||
chat分析报告生成 | [函数插件] 运行后自动生成总结汇报
|
chat分析报告生成 | [函数插件] 运行后自动生成总结汇报
|
||||||
[PDF论文全文翻译功能](https://www.bilibili.com/video/BV1KT411x7Wn) | [函数插件] PDF论文提取题目&摘要+翻译全文(多线程)
|
[PDF论文全文翻译功能](https://www.bilibili.com/video/BV1KT411x7Wn) | [函数插件] PDF论文提取题目&摘要+翻译全文(多线程)
|
||||||
[Arxiv小助手](https://www.bilibili.com/video/BV1LM4y1279X) | [函数插件] 输入arxiv文章url即可一键翻译摘要+下载PDF
|
[Arxiv小助手](https://www.bilibili.com/video/BV1LM4y1279X) | [函数插件] 输入arxiv文章url即可一键翻译摘要+下载PDF
|
||||||
|
Latex论文一键校对 | [函数插件] 仿Grammarly对Latex文章进行语法、拼写纠错+输出对照PDF
|
||||||
[谷歌学术统合小助手](https://www.bilibili.com/video/BV19L411U7ia) | [函数插件] 给定任意谷歌学术搜索页面URL,让gpt帮你[写relatedworks](https://www.bilibili.com/video/BV1GP411U7Az/)
|
[谷歌学术统合小助手](https://www.bilibili.com/video/BV19L411U7ia) | [函数插件] 给定任意谷歌学术搜索页面URL,让gpt帮你[写relatedworks](https://www.bilibili.com/video/BV1GP411U7Az/)
|
||||||
互联网信息聚合+GPT | [函数插件] 一键[让GPT从互联网获取信息](https://www.bilibili.com/video/BV1om4y127ck)回答问题,让信息永不过时
|
互联网信息聚合+GPT | [函数插件] 一键[让GPT从互联网获取信息](https://www.bilibili.com/video/BV1om4y127ck)回答问题,让信息永不过时
|
||||||
⭐Arxiv论文精细翻译 | [函数插件] 一键[以超高质量翻译arxiv论文](https://www.bilibili.com/video/BV1dz4y1v77A/),目前最好的论文翻译工具
|
⭐Arxiv论文精细翻译 | [函数插件] 一键[以超高质量翻译arxiv论文](https://www.bilibili.com/video/BV1dz4y1v77A/),目前最好的论文翻译工具
|
||||||
@@ -50,6 +51,7 @@ chat分析报告生成 | [函数插件] 运行后自动生成总结汇报
|
|||||||
多线程函数插件支持 | 支持多线调用chatgpt,一键处理[海量文本](https://www.bilibili.com/video/BV1FT411H7c5/)或程序
|
多线程函数插件支持 | 支持多线调用chatgpt,一键处理[海量文本](https://www.bilibili.com/video/BV1FT411H7c5/)或程序
|
||||||
启动暗色[主题](https://github.com/binary-husky/gpt_academic/issues/173) | 在浏览器url后面添加```/?__theme=dark```可以切换dark主题
|
启动暗色[主题](https://github.com/binary-husky/gpt_academic/issues/173) | 在浏览器url后面添加```/?__theme=dark```可以切换dark主题
|
||||||
[多LLM模型](https://www.bilibili.com/video/BV1wT411p7yf)支持 | 同时被GPT3.5、GPT4、[清华ChatGLM](https://github.com/THUDM/ChatGLM-6B)、[复旦MOSS](https://github.com/OpenLMLab/MOSS)同时伺候的感觉一定会很不错吧?
|
[多LLM模型](https://www.bilibili.com/video/BV1wT411p7yf)支持 | 同时被GPT3.5、GPT4、[清华ChatGLM](https://github.com/THUDM/ChatGLM-6B)、[复旦MOSS](https://github.com/OpenLMLab/MOSS)同时伺候的感觉一定会很不错吧?
|
||||||
|
ChatGLM2微调模型 | 支持加载ChatGLM2微调模型,提供ChatGLM2微调插件
|
||||||
更多LLM模型接入,支持[huggingface部署](https://huggingface.co/spaces/qingxu98/gpt-academic) | 加入Newbing接口(新必应),引入清华[Jittorllms](https://github.com/Jittor/JittorLLMs)支持[LLaMA](https://github.com/facebookresearch/llama)和[盘古α](https://openi.org.cn/pangu/)
|
更多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/)
|
||||||
更多新功能展示 (图像生成等) …… | 见本文档结尾处 ……
|
更多新功能展示 (图像生成等) …… | 见本文档结尾处 ……
|
||||||
|
|
||||||
@@ -151,9 +153,9 @@ cd gpt_academic # 进入路径
|
|||||||
nano config.py # 用任意文本编辑器编辑config.py, 配置 “Proxy”, “API_KEY” 以及 “WEB_PORT” (例如50923) 等
|
nano config.py # 用任意文本编辑器编辑config.py, 配置 “Proxy”, “API_KEY” 以及 “WEB_PORT” (例如50923) 等
|
||||||
docker build -t gpt-academic . # 安装
|
docker build -t gpt-academic . # 安装
|
||||||
|
|
||||||
#(最后一步-选择1)在Linux环境下,用`--net=host`更方便快捷
|
#(最后一步-Linux操作系统)用`--net=host`更方便快捷
|
||||||
docker run --rm -it --net=host gpt-academic
|
docker run --rm -it --net=host gpt-academic
|
||||||
#(最后一步-选择2)在macOS/windows环境下,只能用-p选项将容器上的端口(例如50923)暴露给主机上的端口
|
#(最后一步-MacOS/Windows操作系统)只能用-p选项将容器上的端口(例如50923)暴露给主机上的端口
|
||||||
docker run --rm -it -e WEB_PORT=50923 -p 50923:50923 gpt-academic
|
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。另外,您也可以直接使用docker-compose获取Latex功能(修改docker-compose.yml,保留方案4并删除其他方案)。
|
||||||
@@ -284,6 +286,8 @@ Tip:不指定文件直接点击 `载入对话历史存档` 可以查看历史h
|
|||||||
|
|
||||||
### II:版本:
|
### II:版本:
|
||||||
- version 3.5(Todo): 使用自然语言调用本项目的所有函数插件(高优先级)
|
- version 3.5(Todo): 使用自然语言调用本项目的所有函数插件(高优先级)
|
||||||
|
- version 3.45: 支持自定义ChatGLM2微调模型
|
||||||
|
- version 3.44: 正式支持Azure,优化界面易用性
|
||||||
- version 3.4: +arxiv论文翻译、latex论文批改功能
|
- version 3.4: +arxiv论文翻译、latex论文批改功能
|
||||||
- version 3.3: +互联网信息综合功能
|
- version 3.3: +互联网信息综合功能
|
||||||
- version 3.2: 函数插件支持更多参数接口 (保存对话功能, 解读任意语言代码+同时询问任意的LLM组合)
|
- version 3.2: 函数插件支持更多参数接口 (保存对话功能, 解读任意语言代码+同时询问任意的LLM组合)
|
||||||
|
|||||||
@@ -74,6 +74,10 @@ AVAIL_LLM_MODELS = ["gpt-3.5-turbo-16k", "gpt-3.5-turbo", "azure-gpt-3.5", "api2
|
|||||||
# P.S. 其他可用的模型还包括 ["gpt-3.5-turbo-0613", "gpt-3.5-turbo-16k-0613", "newbing-free", "jittorllms_rwkv", "jittorllms_pangualpha", "jittorllms_llama"]
|
# P.S. 其他可用的模型还包括 ["gpt-3.5-turbo-0613", "gpt-3.5-turbo-16k-0613", "newbing-free", "jittorllms_rwkv", "jittorllms_pangualpha", "jittorllms_llama"]
|
||||||
|
|
||||||
|
|
||||||
|
# ChatGLM(2) Finetune Model Path (如果使用ChatGLM2微调模型,需要把"chatglmft"加入AVAIL_LLM_MODELS中)
|
||||||
|
ChatGLM_PTUNING_CHECKPOINT = "" # 例如"/home/hmp/ChatGLM2-6B/ptuning/output/6b-pt-128-1e-2/checkpoint-100"
|
||||||
|
|
||||||
|
|
||||||
# 本地LLM模型如ChatGLM的执行方式 CPU/GPU
|
# 本地LLM模型如ChatGLM的执行方式 CPU/GPU
|
||||||
LOCAL_MODEL_DEVICE = "cpu" # 可选 "cuda"
|
LOCAL_MODEL_DEVICE = "cpu" # 可选 "cuda"
|
||||||
|
|
||||||
|
|||||||
@@ -365,6 +365,20 @@ def get_crazy_functions():
|
|||||||
except:
|
except:
|
||||||
print('Load function plugin failed')
|
print('Load function plugin failed')
|
||||||
|
|
||||||
|
# try:
|
||||||
|
# from crazy_functions.chatglm微调工具 import 微调数据集生成
|
||||||
|
# function_plugins.update({
|
||||||
|
# "黑盒模型学习: 微调数据集生成 (先上传数据集)": {
|
||||||
|
# "Color": "stop",
|
||||||
|
# "AsButton": False,
|
||||||
|
# "AdvancedArgs": True,
|
||||||
|
# "ArgsReminder": "针对数据集输入(如 绿帽子*深蓝色衬衫*黑色运动裤)给出指令,例如您可以将以下命令复制到下方: --llm_to_learn=azure-gpt-3.5 --prompt_prefix='根据下面的服装类型提示,想象一个穿着者,对这个人外貌、身处的环境、内心世界、过去经历进行描写。要求:100字以内,用第二人称。' --system_prompt=''",
|
||||||
|
# "Function": HotReload(微调数据集生成)
|
||||||
|
# }
|
||||||
|
# })
|
||||||
|
# except:
|
||||||
|
# print('Load function plugin failed')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from crazy_functions.Latex输出PDF结果 import Latex英文纠错加PDF对比
|
from crazy_functions.Latex输出PDF结果 import Latex英文纠错加PDF对比
|
||||||
function_plugins.update({
|
function_plugins.update({
|
||||||
|
|||||||
141
crazy_functions/chatglm微调工具.py
Normal file
141
crazy_functions/chatglm微调工具.py
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
from toolbox import CatchException, update_ui, promote_file_to_downloadzone
|
||||||
|
from .crazy_utils import request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency
|
||||||
|
import datetime, json
|
||||||
|
|
||||||
|
def fetch_items(list_of_items, batch_size):
|
||||||
|
for i in range(0, len(list_of_items), batch_size):
|
||||||
|
yield list_of_items[i:i + batch_size]
|
||||||
|
|
||||||
|
def string_to_options(arguments):
|
||||||
|
import argparse
|
||||||
|
import shlex
|
||||||
|
|
||||||
|
# Create an argparse.ArgumentParser instance
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
# Add command-line arguments
|
||||||
|
parser.add_argument("--llm_to_learn", type=str, help="LLM model to learn", default="gpt-3.5-turbo")
|
||||||
|
parser.add_argument("--prompt_prefix", type=str, help="Prompt prefix", default='')
|
||||||
|
parser.add_argument("--system_prompt", type=str, help="System prompt", default='')
|
||||||
|
parser.add_argument("--batch", type=int, help="System prompt", default=50)
|
||||||
|
parser.add_argument("--pre_seq_len", type=int, help="pre_seq_len", default=50)
|
||||||
|
parser.add_argument("--learning_rate", type=float, help="learning_rate", default=2e-2)
|
||||||
|
parser.add_argument("--num_gpus", type=int, help="num_gpus", default=1)
|
||||||
|
parser.add_argument("--json_dataset", type=str, help="json_dataset", default="")
|
||||||
|
parser.add_argument("--ptuning_directory", type=str, help="ptuning_directory", default="")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Parse the arguments
|
||||||
|
args = parser.parse_args(shlex.split(arguments))
|
||||||
|
|
||||||
|
return args
|
||||||
|
|
||||||
|
@CatchException
|
||||||
|
def 微调数据集生成(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
|
"""
|
||||||
|
txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径
|
||||||
|
llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行
|
||||||
|
plugin_kwargs 插件模型的参数
|
||||||
|
chatbot 聊天显示框的句柄,用于显示给用户
|
||||||
|
history 聊天历史,前情提要
|
||||||
|
system_prompt 给gpt的静默提醒
|
||||||
|
web_port 当前软件运行的端口号
|
||||||
|
"""
|
||||||
|
history = [] # 清空历史,以免输入溢出
|
||||||
|
chatbot.append(("这是什么功能?", "[Local Message] 微调数据集生成"))
|
||||||
|
if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg")
|
||||||
|
args = plugin_kwargs.get("advanced_arg", None)
|
||||||
|
if args is None:
|
||||||
|
chatbot.append(("没给定指令", "退出"))
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history); return
|
||||||
|
else:
|
||||||
|
arguments = string_to_options(arguments=args)
|
||||||
|
|
||||||
|
dat = []
|
||||||
|
with open(txt, 'r', encoding='utf8') as f:
|
||||||
|
for line in f.readlines():
|
||||||
|
json_dat = json.loads(line)
|
||||||
|
dat.append(json_dat["content"])
|
||||||
|
|
||||||
|
llm_kwargs['llm_model'] = arguments.llm_to_learn
|
||||||
|
for batch in fetch_items(dat, arguments.batch):
|
||||||
|
res = yield from request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency(
|
||||||
|
inputs_array=[f"{arguments.prompt_prefix}\n\n{b}" for b in (batch)],
|
||||||
|
inputs_show_user_array=[f"Show Nothing" for _ in (batch)],
|
||||||
|
llm_kwargs=llm_kwargs,
|
||||||
|
chatbot=chatbot,
|
||||||
|
history_array=[[] for _ in (batch)],
|
||||||
|
sys_prompt_array=[arguments.system_prompt for _ in (batch)],
|
||||||
|
max_workers=10 # OpenAI所允许的最大并行过载
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(txt+'.generated.json', 'a+', encoding='utf8') as f:
|
||||||
|
for b, r in zip(batch, res[1::2]):
|
||||||
|
f.write(json.dumps({"content":b, "summary":r}, ensure_ascii=False)+'\n')
|
||||||
|
|
||||||
|
promote_file_to_downloadzone(txt+'.generated.json', rename_file='generated.json', chatbot=chatbot)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@CatchException
|
||||||
|
def 启动微调(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
|
"""
|
||||||
|
txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径
|
||||||
|
llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行
|
||||||
|
plugin_kwargs 插件模型的参数
|
||||||
|
chatbot 聊天显示框的句柄,用于显示给用户
|
||||||
|
history 聊天历史,前情提要
|
||||||
|
system_prompt 给gpt的静默提醒
|
||||||
|
web_port 当前软件运行的端口号
|
||||||
|
"""
|
||||||
|
import subprocess
|
||||||
|
history = [] # 清空历史,以免输入溢出
|
||||||
|
chatbot.append(("这是什么功能?", "[Local Message] 微调数据集生成"))
|
||||||
|
if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg")
|
||||||
|
args = plugin_kwargs.get("advanced_arg", None)
|
||||||
|
if args is None:
|
||||||
|
chatbot.append(("没给定指令", "退出"))
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history); return
|
||||||
|
else:
|
||||||
|
arguments = string_to_options(arguments=args)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pre_seq_len = arguments.pre_seq_len # 128
|
||||||
|
learning_rate = arguments.learning_rate # 2e-2
|
||||||
|
num_gpus = arguments.num_gpus # 1
|
||||||
|
json_dataset = arguments.json_dataset # 't_code.json'
|
||||||
|
ptuning_directory = arguments.ptuning_directory # '/home/hmp/ChatGLM2-6B/ptuning'
|
||||||
|
|
||||||
|
command = f"torchrun --standalone --nnodes=1 --nproc-per-node={num_gpus} main.py \
|
||||||
|
--do_train \
|
||||||
|
--train_file AdvertiseGen/{json_dataset} \
|
||||||
|
--validation_file AdvertiseGen/{json_dataset} \
|
||||||
|
--preprocessing_num_workers 20 \
|
||||||
|
--prompt_column content \
|
||||||
|
--response_column summary \
|
||||||
|
--overwrite_cache \
|
||||||
|
--model_name_or_path THUDM/chatglm2-6b \
|
||||||
|
--output_dir output/clothgen-chatglm2-6b-pt-{pre_seq_len}-{learning_rate} \
|
||||||
|
--overwrite_output_dir \
|
||||||
|
--max_source_length 256 \
|
||||||
|
--max_target_length 256 \
|
||||||
|
--per_device_train_batch_size 1 \
|
||||||
|
--per_device_eval_batch_size 1 \
|
||||||
|
--gradient_accumulation_steps 16 \
|
||||||
|
--predict_with_generate \
|
||||||
|
--max_steps 100 \
|
||||||
|
--logging_steps 10 \
|
||||||
|
--save_steps 20 \
|
||||||
|
--learning_rate {learning_rate} \
|
||||||
|
--pre_seq_len {pre_seq_len} \
|
||||||
|
--quantization_bit 4"
|
||||||
|
|
||||||
|
process = subprocess.Popen(command, shell=True, cwd=ptuning_directory)
|
||||||
|
try:
|
||||||
|
process.communicate(timeout=3600*24)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
process.kill()
|
||||||
|
return
|
||||||
@@ -211,8 +211,22 @@ def test_Latex():
|
|||||||
# # for cookies, cb, hist, msg in silence_stdout(编译Latex)(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
# # for cookies, cb, hist, msg in silence_stdout(编译Latex)(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
# cli_printer.print(cb) # print(cb)
|
# cli_printer.print(cb) # print(cb)
|
||||||
|
|
||||||
|
def test_chatglm_finetune():
|
||||||
|
from crazy_functions.chatglm微调工具 import 微调数据集生成, 启动微调
|
||||||
|
txt = 'build/dev.json'
|
||||||
|
plugin_kwargs = {"advanced_arg":"--llm_to_learn=gpt-3.5-turbo --prompt_prefix='根据下面的服装类型提示,想象一个穿着者,对这个人外貌、身处的环境、内心世界、人设进行描写。要求:100字以内,用第二人称。' --system_prompt=''" }
|
||||||
|
|
||||||
|
# for cookies, cb, hist, msg in (微调数据集生成)(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
|
# cli_printer.print(cb)
|
||||||
|
|
||||||
|
plugin_kwargs = {"advanced_arg":
|
||||||
|
" --pre_seq_len=128 --learning_rate=2e-2 --num_gpus=1 --json_dataset='t_code.json' --ptuning_directory='/home/hmp/ChatGLM2-6B/ptuning' " }
|
||||||
|
|
||||||
|
for cookies, cb, hist, msg in (启动微调)(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
|
||||||
|
cli_printer.print(cb)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
# test_解析一个Python项目()
|
# test_解析一个Python项目()
|
||||||
# test_Latex英文润色()
|
# test_Latex英文润色()
|
||||||
# test_Markdown中译英()
|
# test_Markdown中译英()
|
||||||
@@ -226,7 +240,7 @@ def test_Latex():
|
|||||||
# test_数学动画生成manim()
|
# test_数学动画生成manim()
|
||||||
# test_Langchain知识库()
|
# test_Langchain知识库()
|
||||||
# test_Langchain知识库读取()
|
# test_Langchain知识库读取()
|
||||||
if __name__ == "__main__":
|
# test_Latex()
|
||||||
test_Latex()
|
test_chatglm_finetune()
|
||||||
input("程序完成,回车退出。")
|
input("程序完成,回车退出。")
|
||||||
print("退出。")
|
print("退出。")
|
||||||
@@ -1,121 +1,107 @@
|
|||||||
from toolbox import update_ui
|
from toolbox import update_ui, promote_file_to_downloadzone, gen_time_str
|
||||||
from toolbox import CatchException, report_execption, write_results_to_file
|
from toolbox import CatchException, report_execption, write_results_to_file
|
||||||
import re
|
|
||||||
import unicodedata
|
|
||||||
fast_debug = False
|
|
||||||
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
|
||||||
|
from .crazy_utils import read_and_clean_pdf_text
|
||||||
|
from .crazy_utils import input_clipping
|
||||||
|
|
||||||
def is_paragraph_break(match):
|
|
||||||
"""
|
|
||||||
根据给定的匹配结果来判断换行符是否表示段落分隔。
|
|
||||||
如果换行符前为句子结束标志(句号,感叹号,问号),且下一个字符为大写字母,则换行符更有可能表示段落分隔。
|
|
||||||
也可以根据之前的内容长度来判断段落是否已经足够长。
|
|
||||||
"""
|
|
||||||
prev_char, next_char = match.groups()
|
|
||||||
|
|
||||||
# 句子结束标志
|
|
||||||
sentence_endings = ".!?"
|
|
||||||
|
|
||||||
# 设定一个最小段落长度阈值
|
|
||||||
min_paragraph_length = 140
|
|
||||||
|
|
||||||
if prev_char in sentence_endings and next_char.isupper() and len(match.string[:match.start(1)]) > min_paragraph_length:
|
|
||||||
return "\n\n"
|
|
||||||
else:
|
|
||||||
return " "
|
|
||||||
|
|
||||||
def normalize_text(text):
|
|
||||||
"""
|
|
||||||
通过把连字(ligatures)等文本特殊符号转换为其基本形式来对文本进行归一化处理。
|
|
||||||
例如,将连字 "fi" 转换为 "f" 和 "i"。
|
|
||||||
"""
|
|
||||||
# 对文本进行归一化处理,分解连字
|
|
||||||
normalized_text = unicodedata.normalize("NFKD", text)
|
|
||||||
|
|
||||||
# 替换其他特殊字符
|
|
||||||
cleaned_text = re.sub(r'[^\x00-\x7F]+', '', normalized_text)
|
|
||||||
|
|
||||||
return cleaned_text
|
|
||||||
|
|
||||||
def clean_text(raw_text):
|
|
||||||
"""
|
|
||||||
对从 PDF 提取出的原始文本进行清洗和格式化处理。
|
|
||||||
1. 对原始文本进行归一化处理。
|
|
||||||
2. 替换跨行的连词
|
|
||||||
3. 根据 heuristic 规则判断换行符是否是段落分隔,并相应地进行替换
|
|
||||||
"""
|
|
||||||
# 对文本进行归一化处理
|
|
||||||
normalized_text = normalize_text(raw_text)
|
|
||||||
|
|
||||||
# 替换跨行的连词
|
|
||||||
text = re.sub(r'(\w+-\n\w+)', lambda m: m.group(1).replace('-\n', ''), normalized_text)
|
|
||||||
|
|
||||||
# 根据前后相邻字符的特点,找到原文本中的换行符
|
|
||||||
newlines = re.compile(r'(\S)\n(\S)')
|
|
||||||
|
|
||||||
# 根据 heuristic 规则,用空格或段落分隔符替换原换行符
|
|
||||||
final_text = re.sub(newlines, lambda m: m.group(1) + is_paragraph_break(m) + m.group(2), text)
|
|
||||||
|
|
||||||
return final_text.strip()
|
|
||||||
|
|
||||||
def 解析PDF(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
def 解析PDF(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt):
|
||||||
import time, glob, os, fitz
|
file_write_buffer = []
|
||||||
print('begin analysis on:', file_manifest)
|
for file_name in file_manifest:
|
||||||
for index, fp in enumerate(file_manifest):
|
print('begin analysis on:', file_name)
|
||||||
with fitz.open(fp) as doc:
|
############################## <第 0 步,切割PDF> ##################################
|
||||||
file_content = ""
|
# 递归地切割PDF文件,每一块(尽量是完整的一个section,比如introduction,experiment等,必要时再进行切割)
|
||||||
for page in doc:
|
# 的长度必须小于 2500 个 Token
|
||||||
file_content += page.get_text()
|
file_content, page_one = read_and_clean_pdf_text(file_name) # (尝试)按照章节切割PDF
|
||||||
file_content = clean_text(file_content)
|
file_content = file_content.encode('utf-8', 'ignore').decode() # avoid reading non-utf8 chars
|
||||||
print(file_content)
|
page_one = str(page_one).encode('utf-8', 'ignore').decode() # avoid reading non-utf8 chars
|
||||||
|
|
||||||
prefix = "接下来请你逐文件分析下面的论文文件,概括其内容" if index==0 else ""
|
TOKEN_LIMIT_PER_FRAGMENT = 2500
|
||||||
i_say = prefix + f'请对下面的文章片段用中文做一个概述,文件名是{os.path.relpath(fp, project_folder)},文章内容是 ```{file_content}```'
|
|
||||||
i_say_show_user = prefix + f'[{index + 1}/{len(file_manifest)}] 请对下面的文章片段做一个概述: {os.path.abspath(fp)}'
|
|
||||||
chatbot.append((i_say_show_user, "[Local Message] waiting gpt response."))
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
|
||||||
|
|
||||||
if not fast_debug:
|
from .crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf
|
||||||
msg = '正常'
|
from request_llm.bridge_all import model_info
|
||||||
# ** gpt request **
|
enc = model_info["gpt-3.5-turbo"]['tokenizer']
|
||||||
|
def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
|
||||||
|
paper_fragments = breakdown_txt_to_satisfy_token_limit_for_pdf(
|
||||||
|
txt=file_content, get_token_fn=get_token_num, limit=TOKEN_LIMIT_PER_FRAGMENT)
|
||||||
|
page_one_fragments = breakdown_txt_to_satisfy_token_limit_for_pdf(
|
||||||
|
txt=str(page_one), get_token_fn=get_token_num, limit=TOKEN_LIMIT_PER_FRAGMENT//4)
|
||||||
|
# 为了更好的效果,我们剥离Introduction之后的部分(如果有)
|
||||||
|
paper_meta = page_one_fragments[0].split('introduction')[0].split('Introduction')[0].split('INTRODUCTION')[0]
|
||||||
|
|
||||||
|
############################## <第 1 步,从摘要中提取高价值信息,放到history中> ##################################
|
||||||
|
final_results = []
|
||||||
|
final_results.append(paper_meta)
|
||||||
|
|
||||||
|
############################## <第 2 步,迭代地历遍整个文章,提取精炼信息> ##################################
|
||||||
|
i_say_show_user = f'首先你在中文语境下通读整篇论文。'; gpt_say = "[Local Message] 收到。" # 用户提示
|
||||||
|
chatbot.append([i_say_show_user, gpt_say]); yield from update_ui(chatbot=chatbot, history=[]) # 更新UI
|
||||||
|
|
||||||
|
iteration_results = []
|
||||||
|
last_iteration_result = paper_meta # 初始值是摘要
|
||||||
|
MAX_WORD_TOTAL = 4096 * 0.7
|
||||||
|
n_fragment = len(paper_fragments)
|
||||||
|
if n_fragment >= 20: print('文章极长,不能达到预期效果')
|
||||||
|
for i in range(n_fragment):
|
||||||
|
NUM_OF_WORD = MAX_WORD_TOTAL // n_fragment
|
||||||
|
i_say = f"Read this section, recapitulate the content of this section with less than {NUM_OF_WORD} Chinese characters: {paper_fragments[i]}"
|
||||||
|
i_say_show_user = f"[{i+1}/{n_fragment}] Read this section, recapitulate the content of this section with less than {NUM_OF_WORD} Chinese characters: {paper_fragments[i][:200]}"
|
||||||
|
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(i_say, i_say_show_user, # i_say=真正给chatgpt的提问, i_say_show_user=给用户看的提问
|
||||||
|
llm_kwargs, chatbot,
|
||||||
|
history=["The main idea of the previous section is?", last_iteration_result], # 迭代上一次的结果
|
||||||
|
sys_prompt="Extract the main idea of this section with Chinese." # 提示
|
||||||
|
)
|
||||||
|
iteration_results.append(gpt_say)
|
||||||
|
last_iteration_result = gpt_say
|
||||||
|
|
||||||
|
############################## <第 3 步,整理history,提取总结> ##################################
|
||||||
|
final_results.extend(iteration_results)
|
||||||
|
final_results.append(f'Please conclude this paper discussed above。')
|
||||||
|
# This prompt is from https://github.com/kaixindelele/ChatPaper/blob/main/chat_paper.py
|
||||||
|
NUM_OF_WORD = 1000
|
||||||
|
i_say = """
|
||||||
|
1. Mark the title of the paper (with Chinese translation)
|
||||||
|
2. list all the authors' names (use English)
|
||||||
|
3. mark the first author's affiliation (output Chinese translation only)
|
||||||
|
4. mark the keywords of this article (use English)
|
||||||
|
5. link to the paper, Github code link (if available, fill in Github:None if not)
|
||||||
|
6. summarize according to the following four points.Be sure to use Chinese answers (proper nouns need to be marked in English)
|
||||||
|
- (1):What is the research background of this article?
|
||||||
|
- (2):What are the past methods? What are the problems with them? Is the approach well motivated?
|
||||||
|
- (3):What is the research methodology proposed in this paper?
|
||||||
|
- (4):On what task and what performance is achieved by the methods in this paper? Can the performance support their goals?
|
||||||
|
Follow the format of the output that follows:
|
||||||
|
1. Title: xxx\n\n
|
||||||
|
2. Authors: xxx\n\n
|
||||||
|
3. Affiliation: xxx\n\n
|
||||||
|
4. Keywords: xxx\n\n
|
||||||
|
5. Urls: xxx or xxx , xxx \n\n
|
||||||
|
6. Summary: \n\n
|
||||||
|
- (1):xxx;\n
|
||||||
|
- (2):xxx;\n
|
||||||
|
- (3):xxx;\n
|
||||||
|
- (4):xxx.\n\n
|
||||||
|
Be sure to use Chinese answers (proper nouns need to be marked in English), statements as concise and academic as possible,
|
||||||
|
do not have too much repetitive information, numerical values using the original numbers.
|
||||||
|
"""
|
||||||
|
# This prompt is from https://github.com/kaixindelele/ChatPaper/blob/main/chat_paper.py
|
||||||
|
file_write_buffer.extend(final_results)
|
||||||
|
i_say, final_results = input_clipping(i_say, final_results, max_token_limit=2000)
|
||||||
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
||||||
inputs=i_say,
|
inputs=i_say, inputs_show_user='开始最终总结',
|
||||||
inputs_show_user=i_say_show_user,
|
llm_kwargs=llm_kwargs, chatbot=chatbot, history=final_results,
|
||||||
llm_kwargs=llm_kwargs,
|
sys_prompt= f"Extract the main idea of this paper with less than {NUM_OF_WORD} Chinese characters"
|
||||||
chatbot=chatbot,
|
)
|
||||||
history=[],
|
final_results.append(gpt_say)
|
||||||
sys_prompt="总结文章。"
|
file_write_buffer.extend([i_say, gpt_say])
|
||||||
) # 带超时倒计时
|
############################## <第 4 步,设置一个token上限> ##################################
|
||||||
|
_, final_results = input_clipping("", final_results, max_token_limit=3200)
|
||||||
|
yield from update_ui(chatbot=chatbot, history=final_results) # 注意这里的历史记录被替代了
|
||||||
|
|
||||||
|
res = write_results_to_file(file_write_buffer, file_name=gen_time_str())
|
||||||
chatbot[-1] = (i_say_show_user, gpt_say)
|
promote_file_to_downloadzone(res.split('\t')[-1], chatbot=chatbot)
|
||||||
history.append(i_say_show_user); history.append(gpt_say)
|
yield from update_ui(chatbot=chatbot, history=final_results) # 刷新界面
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
|
||||||
if not fast_debug: time.sleep(2)
|
|
||||||
|
|
||||||
all_file = ', '.join([os.path.relpath(fp, project_folder) for index, fp in enumerate(file_manifest)])
|
|
||||||
i_say = f'根据以上你自己的分析,对全文进行概括,用学术性语言写一段中文摘要,然后再写一段英文摘要(包括{all_file})。'
|
|
||||||
chatbot.append((i_say, "[Local Message] waiting gpt response."))
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
|
||||||
|
|
||||||
if not fast_debug:
|
|
||||||
msg = '正常'
|
|
||||||
# ** gpt request **
|
|
||||||
gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
|
|
||||||
inputs=i_say,
|
|
||||||
inputs_show_user=i_say,
|
|
||||||
llm_kwargs=llm_kwargs,
|
|
||||||
chatbot=chatbot,
|
|
||||||
history=history,
|
|
||||||
sys_prompt="总结文章。"
|
|
||||||
) # 带超时倒计时
|
|
||||||
|
|
||||||
chatbot[-1] = (i_say, gpt_say)
|
|
||||||
history.append(i_say); history.append(gpt_say)
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
|
||||||
res = write_results_to_file(history)
|
|
||||||
chatbot.append(("完成了吗?", res))
|
|
||||||
yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
|
|
||||||
|
|
||||||
|
|
||||||
@CatchException
|
@CatchException
|
||||||
@@ -151,10 +137,7 @@ def 批量总结PDF文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst
|
|||||||
return
|
return
|
||||||
|
|
||||||
# 搜索需要处理的文件清单
|
# 搜索需要处理的文件清单
|
||||||
file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.pdf', recursive=True)] # + \
|
file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.pdf', recursive=True)]
|
||||||
# [f for f in glob.glob(f'{project_folder}/**/*.tex', recursive=True)] + \
|
|
||||||
# [f for f in glob.glob(f'{project_folder}/**/*.cpp', recursive=True)] + \
|
|
||||||
# [f for f in glob.glob(f'{project_folder}/**/*.c', recursive=True)]
|
|
||||||
|
|
||||||
# 如果没找到任何文件
|
# 如果没找到任何文件
|
||||||
if len(file_manifest) == 0:
|
if len(file_manifest) == 0:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ def 同时问询(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt
|
|||||||
"""
|
"""
|
||||||
txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径
|
txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径
|
||||||
llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行
|
llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行
|
||||||
plugin_kwargs 插件模型的参数,如温度和top_p等,一般原样传递下去就行
|
plugin_kwargs 插件模型的参数,用于灵活调整复杂功能的各种参数
|
||||||
chatbot 聊天显示框的句柄,用于显示给用户
|
chatbot 聊天显示框的句柄,用于显示给用户
|
||||||
history 聊天历史,前情提要
|
history 聊天历史,前情提要
|
||||||
system_prompt 给gpt的静默提醒
|
system_prompt 给gpt的静默提醒
|
||||||
@@ -35,7 +35,7 @@ def 同时问询_指定模型(txt, llm_kwargs, plugin_kwargs, chatbot, history,
|
|||||||
"""
|
"""
|
||||||
txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径
|
txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径
|
||||||
llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行
|
llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行
|
||||||
plugin_kwargs 插件模型的参数,如温度和top_p等,一般原样传递下去就行
|
plugin_kwargs 插件模型的参数,用于灵活调整复杂功能的各种参数
|
||||||
chatbot 聊天显示框的句柄,用于显示给用户
|
chatbot 聊天显示框的句柄,用于显示给用户
|
||||||
history 聊天历史,前情提要
|
history 聊天历史,前情提要
|
||||||
system_prompt 给gpt的静默提醒
|
system_prompt 给gpt的静默提醒
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ def 高阶功能模板函数(txt, llm_kwargs, plugin_kwargs, chatbot, history, s
|
|||||||
"""
|
"""
|
||||||
txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径
|
txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径
|
||||||
llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行
|
llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行
|
||||||
plugin_kwargs 插件模型的参数,如温度和top_p等,一般原样传递下去就行
|
plugin_kwargs 插件模型的参数,用于灵活调整复杂功能的各种参数
|
||||||
chatbot 聊天显示框的句柄,用于显示给用户
|
chatbot 聊天显示框的句柄,用于显示给用户
|
||||||
history 聊天历史,前情提要
|
history 聊天历史,前情提要
|
||||||
system_prompt 给gpt的静默提醒
|
system_prompt 给gpt的静默提醒
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
gpt_academic_nolocalllms:
|
gpt_academic_nolocalllms:
|
||||||
image: ghcr.io/binary-husky/gpt_academic_nolocal:master
|
image: ghcr.io/binary-husky/gpt_academic_nolocal:master # (Auto Built by Dockerfile: docs/GithubAction+NoLocal)
|
||||||
environment:
|
environment:
|
||||||
# 请查阅 `config.py` 以查看所有的配置信息
|
# 请查阅 `config.py` 以查看所有的配置信息
|
||||||
API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx '
|
API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx '
|
||||||
@@ -33,7 +33,7 @@ services:
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
gpt_academic_with_chatglm:
|
gpt_academic_with_chatglm:
|
||||||
image: ghcr.io/binary-husky/gpt_academic_chatglm_moss:master
|
image: ghcr.io/binary-husky/gpt_academic_chatglm_moss:master # (Auto Built by Dockerfile: docs/Dockerfile+ChatGLM)
|
||||||
environment:
|
environment:
|
||||||
# 请查阅 `config.py` 以查看所有的配置信息
|
# 请查阅 `config.py` 以查看所有的配置信息
|
||||||
API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,fkxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx '
|
API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,fkxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx '
|
||||||
@@ -63,7 +63,7 @@ services:
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
gpt_academic_with_rwkv:
|
gpt_academic_with_rwkv:
|
||||||
image: fuqingxu/gpt_academic:jittorllms # [option 2] 如果需要运行ChatGLM本地模型
|
image: fuqingxu/gpt_academic:jittorllms
|
||||||
environment:
|
environment:
|
||||||
# 请查阅 `config.py` 以查看所有的配置信息
|
# 请查阅 `config.py` 以查看所有的配置信息
|
||||||
API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,fkxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx '
|
API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,fkxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx '
|
||||||
@@ -111,7 +111,7 @@ services:
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
gpt_academic_with_latex:
|
gpt_academic_with_latex:
|
||||||
image: ghcr.io/binary-husky/gpt_academic_with_latex:master
|
image: ghcr.io/binary-husky/gpt_academic_with_latex:master # (Auto Built by Dockerfile: docs/GithubAction+NoLocal+Latex)
|
||||||
environment:
|
environment:
|
||||||
# 请查阅 `config.py` 以查看所有的配置信息
|
# 请查阅 `config.py` 以查看所有的配置信息
|
||||||
API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx '
|
API_KEY: ' sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx '
|
||||||
|
|||||||
@@ -269,6 +269,24 @@ if "newbing" in AVAIL_LLM_MODELS: # same with newbing-free
|
|||||||
})
|
})
|
||||||
except:
|
except:
|
||||||
print(trimmed_format_exc())
|
print(trimmed_format_exc())
|
||||||
|
if "chatglmft" in AVAIL_LLM_MODELS: # same with newbing-free
|
||||||
|
try:
|
||||||
|
from .bridge_chatglmft import predict_no_ui_long_connection as chatglmft_noui
|
||||||
|
from .bridge_chatglmft import predict as chatglmft_ui
|
||||||
|
# claude
|
||||||
|
model_info.update({
|
||||||
|
"chatglmft": {
|
||||||
|
"fn_with_ui": chatglmft_ui,
|
||||||
|
"fn_without_ui": chatglmft_noui,
|
||||||
|
"endpoint": None,
|
||||||
|
"max_token": 4096,
|
||||||
|
"tokenizer": tokenizer_gpt35,
|
||||||
|
"token_cnt": get_token_num_gpt35,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
except:
|
||||||
|
print(trimmed_format_exc())
|
||||||
|
|
||||||
|
|
||||||
def LLM_CATCH_EXCEPTION(f):
|
def LLM_CATCH_EXCEPTION(f):
|
||||||
"""
|
"""
|
||||||
@@ -372,6 +390,6 @@ def predict(inputs, llm_kwargs, *args, **kwargs):
|
|||||||
additional_fn代表点击的哪个按钮,按钮见functional.py
|
additional_fn代表点击的哪个按钮,按钮见functional.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
method = model_info[llm_kwargs['llm_model']]["fn_with_ui"]
|
method = model_info[llm_kwargs['llm_model']]["fn_with_ui"] # 如果这里报错,检查config中的AVAIL_LLM_MODELS选项
|
||||||
yield from method(inputs, llm_kwargs, *args, **kwargs)
|
yield from method(inputs, llm_kwargs, *args, **kwargs)
|
||||||
|
|
||||||
|
|||||||
210
request_llm/bridge_chatglmft.py
Normal file
210
request_llm/bridge_chatglmft.py
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
|
||||||
|
from transformers import AutoModel, AutoTokenizer
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import threading
|
||||||
|
import importlib
|
||||||
|
from toolbox import update_ui, get_conf
|
||||||
|
from multiprocessing import Process, Pipe
|
||||||
|
|
||||||
|
load_message = "ChatGLMFT尚未加载,加载需要一段时间。注意,取决于`config.py`的配置,ChatGLMFT消耗大量的内存(CPU)或显存(GPU),也许会导致低配计算机卡死 ……"
|
||||||
|
|
||||||
|
def string_to_options(arguments):
|
||||||
|
import argparse
|
||||||
|
import shlex
|
||||||
|
# Create an argparse.ArgumentParser instance
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
# Add command-line arguments
|
||||||
|
parser.add_argument("--llm_to_learn", type=str, help="LLM model to learn", default="gpt-3.5-turbo")
|
||||||
|
parser.add_argument("--prompt_prefix", type=str, help="Prompt prefix", default='')
|
||||||
|
parser.add_argument("--system_prompt", type=str, help="System prompt", default='')
|
||||||
|
parser.add_argument("--batch", type=int, help="System prompt", default=50)
|
||||||
|
# Parse the arguments
|
||||||
|
args = parser.parse_args(shlex.split(arguments))
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################################
|
||||||
|
class GetGLMFTHandle(Process):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(daemon=True)
|
||||||
|
self.parent, self.child = Pipe()
|
||||||
|
self.chatglmft_model = None
|
||||||
|
self.chatglmft_tokenizer = None
|
||||||
|
self.info = ""
|
||||||
|
self.success = True
|
||||||
|
self.check_dependency()
|
||||||
|
self.start()
|
||||||
|
self.threadLock = threading.Lock()
|
||||||
|
|
||||||
|
def check_dependency(self):
|
||||||
|
try:
|
||||||
|
import sentencepiece
|
||||||
|
self.info = "依赖检测通过"
|
||||||
|
self.success = True
|
||||||
|
except:
|
||||||
|
self.info = "缺少ChatGLMFT的依赖,如果要使用ChatGLMFT,除了基础的pip依赖以外,您还需要运行`pip install -r request_llm/requirements_chatglm.txt`安装ChatGLM的依赖。"
|
||||||
|
self.success = False
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
return self.chatglmft_model is not None
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# 子进程执行
|
||||||
|
# 第一次运行,加载参数
|
||||||
|
retry = 0
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
if self.chatglmft_model is None:
|
||||||
|
from transformers import AutoConfig
|
||||||
|
import torch
|
||||||
|
# conf = 'request_llm/current_ptune_model.json'
|
||||||
|
# if not os.path.exists(conf): raise RuntimeError('找不到微调模型信息')
|
||||||
|
# with open(conf, 'r', encoding='utf8') as f:
|
||||||
|
# model_args = json.loads(f.read())
|
||||||
|
ChatGLM_PTUNING_CHECKPOINT, = get_conf('ChatGLM_PTUNING_CHECKPOINT')
|
||||||
|
assert os.path.exists(ChatGLM_PTUNING_CHECKPOINT), "找不到微调模型检查点"
|
||||||
|
conf = os.path.join(ChatGLM_PTUNING_CHECKPOINT, "config.json")
|
||||||
|
with open(conf, 'r', encoding='utf8') as f:
|
||||||
|
model_args = json.loads(f.read())
|
||||||
|
if 'model_name_or_path' not in model_args:
|
||||||
|
model_args['model_name_or_path'] = model_args['_name_or_path']
|
||||||
|
self.chatglmft_tokenizer = AutoTokenizer.from_pretrained(
|
||||||
|
model_args['model_name_or_path'], trust_remote_code=True)
|
||||||
|
config = AutoConfig.from_pretrained(
|
||||||
|
model_args['model_name_or_path'], trust_remote_code=True)
|
||||||
|
|
||||||
|
config.pre_seq_len = model_args['pre_seq_len']
|
||||||
|
config.prefix_projection = model_args['prefix_projection']
|
||||||
|
|
||||||
|
print(f"Loading prefix_encoder weight from {ChatGLM_PTUNING_CHECKPOINT}")
|
||||||
|
model = AutoModel.from_pretrained(model_args['model_name_or_path'], config=config, trust_remote_code=True)
|
||||||
|
prefix_state_dict = torch.load(os.path.join(ChatGLM_PTUNING_CHECKPOINT, "pytorch_model.bin"))
|
||||||
|
new_prefix_state_dict = {}
|
||||||
|
for k, v in prefix_state_dict.items():
|
||||||
|
if k.startswith("transformer.prefix_encoder."):
|
||||||
|
new_prefix_state_dict[k[len("transformer.prefix_encoder."):]] = v
|
||||||
|
model.transformer.prefix_encoder.load_state_dict(new_prefix_state_dict)
|
||||||
|
|
||||||
|
if model_args['quantization_bit'] is not None:
|
||||||
|
print(f"Quantized to {model_args['quantization_bit']} bit")
|
||||||
|
model = model.quantize(model_args['quantization_bit'])
|
||||||
|
model = model.cuda()
|
||||||
|
if model_args['pre_seq_len'] is not None:
|
||||||
|
# P-tuning v2
|
||||||
|
model.transformer.prefix_encoder.float()
|
||||||
|
self.chatglmft_model = model.eval()
|
||||||
|
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
retry += 1
|
||||||
|
if retry > 3:
|
||||||
|
self.child.send('[Local Message] Call ChatGLMFT fail 不能正常加载ChatGLMFT的参数。')
|
||||||
|
raise RuntimeError("不能正常加载ChatGLMFT的参数!")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# 进入任务等待状态
|
||||||
|
kwargs = self.child.recv()
|
||||||
|
# 收到消息,开始请求
|
||||||
|
try:
|
||||||
|
for response, history in self.chatglmft_model.stream_chat(self.chatglmft_tokenizer, **kwargs):
|
||||||
|
self.child.send(response)
|
||||||
|
# # 中途接收可能的终止指令(如果有的话)
|
||||||
|
# if self.child.poll():
|
||||||
|
# command = self.child.recv()
|
||||||
|
# if command == '[Terminate]': break
|
||||||
|
except:
|
||||||
|
from toolbox import trimmed_format_exc
|
||||||
|
self.child.send('[Local Message] Call ChatGLMFT fail.' + '\n```\n' + trimmed_format_exc() + '\n```\n')
|
||||||
|
# 请求处理结束,开始下一个循环
|
||||||
|
self.child.send('[Finish]')
|
||||||
|
|
||||||
|
def stream_chat(self, **kwargs):
|
||||||
|
# 主进程执行
|
||||||
|
self.threadLock.acquire()
|
||||||
|
self.parent.send(kwargs)
|
||||||
|
while True:
|
||||||
|
res = self.parent.recv()
|
||||||
|
if res != '[Finish]':
|
||||||
|
yield res
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
self.threadLock.release()
|
||||||
|
|
||||||
|
global glmft_handle
|
||||||
|
glmft_handle = None
|
||||||
|
#################################################################################
|
||||||
|
def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=[], console_slience=False):
|
||||||
|
"""
|
||||||
|
多线程方法
|
||||||
|
函数的说明请见 request_llm/bridge_all.py
|
||||||
|
"""
|
||||||
|
global glmft_handle
|
||||||
|
if glmft_handle is None:
|
||||||
|
glmft_handle = GetGLMFTHandle()
|
||||||
|
if len(observe_window) >= 1: observe_window[0] = load_message + "\n\n" + glmft_handle.info
|
||||||
|
if not glmft_handle.success:
|
||||||
|
error = glmft_handle.info
|
||||||
|
glmft_handle = None
|
||||||
|
raise RuntimeError(error)
|
||||||
|
|
||||||
|
# chatglmft 没有 sys_prompt 接口,因此把prompt加入 history
|
||||||
|
history_feedin = []
|
||||||
|
history_feedin.append(["What can I do?", sys_prompt])
|
||||||
|
for i in range(len(history)//2):
|
||||||
|
history_feedin.append([history[2*i], history[2*i+1]] )
|
||||||
|
|
||||||
|
watch_dog_patience = 5 # 看门狗 (watchdog) 的耐心, 设置5秒即可
|
||||||
|
response = ""
|
||||||
|
for response in glmft_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']):
|
||||||
|
if len(observe_window) >= 1: observe_window[0] = response
|
||||||
|
if len(observe_window) >= 2:
|
||||||
|
if (time.time()-observe_window[1]) > watch_dog_patience:
|
||||||
|
raise RuntimeError("程序终止。")
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None):
|
||||||
|
"""
|
||||||
|
单线程方法
|
||||||
|
函数的说明请见 request_llm/bridge_all.py
|
||||||
|
"""
|
||||||
|
chatbot.append((inputs, ""))
|
||||||
|
|
||||||
|
global glmft_handle
|
||||||
|
if glmft_handle is None:
|
||||||
|
glmft_handle = GetGLMFTHandle()
|
||||||
|
chatbot[-1] = (inputs, load_message + "\n\n" + glmft_handle.info)
|
||||||
|
yield from update_ui(chatbot=chatbot, history=[])
|
||||||
|
if not glmft_handle.success:
|
||||||
|
glmft_handle = None
|
||||||
|
return
|
||||||
|
|
||||||
|
if additional_fn is not None:
|
||||||
|
import core_functional
|
||||||
|
importlib.reload(core_functional) # 热更新prompt
|
||||||
|
core_functional = core_functional.get_core_functions()
|
||||||
|
if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话)
|
||||||
|
inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"]
|
||||||
|
|
||||||
|
# 处理历史信息
|
||||||
|
history_feedin = []
|
||||||
|
history_feedin.append(["What can I do?", system_prompt] )
|
||||||
|
for i in range(len(history)//2):
|
||||||
|
history_feedin.append([history[2*i], history[2*i+1]] )
|
||||||
|
|
||||||
|
# 开始接收chatglmft的回复
|
||||||
|
response = "[Local Message]: 等待ChatGLMFT响应中 ..."
|
||||||
|
for response in glmft_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']):
|
||||||
|
chatbot[-1] = (inputs, response)
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history)
|
||||||
|
|
||||||
|
# 总结输出
|
||||||
|
if response == "[Local Message]: 等待ChatGLMFT响应中 ...":
|
||||||
|
response = "[Local Message]: ChatGLMFT响应异常 ..."
|
||||||
|
history.extend([inputs, response])
|
||||||
|
yield from update_ui(chatbot=chatbot, history=history)
|
||||||
@@ -214,7 +214,7 @@ def write_results_to_file(history, file_name=None):
|
|||||||
# remove everything that cannot be handled by utf8
|
# remove everything that cannot be handled by utf8
|
||||||
f.write(content.encode('utf-8', 'ignore').decode())
|
f.write(content.encode('utf-8', 'ignore').decode())
|
||||||
f.write('\n\n')
|
f.write('\n\n')
|
||||||
res = '以上材料已经被写入' + os.path.abspath(f'./gpt_log/{file_name}')
|
res = '以上材料已经被写入:\t' + os.path.abspath(f'./gpt_log/{file_name}')
|
||||||
print(res)
|
print(res)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@@ -467,8 +467,11 @@ 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(f'./gpt_log/', rename_file)
|
new_path = os.path.join(f'./gpt_log/', 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中,避免多用户干扰
|
||||||
if chatbot:
|
if chatbot:
|
||||||
if 'file_to_promote' in chatbot._cookies: current = chatbot._cookies['file_to_promote']
|
if 'file_to_promote' in chatbot._cookies: current = chatbot._cookies['file_to_promote']
|
||||||
else: current = []
|
else: current = []
|
||||||
|
|||||||
4
version
4
version
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": 3.44,
|
"version": 3.45,
|
||||||
"show_feature": true,
|
"show_feature": true,
|
||||||
"new_feature": "改善UI <-> 修复Azure接口的BUG <-> 完善多语言模块 <-> 完善本地Latex矫错和翻译功能 <-> 增加gpt-3.5-16k的支持 <-> 新增最强Arxiv论文翻译插件 <-> 修复gradio复制按钮BUG <-> 修复PDF翻译的BUG, 新增HTML中英双栏对照 <-> 添加了OpenAI图片生成插件"
|
"new_feature": "支持加载自定义的ChatGLM2微调模型 <-> [改善UI] 动态ChatBot窗口高度 <-> 修复Azure接口的BUG <-> 完善多语言模块 <-> 完善本地Latex矫错和翻译功能 <-> 增加gpt-3.5-16k的支持 <-> 新增最强Arxiv论文翻译插件 <-> 修复gradio复制按钮BUG <-> 修复PDF翻译的BUG, 新增HTML中英双栏对照 <-> 添加了OpenAI图片生成插件"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user