Merge branch 'master' into frontier

这个提交包含在:
binary-husky
2025-03-09 00:04:52 +08:00
当前提交 7af6994f7b
共有 8 个文件被更改,包括 172 次插入21 次删除

查看文件

@@ -43,7 +43,8 @@ AVAIL_LLM_MODELS = ["qwen-max", "o1-mini", "o1-mini-2024-09-12", "o1", "o1-2024-
"gpt-3.5-turbo-1106", "gpt-3.5-turbo-16k", "gpt-3.5-turbo", "azure-gpt-3.5", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-16k", "gpt-3.5-turbo", "azure-gpt-3.5",
"gpt-4", "gpt-4-32k", "azure-gpt-4", "glm-4", "glm-4v", "glm-3-turbo", "gpt-4", "gpt-4-32k", "azure-gpt-4", "glm-4", "glm-4v", "glm-3-turbo",
"gemini-1.5-pro", "chatglm3", "chatglm4", "gemini-1.5-pro", "chatglm3", "chatglm4",
"deepseek-chat", "deepseek-coder", "deepseek-reasoner" "deepseek-chat", "deepseek-coder", "deepseek-reasoner",
"volcengine-deepseek-r1-250120", "volcengine-deepseek-v3-241226",
] ]
EMBEDDING_MODEL = "text-embedding-3-small" EMBEDDING_MODEL = "text-embedding-3-small"
@@ -267,6 +268,10 @@ MOONSHOT_API_KEY = ""
YIMODEL_API_KEY = "" YIMODEL_API_KEY = ""
# 接入火山引擎的在线大模型),api-key获取地址 https://console.volcengine.com/ark/region:ark+cn-beijing/endpoint
ARK_API_KEY = "00000000-0000-0000-0000-000000000000" # 火山引擎 API KEY
# 紫东太初大模型 https://ai-maas.wair.ac.cn # 紫东太初大模型 https://ai-maas.wair.ac.cn
TAICHU_API_KEY = "" TAICHU_API_KEY = ""

查看文件

@@ -34,7 +34,7 @@ def encode_plugin_info(k, plugin)->str:
def main(): def main():
import gradio as gr import gradio as gr
if gr.__version__ not in ['3.32.12']: if gr.__version__ not in ['3.32.12', '3.32.13']:
raise ModuleNotFoundError("使用项目内置Gradio获取最优体验! 请运行 `pip install -r requirements.txt` 指令安装内置Gradio及其他依赖, 详情信息见requirements.txt.") raise ModuleNotFoundError("使用项目内置Gradio获取最优体验! 请运行 `pip install -r requirements.txt` 指令安装内置Gradio及其他依赖, 详情信息见requirements.txt.")
# 一些基础工具 # 一些基础工具

查看文件

@@ -80,6 +80,7 @@ ollama_endpoint = "http://localhost:11434/api/chat"
yimodel_endpoint = "https://api.lingyiwanwu.com/v1/chat/completions" yimodel_endpoint = "https://api.lingyiwanwu.com/v1/chat/completions"
deepseekapi_endpoint = "https://api.deepseek.com/v1/chat/completions" deepseekapi_endpoint = "https://api.deepseek.com/v1/chat/completions"
grok_model_endpoint = "https://api.x.ai/v1/chat/completions" grok_model_endpoint = "https://api.x.ai/v1/chat/completions"
volcengine_endpoint = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"
if not AZURE_ENDPOINT.endswith('/'): AZURE_ENDPOINT += '/' if not AZURE_ENDPOINT.endswith('/'): AZURE_ENDPOINT += '/'
azure_endpoint = AZURE_ENDPOINT + f'openai/deployments/{AZURE_ENGINE}/chat/completions?api-version=2023-05-15' azure_endpoint = AZURE_ENDPOINT + f'openai/deployments/{AZURE_ENGINE}/chat/completions?api-version=2023-05-15'
@@ -102,6 +103,7 @@ if ollama_endpoint in API_URL_REDIRECT: ollama_endpoint = API_URL_REDIRECT[ollam
if yimodel_endpoint in API_URL_REDIRECT: yimodel_endpoint = API_URL_REDIRECT[yimodel_endpoint] if yimodel_endpoint in API_URL_REDIRECT: yimodel_endpoint = API_URL_REDIRECT[yimodel_endpoint]
if deepseekapi_endpoint in API_URL_REDIRECT: deepseekapi_endpoint = API_URL_REDIRECT[deepseekapi_endpoint] if deepseekapi_endpoint in API_URL_REDIRECT: deepseekapi_endpoint = API_URL_REDIRECT[deepseekapi_endpoint]
if grok_model_endpoint in API_URL_REDIRECT: grok_model_endpoint = API_URL_REDIRECT[grok_model_endpoint] if grok_model_endpoint in API_URL_REDIRECT: grok_model_endpoint = API_URL_REDIRECT[grok_model_endpoint]
if volcengine_endpoint in API_URL_REDIRECT: volcengine_endpoint = API_URL_REDIRECT[volcengine_endpoint]
# 获取tokenizer # 获取tokenizer
tokenizer_gpt35 = LazyloadTiktoken("gpt-3.5-turbo") tokenizer_gpt35 = LazyloadTiktoken("gpt-3.5-turbo")
@@ -954,7 +956,7 @@ if any(item in grok_models for item in AVAIL_LLM_MODELS):
try: try:
grok_beta_128k_noui, grok_beta_128k_ui = get_predict_function( grok_beta_128k_noui, grok_beta_128k_ui = get_predict_function(
api_key_conf_name="GROK_API_KEY", max_output_token=8192, disable_proxy=False api_key_conf_name="GROK_API_KEY", max_output_token=8192, disable_proxy=False
) )
model_info.update({ model_info.update({
"grok-beta": { "grok-beta": {
@@ -1089,8 +1091,10 @@ if "deepseekcoder" in AVAIL_LLM_MODELS: # deepseekcoder
}) })
except: except:
logger.error(trimmed_format_exc()) logger.error(trimmed_format_exc())
# -=-=-=-=-=-=- 幻方-深度求索大模型在线API -=-=-=-=-=-=- # -=-=-=-=-=-=- 幻方-深度求索大模型在线API -=-=-=-=-=-=-
if "deepseek-chat" in AVAIL_LLM_MODELS or "deepseek-coder" in AVAIL_LLM_MODELS or "deepseek-reasoner" in AVAIL_LLM_MODELS: claude_models = ["deepseek-chat", "deepseek-coder", "deepseek-reasoner"]
if any(item in claude_models for item in AVAIL_LLM_MODELS):
try: try:
deepseekapi_noui, deepseekapi_ui = get_predict_function( deepseekapi_noui, deepseekapi_ui = get_predict_function(
api_key_conf_name="DEEPSEEK_API_KEY", max_output_token=4096, disable_proxy=False api_key_conf_name="DEEPSEEK_API_KEY", max_output_token=4096, disable_proxy=False
@@ -1127,6 +1131,60 @@ if "deepseek-chat" in AVAIL_LLM_MODELS or "deepseek-coder" in AVAIL_LLM_MODELS o
}) })
except: except:
logger.error(trimmed_format_exc()) logger.error(trimmed_format_exc())
# -=-=-=-=-=-=- 火山引擎 对齐支持 -=-=-=-=-=-=-
for model in [m for m in AVAIL_LLM_MODELS if m.startswith("volcengine-")]:
# 为了更灵活地接入volcengine多模型管理界面,设计了此接口,例子AVAIL_LLM_MODELS = ["volcengine-deepseek-r1-250120(max_token=6666)"]
# 其中
# "volcengine-" 是前缀(必要)
# "deepseek-r1-250120" 是模型名(必要)
# "(max_token=6666)" 是配置(非必要)
model_info_extend = model_info
model_info_extend.update({
"deepseek-r1-250120": {
"max_token": 16384,
"enable_reasoning": True,
"can_multi_thread": True,
"endpoint": volcengine_endpoint,
"tokenizer": tokenizer_gpt35,
"token_cnt": get_token_num_gpt35,
},
"deepseek-v3-241226": {
"max_token": 16384,
"enable_reasoning": False,
"can_multi_thread": True,
"endpoint": volcengine_endpoint,
"tokenizer": tokenizer_gpt35,
"token_cnt": get_token_num_gpt35,
},
})
try:
origin_model_name, max_token_tmp = read_one_api_model_name(model)
# 如果是已知模型,则尝试获取其信息
original_model_info = model_info_extend.get(origin_model_name.replace("volcengine-", "", 1), None)
except:
logger.error(f"volcengine模型 {model} 的 max_token 配置不是整数,请检查配置文件。")
continue
volcengine_noui, volcengine_ui = get_predict_function(api_key_conf_name="ARK_API_KEY", max_output_token=8192, disable_proxy=True, model_remove_prefix = ["volcengine-"])
this_model_info = {
"fn_with_ui": volcengine_ui,
"fn_without_ui": volcengine_noui,
"endpoint": volcengine_endpoint,
"can_multi_thread": True,
"max_token": 64000,
"tokenizer": tokenizer_gpt35,
"token_cnt": get_token_num_gpt35,
}
# 同步已知模型的其他信息
attribute = "has_multimodal_capacity"
if original_model_info is not None and original_model_info.get(attribute, None) is not None: this_model_info.update({attribute: original_model_info.get(attribute, None)})
attribute = "enable_reasoning"
if original_model_info is not None and original_model_info.get(attribute, None) is not None: this_model_info.update({attribute: original_model_info.get(attribute, None)})
model_info.update({model: this_model_info})
# -=-=-=-=-=-=- one-api 对齐支持 -=-=-=-=-=-=- # -=-=-=-=-=-=- one-api 对齐支持 -=-=-=-=-=-=-
for model in [m for m in AVAIL_LLM_MODELS if m.startswith("one-api-")]: for model in [m for m in AVAIL_LLM_MODELS if m.startswith("one-api-")]:
# 为了更灵活地接入one-api多模型管理界面,设计了此接口,例子AVAIL_LLM_MODELS = ["one-api-mixtral-8x7b(max_token=6666)"] # 为了更灵活地接入one-api多模型管理界面,设计了此接口,例子AVAIL_LLM_MODELS = ["one-api-mixtral-8x7b(max_token=6666)"]

查看文件

@@ -57,7 +57,7 @@ def decode_chunk(chunk):
finish_reason = chunk["error"]["code"] finish_reason = chunk["error"]["code"]
except: except:
finish_reason = "API_ERROR" finish_reason = "API_ERROR"
return response, reasoning_content, finish_reason return response, reasoning_content, finish_reason, str(chunk)
try: try:
if chunk["choices"][0]["delta"]["content"] is not None: if chunk["choices"][0]["delta"]["content"] is not None:
@@ -122,7 +122,8 @@ def generate_message(input, model, key, history, max_output_token, system_prompt
def get_predict_function( def get_predict_function(
api_key_conf_name, api_key_conf_name,
max_output_token, max_output_token,
disable_proxy = False disable_proxy = False,
model_remove_prefix = [],
): ):
""" """
为openai格式的API生成响应函数,其中传入参数 为openai格式的API生成响应函数,其中传入参数
@@ -137,6 +138,16 @@ def get_predict_function(
APIKEY = get_conf(api_key_conf_name) APIKEY = get_conf(api_key_conf_name)
def remove_prefix(model_name):
# 去除模型名字的前缀,输入 volcengine-deepseek-r1-250120 会返回 deepseek-r1-250120
if not model_remove_prefix:
return model_name
model_without_prefix = model_name
for prefix in model_remove_prefix:
if model_without_prefix.startswith(prefix):
model_without_prefix = model_without_prefix[len(prefix):]
return model_without_prefix
def predict_no_ui_long_connection( def predict_no_ui_long_connection(
inputs, inputs,
llm_kwargs, llm_kwargs,
@@ -164,9 +175,11 @@ def get_predict_function(
raise RuntimeError(f"APIKEY为空,请检查配置文件的{APIKEY}") raise RuntimeError(f"APIKEY为空,请检查配置文件的{APIKEY}")
if inputs == "": if inputs == "":
inputs = "你好👋" inputs = "你好👋"
headers, payload = generate_message( headers, payload = generate_message(
input=inputs, input=inputs,
model=llm_kwargs["llm_model"], model=remove_prefix(llm_kwargs["llm_model"]),
key=APIKEY, key=APIKEY,
history=history, history=history,
max_output_token=max_output_token, max_output_token=max_output_token,
@@ -302,7 +315,7 @@ def get_predict_function(
headers, payload = generate_message( headers, payload = generate_message(
input=inputs, input=inputs,
model=llm_kwargs["llm_model"], model=remove_prefix(llm_kwargs["llm_model"]),
key=APIKEY, key=APIKEY,
history=history, history=history,
max_output_token=max_output_token, max_output_token=max_output_token,

查看文件

@@ -1,4 +1,4 @@
https://public.agent-matrix.com/publish/gradio-3.32.12-py3-none-any.whl https://public.agent-matrix.com/publish/gradio-3.32.13-py3-none-any.whl
fastapi==0.110 fastapi==0.110
gradio-client==0.8 gradio-client==0.8
pypdf2==2.12.1 pypdf2==2.12.1

查看文件

@@ -3,7 +3,8 @@ import re
import os import os
import math import math
import html import html
import base64
import gzip
from loguru import logger from loguru import logger
from textwrap import dedent from textwrap import dedent
from functools import lru_cache from functools import lru_cache
@@ -325,6 +326,14 @@ def markdown_convertion_for_file(txt):
# cat them together # cat them together
return pre + convert_stage_5 + suf return pre + convert_stage_5 + suf
def compress_string(s):
compress_string = gzip.compress(s.encode('utf-8'))
return base64.b64encode(compress_string).decode()
def decompress_string(s):
decoded_string = base64.b64decode(s)
return gzip.decompress(decoded_string).decode('utf-8')
@lru_cache(maxsize=128) # 使用 lru缓存 加快转换速度 @lru_cache(maxsize=128) # 使用 lru缓存 加快转换速度
def markdown_convertion(txt): def markdown_convertion(txt):
""" """
@@ -336,6 +345,12 @@ def markdown_convertion(txt):
# print('警告,输入了已经经过转化的字符串,二次转化可能出问题') # print('警告,输入了已经经过转化的字符串,二次转化可能出问题')
return txt # 已经被转化过,不需要再次转化 return txt # 已经被转化过,不需要再次转化
# 在文本中插入一个base64编码的原始文本,以便在复制时能够获得原始文本
raw_text_encoded = compress_string(txt)
raw_text_node = f'<div class="raw_text">{raw_text_encoded}</div>'
suf = raw_text_node + "</div>"
# 用于查找数学公式的正则表达式
find_equation_pattern = r'<script type="math/tex(?:.*?)>(.*?)</script>' find_equation_pattern = r'<script type="math/tex(?:.*?)>(.*?)</script>'
txt = fix_markdown_indent(txt) txt = fix_markdown_indent(txt)
@@ -493,6 +508,7 @@ def simple_markdown_convertion(text):
suf = "</div>" suf = "</div>"
if text.startswith(pre) and text.endswith(suf): if text.startswith(pre) and text.endswith(suf):
return text # 已经被转化过,不需要再次转化 return text # 已经被转化过,不需要再次转化
text = compat_non_markdown_input(text) # 兼容非markdown输入 text = compat_non_markdown_input(text) # 兼容非markdown输入
text = markdown.markdown( text = markdown.markdown(
text, text,

查看文件

@@ -332,3 +332,7 @@
text-wrap: wrap; text-wrap: wrap;
opacity: 0.8; opacity: 0.8;
} }
.raw_text {
display: none;
}

查看文件

@@ -259,7 +259,24 @@ function cancel_loading_status() {
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// 第 2 部分: 复制按钮 // 第 2 部分: 复制按钮
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// 解压缩函数
function decompressString(compressedString) {
// 第1步Base64解码
const binaryString = atob(compressedString);
// 第2步将二进制字符串转换为Uint8Array
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
// 第3步使用DecompressionStream (基于Web Streams API)进行gzip解压缩
const ds = new DecompressionStream('gzip');
const decompressedStream = new Response(new Blob([bytes])).body.pipeThrough(ds);
// 第4步获取解压后的数据并转换为字符串
return new Response(decompressedStream).text();
}
var allow_auto_read_continously = true; var allow_auto_read_continously = true;
var allow_auto_read_tts_flag = false; var allow_auto_read_tts_flag = false;
@@ -283,19 +300,56 @@ function addCopyButton(botElement, index, is_last_in_arr) {
return; return;
} }
var copyButton = document.createElement('button'); // var copyButton = document.createElement('button');
copyButton.classList.add('copy-bot-btn'); // copyButton.classList.add('copy-bot-btn');
copyButton.setAttribute('aria-label', 'Copy'); // copyButton.setAttribute('aria-label', 'Copy');
copyButton.innerHTML = copyIcon; // copyButton.innerHTML = copyIcon;
copyButton.addEventListener('click', async () => { // copyButton.addEventListener('click', async () => {
const textToCopy = botElement.innerText; // const textToCopy = botElement.innerText;
// try {
// // push_text_to_audio(textToCopy).catch(console.error);
// if ("clipboard" in navigator) {
// await navigator.clipboard.writeText(textToCopy);
// copyButton.innerHTML = copiedIcon;
// setTimeout(() => {
// copyButton.innerHTML = copyIcon;
// }, 1500);
// } else {
// const textArea = document.createElement("textarea");
// textArea.value = textToCopy;
// document.body.appendChild(textArea);
// textArea.select();
// try {
// document.execCommand('copy');
// copyButton.innerHTML = copiedIcon;
// setTimeout(() => {
// copyButton.innerHTML = copyIcon;
// }, 1500);
// } catch (error) {
// console.error("Copy failed: ", error);
// }
// document.body.removeChild(textArea);
// }
// } catch (error) {
// console.error("Copy failed: ", error);
// }
// });
// 原始文本拷贝
var copyButtonOrig = document.createElement('button');
copyButtonOrig.classList.add('copy-bot-btn');
copyButtonOrig.setAttribute('aria-label', 'Copy');
copyButtonOrig.innerHTML = copyIcon;
copyButtonOrig.addEventListener('click', async () => {
try { try {
const base64gzipcode = botElement.getElementsByClassName('raw_text')[0].innerText;
const textToCopy = await decompressString(base64gzipcode);
// push_text_to_audio(textToCopy).catch(console.error); // push_text_to_audio(textToCopy).catch(console.error);
if ("clipboard" in navigator) { if ("clipboard" in navigator) {
await navigator.clipboard.writeText(textToCopy); await navigator.clipboard.writeText(textToCopy);
copyButton.innerHTML = copiedIcon; copyButtonOrig.innerHTML = copiedIcon;
setTimeout(() => { setTimeout(() => {
copyButton.innerHTML = copyIcon; copyButtonOrig.innerHTML = copyIcon;
}, 1500); }, 1500);
} else { } else {
const textArea = document.createElement("textarea"); const textArea = document.createElement("textarea");
@@ -304,9 +358,9 @@ function addCopyButton(botElement, index, is_last_in_arr) {
textArea.select(); textArea.select();
try { try {
document.execCommand('copy'); document.execCommand('copy');
copyButton.innerHTML = copiedIcon; copyButtonOrig.innerHTML = copiedIcon;
setTimeout(() => { setTimeout(() => {
copyButton.innerHTML = copyIcon; copyButtonOrig.innerHTML = copyIcon;
}, 1500); }, 1500);
} catch (error) { } catch (error) {
console.error("Copy failed: ", error); console.error("Copy failed: ", error);
@@ -345,7 +399,8 @@ function addCopyButton(botElement, index, is_last_in_arr) {
var messageBtnColumn = document.createElement('div'); var messageBtnColumn = document.createElement('div');
messageBtnColumn.classList.add('message-btn-row'); messageBtnColumn.classList.add('message-btn-row');
messageBtnColumn.appendChild(copyButton); // messageBtnColumn.appendChild(copyButton);
messageBtnColumn.appendChild(copyButtonOrig);
if (enable_tts) { if (enable_tts) {
messageBtnColumn.appendChild(audioButton); messageBtnColumn.appendChild(audioButton);
} }