diff --git a/README.md b/README.md
index e606db2..e409d56 100644
--- a/README.md
+++ b/README.md
@@ -111,7 +111,7 @@ python -m pip install -r requirements.txt
# (II-3)python -m pip install -r requirements.txt
```
-如果需要支持清华ChatGLM后端,需要额外安装更多依赖(不熟悉python、电脑配置不佳者,建议不要尝试):
+如果需要支持清华ChatGLM后端,需要额外安装更多依赖(前提条件:熟悉python + 电脑配置够强):
```sh
python -m pip install -r request_llm/requirements_chatglm.txt
```
@@ -133,22 +133,25 @@ python main.py
- 函数插件区下拉菜单中有更多功能可供选择
```
-## 安装-方法2:使用Docker (Linux)
+## 安装-方法2:使用Docker
1. 仅ChatGPT(推荐大多数人选择)
+
``` sh
# 下载项目
git clone https://github.com/binary-husky/chatgpt_academic.git
cd chatgpt_academic
-# 配置 海外Proxy 和 OpenAI API KEY
+# 配置 “海外Proxy”, “API_KEY” 以及 “WEB_PORT” (例如50923) 等
用任意文本编辑器编辑 config.py
# 安装
docker build -t gpt-academic .
-# 运行
+#(最后一步-选择1)在Linux环境下,用`--net=host`更方便快捷
docker run --rm -it --net=host gpt-academic
+#(最后一步-选择2)在macOS/windows环境下,只能用-p选项将容器上的端口(例如50923)暴露给主机上的端口
+docker run --rm -it -p 50923:50923 gpt-academic
```
-2. ChatGPT+ChatGLM(需要对docker熟悉 + 读懂Dockerfile + 电脑配置够强)
+2. ChatGPT+ChatGLM(需要对Docker熟悉 + 读懂Dockerfile + 电脑配置够强)
``` sh
# 修改Dockerfile
@@ -261,6 +264,14 @@ docker run --rm -it --net=host --gpus=all gpt-academic bash
+8. 互联网在线信息综合
+
+
+

+
+
+
+
## Todo 与 版本规划:
- version 3.2+ (todo): 函数插件支持更多参数接口
- version 3.1: 支持同时问询多个gpt模型!支持api2d,支持多个apikey负载均衡
diff --git a/config.py b/config.py
index e24c68b..0ad723b 100644
--- a/config.py
+++ b/config.py
@@ -56,3 +56,7 @@ CONCURRENT_COUNT = 100
# 设置用户名和密码(不需要修改)(相关功能不稳定,与gradio版本和网络都相关,如果本地使用不建议加这个)
# [("username", "password"), ("username2", "password2"), ...]
AUTHENTICATION = []
+
+# 重新URL重新定向,实现更换API_URL的作用(常规情况下,不要修改!!)
+# 格式 {"https://api.openai.com/v1/chat/completions": "重定向的URL"}
+API_URL_REDIRECT = {}
diff --git a/crazy_functional.py b/crazy_functional.py
index 090d712..ccaed45 100644
--- a/crazy_functional.py
+++ b/crazy_functional.py
@@ -173,19 +173,23 @@ def get_crazy_functions():
###################### 第三组插件 ###########################
# [第三组插件]: 尚未充分测试的函数插件,放在这里
- try:
- from crazy_functions.下载arxiv论文翻译摘要 import 下载arxiv论文并翻译摘要
- function_plugins.update({
- "一键下载arxiv论文并翻译摘要(先在input输入编号,如1812.10695)": {
- "Color": "stop",
- "AsButton": False, # 加入下拉菜单中
- "Function": HotReload(下载arxiv论文并翻译摘要)
- }
- })
-
- except Exception as err:
- print(f'[下载arxiv论文并翻译摘要] 插件导入失败 {str(err)}')
+ from crazy_functions.下载arxiv论文翻译摘要 import 下载arxiv论文并翻译摘要
+ function_plugins.update({
+ "一键下载arxiv论文并翻译摘要(先在input输入编号,如1812.10695)": {
+ "Color": "stop",
+ "AsButton": False, # 加入下拉菜单中
+ "Function": HotReload(下载arxiv论文并翻译摘要)
+ }
+ })
+ from crazy_functions.联网的ChatGPT import 连接网络回答问题
+ function_plugins.update({
+ "连接网络回答问题(先输入问题,再点击按钮,需要访问谷歌)": {
+ "Color": "stop",
+ "AsButton": False, # 加入下拉菜单中
+ "Function": HotReload(连接网络回答问题)
+ }
+ })
from crazy_functions.解析项目源代码 import 解析任意code项目
function_plugins.update({
diff --git a/crazy_functions/crazy_functions_test.py b/crazy_functions/crazy_functions_test.py
index 2838e54..7b0f072 100644
--- a/crazy_functions/crazy_functions_test.py
+++ b/crazy_functions/crazy_functions_test.py
@@ -12,7 +12,7 @@ def validate_path():
sys.path.append(root_dir_assume)
validate_path() # validate path so you can run from base directory
-
+from colorful import *
from toolbox import get_conf, ChatBotWithCookies
proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, API_KEY = \
get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'API_KEY')
@@ -79,14 +79,46 @@ def test_下载arxiv论文并翻译摘要():
for cookies, cb, hist, msg in 下载arxiv论文并翻译摘要(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
print(cb)
-test_解析一个Python项目()
-test_Latex英文润色()
-test_Markdown中译英()
-test_批量翻译PDF文档()
-test_谷歌检索小助手()
-test_总结word文档()
-test_下载arxiv论文并翻译摘要()
-test_解析一个Cpp项目()
+def test_联网回答问题():
+ from crazy_functions.联网的ChatGPT import 连接网络回答问题
+ # txt = "“我们称之为高效”是什么梗?"
+ # >> 从第0份、第1份、第2份搜索结果可以看出,“我们称之为高效”是指在游戏社区中,用户们用来形容一些游戏策略或行为非常高效且能够带来好的效果的用语。这个用语最初可能是在群星(Stellaris)这个游戏里面流行起来的,后来也传播到了其他游戏中,比如巨像(Titan)等游戏。其中第1份搜索结果中的一篇文章也指出,“我们称之为高效”这 一用语来源于群星(Stellaris)游戏中的一个情节。
+ # txt = "为什么说枪毙P社玩家没有一个冤枉的?"
+ # >> 它们都是关于一个知乎用户所发的帖子,引用了一群游戏玩家对于需要对P社玩家进行枪毙的讨论,这个话题的本质是玩家们对于P 社游戏中的政治与历史元素的不同看法,以及其中不少玩家以极端立场宣扬的想法和言论,因此有人就以枪毙这些玩家来回应此类言论。但是这个话题本身并没有实质内容,只是一个玩笑或者恶搞,并不应该被当做真实的态度或者观点,因此这种说法没有实际意义。
+ # txt = "谁是应急食品?"
+ # >> '根据以上搜索结果可以得知,应急食品是“原神”游戏中的角色派蒙的外号。'
+ # txt = "道路千万条,安全第一条。后面两句是?"
+ # >> '行车不规范,亲人两行泪。'
+ # txt = "What is in the canister?"
+ # >> Rainbow Six Siege 游戏中 Smoke 的 Canister 中装有何种物质相关的官方信息。
+ # txt = "失败的man是什么?"
+ # >> 根据第1份搜索结果,可以得知失败的man是指一位在B站购买了蜘蛛侠COS服后穿上后被网友嘲笑的UP主,而“失败的man”是蜘蛛侠英文名“spiderman”的谐音梗,并且网友们还 给这位UP主起了“苍蝇侠”的外号。因此,失败的man是指这位UP主在穿上蜘蛛侠COS服后被网友嘲笑的情况。
+ # txt = "老六是什么,起源于哪里?"
+ # >> 老六是网络流行语,最初起源于游戏《CSGO》,指游戏中玩家中独来独往、游离于队伍之外的“自由人”或玩得比较菜或者玩得比较阴险的人 ,后来逐渐演变成指玩得比较阴险的玩家。
+ # txt = "罗小黑战记因为什么经常被吐槽?"
+ # >> 3. 更新速度。罗小黑战记的更新时间不定,时而快时而慢,给观众留下了等待的时间过长的印象。
+ # txt = "沙特、伊朗最近的关系如何?"
+ # >> 最近在中国的斡旋下,沙特和伊朗于3月10日达成了恢复两国外交关系的协议,这表明两国关系已经重新回到正常化状态。
+ # txt = "You should have gone for the head. What does that mean?"
+ # >> The phrase "You should have gone for the head" is a quote from the Marvel movies, Avengers: Infinity War and Avengers: Endgame. It was spoken by the character Thanos in Infinity War and by Thor in Endgame.
+ txt = "AutoGPT是什么?"
+ # >> AutoGPT是一个基于GPT-4语言模型的开源应用程序。它可以根据用户需求自主执行任务,包括事件分析、营销方案撰写、代码编程、数学运算等等,并完全不需要用户插手。它可以自己思考,给出实现的步骤和实现细节,甚至可以自问自答执 行任务。最近它在GitHub上爆火,成为了业内最热门的项目之一。
+ # txt = "钟离带什么圣遗物?"
+ for cookies, cb, hist, msg in 连接网络回答问题(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
+ print("当前问答:", cb[-1][-1].replace("\n"," "))
+ for i, it in enumerate(cb): print亮蓝(it[0]); print亮黄(it[1])
+
+# test_解析一个Python项目()
+# test_Latex英文润色()
+# test_Markdown中译英()
+# test_批量翻译PDF文档()
+# test_谷歌检索小助手()
+# test_总结word文档()
+# test_下载arxiv论文并翻译摘要()
+# test_解析一个Cpp项目()
+
+test_联网回答问题()
+
input("程序完成,回车退出。")
print("退出。")
\ No newline at end of file
diff --git a/crazy_functions/联网的ChatGPT.py b/crazy_functions/联网的ChatGPT.py
new file mode 100644
index 0000000..6a7d118
--- /dev/null
+++ b/crazy_functions/联网的ChatGPT.py
@@ -0,0 +1,102 @@
+from toolbox import CatchException, update_ui
+from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive, input_clipping
+import requests
+from bs4 import BeautifulSoup
+from request_llm.bridge_all import model_info
+
+def google(query, proxies):
+ query = query # 在此处替换您要搜索的关键词
+ url = f"https://www.google.com/search?q={query}"
+ headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36'}
+ response = requests.get(url, headers=headers, proxies=proxies)
+ soup = BeautifulSoup(response.content, 'html.parser')
+ results = []
+ for g in soup.find_all('div', class_='g'):
+ anchors = g.find_all('a')
+ if anchors:
+ link = anchors[0]['href']
+ if link.startswith('/url?q='):
+ link = link[7:]
+ if not link.startswith('http'):
+ continue
+ title = g.find('h3').text
+ item = {'title': title, 'link': link}
+ results.append(item)
+
+ for r in results:
+ print(r['link'])
+ return results
+
+def scrape_text(url, proxies) -> str:
+ """Scrape text from a webpage
+
+ Args:
+ url (str): The URL to scrape text from
+
+ Returns:
+ str: The scraped text
+ """
+ headers = {
+ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36',
+ 'Content-Type': 'text/plain',
+ }
+ try:
+ response = requests.get(url, headers=headers, proxies=proxies, timeout=8)
+ if response.encoding == "ISO-8859-1": response.encoding = response.apparent_encoding
+ except:
+ return "无法连接到该网页"
+ soup = BeautifulSoup(response.text, "html.parser")
+ for script in soup(["script", "style"]):
+ script.extract()
+ text = soup.get_text()
+ lines = (line.strip() for line in text.splitlines())
+ chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
+ text = "\n".join(chunk for chunk in chunks if chunk)
+ return text
+
+@CatchException
+def 连接网络回答问题(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port):
+ """
+ txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径
+ llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行
+ plugin_kwargs 插件模型的参数,暂时没有用武之地
+ chatbot 聊天显示框的句柄,用于显示给用户
+ history 聊天历史,前情提要
+ system_prompt 给gpt的静默提醒
+ web_port 当前软件运行的端口号
+ """
+ history = [] # 清空历史,以免输入溢出
+ chatbot.append((f"请结合互联网信息回答以下问题:{txt}",
+ "[Local Message] 请注意,您正在调用一个[函数插件]的模板,该模板可以实现ChatGPT联网信息综合。该函数面向希望实现更多有趣功能的开发者,它可以作为创建新功能函数的模板。您若希望分享新的功能模组,请不吝PR!"))
+ yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新
+
+ # ------------- < 第1步:爬取搜索引擎的结果 > -------------
+ from toolbox import get_conf
+ proxies, = get_conf('proxies')
+ urls = google(txt, proxies)
+ history = []
+
+ # ------------- < 第2步:依次访问网页 > -------------
+ max_search_result = 5 # 最多收纳多少个网页的结果
+ for index, url in enumerate(urls[:max_search_result]):
+ res = scrape_text(url['link'], proxies)
+ history.extend([f"第{index}份搜索结果:", res])
+ chatbot.append([f"第{index}份搜索结果:", res[:500]+"......"])
+ yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新
+
+ # ------------- < 第3步:ChatGPT综合 > -------------
+ i_say = f"从以上搜索结果中抽取信息,然后回答问题:{txt}"
+ i_say, history = input_clipping( # 裁剪输入,从最长的条目开始裁剪,防止爆token
+ inputs=i_say,
+ history=history,
+ max_token_limit=model_info[llm_kwargs['llm_model']]['max_token']*3//4
+ )
+ gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(
+ inputs=i_say, inputs_show_user=i_say,
+ llm_kwargs=llm_kwargs, chatbot=chatbot, history=history,
+ sys_prompt="请从给定的若干条搜索结果中抽取信息,对最相关的两个搜索结果进行总结,然后回答问题。"
+ )
+ chatbot[-1] = (i_say, gpt_say)
+ history.append(i_say);history.append(gpt_say)
+ yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新
+
diff --git a/request_llm/README.md b/request_llm/README.md
index 973adea..4a912d1 100644
--- a/request_llm/README.md
+++ b/request_llm/README.md
@@ -1,4 +1,4 @@
-# 如何使用其他大语言模型(v3.0分支测试中)
+# 如何使用其他大语言模型
## ChatGLM
@@ -15,7 +15,7 @@ LLM_MODEL = "chatglm"
---
-## Text-Generation-UI (TGUI)
+## Text-Generation-UI (TGUI,调试中,暂不可用)
### 1. 部署TGUI
``` sh
diff --git a/request_llm/bridge_all.py b/request_llm/bridge_all.py
index f1f4ee1..311dc6f 100644
--- a/request_llm/bridge_all.py
+++ b/request_llm/bridge_all.py
@@ -1,16 +1,17 @@
"""
- 该文件中主要包含2个函数
+ 该文件中主要包含2个函数,是所有LLM的通用接口,它们会继续向下调用更底层的LLM模型,处理多模型并行等细节
- 不具备多线程能力的函数:
- 1. predict: 正常对话时使用,具备完备的交互功能,不可多线程
+ 不具备多线程能力的函数:正常对话时使用,具备完备的交互功能,不可多线程
+ 1. predict(...)
- 具备多线程调用能力的函数
- 2. predict_no_ui_long_connection:在实验过程中发现调用predict_no_ui处理长文档时,和openai的连接容易断掉,这个函数用stream的方式解决这个问题,同样支持多线程
+ 具备多线程调用能力的函数:在函数插件中被调用,灵活而简洁
+ 2. predict_no_ui_long_connection(...)
"""
import tiktoken
-from functools import wraps, lru_cache
+from functools import lru_cache
from concurrent.futures import ThreadPoolExecutor
+from toolbox import get_conf
from .bridge_chatgpt import predict_no_ui_long_connection as chatgpt_noui
from .bridge_chatgpt import predict as chatgpt_ui
@@ -42,18 +43,37 @@ class LazyloadTiktoken(object):
def decode(self, *args, **kwargs):
encoder = self.get_encoder(self.model)
return encoder.decode(*args, **kwargs)
-
+
+# Endpoint 重定向
+API_URL_REDIRECT, = get_conf("API_URL_REDIRECT")
+openai_endpoint = "https://api.openai.com/v1/chat/completions"
+api2d_endpoint = "https://openai.api2d.net/v1/chat/completions"
+# 兼容旧版的配置
+try:
+ API_URL, = get_conf("API_URL")
+ if API_URL != "https://api.openai.com/v1/chat/completions":
+ openai_endpoint = API_URL
+ print("警告!API_URL配置选项将被弃用,请更换为API_URL_REDIRECT配置")
+except:
+ pass
+# 新版配置
+if openai_endpoint in API_URL_REDIRECT: openai_endpoint = API_URL_REDIRECT[openai_endpoint]
+if api2d_endpoint in API_URL_REDIRECT: api2d_endpoint = API_URL_REDIRECT[api2d_endpoint]
+
+
+# 获取tokenizer
tokenizer_gpt35 = LazyloadTiktoken("gpt-3.5-turbo")
tokenizer_gpt4 = LazyloadTiktoken("gpt-4")
get_token_num_gpt35 = lambda txt: len(tokenizer_gpt35.encode(txt, disallowed_special=()))
get_token_num_gpt4 = lambda txt: len(tokenizer_gpt4.encode(txt, disallowed_special=()))
+
model_info = {
# openai
"gpt-3.5-turbo": {
"fn_with_ui": chatgpt_ui,
"fn_without_ui": chatgpt_noui,
- "endpoint": "https://api.openai.com/v1/chat/completions",
+ "endpoint": openai_endpoint,
"max_token": 4096,
"tokenizer": tokenizer_gpt35,
"token_cnt": get_token_num_gpt35,
@@ -62,7 +82,7 @@ model_info = {
"gpt-4": {
"fn_with_ui": chatgpt_ui,
"fn_without_ui": chatgpt_noui,
- "endpoint": "https://api.openai.com/v1/chat/completions",
+ "endpoint": openai_endpoint,
"max_token": 8192,
"tokenizer": tokenizer_gpt4,
"token_cnt": get_token_num_gpt4,
@@ -72,7 +92,7 @@ model_info = {
"api2d-gpt-3.5-turbo": {
"fn_with_ui": chatgpt_ui,
"fn_without_ui": chatgpt_noui,
- "endpoint": "https://openai.api2d.net/v1/chat/completions",
+ "endpoint": api2d_endpoint,
"max_token": 4096,
"tokenizer": tokenizer_gpt35,
"token_cnt": get_token_num_gpt35,
@@ -81,7 +101,7 @@ model_info = {
"api2d-gpt-4": {
"fn_with_ui": chatgpt_ui,
"fn_without_ui": chatgpt_noui,
- "endpoint": "https://openai.api2d.net/v1/chat/completions",
+ "endpoint": api2d_endpoint,
"max_token": 8192,
"tokenizer": tokenizer_gpt4,
"token_cnt": get_token_num_gpt4,
@@ -190,7 +210,7 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, obser
return_string_collect.append( f"【{str(models[i])} 说】: {future.result()} " )
window_mutex[-1] = False # stop mutex thread
- res = '
\n\n---\n\n'.join(return_string_collect)
+ res = '
\n\n---\n\n'.join(return_string_collect)
return res
diff --git a/request_llm/bridge_chatglm.py b/request_llm/bridge_chatglm.py
index 7af2835..8eef322 100644
--- a/request_llm/bridge_chatglm.py
+++ b/request_llm/bridge_chatglm.py
@@ -92,8 +92,8 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="",
# chatglm 没有 sys_prompt 接口,因此把prompt加入 history
history_feedin = []
+ history_feedin.append(["What can I do?", sys_prompt])
for i in range(len(history)//2):
- history_feedin.append(["What can I do?", sys_prompt] )
history_feedin.append([history[2*i], history[2*i+1]] )
watch_dog_patience = 5 # 看门狗 (watchdog) 的耐心, 设置5秒即可
@@ -131,10 +131,13 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"]
history_feedin = []
+ history_feedin.append(["What can I do?", system_prompt] )
for i in range(len(history)//2):
- history_feedin.append(["What can I do?", system_prompt] )
history_feedin.append([history[2*i], history[2*i+1]] )
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']):
chatbot[-1] = (inputs, response)
- yield from update_ui(chatbot=chatbot, history=history)
\ No newline at end of file
+ yield from update_ui(chatbot=chatbot, history=history)
+
+ history.extend([inputs, response])
+ yield from update_ui(chatbot=chatbot, history=history)
\ No newline at end of file
diff --git a/request_llm/bridge_chatgpt.py b/request_llm/bridge_chatgpt.py
index 34c3ff6..c1a900b 100644
--- a/request_llm/bridge_chatgpt.py
+++ b/request_llm/bridge_chatgpt.py
@@ -21,7 +21,7 @@ import importlib
# config_private.py放自己的秘密如API和代理网址
# 读取时首先看是否存在私密的config_private配置文件(不受git管控),如果有,则覆盖原config文件
-from toolbox import get_conf, update_ui, is_any_api_key, select_api_key
+from toolbox import get_conf, update_ui, is_any_api_key, select_api_key, what_keys
proxies, API_KEY, TIMEOUT_SECONDS, MAX_RETRY = \
get_conf('proxies', 'API_KEY', 'TIMEOUT_SECONDS', 'MAX_RETRY')
@@ -118,7 +118,7 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
"""
if is_any_api_key(inputs):
chatbot._cookies['api_key'] = inputs
- chatbot.append(("输入已识别为openai的api_key", "api_key已导入"))
+ chatbot.append(("输入已识别为openai的api_key", what_keys(inputs)))
yield from update_ui(chatbot=chatbot, history=history, msg="api_key已导入") # 刷新界面
return
elif not is_any_api_key(chatbot._cookies['api_key']):
@@ -141,7 +141,7 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp
try:
headers, payload = generate_payload(inputs, llm_kwargs, history, system_prompt, stream)
except RuntimeError as e:
- chatbot[-1] = (inputs, f"您提供的api-key不满足要求,不包含任何可用于{llm_kwargs['llm_model']}的api-key。")
+ chatbot[-1] = (inputs, f"您提供的api-key不满足要求,不包含任何可用于{llm_kwargs['llm_model']}的api-key。您可能选择了错误的模型或请求源。")
yield from update_ui(chatbot=chatbot, history=history, msg="api-key不满足要求") # 刷新界面
return
diff --git a/toolbox.py b/toolbox.py
index db3a2b7..2fd5da2 100644
--- a/toolbox.py
+++ b/toolbox.py
@@ -433,6 +433,19 @@ def is_any_api_key(key):
else:
return is_openai_api_key(key) or is_api2d_key(key)
+def what_keys(keys):
+ avail_key_list = {'OpenAI Key':0, "API2D Key":0}
+ key_list = keys.split(',')
+
+ for k in key_list:
+ if is_openai_api_key(k):
+ avail_key_list['OpenAI Key'] += 1
+
+ for k in key_list:
+ if is_api2d_key(k):
+ avail_key_list['API2D Key'] += 1
+
+ return f"检测到: OpenAI Key {avail_key_list['OpenAI Key']} 个,API2D Key {avail_key_list['API2D Key']} 个"
def select_api_key(keys, llm_model):
import random
@@ -448,7 +461,7 @@ def select_api_key(keys, llm_model):
if is_api2d_key(k): avail_key_list.append(k)
if len(avail_key_list) == 0:
- raise RuntimeError(f"您提供的api-key不满足要求,不包含任何可用于{llm_model}的api-key。")
+ raise RuntimeError(f"您提供的api-key不满足要求,不包含任何可用于{llm_model}的api-key。您可能选择了错误的模型或请求源。")
api_key = random.choice(avail_key_list) # 随机负载均衡
return api_key
diff --git a/version b/version
index bb462e2..b645825 100644
--- a/version
+++ b/version
@@ -1,5 +1,5 @@
{
- "version": 3.1,
+ "version": 3.15,
"show_feature": true,
- "new_feature": "添加支持清华ChatGLM和GPT-4 <-> 改进架构,支持与多个LLM模型同时对话 <-> 添加支持API2D(国内,可支持gpt4)<-> 支持多API-KEY负载均衡(并列填写,逗号分割) <-> 添加输入区文本清除按键"
+ "new_feature": "添加联网(Google)回答问题插件 <-> 修复ChatGLM上下文BUG <-> 添加支持清华ChatGLM和GPT-4 <-> 改进架构,支持与多个LLM模型同时对话 <-> 添加支持API2D(国内,可支持gpt4)"
}