Merge branch 'binary-husky:frontier' into frontier
This commit is contained in:
commit
87ac06afd2
|
|
@ -161,6 +161,5 @@ temp.*
|
|||
objdump*
|
||||
*.min.*.js
|
||||
TODO
|
||||
|
||||
experimental_mods
|
||||
search_results
|
||||
|
|
|
|||
|
|
@ -273,8 +273,8 @@ GROBID_URLS = [
|
|||
]
|
||||
|
||||
|
||||
# Searxng互联网检索服务
|
||||
SEARXNG_URL = "https://cloud-1.agent-matrix.com/"
|
||||
# Searxng互联网检索服务(这是一个huggingface空间,请前往huggingface复制该空间,然后把自己新的空间地址填在这里)
|
||||
SEARXNG_URLS = [ f"https://kaletianlre-beardvs{i}dd.hf.space/" for i in range(1,5) ]
|
||||
|
||||
|
||||
# 是否允许通过自然语言描述修改本页的配置,该功能具有一定的危险性,默认关闭
|
||||
|
|
@ -311,7 +311,7 @@ NUM_CUSTOM_BASIC_BTN = 4
|
|||
|
||||
|
||||
# 媒体智能体的服务地址(这是一个huggingface空间,请前往huggingface复制该空间,然后把自己新的空间地址填在这里)
|
||||
DAAS_SERVER_URL = "https://hamercity-bbdown.hf.space/stream"
|
||||
DAAS_SERVER_URLS = [ f"https://niuziniu-biligpt{i}.hf.space/stream" for i in range(1,5) ]
|
||||
|
||||
|
||||
|
||||
|
|
@ -403,7 +403,7 @@ DAAS_SERVER_URL = "https://hamercity-bbdown.hf.space/stream"
|
|||
插件在线服务配置依赖关系示意图
|
||||
│
|
||||
├── 互联网检索
|
||||
│ └── SEARXNG_URL
|
||||
│ └── SEARXNG_URLS
|
||||
│
|
||||
├── 语音功能
|
||||
│ ├── ENABLE_AUDIO
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ def get_crazy_functions():
|
|||
"多媒体智能体": {
|
||||
"Group": "智能体",
|
||||
"Color": "stop",
|
||||
"AsButton": True,
|
||||
"AsButton": False,
|
||||
"Info": "【仅测试】多媒体任务",
|
||||
"Function": HotReload(多媒体任务),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from bs4 import BeautifulSoup
|
|||
from functools import lru_cache
|
||||
from itertools import zip_longest
|
||||
from check_proxy import check_proxy
|
||||
from toolbox import CatchException, update_ui, get_conf
|
||||
from toolbox import CatchException, update_ui, get_conf, update_ui_lastest_msg
|
||||
from crazy_functions.crazy_utils import request_gpt_model_in_new_thread_with_ui_alive, input_clipping
|
||||
from request_llms.bridge_all import model_info
|
||||
from request_llms.bridge_all import predict_no_ui_long_connection
|
||||
|
|
@ -115,7 +115,8 @@ def get_auth_ip():
|
|||
|
||||
def searxng_request(query, proxies, categories='general', searxng_url=None, engines=None):
|
||||
if searxng_url is None:
|
||||
url = get_conf("SEARXNG_URL")
|
||||
urls = get_conf("SEARXNG_URLS")
|
||||
url = random.choice(urls)
|
||||
else:
|
||||
url = searxng_url
|
||||
|
||||
|
|
@ -192,6 +193,38 @@ def scrape_text(url, proxies) -> str:
|
|||
text = "\n".join(chunk for chunk in chunks if chunk)
|
||||
return text
|
||||
|
||||
def internet_search_with_analysis_prompt(prompt, analysis_prompt, llm_kwargs, chatbot):
|
||||
from toolbox import get_conf
|
||||
proxies = get_conf('proxies')
|
||||
categories = 'general'
|
||||
searxng_url = None # 使用默认的searxng_url
|
||||
engines = None # 使用默认的搜索引擎
|
||||
yield from update_ui_lastest_msg(lastmsg=f"检索中: {prompt} ...", chatbot=chatbot, history=[], delay=1)
|
||||
urls = searxng_request(prompt, proxies, categories, searxng_url, engines=engines)
|
||||
yield from update_ui_lastest_msg(lastmsg=f"依次访问搜索到的网站 ...", chatbot=chatbot, history=[], delay=1)
|
||||
if len(urls) == 0:
|
||||
return None
|
||||
max_search_result = 5 # 最多收纳多少个网页的结果
|
||||
history = []
|
||||
for index, url in enumerate(urls[:max_search_result]):
|
||||
yield from update_ui_lastest_msg(lastmsg=f"依次访问搜索到的网站: {url['link']} ...", chatbot=chatbot, history=[], delay=1)
|
||||
res = scrape_text(url['link'], proxies)
|
||||
prefix = f"第{index}份搜索结果 [源自{url['source'][0]}搜索] ({url['title'][:25]}):"
|
||||
history.extend([prefix, res])
|
||||
i_say = f"从以上搜索结果中抽取信息,然后回答问题:{prompt} {analysis_prompt}"
|
||||
i_say, history = input_clipping( # 裁剪输入,从最长的条目开始裁剪,防止爆token
|
||||
inputs=i_say,
|
||||
history=history,
|
||||
max_token_limit=8192
|
||||
)
|
||||
gpt_say = predict_no_ui_long_connection(
|
||||
inputs=i_say,
|
||||
llm_kwargs=llm_kwargs,
|
||||
history=history,
|
||||
sys_prompt="请从搜索结果中抽取信息,对最相关的两个搜索结果进行总结,然后回答问题。",
|
||||
console_slience=False,
|
||||
)
|
||||
return gpt_say
|
||||
|
||||
@CatchException
|
||||
def 连接网络回答问题(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, user_request):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
import random
|
||||
from toolbox import get_conf
|
||||
from crazy_functions.Internet_GPT import 连接网络回答问题
|
||||
from crazy_functions.plugin_template.plugin_class_template import GptAcademicPluginTemplate, ArgProperty
|
||||
|
|
@ -20,6 +20,9 @@ class NetworkGPT_Wrap(GptAcademicPluginTemplate):
|
|||
第三个参数,名称`allow_cache`,参数`type`声明这是一个下拉菜单,下拉菜单上方显示`title`+`description`,下拉菜单的选项为`options`,`default_value`为下拉菜单默认值;
|
||||
|
||||
"""
|
||||
urls = get_conf("SEARXNG_URLS")
|
||||
url = random.choice(urls)
|
||||
|
||||
gui_definition = {
|
||||
"main_input":
|
||||
ArgProperty(title="输入问题", description="待通过互联网检索的问题,会自动读取输入框内容", default_value="", type="string").model_dump_json(), # 主输入,自动从输入框同步
|
||||
|
|
@ -30,7 +33,7 @@ class NetworkGPT_Wrap(GptAcademicPluginTemplate):
|
|||
"optimizer":
|
||||
ArgProperty(title="搜索优化", options=["关闭", "开启", "开启(增强)"], default_value="关闭", description="是否使用搜索增强。注意这可能会消耗较多token", type="dropdown").model_dump_json(),
|
||||
"searxng_url":
|
||||
ArgProperty(title="Searxng服务地址", description="输入Searxng的地址", default_value=get_conf("SEARXNG_URL"), type="string").model_dump_json(), # 主输入,自动从输入框同步
|
||||
ArgProperty(title="Searxng服务地址", description="输入Searxng的地址", default_value=url, type="string").model_dump_json(), # 主输入,自动从输入框同步
|
||||
|
||||
}
|
||||
return gui_definition
|
||||
|
|
|
|||
|
|
@ -559,7 +559,7 @@ def PDF翻译中文并重新编译PDF(txt, llm_kwargs, plugin_kwargs, chatbot, h
|
|||
project_folder = move_project(project_folder)
|
||||
|
||||
# <-------------- set a hash tag for repeat-checking ------------->
|
||||
with open(pj(project_folder, hash_tag + '.tag'), 'w') as f:
|
||||
with open(pj(project_folder, hash_tag + '.tag'), 'w', encoding='utf8') as f:
|
||||
f.write(hash_tag)
|
||||
f.close()
|
||||
|
||||
|
|
|
|||
|
|
@ -95,9 +95,6 @@ def Rag问答(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, u
|
|||
yield from update_ui_lastest_msg('已清空', chatbot, history, delay=0) # 刷新界面
|
||||
return
|
||||
|
||||
else:
|
||||
report_exception(chatbot, history, a=f"上传文件路径错误: {txt}", b="请检查并提供正确路径。")
|
||||
|
||||
# 3. Normal Q&A processing
|
||||
chatbot.append([txt, f'正在召回知识 ({current_context}) ...'])
|
||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@ from pydantic import BaseModel, Field
|
|||
class Query(BaseModel):
|
||||
search_keyword: str = Field(description="search query for video resource")
|
||||
|
||||
# {'title': '【麦笛奈Martine】天文馆的猫 | Diffsinger Lynxnet版本中文试听【Cover 泠鸢·折纸信笺】', 'author': '灰条纹的灰猫君', 'author_id': 2083633, 'bvid': 'BV1LSSHYXEtv', '播放量': 75, '弹幕': 0, '评论': 7, '点赞': 5, '发布时间': '2024-10-31 22:10:08', '视频时长': '4:40', 'tag': '虚拟歌姬,鸟蛋,冷鸟,女声翻唱,泠鸢yousa,虚拟主播,虚拟UP主,VTuber,Diffsinger,虚拟歌手分享官,虚拟之声创作计划·2024第三期', 'description': '翻唱:麦笛奈Martine\n调混:灰条纹的灰猫君\nQ版曲绘:西柚Kanno\n原曲:Av847726911\n原唱:泠鸢\n\n滑铲——月更!\n万圣节快乐!今天是和喵星发电报的可爱猫猫~'}
|
||||
|
||||
class VideoResource(BaseModel):
|
||||
thought: str = Field(description="analysis of the search results based on the user's query")
|
||||
title: str = Field(description="title of the video")
|
||||
author: str = Field(description="author/uploader of the video")
|
||||
bvid: str = Field(description="unique ID of the video")
|
||||
another_failsafe_bvid: str = Field(description="provide another bvid, the other one is not working")
|
||||
|
||||
|
||||
def get_video_resource(search_keyword):
|
||||
|
|
@ -54,6 +54,10 @@ def download_video(bvid, user_name, chatbot, history):
|
|||
chatbot.append((None, "下载音频, 请稍等...")); yield from update_ui(chatbot=chatbot, history=history)
|
||||
downloaded_files = yield from download_video(bvid, only_audio=True, user_name=user_name, chatbot=chatbot, history=history)
|
||||
|
||||
if len(downloaded_files) == 0:
|
||||
# failed to download audio
|
||||
return []
|
||||
|
||||
# preview
|
||||
preview_list = [promote_file_to_downloadzone(fp) for fp in downloaded_files]
|
||||
file_links = generate_file_link(preview_list)
|
||||
|
|
@ -79,31 +83,70 @@ def download_video(bvid, user_name, chatbot, history):
|
|||
# return
|
||||
return downloaded_files + downloaded_files_part2
|
||||
|
||||
|
||||
class Strategy(BaseModel):
|
||||
thought: str = Field(description="analysis of the user's wish, for example, can you recall the name of the resource?")
|
||||
which_methods: str = Field(description="Which method to use to find the necessary information? choose from 'method_1' and 'method_2'.")
|
||||
method_1_search_keywords: str = Field(description="Generate keywords to search the internet if you choose method 1, otherwise empty.")
|
||||
method_2_generate_keywords: str = Field(description="Generate keywords for video download engine if you choose method 2, otherwise empty.")
|
||||
|
||||
|
||||
@CatchException
|
||||
def 多媒体任务(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, user_request):
|
||||
user_wish: str = txt
|
||||
# query demos:
|
||||
# - "我想找一首歌,里面有句歌词是“turn your face towards the sun”"
|
||||
# - "一首歌,第一句是红豆生南国"
|
||||
# - "一首音乐,中国航天任务专用的那首"
|
||||
# - "戴森球计划在熔岩星球的音乐"
|
||||
# - "hanser的百变什么精"
|
||||
# - "打大圣残躯时的bgm"
|
||||
# - "渊下宫战斗音乐"
|
||||
|
||||
# 搜索
|
||||
chatbot.append((txt, "检索中, 请稍等..."))
|
||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||
# 结构化生成
|
||||
rf_req = dedent(f"""
|
||||
The user wish to get the following resource:
|
||||
{user_wish}
|
||||
Generate reseach keywords (less than 5 keywords) accordingly.
|
||||
""")
|
||||
if "跳过联网搜索" not in user_wish:
|
||||
# 结构化生成
|
||||
internet_search_keyword = user_wish
|
||||
|
||||
yield from update_ui_lastest_msg(lastmsg=f"发起互联网检索: {internet_search_keyword} ...", chatbot=chatbot, history=[], delay=1)
|
||||
from crazy_functions.Internet_GPT import internet_search_with_analysis_prompt
|
||||
result = yield from internet_search_with_analysis_prompt(
|
||||
prompt=internet_search_keyword,
|
||||
analysis_prompt="请根据搜索结果分析,获取用户需要找的资源的名称、作者、出处等信息。",
|
||||
llm_kwargs=llm_kwargs,
|
||||
chatbot=chatbot
|
||||
)
|
||||
|
||||
yield from update_ui_lastest_msg(lastmsg=f"互联网检索结论: {result} \n\n 正在生成进一步检索方案 ...", chatbot=chatbot, history=[], delay=1)
|
||||
rf_req = dedent(f"""
|
||||
The user wish to get the following resource:
|
||||
{user_wish}
|
||||
Meanwhile, you can access another expert's opinion on the user's wish:
|
||||
{result}
|
||||
Generate search keywords (less than 5 keywords) for video download engine accordingly.
|
||||
""")
|
||||
else:
|
||||
user_wish = user_wish.replace("跳过联网搜索", "").strip()
|
||||
rf_req = dedent(f"""
|
||||
The user wish to get the following resource:
|
||||
{user_wish}
|
||||
Generate reseach keywords (less than 5 keywords) accordingly.
|
||||
""")
|
||||
gpt_json_io = GptJsonIO(Query)
|
||||
inputs = rf_req + gpt_json_io.format_instructions
|
||||
run_gpt_fn = lambda inputs, sys_prompt: predict_no_ui_long_connection(inputs=inputs, llm_kwargs=llm_kwargs, history=[], sys_prompt=sys_prompt, observe_window=[])
|
||||
analyze_res = run_gpt_fn(inputs, "")
|
||||
logger.info(analyze_res)
|
||||
query: Query = gpt_json_io.generate_output_auto_repair(analyze_res, run_gpt_fn)
|
||||
video_engine_keywords = query.search_keyword
|
||||
# 关键词展示
|
||||
chatbot.append((None, f"检索关键词已确认: {query.search_keyword}。筛选中, 请稍等..."))
|
||||
chatbot.append((None, f"检索关键词已确认: {video_engine_keywords}。筛选中, 请稍等..."))
|
||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||
|
||||
# 获取候选资源
|
||||
candadate_dictionary: dict = get_video_resource(query.search_keyword)
|
||||
candadate_dictionary: dict = get_video_resource(video_engine_keywords)
|
||||
candadate_dictionary_as_str = json.dumps(candadate_dictionary, ensure_ascii=False, indent=4)
|
||||
|
||||
# 展示候选资源
|
||||
|
|
@ -124,6 +167,7 @@ def 多媒体任务(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_pro
|
|||
2. The time duration of the video should be less than 10 minutes.
|
||||
3. You should analyze the search results first, before giving your answer.
|
||||
4. Use Chinese if possible.
|
||||
5. Beside the primary video selection, give a backup video resource `bvid`.
|
||||
""")
|
||||
gpt_json_io = GptJsonIO(VideoResource)
|
||||
inputs = rf_req_2 + gpt_json_io.format_instructions
|
||||
|
|
@ -145,4 +189,16 @@ def 多媒体任务(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_pro
|
|||
|
||||
if video_resource and video_resource.bvid:
|
||||
logger.info(video_resource)
|
||||
yield from download_video(video_resource.bvid, chatbot.get_user(), chatbot, history)
|
||||
downloaded = yield from download_video(video_resource.bvid, chatbot.get_user(), chatbot, history)
|
||||
if not downloaded:
|
||||
chatbot.append((None, f"下载失败, 尝试备选 ..."))
|
||||
yield from update_ui(chatbot=chatbot, history=history) # 刷新界面
|
||||
downloaded = yield from download_video(video_resource.another_failsafe_bvid, chatbot.get_user(), chatbot, history)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@CatchException
|
||||
def debug(bvid, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, user_request):
|
||||
yield from download_video(bvid, chatbot.get_user(), chatbot, history)
|
||||
|
|
@ -448,9 +448,6 @@ def 编译Latex(chatbot, history, main_file_original, main_file_modified, work_f
|
|||
except Exception as e:
|
||||
logger.error(e)
|
||||
pass
|
||||
|
||||
|
||||
|
||||
return True # 成功啦
|
||||
else:
|
||||
if n_fix>=max_try: break
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
from toolbox import update_ui, get_conf, promote_file_to_downloadzone, update_ui_lastest_msg, generate_file_link
|
||||
from shared_utils.docker_as_service_api import stream_daas
|
||||
from shared_utils.docker_as_service_api import DockerServiceApiComModel
|
||||
import random
|
||||
|
||||
def download_video(video_id, only_audio, user_name, chatbot, history):
|
||||
from toolbox import get_log_folder
|
||||
chatbot.append([None, "Processing..."])
|
||||
yield from update_ui(chatbot, history)
|
||||
client_command = f'{video_id} --audio-only' if only_audio else video_id
|
||||
server_url = get_conf('DAAS_SERVER_URL')
|
||||
server_urls = get_conf('DAAS_SERVER_URLS')
|
||||
server_url = random.choice(server_urls)
|
||||
docker_service_api_com_model = DockerServiceApiComModel(client_command=client_command)
|
||||
save_file_dir = get_log_folder(user_name, plugin_name='media_downloader')
|
||||
for output_manifest in stream_daas(docker_service_api_com_model, server_url, save_file_dir):
|
||||
|
|
@ -31,7 +33,9 @@ def download_video(video_id, only_audio, user_name, chatbot, history):
|
|||
def search_videos(keywords):
|
||||
from toolbox import get_log_folder
|
||||
client_command = keywords
|
||||
server_url = get_conf('DAAS_SERVER_URL').replace('stream', 'search')
|
||||
server_urls = get_conf('DAAS_SERVER_URLS')
|
||||
server_url = random.choice(server_urls)
|
||||
server_url = server_url.replace('stream', 'search')
|
||||
docker_service_api_com_model = DockerServiceApiComModel(client_command=client_command)
|
||||
save_file_dir = get_log_folder("default_user", plugin_name='media_downloader')
|
||||
for output_manifest in stream_daas(docker_service_api_com_model, server_url, save_file_dir):
|
||||
|
|
|
|||
20
main.py
20
main.py
|
|
@ -34,7 +34,7 @@ def encode_plugin_info(k, plugin)->str:
|
|||
|
||||
def main():
|
||||
import gradio as gr
|
||||
if gr.__version__ not in ['3.32.9', '3.32.10', '3.32.11']:
|
||||
if gr.__version__ not in ['3.32.12']:
|
||||
raise ModuleNotFoundError("使用项目内置Gradio获取最优体验! 请运行 `pip install -r requirements.txt` 指令安装内置Gradio及其他依赖, 详情信息见requirements.txt.")
|
||||
|
||||
# 一些基础工具
|
||||
|
|
@ -57,7 +57,7 @@ def main():
|
|||
# 如果WEB_PORT是-1, 则随机选取WEB端口
|
||||
PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT
|
||||
from check_proxy import get_current_version
|
||||
from themes.theme import adjust_theme, advanced_css, theme_declaration, js_code_clear, js_code_reset, js_code_show_or_hide, js_code_show_or_hide_group2
|
||||
from themes.theme import adjust_theme, advanced_css, theme_declaration, js_code_clear, js_code_show_or_hide, js_code_show_or_hide_group2
|
||||
from themes.theme import js_code_for_toggle_darkmode, js_code_for_persistent_cookie_init
|
||||
from themes.theme import load_dynamic_theme, to_cookie_str, from_cookie_str, assign_user_uuid
|
||||
title_html = f"<h1 align=\"center\">GPT 学术优化 {get_current_version()}</h1>{theme_declaration}"
|
||||
|
|
@ -106,7 +106,7 @@ def main():
|
|||
with gr_L2(scale=2, elem_id="gpt-chat"):
|
||||
chatbot = gr.Chatbot(label=f"当前模型:{LLM_MODEL}", elem_id="gpt-chatbot")
|
||||
if LAYOUT == "TOP-DOWN": chatbot.style(height=CHATBOT_HEIGHT)
|
||||
history, history_cache, history_cache_update = make_history_cache() # 定义 后端state(history)、前端(history_cache)、后端setter(history_cache_update)三兄弟
|
||||
history, _, _ = make_history_cache() # 定义 后端state(history)、前端(history_cache)、后端setter(history_cache_update)三兄弟
|
||||
with gr_L2(scale=1, elem_id="gpt-panel"):
|
||||
with gr.Accordion("输入区", open=True, elem_id="input-panel") as area_input_primary:
|
||||
with gr.Row():
|
||||
|
|
@ -174,6 +174,7 @@ def main():
|
|||
with gr.Accordion("点击展开“文件下载区”。", open=False) as area_file_up:
|
||||
file_upload = gr.Files(label="任何文件, 推荐上传压缩文件(zip, tar)", file_count="multiple", elem_id="elem_upload")
|
||||
|
||||
|
||||
# 左上角工具栏定义
|
||||
from themes.gui_toolbar import define_gui_toolbar
|
||||
checkboxes, checkboxes_2, max_length_sl, theme_dropdown, system_prompt, file_upload_2, md_dropdown, top_p, temperature = \
|
||||
|
|
@ -183,6 +184,9 @@ def main():
|
|||
from themes.gui_floating_menu import define_gui_floating_menu
|
||||
area_input_secondary, txt2, area_customize, _, resetBtn2, clearBtn2, stopBtn2 = \
|
||||
define_gui_floating_menu(customize_btns, functional, predefined_btns, cookies, web_cookie_cache)
|
||||
|
||||
# 浮动时间线定义
|
||||
gr.Spark(label="", value="")
|
||||
|
||||
# 插件二级菜单的实现
|
||||
from themes.gui_advanced_plugin_class import define_gui_advanced_plugin_class
|
||||
|
|
@ -222,11 +226,11 @@ def main():
|
|||
multiplex_sel.select(
|
||||
None, [multiplex_sel], None, _js=f"""(multiplex_sel)=>run_multiplex_shift(multiplex_sel)""")
|
||||
cancel_handles.append(submit_btn.click(**predict_args))
|
||||
resetBtn.click(None, None, [chatbot, history, status], _js=js_code_reset) # 先在前端快速清除chatbot&status
|
||||
resetBtn2.click(None, None, [chatbot, history, status], _js=js_code_reset) # 先在前端快速清除chatbot&status
|
||||
reset_server_side_args = (lambda history: ([], [], "已重置", json.dumps(history)), [history], [chatbot, history, status, history_cache])
|
||||
resetBtn.click(*reset_server_side_args) # 再在后端清除history,把history转存history_cache备用
|
||||
resetBtn2.click(*reset_server_side_args) # 再在后端清除history,把history转存history_cache备用
|
||||
resetBtn.click(None, None, [chatbot, history, status], _js="""(a,b,c)=>clear_conversation(a,b,c)""") # 先在前端快速清除chatbot&status
|
||||
resetBtn2.click(None, None, [chatbot, history, status], _js="""(a,b,c)=>clear_conversation(a,b,c)""") # 先在前端快速清除chatbot&status
|
||||
# reset_server_side_args = (lambda history: ([], [], "已重置"), [history], [chatbot, history, status])
|
||||
# resetBtn.click(*reset_server_side_args) # 再在后端清除history
|
||||
# resetBtn2.click(*reset_server_side_args) # 再在后端清除history
|
||||
clearBtn.click(None, None, [txt, txt2], _js=js_code_clear)
|
||||
clearBtn2.click(None, None, [txt, txt2], _js=js_code_clear)
|
||||
if AUTO_CLEAR_TXT:
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class GetLlamaHandle(LocalLLMHandle):
|
|||
import platform
|
||||
huggingface_token, device = get_conf('HUGGINGFACE_ACCESS_TOKEN', 'LOCAL_MODEL_DEVICE')
|
||||
assert len(huggingface_token) != 0, "没有填写 HUGGINGFACE_ACCESS_TOKEN"
|
||||
with open(os.path.expanduser('~/.cache/huggingface/token'), 'w') as f:
|
||||
with open(os.path.expanduser('~/.cache/huggingface/token'), 'w', encoding='utf8') as f:
|
||||
f.write(huggingface_token)
|
||||
model_id = 'meta-llama/Llama-2-7b-chat-hf'
|
||||
with ProxyNetworkActivate('Download_LLM'):
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class MoonShotInit:
|
|||
files.append(f)
|
||||
for file in files:
|
||||
if file.split('.')[-1] in ['pdf']:
|
||||
with open(file, 'r') as fp:
|
||||
with open(file, 'r', encoding='utf8') as fp:
|
||||
from crazy_functions.crazy_utils import read_and_clean_pdf_text
|
||||
file_content, _ = read_and_clean_pdf_text(fp)
|
||||
what_ask.append({"role": "system", "content": file_content})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
https://public.agent-matrix.com/publish/gradio-3.32.10-py3-none-any.whl
|
||||
https://public.agent-matrix.com/publish/gradio-3.32.12-py3-none-any.whl
|
||||
fastapi==0.110
|
||||
gradio-client==0.8
|
||||
pypdf2==2.12.1
|
||||
|
|
|
|||
|
|
@ -77,16 +77,28 @@ def make_history_cache():
|
|||
# 定义 后端state(history)、前端(history_cache)、后端setter(history_cache_update)三兄弟
|
||||
import gradio as gr
|
||||
# 定义history的后端state
|
||||
history = gr.State([])
|
||||
# 定义history的一个孪生的前端存储区(隐藏)
|
||||
history_cache = gr.Textbox(visible=False, elem_id="history_cache")
|
||||
# 定义history_cache->history的更新方法(隐藏)。在触发这个按钮时,会先执行js代码更新history_cache,然后再执行python代码更新history
|
||||
def process_history_cache(history_cache):
|
||||
return json.loads(history_cache)
|
||||
# 另一种更简单的setter方法
|
||||
history_cache_update = gr.Button("", elem_id="elem_update_history", visible=False).click(
|
||||
process_history_cache, inputs=[history_cache], outputs=[history])
|
||||
return history, history_cache, history_cache_update
|
||||
# history = gr.State([])
|
||||
history = gr.Textbox(visible=False, elem_id="history-ng")
|
||||
# # 定义history的一个孪生的前端存储区(隐藏)
|
||||
# history_cache = gr.Textbox(visible=False, elem_id="history_cache")
|
||||
# # 定义history_cache->history的更新方法(隐藏)。在触发这个按钮时,会先执行js代码更新history_cache,然后再执行python代码更新history
|
||||
# def process_history_cache(history_cache):
|
||||
# return json.loads(history_cache)
|
||||
# # 另一种更简单的setter方法
|
||||
# history_cache_update = gr.Button("", elem_id="elem_update_history", visible=False).click(
|
||||
# process_history_cache, inputs=[history_cache], outputs=[history])
|
||||
# # save history to history_cache
|
||||
# def process_history_cache(history_cache):
|
||||
# return json.dumps(history_cache)
|
||||
# # 定义history->history_cache的更新方法(隐藏)
|
||||
# def sync_history_cache(history):
|
||||
# print("sync_history_cache", history)
|
||||
# return json.dumps(history)
|
||||
# # history.change(sync_history_cache, inputs=[history], outputs=[history_cache])
|
||||
|
||||
# # history_cache_sync = gr.Button("", elem_id="elem_sync_history", visible=False).click(
|
||||
# # lambda history: (json.dumps(history)), inputs=[history_cache], outputs=[history])
|
||||
return history, None, None
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,18 @@ graph TD
|
|||
E --> B
|
||||
D --> F[Save Image and Code]
|
||||
F --> B
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><b>My section header in bold</b></summary>
|
||||
|
||||
Any folded content here. It requires an empty line just above it.
|
||||
|
||||
</details>
|
||||
|
||||
"""
|
||||
def validate_path():
|
||||
import os, sys
|
||||
|
|
@ -44,8 +54,8 @@ def validate_path():
|
|||
validate_path() # validate path so you can run from base directory
|
||||
from toolbox import markdown_convertion
|
||||
from shared_utils.advanced_markdown_format import markdown_convertion_for_file
|
||||
with open("gpt_log/default_user/shared/2024-04-22-01-27-43.zip.extract/translated_markdown.md", "r", encoding="utf-8") as f:
|
||||
md = f.read()
|
||||
# with open("gpt_log/default_user/shared/2024-04-22-01-27-43.zip.extract/translated_markdown.md", "r", encoding="utf-8") as f:
|
||||
# md = f.read()
|
||||
html = markdown_convertion_for_file(md)
|
||||
# print(html)
|
||||
with open("test.html", "w", encoding="utf-8") as f:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
"""
|
||||
对项目中的各个插件进行测试。运行方法:直接运行 python tests/test_plugins.py
|
||||
"""
|
||||
|
||||
import init_test
|
||||
import os, sys
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from test_utils import plugin_test
|
||||
|
||||
plugin_test(plugin='crazy_functions.VideoResource_GPT->多媒体任务', main_input="我想找一首歌,里面有句歌词是“turn your face towards the sun”")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.Internet_GPT->连接网络回答问题', main_input="谁是应急食品?")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.函数动态生成->函数动态生成', main_input='交换图像的蓝色通道和红色通道', advanced_arg={"file_path_arg": "./build/ants.jpg"})
|
||||
|
||||
# plugin_test(plugin='crazy_functions.Latex_Function->Latex翻译中文并重新编译PDF', main_input="2307.07522")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.PDF_Translate->批量翻译PDF文档', main_input='build/pdf/t1.pdf')
|
||||
|
||||
# plugin_test(
|
||||
# plugin="crazy_functions.Latex_Function->Latex翻译中文并重新编译PDF",
|
||||
# main_input="G:/SEAFILE_LOCAL/50503047/我的资料库/学位/paperlatex/aaai/Fu_8368_with_appendix",
|
||||
# )
|
||||
|
||||
# plugin_test(plugin='crazy_functions.虚空终端->虚空终端', main_input='修改api-key为sk-jhoejriotherjep')
|
||||
|
||||
# plugin_test(plugin='crazy_functions.批量翻译PDF文档_NOUGAT->批量翻译PDF文档', main_input='crazy_functions/test_project/pdf_and_word/aaai.pdf')
|
||||
|
||||
# plugin_test(plugin='crazy_functions.虚空终端->虚空终端', main_input='调用插件,对C:/Users/fuqingxu/Desktop/旧文件/gpt/chatgpt_academic/crazy_functions/latex_fns中的python文件进行解析')
|
||||
|
||||
# plugin_test(plugin='crazy_functions.命令行助手->命令行助手', main_input='查看当前的docker容器列表')
|
||||
|
||||
# plugin_test(plugin='crazy_functions.SourceCode_Analyse->解析一个Python项目', main_input="crazy_functions/test_project/python/dqn")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.SourceCode_Analyse->解析一个C项目', main_input="crazy_functions/test_project/cpp/cppipc")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.Latex_Project_Polish->Latex英文润色', main_input="crazy_functions/test_project/latex/attention")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.Markdown_Translate->Markdown中译英', main_input="README.md")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.PDF_Translate->批量翻译PDF文档', main_input='crazy_functions/test_project/pdf_and_word/aaai.pdf')
|
||||
|
||||
# plugin_test(plugin='crazy_functions.谷歌检索小助手->谷歌检索小助手', main_input="https://scholar.google.com/scholar?hl=en&as_sdt=0%2C5&q=auto+reinforcement+learning&btnG=")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.总结word文档->总结word文档', main_input="crazy_functions/test_project/pdf_and_word")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.下载arxiv论文翻译摘要->下载arxiv论文并翻译摘要', main_input="1812.10695")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.联网的ChatGPT->连接网络回答问题', main_input="谁是应急食品?")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.解析JupyterNotebook->解析ipynb文件', main_input="crazy_functions/test_samples")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.数学动画生成manim->动画生成', main_input="A ball split into 2, and then split into 4, and finally split into 8.")
|
||||
|
||||
# for lang in ["English", "French", "Japanese", "Korean", "Russian", "Italian", "German", "Portuguese", "Arabic"]:
|
||||
# plugin_test(plugin='crazy_functions.Markdown_Translate->Markdown翻译指定语言', main_input="README.md", advanced_arg={"advanced_arg": lang})
|
||||
|
||||
# plugin_test(plugin='crazy_functions.知识库文件注入->知识库文件注入', main_input="./")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.知识库文件注入->读取知识库作答', main_input="What is the installation method?")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.知识库文件注入->读取知识库作答', main_input="远程云服务器部署?")
|
||||
|
||||
# plugin_test(plugin='crazy_functions.Latex_Function->Latex翻译中文并重新编译PDF', main_input="2210.03629")
|
||||
|
||||
237
themes/common.js
237
themes/common.js
|
|
@ -318,7 +318,7 @@ function addCopyButton(botElement, index, is_last_in_arr) {
|
|||
}
|
||||
});
|
||||
|
||||
if (enable_tts){
|
||||
if (enable_tts) {
|
||||
var audioButton = document.createElement('button');
|
||||
audioButton.classList.add('audio-toggle-btn');
|
||||
audioButton.innerHTML = audioIcon;
|
||||
|
|
@ -346,7 +346,7 @@ function addCopyButton(botElement, index, is_last_in_arr) {
|
|||
var messageBtnColumn = document.createElement('div');
|
||||
messageBtnColumn.classList.add('message-btn-row');
|
||||
messageBtnColumn.appendChild(copyButton);
|
||||
if (enable_tts){
|
||||
if (enable_tts) {
|
||||
messageBtnColumn.appendChild(audioButton);
|
||||
}
|
||||
botElement.appendChild(messageBtnColumn);
|
||||
|
|
@ -391,6 +391,8 @@ function chatbotContentChanged(attempt = 1, force = false) {
|
|||
|
||||
// Now pass both the message element and the is_last_in_arr boolean to addCopyButton
|
||||
addCopyButton(message, index, is_last_in_arr);
|
||||
|
||||
save_conversation_history();
|
||||
});
|
||||
// gradioApp().querySelectorAll('#gpt-chatbot .message-wrap .message.bot').forEach(addCopyButton);
|
||||
}, i === 0 ? 0 : 200);
|
||||
|
|
@ -854,8 +856,7 @@ function limit_scroll_position() {
|
|||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
function loadLive2D() {
|
||||
if (document.querySelector(".waifu") )
|
||||
{
|
||||
if (document.querySelector(".waifu")) {
|
||||
$('.waifu').show();
|
||||
} else {
|
||||
try {
|
||||
|
|
@ -937,22 +938,154 @@ function gpt_academic_gradio_saveload(
|
|||
}
|
||||
}
|
||||
|
||||
function update_conversation_metadata() {
|
||||
// Create a conversation UUID and timestamp
|
||||
const conversationId = crypto.randomUUID();
|
||||
const timestamp = new Date().toISOString();
|
||||
const conversationData = {
|
||||
id: conversationId,
|
||||
timestamp: timestamp
|
||||
};
|
||||
// Save to cookie
|
||||
setCookie("conversation_metadata", JSON.stringify(conversationData), 2);
|
||||
// read from cookie
|
||||
let conversation_metadata = getCookie("conversation_metadata");
|
||||
console.log("conversation_metadata", conversation_metadata);
|
||||
}
|
||||
|
||||
// // Example schema for conversation data structure
|
||||
// const example_conversation = {
|
||||
// metadata: {
|
||||
// id: "550e8400-e29b-41d4-a716-446655440000",
|
||||
// timestamp: "2024-03-29T12:34:56.789Z"
|
||||
// },
|
||||
// conversation: [
|
||||
// ["user", "Hello, how are you?"],
|
||||
// ["assistant", "I'm doing well, thank you for asking! How can I help you today?"],
|
||||
// ["user", "What is the weather like?"],
|
||||
// ["assistant", "I don't have access to real-time weather information. You would need to check a weather service or look outside to know the current weather conditions."]
|
||||
// ],
|
||||
// preview: "A conversation about greetings and weather"
|
||||
// }
|
||||
|
||||
// Helper function to generate conversation preview
|
||||
function generatePreview(conversation, maxLength = 100) {
|
||||
if (!conversation || conversation.length === 0) return "";
|
||||
// Join all messages with dash separator
|
||||
const preview = conversation.join("\n");
|
||||
if (preview.length <= maxLength) return preview;
|
||||
return preview.substring(0, maxLength) + "...";
|
||||
}
|
||||
|
||||
async function save_conversation_history() {
|
||||
// 505030475
|
||||
let chatbot = await get_data_from_gradio_component('gpt-chatbot');
|
||||
let history = await get_data_from_gradio_component('history-ng');
|
||||
let conversation_metadata = getCookie("conversation_metadata");
|
||||
conversation_metadata = JSON.parse(conversation_metadata);
|
||||
// console.log("conversation_metadata", conversation_metadata);
|
||||
let conversation = {
|
||||
timestamp: conversation_metadata.timestamp,
|
||||
id: conversation_metadata.id,
|
||||
metadata: conversation_metadata,
|
||||
conversation: chatbot,
|
||||
history: history,
|
||||
preview: generatePreview(JSON.parse(history))
|
||||
};
|
||||
|
||||
// Get existing conversation history from local storage
|
||||
let conversation_history = [];
|
||||
try {
|
||||
const stored = localStorage.getItem('conversation_history');
|
||||
if (stored) {
|
||||
conversation_history = JSON.parse(stored);
|
||||
}
|
||||
} catch (e) {
|
||||
// console.error('Error reading conversation history from localStorage:', e);
|
||||
}
|
||||
|
||||
// Find existing conversation with same ID
|
||||
const existingIndex = conversation_history.findIndex(c => c.id === conversation.id);
|
||||
|
||||
if (existingIndex >= 0) {
|
||||
// Update existing conversation
|
||||
conversation_history[existingIndex] = conversation;
|
||||
} else {
|
||||
// Add new conversation
|
||||
conversation_history.push(conversation);
|
||||
}
|
||||
|
||||
// Sort conversations by timestamp, newest first
|
||||
conversation_history.sort((a, b) => {
|
||||
const timeA = new Date(a.timestamp).getTime();
|
||||
const timeB = new Date(b.timestamp).getTime();
|
||||
return timeB - timeA;
|
||||
});
|
||||
|
||||
// Save back to local storage
|
||||
try {
|
||||
localStorage.setItem('conversation_history', JSON.stringify(conversation_history));
|
||||
const LOCAL_STORAGE_UPDATED = "gptac_conversation_history_updated";
|
||||
window.dispatchEvent(
|
||||
new CustomEvent(LOCAL_STORAGE_UPDATED, {
|
||||
detail: conversation_history
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.error('Error saving conversation history to localStorage:', e);
|
||||
}
|
||||
}
|
||||
|
||||
function restore_chat_from_local_storage(event) {
|
||||
let conversation = event.detail;
|
||||
push_data_to_gradio_component(conversation.conversation, "gpt-chatbot", "obj");
|
||||
push_data_to_gradio_component(conversation.history, "history-ng", "obj");
|
||||
console.log("restore_chat_from_local_storage", conversation);
|
||||
|
||||
// Create a conversation UUID and timestamp
|
||||
const conversationId = conversation.id;
|
||||
const timestamp = conversation.timestamp;
|
||||
const conversationData = {
|
||||
id: conversationId,
|
||||
timestamp: timestamp
|
||||
};
|
||||
// Save to cookie
|
||||
setCookie("conversation_metadata", JSON.stringify(conversationData), 2);
|
||||
// read from cookie
|
||||
let conversation_metadata = getCookie("conversation_metadata");
|
||||
console.log("conversation_metadata", conversation_metadata);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function clear_conversation(a, b, c) {
|
||||
update_conversation_metadata();
|
||||
let stopButton = document.getElementById("elem_stop");
|
||||
stopButton.click();
|
||||
// console.log("clear_conversation");
|
||||
return reset_conversation(a, b);
|
||||
}
|
||||
|
||||
function reset_conversation(a, b) {
|
||||
// console.log("js_code_reset");
|
||||
a = btoa(unescape(encodeURIComponent(JSON.stringify(a))));
|
||||
setCookie("js_previous_chat_cookie", a, 1);
|
||||
gen_restore_btn();
|
||||
b = btoa(unescape(encodeURIComponent(JSON.stringify(b))));
|
||||
setCookie("js_previous_history_cookie", b, 1);
|
||||
// gen_restore_btn();
|
||||
return [[], [], "已重置"];
|
||||
}
|
||||
|
||||
// clear -> 将 history 缓存至 history_cache -> 点击复原 -> restore_previous_chat() -> 触发elem_update_history -> 读取 history_cache
|
||||
function restore_previous_chat() {
|
||||
console.log("restore_previous_chat");
|
||||
// console.log("restore_previous_chat");
|
||||
let chat = getCookie("js_previous_chat_cookie");
|
||||
chat = JSON.parse(decodeURIComponent(escape(atob(chat))));
|
||||
push_data_to_gradio_component(chat, "gpt-chatbot", "obj");
|
||||
document.querySelector("#elem_update_history").click(); // in order to call set_history_gr_state, and send history state to server
|
||||
let history = getCookie("js_previous_history_cookie");
|
||||
history = JSON.parse(decodeURIComponent(escape(atob(history))));
|
||||
push_data_to_gradio_component(history, "history-ng", "obj");
|
||||
// document.querySelector("#elem_update_history").click(); // in order to call set_history_gr_state, and send history state to server
|
||||
}
|
||||
|
||||
function gen_restore_btn() {
|
||||
|
|
@ -1010,8 +1143,7 @@ function gen_restore_btn() {
|
|||
`;
|
||||
|
||||
// only add when not exist
|
||||
if (!document.getElementById('recvButtonStyle'))
|
||||
{
|
||||
if (!document.getElementById('recvButtonStyle')) {
|
||||
document.head.appendChild(styleSheet);
|
||||
}
|
||||
|
||||
|
|
@ -1033,8 +1165,7 @@ function gen_restore_btn() {
|
|||
document.body.removeChild(this);
|
||||
});
|
||||
// only add when not exist
|
||||
if (!document.getElementById('recvButton'))
|
||||
{
|
||||
if (!document.getElementById('recvButton')) {
|
||||
document.body.appendChild(button);
|
||||
}
|
||||
|
||||
|
|
@ -1043,7 +1174,7 @@ function gen_restore_btn() {
|
|||
}
|
||||
|
||||
async function on_plugin_exe_complete(fn_name) {
|
||||
console.log(fn_name);
|
||||
// console.log(fn_name);
|
||||
if (fn_name === "保存当前的对话") {
|
||||
// get chat profile path
|
||||
let chatbot = await get_data_from_gradio_component('gpt-chatbot');
|
||||
|
|
@ -1070,7 +1201,7 @@ async function on_plugin_exe_complete(fn_name) {
|
|||
}
|
||||
|
||||
|
||||
async function generate_menu(guiBase64String, btnName){
|
||||
async function generate_menu(guiBase64String, btnName) {
|
||||
// assign the button and menu data
|
||||
push_data_to_gradio_component(guiBase64String, "invisible_current_pop_up_plugin_arg", "string");
|
||||
push_data_to_gradio_component(btnName, "invisible_callback_btn_for_plugin_exe", "string");
|
||||
|
|
@ -1104,22 +1235,22 @@ async function generate_menu(guiBase64String, btnName){
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////// Textbox ////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
if (gui_args[key].type=='string'){ // PLUGIN_ARG_MENU
|
||||
if (gui_args[key].type == 'string') { // PLUGIN_ARG_MENU
|
||||
const component_name = "plugin_arg_txt_" + text_cnt;
|
||||
push_data_to_gradio_component({
|
||||
visible: true,
|
||||
label: gui_args[key].title + "(" + gui_args[key].description + ")",
|
||||
label: gui_args[key].title + "(" + gui_args[key].description + ")",
|
||||
// label: gui_args[key].title,
|
||||
placeholder: gui_args[key].description,
|
||||
__type__: 'update'
|
||||
}, component_name, "obj");
|
||||
if (key === "main_input"){
|
||||
if (key === "main_input") {
|
||||
// 为了与旧插件兼容,生成菜单时,自动加载输入栏的值
|
||||
let current_main_input = await get_data_from_gradio_component('user_input_main');
|
||||
let current_main_input_2 = await get_data_from_gradio_component('user_input_float');
|
||||
push_data_to_gradio_component(current_main_input + current_main_input_2, component_name, "obj");
|
||||
}
|
||||
else if (key === "advanced_arg"){
|
||||
else if (key === "advanced_arg") {
|
||||
// 为了与旧插件兼容,生成菜单时,自动加载旧高级参数输入区的值
|
||||
let advance_arg_input_legacy = await get_data_from_gradio_component('advance_arg_input_legacy');
|
||||
push_data_to_gradio_component(advance_arg_input_legacy, component_name, "obj");
|
||||
|
|
@ -1134,12 +1265,12 @@ async function generate_menu(guiBase64String, btnName){
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////// Dropdown ////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
if (gui_args[key].type=='dropdown'){ // PLUGIN_ARG_MENU
|
||||
if (gui_args[key].type == 'dropdown') { // PLUGIN_ARG_MENU
|
||||
const component_name = "plugin_arg_drop_" + dropdown_cnt;
|
||||
push_data_to_gradio_component({
|
||||
visible: true,
|
||||
choices: gui_args[key].options,
|
||||
label: gui_args[key].title + "(" + gui_args[key].description + ")",
|
||||
label: gui_args[key].title + "(" + gui_args[key].description + ")",
|
||||
// label: gui_args[key].title,
|
||||
placeholder: gui_args[key].description,
|
||||
__type__: 'update'
|
||||
|
|
@ -1154,7 +1285,7 @@ async function generate_menu(guiBase64String, btnName){
|
|||
}
|
||||
}
|
||||
|
||||
async function execute_current_pop_up_plugin(){
|
||||
async function execute_current_pop_up_plugin() {
|
||||
let guiBase64String = await get_data_from_gradio_component('invisible_current_pop_up_plugin_arg');
|
||||
const stringData = atob(guiBase64String);
|
||||
let guiJsonData = JSON.parse(stringData);
|
||||
|
|
@ -1170,8 +1301,8 @@ async function execute_current_pop_up_plugin(){
|
|||
let text_cnt = 0;
|
||||
for (const key in gui_args) {
|
||||
if (gui_args.hasOwnProperty(key)) {
|
||||
if (gui_args[key].type=='string'){ // PLUGIN_ARG_MENU
|
||||
corrisponding_elem_id = "plugin_arg_txt_"+text_cnt
|
||||
if (gui_args[key].type == 'string') { // PLUGIN_ARG_MENU
|
||||
corrisponding_elem_id = "plugin_arg_txt_" + text_cnt
|
||||
gui_args[key].user_confirmed_value = await get_data_from_gradio_component(corrisponding_elem_id);
|
||||
text_cnt += 1;
|
||||
}
|
||||
|
|
@ -1180,8 +1311,8 @@ async function execute_current_pop_up_plugin(){
|
|||
let dropdown_cnt = 0;
|
||||
for (const key in gui_args) {
|
||||
if (gui_args.hasOwnProperty(key)) {
|
||||
if (gui_args[key].type=='dropdown'){ // PLUGIN_ARG_MENU
|
||||
corrisponding_elem_id = "plugin_arg_drop_"+dropdown_cnt
|
||||
if (gui_args[key].type == 'dropdown') { // PLUGIN_ARG_MENU
|
||||
corrisponding_elem_id = "plugin_arg_drop_" + dropdown_cnt
|
||||
gui_args[key].user_confirmed_value = await get_data_from_gradio_component(corrisponding_elem_id);
|
||||
dropdown_cnt += 1;
|
||||
}
|
||||
|
|
@ -1200,29 +1331,29 @@ async function execute_current_pop_up_plugin(){
|
|||
|
||||
}
|
||||
|
||||
function hide_all_elem(){
|
||||
// PLUGIN_ARG_MENU
|
||||
for (text_cnt = 0; text_cnt < 8; text_cnt++){
|
||||
function hide_all_elem() {
|
||||
// PLUGIN_ARG_MENU
|
||||
for (text_cnt = 0; text_cnt < 8; text_cnt++) {
|
||||
push_data_to_gradio_component({
|
||||
visible: false,
|
||||
label: "",
|
||||
__type__: 'update'
|
||||
}, "plugin_arg_txt_"+text_cnt, "obj");
|
||||
document.getElementById("plugin_arg_txt_"+text_cnt).parentNode.parentNode.style.display = 'none';
|
||||
}, "plugin_arg_txt_" + text_cnt, "obj");
|
||||
document.getElementById("plugin_arg_txt_" + text_cnt).parentNode.parentNode.style.display = 'none';
|
||||
}
|
||||
for (dropdown_cnt = 0; dropdown_cnt < 8; dropdown_cnt++){
|
||||
for (dropdown_cnt = 0; dropdown_cnt < 8; dropdown_cnt++) {
|
||||
push_data_to_gradio_component({
|
||||
visible: false,
|
||||
choices: [],
|
||||
label: "",
|
||||
__type__: 'update'
|
||||
}, "plugin_arg_drop_"+dropdown_cnt, "obj");
|
||||
document.getElementById("plugin_arg_drop_"+dropdown_cnt).parentNode.style.display = 'none';
|
||||
}, "plugin_arg_drop_" + dropdown_cnt, "obj");
|
||||
document.getElementById("plugin_arg_drop_" + dropdown_cnt).parentNode.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function close_current_pop_up_plugin(){
|
||||
// PLUGIN_ARG_MENU
|
||||
function close_current_pop_up_plugin() {
|
||||
// PLUGIN_ARG_MENU
|
||||
push_data_to_gradio_component({
|
||||
visible: false,
|
||||
__type__: 'update'
|
||||
|
|
@ -1233,15 +1364,13 @@ function close_current_pop_up_plugin(){
|
|||
|
||||
// 生成高级插件的选择菜单
|
||||
plugin_init_info_lib = {}
|
||||
function register_plugin_init(key, base64String){
|
||||
function register_plugin_init(key, base64String) {
|
||||
// console.log('x')
|
||||
const stringData = atob(base64String);
|
||||
let guiJsonData = JSON.parse(stringData);
|
||||
if (key in plugin_init_info_lib)
|
||||
{
|
||||
if (key in plugin_init_info_lib) {
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
plugin_init_info_lib[key] = {};
|
||||
}
|
||||
plugin_init_info_lib[key].info = guiJsonData.Info;
|
||||
|
|
@ -1251,28 +1380,26 @@ function register_plugin_init(key, base64String){
|
|||
plugin_init_info_lib[key].enable_advanced_arg = guiJsonData.AdvancedArgs;
|
||||
plugin_init_info_lib[key].arg_reminder = guiJsonData.ArgsReminder;
|
||||
}
|
||||
function register_advanced_plugin_init_code(key, code){
|
||||
if (key in plugin_init_info_lib)
|
||||
{
|
||||
function register_advanced_plugin_init_code(key, code) {
|
||||
if (key in plugin_init_info_lib) {
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
plugin_init_info_lib[key] = {};
|
||||
}
|
||||
plugin_init_info_lib[key].secondary_menu_code = code;
|
||||
}
|
||||
function run_advanced_plugin_launch_code(key){
|
||||
function run_advanced_plugin_launch_code(key) {
|
||||
// convert js code string to function
|
||||
generate_menu(plugin_init_info_lib[key].secondary_menu_code, key);
|
||||
}
|
||||
function on_flex_button_click(key){
|
||||
if (plugin_init_info_lib.hasOwnProperty(key) && plugin_init_info_lib[key].hasOwnProperty('secondary_menu_code')){
|
||||
function on_flex_button_click(key) {
|
||||
if (plugin_init_info_lib.hasOwnProperty(key) && plugin_init_info_lib[key].hasOwnProperty('secondary_menu_code')) {
|
||||
run_advanced_plugin_launch_code(key);
|
||||
}else{
|
||||
} else {
|
||||
document.getElementById("old_callback_btn_for_plugin_exe").click();
|
||||
}
|
||||
}
|
||||
async function run_dropdown_shift(dropdown){
|
||||
async function run_dropdown_shift(dropdown) {
|
||||
let key = dropdown;
|
||||
push_data_to_gradio_component({
|
||||
value: key,
|
||||
|
|
@ -1281,7 +1408,7 @@ async function run_dropdown_shift(dropdown){
|
|||
__type__: 'update'
|
||||
}, "elem_switchy_bt", "obj");
|
||||
|
||||
if (plugin_init_info_lib[key].enable_advanced_arg){
|
||||
if (plugin_init_info_lib[key].enable_advanced_arg) {
|
||||
push_data_to_gradio_component({
|
||||
visible: true,
|
||||
label: plugin_init_info_lib[key].label,
|
||||
|
|
@ -1303,9 +1430,9 @@ async function duplicate_in_new_window() {
|
|||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
async function run_classic_plugin_via_id(plugin_elem_id){
|
||||
for (key in plugin_init_info_lib){
|
||||
if (plugin_init_info_lib[key].elem_id == plugin_elem_id){
|
||||
async function run_classic_plugin_via_id(plugin_elem_id) {
|
||||
for (key in plugin_init_info_lib) {
|
||||
if (plugin_init_info_lib[key].elem_id == plugin_elem_id) {
|
||||
// 获取按钮名称
|
||||
let current_btn_name = await get_data_from_gradio_component(plugin_elem_id);
|
||||
// 执行
|
||||
|
|
@ -1326,7 +1453,7 @@ async function call_plugin_via_name(current_btn_name) {
|
|||
hide_all_elem();
|
||||
// 为了与旧插件兼容,生成菜单时,自动加载旧高级参数输入区的值
|
||||
let advance_arg_input_legacy = await get_data_from_gradio_component('advance_arg_input_legacy');
|
||||
if (advance_arg_input_legacy.length != 0){
|
||||
if (advance_arg_input_legacy.length != 0) {
|
||||
gui_args["advanced_arg"] = {};
|
||||
gui_args["advanced_arg"].user_confirmed_value = advance_arg_input_legacy;
|
||||
}
|
||||
|
|
@ -1353,7 +1480,7 @@ async function multiplex_function_begin(multiplex_sel) {
|
|||
// do not delete `REPLACE_EXTENDED_MULTIPLEX_FUNCTIONS_HERE`! It will be read and replaced by Python code.
|
||||
// REPLACE_EXTENDED_MULTIPLEX_FUNCTIONS_HERE
|
||||
}
|
||||
async function run_multiplex_shift(multiplex_sel){
|
||||
async function run_multiplex_shift(multiplex_sel) {
|
||||
let key = multiplex_sel;
|
||||
if (multiplex_sel === "常规对话") {
|
||||
key = "提交";
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ def minimize_js(common_js_path):
|
|||
os.remove(old_min_js)
|
||||
# use rjsmin to minimize `common_js_path`
|
||||
c_jsmin = rjsmin.jsmin
|
||||
with open(common_js_path, "r") as f:
|
||||
with open(common_js_path, "r", encoding='utf-8') as f:
|
||||
js_content = f.read()
|
||||
if common_js_path == "themes/common.js":
|
||||
js_content = inject_mutex_button_code(js_content)
|
||||
|
|
@ -38,7 +38,7 @@ def minimize_js(common_js_path):
|
|||
sha_hash = hashlib.sha256(minimized_js_content.encode()).hexdigest()[:8]
|
||||
minimized_js_path = common_js_path + '.min.' + sha_hash + '.js'
|
||||
# save to minimized js file
|
||||
with open(minimized_js_path, "w") as f:
|
||||
with open(minimized_js_path, "w", encoding='utf-8') as f:
|
||||
f.write(minimized_js_content)
|
||||
# return minimized js file path
|
||||
return minimized_js_path
|
||||
|
|
|
|||
1177
themes/green.css
1177
themes/green.css
File diff suppressed because it is too large
Load Diff
|
|
@ -1,7 +1,7 @@
|
|||
import gradio as gr
|
||||
|
||||
def define_gui_floating_menu(customize_btns, functional, predefined_btns, cookies, web_cookie_cache):
|
||||
with gr.Floating(init_x="20%", init_y="50%", visible=False, width="40%", drag="top") as area_input_secondary:
|
||||
with gr.Floating(init_x="20%", init_y="50%", visible=False, width="40%", drag="top", elem_id="f_area_input_secondary") as area_input_secondary:
|
||||
with gr.Accordion("浮动输入区", open=True, elem_id="input-panel2"):
|
||||
with gr.Row() as row:
|
||||
row.style(equal_height=True)
|
||||
|
|
@ -17,7 +17,7 @@ def define_gui_floating_menu(customize_btns, functional, predefined_btns, cookie
|
|||
clearBtn2 = gr.Button("清除", elem_id="elem_clear2", variant="secondary", visible=False); clearBtn2.style(size="sm")
|
||||
|
||||
|
||||
with gr.Floating(init_x="20%", init_y="50%", visible=False, width="40%", drag="top") as area_customize:
|
||||
with gr.Floating(init_x="20%", init_y="50%", visible=False, width="40%", drag="top", elem_id="f_area_customize") as area_customize:
|
||||
with gr.Accordion("自定义菜单", open=True, elem_id="edit-panel"):
|
||||
with gr.Row() as row:
|
||||
with gr.Column(scale=10):
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ async function GptAcademicJavaScriptInit(dark, prompt, live2d, layout, tts) {
|
|||
audio_fn_init();
|
||||
minor_ui_adjustment();
|
||||
ButtonWithDropdown_init();
|
||||
update_conversation_metadata();
|
||||
window.addEventListener("gptac_restore_chat_from_local_storage", restore_chat_from_local_storage);
|
||||
|
||||
// 加载欢迎页面
|
||||
const welcomeMessage = new WelcomeMessage();
|
||||
|
|
|
|||
|
|
@ -92,15 +92,6 @@ js_code_for_persistent_cookie_init = """(web_cookie_cache, cookie) => {
|
|||
}
|
||||
"""
|
||||
|
||||
# 详见 themes/common.js
|
||||
js_code_reset = """
|
||||
(a,b,c)=>{
|
||||
let stopButton = document.getElementById("elem_stop");
|
||||
stopButton.click();
|
||||
return reset_conversation(a,b);
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
js_code_clear = """
|
||||
(a,b)=>{
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class WelcomeMessage {
|
|||
this.max_welcome_card_num = 6;
|
||||
this.card_array = [];
|
||||
this.static_welcome_message_previous = [];
|
||||
this.reflesh_time_interval = 15*1000;
|
||||
this.reflesh_time_interval = 15 * 1000;
|
||||
|
||||
|
||||
const reflesh_render_status = () => {
|
||||
|
|
@ -105,7 +105,7 @@ class WelcomeMessage {
|
|||
async startRefleshCards() {
|
||||
await new Promise(r => setTimeout(r, this.reflesh_time_interval));
|
||||
await this.reflesh_cards();
|
||||
if (this.visible){
|
||||
if (this.visible) {
|
||||
setTimeout(() => {
|
||||
this.startRefleshCards.call(this);
|
||||
}, 1);
|
||||
|
|
@ -113,7 +113,7 @@ class WelcomeMessage {
|
|||
}
|
||||
|
||||
async reflesh_cards() {
|
||||
if (!this.visible){
|
||||
if (!this.visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -173,18 +173,18 @@ class WelcomeMessage {
|
|||
}
|
||||
|
||||
shuffle(array) {
|
||||
var currentIndex = array.length, randomIndex;
|
||||
var currentIndex = array.length, randomIndex;
|
||||
|
||||
// While there remain elements to shuffle...
|
||||
while (currentIndex != 0) {
|
||||
|
||||
// Pick a remaining element...
|
||||
randomIndex = Math.floor(Math.random() * currentIndex);
|
||||
currentIndex--;
|
||||
// Pick a remaining element...
|
||||
randomIndex = Math.floor(Math.random() * currentIndex);
|
||||
currentIndex--;
|
||||
|
||||
// And swap it with the current element.
|
||||
[array[currentIndex], array[randomIndex]] = [
|
||||
array[randomIndex], array[currentIndex]];
|
||||
// And swap it with the current element.
|
||||
[array[currentIndex], array[randomIndex]] = [
|
||||
array[randomIndex], array[currentIndex]];
|
||||
}
|
||||
|
||||
return array;
|
||||
|
|
@ -193,7 +193,7 @@ class WelcomeMessage {
|
|||
async update() {
|
||||
// console.log('update')
|
||||
var page_width = document.documentElement.clientWidth;
|
||||
const width_to_hide_welcome = 1200;
|
||||
const width_to_hide_welcome = 1000;
|
||||
if (!await this.isChatbotEmpty() || page_width < width_to_hide_welcome) {
|
||||
if (this.visible) {
|
||||
this.removeWelcome();
|
||||
|
|
@ -203,7 +203,7 @@ class WelcomeMessage {
|
|||
}
|
||||
return;
|
||||
}
|
||||
if (this.visible){
|
||||
if (this.visible) {
|
||||
return;
|
||||
}
|
||||
// console.log("welcome");
|
||||
|
|
@ -220,28 +220,28 @@ class WelcomeMessage {
|
|||
const title = document.createElement('div');
|
||||
title.classList.add('welcome-card-title');
|
||||
|
||||
// 创建图标
|
||||
const svg = document.createElement('img');
|
||||
svg.classList.add('welcome-svg');
|
||||
svg.src = message.svg;
|
||||
svg.style.height = '30px';
|
||||
title.appendChild(svg);
|
||||
// 创建图标
|
||||
const svg = document.createElement('img');
|
||||
svg.classList.add('welcome-svg');
|
||||
svg.src = message.svg;
|
||||
svg.style.height = '30px';
|
||||
title.appendChild(svg);
|
||||
|
||||
// 创建标题
|
||||
const text = document.createElement('a');
|
||||
text.textContent = message.title;
|
||||
text.classList.add('welcome-title-text');
|
||||
text.href = message.url;
|
||||
text.target = "_blank";
|
||||
title.appendChild(text)
|
||||
// 创建标题
|
||||
const text = document.createElement('a');
|
||||
text.textContent = message.title;
|
||||
text.classList.add('welcome-title-text');
|
||||
text.href = message.url;
|
||||
text.target = "_blank";
|
||||
title.appendChild(text)
|
||||
|
||||
// 创建内容
|
||||
const content = document.createElement('div');
|
||||
content.classList.add('welcome-content');
|
||||
const content_c = document.createElement('div');
|
||||
content_c.classList.add('welcome-content-c');
|
||||
content_c.textContent = message.content;
|
||||
content.appendChild(content_c);
|
||||
const content_c = document.createElement('div');
|
||||
content_c.classList.add('welcome-content-c');
|
||||
content_c.textContent = message.content;
|
||||
content.appendChild(content_c);
|
||||
|
||||
// 将标题和内容添加到卡片 div 中
|
||||
card.appendChild(title);
|
||||
|
|
@ -307,28 +307,28 @@ class WelcomeMessage {
|
|||
|
||||
class PageFocusHandler {
|
||||
constructor() {
|
||||
this.hasReturned = false;
|
||||
this.focusCallbacks = [];
|
||||
this.hasReturned = false;
|
||||
this.focusCallbacks = [];
|
||||
|
||||
// Bind the focus and blur event handlers
|
||||
window.addEventListener('visibilitychange', this.handleFocus.bind(this));
|
||||
// Bind the focus and blur event handlers
|
||||
window.addEventListener('visibilitychange', this.handleFocus.bind(this));
|
||||
}
|
||||
|
||||
// Method to handle the focus event
|
||||
handleFocus() {
|
||||
if (this.hasReturned) {
|
||||
this.focusCallbacks.forEach(callback => callback());
|
||||
}
|
||||
this.hasReturned = true;
|
||||
if (this.hasReturned) {
|
||||
this.focusCallbacks.forEach(callback => callback());
|
||||
}
|
||||
this.hasReturned = true;
|
||||
}
|
||||
|
||||
// Method to add a custom callback function
|
||||
addFocusCallback(callback) {
|
||||
if (typeof callback === 'function') {
|
||||
this.focusCallbacks.push(callback);
|
||||
} else {
|
||||
throw new Error('Callback must be a function');
|
||||
}
|
||||
if (typeof callback === 'function') {
|
||||
this.focusCallbacks.push(callback);
|
||||
} else {
|
||||
throw new Error('Callback must be a function');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
12
toolbox.py
12
toolbox.py
|
|
@ -8,6 +8,7 @@ import base64
|
|||
import gradio
|
||||
import shutil
|
||||
import glob
|
||||
import json
|
||||
import uuid
|
||||
from loguru import logger
|
||||
from functools import wraps
|
||||
|
|
@ -92,8 +93,9 @@ def ArgsGeneralWrapper(f):
|
|||
"""
|
||||
def decorated(request: gradio.Request, cookies:dict, max_length:int, llm_model:str,
|
||||
txt:str, txt2:str, top_p:float, temperature:float, chatbot:list,
|
||||
history:list, system_prompt:str, plugin_advanced_arg:dict, *args):
|
||||
json_history:str, system_prompt:str, plugin_advanced_arg:dict, *args):
|
||||
txt_passon = txt
|
||||
history = json.loads(json_history) if json_history else []
|
||||
if txt == "" and txt2 != "": txt_passon = txt2
|
||||
# 引入一个有cookie的chatbot
|
||||
if request.username is not None:
|
||||
|
|
@ -148,10 +150,11 @@ def ArgsGeneralWrapper(f):
|
|||
return decorated
|
||||
|
||||
|
||||
def update_ui(chatbot:ChatBotWithCookies, history, msg="正常", **kwargs): # 刷新界面
|
||||
def update_ui(chatbot:ChatBotWithCookies, history:list, msg:str="正常", **kwargs): # 刷新界面
|
||||
"""
|
||||
刷新用户界面
|
||||
"""
|
||||
assert isinstance(history, list), "history必须是一个list"
|
||||
assert isinstance(
|
||||
chatbot, ChatBotWithCookies
|
||||
), "在传递chatbot的过程中不要将其丢弃。必要时, 可用clear将其清空, 然后用for+append循环重新赋值。"
|
||||
|
|
@ -175,10 +178,11 @@ def update_ui(chatbot:ChatBotWithCookies, history, msg="正常", **kwargs): #
|
|||
else:
|
||||
chatbot_gr = chatbot
|
||||
|
||||
yield cookies, chatbot_gr, history, msg
|
||||
json_history = json.dumps(history, ensure_ascii=False)
|
||||
yield cookies, chatbot_gr, json_history, msg
|
||||
|
||||
|
||||
def update_ui_lastest_msg(lastmsg:str, chatbot:ChatBotWithCookies, history:list, delay=1, msg="正常"): # 刷新界面
|
||||
def update_ui_lastest_msg(lastmsg:str, chatbot:ChatBotWithCookies, history:list, delay:float=1, msg:str="正常"): # 刷新界面
|
||||
"""
|
||||
刷新用户界面
|
||||
"""
|
||||
|
|
|
|||
Loading…
Reference in New Issue