3v324v23 commited on
Commit
a76738a
·
2 Parent(s): a6028bd 05c74e6

Merge branch 'v3.1' into huggingface-beta

Browse files
.gitignore CHANGED
@@ -55,7 +55,6 @@ coverage.xml
55
  *.pot
56
  github
57
  .github
58
- .idea/
59
  TEMP
60
  TRASH
61
 
@@ -144,3 +143,4 @@ private_upload
144
  other_llms
145
  cradle*
146
  debug*
 
 
55
  *.pot
56
  github
57
  .github
 
58
  TEMP
59
  TRASH
60
 
 
143
  other_llms
144
  cradle*
145
  debug*
146
+ private*
config.py CHANGED
@@ -1,5 +1,5 @@
1
  # [step 1]>> 例如: API_KEY = "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" (此key无效)
2
- API_KEY = "sk-此处填API密钥"
3
 
4
  # [step 2]>> 改为True应用代理,如果直接在海外服务器部署,此处不修改
5
  USE_PROXY = False
@@ -19,13 +19,12 @@ if USE_PROXY:
19
  else:
20
  proxies = None
21
 
22
- # 多线程函数插件中,默认允许多少路线程同时访问OpenAI。
23
- # Free trial users的限制是每分钟3次,Pay-as-you-go users的限制是每分钟3500次。提高限制请查询:
24
- # https://platform.openai.com/docs/guides/rate-limits/overview
25
  DEFAULT_WORKER_NUM = 3
26
 
27
 
28
- # [step 3]>> 以下配置可以优化体验,但大部分场合下并不需要修改
29
  # 对话窗的高度
30
  CHATBOT_HEIGHT = 1115
31
 
@@ -45,14 +44,15 @@ WEB_PORT = -1
45
  MAX_RETRY = 2
46
 
47
  # OpenAI模型选择是(gpt4现在只对申请成功的人开放)
48
- LLM_MODEL = "gpt-3.5-turbo"
 
49
 
50
- # OpenAI的API_URL
51
- API_URL = "https://api.openai.com/v1/chat/completions"
52
 
53
- # 设置并行使用的线程数
54
  CONCURRENT_COUNT = 100
55
 
56
- # 设置用户名和密码(相关功能不稳定,与gradio版本和网络都相关,如果本地使用不建议加这个)
57
  # [("username", "password"), ("username2", "password2"), ...]
58
  AUTHENTICATION = []
 
1
  # [step 1]>> 例如: API_KEY = "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" (此key无效)
2
+ API_KEY = "sk-此处填API密钥" # 可同时填写多个API-KEY,用英文逗号分割,例如API_KEY = "sk-openaikey1,sk-openaikey2,fkxxxx-api2dkey1,fkxxxx-api2dkey2"
3
 
4
  # [step 2]>> 改为True应用代理,如果直接在海外服务器部署,此处不修改
5
  USE_PROXY = False
 
19
  else:
20
  proxies = None
21
 
22
+ # [step 3]>> 多线程函数插件中,默认允许多少路线程同时访问OpenAI。Free trial users的限制是每分钟3次,Pay-as-you-go users的限制是每分钟3500次
23
+ # 一言以蔽之:免费用户填3,OpenAI绑了信用卡的用户可以填 16 或者更高。提高限制请查询:https://platform.openai.com/docs/guides/rate-limits/overview
 
24
  DEFAULT_WORKER_NUM = 3
25
 
26
 
27
+ # [step 4]>> 以下配置可以优化体验,但大部分场合下并不需要修改
28
  # 对话窗的高度
29
  CHATBOT_HEIGHT = 1115
30
 
 
44
  MAX_RETRY = 2
45
 
46
  # OpenAI模型选择是(gpt4现在只对申请成功的人开放)
47
+ LLM_MODEL = "gpt-3.5-turbo" # 可选 "chatglm"
48
+ AVAIL_LLM_MODELS = ["gpt-3.5-turbo", "chatglm", "gpt-4", "api2d-gpt-4", "api2d-gpt-3.5-turbo"]
49
 
50
+ # 本地LLM模型如ChatGLM的执行方式 CPU/GPU
51
+ LOCAL_MODEL_DEVICE = "cpu" # 可选 "cuda"
52
 
53
+ # 设置gradio的并行线程数(不需要修改)
54
  CONCURRENT_COUNT = 100
55
 
56
+ # 设置用户名和密码(不需要修改)(相关功能不稳定,与gradio版本和网络都相关,如果本地使用不建议加这个)
57
  # [("username", "password"), ("username2", "password2"), ...]
58
  AUTHENTICATION = []
crazy_functional.py CHANGED
@@ -16,16 +16,21 @@ def get_crazy_functions():
16
  from crazy_functions.高级功能函数模板 import 高阶功能模板函数
17
  from crazy_functions.代码重写为全英文_多线程 import 全项目切换英文
18
  from crazy_functions.Latex全文润色 import Latex英文润色
 
19
  from crazy_functions.解析项目源代码 import 解析一个Lua项目
20
  from crazy_functions.解析项目源代码 import 解析一个CSharp项目
21
  function_plugins = {
22
-
 
 
 
23
  "解析整个Python项目": {
24
  "Color": "stop", # 按钮颜色
25
  "Function": HotReload(解析一个Python项目)
26
  },
27
  "解析整个C++项目头文件": {
28
  "Color": "stop", # 按钮颜色
 
29
  "Function": HotReload(解析一个C项目的头文件)
30
  },
31
  "解析整个C++项目(.cpp/.hpp/.c/.h)": {
 
16
  from crazy_functions.高级功能函数模板 import 高阶功能模板函数
17
  from crazy_functions.代码重写为全英文_多线程 import 全项目切换英文
18
  from crazy_functions.Latex全文润色 import Latex英文润色
19
+ from crazy_functions.询问多个大语言模型 import 同时问询
20
  from crazy_functions.解析项目源代码 import 解析一个Lua项目
21
  from crazy_functions.解析项目源代码 import 解析一个CSharp项目
22
  function_plugins = {
23
+ "询问多个GPT模型": {
24
+ "Color": "stop", # 按钮颜色
25
+ "Function": HotReload(同时问询)
26
+ },
27
  "解析整个Python项目": {
28
  "Color": "stop", # 按钮颜色
29
  "Function": HotReload(解析一个Python项目)
30
  },
31
  "解析整个C++项目头文件": {
32
  "Color": "stop", # 按钮颜色
33
+ "AsButton": False, # 加入下拉菜单中
34
  "Function": HotReload(解析一个C项目的头文件)
35
  },
36
  "解析整个C++项目(.cpp/.hpp/.c/.h)": {
crazy_functions/Latex全文润色.py CHANGED
@@ -13,7 +13,7 @@ class PaperFileGroup():
13
  # count_token
14
  import tiktoken
15
  from toolbox import get_conf
16
- enc = tiktoken.encoding_for_model(*get_conf('LLM_MODEL'))
17
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
18
  self.get_token_num = get_token_num
19
 
 
13
  # count_token
14
  import tiktoken
15
  from toolbox import get_conf
16
+ enc = tiktoken.encoding_for_model("gpt-3.5-turbo")
17
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
18
  self.get_token_num = get_token_num
19
 
crazy_functions/Latex全文翻译.py CHANGED
@@ -13,7 +13,7 @@ class PaperFileGroup():
13
  # count_token
14
  import tiktoken
15
  from toolbox import get_conf
16
- enc = tiktoken.encoding_for_model(*get_conf('LLM_MODEL'))
17
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
18
  self.get_token_num = get_token_num
19
 
 
13
  # count_token
14
  import tiktoken
15
  from toolbox import get_conf
16
+ enc = tiktoken.encoding_for_model("gpt-3.5-turbo")
17
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
18
  self.get_token_num = get_token_num
19
 
crazy_functions/crazy_functions_test.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ 这是什么?
3
+ 这个文件用于函数插件的单元测试
4
+ 运行方法 python crazy_functions/crazy_functions_test.py
5
+ """
6
+
7
+ def validate_path():
8
+ import os, sys
9
+ dir_name = os.path.dirname(__file__)
10
+ root_dir_assume = os.path.abspath(os.path.dirname(__file__) + '/..')
11
+ os.chdir(root_dir_assume)
12
+ sys.path.append(root_dir_assume)
13
+
14
+ validate_path() # validate path so you can run from base directory
15
+
16
+ from toolbox import get_conf, ChatBotWithCookies
17
+ proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, API_KEY = \
18
+ get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'API_KEY')
19
+
20
+ llm_kwargs = {
21
+ 'api_key': API_KEY,
22
+ 'llm_model': LLM_MODEL,
23
+ 'top_p':1.0,
24
+ 'max_length': None,
25
+ 'temperature':1.0,
26
+ }
27
+ plugin_kwargs = { }
28
+ chatbot = ChatBotWithCookies(llm_kwargs)
29
+ history = []
30
+ system_prompt = "Serve me as a writing and programming assistant."
31
+ web_port = 1024
32
+
33
+
34
+ def test_总结word文档():
35
+ from crazy_functions.总结word文档 import 总结word文档
36
+ txt = "F:/AMD"
37
+ for _ in 总结word文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
38
+ pass
39
+
40
+ test_总结word文档()
41
+
42
+ input("程序完成,回车退出。")
43
+ print("退出。")
crazy_functions/crazy_utils.py CHANGED
@@ -4,7 +4,7 @@ from toolbox import update_ui, get_conf
4
  def input_clipping(inputs, history, max_token_limit):
5
  import tiktoken
6
  import numpy as np
7
- enc = tiktoken.encoding_for_model(*get_conf('LLM_MODEL'))
8
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
9
 
10
  mode = 'input-and-history'
@@ -61,12 +61,12 @@ def request_gpt_model_in_new_thread_with_ui_alive(
61
  """
62
  import time
63
  from concurrent.futures import ThreadPoolExecutor
64
- from request_llm.bridge_chatgpt import predict_no_ui_long_connection
65
  # 用户反馈
66
  chatbot.append([inputs_show_user, ""])
67
  yield from update_ui(chatbot=chatbot, history=[]) # 刷新界面
68
  executor = ThreadPoolExecutor(max_workers=16)
69
- mutable = ["", time.time()]
70
  def _req_gpt(inputs, history, sys_prompt):
71
  retry_op = retry_times_at_unknown_error
72
  exceeded_cnt = 0
@@ -105,7 +105,7 @@ def request_gpt_model_in_new_thread_with_ui_alive(
105
  if retry_op > 0:
106
  retry_op -= 1
107
  mutable[0] += f"[Local Message] 重试中,请稍等 {retry_times_at_unknown_error-retry_op}/{retry_times_at_unknown_error}:\n\n"
108
- if "Rate limit reached" in tb_str:
109
  time.sleep(30)
110
  time.sleep(5)
111
  continue # 返回重试
@@ -167,13 +167,17 @@ def request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency(
167
  """
168
  import time, random
169
  from concurrent.futures import ThreadPoolExecutor
170
- from request_llm.bridge_chatgpt import predict_no_ui_long_connection
171
  assert len(inputs_array) == len(history_array)
172
  assert len(inputs_array) == len(sys_prompt_array)
173
  if max_workers == -1: # 读取配置文件
174
  try: max_workers, = get_conf('DEFAULT_WORKER_NUM')
175
  except: max_workers = 8
176
  if max_workers <= 0 or max_workers >= 20: max_workers = 8
 
 
 
 
177
  executor = ThreadPoolExecutor(max_workers=max_workers)
178
  n_frag = len(inputs_array)
179
  # 用户反馈
@@ -230,9 +234,9 @@ def request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency(
230
  if retry_op > 0:
231
  retry_op -= 1
232
  wait = random.randint(5, 20)
233
- if "Rate limit reached" in tb_str:
234
  wait = wait * 3
235
- fail_info = "OpenAI请求速率限制 "
236
  else:
237
  fail_info = ""
238
  # 也许等待十几秒后,情况会好转
 
4
  def input_clipping(inputs, history, max_token_limit):
5
  import tiktoken
6
  import numpy as np
7
+ enc = tiktoken.encoding_for_model("gpt-3.5-turbo")
8
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
9
 
10
  mode = 'input-and-history'
 
61
  """
62
  import time
63
  from concurrent.futures import ThreadPoolExecutor
64
+ from request_llm.bridge_all import predict_no_ui_long_connection
65
  # 用户反馈
66
  chatbot.append([inputs_show_user, ""])
67
  yield from update_ui(chatbot=chatbot, history=[]) # 刷新界面
68
  executor = ThreadPoolExecutor(max_workers=16)
69
+ mutable = ["", time.time(), ""]
70
  def _req_gpt(inputs, history, sys_prompt):
71
  retry_op = retry_times_at_unknown_error
72
  exceeded_cnt = 0
 
105
  if retry_op > 0:
106
  retry_op -= 1
107
  mutable[0] += f"[Local Message] 重试中,请稍等 {retry_times_at_unknown_error-retry_op}/{retry_times_at_unknown_error}:\n\n"
108
+ if ("Rate limit reached" in tb_str) or ("Too Many Requests" in tb_str):
109
  time.sleep(30)
110
  time.sleep(5)
111
  continue # 返回重试
 
167
  """
168
  import time, random
169
  from concurrent.futures import ThreadPoolExecutor
170
+ from request_llm.bridge_all import predict_no_ui_long_connection
171
  assert len(inputs_array) == len(history_array)
172
  assert len(inputs_array) == len(sys_prompt_array)
173
  if max_workers == -1: # 读取配置文件
174
  try: max_workers, = get_conf('DEFAULT_WORKER_NUM')
175
  except: max_workers = 8
176
  if max_workers <= 0 or max_workers >= 20: max_workers = 8
177
+ # 屏蔽掉 chatglm的多线程,可能会导致严重卡顿
178
+ if not (llm_kwargs['llm_model'].startswith('gpt-') or llm_kwargs['llm_model'].startswith('api2d-')):
179
+ max_workers = 1
180
+
181
  executor = ThreadPoolExecutor(max_workers=max_workers)
182
  n_frag = len(inputs_array)
183
  # 用户反馈
 
234
  if retry_op > 0:
235
  retry_op -= 1
236
  wait = random.randint(5, 20)
237
+ if ("Rate limit reached" in tb_str) or ("Too Many Requests" in tb_str):
238
  wait = wait * 3
239
+ fail_info = "OpenAI绑定信用卡可解除频率限制 "
240
  else:
241
  fail_info = ""
242
  # 也许等待十几秒后,情况会好转
crazy_functions/代码重写为全英文_多线程.py CHANGED
@@ -1,5 +1,5 @@
1
  import threading
2
- from request_llm.bridge_chatgpt import predict_no_ui_long_connection
3
  from toolbox import update_ui
4
  from toolbox import CatchException, write_results_to_file, report_execption
5
  from .crazy_utils import breakdown_txt_to_satisfy_token_limit
@@ -61,7 +61,7 @@ def 全项目切换英文(txt, llm_kwargs, plugin_kwargs, chatbot, history, sys_
61
  MAX_TOKEN = 3000
62
  import tiktoken
63
  from toolbox import get_conf
64
- enc = tiktoken.encoding_for_model(*get_conf('LLM_MODEL'))
65
  def get_token_fn(txt): return len(enc.encode(txt, disallowed_special=()))
66
 
67
 
 
1
  import threading
2
+ from request_llm.bridge_all import predict_no_ui_long_connection
3
  from toolbox import update_ui
4
  from toolbox import CatchException, write_results_to_file, report_execption
5
  from .crazy_utils import breakdown_txt_to_satisfy_token_limit
 
61
  MAX_TOKEN = 3000
62
  import tiktoken
63
  from toolbox import get_conf
64
+ enc = tiktoken.encoding_for_model("gpt-3.5-turbo")
65
  def get_token_fn(txt): return len(enc.encode(txt, disallowed_special=()))
66
 
67
 
crazy_functions/总结word文档.py CHANGED
@@ -8,8 +8,6 @@ def 解析docx(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot
8
  import time, os
9
  # pip install python-docx 用于docx格式,跨平台
10
  # pip install pywin32 用于doc格式,仅支持Win平台
11
-
12
- print('begin analysis on:', file_manifest)
13
  for index, fp in enumerate(file_manifest):
14
  if fp.split(".")[-1] == "docx":
15
  from docx import Document
@@ -29,18 +27,20 @@ def 解析docx(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot
29
  word.Quit()
30
 
31
  print(file_content)
32
-
33
- prefix = "接下来请你逐文件分析下面的论文文件," if index == 0 else ""
34
  # private_upload里面的文件名在解压zip后容易出现乱码(rar和7z格式正常),故可以只分析文章内容,不输入文件名
35
- i_say = prefix + f'请对下面的文章片段用中英文做概述,文件名是{os.path.relpath(fp, project_folder)},' \
36
- f'文章内容是 ```{file_content}```'
37
- i_say_show_user = prefix + f'[{index+1}/{len(file_manifest)}] 假设你是论文审稿专家,请对下面的文章片段做概述: {os.path.abspath(fp)}'
38
- chatbot.append((i_say_show_user, "[Local Message] waiting gpt response."))
39
- yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
40
-
41
- if not fast_debug:
42
- msg = '正常'
43
- # ** gpt request **
 
 
 
 
44
  gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
45
  inputs=i_say,
46
  inputs_show_user=i_say_show_user,
@@ -48,46 +48,34 @@ def 解析docx(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot
48
  chatbot=chatbot,
49
  history=[],
50
  sys_prompt="总结文章。"
51
- ) # 带超时倒计时
 
52
  chatbot[-1] = (i_say_show_user, gpt_say)
53
- history.append(i_say_show_user)
54
- history.append(gpt_say)
55
- yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
56
- if not fast_debug: time.sleep(2)
57
-
58
- """
59
- # 可按需启用
60
- i_say = f'根据你上述的分析,对全文进行概括,用学术性语言写一段中文摘要,然后再写一篇英文的。'
61
- chatbot.append((i_say, "[Local Message] waiting gpt response."))
62
- yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
- i_say = f'我想让你做一个论文写作导师。您的任务是使用人工智能工具(例如自然语言处理)提供有关如何改进其上述文章的反馈。' \
66
- f'您还应该利用您在有效写作技巧方面的修辞知识和经验来建议作者可以更好地以书面形式表达他们的想法和想法的方法。' \
67
- f'根据你之前的分析,提出建议'
68
- chatbot.append((i_say, "[Local Message] waiting gpt response."))
69
- yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
70
-
71
- """
72
-
73
- if not fast_debug:
74
- msg = '正常'
75
- # ** gpt request **
76
- gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
77
- inputs=i_say,
78
- inputs_show_user=i_say,
79
- llm_kwargs=llm_kwargs,
80
- chatbot=chatbot,
81
- history=history,
82
- sys_prompt="总结文章。"
83
- ) # 带超时倒计时
84
- chatbot[-1] = (i_say, gpt_say)
85
- history.append(i_say)
86
- history.append(gpt_say)
87
- yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
88
  res = write_results_to_file(history)
89
  chatbot.append(("完成了吗?", res))
90
- yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面
 
 
 
 
91
 
92
 
93
  @CatchException
@@ -123,11 +111,11 @@ def 总结word文档(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_pr
123
  return
124
 
125
  # 搜索需要处理的文件清单
126
- file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.docx', recursive=True)] + \
127
- [f for f in glob.glob(f'{project_folder}/**/*.doc', recursive=True)]
128
- # [f for f in glob.glob(f'{project_folder}/**/*.tex', recursive=True)] + \
129
- # [f for f in glob.glob(f'{project_folder}/**/*.cpp', recursive=True)] + \
130
- # [f for f in glob.glob(f'{project_folder}/**/*.c', recursive=True)]
131
 
132
  # 如果没找到任何文件
133
  if len(file_manifest) == 0:
 
8
  import time, os
9
  # pip install python-docx 用于docx格式,跨平台
10
  # pip install pywin32 用于doc格式,仅支持Win平台
 
 
11
  for index, fp in enumerate(file_manifest):
12
  if fp.split(".")[-1] == "docx":
13
  from docx import Document
 
27
  word.Quit()
28
 
29
  print(file_content)
 
 
30
  # private_upload里面的文件名在解压zip后容易出现乱码(rar和7z格式正常),故可以只分析文章内容,不输入文件名
31
+ from .crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf
32
+ from request_llm.bridge_all import model_info
33
+ max_token = model_info[llm_kwargs['llm_model']]['max_token']
34
+ TOKEN_LIMIT_PER_FRAGMENT = max_token * 3 // 4
35
+ paper_fragments = breakdown_txt_to_satisfy_token_limit_for_pdf(
36
+ txt=file_content,
37
+ get_token_fn=model_info[llm_kwargs['llm_model']]['token_cnt'],
38
+ limit=TOKEN_LIMIT_PER_FRAGMENT
39
+ )
40
+ this_paper_history = []
41
+ for i, paper_frag in enumerate(paper_fragments):
42
+ i_say = f'请对下面的文章片段用中文做概述,文件名是{os.path.relpath(fp, project_folder)},文章内容是 ```{paper_frag}```'
43
+ i_say_show_user = f'请对下面的文章片段做概述: {os.path.abspath(fp)}的第{i+1}/{len(paper_fragments)}个片段。'
44
  gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
45
  inputs=i_say,
46
  inputs_show_user=i_say_show_user,
 
48
  chatbot=chatbot,
49
  history=[],
50
  sys_prompt="总结文章。"
51
+ )
52
+
53
  chatbot[-1] = (i_say_show_user, gpt_say)
54
+ history.extend([i_say_show_user,gpt_say])
55
+ this_paper_history.extend([i_say_show_user,gpt_say])
 
 
 
 
 
 
 
 
56
 
57
+ # 已经对该文章的所有片段总结完毕,如果文章被切分了,
58
+ if len(paper_fragments) > 1:
59
+ i_say = f"根据以上的对话,总结文章{os.path.abspath(fp)}的主要内容。"
60
+ gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
61
+ inputs=i_say,
62
+ inputs_show_user=i_say,
63
+ llm_kwargs=llm_kwargs,
64
+ chatbot=chatbot,
65
+ history=this_paper_history,
66
+ sys_prompt="总结文章。"
67
+ )
68
+
69
+ history.extend([i_say,gpt_say])
70
+ this_paper_history.extend([i_say,gpt_say])
71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  res = write_results_to_file(history)
73
  chatbot.append(("完成了吗?", res))
74
+ yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
75
+
76
+ res = write_results_to_file(history)
77
+ chatbot.append(("所有文件都总结完成了吗?", res))
78
+ yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
79
 
80
 
81
  @CatchException
 
111
  return
112
 
113
  # 搜索需要处理的文件清单
114
+ if txt.endswith('.docx') or txt.endswith('.doc'):
115
+ file_manifest = [txt]
116
+ else:
117
+ file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.docx', recursive=True)] + \
118
+ [f for f in glob.glob(f'{project_folder}/**/*.doc', recursive=True)]
119
 
120
  # 如果没找到任何文件
121
  if len(file_manifest) == 0:
crazy_functions/批量Markdown翻译.py CHANGED
@@ -13,7 +13,7 @@ class PaperFileGroup():
13
  # count_token
14
  import tiktoken
15
  from toolbox import get_conf
16
- enc = tiktoken.encoding_for_model(*get_conf('LLM_MODEL'))
17
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
18
  self.get_token_num = get_token_num
19
 
 
13
  # count_token
14
  import tiktoken
15
  from toolbox import get_conf
16
+ enc = tiktoken.encoding_for_model("gpt-3.5-turbo")
17
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
18
  self.get_token_num = get_token_num
19
 
crazy_functions/批量翻译PDF文档_多线程.py CHANGED
@@ -69,7 +69,7 @@ def 解析PDF(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot,
69
  # 递归地切割PDF文件
70
  from .crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf
71
  from toolbox import get_conf
72
- enc = tiktoken.encoding_for_model(*get_conf('LLM_MODEL'))
73
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
74
  paper_fragments = breakdown_txt_to_satisfy_token_limit_for_pdf(
75
  txt=file_content, get_token_fn=get_token_num, limit=TOKEN_LIMIT_PER_FRAGMENT)
 
69
  # 递归地切割PDF文件
70
  from .crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf
71
  from toolbox import get_conf
72
+ enc = tiktoken.encoding_for_model("gpt-3.5-turbo")
73
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
74
  paper_fragments = breakdown_txt_to_satisfy_token_limit_for_pdf(
75
  txt=file_content, get_token_fn=get_token_num, limit=TOKEN_LIMIT_PER_FRAGMENT)
crazy_functions/理解PDF文档内容.py CHANGED
@@ -18,7 +18,7 @@ def 解析PDF(file_name, llm_kwargs, plugin_kwargs, chatbot, history, system_pro
18
 
19
  from .crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf
20
  from toolbox import get_conf
21
- enc = tiktoken.encoding_for_model(*get_conf('LLM_MODEL'))
22
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
23
  paper_fragments = breakdown_txt_to_satisfy_token_limit_for_pdf(
24
  txt=file_content, get_token_fn=get_token_num, limit=TOKEN_LIMIT_PER_FRAGMENT)
 
18
 
19
  from .crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf
20
  from toolbox import get_conf
21
+ enc = tiktoken.encoding_for_model("gpt-3.5-turbo")
22
  def get_token_num(txt): return len(enc.encode(txt, disallowed_special=()))
23
  paper_fragments = breakdown_txt_to_satisfy_token_limit_for_pdf(
24
  txt=file_content, get_token_fn=get_token_num, limit=TOKEN_LIMIT_PER_FRAGMENT)
crazy_functions/解析项目源代码.py CHANGED
@@ -12,7 +12,7 @@ def 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs,
12
  sys_prompt_array = []
13
  report_part_1 = []
14
 
15
- assert len(file_manifest) <= 1024, "源文件太多(超过1024个), 请缩减输入文件的数量。或者,您也可以选择删除此行警告,并修改代码拆分file_manifest列表,从而实现分批次处理。"
16
  ############################## <第一步,逐个文件分析,多线程> ##################################
17
  for index, fp in enumerate(file_manifest):
18
  # 读取文件
 
12
  sys_prompt_array = []
13
  report_part_1 = []
14
 
15
+ assert len(file_manifest) <= 512, "源文件太多(超过512个), 请缩减输入文件的数量。或者,您也可以选择删除此行警告,并修改代码拆分file_manifest列表,从而实现分批次处理。"
16
  ############################## <第一步,逐个文件分析,多线程> ##################################
17
  for index, fp in enumerate(file_manifest):
18
  # 读取文件
crazy_functions/询问多个大语言模型.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from toolbox import CatchException, update_ui
2
+ from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive
3
+ import datetime
4
+ @CatchException
5
+ def 同时问询(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
6
+ """
7
+ txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径
8
+ llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行
9
+ plugin_kwargs 插件模型的参数,如温度和top_p等,一般原样传递下去就行
10
+ chatbot 聊天显示框的句柄,用于显示给用户
11
+ history 聊天历史,前情提要
12
+ system_prompt 给gpt的静默提醒
13
+ web_port 当前软件运行的端口号
14
+ """
15
+ history = [] # 清空历史,以免输入溢出
16
+ chatbot.append((txt, "正在同时咨询ChatGPT和ChatGLM……"))
17
+ yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新
18
+
19
+ # llm_kwargs['llm_model'] = 'chatglm&gpt-3.5-turbo&api2d-gpt-3.5-turbo' # 支持任意数量的llm接口,用&符号分隔
20
+ llm_kwargs['llm_model'] = 'chatglm&gpt-3.5-turbo' # 支持任意数量的llm接口,用&符号分隔
21
+ gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
22
+ inputs=txt, inputs_show_user=txt,
23
+ llm_kwargs=llm_kwargs, chatbot=chatbot, history=history,
24
+ sys_prompt=system_prompt,
25
+ retry_times_at_unknown_error=0
26
+ )
27
+
28
+ history.append(txt)
29
+ history.append(gpt_say)
30
+ yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
docs/Dockerfile+ChatGLM ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # How to build | 如何构建: docker build -t gpt-academic --network=host -f Dockerfile+ChatGLM .
2
+ # How to run | 如何运行 (1) 直接运行: docker run --rm -it --net=host --gpus=all gpt-academic
3
+ # How to run | 如何运行 (2) 我想运行之前进容器做一些调整: docker run --rm -it --net=host --gpus=all gpt-academic bash
4
+
5
+ # 从NVIDIA源,从而支持显卡运损(检查宿主的nvidia-smi中的cuda版本必须>=11.3)
6
+ FROM nvidia/cuda:11.3.1-runtime-ubuntu20.04
7
+ ARG useProxyNetwork=''
8
+ RUN apt-get update
9
+ RUN apt-get install -y curl proxychains curl
10
+ RUN apt-get install -y git python python3 python-dev python3-dev --fix-missing
11
+
12
+ # 配置代理网络(构建Docker镜像时使用)
13
+ # # comment out below if you do not need proxy network | 如果不需要翻墙 - 从此行向下删除
14
+ RUN $useProxyNetwork curl cip.cc
15
+ RUN sed -i '$ d' /etc/proxychains.conf
16
+ RUN sed -i '$ d' /etc/proxychains.conf
17
+ RUN echo "socks5 127.0.0.1 10880" >> /etc/proxychains.conf
18
+ ARG useProxyNetwork=proxychains
19
+ # # comment out above if you do not need proxy network | 如果不需要翻墙 - 从此行向上删除
20
+
21
+
22
+ # use python3 as the system default python
23
+ RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.8
24
+
25
+ # 下载分支
26
+ WORKDIR /gpt
27
+ RUN $useProxyNetwork git clone https://github.com/binary-husky/chatgpt_academic.git -b v3.1
28
+ WORKDIR /gpt/chatgpt_academic
29
+ RUN $useProxyNetwork python3 -m pip install -r requirements.txt
30
+ RUN $useProxyNetwork python3 -m pip install -r request_llm/requirements_chatglm.txt
31
+ RUN $useProxyNetwork python3 -m pip install torch --extra-index-url https://download.pytorch.org/whl/cu113
32
+
33
+ # 预热CHATGLM参数(非必要 可选步骤)
34
+ RUN echo ' \n\
35
+ from transformers import AutoModel, AutoTokenizer \n\
36
+ chatglm_tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True) \n\
37
+ chatglm_model = AutoModel.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True).float() ' >> warm_up_chatglm.py
38
+ RUN python3 -u warm_up_chatglm.py
39
+ RUN $useProxyNetwork git pull
40
+
41
+ # 为chatgpt-academic配置代理和API-KEY (非必要 可选步骤)
42
+ RUN echo ' \n\
43
+ API_KEY = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \n\
44
+ USE_PROXY = True \n\
45
+ LLM_MODEL = "chatglm" \n\
46
+ LOCAL_MODEL_DEVICE = "cuda" \n\
47
+ proxies = { "http": "socks5h://localhost:10880", "https": "socks5h://localhost:10880", } ' >> config_private.py
48
+
49
+ # 启动
50
+ CMD ["python3", "-u", "main.py"]
{img → docs}/README_EN.md RENAMED
File without changes
{img → docs}/demo.jpg RENAMED
File without changes
{img → docs}/demo2.jpg RENAMED
File without changes
docs/self_analysis.md ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # chatgpt-academic项目自译解报告
2
+ (Author补充:以下分析均由本项目调用ChatGPT一键生成,如果有不准确的地方,全怪GPT😄)
3
+
4
+ ## 对程序的整体功能和构架做出概括。然后用一张markdown表格整理每个文件的功能。
5
+
6
+ 整体概括:
7
+
8
+ 该程序是一个基于自然语言处理和机器学习的科学论文辅助工具,主要功能包括聊天机器人、批量总结PDF文档、批量翻译PDF文档、生成函数注释、解析项目源代码等。程序基于 Gradio 构建 Web 服务,并集成了代理和自动更新功能,提高了用户的使用体验。
9
+
10
+ 文件功能表格:
11
+
12
+ | 文件名 | 文件功能 |
13
+ | --- | --- |
14
+ | check_proxy.py | 用于检查代理的正确性和可用性 |
15
+ | colorful.py | 包含不同预设置颜色的常量,并用于多种UI元素 |
16
+ | config.py | 用于全局配置的类 |
17
+ | config_private.py | 与config.py文件一起使用的另一个配置文件,用于更改私密信息 |
18
+ | core_functional.py | 包含一些TextFunctional类和基础功能函数 |
19
+ | crazy_functional.py | 包含大量高级功能函数和实验性的功能函数 |
20
+ | main.py | 程序的主入口,包含GUI主窗口和主要的UI管理功能 |
21
+ | theme.py | 包含一些预设置主题的颜色 |
22
+ | toolbox.py | 提供了一些有用的工具函数 |
23
+ | crazy_functions\crazy_utils.py | 包含一些用于实现高级功能的辅助函数 |
24
+ | crazy_functions\Latex全文润色.py | 实现了对LaTeX文件中全文的润色和格式化功能 |
25
+ | crazy_functions\Latex全文翻译.py | 实现了对LaTeX文件中的内容进行翻译的功能 |
26
+ | crazy_functions\_\_init\_\_.py | 用于导入crazy_functional.py中的功能函数 |
27
+ | crazy_functions\下载arxiv论文翻译摘要.py | 从Arxiv上下载论文并提取重要信息 |
28
+ | crazy_functions\代码重写为全英文_多线程.py | 针对中文Python文件,将其翻译为全英文 |
29
+ | crazy_functions\总结word文档.py | 提取Word文件的重要内容来生成摘要 |
30
+ | crazy_functions\批量Markdown翻译.py | 批量翻译Markdown文件 |
31
+ | crazy_functions\批量总结PDF文档.py | 批量从PDF文件中提取摘要 |
32
+ | crazy_functions\批量总结PDF文档pdfminer.py | 批量从PDF文件中提取摘要 |
33
+ | crazy_functions\批量翻译PDF文档_多线程.py | 批量翻译PDF文件 |
34
+ | crazy_functions\理解PDF文档内容.py | 批量分析PDF文件并提取摘要 |
35
+ | crazy_functions\生成函数注释.py | 自动生成Python文件中函数的注释 |
36
+ | crazy_functions\解析项目源代码.py | 解析并分析给定项目的源代码 |
37
+ | crazy_functions\询问多个大语言模型.py | 向多个大语言模型询问输入文本并进行处理 |
38
+ | crazy_functions\读文献写摘要.py | 根据用户输入读取文献内容并生成摘要 |
39
+ | crazy_functions\谷歌检索小助手.py | 利用谷歌学术检索用户提供的论文信息并提取相关信息 |
40
+ | crazy_functions\高级功能函数模板.py | 实现高级功能的模板函数 |
41
+ | request_llm\bridge_all.py | 处理与LLM的交互 |
42
+ | request_llm\bridge_chatglm.py | 使用ChatGLM模型进行聊天 |
43
+ | request_llm\bridge_chatgpt.py | 实现对话生成的各项功能 |
44
+ | request_llm\bridge_tgui.py | 在Websockets中与用户进行交互并生成文本输出 |
45
+
46
+
47
+
48
+ ## [0/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\check_proxy.py
49
+
50
+ 该文件主要包括四个函数:check_proxy、backup_and_download、patch_and_restart 和 auto_update。其中,check_proxy 函数用于检查代理是否可用;backup_and_download 用于进行一键更新备份和下载;patch_and_restart 是一键更新协议的重要函数,用于覆盖和重启;auto_update 函数用于查询版本和用户意见,并自动进行一键更新。该文件主要使用了 requests、json、shutil、zipfile、distutils、subprocess 等 Python 标准库和 toolbox 和 colorful 两个第三方库。
51
+
52
+ ## [1/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\colorful.py
53
+
54
+ 该程序文件实现了一些打印文本的函数,使其具有不同的颜色输出。当系统为Linux时直接跳过,否则使用colorama库来实现颜色输出。程序提供了深色和亮色两种颜色输出方式,同时也提供了对打印函数的别名。对于不是终端输出的情况,对所有的打印函数进行重复定义,以便在重定向时能够避免打印错误日志。
55
+
56
+ ## [2/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\config.py
57
+
58
+ 该程序文件是一个配置文件,其主要功能是提供使用API密钥等信息,以及对程序的体验进行优化,例如定义对话框高度、布局等。还包含一些其他的设置,例如设置并行使用的线程数、重试次数限制等等。
59
+
60
+ ## [3/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\config_private.py
61
+
62
+ 这是一个名为config_private.py的Python文件,它用于配置API_KEY和代理信息。API_KEY是一个私密密钥,用于访���某些受保护的API。USE_PROXY变量设置为True以应用代理,proxies变量配置了代理网络的地址和协议。在使用该文件时,需要填写正确的API_KEY和代理信息。
63
+
64
+ ## [4/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\core_functional.py
65
+
66
+ 该文件是一个Python模块,名为"core_functional.py"。模块中定义了一个字典,包含了各种核心功能的配置信息,如英语学术润色、中文学术润色、查找语法错误等。每个功能都包含一些前言和后语,在前言中描述了该功能的任务和要求,在后语中提供一些附加信息。此外,有些功能还定义了一些特定的处理函数和按钮颜色。
67
+
68
+ ## [5/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functional.py
69
+
70
+ 这是一个Python程序文件,文件名是crazy_functional.py。它导入了一个名为HotReload的工具箱,并定义了一个名为get_crazy_functions()的函数。这个函数包括三个部分的插件组,分别是已经编写完成的第一组插件、已经测试但距离完美状态还差一点点的第二组插件和尚未充分测试的第三组插件。每个插件都有一个名称、一个按钮颜色、一个函数和一个是否加入下拉菜单中的标志位。这些插件提供了多种功能,包括生成函数注释、解析项目源代码、批量翻译PDF文档、谷歌检索、PDF文档内容理解和Latex文档的全文润色、翻译等功能。其中第三组插件可能还存在一定的bug。
71
+
72
+ ## [6/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\main.py
73
+
74
+ 该Python脚本代码实现了一个用于交互式对话的Chatbot机器人。它使用了Gradio框架来构建一个Web界面,并在此基础之上嵌入了一个文本输入框和与Chatbot进行交互的其他控件,包括提交、重置、停止和清除按钮、选择框和滑块等。此外,它还包括了一些类和函数和一些用于编程分析的工具和方法。整个程序文件的结构清晰,注释丰富,并提供了很多技术细节,使得开发者可以很容易地在其基础上进行二次开发、修改、扩展和集成。
75
+
76
+ ## [7/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\theme.py
77
+
78
+ 该程序文件名为theme.py,主要功能为调节Gradio的全局样式。在该文件中,调节了Gradio的主题颜色、字体、阴影、边框、渐变等等样式。同时,该文件还添加了一些高级CSS样式,比如调整表格单元格的背景和边框,设定聊天气泡的圆角、最大宽度和阴影等等。如果CODE_HIGHLIGHT为True,则还进行了代码高亮显示。
79
+
80
+ ## [8/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\toolbox.py
81
+
82
+ 这是一个名为`toolbox.py`的源代码文件。该文件包含了一系列工具函数和装饰器,用于聊天Bot的开发和调试。其中有一些功能包括将输入参数进行重组、捕捉函数中的异常并记录到历史记录中、生成Markdown格式的聊天记录报告等。该文件中还包含了一些与转换Markdown文本相关的函数。
83
+
84
+ ## [9/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\crazy_utils.py
85
+
86
+ 这是一个Python程序文件 `crazy_utils.py`,它包含了两个函数:
87
+
88
+ - `input_clipping(inputs, history, max_token_limit)`:这个函数接收三个参数,inputs 是一个字符串,history 是一个列表,max_token_limit 是一个整数。它使用 `tiktoken` 、`numpy` 和 `toolbox` 模块,处理输入文本和历史记录,将其裁剪到指定的最大标记数,避免输入过长导致的性能问题。如果 inputs 长度不超过 max_token_limit 的一半,则只裁剪历史;否则,同时裁剪输入和历史。
89
+ - `request_gpt_model_in_new_thread_with_ui_alive(inputs, inputs_show_user, llm_kwargs, chatbot, history, sys_prompt, refresh_interval=0.2, handle_token_exceed=True, retry_times_at_unknown_error=2)`:这个函数接收八个参数,其中后三个是列表类型,其他为标量或句柄等。它提供对话窗口和刷新控制,执行 `predict_no_ui_long_connection` 方法,将输入数据发送至 GPT 模型并获取结果,如果子任务出错,返回相应的错误信息,否则返回结果。
90
+
91
+ ## [10/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\Latex全文润色.py
92
+
93
+ 这是一个名为"crazy_functions\Latex全文润色.py"的程序文件,其中包含了两个函数"Latex英文润色"和"Latex中文润色",以及其他辅助函数。这些函数能够对 Latex 项目进行润色处理,其中 "多文件润色" 函数是一个主要函数,它调用了其他辅助函数用于读取和处理 Latex 项目中的文件。函数使用了多线程和机器学习模型进行自然语言处理,对文件进行简化和排版来满足学术标准。注释已删除并可以在函数内部查找。
94
+
95
+ ## [11/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\Latex全文翻译.py
96
+
97
+ 这个程序文件包括一个用于对整个Latex项目进行翻译的函数 `Latex英译中` 和一个用于将中文翻译为英文的函数 `Latex中译英`。这两个函数都会尝试导入依赖库 tiktoken, 若无法导入则会提示用户安装。`Latex英译中` 函数会对 Latex 项目中的文件进行分离并去除注释,然后运行多线程翻译。`Latex中译英` 也做同样的事情,只不过是将中文翻译为英文。这个程序文件还包括其他一些帮助函数。
98
+
99
+ ## [12/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\__init__.py
100
+
101
+ 这是一个 Python 包,包名为 `crazy_functions`,在 `__init__.py` 文件中定义了一些函数,包含以下函数:
102
+
103
+ - `crazy_addition(a, b)`:对两个数进行加法运算,并将结果返回。
104
+ - `crazy_multiplication(a, b)`:对两个数进行乘法运算,并将结果返回。
105
+ - `crazy_subtraction(a, b)`:对两个数进行减法运算,并将结果返回。
106
+ - `crazy_division(a, b)`:对两个数进行除法运算,并将结果返回。
107
+ - `crazy_factorial(n)`:计算 `n` 的阶乘并返回结果。
108
+
109
+ 这些函数可能会有一些奇怪或者不符合常规的实现方式(由函数名可以看出来),所以这个包的名称为 `crazy_functions`,可能是暗示这些函数会有一些“疯狂”的实现方式。
110
+
111
+ ## [13/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\下载arxiv论文翻译摘要.py
112
+
113
+ 该程序实现了一个名为“下载arxiv论文并翻译摘要”的函数插件,作者是“binary-husky”。该函数的功能是,在输入一篇arxiv论文的链接后,提取摘要、下载PDF文档、翻译摘要为中文,并将翻译结果保存到文件中。程序使用了一些Python库,如requests、pdfminer和beautifulsoup4等。程序入口是名为“下载arxiv论文并翻译摘要”的函数,其中使用了自定义的辅助函数download_arxiv_和get_name。程序中还使用了其他非函数的辅助函数和变量,如update_ui、CatchException、report_exception和get_conf等。
114
+
115
+ ## [14/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\代码重写为全英文_多线程.py
116
+
117
+ 该文件是一个多线程Python脚本,包含多个函数和利用第三方库进行的API请求。主要功能是将给定文件夹内的Python代码文件中所有中文转化为英文,然后输出转化后的英文代码。重要的功能和步骤包括:
118
+
119
+ 1. 清空历史,以免输入溢出
120
+ 2. 尝试导入依赖,如果缺少依赖,则给出安装建议
121
+ 3. 集合文件
122
+ 4. 显示随意内容以防卡顿的感觉
123
+ 5. Token限制下的截断与处理
124
+ 6. 多线程操作请求转换中文变为英文的代码
125
+ 7. 所有线程同时开始执行任务函数
126
+ 8. 循环轮询各个线程是否执行完毕
127
+ 9. 把结果写入文件
128
+ 10. 备份一个文件
129
+
130
+ ## [15/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\总结word文档.py
131
+
132
+ 这是一个名为"总结word文档.py"的程序文件,使用python编写。该文件导入了"toolbox"和"crazy_utils"模块,实现了解析docx格式和doc格式的文件的功能。该文件包含了一个名为"解析docx"的函数,通过对文件内容应用自然语言处理技术,生成文章片段的中英文概述。具体实现过程中,该函数使用了"docx"模块和"win32com.client"模块来实现对docx和doc格式文件的解析,同时使用了"request_gpt_model_in_new_thread_with_ui_alive"函数来向GPT模型发起请求。最后,该文件还实现了一个名为"总结word文档"的函数来批量总结Word文档。
133
+
134
+ ## [16/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\批量Markdown翻译.py
135
+
136
+ 这个程序文件实现了一个批量Markdown翻译功能,可以将一个源代码项目中的Markdown文本翻译成指定语言(目前支持中<-英和英<-中)。程序主要分为三个函数,`PaperFileGroup`类用于处理长文本的拆分,`多文件翻译`是主要函数调用了`request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency`函数进行多线程翻译并输出结果,`Markdown英译中`和`Markdown中译外`分别是英译中和中译英的入口函数,用于解析项目路径和调用翻译函数。程序依赖于tiktoken等库实现。
137
+
138
+ ## [17/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\批量总结PDF文档.py
139
+
140
+ 这是一个名为“批量总结PDF文档”的Python脚本,包含了多个函数。其中有一个函数名为“clean_text”,可以对PDF提取出的原始文本进行清洗和格式化处理,将连字转换为其基本形式,并根据heuristic规则判断换行符是否是段落分隔,并相应地进行替换。另一个函数名为“解析PDF”,可以接收一个PDF文件清单,并对清单中的每一个PDF进行解析,提取��文本并调用“clean_text”函数进行清洗和格式化处理,然后向用户发送一个包含文章简介信息的问题并等待用户回答。最后,该脚本也包含一个名为“批量总结PDF文档”的主函数,其中调用了“解析PDF”函数来完成对PDF文件的批量处理。
141
+
142
+ ## [18/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\批量总结PDF文档pdfminer.py
143
+
144
+ 这个文件是一个Python模块,文件名为pdfminer.py,它定义了一个函数批量总结PDF文档。该函数接受一些参数,然后尝试导入pdfminer和beautifulsoup4库。该函数将读取pdf文件或tex文件中的内容,对其进行分析,并使用GPT模型进行自然语言摘要。文件中还有一个辅助函数readPdf,用于读取pdf文件中的内容。
145
+
146
+ ## [19/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\批量翻译PDF文档_多线程.py
147
+
148
+ 这是一个Python脚本,文件名是crazy_functions\批量翻译PDF文档_多线程.py。该脚本提供了一个名为“批量翻译PDF文档”的函数,可以批量翻译PDF文件并生成报告文件。该函数使用了多个模块和函数(如toolbox、crazy_utils、update_ui等),使用了Python的异常处理和多线程功能,还使用了一些文本处理函数和第三方库(如fitz和tiktoken)。在函数执行过程中,它会进行一些参数检查、读取和清理PDF文本、递归地切割PDF文件、获取文章meta信息、多线程翻译、整理报告格式等操作,并更新UI界面和生成报告文件。
149
+
150
+ ## [20/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\理解PDF文档内容.py
151
+
152
+ 这是一个解析PDF文件内容的Python程序,程序文件名为"理解PDF文档内容.py",程序主要由5个步骤组成:第0步是切割PDF文件;第1步是从摘要中提取高价值信息,放到history中;第2步是迭代地历遍整个文章,提取精炼信息;第3步是整理history;第4步是设置一个token上限,防止回答时Token溢出。程序主要用到了Python中的各种模块和函数库,如:toolbox, tiktoken, pymupdf等。
153
+
154
+ ## [21/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\生成函数注释.py
155
+
156
+ 这是一个名为"生成函数注释"的函数,带有一个装饰器"@CatchException",可以捕获异常。该函数接受文件路径、参数和聊天机器人等参数,用于对多个Python或C++文件进行函数注释,使用了"toolbox"和"crazy_utils"模块中的函数。该函数会逐个读取指定文件中的内容,并使用聊天机器人进行交互,向用户请求注释信息,然后将生成的注释与原文件内容一起输出到一个markdown表格中。最后,该函数返回一个字符串,指示任务是否已完成。另外还包含一个名为"批量生成函数注释"的函数,它与"生成函数注释"函数一起用于批量处理多个文件。
157
+
158
+ ## [22/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\解析项目源代码.py
159
+
160
+ 这个程序文件实现了对一个源代码项目进行分析的功能。其中,函数`解析项目本身`、`解析一个Python项目`、`解析一个C项目的头文件`、`解析一个C项目`、`解析一个Java项目`和`解析一个Rect项目`分别用于解析不同类型的项目。函数`解析源代码新`实现了对每一个源代码文件的分析,并将分析结果汇总,同时还实现了分组和迭代处理,提高了效率。最后,函数`write_results_to_file`将所有分析结果写入文件。中间,还用到了`request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency`和`request_gpt_model_in_new_thread_with_ui_alive`来完成请求和响应,并用`update_ui`实时更新界面。
161
+
162
+ ## [23/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\询问多个大语言模型.py
163
+
164
+ 这是一个Python程序,文件名为"crazy_functions\询问多个大语言模型.py"。该程序实现了一个同时向多个大语言模型询问的功能,接收用户输入文本以及模型参数,向ChatGPT和ChatGLM模型发出请求,并将对话记录显示在聊天框中,同时刷新界面。
165
+
166
+ ## [24/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\读文章写摘要.py
167
+
168
+ 该程序文件是一个Python模块,文件名为"读文章写摘要.py",主要包含两个函数:"解析Paper"和"读文章写摘要"。其中,"解析Paper"函数接受文件路径、参数等参数,逐个打印文件内容并使用GPT模型生成对该文件的摘要;"读文章写摘要"函数则接受一段文本内容和参数,将该文本内容及其所有.tex文件逐个传递给"解析Paper"函数进行处理,并使用GPT模型生成文章的中英文摘要。文件还导入了一些工具函数,如异常处理、信息上报和文件写入等。
169
+
170
+ ## [25/31] 请对下面��程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\谷歌检索小助手.py
171
+
172
+ 该文件代码包含了一个名为`get_meta_information`的函数和一个名为`谷歌检索小助手`的装饰器函数,用于从谷歌学术中抓取文章元信息,并从用户提供的搜索页面中分析所有文章的相关信息。该文件使用了许多第三方库,如requests、arxiv、BeautifulSoup等。其中`get_meta_information`函数中还定义了一个名为`string_similar`的辅助函数,用于比较字符串相似度。
173
+
174
+ ## [26/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\crazy_functions\高级功能函数模板.py
175
+
176
+ 该程序文件是一个 Python 模块,包含一个名为“高阶功能模板函数”的函数。该函数接受多个参数,其中包括输入文本、GPT 模型参数、插件模型参数、聊天显示框、聊天历史等。 该函数的主要功能是根据输入文本,使用 GPT 模型生成一些问题,并等待用户回答这些问题(使用 Markdown 格式),然后将用户回答加入到聊天历史中,并更新聊天显示框。该函数还包含了一些异常处理和多线程的相关操作。该程序文件还引用了另一个 Python 模块中的两个函数,分别为“CatchException”和“update_ui”,并且还引用了一个名为“request_gpt_model_in_new_thread_with_ui_alive”的自定义函数。
177
+
178
+ ## [27/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\request_llm\bridge_all.py
179
+
180
+ 这个文件是用来处理与LLM的交互的。包含两个函数,一个是 predict_no_ui_long_connection 用来处理长文本的输出,可以多线程调用;另一个是 predict 用来处理基础的对话功能。这个文件会导入其他文件中定义的方法进行调用,具体调用哪个方法取决于传入的参数。函数中还有一些装饰器和管理多线程的逻辑。
181
+
182
+ ## [28/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\request_llm\bridge_chatglm.py
183
+
184
+ 这个程序文件实现了一个使用ChatGLM模型进行聊天的功能。具体实现过程是:首先进行初始化,然后使用GetGLMHandle类进行ChatGLM模型的加载和运行。predict_no_ui_long_connection函数用于多线程聊天,而predict函数用于单线程聊天,它们的不同之处在于前者不会更新UI界面,后者会。这个文件还导入了其他模块和库,例如transformers、time、importlib等,并使用了多进程Pipe。
185
+
186
+ ## [29/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\request_llm\bridge_chatgpt.py
187
+
188
+ 这个程序文件是用于对话生成的,主要包含三个函数:predict、predict_no_ui、predict_no_ui_long_connection。其中,predict是用于普通对话的函数,具备完备的交互功能,但不具备多线程能力;predict_no_ui是高级实验性功能模块调用的函数,参数简单,可以多线程并行,方便实现复杂的功能逻辑;predict_no_ui_long_connection解决了predict_no_ui在处理长文档时容易断开连接的问题,同样支持多线程。程序中还包含一些常量和工具函数,用于整合信息,选择LLM模型,生成http请求,发送请求,接收响应等。它需要配置一个config文件,包含代理网址、API等敏感信息。
189
+
190
+ ## [30/31] 请对下面的程序文件做一个概述: H:\chatgpt_academic_resolve\request_llm\bridge_tgui.py
191
+
192
+ 该程序文件实现了一个基于Websockets的文本生成服务和对话功能。其中,有三个函数:`run()`、`predict()`和`predict_no_ui_long_connection()`。`run()`函数用于连接到Websocket服务并生成文本结果;`predict()`函数用于将用户输入作为文本生成的输入,同时在UI上显示对话历史记录,并在不断更新UI的过程中不断更新生成的文本输出;`predict_no_ui_long_connection()`函数与`predict()`函数类似,但没有UI,并在一段时间内返回单个生成的文本。整个程序还引入了多个Python模块来完成相关功能,例如`asyncio`、`websockets`、`json`等等。
193
+
194
+ ## 根据以上分析,对程序的整体功能和构架重新做出概括。然后用一张markdown表格整理每个文件的功能(包括check_proxy.py, colorful.py, config.py, config_private.py, core_functional.py, crazy_functional.py, main.py, theme.py, toolbox.py, crazy_functions\crazy_utils.py, crazy_functions\Latex全文润色.py, crazy_functions\Latex全文翻译.py, crazy_functions\__init__.py, crazy_functions\下载arxiv论文翻译摘要.py, crazy_functions\代码重写为全英文_多线程.py, crazy_functions\总结word文档.py)。
195
+
196
+ 程序功能概括:该程序是一个聊天机器人,可以通过 Web 界面与用户进行交互。它包含了丰富的功能,如文本润色、翻译、代码重写、在线查找等,并且支持多线程处理。用户可以通过 Gradio 框架提供的 Web 界面进行交互,程序还提供了一些调试工具,如toolbox 模块,方便程序开发和调试。
197
+
198
+ ���表概述了每个文件的功能:
199
+
200
+ | 文件名 | 功能 |
201
+ | ----------------------------------------------------------- | ------------------------------------------------------------ |
202
+ | check_proxy.py | 检查代理是否可用 |
203
+ | colorful.py | 用于打印文本的字体颜色输出模块 |
204
+ | config.py | 用于程序中的各种设置,如并行线程数量和重试次数的限制等 |
205
+ | config_private.py | 配置API_KEY和代理信息的文件 |
206
+ | core_functional.py | 包含具体的文本处理功能的模块 |
207
+ | crazy_functional.py | 包括各种插件函数的模块,提供了多种文本处理功能 |
208
+ | main.py | 包含 Chatbot 机器人主程序的模块 |
209
+ | theme.py | 用于调节全局样式的模块 |
210
+ | toolbox.py | 包含工具函数和装饰器,用于聊天Bot的开发和调试 |
211
+ | crazy_functions\crazy_utils.py | 包含一些辅助函数,如文本裁剪和消息捕捉等 |
212
+ | crazy_functions\Latex全文润色.py | 对 Latex 项目进行润色处理的功能模块 |
213
+ | crazy_functions\Latex全文翻译.py | 对 Latex 项目进行翻译的功能模块 |
214
+ | crazy_functions\__init__.py | 定义一些奇特的数学函数等 |
215
+ | crazy_functions\下载arxiv论文翻译摘要.py | 下载 Arxiv 论文并翻译摘要的功能模块 |
216
+ | crazy_functions\代码重写为全英文_多线程.py | 将Python程序中所有中文转化为英文的功能模块 |
217
+ | crazy_functions\总结word文档.py | 解析 docx 和 doc 格式的文件,生成文章片段的中英文概述的功能模块 |
218
+
219
+ ## 根据以上分析,对程序的整体功能和构架重新做出概括。然后用一张markdown表格整理每个文件的功能(包括check_proxy.py, colorful.py, config.py, config_private.py, core_functional.py, crazy_functional.py, main.py, theme.py, toolbox.py, crazy_functions\crazy_utils.py, crazy_functions\Latex全文润色.py, crazy_functions\Latex全文翻译.py, crazy_functions\__init__.py, crazy_functions\下载arxiv论文翻译摘要.py, crazy_functions\代码重写为全英文_多线程.py, crazy_functions\总结word文档.py, crazy_functions\批量Markdown翻译.py, crazy_functions\批量总结PDF文档.py, crazy_functions\批量总结PDF文档pdfminer.py, crazy_functions\批量翻译PDF文档_多线程.py, crazy_functions\理解PDF文档内容.py, crazy_functions\生成函数注释.py, crazy_functions\解析项目源代码.py, crazy_functions\询问多个大语言模型.py, crazy_functions\读文章写摘要.py, crazy_functions\谷歌检索小助手.py, crazy_functions\高级功能函数模板.py, request_llm\bridge_all.py, request_llm\bridge_chatglm.py, request_llm\bridge_chatgpt.py, request_llm\bridge_tgui.py)。
220
+
221
+ 根据以上分析,整个程序是一个集成了多个有用工具和功能的文本处理和生成工具,提供了多种在不同场景下使用的功能,包括但不限于对话生成、文本摘要、PDF文件批量处理、代码翻译和实用工具等。主要的Python模块包括"toolbox.py"、"config.py"、"core_functional.py"和"crazy_functional.py"等,并且还使用了许多第三方库和模块实现相关功能。以下是每个程序文件的功能:
222
+
223
+ | 文件名 | 文件功能 |
224
+ | --- | --- |
225
+ | check_proxy.py | 用于检查代理的正确性和可用性 |
226
+ | colorful.py | 包含不同预设置颜色的常量,并用于多种UI元素 |
227
+ | config.py | 用于全局配置的类 |
228
+ | config_private.py | 与config.py文件一起使用的另一个配置文件,用于更改私密信息 |
229
+ | core_functional.py | 包含一些TextFunctional类和基础功能函数 |
230
+ | crazy_functional.py | 包含大量高级功能函数和实验性的功能函数 |
231
+ | main.py | 程序的主入口,包含GUI主窗口和主要的UI管理功能 |
232
+ | theme.py | 包含一些预设置主题的颜色 |
233
+ | toolbox.py | 提供了一些有用的工具函数 |
234
+ | crazy_functions\crazy_utils.py | 包含一些用于实现高级功能的辅助函数 |
235
+ | crazy_functions\Latex全文润色.py | 实现了对LaTeX文件中全文的润色和格式化功能 |
236
+ | crazy_functions\Latex全文翻译.py | 实现了对LaTeX文件中的内容进行翻译的功能 |
237
+ | crazy_functions\_\_init\_\_.py | 用于导入crazy_functional.py中的功能函数 |
238
+ | crazy_functions\下载arxiv论文翻译摘要.py | 从Arxiv上下载论文并提取重要信息 |
239
+ | crazy_functions\代码重写为全英文_多线程.py | 针对中文Python文件,将其翻译为全英文 |
240
+ | crazy_functions\总结word文档.py | 提取Word文件的重要内容来生成摘要 |
241
+ | crazy_functions\批量Markdown翻译.py | 批量翻译Markdown文件 |
242
+ | crazy_functions\批量总结PDF文档.py | 批量从PDF文件中提取摘要 |
243
+ | crazy_functions\批量总结PDF文档pdfminer.py | 批量从PDF文件中提取摘要 |
244
+ | crazy_functions\批量翻译PDF文档_多线程.py | 批量翻译PDF文件 |
245
+ | crazy_functions\理解PDF文档内容.py | 批量分析PDF文件并提取摘要 |
246
+ | crazy_functions\生成函数注释.py | 自动生成Python文件中函数的注释 |
247
+ | crazy_functions\解析项目源代码.py | 解析并分析给定项目的源代码 |
248
+ | crazy_functions\询问多个大语言模型.py | 向多个大语言模型询问输入文本并进行处理 |
249
+ | crazy_functions\读文献写摘要.py | 根据用户输入读取文献内容并生成摘要 |
250
+ | crazy_functions\谷歌检索小助手.py | 利用谷歌学术检索用户提供的论文信息并提取相关信息 |
251
+ | crazy_functions\高级功能函数模板.py | 实现高级功能的模板函数 |
252
+ | request_llm\bridge_all.py | 处理与LLM的交互 |
253
+ | request_llm\bridge_chatglm.py | 使用ChatGLM模型进行聊天 |
254
+ | request_llm\bridge_chatgpt.py | 实现对话生成的各项功能 |
255
+ | request_llm\bridge_tgui.py | 在Websockets中与用户进行交互并生成文本输出 |
256
+
main.py CHANGED
@@ -1,175 +1,168 @@
1
  import os; os.environ['no_proxy'] = '*' # 避免代理网络产生意外污染
2
- import gradio as gr
3
- from request_llm.bridge_chatgpt import predict
4
- from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf, ArgsGeneralWrapper, DummyWith
5
 
6
- # 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到
7
- proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, API_KEY = \
8
- get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'API_KEY')
 
 
 
 
9
 
10
- # 如果WEB_PORT是-1, 则随机选取WEB端口
11
- PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT
12
- if not AUTHENTICATION: AUTHENTICATION = None
13
 
14
- from check_proxy import get_current_version
15
- initial_prompt = "Serve me as a writing and programming assistant."
16
- title_html = f"<h1 align=\"center\">ChatGPT 学术优化 {get_current_version()}</h1>"
17
- description = """代码开源和更新[地址🚀](https://github.com/binary-husky/chatgpt_academic),感谢热情的[开发者们❤️](https://github.com/binary-husky/chatgpt_academic/graphs/contributors)"""
18
 
19
- # 问询记录, python 版本建议3.9+(越新越好)
20
- import logging
21
- os.makedirs("gpt_log", exist_ok=True)
22
- try:logging.basicConfig(filename="gpt_log/chat_secrets.log", level=logging.INFO, encoding="utf-8")
23
- except:logging.basicConfig(filename="gpt_log/chat_secrets.log", level=logging.INFO)
24
- print("所有问询记录将自动保存在本地目录./gpt_log/chat_secrets.log, 请注意自我隐私保护哦!")
25
 
26
- # 一些普通功能模块
27
- from core_functional import get_core_functions
28
- functional = get_core_functions()
29
 
30
- # 高级函数插件
31
- from crazy_functional import get_crazy_functions
32
- crazy_fns = get_crazy_functions()
33
 
34
- # 处理markdown文本格式的转变
35
- gr.Chatbot.postprocess = format_io
36
 
37
- # 做一些外观色彩上的调整
38
- from theme import adjust_theme, advanced_css
39
- set_theme = adjust_theme()
40
 
41
- # 代理与自动更新
42
- from check_proxy import check_proxy, auto_update
43
- proxy_info = check_proxy(proxies)
44
 
45
- gr_L1 = lambda: gr.Row().style()
46
- gr_L2 = lambda scale: gr.Column(scale=scale)
47
- if LAYOUT == "TOP-DOWN":
48
- gr_L1 = lambda: DummyWith()
49
- gr_L2 = lambda scale: gr.Row()
50
- CHATBOT_HEIGHT /= 2
51
 
52
- cancel_handles = []
53
- with gr.Blocks(title="ChatGPT 学术优化", theme=set_theme, analytics_enabled=False, css=advanced_css) as demo:
54
- gr.HTML(title_html)
55
- gr.HTML('''<center><a href="https://huggingface.co/spaces/qingxu98/gpt-academic?duplicate=true"><img src="https://bit.ly/3gLdBN6" alt="Duplicate Space"></a>请您打开此页面后务必点击上方的“复制空间”(Duplicate Space)按钮!<font color="#FF00FF">使用时,先在输入框填入API-KEY然后回车。</font><br/>切忌在“复制空间”(Duplicate Space)之前填入API_KEY或进行提问,否则您的API_KEY将极可能被空间所有者攫取!</center>''')
56
- cookies = gr.State({'api_key': API_KEY, 'llm_model': LLM_MODEL})
57
- with gr_L1():
58
- with gr_L2(scale=2):
59
- chatbot = gr.Chatbot()
60
- chatbot.style(height=CHATBOT_HEIGHT)
61
- history = gr.State([])
62
- with gr_L2(scale=1):
63
- with gr.Accordion("输入区", open=True) as area_input_primary:
64
- with gr.Row():
65
- txt = gr.Textbox(show_label=False, placeholder="Input question/api-key here.").style(container=False)
66
- with gr.Row():
67
- submitBtn = gr.Button("提交", variant="primary")
68
- with gr.Row():
69
- resetBtn = gr.Button("重置", variant="secondary"); resetBtn.style(size="sm")
70
- stopBtn = gr.Button("停止", variant="secondary"); stopBtn.style(size="sm")
71
- with gr.Row():
72
- status = gr.Markdown(f"Tip: 按Enter提交, 按Shift+Enter换行。当前模型: {LLM_MODEL} \n {proxy_info}")
73
- with gr.Accordion("基础功能区", open=True) as area_basic_fn:
74
- with gr.Row():
75
- for k in functional:
76
- variant = functional[k]["Color"] if "Color" in functional[k] else "secondary"
77
- functional[k]["Button"] = gr.Button(k, variant=variant)
78
- with gr.Accordion("函数插件区", open=True) as area_crazy_fn:
79
- with gr.Row():
80
- gr.Markdown("注意:以下“红颜色”标识的函数插件需从输入区读取路径作为参数.")
81
- with gr.Row():
82
- for k in crazy_fns:
83
- if not crazy_fns[k].get("AsButton", True): continue
84
- variant = crazy_fns[k]["Color"] if "Color" in crazy_fns[k] else "secondary"
85
- crazy_fns[k]["Button"] = gr.Button(k, variant=variant)
86
- crazy_fns[k]["Button"].style(size="sm")
87
- with gr.Row():
88
- with gr.Accordion("更多函数插件", open=True):
89
- dropdown_fn_list = [k for k in crazy_fns.keys() if not crazy_fns[k].get("AsButton", True)]
90
- with gr.Column(scale=1):
91
- dropdown = gr.Dropdown(dropdown_fn_list, value=r"打开插件列表", label="").style(container=False)
92
- with gr.Column(scale=1):
93
- switchy_bt = gr.Button(r"请先从插件列表中选择", variant="secondary")
94
- with gr.Row():
95
- with gr.Accordion("点击展开“文件上传区”。上传本地文件可供红色函数插件调用。", open=False) as area_file_up:
96
- file_upload = gr.Files(label="任何文件, 但推荐上传压缩文件(zip, tar)", file_count="multiple")
97
- with gr.Accordion("展开SysPrompt & 交互界面布局 & Github地址", open=(LAYOUT == "TOP-DOWN")):
98
- system_prompt = gr.Textbox(show_label=True, placeholder=f"System Prompt", label="System prompt", value=initial_prompt)
99
- top_p = gr.Slider(minimum=-0, maximum=1.0, value=1.0, step=0.01,interactive=True, label="Top-p (nucleus sampling)",)
100
- temperature = gr.Slider(minimum=-0, maximum=2.0, value=1.0, step=0.01, interactive=True, label="Temperature",)
101
- checkboxes = gr.CheckboxGroup(["基础功能区", "函数插件区", "底部输入区"], value=["基础功能区", "函数插件区"], label="显示/隐藏功能区")
102
- gr.Markdown(description)
103
- with gr.Accordion("备选输入区", open=True, visible=False) as area_input_secondary:
104
- with gr.Row():
105
- txt2 = gr.Textbox(show_label=False, placeholder="Input question here.", label="输入区2").style(container=False)
106
- with gr.Row():
107
- submitBtn2 = gr.Button("提交", variant="primary")
108
- with gr.Row():
109
- resetBtn2 = gr.Button("重置", variant="secondary"); resetBtn.style(size="sm")
110
- stopBtn2 = gr.Button("停止", variant="secondary"); stopBtn.style(size="sm")
111
- # 功能区显示开关与功能区的互动
112
- def fn_area_visibility(a):
113
- ret = {}
114
- ret.update({area_basic_fn: gr.update(visible=("基础功能区" in a))})
115
- ret.update({area_crazy_fn: gr.update(visible=("函数插件区" in a))})
116
- ret.update({area_input_primary: gr.update(visible=("底部输入区" not in a))})
117
- ret.update({area_input_secondary: gr.update(visible=("底部输入区" in a))})
118
- if "底部输入区" in a: ret.update({txt: gr.update(value="")})
119
- return ret
120
- checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn, area_input_primary, area_input_secondary, txt, txt2] )
121
- # 整理反复出现的控件句柄组合
122
- input_combo = [cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt]
123
- output_combo = [cookies, chatbot, history, status]
124
- predict_args = dict(fn=ArgsGeneralWrapper(predict), inputs=input_combo, outputs=output_combo)
125
- # 提交按钮、重置按钮
126
- cancel_handles.append(txt.submit(**predict_args))
127
- cancel_handles.append(txt2.submit(**predict_args))
128
- cancel_handles.append(submitBtn.click(**predict_args))
129
- cancel_handles.append(submitBtn2.click(**predict_args))
130
- resetBtn.click(lambda: ([], [], "已重置"), None, [chatbot, history, status])
131
- resetBtn2.click(lambda: ([], [], "已重置"), None, [chatbot, history, status])
132
- # 基础功能区的回调函数注册
133
- for k in functional:
134
- click_handle = functional[k]["Button"].click(fn=ArgsGeneralWrapper(predict), inputs=[*input_combo, gr.State(True), gr.State(k)], outputs=output_combo)
135
- cancel_handles.append(click_handle)
136
- # 文件上传区,接收文件后与chatbot的互动
137
- file_upload.upload(on_file_uploaded, [file_upload, chatbot, txt], [chatbot, txt])
138
- # 函数插件-固定按钮区
139
- for k in crazy_fns:
140
- if not crazy_fns[k].get("AsButton", True): continue
141
- click_handle = crazy_fns[k]["Button"].click(ArgsGeneralWrapper(crazy_fns[k]["Function"]), [*input_combo, gr.State(PORT)], output_combo)
142
- click_handle.then(on_report_generated, [file_upload, chatbot], [file_upload, chatbot])
143
- cancel_handles.append(click_handle)
144
- # 函数插件-下拉菜单与随变按钮的互动
145
- def on_dropdown_changed(k):
146
- variant = crazy_fns[k]["Color"] if "Color" in crazy_fns[k] else "secondary"
147
- return {switchy_bt: gr.update(value=k, variant=variant)}
148
- dropdown.select(on_dropdown_changed, [dropdown], [switchy_bt] )
149
- # 随变按钮的回调函数注册
150
- def route(k, *args, **kwargs):
151
- if k in [r"打开插件列表", r"请先从插件列表中选择"]: return
152
- yield from ArgsGeneralWrapper(crazy_fns[k]["Function"])(*args, **kwargs)
153
- click_handle = switchy_bt.click(route,[switchy_bt, *input_combo, gr.State(PORT)], output_combo)
154
- click_handle.then(on_report_generated, [file_upload, chatbot], [file_upload, chatbot])
155
- # def expand_file_area(file_upload, area_file_up):
156
- # if len(file_upload)>0: return {area_file_up: gr.update(open=True)}
157
- # click_handle.then(expand_file_area, [file_upload, area_file_up], [area_file_up])
158
- cancel_handles.append(click_handle)
159
- # 终止按钮的回调函数注册
160
- stopBtn.click(fn=None, inputs=None, outputs=None, cancels=cancel_handles)
161
- stopBtn2.click(fn=None, inputs=None, outputs=None, cancels=cancel_handles)
162
- # gradio的inbrowser触发不太稳定,回滚代码到原始的浏览器打开函数
163
- def auto_opentab_delay():
164
- import threading, webbrowser, time
165
- print(f"如果浏览器没有自动打开,请复制并转到以下URL:")
166
- print(f"\t(亮色主题): http://localhost:{PORT}")
167
- print(f"\t(暗色主题): http://localhost:{PORT}/?__dark-theme=true")
168
- def open():
169
- time.sleep(2) # 打开浏览器
170
- webbrowser.open_new_tab(f"http://localhost:{PORT}/?__dark-theme=true")
171
- threading.Thread(target=open, name="open-browser", daemon=True).start()
172
- threading.Thread(target=auto_update, name="self-upgrade", daemon=True).start()
173
 
174
- auto_opentab_delay()
175
- demo.queue(concurrency_count=CONCURRENT_COUNT).launch(server_name="0.0.0.0", share=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os; os.environ['no_proxy'] = '*' # 避免代理网络产生意外污染
 
 
 
2
 
3
+ def main():
4
+ import gradio as gr
5
+ from request_llm.bridge_all import predict
6
+ from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf, ArgsGeneralWrapper, DummyWith
7
+ # 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到
8
+ proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, API_KEY, AVAIL_LLM_MODELS = \
9
+ get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'API_KEY', 'AVAIL_LLM_MODELS')
10
 
11
+ # 如果WEB_PORT是-1, 则随机选取WEB端口
12
+ PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT
13
+ if not AUTHENTICATION: AUTHENTICATION = None
14
 
15
+ from check_proxy import get_current_version
16
+ initial_prompt = "Serve me as a writing and programming assistant."
17
+ title_html = f"<h1 align=\"center\">ChatGPT 学术优化 {get_current_version()}</h1>"
18
+ description = """代码开源和更新[地址🚀](https://github.com/binary-husky/chatgpt_academic),感谢热情的[开发者们❤️](https://github.com/binary-husky/chatgpt_academic/graphs/contributors)"""
19
 
20
+ # 问询记录, python 版本建议3.9+(越新越好)
21
+ import logging
22
+ os.makedirs("gpt_log", exist_ok=True)
23
+ try:logging.basicConfig(filename="gpt_log/chat_secrets.log", level=logging.INFO, encoding="utf-8")
24
+ except:logging.basicConfig(filename="gpt_log/chat_secrets.log", level=logging.INFO)
25
+ print("所有问询记录将自动保存在本地目录./gpt_log/chat_secrets.log, 请注意自我隐私保护哦!")
26
 
27
+ # 一些普通功能模块
28
+ from core_functional import get_core_functions
29
+ functional = get_core_functions()
30
 
31
+ # 高级函数插件
32
+ from crazy_functional import get_crazy_functions
33
+ crazy_fns = get_crazy_functions()
34
 
35
+ # 处理markdown文本格式的转变
36
+ gr.Chatbot.postprocess = format_io
37
 
38
+ # 做一些外观色彩上的调整
39
+ from theme import adjust_theme, advanced_css
40
+ set_theme = adjust_theme()
41
 
42
+ # 代理与自动更新
43
+ from check_proxy import check_proxy, auto_update
44
+ proxy_info = check_proxy(proxies)
45
 
46
+ gr_L1 = lambda: gr.Row().style()
47
+ gr_L2 = lambda scale: gr.Column(scale=scale)
48
+ if LAYOUT == "TOP-DOWN":
49
+ gr_L1 = lambda: DummyWith()
50
+ gr_L2 = lambda scale: gr.Row()
51
+ CHATBOT_HEIGHT /= 2
52
 
53
+ cancel_handles = []
54
+ with gr.Blocks(title="ChatGPT 学术优化", theme=set_theme, analytics_enabled=False, css=advanced_css) as demo:
55
+ gr.HTML(title_html)
56
+ gr.HTML('''<center><a href="https://huggingface.co/spaces/qingxu98/gpt-academic?duplicate=true"><img src="https://bit.ly/3gLdBN6" alt="Duplicate Space"></a>请您打开此页面后务必点击上方的“复制空间”(Duplicate Space)按钮!<font color="#FF00FF">使用时,先在输入框填入API-KEY然后回车。</font><br/>切忌在“复制空间”(Duplicate Space)之前填入API_KEY或进行提问,否则您的API_KEY将极可能被空间所有者攫取!</center>''')
57
+ cookies = gr.State({'api_key': API_KEY, 'llm_model': LLM_MODEL})
58
+ with gr_L1():
59
+ with gr_L2(scale=2):
60
+ chatbot = gr.Chatbot()
61
+ chatbot.style(height=CHATBOT_HEIGHT)
62
+ history = gr.State([])
63
+ with gr_L2(scale=1):
64
+ with gr.Accordion("输入区", open=True) as area_input_primary:
65
+ with gr.Row():
66
+ txt = gr.Textbox(show_label=False, placeholder="Input question/api-key here.").style(container=False)
67
+ with gr.Row():
68
+ submitBtn = gr.Button("���交", variant="primary")
69
+ with gr.Row():
70
+ resetBtn = gr.Button("重置", variant="secondary"); resetBtn.style(size="sm")
71
+ stopBtn = gr.Button("停止", variant="secondary"); stopBtn.style(size="sm")
72
+ with gr.Row():
73
+ status = gr.Markdown(f"Tip: 按Enter提交, 按Shift+Enter换行。当前模型: {LLM_MODEL} \n {proxy_info}")
74
+ with gr.Accordion("基础功能区", open=True) as area_basic_fn:
75
+ with gr.Row():
76
+ for k in functional:
77
+ variant = functional[k]["Color"] if "Color" in functional[k] else "secondary"
78
+ functional[k]["Button"] = gr.Button(k, variant=variant)
79
+ with gr.Accordion("函数插件区", open=True) as area_crazy_fn:
80
+ with gr.Row():
81
+ gr.Markdown("注意:以下“红颜色”标识的函数插件需从输入区读取路径作为参数.")
82
+ with gr.Row():
83
+ for k in crazy_fns:
84
+ if not crazy_fns[k].get("AsButton", True): continue
85
+ variant = crazy_fns[k]["Color"] if "Color" in crazy_fns[k] else "secondary"
86
+ crazy_fns[k]["Button"] = gr.Button(k, variant=variant)
87
+ crazy_fns[k]["Button"].style(size="sm")
88
+ with gr.Row():
89
+ with gr.Accordion("更多函数插件", open=True):
90
+ dropdown_fn_list = [k for k in crazy_fns.keys() if not crazy_fns[k].get("AsButton", True)]
91
+ with gr.Column(scale=1):
92
+ dropdown = gr.Dropdown(dropdown_fn_list, value=r"打开插件列表", label="").style(container=False)
93
+ with gr.Column(scale=1):
94
+ switchy_bt = gr.Button(r"请先从插件列表中选择", variant="secondary")
95
+ with gr.Row():
96
+ with gr.Accordion("点击展开“文件上传区”。上传本地文件可供红色函数插件调用。", open=False) as area_file_up:
97
+ file_upload = gr.Files(label="任何文件, 但推荐上传压缩文件(zip, tar)", file_count="multiple")
98
+ with gr.Accordion("展开SysPrompt & 交互界面布局 & Github地址", open=(LAYOUT == "TOP-DOWN")):
99
+ system_prompt = gr.Textbox(show_label=True, placeholder=f"System Prompt", label="System prompt", value=initial_prompt)
100
+ top_p = gr.Slider(minimum=-0, maximum=1.0, value=1.0, step=0.01,interactive=True, label="Top-p (nucleus sampling)",)
101
+ temperature = gr.Slider(minimum=-0, maximum=2.0, value=1.0, step=0.01, interactive=True, label="Temperature",)
102
+ checkboxes = gr.CheckboxGroup(["基础功能区", "函数插件区", "底部输入区"], value=["基础功能区", "函数插件区"], label="显示/隐藏功能区")
103
+ gr.Markdown(description)
104
+ with gr.Accordion("备选输入区", open=True, visible=False) as area_input_secondary:
105
+ with gr.Row():
106
+ txt2 = gr.Textbox(show_label=False, placeholder="Input question here.", label="输入区2").style(container=False)
107
+ with gr.Row():
108
+ submitBtn2 = gr.Button("提交", variant="primary")
109
+ with gr.Row():
110
+ resetBtn2 = gr.Button("重置", variant="secondary"); resetBtn.style(size="sm")
111
+ stopBtn2 = gr.Button("停止", variant="secondary"); stopBtn.style(size="sm")
112
+ # 功能区显示开关与功能区的互动
113
+ def fn_area_visibility(a):
114
+ ret = {}
115
+ ret.update({area_basic_fn: gr.update(visible=("基础功能区" in a))})
116
+ ret.update({area_crazy_fn: gr.update(visible=("函数插件区" in a))})
117
+ ret.update({area_input_primary: gr.update(visible=("底部输入区" not in a))})
118
+ ret.update({area_input_secondary: gr.update(visible=("底部输入区" in a))})
119
+ if "底部输入区" in a: ret.update({txt: gr.update(value="")})
120
+ return ret
121
+ checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn, area_input_primary, area_input_secondary, txt, txt2] )
122
+ # 整理反复出现的控件句柄组合
123
+ input_combo = [cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt]
124
+ output_combo = [cookies, chatbot, history, status]
125
+ predict_args = dict(fn=ArgsGeneralWrapper(predict), inputs=input_combo, outputs=output_combo)
126
+ # 提交按钮、重置按钮
127
+ cancel_handles.append(txt.submit(**predict_args))
128
+ cancel_handles.append(txt2.submit(**predict_args))
129
+ cancel_handles.append(submitBtn.click(**predict_args))
130
+ cancel_handles.append(submitBtn2.click(**predict_args))
131
+ resetBtn.click(lambda: ([], [], "已重置"), None, [chatbot, history, status])
132
+ resetBtn2.click(lambda: ([], [], "已重置"), None, [chatbot, history, status])
133
+ # 基础功能区的回调函数注册
134
+ for k in functional:
135
+ click_handle = functional[k]["Button"].click(fn=ArgsGeneralWrapper(predict), inputs=[*input_combo, gr.State(True), gr.State(k)], outputs=output_combo)
136
+ cancel_handles.append(click_handle)
137
+ # 文件上传区,接收文件后与chatbot的互动
138
+ file_upload.upload(on_file_uploaded, [file_upload, chatbot, txt], [chatbot, txt])
139
+ # 函数插件-固定按钮区
140
+ for k in crazy_fns:
141
+ if not crazy_fns[k].get("AsButton", True): continue
142
+ click_handle = crazy_fns[k]["Button"].click(ArgsGeneralWrapper(crazy_fns[k]["Function"]), [*input_combo, gr.State(PORT)], output_combo)
143
+ click_handle.then(on_report_generated, [file_upload, chatbot], [file_upload, chatbot])
144
+ # def expand_file_area(file_upload, area_file_up):
145
+ # if len(file_upload)>0: return {area_file_up: gr.update(open=True)}
146
+ # click_handle.then(expand_file_area, [file_upload, area_file_up], [area_file_up])
147
+ cancel_handles.append(click_handle)
148
+ # 终止按钮的回调函数注册
149
+ stopBtn.click(fn=None, inputs=None, outputs=None, cancels=cancel_handles)
150
+ stopBtn2.click(fn=None, inputs=None, outputs=None, cancels=cancel_handles)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
 
152
+ # gradio的inbrowser触发不太稳定,回滚代码到原始的浏览器打开函数
153
+ def auto_opentab_delay():
154
+ import threading, webbrowser, time
155
+ print(f"如果浏览器没有自动打开,请复制并转到以下URL:")
156
+ print(f"\t(亮色主题): http://localhost:{PORT}")
157
+ print(f"\t(暗色主题): http://localhost:{PORT}/?__dark-theme=true")
158
+ def open():
159
+ time.sleep(2) # 打开浏览器
160
+ webbrowser.open_new_tab(f"http://localhost:{PORT}/?__dark-theme=true")
161
+ threading.Thread(target=open, name="open-browser", daemon=True).start()
162
+ threading.Thread(target=auto_update, name="self-upgrade", daemon=True).start()
163
+
164
+ auto_opentab_delay()
165
+ demo.queue(concurrency_count=CONCURRENT_COUNT).launch(server_name="0.0.0.0", share=False)
166
+
167
+ if __name__ == "__main__":
168
+ main()
request_llm/README.md CHANGED
@@ -1,35 +1,53 @@
1
  # 如何使用其他大语言模型(v3.0分支测试中)
2
 
3
- ## 1. 先运行text-generation
 
 
 
 
4
  ``` sh
5
- # 下载模型( text-generation 这么牛的项目,别忘了给人家star )
6
- git clone https://github.com/oobabooga/text-generation-webui.git
 
 
 
 
7
 
8
- # 安装text-generation的额外依赖
9
- pip install accelerate bitsandbytes flexgen gradio llamacpp markdown numpy peft requests rwkv safetensors sentencepiece tqdm datasets git+https://github.com/huggingface/transformers
10
 
11
- # 切换路径
12
- cd text-generation-webui
13
 
14
- # 下载模型
 
 
 
 
 
 
 
 
 
 
15
  python download-model.py facebook/galactica-1.3b
16
  # 其他可选如 facebook/opt-1.3b
 
17
  # facebook/galactica-6.7b
18
  # facebook/galactica-120b
19
  # facebook/pygmalion-1.3b 等
20
  # 详情见 https://github.com/oobabooga/text-generation-webui
21
 
22
- # 启动text-generation,注意把模型的斜杠改成下划线
23
- python server.py --cpu --listen --listen-port 7860 --model facebook_galactica-1.3b
24
  ```
25
 
26
- ## 2. 修改config.py
 
27
  ``` sh
28
- # LLM_MODEL格式较复杂 TGUI:[模型]@[ws地址]:[ws端口] , 端口要和上面给定的端口一致
29
- LLM_MODEL = "TGUI:galactica-1.3b@localhost:7860"
30
  ```
31
 
32
- ## 3. 运行!
33
  ``` sh
34
  cd chatgpt-academic
35
  python main.py
 
1
  # 如何使用其他大语言模型(v3.0分支测试中)
2
 
3
+ ## ChatGLM
4
+
5
+ - 安装依赖 `pip install -r request_llm/requirements_chatglm.txt`
6
+ - 修改配置,在config.py中将LLM_MODEL的值改为"chatglm"
7
+
8
  ``` sh
9
+ LLM_MODEL = "chatglm"
10
+ ```
11
+ - 运行!
12
+ ``` sh
13
+ `python main.py`
14
+ ```
15
 
 
 
16
 
17
+ ---
18
+ ## Text-Generation-UI (TGUI)
19
 
20
+ ### 1. 部署TGUI
21
+ ``` sh
22
+ # 1 下载模型
23
+ git clone https://github.com/oobabooga/text-generation-webui.git
24
+ # 2 这个仓库的最新代码有问题,回滚到几周之前
25
+ git reset --hard fcda3f87767e642d1c0411776e549e1d3894843d
26
+ # 3 切换路径
27
+ cd text-generation-webui
28
+ # 4 安装text-generation的额外依赖
29
+ pip install accelerate bitsandbytes flexgen gradio llamacpp markdown numpy peft requests rwkv safetensors sentencepiece tqdm datasets git+https://github.com/huggingface/transformers
30
+ # 5 下载模型
31
  python download-model.py facebook/galactica-1.3b
32
  # 其他可选如 facebook/opt-1.3b
33
+ # facebook/galactica-1.3b
34
  # facebook/galactica-6.7b
35
  # facebook/galactica-120b
36
  # facebook/pygmalion-1.3b 等
37
  # 详情见 https://github.com/oobabooga/text-generation-webui
38
 
39
+ # 6 启动text-generation
40
+ python server.py --cpu --listen --listen-port 7865 --model facebook_galactica-1.3b
41
  ```
42
 
43
+ ### 2. 修改config.py
44
+
45
  ``` sh
46
+ # LLM_MODEL格式: tgui:[模型]@[ws地址]:[ws端口] , 端口要和上面给定的端口一致
47
+ LLM_MODEL = "tgui:galactica-1.3b@localhost:7860"
48
  ```
49
 
50
+ ### 3. 运行!
51
  ``` sh
52
  cd chatgpt-academic
53
  python main.py
request_llm/bridge_all.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ """
3
+ 该文件中主要包含2个函数
4
+
5
+ 不具备多线程能力的函数:
6
+ 1. predict: 正常对话时使用,具备完备的交互功能,不可多线程
7
+
8
+ 具备多线程调用能力的函数
9
+ 2. predict_no_ui_long_connection:在实验过程中发现调用predict_no_ui处理长文档时,和openai的连接容易断掉,这个函数用stream的方式解决这个问题,同样支持多线程
10
+ """
11
+ import tiktoken
12
+
13
+ from concurrent.futures import ThreadPoolExecutor
14
+
15
+ from .bridge_chatgpt import predict_no_ui_long_connection as chatgpt_noui
16
+ from .bridge_chatgpt import predict as chatgpt_ui
17
+
18
+ from .bridge_chatglm import predict_no_ui_long_connection as chatglm_noui
19
+ from .bridge_chatglm import predict as chatglm_ui
20
+
21
+ from .bridge_tgui import predict_no_ui_long_connection as tgui_noui
22
+ from .bridge_tgui import predict as tgui_ui
23
+
24
+ colors = ['#FF00FF', '#00FFFF', '#FF0000', '#990099', '#009999', '#990044']
25
+
26
+ model_info = {
27
+ # openai
28
+ "gpt-3.5-turbo": {
29
+ "fn_with_ui": chatgpt_ui,
30
+ "fn_without_ui": chatgpt_noui,
31
+ "endpoint": "https://api.openai.com/v1/chat/completions",
32
+ "max_token": 4096,
33
+ "tokenizer": tiktoken.encoding_for_model("gpt-3.5-turbo"),
34
+ "token_cnt": lambda txt: len(tiktoken.encoding_for_model("gpt-3.5-turbo").encode(txt, disallowed_special=())),
35
+ },
36
+
37
+ "gpt-4": {
38
+ "fn_with_ui": chatgpt_ui,
39
+ "fn_without_ui": chatgpt_noui,
40
+ "endpoint": "https://api.openai.com/v1/chat/completions",
41
+ "max_token": 8192,
42
+ "tokenizer": tiktoken.encoding_for_model("gpt-4"),
43
+ "token_cnt": lambda txt: len(tiktoken.encoding_for_model("gpt-4").encode(txt, disallowed_special=())),
44
+ },
45
+
46
+ # api_2d
47
+ "api2d-gpt-3.5-turbo": {
48
+ "fn_with_ui": chatgpt_ui,
49
+ "fn_without_ui": chatgpt_noui,
50
+ "endpoint": "https://openai.api2d.net/v1/chat/completions",
51
+ "max_token": 4096,
52
+ "tokenizer": tiktoken.encoding_for_model("gpt-3.5-turbo"),
53
+ "token_cnt": lambda txt: len(tiktoken.encoding_for_model("gpt-3.5-turbo").encode(txt, disallowed_special=())),
54
+ },
55
+
56
+ "api2d-gpt-4": {
57
+ "fn_with_ui": chatgpt_ui,
58
+ "fn_without_ui": chatgpt_noui,
59
+ "endpoint": "https://openai.api2d.net/v1/chat/completions",
60
+ "max_token": 8192,
61
+ "tokenizer": tiktoken.encoding_for_model("gpt-4"),
62
+ "token_cnt": lambda txt: len(tiktoken.encoding_for_model("gpt-4").encode(txt, disallowed_special=())),
63
+ },
64
+
65
+ # chatglm
66
+ "chatglm": {
67
+ "fn_with_ui": chatglm_ui,
68
+ "fn_without_ui": chatglm_noui,
69
+ "endpoint": None,
70
+ "max_token": 1024,
71
+ "tokenizer": tiktoken.encoding_for_model("gpt-3.5-turbo"),
72
+ "token_cnt": lambda txt: len(tiktoken.encoding_for_model("gpt-3.5-turbo").encode(txt, disallowed_special=())),
73
+ },
74
+
75
+ }
76
+
77
+
78
+ def LLM_CATCH_EXCEPTION(f):
79
+ """
80
+ 装饰器函数,将错误显示出来
81
+ """
82
+ def decorated(inputs, llm_kwargs, history, sys_prompt, observe_window, console_slience):
83
+ try:
84
+ return f(inputs, llm_kwargs, history, sys_prompt, observe_window, console_slience)
85
+ except Exception as e:
86
+ from toolbox import get_conf
87
+ import traceback
88
+ proxies, = get_conf('proxies')
89
+ tb_str = '\n```\n' + traceback.format_exc() + '\n```\n'
90
+ observe_window[0] = tb_str
91
+ return tb_str
92
+ return decorated
93
+
94
+
95
+ def predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, observe_window, console_slience=False):
96
+ """
97
+ 发送至LLM,等待回复,一次性完成,不显示中间过程。但内部用stream的方法避免中途网线被掐。
98
+ inputs:
99
+ 是本次问询的输入
100
+ sys_prompt:
101
+ 系统静默prompt
102
+ llm_kwargs:
103
+ LLM的内部调优参数
104
+ history:
105
+ 是之前的对话列表
106
+ observe_window = None:
107
+ 用于负责跨越线程传递已经输出的部分,大部分时候仅仅为了fancy的视觉效果,留空即可。observe_window[0]:观测窗。observe_window[1]:看门狗
108
+ """
109
+ import threading, time, copy
110
+
111
+ model = llm_kwargs['llm_model']
112
+ n_model = 1
113
+ if '&' not in model:
114
+ assert not model.startswith("tgui"), "TGUI不支持函数插件的实现"
115
+
116
+ # 如果只询问1个大语言模型:
117
+ method = model_info[model]["fn_without_ui"]
118
+ return method(inputs, llm_kwargs, history, sys_prompt, observe_window, console_slience)
119
+ else:
120
+ # 如果同时询问多个大语言模型:
121
+ executor = ThreadPoolExecutor(max_workers=4)
122
+ models = model.split('&')
123
+ n_model = len(models)
124
+
125
+ window_len = len(observe_window)
126
+ assert window_len==3
127
+ window_mutex = [["", time.time(), ""] for _ in range(n_model)] + [True]
128
+
129
+ futures = []
130
+ for i in range(n_model):
131
+ model = models[i]
132
+ method = model_info[model]["fn_without_ui"]
133
+ llm_kwargs_feedin = copy.deepcopy(llm_kwargs)
134
+ llm_kwargs_feedin['llm_model'] = model
135
+ future = executor.submit(LLM_CATCH_EXCEPTION(method), inputs, llm_kwargs_feedin, history, sys_prompt, window_mutex[i], console_slience)
136
+ futures.append(future)
137
+
138
+ def mutex_manager(window_mutex, observe_window):
139
+ while True:
140
+ time.sleep(0.5)
141
+ if not window_mutex[-1]: break
142
+ # 看门狗(watchdog)
143
+ for i in range(n_model):
144
+ window_mutex[i][1] = observe_window[1]
145
+ # 观察窗(window)
146
+ chat_string = []
147
+ for i in range(n_model):
148
+ chat_string.append( f"【{str(models[i])} 说】: <font color=\"{colors[i]}\"> {window_mutex[i][0]} </font>" )
149
+ res = '<br/><br/>\n\n---\n\n'.join(chat_string)
150
+ # # # # # # # # # # #
151
+ observe_window[0] = res
152
+
153
+ t_model = threading.Thread(target=mutex_manager, args=(window_mutex, observe_window), daemon=True)
154
+ t_model.start()
155
+
156
+ return_string_collect = []
157
+ while True:
158
+ worker_done = [h.done() for h in futures]
159
+ if all(worker_done):
160
+ executor.shutdown()
161
+ break
162
+ time.sleep(1)
163
+
164
+ for i, future in enumerate(futures): # wait and get
165
+ return_string_collect.append( f"【{str(models[i])} 说】: <font color=\"{colors[i]}\"> {future.result()} </font>" )
166
+
167
+ window_mutex[-1] = False # stop mutex thread
168
+ res = '<br/>\n\n---\n\n'.join(return_string_collect)
169
+ return res
170
+
171
+
172
+ def predict(inputs, llm_kwargs, *args, **kwargs):
173
+ """
174
+ 发送至LLM,流式获取输出。
175
+ 用于基础的对话功能。
176
+ inputs 是本次问询的输入
177
+ top_p, temperature是LLM的内部调优参数
178
+ history 是之前的对话列表(注意无论是inputs还是history,内容太长了都会触发token数量溢出的错误)
179
+ chatbot 为WebUI中显示的对话列表,修改它,然后yeild出去,可以直接修改对话界面内容
180
+ additional_fn代表点击的哪个按钮,按钮见functional.py
181
+ """
182
+
183
+ method = model_info[llm_kwargs['llm_model']]["fn_with_ui"]
184
+ yield from method(inputs, llm_kwargs, *args, **kwargs)
185
+
request_llm/bridge_chatglm.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from transformers import AutoModel, AutoTokenizer
3
+ import time
4
+ import importlib
5
+ from toolbox import update_ui, get_conf
6
+ from multiprocessing import Process, Pipe
7
+
8
+ #################################################################################
9
+ class GetGLMHandle(Process):
10
+ def __init__(self):
11
+ super().__init__(daemon=True)
12
+ self.parent, self.child = Pipe()
13
+ self.chatglm_model = None
14
+ self.chatglm_tokenizer = None
15
+ self.start()
16
+ print('初始化')
17
+
18
+ def ready(self):
19
+ return self.chatglm_model is not None
20
+
21
+ def run(self):
22
+ while True:
23
+ try:
24
+ if self.chatglm_model is None:
25
+ self.chatglm_tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
26
+ device, = get_conf('LOCAL_MODEL_DEVICE')
27
+ if device=='cpu':
28
+ self.chatglm_model = AutoModel.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True).float()
29
+ else:
30
+ self.chatglm_model = AutoModel.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True).half().cuda()
31
+ self.chatglm_model = self.chatglm_model.eval()
32
+ break
33
+ else:
34
+ break
35
+ except:
36
+ pass
37
+ while True:
38
+ kwargs = self.child.recv()
39
+ try:
40
+ for response, history in self.chatglm_model.stream_chat(self.chatglm_tokenizer, **kwargs):
41
+ self.child.send(response)
42
+ except:
43
+ self.child.send('[Local Message] Call ChatGLM fail.')
44
+ self.child.send('[Finish]')
45
+
46
+ def stream_chat(self, **kwargs):
47
+ self.parent.send(kwargs)
48
+ while True:
49
+ res = self.parent.recv()
50
+ if res != '[Finish]':
51
+ yield res
52
+ else:
53
+ break
54
+ return
55
+
56
+ global glm_handle
57
+ glm_handle = None
58
+ #################################################################################
59
+ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=None, console_slience=False):
60
+ """
61
+ 多线程方法
62
+ 函数的说明请见 request_llm/bridge_all.py
63
+ """
64
+ global glm_handle
65
+ if glm_handle is None:
66
+ glm_handle = GetGLMHandle()
67
+ observe_window[0] = "ChatGLM尚未加载,加载需要一段时间。注意,取决于`config.py`的配置,ChatGLM消耗大量的内存(CPU)或显存(GPU),也许会导致低配计算机卡死 ……"
68
+
69
+ # chatglm 没有 sys_prompt 接口,因此把prompt加入 history
70
+ history_feedin = []
71
+ for i in range(len(history)//2):
72
+ history_feedin.append(["What can I do?", sys_prompt] )
73
+ history_feedin.append([history[2*i], history[2*i+1]] )
74
+
75
+ watch_dog_patience = 5 # 看门狗 (watchdog) 的耐心, 设置5秒即可
76
+ response = ""
77
+ for response in glm_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']):
78
+ observe_window[0] = response
79
+ if len(observe_window) >= 2:
80
+ if (time.time()-observe_window[1]) > watch_dog_patience:
81
+ raise RuntimeError("程序终止。")
82
+ return response
83
+
84
+
85
+
86
+ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None):
87
+ """
88
+ 单线程方法
89
+ 函数的说明请见 request_llm/bridge_all.py
90
+ """
91
+ chatbot.append((inputs, ""))
92
+
93
+ global glm_handle
94
+ if glm_handle is None:
95
+ glm_handle = GetGLMHandle()
96
+ chatbot[-1] = (inputs, "ChatGLM尚未加载,加载需要一段时间。注意,取决于`config.py`的配置,ChatGLM消耗大量的内存(CPU)或显存(GPU),也许会导致低配计算机卡死 ……")
97
+ yield from update_ui(chatbot=chatbot, history=[])
98
+
99
+ if additional_fn is not None:
100
+ import core_functional
101
+ importlib.reload(core_functional) # 热更新prompt
102
+ core_functional = core_functional.get_core_functions()
103
+ if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话)
104
+ inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"]
105
+
106
+ history_feedin = []
107
+ for i in range(len(history)//2):
108
+ history_feedin.append(["What can I do?", system_prompt] )
109
+ history_feedin.append([history[2*i], history[2*i+1]] )
110
+
111
+ for response in glm_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']):
112
+ chatbot[-1] = (inputs, response)
113
+ yield from update_ui(chatbot=chatbot, history=history)
request_llm/bridge_chatgpt.py CHANGED
@@ -21,9 +21,9 @@ import importlib
21
 
22
  # config_private.py放自己的秘密如API和代理网址
23
  # 读取时首先看是否存在私密的config_private配置文件(不受git管控),如果有,则覆盖原config文件
24
- from toolbox import get_conf, update_ui
25
- proxies, API_URL, API_KEY, TIMEOUT_SECONDS, MAX_RETRY, LLM_MODEL = \
26
- get_conf('proxies', 'API_URL', 'API_KEY', 'TIMEOUT_SECONDS', 'MAX_RETRY', 'LLM_MODEL')
27
 
28
  timeout_bot_msg = '[Local Message] Request timeout. Network error. Please check proxy settings in config.py.' + \
29
  '网络错误,检查代理服务器是否可用,以及代理设置的格式是否正确,格式须是[协议]://[地址]:[端口],缺一不可。'
@@ -42,17 +42,17 @@ def get_full_error(chunk, stream_response):
42
 
43
  def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=None, console_slience=False):
44
  """
45
- 发送至chatGPT,等待回复,一次性完成,不显示中间过程。但内部用stream的方法避免中途网线被掐。
46
- inputs:
47
- 是本次问询的输入
48
- sys_prompt:
49
- 系统静默prompt
50
- llm_kwargs:
51
- chatGPT的内部调优参数
52
- history:
53
- 是之前的对话列表
54
- observe_window = None:
55
- 用于负责跨越线程传递已经输出的部分,大部分时候仅仅为了fancy的视觉效果,留空即可。observe_window[0]:观测窗。observe_window[1]:看门狗
56
  """
57
  watch_dog_patience = 5 # 看门狗的耐心, 设置5秒即可
58
  headers, payload = generate_payload(inputs, llm_kwargs, history, system_prompt=sys_prompt, stream=True)
@@ -60,7 +60,9 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
60
  while True:
61
  try:
62
  # make a POST request to the API endpoint, stream=False
63
- response = requests.post(API_URL, headers=headers, proxies=proxies,
 
 
64
  json=payload, stream=True, timeout=TIMEOUT_SECONDS); break
65
  except requests.exceptions.ReadTimeout as e:
66
  retry += 1
@@ -105,22 +107,22 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
105
 
106
  def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None):
107
  """
108
- 发送至chatGPT,流式获取输出。
109
- 用于基础的对话功能。
110
- inputs 是本次问询的输入
111
- top_p, temperature是chatGPT的内部调优参数
112
- history 是之前的对话列表(注意无论是inputs还是history,内容太长了都会触发token数量溢出的错误)
113
- chatbot 为WebUI中显示的对话列表,修改它,然后yeild出去,可以直接修改对话界面内容
114
- additional_fn代表点击的哪个按钮,按钮见functional.py
115
  """
116
- if inputs.startswith('sk-') and len(inputs) == 51:
117
  chatbot._cookies['api_key'] = inputs
118
  chatbot.append(("输入已识别为openai的api_key", "api_key已导入"))
119
  yield from update_ui(chatbot=chatbot, history=history, msg="api_key已导入") # 刷新界面
120
  return
121
- elif len(chatbot._cookies['api_key']) != 51:
122
  chatbot.append((inputs, "缺少api_key。\n\n1. 临时解决方案:直接在输入区键入api_key,然后回车提交。\n\n2. 长效解决方案:在config.py中配置。"))
123
- yield from update_ui(chatbot=chatbot, history=history, msg="api_key已导入") # 刷新界面
124
  return
125
 
126
  if additional_fn is not None:
@@ -130,20 +132,27 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
130
  if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话)
131
  inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"]
132
 
133
- if stream:
134
- raw_input = inputs
135
- logging.info(f'[raw_input] {raw_input}')
136
- chatbot.append((inputs, ""))
137
- yield from update_ui(chatbot=chatbot, history=history, msg="等待响应") # 刷新界面
138
 
139
- headers, payload = generate_payload(inputs, llm_kwargs, history, system_prompt, stream)
 
 
 
 
 
 
140
  history.append(inputs); history.append(" ")
141
 
142
  retry = 0
143
  while True:
144
  try:
145
  # make a POST request to the API endpoint, stream=True
146
- response = requests.post(API_URL, headers=headers, proxies=proxies,
 
 
147
  json=payload, stream=True, timeout=TIMEOUT_SECONDS);break
148
  except:
149
  retry += 1
@@ -160,7 +169,7 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
160
  while True:
161
  chunk = next(stream_response)
162
  # print(chunk.decode()[6:])
163
- if is_head_of_the_stream:
164
  # 数据流的第一帧不携带content
165
  is_head_of_the_stream = False; continue
166
 
@@ -191,6 +200,8 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
191
  chatbot[-1] = (chatbot[-1][0], "[Local Message] Incorrect API key. OpenAI以提供了不正确的API_KEY为由,拒绝服务.")
192
  elif "exceeded your current quota" in error_msg:
193
  chatbot[-1] = (chatbot[-1][0], "[Local Message] You exceeded your current quota. OpenAI以账户额度不足为由,拒绝服务.")
 
 
194
  else:
195
  from toolbox import regular_txt_to_markdown
196
  tb_str = '```\n' + traceback.format_exc() + '```'
@@ -200,14 +211,16 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
200
 
201
  def generate_payload(inputs, llm_kwargs, history, system_prompt, stream):
202
  """
203
- 整合所有信息,选择LLM模型,生成http请求,为发送请求做准备
204
  """
205
- if len(llm_kwargs['api_key']) != 51:
206
  raise AssertionError("你提供了错误的API_KEY。\n\n1. 临时解决方案:直接在输入区键入api_key,然后回车提交。\n\n2. 长效解决方案:在config.py中配置。")
207
 
 
 
208
  headers = {
209
  "Content-Type": "application/json",
210
- "Authorization": f"Bearer {llm_kwargs['api_key']}"
211
  }
212
 
213
  conversation_cnt = len(history) // 2
@@ -235,7 +248,7 @@ def generate_payload(inputs, llm_kwargs, history, system_prompt, stream):
235
  messages.append(what_i_ask_now)
236
 
237
  payload = {
238
- "model": llm_kwargs['llm_model'],
239
  "messages": messages,
240
  "temperature": llm_kwargs['temperature'], # 1.0,
241
  "top_p": llm_kwargs['top_p'], # 1.0,
 
21
 
22
  # config_private.py放自己的秘密如API和代理网址
23
  # 读取时首先看是否存在私密的config_private配置文件(不受git管控),如果有,则覆盖原config文件
24
+ from toolbox import get_conf, update_ui, is_any_api_key, select_api_key
25
+ proxies, API_KEY, TIMEOUT_SECONDS, MAX_RETRY = \
26
+ get_conf('proxies', 'API_KEY', 'TIMEOUT_SECONDS', 'MAX_RETRY')
27
 
28
  timeout_bot_msg = '[Local Message] Request timeout. Network error. Please check proxy settings in config.py.' + \
29
  '网络错误,检查代理服务器是否可用,以及代理设置的格式是否正确,格式须是[协议]://[地址]:[端口],缺一不可。'
 
42
 
43
  def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", observe_window=None, console_slience=False):
44
  """
45
+ 发送至chatGPT,等待回复,一次性完成,不显示中间过程。但内部用stream的方法避免中途网线被掐。
46
+ inputs:
47
+ 是本次问询的输入
48
+ sys_prompt:
49
+ 系统静默prompt
50
+ llm_kwargs:
51
+ chatGPT的内部调优参数
52
+ history:
53
+ 是之前的对话列表
54
+ observe_window = None:
55
+ 用于负责跨越线程传递已经输出的部分,大部分时候仅仅为了fancy的视觉效果,留空即可。observe_window[0]:观测窗。observe_window[1]:看门狗
56
  """
57
  watch_dog_patience = 5 # 看门狗的耐心, 设置5秒即可
58
  headers, payload = generate_payload(inputs, llm_kwargs, history, system_prompt=sys_prompt, stream=True)
 
60
  while True:
61
  try:
62
  # make a POST request to the API endpoint, stream=False
63
+ from .bridge_all import model_info
64
+ endpoint = model_info[llm_kwargs['llm_model']]['endpoint']
65
+ response = requests.post(endpoint, headers=headers, proxies=proxies,
66
  json=payload, stream=True, timeout=TIMEOUT_SECONDS); break
67
  except requests.exceptions.ReadTimeout as e:
68
  retry += 1
 
107
 
108
  def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None):
109
  """
110
+ 发送至chatGPT,流式获取输出。
111
+ 用于基础的对话功能。
112
+ inputs 是本次问询的输入
113
+ top_p, temperature是chatGPT的内部调优参数
114
+ history 是之前的对话列表(注意无论是inputs还是history,内容太长了都会触发token数量溢出的错误)
115
+ chatbot 为WebUI中显示的对话列表,修改它,然后yeild出去,可以直接修改对话界面内容
116
+ additional_fn代表点击的哪个按钮,按钮见functional.py
117
  """
118
+ if is_any_api_key(inputs):
119
  chatbot._cookies['api_key'] = inputs
120
  chatbot.append(("输入已识别为openai的api_key", "api_key已导入"))
121
  yield from update_ui(chatbot=chatbot, history=history, msg="api_key已导入") # 刷新界面
122
  return
123
+ elif not is_any_api_key(chatbot._cookies['api_key']):
124
  chatbot.append((inputs, "缺少api_key。\n\n1. 临时解决方案:直接在输入区键入api_key,然后回车提交。\n\n2. 长效解决方案:在config.py中配置。"))
125
+ yield from update_ui(chatbot=chatbot, history=history, msg="缺少api_key") # 刷新界面
126
  return
127
 
128
  if additional_fn is not None:
 
132
  if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话)
133
  inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"]
134
 
135
+ raw_input = inputs
136
+ logging.info(f'[raw_input] {raw_input}')
137
+ chatbot.append((inputs, ""))
138
+ yield from update_ui(chatbot=chatbot, history=history, msg="等待响应") # 刷新界面
 
139
 
140
+ try:
141
+ headers, payload = generate_payload(inputs, llm_kwargs, history, system_prompt, stream)
142
+ except RuntimeError as e:
143
+ chatbot[-1] = (inputs, f"您提供的api-key不满足要求,不包含任何可用于{llm_kwargs['llm_model']}的api-key。")
144
+ yield from update_ui(chatbot=chatbot, history=history, msg="api-key不满足要求") # 刷新界面
145
+ return
146
+
147
  history.append(inputs); history.append(" ")
148
 
149
  retry = 0
150
  while True:
151
  try:
152
  # make a POST request to the API endpoint, stream=True
153
+ from .bridge_all import model_info
154
+ endpoint = model_info[llm_kwargs['llm_model']]['endpoint']
155
+ response = requests.post(endpoint, headers=headers, proxies=proxies,
156
  json=payload, stream=True, timeout=TIMEOUT_SECONDS);break
157
  except:
158
  retry += 1
 
169
  while True:
170
  chunk = next(stream_response)
171
  # print(chunk.decode()[6:])
172
+ if is_head_of_the_stream and (r'"object":"error"' not in chunk.decode()):
173
  # 数据流的第一帧不携带content
174
  is_head_of_the_stream = False; continue
175
 
 
200
  chatbot[-1] = (chatbot[-1][0], "[Local Message] Incorrect API key. OpenAI以提供了不正确的API_KEY为由,拒绝服务.")
201
  elif "exceeded your current quota" in error_msg:
202
  chatbot[-1] = (chatbot[-1][0], "[Local Message] You exceeded your current quota. OpenAI以账户额度不足为由,拒绝服务.")
203
+ elif "bad forward key" in error_msg:
204
+ chatbot[-1] = (chatbot[-1][0], "[Local Message] Bad forward key. API2D账户额度不足.")
205
  else:
206
  from toolbox import regular_txt_to_markdown
207
  tb_str = '```\n' + traceback.format_exc() + '```'
 
211
 
212
  def generate_payload(inputs, llm_kwargs, history, system_prompt, stream):
213
  """
214
+ 整合所有信息,选择LLM模型,生成http请求,为发送请求做准备
215
  """
216
+ if not is_any_api_key(llm_kwargs['api_key']):
217
  raise AssertionError("你提供了错误的API_KEY。\n\n1. 临时解决方案:直接在输入区键入api_key,然后回车提交。\n\n2. 长效解决方案:在config.py中配置。")
218
 
219
+ api_key = select_api_key(llm_kwargs['api_key'], llm_kwargs['llm_model'])
220
+
221
  headers = {
222
  "Content-Type": "application/json",
223
+ "Authorization": f"Bearer {api_key}"
224
  }
225
 
226
  conversation_cnt = len(history) // 2
 
248
  messages.append(what_i_ask_now)
249
 
250
  payload = {
251
+ "model": llm_kwargs['llm_model'].strip('api2d-'),
252
  "messages": messages,
253
  "temperature": llm_kwargs['temperature'], # 1.0,
254
  "top_p": llm_kwargs['top_p'], # 1.0,
request_llm/bridge_tgui.py CHANGED
@@ -13,23 +13,18 @@ import time
13
  import threading
14
  import importlib
15
  from toolbox import get_conf, update_ui
16
- LLM_MODEL, = get_conf('LLM_MODEL')
17
 
18
- # "TGUI:galactica-1.3b@localhost:7860"
19
- model_name, addr_port = LLM_MODEL.split('@')
20
- assert ':' in addr_port, "LLM_MODEL 格式不正确!" + LLM_MODEL
21
- addr, port = addr_port.split(':')
22
 
23
  def random_hash():
24
  letters = string.ascii_lowercase + string.digits
25
  return ''.join(random.choice(letters) for i in range(9))
26
 
27
- async def run(context, max_token=512):
28
  params = {
29
  'max_new_tokens': max_token,
30
  'do_sample': True,
31
- 'temperature': 0.5,
32
- 'top_p': 0.9,
33
  'typical_p': 1,
34
  'repetition_penalty': 1.05,
35
  'encoder_repetition_penalty': 1.0,
@@ -90,7 +85,7 @@ async def run(context, max_token=512):
90
 
91
 
92
 
93
- def predict_tgui(inputs, top_p, temperature, chatbot, history=[], system_prompt='', stream = True, additional_fn=None):
94
  """
95
  发送至chatGPT,流式获取输出。
96
  用于基础的对话功能。
@@ -108,18 +103,26 @@ def predict_tgui(inputs, top_p, temperature, chatbot, history=[], system_prompt=
108
  inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"]
109
 
110
  raw_input = "What I would like to say is the following: " + inputs
111
- logging.info(f'[raw_input] {raw_input}')
112
  history.extend([inputs, ""])
113
  chatbot.append([inputs, ""])
114
  yield from update_ui(chatbot=chatbot, history=history, msg="等待响应") # 刷新界面
115
 
116
- prompt = inputs
117
  tgui_say = ""
118
 
 
 
 
 
 
119
  mutable = ["", time.time()]
120
  def run_coorotine(mutable):
121
  async def get_result(mutable):
122
- async for response in run(prompt):
 
 
 
 
123
  print(response[len(mutable[0]):])
124
  mutable[0] = response
125
  if (time.time() - mutable[1]) > 3:
@@ -140,28 +143,29 @@ def predict_tgui(inputs, top_p, temperature, chatbot, history=[], system_prompt=
140
  chatbot[-1] = (history[-2], history[-1])
141
  yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
142
 
143
- logging.info(f'[response] {tgui_say}')
144
 
145
 
146
 
147
- def predict_tgui_no_ui(inputs, top_p, temperature, history=[], sys_prompt=""):
148
  raw_input = "What I would like to say is the following: " + inputs
149
- prompt = inputs
150
  tgui_say = ""
151
- mutable = ["", time.time()]
152
- def run_coorotine(mutable):
153
- async def get_result(mutable):
154
- async for response in run(prompt, max_token=20):
155
- print(response[len(mutable[0]):])
156
- mutable[0] = response
157
- if (time.time() - mutable[1]) > 3:
 
 
 
 
 
 
158
  print('exit when no listener')
159
  break
160
- asyncio.run(get_result(mutable))
161
- thread_listen = threading.Thread(target=run_coorotine, args=(mutable,))
162
  thread_listen.start()
163
- while thread_listen.is_alive():
164
- time.sleep(1)
165
- mutable[1] = time.time()
166
- tgui_say = mutable[0]
167
- return tgui_say
 
13
  import threading
14
  import importlib
15
  from toolbox import get_conf, update_ui
 
16
 
 
 
 
 
17
 
18
  def random_hash():
19
  letters = string.ascii_lowercase + string.digits
20
  return ''.join(random.choice(letters) for i in range(9))
21
 
22
+ async def run(context, max_token, temperature, top_p, addr, port):
23
  params = {
24
  'max_new_tokens': max_token,
25
  'do_sample': True,
26
+ 'temperature': temperature,
27
+ 'top_p': top_p,
28
  'typical_p': 1,
29
  'repetition_penalty': 1.05,
30
  'encoder_repetition_penalty': 1.0,
 
85
 
86
 
87
 
88
+ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_prompt='', stream = True, additional_fn=None):
89
  """
90
  发送至chatGPT,流式获取输出。
91
  用于基础的对话功能。
 
103
  inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"]
104
 
105
  raw_input = "What I would like to say is the following: " + inputs
 
106
  history.extend([inputs, ""])
107
  chatbot.append([inputs, ""])
108
  yield from update_ui(chatbot=chatbot, history=history, msg="等待响应") # 刷新界面
109
 
110
+ prompt = raw_input
111
  tgui_say = ""
112
 
113
+ model_name, addr_port = llm_kwargs['llm_model'].split('@')
114
+ assert ':' in addr_port, "LLM_MODEL 格式不正确!" + llm_kwargs['llm_model']
115
+ addr, port = addr_port.split(':')
116
+
117
+
118
  mutable = ["", time.time()]
119
  def run_coorotine(mutable):
120
  async def get_result(mutable):
121
+ # "tgui:galactica-1.3b@localhost:7860"
122
+
123
+ async for response in run(context=prompt, max_token=llm_kwargs['max_length'],
124
+ temperature=llm_kwargs['temperature'],
125
+ top_p=llm_kwargs['top_p'], addr=addr, port=port):
126
  print(response[len(mutable[0]):])
127
  mutable[0] = response
128
  if (time.time() - mutable[1]) > 3:
 
143
  chatbot[-1] = (history[-2], history[-1])
144
  yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
145
 
 
146
 
147
 
148
 
149
+ def predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, observe_window, console_slience=False):
150
  raw_input = "What I would like to say is the following: " + inputs
151
+ prompt = raw_input
152
  tgui_say = ""
153
+ model_name, addr_port = llm_kwargs['llm_model'].split('@')
154
+ assert ':' in addr_port, "LLM_MODEL 格式不正确!" + llm_kwargs['llm_model']
155
+ addr, port = addr_port.split(':')
156
+
157
+
158
+ def run_coorotine(observe_window):
159
+ async def get_result(observe_window):
160
+ async for response in run(context=prompt, max_token=llm_kwargs['max_length'],
161
+ temperature=llm_kwargs['temperature'],
162
+ top_p=llm_kwargs['top_p'], addr=addr, port=port):
163
+ print(response[len(observe_window[0]):])
164
+ observe_window[0] = response
165
+ if (time.time() - observe_window[1]) > 5:
166
  print('exit when no listener')
167
  break
168
+ asyncio.run(get_result(observe_window))
169
+ thread_listen = threading.Thread(target=run_coorotine, args=(observe_window,))
170
  thread_listen.start()
171
+ return observe_window[0]
 
 
 
 
request_llm/requirements_chatglm.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ protobuf
2
+ transformers==4.27.1
3
+ cpm_kernels
4
+ torch>=1.10
5
+ mdtex2html
6
+ sentencepiece
self_analysis.md DELETED
@@ -1,262 +0,0 @@
1
- # chatgpt-academic项目自译解报告
2
- (Author补充:以下分析均由本项目调用ChatGPT一键生成,如果有不准确的地方,全怪GPT😄)
3
-
4
- ## 对程序的整体功能和构架做出概括。然后用一张markdown表格整理每个文件的功能(包括'check_proxy.py', 'config.py'等)。
5
-
6
- 整体概括:
7
-
8
- 该程序是一个基于自然语言处理和机器学习的科学论文辅助工具,主要功能包括聊天机器人、批量总结PDF文档、批量翻译PDF文档、生成函数注释、解析项目源代码等。程序基于 Gradio 构建 Web 服务,并集成了代理和自动更新功能,提高了用户的使用体验。
9
-
10
- 文件功能表格:
11
-
12
- | 文件名称 | 功能 |
13
- | ------------------------------------------------------------ | ------------------------------------------------------------ |
14
- | .\check_proxy.py | 检查代理设置功能。 |
15
- | .\config.py | 配置文件,存储程序的基本设置。 |
16
- | .\config_private.py | 存储代理网络地址的文件。 |
17
- | .\core_functional.py | 主要的程序逻辑,包括聊天机器人和文件处理。 |
18
- | .\cradle.py | 程序入口,初始化程序和启动 Web 服务。 |
19
- | .\crazy_functional.py | 辅助程序功能,包括PDF文档处理、代码处理、函数注释生成等。 |
20
- | .\main.py | 包含聊天机器人的具体实现。 |
21
- | .\show_math.py | 处理 LaTeX 公式的函数。 |
22
- | .\theme.py | 存储 Gradio Web 服务的 CSS 样式文件。 |
23
- | .\toolbox.py | 提供了一系列工具函数,包括文件读写、网页抓取、解析函数参数、生成 HTML 等。 |
24
- | ./crazy_functions/crazy_utils.py | 提供各种工具函数,如解析字符串、清洗文本、清理目录结构等。 |
25
- | ./crazy_functions/\_\_init\_\_.py | crazy_functions 模块的入口文件。 |
26
- | ./crazy_functions/下载arxiv论文翻译摘要.py | 对 arxiv.org 上的 PDF 论文进行下载和翻译。 |
27
- | ./crazy_functions/代码重写为全英文_多线程.py | 将代码文件中的中文注释和字符串替换为英文。 |
28
- | ./crazy_functions/总结word文档.py | 读取 Word 文档并生成摘要。 |
29
- | ./crazy_functions/批量总结PDF文档.py | 批量读取 PDF 文件并生成摘要。 |
30
- | ./crazy_functions/批量总结PDF文档pdfminer.py | 使用 pdfminer 库进行 PDF 文件处理。 |
31
- | ./crazy_functions/批量翻译PDF文档_多线程.py | 使用多线程技术批量翻译 PDF 文件。 |
32
- | ./crazy_functions/生成函数注释.py | 给 Python 函数自动生成说明文档。 |
33
- | ./crazy_functions/解析项目源代码.py | 解析项目中的源代码,提取注释和函数名等信息。 |
34
- | ./crazy_functions/读文章写摘要.py | 读取多个文本文件并生成对应的摘要。 |
35
- | ./crazy_functions/高级功能函数模板.py | 使用 GPT 模型进行文本处理。 |
36
-
37
-
38
-
39
- ## [0/22] 程序概述: check_proxy.py
40
-
41
- 该程序的文件名是check_proxy.py,主要有两个函数:check_proxy和auto_update。
42
-
43
- check_proxy函数中会借助requests库向一个IP查询API发送请求,并返回该IP的地理位置信息。同时根据返回的数据来判断代理是否有效。
44
-
45
- auto_update函数主要用于检查程序更新,会从Github获取程序最新的版本信息,如果当前版本和最新版本相差较大,则会提示用户进行更新。该函数中也会依赖requests库进行网络请求。
46
-
47
- 在程序的开头,还添加了一句防止代理网络影响的代码。程序使用了自己编写的toolbox模块中的get_conf函数来获取代理设置。
48
-
49
- ## [1/22] 程序概述: config.py
50
-
51
- 该程序文件是一个Python模块,文件名为config.py。该模块包含了一些变量和配置选项,用���配置一个OpenAI的聊天机器人。具体的配置选项如下:
52
-
53
- - API_KEY: 密钥,用于连接OpenAI的API。需要填写有效的API密钥。
54
- - USE_PROXY: 是否使用代理。如果需要使用代理,需要将其改为True。
55
- - proxies: 代理的协议、地址和端口。
56
- - CHATBOT_HEIGHT: 聊天机器人对话框的高度。
57
- - LAYOUT: 聊天机器人对话框的布局,默认为左右布局。
58
- - TIMEOUT_SECONDS: 发送请求到OpenAI后,等待多久判定为超时。
59
- - WEB_PORT: 网页的端口,-1代表随机端口。
60
- - MAX_RETRY: 如果OpenAI不响应(网络卡顿、代理失败、KEY失效),重试的次数限制。
61
- - LLM_MODEL: OpenAI模型选择,目前只对某些用户开放的gpt4。
62
- - API_URL: OpenAI的API地址。
63
- - CONCURRENT_COUNT: 使用的线程数。
64
- - AUTHENTICATION: 用户名和密码,如果需要。
65
-
66
- ## [2/22] 程序概述: config_private.py
67
-
68
- 该程序文件名为config_private.py,包含了API_KEY的设置和代理的配置。使用了一个名为API_KEY的常量来存储私人的API密钥。此外,还有一个名为USE_PROXY的常量来标记是否需要使用代理。如果需要代理,则使用了一个名为proxies的字典来存储代理网络的地址,其中包括协议类型、地址和端口。
69
-
70
- ## [3/22] 程序概述: core_functional.py
71
-
72
- 该程序文件名为`core_functional.py`,主要是定义了一些核心功能函数,包括英语和中文学术润色、查找语法错误、中译英、学术中英互译、英译中、找图片和解释代码等。每个功能都有一个`Prefix`属性和`Suffix`属性,`Prefix`是指在用户输入的任务前面要显示的文本,`Suffix`是指在任务后面要显示的文本。此外,还有一个`Color`属性指示按钮的颜色,以及一个`PreProcess`函数表示对输入进行预处理的函数。
73
-
74
- ## [4/22] 程序概述: cradle.py
75
-
76
- 该程序文件名为cradle.py,主要功能是检测当前版本与远程最新版本是否一致,如果不一致则输出新版本信息并提示更新。其流程大致如下:
77
-
78
- 1. 导入相关模块与自定义工具箱函数get_conf
79
- 2. 读取配置文件中的代理proxies
80
- 3. 使用requests模块请求远程版本信息(url为https://raw.githubusercontent.com/binary-husky/chatgpt_academic/master/version)并加载为json格式
81
- 4. 获取远程版本号、是否显示新功能信息、新功能内容
82
- 5. 读取本地版本文件version并加载为json格式
83
- 6. 获取当前版本号
84
- 7. 比较当前版本与远程版本,如果远程版本号比当前版本号高0.05以上,则输出新版本信息并提示更新
85
- 8. 如果不需要更新,则直接返回
86
-
87
- ## [5/22] 程序概述: crazy_functional.py
88
-
89
- 该程序文件名为.\crazy_functional.py,主要定义了一个名为get_crazy_functions()的函数,该函数返回一个字典类型的变量function_plugins,其中包含了一些函数插件。
90
-
91
- 一些重要的函数插件包括:
92
-
93
- - 读文章写摘要:可以自动读取Tex格式的论文,并生成其摘要。
94
-
95
- - 批量生成函数注释:可以批量生成Python函数的文档注释。
96
-
97
- - 解析项目源代码:可以解析Python、C++、Golang、Java及React项目的源代码。
98
-
99
- - 批量总结PDF文档:可以对PDF文档进行批量总结,以提取其中的关键信息。
100
-
101
- - 一键下载arxiv论文并翻译摘要:可以自动下载arxiv.org网站上的PDF论文,并翻译生成其摘要。
102
-
103
- - 批量翻译PDF文档(多线程):可以对PDF文档进行批量翻译,并使用多线程方式提高翻译效率。
104
-
105
- ## [6/22] 程序概述: main.py
106
-
107
- 本程序为一个基于 Gradio 和 GPT-3 的交互式聊天机器人,文件名为 main.py。其中主要功能包括:
108
-
109
- 1. 使用 Gradio 建立 Web 界面,实现用户与聊天机器人的交互;
110
- 2. 通过 bridge_chatgpt 模块,利用 GPT-3 模型实现聊天机器人的逻辑;
111
- 3. 提供一些基础功能和高级函数插件,用户可以通过按钮选择使用;
112
- 4. 提供文档格式转变、外观调整以及代理和自动更新等功能。
113
-
114
- 程序的主要流程为:
115
-
116
- 1. 导入所需的库和模块,并通过 get_conf 函数获取配置信息;
117
- 2. 设置 Gradio 界面的各个组件,包括聊天窗口、输入区、功能区、函数插件区等;
118
- 3. 注册各个组件的回调函数,包括用户输入、信号按钮等,实现机器人逻辑的交互;
119
- 4. 通过 Gradio 的 queue 函数和 launch 函数启动 Web 服务,并提供聊天机器人的功能。
120
-
121
- 此外,程序还提供了代理和自动更新功能,可以确保用户的使用体验。
122
-
123
- ## [7/22] 程序概述: show_math.py
124
-
125
- 该程序是一个Python脚本,文件名为show_math.py。它转换Markdown和LaTeX混合语法到带MathML的HTML。程序使用latex2mathml模块来实现从LaTeX到MathML的转换,将符号转换为HTML实体以批量处理。程序利用正则表达式和递归函数的方法处理不同形式的LaTeX语法,支持以下四种情况:$$形式、$形式、\[..]形式和\(...\)形式。如果无法转��某个公式,则在该位置插入一条错误消息。最后,程序输出HTML字符串。
126
-
127
- ## [8/22] 程序概述: theme.py
128
-
129
- 该程序文件为一个Python脚本,其功能是调整Gradio应用的主题和样式,包括字体、颜色、阴影、背景等等。在程序中,使用了Gradio提供的默认颜色主题,并针对不同元素设置了相应的样式属性,以达到美化显示的效果。此外,程序中还包含了一段高级CSS样式代码,针对表格、列表、聊天气泡、行内代码等元素进行了样式设定。
130
-
131
- ## [9/22] 程序概述: toolbox.py
132
-
133
- 此程序文件主要包含了一系列用于聊天机器人开发的实用工具函数和装饰器函数。主要函数包括:
134
-
135
- 1. ArgsGeneralWrapper:一个装饰器函数,用于重组输入参数,改变输入参数的顺序与结构。
136
-
137
- 2. get_reduce_token_percent:一个函数,用于计算自然语言处理时会出现的token溢出比例。
138
-
139
- 3. predict_no_ui_but_counting_down:一个函数,调用聊天接口,并且保留了一定的界面心跳功能,即当对话太长时,会自动采用二分法截断。
140
-
141
- 4. write_results_to_file:一个函数,将对话记录history生成Markdown格式的文本,并写入文件中。
142
-
143
- 5. regular_txt_to_markdown:一个函数,将普通文本转换为Markdown格式的文本。
144
-
145
- 6. CatchException:一个装饰器函数,捕捉函数调度中的异常,并封装到一个生成器中返回,并显示到聊天当中。
146
-
147
- 7. HotReload:一个装饰器函数,实现函数插件的热更新。
148
-
149
- 8. report_execption:一个函数,向chatbot中添加错误信息。
150
-
151
- 9. text_divide_paragraph:一个函数,将文本按照段落分隔符分割开,生成带有段落标签的HTML代码。
152
-
153
- 10. markdown_convertion:一个函数,将Markdown格式的文本转换为HTML格式。如果包含数学公式,则先将公式转换为HTML格式。
154
-
155
- 11. close_up_code_segment_during_stream:一个函数,用于在gpt输出代码的中途,即输出了前面的```,但还没输出完后面的```,补上后面的```。
156
-
157
- 12. format_io:一个函数,将输入和输出解析为HTML格式。将输出部分的Markdown和数学公式转换为HTML格式。
158
-
159
- 13. find_free_port:一个函数,返回当前系统中可用的未使用端口。
160
-
161
- 14. extract_archive:一个函数,解压缩文件。
162
-
163
- 15. find_recent_files:一个函数,查找目录下一分钟内创建的文件。
164
-
165
- 16. on_file_uploaded:一个函数,响应用户上传的文件。
166
-
167
- ## [10/22] 程序概述: crazy_functions\crazy_utils.py
168
-
169
- 这是一个名为"crazy_utils.py"的Python程序文件,包含了两个函数:
170
- 1. `breakdown_txt_to_satisfy_token_limit()`:接受文本字符串、计算文本单词数量的函数和单词数量限制作为输入参数,将长文本拆分成合适的长度,以满足单词数量限制。这个函数使用一个递归方法去拆分长文本。
171
- 2. `breakdown_txt_to_satisfy_token_limit_for_pdf()`:类似于`breakdown_txt_to_satisfy_token_limit()`,但是它使用一个不同的递归方法来拆分长文本,以满足PDF文档中的需求。当出现无法继续拆分的情况时,该函数将使用一个中文句号标记插入文本来截断长文本。如果还是无法拆分,则会引发运行时异常。
172
-
173
- ## [11/22] 程序概述: crazy_functions\__init__.py
174
-
175
- 这个程序文件是一个 Python 的包,包名为 "crazy_functions",并且是其中的一个子模块 "__init__.py"。该包中可能包含多个函数或类,用于实现各种疯狂的功能。由于该文件的具体代码没有给出,因此无法进一步确定该包中的功能。通常情况下,一个包应该具有 __init__.py、__main__.py 和其它相关的模块文件,用于实现该包的各种功能。
176
-
177
- ## [12/22] 程序概述: crazy_functions\下载arxiv论文翻译摘要.py
178
-
179
- 这个程序实现的功能是下载arxiv论文并翻译摘要,文件名为`下载arxiv论文翻译摘要.py`。这个程序引入了`requests`、`unicodedata`、`os`、`re`等Python标准库,以及`pdfminer`、`bs4`等第三方库。其中`download_arxiv_`函数主要实现了从arxiv网站下载论文的功能,包括解析链接、获取论文信息、下载论文和生成文件名等,`get_name`函数则是为了从arxiv网站中获取论文信息创建的辅助函数。`下载arxiv论文并翻译摘要`函数则是实现了从下载好的PDF文件中提取摘要,然后使用预先训练的GPT模型翻译为中文的功能。同时,该函数还会将历史记录写入文件中。函数还会通过`CatchException`函数来捕获程序中出现的异常信息。
180
-
181
- ## [13/22] 程序概述: crazy_functions\代码重写为全英文_多线程.py
182
-
183
- 该程序文件为一个Python多线程程序,文件名为"crazy_functions\代码重写为全英文_多线程.py"。该程序使用了多线程技术,将一个大任务拆成多个小任务,同时执行,提高运行效率。
184
-
185
- 程序的主要功能是将Python文件中的中文转换为英文,同时���转换后的代码输出。程序先清空历史记录,然后尝试导入openai和transformers等依赖库。程序接下来会读取当前路径下的.py文件和crazy_functions文件夹中的.py文件,并将其整合成一个文件清单。随后程序会使用GPT2模型进行中英文的翻译,并将结果保存在本地路径下的"gpt_log/generated_english_version"文件夹中。程序最终会生成一个任务执行报告。
186
-
187
- 需要注意的是,该程序依赖于"request_llm"和"toolbox"库以及本地的"crazy_utils"模块。
188
-
189
- ## [14/22] 程序概述: crazy_functions\总结word文档.py
190
-
191
- 该程序文件是一个 Python 脚本文件,文件名为 ./crazy_functions/总结word文档.py。该脚本是一个函数插件,提供了名为“总结word文档”的函数。该函数的主要功能是批量读取给定文件夹下的 Word 文档文件,并使用 GPT 模型生成对每个文件的概述和意见建议。其中涉及到了读取 Word 文档、使用 GPT 模型等操作,依赖于许多第三方库。该文件也提供了导入依赖的方法,使用该脚本需要安装依赖库 python-docx 和 pywin32。函数功能实现的过程中,使用了一些用于调试的变量(如 fast_debug),可在需要时设置为 True。该脚本文件也提供了对程序功能和贡献者的注释。
192
-
193
- ## [15/22] 程序概述: crazy_functions\批量总结PDF文档.py
194
-
195
- 该程序文件名为 `./crazy_functions\批量总结PDF文档.py`,主要实现了批量处理PDF文档的功能。具体实现了以下几个函数:
196
-
197
- 1. `is_paragraph_break(match)`:根据给定的匹配结果判断换行符是否表示段落分隔。
198
- 2. `normalize_text(text)`:通过将文本特殊符号转换为其基本形式来对文本进行归一化处理。
199
- 3. `clean_text(raw_text)`:对从 PDF 提取出的原始文本进行清洗和格式化处理。
200
- 4. `解析PDF(file_manifest, project_folder, top_p, temperature, chatbot, history, systemPromptTxt)`:对给定的PDF文件进行分析并生成相应的概述。
201
- 5. `批量总结PDF文档(txt, top_p, temperature, chatbot, history, systemPromptTxt, WEB_PORT)`:批量处理PDF文件,对其进行摘要生成。
202
-
203
- 其中,主要用到了第三方库`pymupdf`对PDF文件进行处理。程序通过调用`fitz.open`函数打开PDF文件,使用`page.get_text()`方法获取PDF文本内容。然后,使用`clean_text`函数对文本进行清洗和格式化处理,生成最终的摘要。最后,调用`write_results_to_file`函数将历史记录写入文件并输出。
204
-
205
- ## [16/22] 程序概述: crazy_functions\批量总结PDF文档pdfminer.py
206
-
207
- 这个程序文件名是./crazy_functions\批量总结PDF文档pdfminer.py,是一个用于批量读取PDF文件,解析其中的内容,并对其进行概括的程序。程序中引用了pdfminer和beautifulsoup4等Python库,读取PDF文件并将其转化为文本内容,然后利用GPT模型生成摘要语言,最终输出一个中文和英文的摘要。程序还有一些错误处理的代码,会输出错误信息。
208
-
209
- ## [17/22] 程序概述: crazy_functions\批量翻译PDF文档_多线程.py
210
-
211
- 这是一个 Python 程序文件,文件名为 `批量翻译PDF文档_多线程.py`,包含多个函数。主要功能是批量处理 PDF 文档,解析其中的文本,进行清洗和格式化处理,并使用 OpenAI 的 GPT 模型进行翻译。其中使用了多线程技术来提高程序的效率和并行度。
212
-
213
- ## [18/22] 程序概述: crazy_functions\生成函数注释.py
214
-
215
- 该程序文件名为./crazy_functions\生成函数注释.py。该文件包含两个函数,分别为`生成函数注释`和`批量生成函数注释`。
216
-
217
- 函数`生成函数注释`包含参数`file_manifest`、`project_folder`、`top_p`、`temperature`、`chatbot`、`history`和`systemPromptTxt`。其中,`file_manifest`为一个包含待处理文件路径的列表,`project_folder`表示项目文件夹路径,`top_p`和`temperature`是GPT模型参数,`chatbot`为与用户交互的聊天机器人,`history`记录聊天机器人与用户的历史记录,`systemPromptTxt`为聊天机器人发送信息前的提示语。`生成函数注释`通过读取文件内容,并调用GPT模型对文件中的所有函数生成注释,最后使用markdown表格输出结果。函数中还包含一些条件判断和计时器,以及调用其他自定义模块的函数。
218
-
219
- 函数`批量生成函数注释`包含参数`txt`、`top_p`、`temperature`、`chatbot`、`history`、`systemPromptTxt`和`WEB_PORT`。其中,`txt`表示用户输入的项目文件夹路径,其他参数含义与`生成函数注释`中相同。`批量生成函数注释`主要是通过解析项目文件夹,获取所有待处理文件的路径,并调用函数`生成函数注释`对每个文件进行处理,最终生成注释表格输出给用户。
220
-
221
- ## [19/22] 程序概述: crazy_functions\解析项目源代码.py
222
-
223
- 该程序文件包含了多个函数,用于解析不同类型的项目,如Python项目、C项目、Java项目等。其中,最核心的函��是`解析源代码()`,它会对给定的一组文件进行分析,并返回对应的结果。具体流程如下:
224
-
225
- 1. 遍历所有待分析的文件,对每个文件进行如下处理:
226
-
227
- 1.1 从文件中读取代码内容,构造成一个字符串。
228
-
229
- 1.2 构造一条GPT请求,向`predict_no_ui_but_counting_down()`函数发送请求,等待GPT回复。
230
-
231
- 1.3 将GPT回复添加到机器人会话列表中,更新历史记录。
232
-
233
- 1.4 如果不是快速调试模式,则等待2秒钟,继续分析下一个文件。
234
-
235
- 2. 如果所有文件都分析完成,则向机器人会话列表中添加一条新消息,提示用户整个分析过程已经结束。
236
-
237
- 3. 返回机器人会话列表和历史记录。
238
-
239
- 除此之外,该程序文件还定义了若干个函数,用于针对不同类型的项目进行解析。这些函数会按照不同的方式调用`解析源代码()`函数。例如,对于Python项目,只需要分析.py文件;对于C项目,需要同时分析.h和.cpp文件等。每个函数中都会首先根据给定的项目路径读取相应的文件,然后调用`解析源代码()`函数进行分析。
240
-
241
- ## [20/22] 程序概述: crazy_functions\读文章写摘要.py
242
-
243
- 该程序文件为一个名为“读文章写摘要”的Python函数,用于解析项目文件夹中的.tex文件,并使用GPT模型生成文章的中英文摘要。函数使用了request_llm.bridge_chatgpt和toolbox模块中的函数,并包含两个子函数:解析Paper和CatchException。函数参数包括txt,top_p,temperature,chatbot,history,systemPromptTxt和WEB_PORT。执行过程中函数首先清空历史,然后根据项目文件夹中的.tex文件列表,对每个文件调用解析Paper函数生成中文摘要,最后根据所有文件的中文摘要,调用GPT模型生成英文摘要。函数运行过程中会将结果写入文件并返回聊天机器人和历史记录。
244
-
245
- ## [21/22] 程序概述: crazy_functions\高级功能函数模板.py
246
-
247
- 该程序文件为一个高级功能函数模板,文件名为"./crazy_functions\高级功能函数模板.py"。
248
-
249
- 该文件导入了两个模块,分别是"request_llm.bridge_chatgpt"和"toolbox"。其中"request_llm.bridge_chatgpt"模块包含了一个函数"predict_no_ui_long_connection",该函数用于请求GPT模型进行对话生成。"toolbox"模块包含了三个函数,分别是"catchException"、"report_exception"和"write_results_to_file"函数,这三个函数主要用于异常处理和日志记录等。
250
-
251
- 该文件定义了一个名为"高阶功能模板函数"的函数,并通过"decorator"装饰器将该函数装饰为一个异常处理函数,可以处理函数执行过程中出现的错误。该函数的作用是生成历史事件查询的问题,并向用户询问历史中哪些事件发生在指定日期,并索要相关图片。在查询完所有日期后,该函数返回所有历史事件及其相关图片的列表。其中,该函数的输入参数包括:
252
-
253
- 1. txt: 一个字符串,表示当前消息的文本内容。
254
- 2. top_p: 一个浮点数,表示GPT模型生成文本时的"top_p"参数。
255
- 3. temperature: 一个浮点数,表示GPT模型生成文本时的"temperature"参数。
256
- 4. chatbot: 一个列表,表示当前对话的记录列表。
257
- 5. history: 一个列表,表示当前对话的历史记录列表。
258
- 6. systemPromptTxt: 一个字符串,表示当前对话的系统提示信息。
259
- 7. WEB_PORT: 一个整数,表示当前应用程序的WEB端口号。
260
-
261
- 该函数在执行过程中,会先清空历史记录,以免输入溢出。然后,它会循环5次,生成5个历史事件查询的问题,并向用户请求输入相关信息。每次询问不携带之前的询问历史。在生成每个问题时,该函数会向"chatbot"列表中添加一条消息记录,并设置该记录的初始状态为"[Local Message] waiting gpt response."。然后,该函数会调用"predict_no_ui_long_connection"函数向GPT模型请求生成一段文本,并将生成的文本作为回答。如果请求过程中出现异常,该函数会忽略异常。最后,该函数将问题和回答添加到"chatbot"列表和"history"列表中,并将"chatbot"和"history"列表作为函数的返回值返回。
262
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
toolbox.py CHANGED
@@ -1,13 +1,10 @@
1
  import markdown
2
- import mdtex2html
3
- import threading
4
  import importlib
5
  import traceback
6
  import inspect
7
  import re
8
  from latex2mathml.converter import convert as tex2mathml
9
  from functools import wraps, lru_cache
10
-
11
  ############################### 插件输入输出接驳区 #######################################
12
  class ChatBotWithCookies(list):
13
  def __init__(self, cookie):
@@ -25,9 +22,10 @@ class ChatBotWithCookies(list):
25
 
26
  def ArgsGeneralWrapper(f):
27
  """
28
- 装饰器函数,用于重组输入参数,改变输入参数的顺序与结构。
29
  """
30
- def decorated(cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt, *args):
 
31
  txt_passon = txt
32
  if txt == "" and txt2 != "": txt_passon = txt2
33
  # 引入一个有cookie的chatbot
@@ -37,8 +35,9 @@ def ArgsGeneralWrapper(f):
37
  })
38
  llm_kwargs = {
39
  'api_key': cookies['api_key'],
40
- 'llm_model': cookies['llm_model'],
41
  'top_p':top_p,
 
42
  'temperature':temperature,
43
  }
44
  plugin_kwargs = {
@@ -55,8 +54,47 @@ def update_ui(chatbot, history, msg='正常', **kwargs): # 刷新界面
55
  """
56
  assert isinstance(chatbot, ChatBotWithCookies), "在传递chatbot的过程中不要将其丢弃。必要时,可用clear将其清空,然后用for+append循环重新赋值。"
57
  yield chatbot.get_cookies(), chatbot, history, msg
58
- ############################### ################## #######################################
59
- ##########################################################################################
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  def get_reduce_token_percent(text):
62
  """
@@ -75,71 +113,11 @@ def get_reduce_token_percent(text):
75
  except:
76
  return 0.5, '不详'
77
 
78
- def predict_no_ui_but_counting_down(i_say, i_say_show_user, chatbot, llm_kwargs, history=[], sys_prompt='', long_connection=True):
79
- """
80
- * 此函数未来将被弃用(替代函数 request_gpt_model_in_new_thread_with_ui_alive 文件 chatgpt_academic/crazy_functions/crazy_utils)
81
-
82
- 调用简单的predict_no_ui接口,但是依然保留了些许界面心跳功能,当对话太长时,会自动采用二分法截断
83
- i_say: 当前输入
84
- i_say_show_user: 显示到对话界面上的当前输入,例如,输入整个文件时,你绝对不想把文件的内容都糊到对话界面上
85
- chatbot: 对话界面句柄
86
- top_p, temperature: gpt参数
87
- history: gpt参数 对话历史
88
- sys_prompt: gpt参数 sys_prompt
89
- long_connection: 是否采用更稳定的连接方式(推荐)(已弃用)
90
- """
91
- import time
92
- from request_llm.bridge_chatgpt import predict_no_ui_long_connection
93
- from toolbox import get_conf
94
- TIMEOUT_SECONDS, MAX_RETRY = get_conf('TIMEOUT_SECONDS', 'MAX_RETRY')
95
- # 多线程的时候,需要一个mutable结构在不同线程之间传递信息
96
- # list就是最简单的mutable结构,我们第一个位置放gpt输出,第二个位置传递报错信息
97
- mutable = [None, '']
98
- # multi-threading worker
99
-
100
- def mt(i_say, history):
101
- while True:
102
- try:
103
- mutable[0] = predict_no_ui_long_connection(
104
- inputs=i_say, llm_kwargs=llm_kwargs, history=history, sys_prompt=sys_prompt)
105
-
106
- except ConnectionAbortedError as token_exceeded_error:
107
- # 尝试计算比例,尽可能多地保留文本
108
- p_ratio, n_exceed = get_reduce_token_percent(
109
- str(token_exceeded_error))
110
- if len(history) > 0:
111
- history = [his[int(len(his) * p_ratio):]
112
- for his in history if his is not None]
113
- else:
114
- i_say = i_say[: int(len(i_say) * p_ratio)]
115
- mutable[1] = f'警告,文本过长将进行截断,Token溢出数:{n_exceed},截断比例:{(1-p_ratio):.0%}。'
116
- except TimeoutError as e:
117
- mutable[0] = '[Local Message] 请求超时。'
118
- raise TimeoutError
119
- except Exception as e:
120
- mutable[0] = f'[Local Message] 异常:{str(e)}.'
121
- raise RuntimeError(f'[Local Message] 异常:{str(e)}.')
122
- # 创建新线程发出http请求
123
- thread_name = threading.Thread(target=mt, args=(i_say, history))
124
- thread_name.start()
125
- # 原来的线程则负责持续更新UI,实现一个超时倒计时,并等待新线程的任务完成
126
- cnt = 0
127
- while thread_name.is_alive():
128
- cnt += 1
129
- chatbot[-1] = (i_say_show_user,
130
- f"[Local Message] {mutable[1]}waiting gpt response {cnt}/{TIMEOUT_SECONDS*2*(MAX_RETRY+1)}"+''.join(['.']*(cnt % 4)))
131
- yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
132
- time.sleep(1)
133
- # 把gpt的输出从mutable中取出来
134
- gpt_say = mutable[0]
135
- if gpt_say == '[Local Message] Failed with timeout.':
136
- raise TimeoutError
137
- return gpt_say
138
 
139
 
140
  def write_results_to_file(history, file_name=None):
141
  """
142
- 将对话记录history以Markdown格式写入文件中。如果没有指定文件名,则使用当前时间生成文件名。
143
  """
144
  import os
145
  import time
@@ -167,7 +145,7 @@ def write_results_to_file(history, file_name=None):
167
 
168
  def regular_txt_to_markdown(text):
169
  """
170
- 将普通文本转换为Markdown格式的文本。
171
  """
172
  text = text.replace('\n', '\n\n')
173
  text = text.replace('\n\n\n', '\n\n')
@@ -175,48 +153,11 @@ def regular_txt_to_markdown(text):
175
  return text
176
 
177
 
178
- def CatchException(f):
179
- """
180
- 装饰器函数,捕捉函数f中的异常并封装到一个生成器中返回,并显示到聊天当中。
181
- """
182
- @wraps(f)
183
- def decorated(txt, top_p, temperature, chatbot, history, systemPromptTxt, WEB_PORT):
184
- try:
185
- yield from f(txt, top_p, temperature, chatbot, history, systemPromptTxt, WEB_PORT)
186
- except Exception as e:
187
- from check_proxy import check_proxy
188
- from toolbox import get_conf
189
- proxies, = get_conf('proxies')
190
- tb_str = '```\n' + traceback.format_exc() + '```'
191
- if chatbot is None or len(chatbot) == 0:
192
- chatbot = [["插件调度异常", "异常原因"]]
193
- chatbot[-1] = (chatbot[-1][0],
194
- f"[Local Message] 实验性函数调用出错: \n\n{tb_str} \n\n当前代理可用性: \n\n{check_proxy(proxies)}")
195
- yield from update_ui(chatbot=chatbot, history=history, msg=f'异常 {e}') # 刷新界面
196
- return decorated
197
-
198
-
199
- def HotReload(f):
200
- """
201
- HotReload的装饰器函数,用于实现Python函数插件的热更新。
202
- 函数热更新是指在不停止程序运行的情况下,更新函数代码,从而达到实时更新功能。
203
- 在装饰器内部,使用wraps(f)来保留函数的元信息,并定义了一个名为decorated的内部函数。
204
- 内部函数通过使用importlib模块的reload函数和inspect模块的getmodule函数来重新加载并获取函数模块,
205
- 然后通过getattr函数获取函数名,并在新模块中重新加载函数。
206
- 最后,使用yield from语句返回重新加载过的函数,并在被装饰的函数上执行。
207
- 最终,装饰器函数返回内部函数。这个内部函数可以将函数的原始定义更新为最新版本,并执行函数的新版本。
208
- """
209
- @wraps(f)
210
- def decorated(*args, **kwargs):
211
- fn_name = f.__name__
212
- f_hot_reload = getattr(importlib.reload(inspect.getmodule(f)), fn_name)
213
- yield from f_hot_reload(*args, **kwargs)
214
- return decorated
215
 
216
 
217
  def report_execption(chatbot, history, a, b):
218
  """
219
- 向chatbot中添加错误信息
220
  """
221
  chatbot.append((a, b))
222
  history.append(a)
@@ -225,7 +166,7 @@ def report_execption(chatbot, history, a, b):
225
 
226
  def text_divide_paragraph(text):
227
  """
228
- 将文本按照段落分隔符分割开,生成带有段落标签的HTML代码。
229
  """
230
  if '```' in text:
231
  # careful input
@@ -241,7 +182,7 @@ def text_divide_paragraph(text):
241
 
242
  def markdown_convertion(txt):
243
  """
244
- 将Markdown格式的文本转换为HTML格式。如果包含数学公式,则先将公式转换为HTML格式。
245
  """
246
  pre = '<div class="markdown-body">'
247
  suf = '</div>'
@@ -333,7 +274,7 @@ def close_up_code_segment_during_stream(gpt_reply):
333
 
334
  def format_io(self, y):
335
  """
336
- 将输入和输出解析为HTML格式。将y中最后一项的输入部分段落化,并将输出部分的Markdown和数学公式转换为HTML格式。
337
  """
338
  if y is None or y == []:
339
  return []
@@ -349,7 +290,7 @@ def format_io(self, y):
349
 
350
  def find_free_port():
351
  """
352
- 返回当前系统中可用的未使用端口。
353
  """
354
  import socket
355
  from contextlib import closing
@@ -428,7 +369,7 @@ def find_recent_files(directory):
428
  return recent_files
429
 
430
 
431
- def on_file_uploaded(files, chatbot, txt):
432
  if len(files) == 0:
433
  return chatbot, txt
434
  import shutil
@@ -450,13 +391,18 @@ def on_file_uploaded(files, chatbot, txt):
450
  dest_dir=f'private_upload/{time_tag}/{file_origin_name}.extract')
451
  moved_files = [fp for fp in glob.glob(
452
  'private_upload/**/*', recursive=True)]
453
- txt = f'private_upload/{time_tag}'
 
 
 
 
 
454
  moved_files_str = '\t\n\n'.join(moved_files)
455
  chatbot.append(['我上传了文件,请查收',
456
  f'[Local Message] 收到以下文件: \n\n{moved_files_str}' +
457
  f'\n\n调用路径参数已自动修正到: \n\n{txt}' +
458
  f'\n\n现在您点击任意实验功能时,以上文件将被作为输入参数'+err_msg])
459
- return chatbot, txt
460
 
461
 
462
  def on_report_generated(files, chatbot):
@@ -469,9 +415,43 @@ def on_report_generated(files, chatbot):
469
  return report_files, chatbot
470
 
471
  def is_openai_api_key(key):
472
- # 正确的 API_KEY 是 "sk-" + 48 位大小写字母数字的组合
473
  API_MATCH = re.match(r"sk-[a-zA-Z0-9]{48}$", key)
474
- return API_MATCH
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
 
476
  @lru_cache(maxsize=128)
477
  def read_single_conf_with_lru_cache(arg):
@@ -482,14 +462,13 @@ def read_single_conf_with_lru_cache(arg):
482
  r = getattr(importlib.import_module('config'), arg)
483
  # 在读取API_KEY时,检查一下是不是忘了改config
484
  if arg == 'API_KEY':
485
- if is_openai_api_key(r):
486
  print亮绿(f"[API_KEY] 您的 API_KEY 是: {r[:15]}*** API_KEY 导入成功")
487
  else:
488
- print亮红( "[API_KEY] 正确的 API_KEY 是 'sk-' + '48 位大小写字母数字' 的组合,请在config文件中修改API密钥, 添加海外代理之后再运行。" + \
489
- "(如果您刚更新过代码,请确保旧版config_private文件中没有遗留任何新增键值)")
490
  if arg == 'proxies':
491
  if r is None:
492
- print亮红('[PROXY] 网络代理状态:未配置。无代理状态下很可能无法访问。建议:检查USE_PROXY选项是否修改。')
493
  else:
494
  print亮绿('[PROXY] 网络代理状态:已配置。配置信息如下:', r)
495
  assert isinstance(r, dict), 'proxies格式错误,请注意proxies选项的格式,不要遗漏括号。'
 
1
  import markdown
 
 
2
  import importlib
3
  import traceback
4
  import inspect
5
  import re
6
  from latex2mathml.converter import convert as tex2mathml
7
  from functools import wraps, lru_cache
 
8
  ############################### 插件输入输出接驳区 #######################################
9
  class ChatBotWithCookies(list):
10
  def __init__(self, cookie):
 
22
 
23
  def ArgsGeneralWrapper(f):
24
  """
25
+ 装饰器函数,用于重组输入参数,改变输入参数的顺序与结构。
26
  """
27
+ def decorated(cookies, max_length, llm_model, txt, txt2, top_p, temperature, chatbot, history, system_prompt, *args):
28
+ from request_llm.bridge_all import model_info
29
  txt_passon = txt
30
  if txt == "" and txt2 != "": txt_passon = txt2
31
  # 引入一个有cookie的chatbot
 
35
  })
36
  llm_kwargs = {
37
  'api_key': cookies['api_key'],
38
+ 'llm_model': llm_model,
39
  'top_p':top_p,
40
+ 'max_length': max_length,
41
  'temperature':temperature,
42
  }
43
  plugin_kwargs = {
 
54
  """
55
  assert isinstance(chatbot, ChatBotWithCookies), "在传递chatbot的过程中不要将其丢弃。必要时,可用clear将其清空,然后用for+append循环重新赋值。"
56
  yield chatbot.get_cookies(), chatbot, history, msg
57
+
58
+ def CatchException(f):
59
+ """
60
+ 装饰器函数,捕捉函数f中的异常并封装到一个生成器中返回,并显示到聊天当中。
61
+ """
62
+ @wraps(f)
63
+ def decorated(txt, top_p, temperature, chatbot, history, systemPromptTxt, WEB_PORT):
64
+ try:
65
+ yield from f(txt, top_p, temperature, chatbot, history, systemPromptTxt, WEB_PORT)
66
+ except Exception as e:
67
+ from check_proxy import check_proxy
68
+ from toolbox import get_conf
69
+ proxies, = get_conf('proxies')
70
+ tb_str = '```\n' + traceback.format_exc() + '```'
71
+ if chatbot is None or len(chatbot) == 0:
72
+ chatbot = [["插件调度异常", "异常原因"]]
73
+ chatbot[-1] = (chatbot[-1][0],
74
+ f"[Local Message] 实验性函数调用出错: \n\n{tb_str} \n\n当前代理可用性: \n\n{check_proxy(proxies)}")
75
+ yield from update_ui(chatbot=chatbot, history=history, msg=f'异常 {e}') # 刷新界面
76
+ return decorated
77
+
78
+
79
+ def HotReload(f):
80
+ """
81
+ HotReload的装饰器函数,用于实现Python函数插件的热更新。
82
+ 函数热更新是指在不停止程序运行的情况下,更新函数代码,从而达到实时更新功能。
83
+ 在装饰器内部,使用wraps(f)来保留函数的元信息,并定义了一个名为decorated的内部函数。
84
+ 内部函数通过使用importlib模块的reload函数和inspect模块的getmodule函数来重新加载并获取函数模块,
85
+ 然后通过getattr函数获取函数名,并在新模块中重新加载函数。
86
+ 最后,使用yield from语句返回重新加载过的函数,并在被装饰的函数上执行。
87
+ 最终,装饰器函数返回内部函数。这个内部函数可以将函数的原始定义更新为最新版本,并执行函数的新版本。
88
+ """
89
+ @wraps(f)
90
+ def decorated(*args, **kwargs):
91
+ fn_name = f.__name__
92
+ f_hot_reload = getattr(importlib.reload(inspect.getmodule(f)), fn_name)
93
+ yield from f_hot_reload(*args, **kwargs)
94
+ return decorated
95
+
96
+
97
+ ####################################### 其他小工具 #####################################
98
 
99
  def get_reduce_token_percent(text):
100
  """
 
113
  except:
114
  return 0.5, '不详'
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
 
118
  def write_results_to_file(history, file_name=None):
119
  """
120
+ 将对话记录history以Markdown格式写入文件中。如果没有指定文件名,则使用当前时间生成文件名。
121
  """
122
  import os
123
  import time
 
145
 
146
  def regular_txt_to_markdown(text):
147
  """
148
+ 将普通文本转换为Markdown格式的文本。
149
  """
150
  text = text.replace('\n', '\n\n')
151
  text = text.replace('\n\n\n', '\n\n')
 
153
  return text
154
 
155
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
 
157
 
158
  def report_execption(chatbot, history, a, b):
159
  """
160
+ 向chatbot中添加错误信息
161
  """
162
  chatbot.append((a, b))
163
  history.append(a)
 
166
 
167
  def text_divide_paragraph(text):
168
  """
169
+ 将文本按照段落分隔符分割开,生成带有段落标签的HTML代码。
170
  """
171
  if '```' in text:
172
  # careful input
 
182
 
183
  def markdown_convertion(txt):
184
  """
185
+ 将Markdown格式的文本转换为HTML格式。如果包含数学公式,则先将公式转换为HTML格式。
186
  """
187
  pre = '<div class="markdown-body">'
188
  suf = '</div>'
 
274
 
275
  def format_io(self, y):
276
  """
277
+ 将输入和输出解析为HTML格式。将y中最后一项的输入部分段落化,并将输出部分的Markdown和数学公式转换为HTML格式。
278
  """
279
  if y is None or y == []:
280
  return []
 
290
 
291
  def find_free_port():
292
  """
293
+ 返回当前系统中可用的未使用端口。
294
  """
295
  import socket
296
  from contextlib import closing
 
369
  return recent_files
370
 
371
 
372
+ def on_file_uploaded(files, chatbot, txt, txt2, checkboxes):
373
  if len(files) == 0:
374
  return chatbot, txt
375
  import shutil
 
391
  dest_dir=f'private_upload/{time_tag}/{file_origin_name}.extract')
392
  moved_files = [fp for fp in glob.glob(
393
  'private_upload/**/*', recursive=True)]
394
+ if "底部输入区" in checkboxes:
395
+ txt = ""
396
+ txt2 = f'private_upload/{time_tag}'
397
+ else:
398
+ txt = f'private_upload/{time_tag}'
399
+ txt2 = ""
400
  moved_files_str = '\t\n\n'.join(moved_files)
401
  chatbot.append(['我上传了文件,请查收',
402
  f'[Local Message] 收到以下文件: \n\n{moved_files_str}' +
403
  f'\n\n调用路径参数已自动修正到: \n\n{txt}' +
404
  f'\n\n现在您点击任意实验功能时,以上文件将被作为输入参数'+err_msg])
405
+ return chatbot, txt, txt2
406
 
407
 
408
  def on_report_generated(files, chatbot):
 
415
  return report_files, chatbot
416
 
417
  def is_openai_api_key(key):
 
418
  API_MATCH = re.match(r"sk-[a-zA-Z0-9]{48}$", key)
419
+ return bool(API_MATCH)
420
+
421
+ def is_api2d_key(key):
422
+ if key.startswith('fk') and len(key) == 41:
423
+ return True
424
+ else:
425
+ return False
426
+
427
+ def is_any_api_key(key):
428
+ if ',' in key:
429
+ keys = key.split(',')
430
+ for k in keys:
431
+ if is_any_api_key(k): return True
432
+ return False
433
+ else:
434
+ return is_openai_api_key(key) or is_api2d_key(key)
435
+
436
+
437
+ def select_api_key(keys, llm_model):
438
+ import random
439
+ avail_key_list = []
440
+ key_list = keys.split(',')
441
+
442
+ if llm_model.startswith('gpt-'):
443
+ for k in key_list:
444
+ if is_openai_api_key(k): avail_key_list.append(k)
445
+
446
+ if llm_model.startswith('api2d-'):
447
+ for k in key_list:
448
+ if is_api2d_key(k): avail_key_list.append(k)
449
+
450
+ if len(avail_key_list) == 0:
451
+ raise RuntimeError(f"您提供的api-key不满足要求,不包含任何可用于{llm_model}的api-key。")
452
+
453
+ api_key = random.choice(avail_key_list) # 随机负载均衡
454
+ return api_key
455
 
456
  @lru_cache(maxsize=128)
457
  def read_single_conf_with_lru_cache(arg):
 
462
  r = getattr(importlib.import_module('config'), arg)
463
  # 在读取API_KEY时,检查一下是不是忘了改config
464
  if arg == 'API_KEY':
465
+ if is_any_api_key(r):
466
  print亮绿(f"[API_KEY] 您的 API_KEY 是: {r[:15]}*** API_KEY 导入成功")
467
  else:
468
+ print亮红( "[API_KEY] 正确的 API_KEY 是'sk'开头的51位密钥(OpenAI),或者 'fk'开头的41位密钥,请在config文件中修改API密钥之后再运行。")
 
469
  if arg == 'proxies':
470
  if r is None:
471
+ print亮红('[PROXY] 网络代理状态:未配置。无代理状态下很可能无法访问OpenAI家族的模型。建议:检查USE_PROXY选项是否修改。')
472
  else:
473
  print亮绿('[PROXY] 网络代理状态:已配置。配置信息如下:', r)
474
  assert isinstance(r, dict), 'proxies格式错误,请注意proxies选项的格式,不要遗漏括号。'
version CHANGED
@@ -1,5 +1,5 @@
1
  {
2
- "version": 2.68,
3
  "show_feature": true,
4
- "new_feature": "改善理解pdf(chatpdf)功能 <-> 修复读取罕见字符的BUG <-> 如果一键更新失败,可前往github手动更新"
5
  }
 
1
  {
2
+ "version": 3.1,
3
  "show_feature": true,
4
+ "new_feature": "支持ChatGLM <-> 支持多LLM模型同时对话"
5
  }