镜像自地址
https://github.com/binary-husky/gpt_academic.git
已同步 2025-12-08 07:26:48 +00:00
Merge branch 'master' into frontier
这个提交包含在:
@@ -45,6 +45,7 @@ AVAIL_LLM_MODELS = ["qwen-max", "o1-mini", "o1-mini-2024-09-12", "o1", "o1-2024-
|
|||||||
"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",
|
"volcengine-deepseek-r1-250120", "volcengine-deepseek-v3-241226",
|
||||||
|
"dashscope-deepseek-r1", "dashscope-deepseek-v3",
|
||||||
]
|
]
|
||||||
|
|
||||||
EMBEDDING_MODEL = "text-embedding-3-small"
|
EMBEDDING_MODEL = "text-embedding-3-small"
|
||||||
|
|||||||
2
main.py
2
main.py
@@ -184,7 +184,7 @@ def main():
|
|||||||
from themes.gui_floating_menu import define_gui_floating_menu
|
from themes.gui_floating_menu import define_gui_floating_menu
|
||||||
area_input_secondary, txt2, area_customize, _, resetBtn2, clearBtn2, stopBtn2 = \
|
area_input_secondary, txt2, area_customize, _, resetBtn2, clearBtn2, stopBtn2 = \
|
||||||
define_gui_floating_menu(customize_btns, functional, predefined_btns, cookies, web_cookie_cache)
|
define_gui_floating_menu(customize_btns, functional, predefined_btns, cookies, web_cookie_cache)
|
||||||
|
|
||||||
# 浮动时间线定义
|
# 浮动时间线定义
|
||||||
gr.Spark()
|
gr.Spark()
|
||||||
|
|
||||||
|
|||||||
@@ -530,6 +530,15 @@ model_info = {
|
|||||||
"tokenizer": tokenizer_gpt35,
|
"tokenizer": tokenizer_gpt35,
|
||||||
"token_cnt": get_token_num_gpt35,
|
"token_cnt": get_token_num_gpt35,
|
||||||
},
|
},
|
||||||
|
"gemini-2.0-flash": {
|
||||||
|
"fn_with_ui": genai_ui,
|
||||||
|
"fn_without_ui": genai_noui,
|
||||||
|
"endpoint": gemini_endpoint,
|
||||||
|
"has_multimodal_capacity": True,
|
||||||
|
"max_token": 1024 * 204800,
|
||||||
|
"tokenizer": tokenizer_gpt35,
|
||||||
|
"token_cnt": get_token_num_gpt35,
|
||||||
|
},
|
||||||
|
|
||||||
# cohere
|
# cohere
|
||||||
"cohere-command-r-plus": {
|
"cohere-command-r-plus": {
|
||||||
@@ -813,8 +822,9 @@ if "qwen-local" in AVAIL_LLM_MODELS:
|
|||||||
})
|
})
|
||||||
except:
|
except:
|
||||||
logger.error(trimmed_format_exc())
|
logger.error(trimmed_format_exc())
|
||||||
# -=-=-=-=-=-=- 通义-在线模型 -=-=-=-=-=-=-
|
|
||||||
qwen_models = ["qwen-max-latest", "qwen-max-2025-01-25","qwen-max","qwen-turbo","qwen-plus"]
|
# -=-=-=-=-=-=- 阿里云百炼(通义)-在线模型 -=-=-=-=-=-=-
|
||||||
|
qwen_models = ["qwen-max-latest", "qwen-max-2025-01-25","qwen-max","qwen-turbo","qwen-plus","dashscope-deepseek-r1","dashscope-deepseek-v3"]
|
||||||
if any(item in qwen_models for item in AVAIL_LLM_MODELS):
|
if any(item in qwen_models for item in AVAIL_LLM_MODELS):
|
||||||
try:
|
try:
|
||||||
from .bridge_qwen import predict_no_ui_long_connection as qwen_noui
|
from .bridge_qwen import predict_no_ui_long_connection as qwen_noui
|
||||||
@@ -864,10 +874,30 @@ if any(item in qwen_models for item in AVAIL_LLM_MODELS):
|
|||||||
"max_token": 30720,
|
"max_token": 30720,
|
||||||
"tokenizer": tokenizer_gpt35,
|
"tokenizer": tokenizer_gpt35,
|
||||||
"token_cnt": get_token_num_gpt35,
|
"token_cnt": get_token_num_gpt35,
|
||||||
|
},
|
||||||
|
"dashscope-deepseek-r1": {
|
||||||
|
"fn_with_ui": qwen_ui,
|
||||||
|
"fn_without_ui": qwen_noui,
|
||||||
|
"enable_reasoning": True,
|
||||||
|
"can_multi_thread": True,
|
||||||
|
"endpoint": None,
|
||||||
|
"max_token": 57344,
|
||||||
|
"tokenizer": tokenizer_gpt35,
|
||||||
|
"token_cnt": get_token_num_gpt35,
|
||||||
|
},
|
||||||
|
"dashscope-deepseek-v3": {
|
||||||
|
"fn_with_ui": qwen_ui,
|
||||||
|
"fn_without_ui": qwen_noui,
|
||||||
|
"can_multi_thread": True,
|
||||||
|
"endpoint": None,
|
||||||
|
"max_token": 57344,
|
||||||
|
"tokenizer": tokenizer_gpt35,
|
||||||
|
"token_cnt": get_token_num_gpt35,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
except:
|
except:
|
||||||
logger.error(trimmed_format_exc())
|
logger.error(trimmed_format_exc())
|
||||||
|
|
||||||
# -=-=-=-=-=-=- 零一万物模型 -=-=-=-=-=-=-
|
# -=-=-=-=-=-=- 零一万物模型 -=-=-=-=-=-=-
|
||||||
yi_models = ["yi-34b-chat-0205","yi-34b-chat-200k","yi-large","yi-medium","yi-spark","yi-large-turbo","yi-large-preview"]
|
yi_models = ["yi-34b-chat-0205","yi-34b-chat-200k","yi-large","yi-medium","yi-spark","yi-large-turbo","yi-large-preview"]
|
||||||
if any(item in yi_models for item in AVAIL_LLM_MODELS):
|
if any(item in yi_models for item in AVAIL_LLM_MODELS):
|
||||||
|
|||||||
@@ -368,12 +368,12 @@ def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWith
|
|||||||
log_chat(llm_model=llm_kwargs["llm_model"], input_str=inputs, output_str=gpt_replying_buffer)
|
log_chat(llm_model=llm_kwargs["llm_model"], input_str=inputs, output_str=gpt_replying_buffer)
|
||||||
break # 对于符合规范的接口,这里可以break
|
break # 对于符合规范的接口,这里可以break
|
||||||
else:
|
else:
|
||||||
continue # 对于不符合规范的狗屎接口,这里需要继续
|
continue # 对于不符合规范的接口,这里需要继续
|
||||||
# 到这里,我们已经可以假定必须包含choice了
|
# 到这里,我们已经可以假定必须包含choice了
|
||||||
try:
|
try:
|
||||||
status_text = f"finish_reason: {chunkjson['choices'][0].get('finish_reason', 'null')}"
|
status_text = f"finish_reason: {chunkjson['choices'][0].get('finish_reason', 'null')}"
|
||||||
except:
|
except:
|
||||||
logger.error(f"一些垃圾第三方接口出现这样的错误,兼容一下吧: {chunk_decoded}")
|
logger.error(f"一些第三方接口出现这样的错误,兼容一下吧: {chunk_decoded}")
|
||||||
# 处理数据流的主体
|
# 处理数据流的主体
|
||||||
if has_content:
|
if has_content:
|
||||||
# 正常情况
|
# 正常情况
|
||||||
@@ -382,9 +382,9 @@ def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWith
|
|||||||
# 一些第三方接口的出现这样的错误,兼容一下吧
|
# 一些第三方接口的出现这样的错误,兼容一下吧
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
# 至此已经超出了正常接口应该进入的范围,一些垃圾第三方接口会出现这样的错误
|
# 至此已经超出了正常接口应该进入的范围,一些第三方接口会出现这样的错误
|
||||||
if chunkjson['choices'][0]["delta"].get("content", None) is None:
|
if chunkjson['choices'][0]["delta"].get("content", None) is None:
|
||||||
logger.error(f"一些垃圾第三方接口出现这样的错误,兼容一下吧: {chunk_decoded}")
|
logger.error(f"一些第三方接口出现这样的错误,兼容一下吧: {chunk_decoded}")
|
||||||
continue
|
continue
|
||||||
gpt_replying_buffer = gpt_replying_buffer + chunkjson['choices'][0]["delta"]["content"]
|
gpt_replying_buffer = gpt_replying_buffer + chunkjson['choices'][0]["delta"]["content"]
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from toolbox import get_conf
|
|||||||
import threading
|
import threading
|
||||||
|
|
||||||
timeout_bot_msg = '[Local Message] Request timeout. Network error.'
|
timeout_bot_msg = '[Local Message] Request timeout. Network error.'
|
||||||
|
model_prefix_to_remove = 'dashscope-'
|
||||||
|
|
||||||
class QwenRequestInstance():
|
class QwenRequestInstance():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -20,6 +21,13 @@ class QwenRequestInstance():
|
|||||||
raise RuntimeError('请配置 DASHSCOPE_API_KEY')
|
raise RuntimeError('请配置 DASHSCOPE_API_KEY')
|
||||||
dashscope.api_key = get_conf("DASHSCOPE_API_KEY")
|
dashscope.api_key = get_conf("DASHSCOPE_API_KEY")
|
||||||
|
|
||||||
|
def format_reasoning(self, reasoning_content:str, main_content:str):
|
||||||
|
if reasoning_content:
|
||||||
|
reasoning_content_paragraphs = ''.join([f'<p style="margin: 1.25em 0;">{line}</p>' for line in reasoning_content.split('\n')])
|
||||||
|
formatted_reasoning_content = f'<div class="reasoning_process">{reasoning_content_paragraphs}</div>\n\n---\n\n'
|
||||||
|
return formatted_reasoning_content + main_content
|
||||||
|
else:
|
||||||
|
return main_content
|
||||||
|
|
||||||
def generate(self, inputs, llm_kwargs, history, system_prompt):
|
def generate(self, inputs, llm_kwargs, history, system_prompt):
|
||||||
# import _thread as thread
|
# import _thread as thread
|
||||||
@@ -28,9 +36,13 @@ class QwenRequestInstance():
|
|||||||
if top_p == 0: top_p += 1e-5
|
if top_p == 0: top_p += 1e-5
|
||||||
if top_p == 1: top_p -= 1e-5
|
if top_p == 1: top_p -= 1e-5
|
||||||
|
|
||||||
|
model_name = llm_kwargs['llm_model']
|
||||||
|
if model_name.startswith(model_prefix_to_remove): model_name = model_name[len(model_prefix_to_remove):]
|
||||||
|
|
||||||
|
self.reasoning_buf = ""
|
||||||
self.result_buf = ""
|
self.result_buf = ""
|
||||||
responses = Generation.call(
|
responses = Generation.call(
|
||||||
model=llm_kwargs['llm_model'],
|
model=model_name,
|
||||||
messages=generate_message_payload(inputs, llm_kwargs, history, system_prompt),
|
messages=generate_message_payload(inputs, llm_kwargs, history, system_prompt),
|
||||||
top_p=top_p,
|
top_p=top_p,
|
||||||
temperature=llm_kwargs.get('temperature', 1.0),
|
temperature=llm_kwargs.get('temperature', 1.0),
|
||||||
@@ -46,18 +58,24 @@ class QwenRequestInstance():
|
|||||||
self.result_buf += response.output.choices[0].message.content
|
self.result_buf += response.output.choices[0].message.content
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
yield self.result_buf
|
yield self.format_reasoning(self.reasoning_buf, self.result_buf)
|
||||||
break
|
break
|
||||||
elif response.output.choices[0].finish_reason == 'length':
|
elif response.output.choices[0].finish_reason == 'length':
|
||||||
self.result_buf += "[Local Message] 生成长度过长,后续输出被截断"
|
self.result_buf += "[Local Message] 生成长度过长,后续输出被截断"
|
||||||
yield self.result_buf
|
yield self.format_reasoning(self.reasoning_buf, self.result_buf)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
try:
|
||||||
|
contain_reasoning = hasattr(response.output.choices[0].message, 'reasoning_content')
|
||||||
|
except:
|
||||||
|
contain_reasoning = False
|
||||||
|
if contain_reasoning:
|
||||||
|
self.reasoning_buf += response.output.choices[0].message.reasoning_content
|
||||||
self.result_buf += response.output.choices[0].message.content
|
self.result_buf += response.output.choices[0].message.content
|
||||||
yield self.result_buf
|
yield self.format_reasoning(self.reasoning_buf, self.result_buf)
|
||||||
else:
|
else:
|
||||||
self.result_buf += f"[Local Message] 请求错误:状态码:{response.status_code},错误码:{response.code},消息:{response.message}"
|
self.result_buf += f"[Local Message] 请求错误:状态码:{response.status_code},错误码:{response.code},消息:{response.message}"
|
||||||
yield self.result_buf
|
yield self.format_reasoning(self.reasoning_buf, self.result_buf)
|
||||||
break
|
break
|
||||||
|
|
||||||
# 耗尽generator避免报错
|
# 耗尽generator避免报错
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ def markdown_convertion(txt):
|
|||||||
|
|
||||||
# 在文本中插入一个base64编码的原始文本,以便在复制时能够获得原始文本
|
# 在文本中插入一个base64编码的原始文本,以便在复制时能够获得原始文本
|
||||||
raw_text_encoded = compress_string(txt)
|
raw_text_encoded = compress_string(txt)
|
||||||
raw_text_node = f'<div class="raw_text" style="display:none">{raw_text_encoded}</div>'
|
raw_text_node = f'<div class="raw_text" style="display:none">{raw_text_encoded}</div><div class="message_tail" style="display:none"/>'
|
||||||
suf = raw_text_node + "</div>"
|
suf = raw_text_node + "</div>"
|
||||||
|
|
||||||
# 用于查找数学公式的正则表达式
|
# 用于查找数学公式的正则表达式
|
||||||
|
|||||||
@@ -335,4 +335,74 @@
|
|||||||
|
|
||||||
.raw_text {
|
.raw_text {
|
||||||
display: none;
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message_tail {
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.message_tail_stop {
|
||||||
|
border: dotted !important;
|
||||||
|
margin-top: 5px !important;
|
||||||
|
padding-left: 8px !important;
|
||||||
|
padding-top: 1px !important;
|
||||||
|
padding-bottom: 1px !important;
|
||||||
|
padding-right: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ant 开始 */
|
||||||
|
|
||||||
|
/* 通用按钮样式 */
|
||||||
|
.ant-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 按钮颜色和状态 */
|
||||||
|
.ant-btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-btn-primary:hover {
|
||||||
|
background-color: #40a9ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-btn-loading {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图标样式 */
|
||||||
|
.ant-btn-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
fill: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anticon-spin {
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 动画效果 */
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
114
themes/common.js
114
themes/common.js
@@ -289,7 +289,7 @@ function addCopyButton(botElement, index, is_last_in_arr) {
|
|||||||
const audioIcon = '<span><svg t="1713628577799" fill="currentColor" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4587" width=".9em" height=".9em"><path d="M113.7664 540.4672c0-219.9552 178.2784-398.2336 398.2336-398.2336S910.2336 320.512 910.2336 540.4672v284.4672c0 31.4368-25.4976 56.9344-56.9344 56.9344h-56.9344c-31.4368 0-56.9344-25.4976-56.9344-56.9344V597.2992c0-31.4368 25.4976-56.9344 56.9344-56.9344h56.9344c0-188.5184-152.7808-341.2992-341.2992-341.2992S170.7008 351.9488 170.7008 540.4672h56.9344c31.4368 0 56.9344 25.4976 56.9344 56.9344v227.5328c0 31.4368-25.4976 56.9344-56.9344 56.9344h-56.9344c-31.4368 0-56.9344-25.4976-56.9344-56.9344V540.4672z" p-id="4588"></path></svg></span>';
|
const audioIcon = '<span><svg t="1713628577799" fill="currentColor" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4587" width=".9em" height=".9em"><path d="M113.7664 540.4672c0-219.9552 178.2784-398.2336 398.2336-398.2336S910.2336 320.512 910.2336 540.4672v284.4672c0 31.4368-25.4976 56.9344-56.9344 56.9344h-56.9344c-31.4368 0-56.9344-25.4976-56.9344-56.9344V597.2992c0-31.4368 25.4976-56.9344 56.9344-56.9344h56.9344c0-188.5184-152.7808-341.2992-341.2992-341.2992S170.7008 351.9488 170.7008 540.4672h56.9344c31.4368 0 56.9344 25.4976 56.9344 56.9344v227.5328c0 31.4368-25.4976 56.9344-56.9344 56.9344h-56.9344c-31.4368 0-56.9344-25.4976-56.9344-56.9344V540.4672z" p-id="4588"></path></svg></span>';
|
||||||
// const cancelAudioIcon = '<span><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height=".8em" width=".8em" xmlns="http://www.w3.org/2000/svg"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></span>';
|
// const cancelAudioIcon = '<span><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" height=".8em" width=".8em" xmlns="http://www.w3.org/2000/svg"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></span>';
|
||||||
|
|
||||||
// 此功能没准备好
|
// audio functionality
|
||||||
if (allow_auto_read_continously && is_last_in_arr && allow_auto_read_tts_flag) {
|
if (allow_auto_read_continously && is_last_in_arr && allow_auto_read_tts_flag) {
|
||||||
process_latest_text_output(botElement.innerText, index);
|
process_latest_text_output(botElement.innerText, index);
|
||||||
}
|
}
|
||||||
@@ -300,41 +300,6 @@ function addCopyButton(botElement, index, is_last_in_arr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// var copyButton = document.createElement('button');
|
|
||||||
// copyButton.classList.add('copy-bot-btn');
|
|
||||||
// copyButton.setAttribute('aria-label', 'Copy');
|
|
||||||
// copyButton.innerHTML = copyIcon;
|
|
||||||
// copyButton.addEventListener('click', async () => {
|
|
||||||
// const textToCopy = botElement.innerText;
|
|
||||||
// try {
|
|
||||||
// // 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');
|
var copyButtonOrig = document.createElement('button');
|
||||||
copyButtonOrig.classList.add('copy-bot-btn');
|
copyButtonOrig.classList.add('copy-bot-btn');
|
||||||
@@ -436,7 +401,6 @@ function do_something_but_not_too_frequently(min_interval, func) {
|
|||||||
|
|
||||||
|
|
||||||
function chatbotContentChanged(attempt = 1, force = false) {
|
function chatbotContentChanged(attempt = 1, force = false) {
|
||||||
// https://github.com/GaiZhenbiao/ChuanhuChatGPT/tree/main/web_assets/javascript
|
|
||||||
for (var i = 0; i < attempt; i++) {
|
for (var i = 0; i < attempt; i++) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const messages = gradioApp().querySelectorAll('#gpt-chatbot .message-wrap .message.bot');
|
const messages = gradioApp().querySelectorAll('#gpt-chatbot .message-wrap .message.bot');
|
||||||
@@ -447,6 +411,9 @@ function chatbotContentChanged(attempt = 1, force = false) {
|
|||||||
// Now pass both the message element and the is_last_in_arr boolean to addCopyButton
|
// Now pass both the message element and the is_last_in_arr boolean to addCopyButton
|
||||||
addCopyButton(message, index, is_last_in_arr);
|
addCopyButton(message, index, is_last_in_arr);
|
||||||
|
|
||||||
|
// if last message, add stop btn link
|
||||||
|
addStopButton(message, index, is_last_in_arr);
|
||||||
|
|
||||||
// save_conversation_history
|
// save_conversation_history
|
||||||
save_conversation_history_slow_down();
|
save_conversation_history_slow_down();
|
||||||
});
|
});
|
||||||
@@ -457,6 +424,79 @@ function chatbotContentChanged(attempt = 1, force = false) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addStopButton(botElement, index, is_last_in_arr) {
|
||||||
|
function is_generating() {
|
||||||
|
var statePanelElement = document.getElementById("state-panel");
|
||||||
|
var generatingElement = statePanelElement.querySelector(".generating");
|
||||||
|
if (generatingElement) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function on_stop_btn_click() {
|
||||||
|
let stopButton = document.getElementById("elem_stop");
|
||||||
|
stopButton.click();
|
||||||
|
}
|
||||||
|
function remove_stop_generate_btn(messageTailElement) {
|
||||||
|
// remove all child elements of messageTailElement
|
||||||
|
while (messageTailElement.firstChild) {
|
||||||
|
messageTailElement.removeChild(messageTailElement.firstChild);
|
||||||
|
}
|
||||||
|
messageTailElement.style.display = 'none';
|
||||||
|
messageTailElement.classList.add('removed');
|
||||||
|
}
|
||||||
|
function add_stop_generate_btn() {
|
||||||
|
// write here: add a beautiful stop btn `bottomElement` as child, when clicked execute on_stop_btn_click
|
||||||
|
console.log("get_gradio_component")
|
||||||
|
const bottomElement = document.createElement('button');
|
||||||
|
bottomElement.className = 'ant-btn ant-btn-primary';
|
||||||
|
bottomElement.innerHTML = `
|
||||||
|
<span class="ant-btn-icon">
|
||||||
|
<svg viewBox="64 64 896 896" focusable="false" data-icon="sync" width="1em" height="1em" fill="currentColor" aria-hidden="true" class="anticon anticon-sync anticon-spin">
|
||||||
|
<path d="M168 504.2c1-43.7 10-86.1 26.9-126 17.3-41 42.1-77.7 73.7-109.4S337 212.3 378 195c42.4-17.9 87.4-27 133.9-27s91.5 9.1 133.8 27A341.5 341.5 0 01755 268.8c9.9 9.9 19.2 20.4 27.8 31.4l-60.2 47a8 8 0 003 14.1l175.7 43c5 1.2 9.9-2.6 9.9-7.7l.8-180.9c0-6.7-7.7-10.5-12.9-6.3l-56.4 44.1C765.8 155.1 646.2 92 511.8 92 282.7 92 96.3 275.6 92 503.8a8 8 0 008 8.2h60c4.4 0 7.9-3.5 8-7.8zm756 7.8h-60c-4.4 0-7.9 3.5-8 7.8-1 43.7-10 86.1-26.9 126-17.3 41-42.1 77.8-73.7 109.4A342.45 342.45 0 01512.1 856a342.24 342.24 0 01-243.2-100.8c-9.9-9.9-19.2-20.4-27.8-31.4l60.2-47a8 8 0 00-3-14.1l-175.7-43c-5-1.2-9.9 2.6-9.9 7.7l-.7 181c0 6.7 7.7 10.5 12.9 6.3l56.4-44.1C258.2 868.9 377.8 932 512.2 932c229.2 0 415.5-183.7 419.8-411.8a8 8 0 00-8-8.2z"></path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span>终止</span>
|
||||||
|
`;
|
||||||
|
bottomElement.classList.add('message_tail_stop');
|
||||||
|
bottomElement.addEventListener('click', on_stop_btn_click);
|
||||||
|
messageTailElement.appendChild(bottomElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// find a sub element of class `message_tail`
|
||||||
|
const messageTailElement = botElement.querySelector('.message_tail');
|
||||||
|
// if not is_last_in_arr, hide this elem (display none)
|
||||||
|
if (!messageTailElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (messageTailElement.classList.contains('removed')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!is_last_in_arr) {
|
||||||
|
remove_stop_generate_btn(messageTailElement);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
messageTailElement.style.display = 'flex';
|
||||||
|
const messageTailStopElem = messageTailElement.querySelector('.message_tail_stop');
|
||||||
|
if(!is_generating()) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if(!is_generating()) {
|
||||||
|
remove_stop_generate_btn(messageTailElement);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (!messageTailStopElem) {
|
||||||
|
add_stop_generate_btn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
if (!messageTailStopElem) {
|
||||||
|
add_stop_generate_btn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户