From b31abbcad352cf773a7b512d129f3be9f97ba2ad Mon Sep 17 00:00:00 2001 From: qingxu fu <505030475@qq.com> Date: Thu, 31 Aug 2023 15:59:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=AF=8F=E4=B8=AA=E6=8F=92=E4=BB=B6=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E5=BD=92=E5=B1=9E=E5=A4=9A=E4=B8=AAGroup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functional.py | 30 ++++++++---- main.py | 110 ++++++++++++++++++-------------------------- 2 files changed, 64 insertions(+), 76 deletions(-) diff --git a/crazy_functional.py b/crazy_functional.py index ee3ed99..e51dec0 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -168,7 +168,7 @@ def get_crazy_functions(): "Function": HotReload(对话历史存档) }, "[多线程Demo]解析此项目本身(源码自译解)": { - "Group": "对话", + "Group": "对话|编程", "AsButton": False, # 加入下拉菜单中 "Function": HotReload(解析项目本身) }, @@ -499,13 +499,23 @@ def get_crazy_functions(): # except: # print('Load function plugin failed') - regroupped_functions = {} + + + """ + 设置默认值: + - 默认 Group = 对话 + - 默认 AsButton = True + - 默认 AdvancedArgs = False + - 默认 Color = secondary + """ for name, function_meta in function_plugins.items(): - if "Group" in function_meta: - groups = function_meta["Group"].split('|') - else: - groups = ['对话'] - for gruop in groups: - regroupped_functions[gruop] = regroupped_functions.get(gruop, {}) - regroupped_functions[gruop].update({name: function_meta}) - return regroupped_functions + if "Group" not in function_meta: + function_plugins[name]["Group"] = '对话' + if "AsButton" not in function_meta: + function_plugins[name]["AsButton"] = True + if "AdvancedArgs" not in function_meta: + function_plugins[name]["AdvancedArgs"] = False + if "Color" not in function_meta: + function_plugins[name]["Color"] = 'secondary' + + return function_plugins diff --git a/main.py b/main.py index f21383b..50028c2 100644 --- a/main.py +++ b/main.py @@ -5,19 +5,20 @@ def main(): # if gr.__version__ not in ['3.28.3','3.32.2']: assert False, "需要特殊依赖,请务必用 pip install -r requirements.txt 指令安装依赖,详情信息见requirements.txt" from request_llm.bridge_all import predict from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf, ArgsGeneralWrapper, load_chat_cookies, DummyWith + # 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到 - proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, AVAIL_LLM_MODELS, AUTO_CLEAR_TXT = \ - get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'AVAIL_LLM_MODELS', 'AUTO_CLEAR_TXT') + proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION = get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION') + CHATBOT_HEIGHT, LAYOUT, AVAIL_LLM_MODELS, AUTO_CLEAR_TXT = get_conf('CHATBOT_HEIGHT', 'LAYOUT', 'AVAIL_LLM_MODELS', 'AUTO_CLEAR_TXT') ENABLE_AUDIO, AUTO_CLEAR_TXT = get_conf('ENABLE_AUDIO', 'AUTO_CLEAR_TXT') + # 如果WEB_PORT是-1, 则随机选取WEB端口 PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT - if not AUTHENTICATION: AUTHENTICATION = None - from check_proxy import get_current_version from themes.theme import adjust_theme, advanced_css, theme_declaration initial_prompt = "Serve me as a writing and programming assistant." title_html = f"

GPT 学术优化 {get_current_version()}

{theme_declaration}" - description = """代码开源和更新[地址🚀](https://github.com/binary-husky/chatgpt_academic),感谢热情的[开发者们❤️](https://github.com/binary-husky/chatgpt_academic/graphs/contributors)""" + description = "代码开源和更新[地址🚀](https://github.com/binary-husky/gpt_academic)," + description += "感谢热情的[开发者们❤️](https://github.com/binary-husky/gpt_academic/graphs/contributors)" # 问询记录, python 版本建议3.9+(越新越好) import logging, uuid @@ -35,12 +36,9 @@ def main(): # 高级函数插件 from crazy_functional import get_crazy_functions DEFAULT_FN_GROUPS, = get_conf('DEFAULT_FN_GROUPS') - crazy_fns_role = get_crazy_functions() - crazy_classification = [i for i in crazy_fns_role] - crazy_fns = {} - for role in crazy_fns_role: - for k in crazy_fns_role[role]: - crazy_fns[k] = crazy_fns_role[role][k] + plugins = get_crazy_functions() + all_plugin_groups = list(set([g for _, plugin in plugins.items() for g in plugin['Group'].split('|')])) + match_group = lambda tags, groups: any([g in groups for g in tags.split('|')]) # 处理markdown文本格式的转变 gr.Chatbot.postprocess = format_io @@ -94,35 +92,21 @@ def main(): with gr.Row(): gr.Markdown("插件可读取“输入区”文本/路径作为参数(上传文件自动修正路径)") with gr.Row(elem_id="input-plugin-group"): - plugin_dropdown = gr.Dropdown(choices=crazy_classification, label='', - value=DEFAULT_FN_GROUPS, - multiselect=True, interactive=True, - elem_classes='normal_mut_select', - ).style(container=False) + plugin_group_sel = gr.Dropdown(choices=all_plugin_groups, label='', show_label=False, value=DEFAULT_FN_GROUPS, + multiselect=True, interactive=True, elem_classes='normal_mut_select').style(container=False) with gr.Row(): - for role in crazy_fns_role: - for k in crazy_fns_role[role]: - if not crazy_fns_role[role][k].get("AsButton", True): continue - if role not in DEFAULT_FN_GROUPS: - variant = crazy_fns_role[role][k]["Color"] if "Color" in crazy_fns_role[role][ - k] else "secondary" - crazy_fns_role[role][k]['Button'] = gr.Button(k, variant=variant, - visible=False).style(size="sm") - else: - variant = crazy_fns[k]["Color"] if "Color" in crazy_fns_role[role][ - k] else "secondary" - crazy_fns_role[role][k]['Button'] = gr.Button(k, variant=variant, - visible=True).style(size="sm") + for k, plugin in plugins.items(): + if not plugin.get("AsButton", True): continue + visible = True if match_group(plugin['Group'], DEFAULT_FN_GROUPS) else False + variant = plugins[k]["Color"] if "Color" in plugin else "secondary" + plugin['Button'] = plugins[k]['Button'] = gr.Button(k, variant=variant, visible=visible).style(size="sm") with gr.Row(): with gr.Accordion("更多函数插件", open=True): dropdown_fn_list = [] - for role in crazy_fns_role: - if role in DEFAULT_FN_GROUPS: - for k in crazy_fns_role[role]: - if not crazy_fns_role[role][k].get("AsButton", True): - dropdown_fn_list.append(k) - elif crazy_fns_role[role][k].get('AdvancedArgs', False): - dropdown_fn_list.append(k) + for k, plugin in plugins.items(): + if not match_group(plugin['Group'], DEFAULT_FN_GROUPS): continue + if not plugin.get("AsButton", True): dropdown_fn_list.append(k) # 排除已经是按钮的插件 + elif plugin.get('AdvancedArgs', False): dropdown_fn_list.append(k) # 对于需要高级参数的插件,亦在下拉菜单中显示 with gr.Row(): dropdown = gr.Dropdown(dropdown_fn_list, value=r"打开插件列表", label="", show_label=False).style(container=False) with gr.Row(): @@ -150,6 +134,7 @@ def main(): resetBtn2 = gr.Button("重置", variant="secondary"); resetBtn2.style(size="sm") stopBtn2 = gr.Button("停止", variant="secondary"); stopBtn2.style(size="sm") clearBtn2 = gr.Button("清除", variant="secondary", visible=False); clearBtn2.style(size="sm") + # 功能区显示开关与功能区的互动 def fn_area_visibility(a): ret = {} @@ -189,17 +174,17 @@ def main(): # 文件上传区,接收文件后与chatbot的互动 file_upload.upload(on_file_uploaded, [file_upload, chatbot, txt, txt2, checkboxes], [chatbot, txt, txt2]) # 函数插件-固定按钮区 - for k in crazy_fns: - if not crazy_fns[k].get("AsButton", True): continue - click_handle = crazy_fns[k]["Button"].click(ArgsGeneralWrapper(crazy_fns[k]["Function"]), [*input_combo, gr.State(PORT)], output_combo) + for k in plugins: + if not plugins[k].get("AsButton", True): continue + click_handle = plugins[k]["Button"].click(ArgsGeneralWrapper(plugins[k]["Function"]), [*input_combo, gr.State(PORT)], output_combo) click_handle.then(on_report_generated, [cookies, file_upload, chatbot], [cookies, file_upload, chatbot]) cancel_handles.append(click_handle) # 函数插件-下拉菜单与随变按钮的互动 def on_dropdown_changed(k): - variant = crazy_fns[k]["Color"] if "Color" in crazy_fns[k] else "secondary" + variant = plugins[k]["Color"] if "Color" in plugins[k] else "secondary" ret = {switchy_bt: gr.update(value=k, variant=variant)} - if crazy_fns[k].get("AdvancedArgs", False): # 是否唤起高级插件参数区 - ret.update({plugin_advanced_arg: gr.update(visible=True, label=f"插件[{k}]的高级参数说明:" + crazy_fns[k].get("ArgsReminder", [f"没有提供高级参数功能说明"]))}) + if plugins[k].get("AdvancedArgs", False): # 是否唤起高级插件参数区 + ret.update({plugin_advanced_arg: gr.update(visible=True, label=f"插件[{k}]的高级参数说明:" + plugins[k].get("ArgsReminder", [f"没有提供高级参数功能说明"]))}) else: ret.update({plugin_advanced_arg: gr.update(visible=False, label=f"插件[{k}]不需要高级参数。")}) return ret @@ -210,35 +195,26 @@ def main(): # 随变按钮的回调函数注册 def route(request: gr.Request, k, *args, **kwargs): if k in [r"打开插件列表", r"请先从插件列表中选择"]: return - yield from ArgsGeneralWrapper(crazy_fns[k]["Function"])(request, *args, **kwargs) + yield from ArgsGeneralWrapper(plugins[k]["Function"])(request, *args, **kwargs) click_handle = switchy_bt.click(route,[switchy_bt, *input_combo, gr.State(PORT)], output_combo) click_handle.then(on_report_generated, [cookies, file_upload, chatbot], [cookies, file_upload, chatbot]) cancel_handles.append(click_handle) # 终止按钮的回调函数注册 stopBtn.click(fn=None, inputs=None, outputs=None, cancels=cancel_handles) stopBtn2.click(fn=None, inputs=None, outputs=None, cancels=cancel_handles) - fn_btn_dict = {crazy_fns_role[role][k]['Button']: {role: k} for role in crazy_fns_role for k in crazy_fns_role[role] if crazy_fns_role[role][k].get('Button')} - def show_plugin_btn(plu_list): - new_btn_list = [] + plugins_as_btn = {name:plugin for name, plugin in plugins.items() if plugin.get('Button', None)} + def on_group_change(group_list): + btn_list = [] fns_list = [] - if not plu_list: - return [*[fns.update(visible=False) for fns in fn_btn_dict], gr.Dropdown.update(choices=[])] - else: - for fns in fn_btn_dict: - if list(fn_btn_dict[fns].keys())[0] in plu_list: - new_btn_list.append(fns.update(visible=True)) - else: - new_btn_list.append(fns.update(visible=False)) - for role in crazy_fns_role: - if role in plu_list: - for k in crazy_fns_role[role]: - if not crazy_fns_role[role][k].get("AsButton", True): - fns_list.append(k) - elif crazy_fns_role[role][k].get('AdvancedArgs', False): - fns_list.append(k) - return [*new_btn_list, gr.Dropdown.update(choices=fns_list)] - plugin_dropdown.select(fn=show_plugin_btn, inputs=[plugin_dropdown], - outputs=[*fn_btn_dict.keys(), dropdown]) + if not group_list: # 处理特殊情况:没有选择任何插件组 + return [*[plugin['Button'].update(visible=False) for _, plugin in plugins_as_btn.items()], gr.Dropdown.update(choices=[])] + for k, plugin in plugins.items(): + if plugin.get("AsButton", True): + btn_list.append(plugin['Button'].update(visible=match_group(plugin['Group'], group_list))) # 刷新按钮 + if plugin.get('AdvancedArgs', False): dropdown_fn_list.append(k) # 对于需要高级参数的插件,亦在下拉菜单中显示 + elif match_group(plugin['Group'], group_list): fns_list.append(k) # 刷新下拉列表 + return [*btn_list, gr.Dropdown.update(choices=fns_list)] + plugin_group_sel.select(fn=on_group_change, inputs=[plugin_group_sel], outputs=[*[plugin['Button'] for name, plugin in plugins_as_btn.items()], dropdown]) if ENABLE_AUDIO: from crazy_functions.live_audio.audio_io import RealtimeAudioDistribution rad = RealtimeAudioDistribution() @@ -270,8 +246,10 @@ def main(): auto_opentab_delay() demo.queue(concurrency_count=CONCURRENT_COUNT).launch( - server_name="0.0.0.0", server_port=PORT, - favicon_path="docs/logo.png", auth=AUTHENTICATION, + server_name="0.0.0.0", + server_port=PORT, + favicon_path="docs/logo.png", + auth=AUTHENTICATION if len(AUTHENTICATION) != 0 else None, blocked_paths=["config.py","config_private.py","docker-compose.yml","Dockerfile"]) # 如果需要在二级路径下运行