From 2f9a4e1618463b45ffd3df4e43d6c3c64d50b3a7 Mon Sep 17 00:00:00 2001 From: mrhblfx Date: Sun, 16 Apr 2023 23:00:45 +0800 Subject: [PATCH 01/52] Add parsing arbitrary code items --- crazy_functional.py | 12 ++++++-- crazy_functions/解析项目源代码.py | 49 +++++++++++++++++++++++++------ main.py | 27 ++++++++++++++--- toolbox.py | 21 ++++++------- 4 files changed, 84 insertions(+), 25 deletions(-) diff --git a/crazy_functional.py b/crazy_functional.py index af308b7f..afc32171 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -162,7 +162,7 @@ def get_crazy_functions(): "AsButton": False, # 加入下拉菜单中 "Function": HotReload(Markdown英译中) }, - + }) ###################### 第三组插件 ########################### @@ -179,8 +179,16 @@ def get_crazy_functions(): except Exception as err: print(f'[下载arxiv论文并翻译摘要] 插件导入失败 {str(err)}') - + from crazy_functions.解析项目源代码 import 解析任意code项目 + function_plugins.update({ + "解析任意code项目": { + "Color": "stop", + "AsButton": False, + "Function": HotReload(解析任意code项目) + }, + }) + ###################### 第n组插件 ########################### return function_plugins diff --git a/crazy_functions/解析项目源代码.py b/crazy_functions/解析项目源代码.py index 04e5128a..283f1033 100644 --- a/crazy_functions/解析项目源代码.py +++ b/crazy_functions/解析项目源代码.py @@ -11,7 +11,7 @@ def 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, history_array = [] sys_prompt_array = [] report_part_1 = [] - + assert len(file_manifest) <= 1024, "源文件太多(超过1024个), 请缩减输入文件的数量。或者,您也可以选择删除此行警告,并修改代码拆分file_manifest列表,从而实现分批次处理。" ############################## <第一步,逐个文件分析,多线程> ################################## for index, fp in enumerate(file_manifest): @@ -63,10 +63,10 @@ def 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, current_iteration_focus = ', '.join([os.path.relpath(fp, project_folder) for index, fp in enumerate(this_iteration_file_manifest)]) i_say = f'根据以上分析,对程序的整体功能和构架重新做出概括。然后用一张markdown表格整理每个文件的功能(包括{previous_iteration_files_string})。' inputs_show_user = f'根据以上分析,对程序的整体功能和构架重新做出概括,由于输入长度限制,可能需要分组处理,本组文件为 {current_iteration_focus} + 已经汇总的文件组。' - this_iteration_history = copy.deepcopy(this_iteration_gpt_response_collection) + this_iteration_history = copy.deepcopy(this_iteration_gpt_response_collection) this_iteration_history.append(last_iteration_result) result = yield from request_gpt_model_in_new_thread_with_ui_alive( - inputs=i_say, inputs_show_user=inputs_show_user, llm_kwargs=llm_kwargs, chatbot=chatbot, + inputs=i_say, inputs_show_user=inputs_show_user, llm_kwargs=llm_kwargs, chatbot=chatbot, history=this_iteration_history, # 迭代之前的分析 sys_prompt="你是一个程序架构分析师,正在分析一个项目的源代码。") report_part_2.extend([i_say, result]) @@ -222,8 +222,8 @@ def 解析一个Golang项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, s yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 return yield from 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt) - - + + @CatchException def 解析一个Lua项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): history = [] # 清空历史,以免输入溢出 @@ -243,9 +243,9 @@ def 解析一个Lua项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到任何lua文件: {txt}") yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 return - yield from 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt) - - + yield from 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt) + + @CatchException def 解析一个CSharp项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): history = [] # 清空历史,以免输入溢出 @@ -263,4 +263,35 @@ def 解析一个CSharp项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, s report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到任何CSharp文件: {txt}") yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 return - yield from 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt) + yield from 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt) + + +@CatchException +def 解析任意code项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + txt_include = plugin_kwargs.get("txt_include") + txt_except = plugin_kwargs.get("txt_except") + # 将要匹配的后缀 + pattern_include = [_.lstrip(" .,,").rstrip(" ,,") for _ in txt_include.split(" ") if _ != ""] + pattern_include = [_.lstrip(" .,,").rstrip(" ,,") for __ in pattern_include for _ in __.split(",") if _ != ""] + pattern_include = [_.lstrip(" .,,").rstrip(" ,,") for __ in pattern_include for _ in __.split(",") if _ != ""] + # 将要忽略匹配的后缀 + pattern_except = [_.lstrip(" .,,").rstrip(" ,,") for _ in txt_except.split(" ") if _ != ""] + pattern_except = [_.lstrip(" .,,").rstrip(" ,,") for __ in pattern_except for _ in __.split(",") if _ != ""] + pattern_except = [_.lstrip(" .,,").rstrip(" ,,") for __ in pattern_except for _ in __.split(",") if _ != ""] + pattern_except += ['zip', 'rar', '7z', 'tar', 'gz'] # 避免解析上传的压缩文件 + history = [] # 清空历史,以免输入溢出 + import glob, os + if os.path.exists(txt): + project_folder = txt + else: + if txt == "": txt = '空空如也的输入栏' + report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到本地项目或无权访问: {txt}") + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + return + file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.*', recursive=True) if os.path.isfile(f) and \ + ([] == pattern_include or f.split(".")[-1] in pattern_include) and f.split(".")[-1] not in pattern_except] + if len(file_manifest) == 0: + report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到任何文件: {txt}") + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + return + yield from 解析源代码新(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt) \ No newline at end of file diff --git a/main.py b/main.py index 2e4e275d..73646dcb 100644 --- a/main.py +++ b/main.py @@ -44,7 +44,7 @@ proxy_info = check_proxy(proxies) gr_L1 = lambda: gr.Row().style() gr_L2 = lambda scale: gr.Column(scale=scale) -if LAYOUT == "TOP-DOWN": +if LAYOUT == "TOP-DOWN": gr_L1 = lambda: DummyWith() gr_L2 = lambda scale: gr.Row() CHATBOT_HEIGHT /= 2 @@ -83,9 +83,23 @@ with gr.Blocks(title="ChatGPT 学术优化", theme=set_theme, analytics_enabled= variant = crazy_fns[k]["Color"] if "Color" in crazy_fns[k] else "secondary" crazy_fns[k]["Button"] = gr.Button(k, variant=variant) crazy_fns[k]["Button"].style(size="sm") + with gr.Row(): + with gr.Accordion("解析任意code项目", open=True): + gr.Markdown("输入的文件后缀用空格或逗号隔开, 可混合使用空格逗号") + with gr.Row(): + gr.Markdown("将要匹配文件的后缀, 不输入则代表解析所有文件") + txt_pattern_include = gr.Textbox(show_label=False, placeholder="例如: .c .cpp .py").style(container=False) + with gr.Row(): + gr.Markdown("将要忽略匹配文件的后缀") + txt_pattern_except = gr.Textbox(show_label=False, placeholder="例如: .png, .jpg wav flac").style(container=False) + code_plugin_name = "解析任意code项目" + variant = crazy_fns[code_plugin_name]["Color"] if "Color" in crazy_fns[code_plugin_name] else "secondary" + crazy_fns[code_plugin_name]["Button"] = gr.Button(code_plugin_name, variant=variant) + crazy_fns[code_plugin_name]["Button"].style(size="sm") with gr.Row(): with gr.Accordion("更多函数插件", open=True): dropdown_fn_list = [k for k in crazy_fns.keys() if not crazy_fns[k].get("AsButton", True)] + dropdown_fn_list.remove(code_plugin_name) with gr.Column(scale=1): dropdown = gr.Dropdown(dropdown_fn_list, value=r"打开插件列表", label="").style(container=False) with gr.Column(scale=1): @@ -118,7 +132,8 @@ with gr.Blocks(title="ChatGPT 学术优化", theme=set_theme, analytics_enabled= return ret checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn, area_input_primary, area_input_secondary, txt, txt2] ) # 整理反复出现的控件句柄组合 - input_combo = [cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt] + add_input_combo = (txt_pattern_include, txt_pattern_except) + input_combo = [cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt, *add_input_combo] output_combo = [cookies, chatbot, history, status] predict_args = dict(fn=ArgsGeneralWrapper(predict), inputs=input_combo, outputs=output_combo) # 提交按钮、重置按钮 @@ -140,6 +155,10 @@ with gr.Blocks(title="ChatGPT 学术优化", theme=set_theme, analytics_enabled= click_handle = crazy_fns[k]["Button"].click(ArgsGeneralWrapper(crazy_fns[k]["Function"]), [*input_combo, gr.State(PORT)], output_combo) click_handle.then(on_report_generated, [file_upload, chatbot], [file_upload, chatbot]) cancel_handles.append(click_handle) + # 函数插件-解析任意code项目 + click_handle = crazy_fns[code_plugin_name]["Button"].click(ArgsGeneralWrapper(crazy_fns[code_plugin_name]["Function"]), [*input_combo, gr.State(PORT)], output_combo) + click_handle.then(on_report_generated, [file_upload, chatbot], [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" @@ -147,7 +166,7 @@ with gr.Blocks(title="ChatGPT 学术优化", theme=set_theme, analytics_enabled= dropdown.select(on_dropdown_changed, [dropdown], [switchy_bt] ) # 随变按钮的回调函数注册 def route(k, *args, **kwargs): - if k in [r"打开插件列表", r"请先从插件列表中选择"]: return + if k in [r"打开插件列表", r"请先从插件列表中选择"]: return yield from ArgsGeneralWrapper(crazy_fns[k]["Function"])(*args, **kwargs) click_handle = switchy_bt.click(route,[switchy_bt, *input_combo, gr.State(PORT)], output_combo) click_handle.then(on_report_generated, [file_upload, chatbot], [file_upload, chatbot]) @@ -164,7 +183,7 @@ def auto_opentab_delay(): print(f"如果浏览器没有自动打开,请复制并转到以下URL:") print(f"\t(亮色主题): http://localhost:{PORT}") print(f"\t(暗色主题): http://localhost:{PORT}/?__dark-theme=true") - def open(): + def open(): time.sleep(2) # 打开浏览器 webbrowser.open_new_tab(f"http://localhost:{PORT}/?__dark-theme=true") threading.Thread(target=open, name="open-browser", daemon=True).start() diff --git a/toolbox.py b/toolbox.py index 3ced6534..8de3a8dd 100644 --- a/toolbox.py +++ b/toolbox.py @@ -27,23 +27,24 @@ def ArgsGeneralWrapper(f): """ 装饰器函数,用于重组输入参数,改变输入参数的顺序与结构。 """ - def decorated(cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt, *args): + def decorated(cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt, txt_include, txt_except, *args): txt_passon = txt if txt == "" and txt2 != "": txt_passon = txt2 # 引入一个有cookie的chatbot cookies.update({ - 'top_p':top_p, + 'top_p':top_p, 'temperature':temperature, }) llm_kwargs = { 'api_key': cookies['api_key'], 'llm_model': cookies['llm_model'], - 'top_p':top_p, + 'top_p':top_p, 'temperature':temperature, } - plugin_kwargs = { - # 目前还没有 - } + # plugin_kwargs = { + # # 目前还没有 + # } + plugin_kwargs = dict(txt_include = txt_include, txt_except = txt_except) chatbot_with_cookie = ChatBotWithCookies(cookies) chatbot_with_cookie.write_list(chatbot) yield from f(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, *args) @@ -279,7 +280,7 @@ def markdown_convertion(txt): return content else: return tex2mathml_catch_exception(content) - + def markdown_bug_hunt(content): """ 解决一个mdx_math的bug(单$包裹begin命令时多余\n', '') return content - + if ('$' in txt) and ('```' not in txt): # 有$标识的公式符号,且没有代码段```的标识 # convert everything to html format @@ -308,7 +309,7 @@ def markdown_convertion(txt): def close_up_code_segment_during_stream(gpt_reply): """ 在gpt输出代码的中途(输出了前面的```,但还没输出完后面的```),补上后面的``` - + Args: gpt_reply (str): GPT模型返回的回复字符串。 @@ -518,7 +519,7 @@ class DummyWith(): 它的作用是……额……没用,即在代码结构不变得情况下取代其他的上下文管理器。 上下文管理器是一种Python对象,用于与with语句一起使用, 以确保一些资源在代码块执行期间得到正确的初始化和清理。 - 上下文管理器必须实现两个方法,分别为 __enter__()和 __exit__()。 + 上下文管理器必须实现两个方法,分别为 __enter__()和 __exit__()。 在上下文执行开始的情况下,__enter__()方法会在代码块被执行前被调用, 而在上下文执行结束时,__exit__()方法则会被调用。 """ From d1926725d3c9dd7d5d8540303f67069f04e7a3d5 Mon Sep 17 00:00:00 2001 From: mrhblfx Date: Sun, 16 Apr 2023 23:33:43 +0800 Subject: [PATCH 02/52] Add parsing arbitrary code items --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index 73646dcb..7db70523 100644 --- a/main.py +++ b/main.py @@ -85,7 +85,7 @@ with gr.Blocks(title="ChatGPT 学术优化", theme=set_theme, analytics_enabled= crazy_fns[k]["Button"].style(size="sm") with gr.Row(): with gr.Accordion("解析任意code项目", open=True): - gr.Markdown("输入的文件后缀用空格或逗号隔开, 可混合使用空格逗号") + gr.Markdown("输入的文件后缀用空格或逗号隔开,可混合使用空格逗号, 其中`.`可省略
例如:`.c, cpp py .go, .toml, json`") with gr.Row(): gr.Markdown("将要匹配文件的后缀, 不输入则代表解析所有文件") txt_pattern_include = gr.Textbox(show_label=False, placeholder="例如: .c .cpp .py").style(container=False) From 11e33ec657aecdacda3f0f64834f65519493da8c Mon Sep 17 00:00:00 2001 From: mrhblfx Date: Tue, 18 Apr 2023 23:29:18 +0800 Subject: [PATCH 03/52] Reduced one input box --- main.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index 7db70523..1b76783b 100644 --- a/main.py +++ b/main.py @@ -85,13 +85,9 @@ with gr.Blocks(title="ChatGPT 学术优化", theme=set_theme, analytics_enabled= crazy_fns[k]["Button"].style(size="sm") with gr.Row(): with gr.Accordion("解析任意code项目", open=True): - gr.Markdown("输入的文件后缀用空格或逗号隔开,可混合使用空格逗号, 其中`.`可省略
例如:`.c, cpp py .go, .toml, json`") + gr.Markdown("输入时用逗号隔开, `*`代表通配符, 加了`^`代表不匹配
例如: `*.c, ^*.cpp, config.toml, ^README.md`") with gr.Row(): - gr.Markdown("将要匹配文件的后缀, 不输入则代表解析所有文件") - txt_pattern_include = gr.Textbox(show_label=False, placeholder="例如: .c .cpp .py").style(container=False) - with gr.Row(): - gr.Markdown("将要忽略匹配文件的后缀") - txt_pattern_except = gr.Textbox(show_label=False, placeholder="例如: .png, .jpg wav flac").style(container=False) + txt_pattern = gr.Textbox(show_label=False, placeholder="输入框为空则代表匹配所有文件").style(container=False) code_plugin_name = "解析任意code项目" variant = crazy_fns[code_plugin_name]["Color"] if "Color" in crazy_fns[code_plugin_name] else "secondary" crazy_fns[code_plugin_name]["Button"] = gr.Button(code_plugin_name, variant=variant) @@ -132,8 +128,7 @@ with gr.Blocks(title="ChatGPT 学术优化", theme=set_theme, analytics_enabled= return ret checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn, area_input_primary, area_input_secondary, txt, txt2] ) # 整理反复出现的控件句柄组合 - add_input_combo = (txt_pattern_include, txt_pattern_except) - input_combo = [cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt, *add_input_combo] + input_combo = [cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt, txt_pattern] output_combo = [cookies, chatbot, history, status] predict_args = dict(fn=ArgsGeneralWrapper(predict), inputs=input_combo, outputs=output_combo) # 提交按钮、重置按钮 From 3a561a70db63e0e8ece844eb420e63859ba0b521 Mon Sep 17 00:00:00 2001 From: mrhblfx Date: Tue, 18 Apr 2023 23:30:19 +0800 Subject: [PATCH 04/52] Reduced one parameter --- toolbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toolbox.py b/toolbox.py index 8de3a8dd..e3e75ce0 100644 --- a/toolbox.py +++ b/toolbox.py @@ -27,7 +27,7 @@ def ArgsGeneralWrapper(f): """ 装饰器函数,用于重组输入参数,改变输入参数的顺序与结构。 """ - def decorated(cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt, txt_include, txt_except, *args): + def decorated(cookies, txt, txt2, top_p, temperature, chatbot, history, system_prompt, txt_pattern, *args): txt_passon = txt if txt == "" and txt2 != "": txt_passon = txt2 # 引入一个有cookie的chatbot @@ -44,7 +44,7 @@ def ArgsGeneralWrapper(f): # plugin_kwargs = { # # 目前还没有 # } - plugin_kwargs = dict(txt_include = txt_include, txt_except = txt_except) + plugin_kwargs = dict(txt_pattern = txt_pattern) chatbot_with_cookie = ChatBotWithCookies(cookies) chatbot_with_cookie.write_list(chatbot) yield from f(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, *args) From 9b5f0887939a2e8de21628733b2150f3638ccf8b Mon Sep 17 00:00:00 2001 From: mrhblfx Date: Tue, 18 Apr 2023 23:31:12 +0800 Subject: [PATCH 05/52] Changed matching rules --- crazy_functions/解析项目源代码.py | 38 +++++++++++++++++++------------ 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/crazy_functions/解析项目源代码.py b/crazy_functions/解析项目源代码.py index 283f1033..6eb67a31 100644 --- a/crazy_functions/解析项目源代码.py +++ b/crazy_functions/解析项目源代码.py @@ -268,19 +268,22 @@ def 解析一个CSharp项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, s @CatchException def 解析任意code项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): - txt_include = plugin_kwargs.get("txt_include") - txt_except = plugin_kwargs.get("txt_except") - # 将要匹配的后缀 - pattern_include = [_.lstrip(" .,,").rstrip(" ,,") for _ in txt_include.split(" ") if _ != ""] - pattern_include = [_.lstrip(" .,,").rstrip(" ,,") for __ in pattern_include for _ in __.split(",") if _ != ""] - pattern_include = [_.lstrip(" .,,").rstrip(" ,,") for __ in pattern_include for _ in __.split(",") if _ != ""] - # 将要忽略匹配的后缀 - pattern_except = [_.lstrip(" .,,").rstrip(" ,,") for _ in txt_except.split(" ") if _ != ""] - pattern_except = [_.lstrip(" .,,").rstrip(" ,,") for __ in pattern_except for _ in __.split(",") if _ != ""] - pattern_except = [_.lstrip(" .,,").rstrip(" ,,") for __ in pattern_except for _ in __.split(",") if _ != ""] - pattern_except += ['zip', 'rar', '7z', 'tar', 'gz'] # 避免解析上传的压缩文件 - history = [] # 清空历史,以免输入溢出 - import glob, os + txt_pattern = plugin_kwargs.get("txt_pattern") + txt_pattern = txt_pattern.replace(",", ",") + # 将要匹配的模式(例如: *.c, *.cpp, *.py, config.toml) + pattern_include = [_.lstrip(" ,").rstrip(" ,") for _ in txt_pattern.split(",") if _ != "" and not _.strip().startswith("^")] + if not pattern_include: pattern_include = ["*"] # 不输入即全部匹配 + # 将要忽略匹配的文件后缀(例如: ^*.c, ^*.cpp, ^*.py) + pattern_except_suffix = [_.lstrip(" ^*.,").rstrip(" ,") for _ in txt_pattern.split(" ") if _ != "" and _.strip().startswith("^*.")] + pattern_except_suffix += ['zip', 'rar', '7z', 'tar', 'gz'] # 避免解析压缩文件 + # 将要忽略匹配的文件名(例如: ^README.md) + pattern_except_name = [_.lstrip(" ^*,").rstrip(" ,").replace(".", "\.") for _ in txt_pattern.split(" ") if _ != "" and _.strip().startswith("^") and not _.strip().startswith("^*.")] + # 生成正则表达式 + pattern_except = '/[^/]+\.(' + "|".join(pattern_except_suffix) + ')$' + pattern_except += '|/(' + "|".join(pattern_except_name) + ')$' if pattern_except_name != [] else '' + + history.clear() + import glob, os, re if os.path.exists(txt): project_folder = txt else: @@ -288,8 +291,13 @@ def 解析任意code项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, sys report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到本地项目或无权访问: {txt}") yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 return - file_manifest = [f for f in glob.glob(f'{project_folder}/**/*.*', recursive=True) if os.path.isfile(f) and \ - ([] == pattern_include or f.split(".")[-1] in pattern_include) and f.split(".")[-1] not in pattern_except] + # 若上传压缩文件, 先寻找到解压的文件夹路径, 从而避免解析压缩文件 + maybe_dir = [f for f in glob.glob(f'{project_folder}/**') if os.path.isdir(f)] + extract_folder_path = maybe_dir[0].replace('\\', '/') if len(maybe_dir) != 0 else "" + # 按输入的匹配模式寻找上传的非压缩文件和已解压的文件 + file_manifest = [f for f in glob.glob(f'{project_folder}/**') if os.path.isfile(f) and not re.search(pattern_except, f)] + \ + [f for _ in pattern_include for f in glob.glob(f'{extract_folder_path}/**/{_}', recursive=True) if \ + "" != extract_folder_path and os.path.isfile(f) and not re.search(pattern_except, f)] if len(file_manifest) == 0: report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到任何文件: {txt}") yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 From 4cfbacdb26bd495e60d7efadc054e0aef89c3769 Mon Sep 17 00:00:00 2001 From: yuxiaoyuan0406 <973971990@qq.com> Date: Thu, 20 Apr 2023 17:21:47 +0800 Subject: [PATCH 06/52] fix sub-path deploy --- main.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index 2e4e275d..06719abe 100644 --- a/main.py +++ b/main.py @@ -171,4 +171,21 @@ def auto_opentab_delay(): threading.Thread(target=auto_update, name="self-upgrade", daemon=True).start() auto_opentab_delay() -demo.queue(concurrency_count=CONCURRENT_COUNT).launch(server_name="0.0.0.0", server_port=PORT, auth=AUTHENTICATION) +# demo.queue(concurrency_count=CONCURRENT_COUNT).launch(server_name="0.0.0.0", server_port=PORT, auth=AUTHENTICATION) +demo.queue(concurrency_count=CONCURRENT_COUNT) + +CUSTOM_PATH = '/chatgpt' + +import uvicorn +from fastapi import FastAPI + +app = FastAPI() + +@app.get("/") +def read_main(): + return {"message": "NULL"} + +app = gr.mount_gradio_app(app, demo, path=CUSTOM_PATH) + +if __name__ == '__main__': + uvicorn.run(app, host="0.0.0.0", port=PORT) From 7dd73e1330d610c16f5c6ebb113e35c3176682d8 Mon Sep 17 00:00:00 2001 From: yuxiaoyuan0406 <973971990@qq.com> Date: Thu, 20 Apr 2023 18:20:25 +0800 Subject: [PATCH 07/52] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E6=A3=80=E6=9F=A5path=E7=9A=84=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- toolbox.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/toolbox.py b/toolbox.py index 5bbe954e..4921e6ef 100644 --- a/toolbox.py +++ b/toolbox.py @@ -527,3 +527,22 @@ class DummyWith(): def __exit__(self, exc_type, exc_value, traceback): return + +def custom_path_check(path: str)->bool: + ''' + check path for sub url + + path: path to check + + return value: do sub url wrap + ''' + if len(path) == 0: + print("ilegal custom path: {}\npath must not be empty\ndeploy on root url".format(path)) + return False + if path[0] == '/': + if path[1] != '/': + print("deploy on sub-path {}".format(path)) + return True + return False + print("ilegal custom path: {}\npath should begin with \'/\'\ndeploy on root url".format(path)) + return False From f0ff1f2c64378e3266a8e1a7c348c5fcb3d57cac Mon Sep 17 00:00:00 2001 From: yuxiaoyuan0406 <973971990@qq.com> Date: Thu, 20 Apr 2023 18:22:58 +0800 Subject: [PATCH 08/52] =?UTF-8?q?=E6=B7=BB=E5=8A=A0CUSTOM=5FPATH=E6=9D=A5?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E5=88=B0=E5=AD=90=E7=BA=A7=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.py | 2 ++ main.py | 29 +++++++++++++++-------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/config.py b/config.py index 658de99e..ce65e067 100644 --- a/config.py +++ b/config.py @@ -56,3 +56,5 @@ CONCURRENT_COUNT = 100 # 设置用户名和密码(相关功能不稳定,与gradio版本和网络都相关,如果本地使用不建议加这个) # [("username", "password"), ("username2", "password2"), ...] AUTHENTICATION = [] + +CUSTOM_PATH = "/" diff --git a/main.py b/main.py index 06719abe..09e67ccb 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,11 @@ import os; os.environ['no_proxy'] = '*' # 避免代理网络产生意外污染 import gradio as gr from request_llm.bridge_chatgpt import predict -from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf, ArgsGeneralWrapper, DummyWith +from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf, ArgsGeneralWrapper, custom_path_check, DummyWith # 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到 -proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, API_KEY = \ - get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'API_KEY') +proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, API_KEY, CUSTOM_PATH = \ + get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'API_KEY', 'CUSTOM_PATH') # 如果WEB_PORT是-1, 则随机选取WEB端口 PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT @@ -171,21 +171,22 @@ def auto_opentab_delay(): threading.Thread(target=auto_update, name="self-upgrade", daemon=True).start() auto_opentab_delay() -# demo.queue(concurrency_count=CONCURRENT_COUNT).launch(server_name="0.0.0.0", server_port=PORT, auth=AUTHENTICATION) demo.queue(concurrency_count=CONCURRENT_COUNT) -CUSTOM_PATH = '/chatgpt' +if custom_path_check(CUSTOM_PATH): + import uvicorn + from fastapi import FastAPI -import uvicorn -from fastapi import FastAPI + app = FastAPI() -app = FastAPI() + @app.get("/") + def read_main(): + return {"message": "NULL"} -@app.get("/") -def read_main(): - return {"message": "NULL"} + app = gr.mount_gradio_app(app, demo, path=CUSTOM_PATH) -app = gr.mount_gradio_app(app, demo, path=CUSTOM_PATH) - -if __name__ == '__main__': uvicorn.run(app, host="0.0.0.0", port=PORT) +else: + demo.launch(server_name="0.0.0.0", server_port=PORT, auth=AUTHENTICATION) + + From 9945d5048a60b1d48d9829999a98dd80d3d8a7ac Mon Sep 17 00:00:00 2001 From: yuxiaoyuan0406 <973971990@qq.com> Date: Thu, 20 Apr 2023 18:31:26 +0800 Subject: [PATCH 09/52] =?UTF-8?q?=E6=9B=B4=E5=A5=BD=E7=9A=84=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=E5=AD=90=E8=B7=AF=E5=BE=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- toolbox.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/toolbox.py b/toolbox.py index 4921e6ef..b5212687 100644 --- a/toolbox.py +++ b/toolbox.py @@ -540,6 +540,9 @@ def custom_path_check(path: str)->bool: print("ilegal custom path: {}\npath must not be empty\ndeploy on root url".format(path)) return False if path[0] == '/': + if len(path) == 1: + print("deploy on root url") + return False if path[1] != '/': print("deploy on sub-path {}".format(path)) return True From 0ff838443ea5d5c3fbab70261c042c9fb0c2d9af Mon Sep 17 00:00:00 2001 From: mrhblfx Date: Thu, 20 Apr 2023 21:44:35 +0800 Subject: [PATCH 10/52] fix a bug --- crazy_functions/解析项目源代码.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crazy_functions/解析项目源代码.py b/crazy_functions/解析项目源代码.py index 9218fa50..64af5ec8 100644 --- a/crazy_functions/解析项目源代码.py +++ b/crazy_functions/解析项目源代码.py @@ -296,8 +296,9 @@ def 解析任意code项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, sys extract_folder_path = maybe_dir[0].replace('\\', '/') if len(maybe_dir) != 0 else "" # 按输入的匹配模式寻找上传的非压缩文件和已解压的文件 file_manifest = [f for f in glob.glob(f'{project_folder}/**') if os.path.isfile(f) and not re.search(pattern_except, f)] + \ - [f for _ in pattern_include for f in glob.glob(f'{extract_folder_path}/**/{_}', recursive=True) if \ - "" != extract_folder_path and os.path.isfile(f) and not re.search(pattern_except, f)] + [f for _ in pattern_include for f in glob.glob(f'{extract_folder_path}/**/{_}', recursive=True) if "" != extract_folder_path and \ + os.path.isfile(f) and (not re.search(pattern_except, f) or _.endswith('.' + re.search(pattern_except, f).group().split('.')[-1]))] + if len(file_manifest) == 0: report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到任何文件: {txt}") yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 From de0ed4a6f535bf4f6d7b0b251d902f46ede03550 Mon Sep 17 00:00:00 2001 From: mrhblfx Date: Thu, 20 Apr 2023 22:01:27 +0800 Subject: [PATCH 11/52] =?UTF-8?q?style:accordion=20of=20=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E4=BB=BB=E6=84=8Fcode=E9=A1=B9=E7=9B=AE=20is=20closed=20by=20d?= =?UTF-8?q?efault?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index 44fe06af..a0b0b040 100644 --- a/main.py +++ b/main.py @@ -86,7 +86,7 @@ def main(): crazy_fns[k]["Button"] = gr.Button(k, variant=variant) crazy_fns[k]["Button"].style(size="sm") with gr.Row(): - with gr.Accordion("解析任意code项目", open=True): + with gr.Accordion("解析任意code项目", open=False): gr.Markdown("输入时用逗号隔开, `*`代表通配符, 加了`^`代表不匹配
例如: `*.c, ^*.cpp, config.toml, ^README.md`") with gr.Row(): txt_pattern = gr.Textbox(show_label=False, placeholder="输入框为空则代表匹配所有文件").style(container=False) From e889590a91884071514fca2d8125fa3b5976f2e8 Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Fri, 21 Apr 2023 18:49:24 +0800 Subject: [PATCH 12/52] Update README.md --- request_llm/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/request_llm/README.md b/request_llm/README.md index 973adea1..4a912d10 100644 --- a/request_llm/README.md +++ b/request_llm/README.md @@ -1,4 +1,4 @@ -# 如何使用其他大语言模型(v3.0分支测试中) +# 如何使用其他大语言模型 ## ChatGLM @@ -15,7 +15,7 @@ LLM_MODEL = "chatglm" --- -## Text-Generation-UI (TGUI) +## Text-Generation-UI (TGUI,调试中,暂不可用) ### 1. 部署TGUI ``` sh From a9a489231ae0e30e13ffda298c192cfd9dbc6bf1 Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Fri, 21 Apr 2023 18:56:56 +0800 Subject: [PATCH 13/52] Update bridge_all.py --- request_llm/bridge_all.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/request_llm/bridge_all.py b/request_llm/bridge_all.py index d1bc5189..fee2db20 100644 --- a/request_llm/bridge_all.py +++ b/request_llm/bridge_all.py @@ -1,12 +1,12 @@ """ - 该文件中主要包含2个函数 + 该文件中主要包含2个函数,是所有LLM的通用接口,它们会继续向下调用更底层的LLM模型,处理多模型并行等细节 - 不具备多线程能力的函数: - 1. predict: 正常对话时使用,具备完备的交互功能,不可多线程 + 不具备多线程能力的函数:正常对话时使用,具备完备的交互功能,不可多线程 + 1. predict(...) - 具备多线程调用能力的函数 - 2. predict_no_ui_long_connection:在实验过程中发现调用predict_no_ui处理长文档时,和openai的连接容易断掉,这个函数用stream的方式解决这个问题,同样支持多线程 + 具备多线程调用能力的函数:在函数插件中被调用,灵活而简洁 + 2. predict_no_ui_long_connection(...) """ import tiktoken from functools import lru_cache From ce1fc3a99909a503880c800857f4f3dd6c9cf59b Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 21 Apr 2023 19:28:32 +0800 Subject: [PATCH 14/52] =?UTF-8?q?=E4=BF=AE=E6=94=B9chatglm=E4=B8=8D?= =?UTF-8?q?=E8=AE=B0=E5=BF=86=E4=B8=8A=E4=B8=8B=E6=96=87=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- request_llm/bridge_chatglm.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/request_llm/bridge_chatglm.py b/request_llm/bridge_chatglm.py index 7af28356..8eef3228 100644 --- a/request_llm/bridge_chatglm.py +++ b/request_llm/bridge_chatglm.py @@ -92,8 +92,8 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history=[], sys_prompt="", # chatglm 没有 sys_prompt 接口,因此把prompt加入 history history_feedin = [] + history_feedin.append(["What can I do?", sys_prompt]) for i in range(len(history)//2): - history_feedin.append(["What can I do?", sys_prompt] ) history_feedin.append([history[2*i], history[2*i+1]] ) watch_dog_patience = 5 # 看门狗 (watchdog) 的耐心, 设置5秒即可 @@ -131,10 +131,13 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] history_feedin = [] + history_feedin.append(["What can I do?", system_prompt] ) for i in range(len(history)//2): - history_feedin.append(["What can I do?", system_prompt] ) history_feedin.append([history[2*i], history[2*i+1]] ) for response in glm_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']): chatbot[-1] = (inputs, response) - yield from update_ui(chatbot=chatbot, history=history) \ No newline at end of file + yield from update_ui(chatbot=chatbot, history=history) + + history.extend([inputs, response]) + yield from update_ui(chatbot=chatbot, history=history) \ No newline at end of file From 5353eba376e9f84ccc221be1fce212bbd1b564b3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 21 Apr 2023 20:03:38 +0800 Subject: [PATCH 15/52] =?UTF-8?q?version=203.15=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=81=94=E7=BD=91=E5=9B=9E=E7=AD=94=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- request_llm/bridge_all.py | 2 +- version | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/request_llm/bridge_all.py b/request_llm/bridge_all.py index fee2db20..311dc6f4 100644 --- a/request_llm/bridge_all.py +++ b/request_llm/bridge_all.py @@ -210,7 +210,7 @@ def predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, obser return_string_collect.append( f"【{str(models[i])} 说】: {future.result()} " ) window_mutex[-1] = False # stop mutex thread - res = '
\n\n---\n\n'.join(return_string_collect) + res = '

\n\n---\n\n'.join(return_string_collect) return res diff --git a/version b/version index bb462e21..b6458253 100644 --- a/version +++ b/version @@ -1,5 +1,5 @@ { - "version": 3.1, + "version": 3.15, "show_feature": true, - "new_feature": "添加支持清华ChatGLM和GPT-4 <-> 改进架构,支持与多个LLM模型同时对话 <-> 添加支持API2D(国内,可支持gpt4)<-> 支持多API-KEY负载均衡(并列填写,逗号分割) <-> 添加输入区文本清除按键" + "new_feature": "添加联网(Google)回答问题插件 <-> 修复ChatGLM上下文BUG <-> 添加支持清华ChatGLM和GPT-4 <-> 改进架构,支持与多个LLM模型同时对话 <-> 添加支持API2D(国内,可支持gpt4)" } From e20070939c6c7eeca33a8438041c9e038836957b Mon Sep 17 00:00:00 2001 From: saltfish Date: Sat, 22 Apr 2023 00:36:28 +0800 Subject: [PATCH 16/52] Parse and generate ipynb (Issue #501) Implemented code to parse and generate the ipynb files. The solution addresses Issue #501. --- crazy_functional.py | 6 ++ crazy_functions/解析JupyterNotebook.py | 135 +++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 crazy_functions/解析JupyterNotebook.py diff --git a/crazy_functional.py b/crazy_functional.py index 8e3ab6a8..8f3b6821 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -19,12 +19,18 @@ def get_crazy_functions(): from crazy_functions.解析项目源代码 import 解析一个Lua项目 from crazy_functions.解析项目源代码 import 解析一个CSharp项目 from crazy_functions.总结word文档 import 总结word文档 + from crazy_functions.解析JupyterNotebook import 解析ipynb文件 function_plugins = { "解析整个Python项目": { "Color": "stop", # 按钮颜色 "Function": HotReload(解析一个Python项目) }, + "解析Jupyter Notebook文件": { + "Color": "stop", + "AsButton":False, + "Function": HotReload(解析ipynb文件), + }, "批量总结Word文档": { "Color": "stop", "Function": HotReload(总结word文档) diff --git a/crazy_functions/解析JupyterNotebook.py b/crazy_functions/解析JupyterNotebook.py new file mode 100644 index 00000000..86f246c9 --- /dev/null +++ b/crazy_functions/解析JupyterNotebook.py @@ -0,0 +1,135 @@ +from toolbox import update_ui +from toolbox import CatchException, report_execption +fast_debug = True + + +class PaperFileGroup(): + def __init__(self): + self.file_paths = [] + self.file_contents = [] + self.sp_file_contents = [] + self.sp_file_index = [] + self.sp_file_tag = [] + + # count_token + from request_llm.bridge_all import model_info + enc = model_info["gpt-3.5-turbo"]['tokenizer'] + def get_token_num(txt): return len( + enc.encode(txt, disallowed_special=())) + self.get_token_num = get_token_num + + def run_file_split(self, max_token_limit=1900): + """ + 将长文本分离开来 + """ + for index, file_content in enumerate(self.file_contents): + if self.get_token_num(file_content) < max_token_limit: + self.sp_file_contents.append(file_content) + self.sp_file_index.append(index) + self.sp_file_tag.append(self.file_paths[index]) + else: + from .crazy_utils import breakdown_txt_to_satisfy_token_limit_for_pdf + segments = breakdown_txt_to_satisfy_token_limit_for_pdf( + file_content, self.get_token_num, max_token_limit) + for j, segment in enumerate(segments): + self.sp_file_contents.append(segment) + self.sp_file_index.append(index) + self.sp_file_tag.append( + self.file_paths[index] + f".part-{j}.txt") + + + +def parseNotebook(filename, enable_markdown=1): + import json + + CodeBlocks = [] + with open(filename, 'r', encoding='utf-8', errors='replace') as f: + notebook = json.load(f) + for cell in notebook['cells']: + if cell['cell_type'] == 'code' and cell['source']: + # remove blank lines + cell['source'] = [line for line in cell['source'] if line.strip() + != ''] + CodeBlocks.append("".join(cell['source'])) + elif enable_markdown and cell['cell_type'] == 'markdown' and cell['source']: + cell['source'] = [line for line in cell['source'] if line.strip() + != ''] + CodeBlocks.append("Markdown:"+"".join(cell['source'])) + + Code = "" + for idx, code in enumerate(CodeBlocks): + Code += f"This is {idx+1}th code block: \n" + Code += code+"\n" + + return Code + + +def ipynb解释(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt): + from .crazy_utils import request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency + + pfg = PaperFileGroup() + + print(file_manifest) + for fp in file_manifest: + file_content = parseNotebook(fp, enable_markdown=1) + pfg.file_paths.append(fp) + pfg.file_contents.append(file_content) + + # <-------- 拆分过长的IPynb文件 ----------> + pfg.run_file_split(max_token_limit=1024) + n_split = len(pfg.sp_file_contents) + + inputs_array = [f"This is a Jupyter Notebook file, tell me about Each Block in Chinese. Focus Just On Code." + + f"If a block starts with `Markdown` which means it's a markdown block in ipynbipynb. " + + f"Start a new line for a block and block num use Chinese." + + f"\n\n{frag}" for frag in pfg.sp_file_contents] + inputs_show_user_array = [f"{f}的分析如下" for f in pfg.sp_file_tag] + sys_prompt_array = ["You are a professional programmer."] * n_split + + gpt_response_collection = yield from request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency( + inputs_array=inputs_array, + inputs_show_user_array=inputs_show_user_array, + llm_kwargs=llm_kwargs, + chatbot=chatbot, + history_array=[[""] for _ in range(n_split)], + sys_prompt_array=sys_prompt_array, + # max_workers=5, # OpenAI所允许的最大并行过载 + scroller_max_len=80 + ) + + # <-------- 整理结果,退出 ----------> + block_result = " \n".join(gpt_response_collection) + chatbot.append(("解析的结果如下", block_result)) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + + +@CatchException +def 解析ipynb文件(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + chatbot.append([ + "函数插件功能?", + "对IPynb文件进行解析"]) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + + history = [] # 清空历史 + import glob + import os + if os.path.exists(txt): + project_folder = txt + else: + if txt == "": + txt = '空空如也的输入栏' + report_execption(chatbot, history, + a=f"解析项目: {txt}", b=f"找不到本地项目或无权访问: {txt}") + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + return + if txt.endswith('.ipynb'): + file_manifest = [txt] + else: + file_manifest = [f for f in glob.glob( + f'{project_folder}/**/*.ipynb', recursive=True)] + if len(file_manifest) == 0: + report_execption(chatbot, history, + a=f"解析项目: {txt}", b=f"找不到任何.ipynb文件: {txt}") + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + return + yield from ipynb解释(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, ) From 1139d395f27167a6785c4b42e69d75bb894573c8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 22 Apr 2023 15:06:54 +0800 Subject: [PATCH 17/52] =?UTF-8?q?=E5=B0=86=E9=AB=98=E7=BA=A7=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E8=BE=93=E5=85=A5=E9=80=9A=E7=94=A8=E5=8C=96=EF=BC=88?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=9A=90=E8=97=8F=EF=BC=89=EF=BC=8C=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E5=88=B0=E6=89=80=E6=9C=89=E7=9A=84=E4=B8=8B=E6=8B=89?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E5=87=BD=E6=95=B0=E6=8F=92=E4=BB=B6=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functional.py | 2 ++ crazy_functions/解析项目源代码.py | 2 +- main.py | 36 ++++++++++++++----------------- toolbox.py | 9 ++++---- 4 files changed, 23 insertions(+), 26 deletions(-) diff --git a/crazy_functional.py b/crazy_functional.py index ccaed45c..6453af86 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -196,6 +196,8 @@ def get_crazy_functions(): "解析任意code项目": { "Color": "stop", "AsButton": False, + "AdvancedArgs": True, # 调用时,唤起高级参数输入区(默认False) + "ArgsReminder": "输入时用逗号隔开, `*`代表通配符, 加了`^`代表不匹配
例如: `*.c, ^*.cpp, config.toml, ^README.md`", # 高级参数输入区的显示提示 "Function": HotReload(解析任意code项目) }, }) diff --git a/crazy_functions/解析项目源代码.py b/crazy_functions/解析项目源代码.py index 64af5ec8..60de1cbc 100644 --- a/crazy_functions/解析项目源代码.py +++ b/crazy_functions/解析项目源代码.py @@ -268,7 +268,7 @@ def 解析一个CSharp项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, s @CatchException def 解析任意code项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): - txt_pattern = plugin_kwargs.get("txt_pattern") + txt_pattern = plugin_kwargs.get("advanced_arg") txt_pattern = txt_pattern.replace(",", ",") # 将要匹配的模式(例如: *.c, *.cpp, *.py, config.toml) pattern_include = [_.lstrip(" ,").rstrip(" ,") for _ in txt_pattern.split(",") if _ != "" and not _.strip().startswith("^")] diff --git a/main.py b/main.py index a0b0b040..9d16b856 100644 --- a/main.py +++ b/main.py @@ -85,21 +85,15 @@ def main(): variant = crazy_fns[k]["Color"] if "Color" in crazy_fns[k] else "secondary" crazy_fns[k]["Button"] = gr.Button(k, variant=variant) crazy_fns[k]["Button"].style(size="sm") - with gr.Row(): - with gr.Accordion("解析任意code项目", open=False): - gr.Markdown("输入时用逗号隔开, `*`代表通配符, 加了`^`代表不匹配
例如: `*.c, ^*.cpp, config.toml, ^README.md`") - with gr.Row(): - txt_pattern = gr.Textbox(show_label=False, placeholder="输入框为空则代表匹配所有文件").style(container=False) - code_plugin_name = "解析任意code项目" - variant = crazy_fns[code_plugin_name]["Color"] if "Color" in crazy_fns[code_plugin_name] else "secondary" - crazy_fns[code_plugin_name]["Button"] = gr.Button(code_plugin_name, variant=variant) - crazy_fns[code_plugin_name]["Button"].style(size="sm") with gr.Row(): with gr.Accordion("更多函数插件", open=True): dropdown_fn_list = [k for k in crazy_fns.keys() if not crazy_fns[k].get("AsButton", True)] - with gr.Column(scale=1): + with gr.Row(): dropdown = gr.Dropdown(dropdown_fn_list, value=r"打开插件列表", label="").style(container=False) - with gr.Column(scale=1): + with gr.Row(): + with gr.Accordion("高级函数插件参数区:", open=True, visible=False) as area_fn_kwargs: + plugin_advanced_arg = gr.Textbox(show_label=False, placeholder="输入框为空则代表匹配所有文件").style(container=False) + with gr.Row(): switchy_bt = gr.Button(r"请先从插件列表中选择", variant="secondary") with gr.Row(): with gr.Accordion("点击展开“文件上传区”。上传本地文件可供红色函数插件调用。", open=False) as area_file_up: @@ -109,7 +103,7 @@ def main(): top_p = gr.Slider(minimum=-0, maximum=1.0, value=1.0, step=0.01,interactive=True, label="Top-p (nucleus sampling)",) temperature = gr.Slider(minimum=-0, maximum=2.0, value=1.0, step=0.01, interactive=True, label="Temperature",) max_length_sl = gr.Slider(minimum=256, maximum=4096, value=512, step=1, interactive=True, label="Local LLM MaxLength",) - checkboxes = gr.CheckboxGroup(["基础功能区", "函数插件区", "底部输入区", "输入清除键"], value=["基础功能区", "函数插件区"], label="显示/隐藏功能区") + checkboxes = gr.CheckboxGroup(["基础功能区", "函数插件区", "底部输入区", "输入清除键", "插件参数区"], value=["基础功能区", "函数插件区"], label="显示/隐藏功能区") md_dropdown = gr.Dropdown(AVAIL_LLM_MODELS, value=LLM_MODEL, label="更换LLM模型/请求源").style(container=False) gr.Markdown(description) @@ -131,11 +125,12 @@ def main(): ret.update({area_input_secondary: gr.update(visible=("底部输入区" in a))}) ret.update({clearBtn: gr.update(visible=("输入清除键" in a))}) ret.update({clearBtn2: gr.update(visible=("输入清除键" in a))}) + ret.update({area_fn_kwargs: gr.update(visible=("插件参数区" in a))}) if "底部输入区" in a: ret.update({txt: gr.update(value="")}) return ret - checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn, area_input_primary, area_input_secondary, txt, txt2, clearBtn, clearBtn2] ) + checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn, area_input_primary, area_input_secondary, txt, txt2, clearBtn, clearBtn2, area_fn_kwargs] ) # 整理反复出现的控件句柄组合 - input_combo = [cookies, max_length_sl, md_dropdown, txt, txt2, top_p, temperature, chatbot, history, system_prompt, txt_pattern] + input_combo = [cookies, max_length_sl, md_dropdown, txt, txt2, top_p, temperature, chatbot, history, system_prompt, plugin_advanced_arg] output_combo = [cookies, chatbot, history, status] predict_args = dict(fn=ArgsGeneralWrapper(predict), inputs=input_combo, outputs=output_combo) # 提交按钮、重置按钮 @@ -159,15 +154,16 @@ def main(): click_handle = crazy_fns[k]["Button"].click(ArgsGeneralWrapper(crazy_fns[k]["Function"]), [*input_combo, gr.State(PORT)], output_combo) click_handle.then(on_report_generated, [file_upload, chatbot], [file_upload, chatbot]) cancel_handles.append(click_handle) - # 函数插件-解析任意code项目 - click_handle = crazy_fns[code_plugin_name]["Button"].click(ArgsGeneralWrapper(crazy_fns[code_plugin_name]["Function"]), [*input_combo, gr.State(PORT)], output_combo) - click_handle.then(on_report_generated, [file_upload, chatbot], [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" - return {switchy_bt: gr.update(value=k, variant=variant)} - dropdown.select(on_dropdown_changed, [dropdown], [switchy_bt] ) + ret = {switchy_bt: gr.update(value=k, variant=variant)} + if crazy_fns[k].get("AdvancedArgs", False): # 是否唤起高级插件参数区 + ret.update({area_fn_kwargs: gr.update(visible=True, label=f"插件{k}的高级参数说明:" + crazy_fns[k].get("ArgsReminder", [f"没有提供高级参数功能说明"]))}) + else: + ret.update({area_fn_kwargs: gr.update(visible=False, label=f"插件{k}不需要高级参数。")}) + return ret + dropdown.select(on_dropdown_changed, [dropdown], [switchy_bt, area_fn_kwargs] ) def on_md_dropdown_changed(k): return {chatbot: gr.update(label="当前模型:"+k)} md_dropdown.select(on_md_dropdown_changed, [md_dropdown], [chatbot] ) diff --git a/toolbox.py b/toolbox.py index 2fd5da2d..53bb882c 100644 --- a/toolbox.py +++ b/toolbox.py @@ -24,7 +24,7 @@ def ArgsGeneralWrapper(f): """ 装饰器函数,用于重组输入参数,改变输入参数的顺序与结构。 """ - def decorated(cookies, max_length, llm_model, txt, txt2, top_p, temperature, chatbot, history, system_prompt, txt_pattern, *args): + def decorated(cookies, max_length, llm_model, txt, txt2, top_p, temperature, chatbot, history, system_prompt, plugin_advanced_arg, *args): txt_passon = txt if txt == "" and txt2 != "": txt_passon = txt2 # 引入一个有cookie的chatbot @@ -39,10 +39,9 @@ def ArgsGeneralWrapper(f): 'max_length': max_length, 'temperature':temperature, } - # plugin_kwargs = { - # # 目前还没有 - # } - plugin_kwargs = dict(txt_pattern = txt_pattern) + plugin_kwargs = { + "advanced_arg": plugin_advanced_arg, + } chatbot_with_cookie = ChatBotWithCookies(cookies) chatbot_with_cookie.write_list(chatbot) yield from f(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, *args) From 89a75e26c3872ecce59842a454fc23229e7c3f03 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 22 Apr 2023 15:36:49 +0800 Subject: [PATCH 18/52] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dextract=5Ffolder=5Fpath?= =?UTF-8?q?=E8=A2=AB=E5=AE=9A=E4=BD=8D=E5=88=B0=E6=A0=B9=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functions/解析项目源代码.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/crazy_functions/解析项目源代码.py b/crazy_functions/解析项目源代码.py index 60de1cbc..5563d3b7 100644 --- a/crazy_functions/解析项目源代码.py +++ b/crazy_functions/解析项目源代码.py @@ -292,13 +292,14 @@ def 解析任意code项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, sys yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 return # 若上传压缩文件, 先寻找到解压的文件夹路径, 从而避免解析压缩文件 - maybe_dir = [f for f in glob.glob(f'{project_folder}/**') if os.path.isdir(f)] - extract_folder_path = maybe_dir[0].replace('\\', '/') if len(maybe_dir) != 0 else "" + maybe_dir = [f for f in glob.glob(f'{project_folder}/*') if os.path.isdir(f)] + if maybe_dir[0].endswith('.extract'): + extract_folder_path = maybe_dir[0] + else: + extract_folder_path = project_folder # 按输入的匹配模式寻找上传的非压缩文件和已解压的文件 - file_manifest = [f for f in glob.glob(f'{project_folder}/**') if os.path.isfile(f) and not re.search(pattern_except, f)] + \ - [f for _ in pattern_include for f in glob.glob(f'{extract_folder_path}/**/{_}', recursive=True) if "" != extract_folder_path and \ - os.path.isfile(f) and (not re.search(pattern_except, f) or _.endswith('.' + re.search(pattern_except, f).group().split('.')[-1]))] - + file_manifest = [f for pattern in pattern_include for f in glob.glob(f'{extract_folder_path}/**/{pattern}', recursive=True) if "" != extract_folder_path and \ + os.path.isfile(f) and (not re.search(pattern_except, f) or pattern.endswith('.' + re.search(pattern_except, f).group().split('.')[-1]))] if len(file_manifest) == 0: report_execption(chatbot, history, a = f"解析项目: {txt}", b = f"找不到任何文件: {txt}") yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 From e9a6efef7fb5b53e4616bd8e3d346348aaad640c Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 22 Apr 2023 15:39:51 +0800 Subject: [PATCH 19/52] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=9D=9E=E5=8E=8B?= =?UTF-8?q?=E7=BC=A9=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E7=9A=84=E8=AF=BB?= =?UTF-8?q?=E5=8F=96=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functions/解析项目源代码.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crazy_functions/解析项目源代码.py b/crazy_functions/解析项目源代码.py index 5563d3b7..bfa473ae 100644 --- a/crazy_functions/解析项目源代码.py +++ b/crazy_functions/解析项目源代码.py @@ -293,7 +293,7 @@ def 解析任意code项目(txt, llm_kwargs, plugin_kwargs, chatbot, history, sys return # 若上传压缩文件, 先寻找到解压的文件夹路径, 从而避免解析压缩文件 maybe_dir = [f for f in glob.glob(f'{project_folder}/*') if os.path.isdir(f)] - if maybe_dir[0].endswith('.extract'): + if len(maybe_dir)>0 and maybe_dir[0].endswith('.extract'): extract_folder_path = maybe_dir[0] else: extract_folder_path = project_folder From c3cafd8d6f807031ebc7521f73a309703041f930 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 22 Apr 2023 15:52:21 +0800 Subject: [PATCH 20/52] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functional.py | 4 ++-- main.py | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crazy_functional.py b/crazy_functional.py index 6453af86..19041405 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -193,11 +193,11 @@ def get_crazy_functions(): from crazy_functions.解析项目源代码 import 解析任意code项目 function_plugins.update({ - "解析任意code项目": { + "解析项目源代码(手动指定和筛选源代码文件类型)": { "Color": "stop", "AsButton": False, "AdvancedArgs": True, # 调用时,唤起高级参数输入区(默认False) - "ArgsReminder": "输入时用逗号隔开, `*`代表通配符, 加了`^`代表不匹配
例如: `*.c, ^*.cpp, config.toml, ^README.md`", # 高级参数输入区的显示提示 + "ArgsReminder": "输入时用逗号隔开, *代表通配符, 加了^代表不匹配。例如: \"*.c, ^*.cpp, config.toml, ^README.md\"", # 高级参数输入区的显示提示 "Function": HotReload(解析任意code项目) }, }) diff --git a/main.py b/main.py index 9d16b856..d3efcad2 100644 --- a/main.py +++ b/main.py @@ -91,8 +91,8 @@ def main(): with gr.Row(): dropdown = gr.Dropdown(dropdown_fn_list, value=r"打开插件列表", label="").style(container=False) with gr.Row(): - with gr.Accordion("高级函数插件参数区:", open=True, visible=False) as area_fn_kwargs: - plugin_advanced_arg = gr.Textbox(show_label=False, placeholder="输入框为空则代表匹配所有文件").style(container=False) + plugin_advanced_arg = gr.Textbox(show_label=True, label="高级参数输入区", visible=False, + placeholder="这里是特殊函数插件的高级参数输入区").style(container=False) with gr.Row(): switchy_bt = gr.Button(r"请先从插件列表中选择", variant="secondary") with gr.Row(): @@ -125,10 +125,10 @@ def main(): ret.update({area_input_secondary: gr.update(visible=("底部输入区" in a))}) ret.update({clearBtn: gr.update(visible=("输入清除键" in a))}) ret.update({clearBtn2: gr.update(visible=("输入清除键" in a))}) - ret.update({area_fn_kwargs: gr.update(visible=("插件参数区" in a))}) + ret.update({plugin_advanced_arg: gr.update(visible=("插件参数区" in a))}) if "底部输入区" in a: ret.update({txt: gr.update(value="")}) return ret - checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn, area_input_primary, area_input_secondary, txt, txt2, clearBtn, clearBtn2, area_fn_kwargs] ) + checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn, area_input_primary, area_input_secondary, txt, txt2, clearBtn, clearBtn2, plugin_advanced_arg] ) # 整理反复出现的控件句柄组合 input_combo = [cookies, max_length_sl, md_dropdown, txt, txt2, top_p, temperature, chatbot, history, system_prompt, plugin_advanced_arg] output_combo = [cookies, chatbot, history, status] @@ -159,11 +159,11 @@ def main(): variant = crazy_fns[k]["Color"] if "Color" in crazy_fns[k] else "secondary" ret = {switchy_bt: gr.update(value=k, variant=variant)} if crazy_fns[k].get("AdvancedArgs", False): # 是否唤起高级插件参数区 - ret.update({area_fn_kwargs: gr.update(visible=True, label=f"插件{k}的高级参数说明:" + crazy_fns[k].get("ArgsReminder", [f"没有提供高级参数功能说明"]))}) + ret.update({plugin_advanced_arg: gr.update(visible=True, label=f"插件[{k}]的高级参数说明:" + crazy_fns[k].get("ArgsReminder", [f"没有提供高级参数功能说明"]))}) else: - ret.update({area_fn_kwargs: gr.update(visible=False, label=f"插件{k}不需要高级参数。")}) + ret.update({plugin_advanced_arg: gr.update(visible=False, label=f"插件[{k}]不需要高级参数。")}) return ret - dropdown.select(on_dropdown_changed, [dropdown], [switchy_bt, area_fn_kwargs] ) + dropdown.select(on_dropdown_changed, [dropdown], [switchy_bt, plugin_advanced_arg] ) def on_md_dropdown_changed(k): return {chatbot: gr.update(label="当前模型:"+k)} md_dropdown.select(on_md_dropdown_changed, [md_dropdown], [chatbot] ) From 64548d33a95df51dbd0efce7460e19d2a2dc4b08 Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Sat, 22 Apr 2023 15:58:43 +0800 Subject: [PATCH 21/52] Update crazy_functional.py --- crazy_functional.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crazy_functional.py b/crazy_functional.py index 8f3b6821..cdc47cf6 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -26,7 +26,7 @@ def get_crazy_functions(): "Color": "stop", # 按钮颜色 "Function": HotReload(解析一个Python项目) }, - "解析Jupyter Notebook文件": { + "[测试功能] 解析Jupyter Notebook文件": { "Color": "stop", "AsButton":False, "Function": HotReload(解析ipynb文件), From 9d9df8aa573a9fb509e6836425d3e19cd336f78e Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Sat, 22 Apr 2023 16:01:32 +0800 Subject: [PATCH 22/52] =?UTF-8?q?Update=20=E8=A7=A3=E6=9E=90JupyterNoteboo?= =?UTF-8?q?k.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functions/解析JupyterNotebook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crazy_functions/解析JupyterNotebook.py b/crazy_functions/解析JupyterNotebook.py index 86f246c9..1627f887 100644 --- a/crazy_functions/解析JupyterNotebook.py +++ b/crazy_functions/解析JupyterNotebook.py @@ -107,7 +107,7 @@ def ipynb解释(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbo def 解析ipynb文件(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): chatbot.append([ "函数插件功能?", - "对IPynb文件进行解析"]) + "对IPynb文件进行解析。Contributor: codycjy."]) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 history = [] # 清空历史 From 880be21bf713bfff940e81f0afebdc8fff98c88e Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 22 Apr 2023 16:19:36 +0800 Subject: [PATCH 23/52] Add test for juptyer notebook plugin --- .gitignore | 1 + crazy_functions/crazy_functions_test.py | 12 +++++++++--- crazy_functions/解析JupyterNotebook.py | 13 +++++++++---- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 987f0547..7a9c92b8 100644 --- a/.gitignore +++ b/.gitignore @@ -145,3 +145,4 @@ cradle* debug* private* crazy_functions/test_project/pdf_and_word +crazy_functions/test_samples diff --git a/crazy_functions/crazy_functions_test.py b/crazy_functions/crazy_functions_test.py index 7b0f0725..6020fa2f 100644 --- a/crazy_functions/crazy_functions_test.py +++ b/crazy_functions/crazy_functions_test.py @@ -108,6 +108,13 @@ def test_联网回答问题(): print("当前问答:", cb[-1][-1].replace("\n"," ")) for i, it in enumerate(cb): print亮蓝(it[0]); print亮黄(it[1]) +def test_解析ipynb文件(): + from crazy_functions.解析JupyterNotebook import 解析ipynb文件 + txt = "crazy_functions/test_samples" + for cookies, cb, hist, msg in 解析ipynb文件(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + print(cb) + + # test_解析一个Python项目() # test_Latex英文润色() # test_Markdown中译英() @@ -116,9 +123,8 @@ def test_联网回答问题(): # test_总结word文档() # test_下载arxiv论文并翻译摘要() # test_解析一个Cpp项目() - -test_联网回答问题() - +# test_联网回答问题() +test_解析ipynb文件() input("程序完成,回车退出。") print("退出。") \ No newline at end of file diff --git a/crazy_functions/解析JupyterNotebook.py b/crazy_functions/解析JupyterNotebook.py index 1627f887..3c9948b8 100644 --- a/crazy_functions/解析JupyterNotebook.py +++ b/crazy_functions/解析JupyterNotebook.py @@ -1,5 +1,5 @@ from toolbox import update_ui -from toolbox import CatchException, report_execption +from toolbox import CatchException, report_execption, write_results_to_file fast_debug = True @@ -79,9 +79,9 @@ def ipynb解释(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbo pfg.run_file_split(max_token_limit=1024) n_split = len(pfg.sp_file_contents) - inputs_array = [f"This is a Jupyter Notebook file, tell me about Each Block in Chinese. Focus Just On Code." + - f"If a block starts with `Markdown` which means it's a markdown block in ipynbipynb. " + - f"Start a new line for a block and block num use Chinese." + + inputs_array = [r"This is a Jupyter Notebook file, tell me about Each Block in Chinese. Focus Just On Code." + + r"If a block starts with `Markdown` which means it's a markdown block in ipynbipynb. " + + r"Start a new line for a block and block num use Chinese." + f"\n\n{frag}" for frag in pfg.sp_file_contents] inputs_show_user_array = [f"{f}的分析如下" for f in pfg.sp_file_tag] sys_prompt_array = ["You are a professional programmer."] * n_split @@ -100,8 +100,13 @@ def ipynb解释(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbo # <-------- 整理结果,退出 ----------> block_result = " \n".join(gpt_response_collection) chatbot.append(("解析的结果如下", block_result)) + history.extend(["解析的结果如下", block_result]) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + # <-------- 写入文件,退出 ----------> + res = write_results_to_file(history) + chatbot.append(("完成了吗?", res)) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 @CatchException def 解析ipynb文件(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): From 7beea951c667415a24f502e38f09e6df2fac2bdb Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 22 Apr 2023 17:24:22 +0800 Subject: [PATCH 24/52] unifying code --- config.py | 2 +- main.py | 8 ++++---- toolbox.py | 13 +++++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/config.py b/config.py index a78af65a..f4a59ded 100644 --- a/config.py +++ b/config.py @@ -62,4 +62,4 @@ AUTHENTICATION = [] API_URL_REDIRECT = {} # 如果你需要把网址放在二级地址下(常规情况下,不要修改!!) -CUSTOM_PATH = "/" +CUSTOM_PATH = "/gra" diff --git a/main.py b/main.py index 11f92f4b..ce2c5666 100644 --- a/main.py +++ b/main.py @@ -176,18 +176,18 @@ def main(): def auto_opentab_delay(): import threading, webbrowser, time print(f"如果浏览器没有自动打开,请复制并转到以下URL:") - print(f"\t(亮色主题): http://localhost:{PORT}") - print(f"\t(暗色主题): http://localhost:{PORT}/?__dark-theme=true") + print(f"\t(亮色主题): http://localhost:{PORT}" + f"{CUSTOM_PATH}".replace('//','/')) + print(f"\t(暗色主题): http://localhost:{PORT}" + f"{CUSTOM_PATH}/?__dark-theme=true".replace('//','/')) def open(): time.sleep(2) # 打开浏览器 - webbrowser.open_new_tab(f"http://localhost:{PORT}/?__dark-theme=true") + webbrowser.open_new_tab(f"http://localhost:{PORT}" + f"{CUSTOM_PATH}/?__dark-theme=true".replace('//','/')) threading.Thread(target=open, name="open-browser", daemon=True).start() threading.Thread(target=auto_update, name="self-upgrade", daemon=True).start() threading.Thread(target=warm_up_modules, name="warm-up", daemon=True).start() auto_opentab_delay() demo.queue(concurrency_count=CONCURRENT_COUNT) - run_gradio(demo, auth=AUTHENTICATION, favicon_path="docs/logo.png", port=PORT, custom_path=CUSTOM_PATH) + run_gradio(demo, auth=AUTHENTICATION, port=PORT, custom_path=CUSTOM_PATH) if __name__ == "__main__": main() diff --git a/toolbox.py b/toolbox.py index bf32ccdb..cd6c61e1 100644 --- a/toolbox.py +++ b/toolbox.py @@ -521,13 +521,14 @@ class DummyWith(): def __exit__(self, exc_type, exc_value, traceback): return -def run_gradio(demo, auth, favicon_path, port, custom_path): +def run_gradio(demo, auth, port, custom_path): import uvicorn import gradio as gr from fastapi import FastAPI app = FastAPI() - @app.get("/") - def read_main(): - return {"message": "NULL"} - app = gr.mount_gradio_app(app, demo, path=custom_path, auth=auth, favicon_path=favicon_path) - uvicorn.run(app, host="0.0.0.0", port=port) + if custom_path != "/": + @app.get("/") + def read_main(): + return {"message": f"Gradio is running at: {custom_path}"} + app = gr.mount_gradio_app(app, demo, path=custom_path) + uvicorn.run(app, host="0.0.0.0", port=port) # , auth=auth From f1234937c68f5b74391454d337aae082210769d2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 22 Apr 2023 17:30:21 +0800 Subject: [PATCH 25/52] add check path back --- config.py | 2 +- toolbox.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/config.py b/config.py index f4a59ded..a78af65a 100644 --- a/config.py +++ b/config.py @@ -62,4 +62,4 @@ AUTHENTICATION = [] API_URL_REDIRECT = {} # 如果你需要把网址放在二级地址下(常规情况下,不要修改!!) -CUSTOM_PATH = "/gra" +CUSTOM_PATH = "/" diff --git a/toolbox.py b/toolbox.py index cd6c61e1..2bf54514 100644 --- a/toolbox.py +++ b/toolbox.py @@ -522,6 +522,25 @@ class DummyWith(): return def run_gradio(demo, auth, port, custom_path): + def is_path_legal(path: str)->bool: + ''' + check path for sub url + path: path to check + return value: do sub url wrap + ''' + if path == "/": return True + if len(path) == 0: + print("ilegal custom path: {}\npath must not be empty\ndeploy on root url".format(path)) + return False + if path[0] == '/': + if path[1] != '/': + print("deploy on sub-path {}".format(path)) + return True + return False + print("ilegal custom path: {}\npath should begin with \'/\'\ndeploy on root url".format(path)) + return False + + if not is_path_legal(custom_path): raise RuntimeError('Ilegal custom path') import uvicorn import gradio as gr from fastapi import FastAPI From 7d44210a48f7a5eba444c9aa5e6b1678c50af84f Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 22 Apr 2023 17:55:50 +0800 Subject: [PATCH 26/52] fix apache2 sub-path deploy issue #544 --- docs/WithFastapi.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 docs/WithFastapi.md diff --git a/docs/WithFastapi.md b/docs/WithFastapi.md new file mode 100644 index 00000000..9f4baa14 --- /dev/null +++ b/docs/WithFastapi.md @@ -0,0 +1,28 @@ +# Running with fastapi + +We currently support fastapi in order to solve sub-path deploy issue. + +1. checkout to `subpath` branch + +``` sh +git checkout subpath +``` + + +2. merge lastest features (optional) + +``` sh +git merge master +``` + +3. change CUSTOM_PATH setting in `config.py` + +``` sh +nano config.py +``` + +4. Go! + +``` sh +python main.py +``` From e90eee2d8e515eab539f4923f08d6d5f33deb1ac Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 22 Apr 2023 18:07:24 +0800 Subject: [PATCH 27/52] =?UTF-8?q?=E5=8A=A0=E5=85=A5subpath=E6=94=AF?= =?UTF-8?q?=E6=8C=81=EF=BC=8C=E4=BD=86=E6=9A=82=E4=B8=8D=E5=90=AF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.py | 2 +- main.py | 25 +++++++++++++++---------- toolbox.py | 2 +- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/config.py b/config.py index a78af65a..9cf06e77 100644 --- a/config.py +++ b/config.py @@ -61,5 +61,5 @@ AUTHENTICATION = [] # 格式 {"https://api.openai.com/v1/chat/completions": "重定向的URL"} API_URL_REDIRECT = {} -# 如果你需要把网址放在二级地址下(常规情况下,不要修改!!) +# 如果你需要把网址放在二级地址下(常规情况下,不要修改!!)(需要配合修改main.py才能生效) CUSTOM_PATH = "/" diff --git a/main.py b/main.py index ce2c5666..f57ac1a6 100644 --- a/main.py +++ b/main.py @@ -3,10 +3,10 @@ import os; os.environ['no_proxy'] = '*' # 避免代理网络产生意外污染 def main(): import gradio as gr from request_llm.bridge_all import predict - from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf, ArgsGeneralWrapper, run_gradio, DummyWith + from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf, ArgsGeneralWrapper, DummyWith # 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到 - proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, API_KEY, AVAIL_LLM_MODELS, CUSTOM_PATH = \ - get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'API_KEY', 'AVAIL_LLM_MODELS', 'CUSTOM_PATH') + proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT, LAYOUT, API_KEY, AVAIL_LLM_MODELS = \ + get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT', 'LAYOUT', 'API_KEY', 'AVAIL_LLM_MODELS') # 如果WEB_PORT是-1, 则随机选取WEB端口 PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT @@ -176,20 +176,25 @@ def main(): def auto_opentab_delay(): import threading, webbrowser, time print(f"如果浏览器没有自动打开,请复制并转到以下URL:") - print(f"\t(亮色主题): http://localhost:{PORT}" + f"{CUSTOM_PATH}".replace('//','/')) - print(f"\t(暗色主题): http://localhost:{PORT}" + f"{CUSTOM_PATH}/?__dark-theme=true".replace('//','/')) + print(f"\t(亮色主题): http://localhost:{PORT}") + print(f"\t(暗色主题): http://localhost:{PORT}/?__dark-theme=true") def open(): time.sleep(2) # 打开浏览器 - webbrowser.open_new_tab(f"http://localhost:{PORT}" + f"{CUSTOM_PATH}/?__dark-theme=true".replace('//','/')) + webbrowser.open_new_tab(f"http://localhost:{PORT}/?__dark-theme=true") threading.Thread(target=open, name="open-browser", daemon=True).start() threading.Thread(target=auto_update, name="self-upgrade", daemon=True).start() threading.Thread(target=warm_up_modules, name="warm-up", daemon=True).start() auto_opentab_delay() - demo.queue(concurrency_count=CONCURRENT_COUNT) - run_gradio(demo, auth=AUTHENTICATION, port=PORT, custom_path=CUSTOM_PATH) + demo.queue(concurrency_count=CONCURRENT_COUNT).launch(server_name="0.0.0.0", server_port=PORT, auth=AUTHENTICATION, favicon_path="docs/logo.png") + + # 如果需要在二级路径下运行gradio + # CUSTOM_PATH, = get_conf('CUSTOM_PATH') + # if CUSTOM_PATH != "/": + # from toolbox import run_gradio_in_subpath + # run_gradio_in_subpath(demo, auth=AUTHENTICATION, port=PORT, custom_path=CUSTOM_PATH) + # else: + # demo.launch(server_name="0.0.0.0", server_port=PORT, auth=AUTHENTICATION, favicon_path="docs/logo.png") if __name__ == "__main__": main() - - diff --git a/toolbox.py b/toolbox.py index 2bf54514..febf6bc3 100644 --- a/toolbox.py +++ b/toolbox.py @@ -521,7 +521,7 @@ class DummyWith(): def __exit__(self, exc_type, exc_value, traceback): return -def run_gradio(demo, auth, port, custom_path): +def run_gradio_in_subpath(demo, auth, port, custom_path): def is_path_legal(path: str)->bool: ''' check path for sub url From 4575046ce1cd27f8cb9c2e4e7d1208cbe4b28e3f Mon Sep 17 00:00:00 2001 From: mrhblfx Date: Sat, 22 Apr 2023 18:08:27 +0800 Subject: [PATCH 28/52] =?UTF-8?q?=E4=BD=BF=E6=8F=90=E7=A4=BA=E6=9B=B4?= =?UTF-8?q?=E4=BD=B3=E5=85=A8=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functional.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crazy_functional.py b/crazy_functional.py index 6d2192bf..8a761000 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -203,7 +203,7 @@ def get_crazy_functions(): "Color": "stop", "AsButton": False, "AdvancedArgs": True, # 调用时,唤起高级参数输入区(默认False) - "ArgsReminder": "输入时用逗号隔开, *代表通配符, 加了^代表不匹配。例如: \"*.c, ^*.cpp, config.toml, ^README.md\"", # 高级参数输入区的显示提示 + "ArgsReminder": "输入时用逗号隔开, *代表通配符, 加了^代表不匹配; 不输入代表全部匹配。例如: \"*.c, ^*.cpp, config.toml, ^*.json\"", # 高级参数输入区的显示提示 "Function": HotReload(解析任意code项目) }, }) From a0f15f151259a45d3e6aadc3c8eb6cce933d8483 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 22 Apr 2023 18:10:42 +0800 Subject: [PATCH 29/52] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.py | 4 ++-- main.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.py b/config.py index 9cf06e77..b2727da0 100644 --- a/config.py +++ b/config.py @@ -57,9 +57,9 @@ CONCURRENT_COUNT = 100 # [("username", "password"), ("username2", "password2"), ...] AUTHENTICATION = [] -# 重新URL重新定向,实现更换API_URL的作用(常规情况下,不要修改!!) +# 重新URL重新定向,实现更换API_URL的作用(常规情况下,不要修改!!) # 格式 {"https://api.openai.com/v1/chat/completions": "重定向的URL"} API_URL_REDIRECT = {} -# 如果你需要把网址放在二级地址下(常规情况下,不要修改!!)(需要配合修改main.py才能生效) +# 如果需要在二级路径下运行(常规情况下,不要修改!!)(需要配合修改main.py才能生效!) CUSTOM_PATH = "/" diff --git a/main.py b/main.py index f57ac1a6..793b25ff 100644 --- a/main.py +++ b/main.py @@ -188,7 +188,7 @@ def main(): auto_opentab_delay() demo.queue(concurrency_count=CONCURRENT_COUNT).launch(server_name="0.0.0.0", server_port=PORT, auth=AUTHENTICATION, favicon_path="docs/logo.png") - # 如果需要在二级路径下运行gradio + # 如果需要在二级路径下运行 # CUSTOM_PATH, = get_conf('CUSTOM_PATH') # if CUSTOM_PATH != "/": # from toolbox import run_gradio_in_subpath From 70bd21f09a8a9adf69abdd132e14df74058b747b Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Sat, 22 Apr 2023 18:19:49 +0800 Subject: [PATCH 30/52] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=8C=E7=BA=A7?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E8=BF=90=E8=A1=8C=E7=9A=84=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/WithFastapi.md | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/docs/WithFastapi.md b/docs/WithFastapi.md index 9f4baa14..188b5271 100644 --- a/docs/WithFastapi.md +++ b/docs/WithFastapi.md @@ -2,26 +2,41 @@ We currently support fastapi in order to solve sub-path deploy issue. -1. checkout to `subpath` branch - -``` sh -git checkout subpath -``` - - -2. merge lastest features (optional) - -``` sh -git merge master -``` - -3. change CUSTOM_PATH setting in `config.py` +1. change CUSTOM_PATH setting in `config.py` ``` sh nano config.py ``` -4. Go! +2. Edit main.py + +```diff + auto_opentab_delay() + - demo.queue(concurrency_count=CONCURRENT_COUNT).launch(server_name="0.0.0.0", server_port=PORT, auth=AUTHENTICATION, favicon_path="docs/logo.png") + + demo.queue(concurrency_count=CONCURRENT_COUNT) + + - # 如果需要在二级路径下运行 + - # CUSTOM_PATH, = get_conf('CUSTOM_PATH') + - # if CUSTOM_PATH != "/": + - # from toolbox import run_gradio_in_subpath + - # run_gradio_in_subpath(demo, auth=AUTHENTICATION, port=PORT, custom_path=CUSTOM_PATH) + - # else: + - # demo.launch(server_name="0.0.0.0", server_port=PORT, auth=AUTHENTICATION, favicon_path="docs/logo.png") + + + 如果需要在二级路径下运行 + + CUSTOM_PATH, = get_conf('CUSTOM_PATH') + + if CUSTOM_PATH != "/": + + from toolbox import run_gradio_in_subpath + + run_gradio_in_subpath(demo, auth=AUTHENTICATION, port=PORT, custom_path=CUSTOM_PATH) + + else: + + demo.launch(server_name="0.0.0.0", server_port=PORT, auth=AUTHENTICATION, favicon_path="docs/logo.png") + +if __name__ == "__main__": + main() +``` + + +3. Go! ``` sh python main.py From bd62c6be68ee406af1321391ee35db1b79d26a01 Mon Sep 17 00:00:00 2001 From: mrhblfx Date: Sat, 22 Apr 2023 18:20:01 +0800 Subject: [PATCH 31/52] =?UTF-8?q?=E4=BD=BF=E6=8F=90=E7=A4=BA=E6=9B=B4?= =?UTF-8?q?=E4=BD=B3=E5=85=A8=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functional.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crazy_functional.py b/crazy_functional.py index 8a761000..04ebaa53 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -203,7 +203,7 @@ def get_crazy_functions(): "Color": "stop", "AsButton": False, "AdvancedArgs": True, # 调用时,唤起高级参数输入区(默认False) - "ArgsReminder": "输入时用逗号隔开, *代表通配符, 加了^代表不匹配; 不输入代表全部匹配。例如: \"*.c, ^*.cpp, config.toml, ^*.json\"", # 高级参数输入区的显示提示 + "ArgsReminder": "输入时用逗号隔开, *代表通配符, 加了^代表不匹配; 不输入代表全部匹配。例如: \"*.c, ^*.cpp, config.toml, ^*.toml\"", # 高级参数输入区的显示提示 "Function": HotReload(解析任意code项目) }, }) From c0f1b5bc8e832bf6d93e87d869e5d6e42fbb90a0 Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Sat, 22 Apr 2023 18:21:43 +0800 Subject: [PATCH 32/52] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e409d564..4eb1fc55 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,8 @@ docker run --rm -it --net=host --gpus=all gpt-academic bash 2. 使用WSL2(Windows Subsystem for Linux 子系统) 请访问[部署wiki-2](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) +3. 如何在二级网址( 如http://localhost/subpath )下运行 +请访问[FastAPI运行说明](docs/WithFastapi.md) ## 安装-代理配置 1. 常规方法 From 15c6b52b5f20fb9d2228572b87fdcc256b922e60 Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Sat, 22 Apr 2023 18:22:33 +0800 Subject: [PATCH 33/52] =?UTF-8?q?=E4=BF=AE=E6=94=B9README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4eb1fc55..e2fa3ed6 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ docker run --rm -it --net=host --gpus=all gpt-academic bash 2. 使用WSL2(Windows Subsystem for Linux 子系统) 请访问[部署wiki-2](https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BD%BF%E7%94%A8WSL2%EF%BC%88Windows-Subsystem-for-Linux-%E5%AD%90%E7%B3%BB%E7%BB%9F%EF%BC%89%E9%83%A8%E7%BD%B2) -3. 如何在二级网址( 如http://localhost/subpath )下运行 +3. 如何在二级网址(如`http://localhost/subpath`)下运行 请访问[FastAPI运行说明](docs/WithFastapi.md) ## 安装-代理配置 From d3dcd432e8346295936bcecf112716f78f33aabd Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Sat, 22 Apr 2023 18:47:11 +0800 Subject: [PATCH 34/52] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e2fa3ed6..a77ffc81 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,8 @@ docker run --rm -it --net=host --gpus=all gpt-academic bash
+ +
From 4065d6e234869c7261fb14a923f6782002508b3e Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Sat, 22 Apr 2023 18:56:02 +0800 Subject: [PATCH 35/52] =?UTF-8?q?=E7=89=88=E6=9C=AC3.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functional.py | 11 +++++++++- crazy_functions/询问多个大语言模型.py | 29 +++++++++++++++++++++++++++ version | 4 ++-- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/crazy_functional.py b/crazy_functional.py index 04ebaa53..45fd5618 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -207,6 +207,15 @@ def get_crazy_functions(): "Function": HotReload(解析任意code项目) }, }) - + from crazy_functions.询问多个大语言模型 import 同时问询_指定模型 + function_plugins.update({ + "询问多个GPT模型(手动指定询问哪些模型)": { + "Color": "stop", + "AsButton": False, + "AdvancedArgs": True, # 调用时,唤起高级参数输入区(默认False) + "ArgsReminder": "支持任意数量的llm接口,用&符号分隔。例如chatglm&gpt-3.5-turbo&api2d-gpt-4", # 高级参数输入区的显示提示 + "Function": HotReload(同时问询_指定模型) + }, + }) ###################### 第n组插件 ########################### return function_plugins diff --git a/crazy_functions/询问多个大语言模型.py b/crazy_functions/询问多个大语言模型.py index fb781458..2939d045 100644 --- a/crazy_functions/询问多个大语言模型.py +++ b/crazy_functions/询问多个大语言模型.py @@ -25,6 +25,35 @@ def 同时问询(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt retry_times_at_unknown_error=0 ) + history.append(txt) + history.append(gpt_say) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新 + + +@CatchException +def 同时问询_指定模型(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + """ + txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径 + llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行 + plugin_kwargs 插件模型的参数,如温度和top_p等,一般原样传递下去就行 + chatbot 聊天显示框的句柄,用于显示给用户 + history 聊天历史,前情提要 + system_prompt 给gpt的静默提醒 + web_port 当前软件运行的端口号 + """ + history = [] # 清空历史,以免输入溢出 + chatbot.append((txt, "正在同时咨询ChatGPT和ChatGLM……")) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新 + + # llm_kwargs['llm_model'] = 'chatglm&gpt-3.5-turbo&api2d-gpt-3.5-turbo' # 支持任意数量的llm接口,用&符号分隔 + llm_kwargs['llm_model'] = plugin_kwargs.get("advanced_arg", 'chatglm&gpt-3.5-turbo') # 'chatglm&gpt-3.5-turbo' # 支持任意数量的llm接口,用&符号分隔 + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( + inputs=txt, inputs_show_user=txt, + llm_kwargs=llm_kwargs, chatbot=chatbot, history=history, + sys_prompt=system_prompt, + retry_times_at_unknown_error=0 + ) + history.append(txt) history.append(gpt_say) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新 \ No newline at end of file diff --git a/version b/version index b6458253..ec50d822 100644 --- a/version +++ b/version @@ -1,5 +1,5 @@ { - "version": 3.15, + "version": 3.2, "show_feature": true, - "new_feature": "添加联网(Google)回答问题插件 <-> 修复ChatGLM上下文BUG <-> 添加支持清华ChatGLM和GPT-4 <-> 改进架构,支持与多个LLM模型同时对话 <-> 添加支持API2D(国内,可支持gpt4)" + "new_feature": "现函数插件可读取高级参数(解读任意语言代码+同时询问任意的LLM组合)<-> 添加联网(Google)回答问题插件 <-> 修复ChatGLM上下文BUG <-> 添加支持清华ChatGLM和GPT-4 <-> 改进架构,支持与多个LLM模型同时对话 <-> 添加支持API2D(国内,可支持gpt4)" } From 13342c29889c3afcf9d13990ae5f2ca4aca75f8e Mon Sep 17 00:00:00 2001 From: saltfish Date: Sat, 22 Apr 2023 21:11:24 +0800 Subject: [PATCH 36/52] feat(jupter): use args to disable Markdown parse --- crazy_functional.py | 2 ++ crazy_functions/解析JupyterNotebook.py | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/crazy_functional.py b/crazy_functional.py index 45fd5618..79c8872d 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -30,6 +30,8 @@ def get_crazy_functions(): "Color": "stop", "AsButton":False, "Function": HotReload(解析ipynb文件), + "AdvancedArgs": True, # 调用时,唤起高级参数输入区(默认False) + "ArgsReminder": "若输入0,则不解析notebook中的Markdown块", # 高级参数输入区的显示提示 }, "批量总结Word文档": { "Color": "stop", diff --git a/crazy_functions/解析JupyterNotebook.py b/crazy_functions/解析JupyterNotebook.py index 3c9948b8..95a3d696 100644 --- a/crazy_functions/解析JupyterNotebook.py +++ b/crazy_functions/解析JupyterNotebook.py @@ -67,11 +67,16 @@ def parseNotebook(filename, enable_markdown=1): def ipynb解释(file_manifest, project_folder, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt): from .crazy_utils import request_gpt_model_multi_threads_with_very_awesome_ui_and_high_efficiency + enable_markdown = plugin_kwargs.get("advanced_arg", "1") + try: + enable_markdown = int(enable_markdown) + except ValueError: + enable_markdown = 1 + pfg = PaperFileGroup() - print(file_manifest) for fp in file_manifest: - file_content = parseNotebook(fp, enable_markdown=1) + file_content = parseNotebook(fp, enable_markdown=enable_markdown) pfg.file_paths.append(fp) pfg.file_contents.append(file_content) From 07807e4653f7fa115fdb84b8d672a80d66a56d2f Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Sun, 23 Apr 2023 11:17:56 +0800 Subject: [PATCH 37/52] =?UTF-8?q?=E6=8F=92=E4=BB=B6=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E5=AF=B9=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functional.py | 5 ++++ crazy_functions/对话历史存档.py | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 crazy_functions/对话历史存档.py diff --git a/crazy_functional.py b/crazy_functional.py index 45fd5618..df695e24 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -20,12 +20,17 @@ def get_crazy_functions(): from crazy_functions.解析项目源代码 import 解析一个CSharp项目 from crazy_functions.总结word文档 import 总结word文档 from crazy_functions.解析JupyterNotebook import 解析ipynb文件 + from crazy_functions.对话历史存档 import 对话历史存档 function_plugins = { "解析整个Python项目": { "Color": "stop", # 按钮颜色 "Function": HotReload(解析一个Python项目) }, + "保存当前的对话": { + "AsButton":False, + "Function": HotReload(对话历史存档) + }, "[测试功能] 解析Jupyter Notebook文件": { "Color": "stop", "AsButton":False, diff --git a/crazy_functions/对话历史存档.py b/crazy_functions/对话历史存档.py new file mode 100644 index 00000000..1b232de4 --- /dev/null +++ b/crazy_functions/对话历史存档.py @@ -0,0 +1,42 @@ +from toolbox import CatchException, update_ui +from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive + +def write_chat_to_file(chatbot, file_name=None): + """ + 将对话记录history以Markdown格式写入文件中。如果没有指定文件名,则使用当前时间生成文件名。 + """ + import os + import time + if file_name is None: + file_name = 'chatGPT对话历史' + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + '.html' + os.makedirs('./gpt_log/', exist_ok=True) + with open(f'./gpt_log/{file_name}', 'w', encoding='utf8') as f: + for i, contents in enumerate(chatbot): + for content in contents: + try: # 这个bug没找到触发条件,暂时先这样顶一下 + if type(content) != str: content = str(content) + except: + continue + f.write(content) + f.write('\n\n') + f.write('
\n\n') + + res = '对话历史写入:' + os.path.abspath(f'./gpt_log/{file_name}') + print(res) + return res + +@CatchException +def 对话历史存档(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): + """ + txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径 + llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行 + plugin_kwargs 插件模型的参数,暂时没有用武之地 + chatbot 聊天显示框的句柄,用于显示给用户 + history 聊天历史,前情提要 + system_prompt 给gpt的静默提醒 + web_port 当前软件运行的端口号 + """ + + chatbot.append(("保存当前对话", f"[Local Message] {write_chat_to_file(chatbot)}")) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 由于请求gpt需要一段时间,我们先及时地做一次界面更新 + From 87d963bda591e16d4bbf700dee5b0e704f5544cd Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Sun, 23 Apr 2023 11:19:16 +0800 Subject: [PATCH 38/52] UP --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index ec50d822..a2a877b7 100644 --- a/version +++ b/version @@ -1,5 +1,5 @@ { "version": 3.2, "show_feature": true, - "new_feature": "现函数插件可读取高级参数(解读任意语言代码+同时询问任意的LLM组合)<-> 添加联网(Google)回答问题插件 <-> 修复ChatGLM上下文BUG <-> 添加支持清华ChatGLM和GPT-4 <-> 改进架构,支持与多个LLM模型同时对话 <-> 添加支持API2D(国内,可支持gpt4)" + "new_feature": "保存对话功能 <-> 解读任意语言代码+同时询问任意的LLM组合 <-> 添加联网(Google)回答问题插件 <-> 修复ChatGLM上下文BUG <-> 添加支持清华ChatGLM和GPT-4 <-> 改进架构,支持与多个LLM模型同时对话 <-> 添加支持API2D(国内,可支持gpt4)" } From 2f4e05061200ff2e08837ccbc22f0361e8f116c3 Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Sun, 23 Apr 2023 11:22:35 +0800 Subject: [PATCH 39/52] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a77ffc81..d4e8539f 100644 --- a/README.md +++ b/README.md @@ -277,7 +277,8 @@ docker run --rm -it --net=host --gpus=all gpt-academic bash ## Todo 与 版本规划: -- version 3.2+ (todo): 函数插件支持更多参数接口 +- version 3.3+ (todo): NewBing支持 +- version 3.2: 函数插件支持更多参数接口 (保存对话功能, 解读任意语言代码+同时询问任意的LLM组合) - version 3.1: 支持同时问询多个gpt模型!支持api2d,支持多个apikey负载均衡 - version 3.0: 对chatglm和其他小型llm的支持 - version 2.6: 重构了插件结构,提高了交互性,加入更多插件 From 676fe40d39883b6cae70234652ec84c3db1b31e3 Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Sun, 23 Apr 2023 17:32:44 +0800 Subject: [PATCH 40/52] =?UTF-8?q?=E4=BC=98=E5=8C=96chatgpt=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E7=9A=84=E6=88=AA=E6=96=AD=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functions/谷歌检索小助手.py | 3 +- request_llm/bridge_chatgpt.py | 17 +++++++----- toolbox.py | 46 +++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/crazy_functions/谷歌检索小助手.py b/crazy_functions/谷歌检索小助手.py index 94ef2563..786b266f 100644 --- a/crazy_functions/谷歌检索小助手.py +++ b/crazy_functions/谷歌检索小助手.py @@ -98,7 +98,8 @@ def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst history.extend([ "第一批", gpt_say ]) meta_paper_info_list = meta_paper_info_list[10:] - chatbot.append(["状态?", "已经全部完成"]) + chatbot.append(["状态?", + "已经全部完成,您可以试试让AI写一个Related Works,例如您可以继续输入Write a \"Related Works\" section about \"你搜索的研究领域\" for me."]) msg = '正常' yield from update_ui(chatbot=chatbot, history=history, msg=msg) # 刷新界面 res = write_results_to_file(history) diff --git a/request_llm/bridge_chatgpt.py b/request_llm/bridge_chatgpt.py index c1a900b1..a1614b72 100644 --- a/request_llm/bridge_chatgpt.py +++ b/request_llm/bridge_chatgpt.py @@ -21,7 +21,7 @@ import importlib # config_private.py放自己的秘密如API和代理网址 # 读取时首先看是否存在私密的config_private配置文件(不受git管控),如果有,则覆盖原config文件 -from toolbox import get_conf, update_ui, is_any_api_key, select_api_key, what_keys +from toolbox import get_conf, update_ui, is_any_api_key, select_api_key, what_keys, clip_history proxies, API_KEY, TIMEOUT_SECONDS, MAX_RETRY = \ get_conf('proxies', 'API_KEY', 'TIMEOUT_SECONDS', 'MAX_RETRY') @@ -145,7 +145,7 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp yield from update_ui(chatbot=chatbot, history=history, msg="api-key不满足要求") # 刷新界面 return - history.append(inputs); history.append(" ") + history.append(inputs); history.append("") retry = 0 while True: @@ -198,14 +198,17 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp chunk_decoded = chunk.decode() error_msg = chunk_decoded if "reduce the length" in error_msg: - chatbot[-1] = (chatbot[-1][0], "[Local Message] Reduce the length. 本次输入过长,或历史数据过长. 历史缓存数据现已释放,您可以请再次尝试.") - history = [] # 清除历史 + if len(history) >= 2: history[-1] = ""; history[-2] = "" # 清除当前溢出的输入:history[-2] 是本次输入, history[-1] 是本次输出 + history = clip_history(inputs=inputs, history=history, tokenizer=model_info[llm_kwargs['llm_model']]['tokenizer'], + max_token_limit=(model_info[llm_kwargs['llm_model']]['max_token'])//2) # history至少释放二分之一 + chatbot[-1] = (chatbot[-1][0], "[Local Message] Reduce the length. 本次输入过长, 或历史数据过长. 历史缓存数据已部分释放, 您可以请再次尝试. (若再次失败则更可能是因为输入过长.)") + # history = [] # 清除历史 elif "does not exist" in error_msg: - chatbot[-1] = (chatbot[-1][0], f"[Local Message] Model {llm_kwargs['llm_model']} does not exist. 模型不存在,或者您没有获得体验资格.") + chatbot[-1] = (chatbot[-1][0], f"[Local Message] Model {llm_kwargs['llm_model']} does not exist. 模型不存在, 或者您没有获得体验资格.") elif "Incorrect API key" in error_msg: - chatbot[-1] = (chatbot[-1][0], "[Local Message] Incorrect API key. OpenAI以提供了不正确的API_KEY为由,拒绝服务.") + chatbot[-1] = (chatbot[-1][0], "[Local Message] Incorrect API key. OpenAI以提供了不正确的API_KEY为由, 拒绝服务.") elif "exceeded your current quota" in error_msg: - chatbot[-1] = (chatbot[-1][0], "[Local Message] You exceeded your current quota. OpenAI以账户额度不足为由,拒绝服务.") + chatbot[-1] = (chatbot[-1][0], "[Local Message] You exceeded your current quota. OpenAI以账户额度不足为由, 拒绝服务.") elif "bad forward key" in error_msg: chatbot[-1] = (chatbot[-1][0], "[Local Message] Bad forward key. API2D账户额度不足.") elif "Not enough point" in error_msg: diff --git a/toolbox.py b/toolbox.py index 6625c43d..4340814c 100644 --- a/toolbox.py +++ b/toolbox.py @@ -551,3 +551,49 @@ def run_gradio_in_subpath(demo, auth, port, custom_path): return {"message": f"Gradio is running at: {custom_path}"} app = gr.mount_gradio_app(app, demo, path=custom_path) uvicorn.run(app, host="0.0.0.0", port=port) # , auth=auth + + +def clip_history(inputs, history, tokenizer, max_token_limit): + """ + reduce the length of input/history by clipping. + this function search for the longest entries to clip, little by little, + until the number of token of input/history is reduced under threshold. + 通过剪辑来缩短输入/历史记录的长度。 + 此函数逐渐地搜索最长的条目进行剪辑, + 直到输入/历史记录的标记数量降低到阈值以下。 + """ + import numpy as np + from request_llm.bridge_all import model_info + def get_token_num(txt): + return len(tokenizer.encode(txt, disallowed_special=())) + input_token_num = get_token_num(inputs) + if input_token_num < max_token_limit * 3 / 4: + # 当输入部分的token占比小于限制的3/4时,在裁剪时把input的余量留出来 + max_token_limit = max_token_limit - input_token_num + if max_token_limit < 128: + # 余量太小了,直接清除历史 + history = [] + return history + else: + # 当输入部分的token占比 > 限制的3/4时,直接清除历史 + history = [] + return history + + everything = [''] + everything.extend(history) + n_token = get_token_num('\n'.join(everything)) + everything_token = [get_token_num(e) for e in everything] + + # 截断时的颗粒度 + delta = max(everything_token) // 16 + + while n_token > max_token_limit: + where = np.argmax(everything_token) + encoded = tokenizer.encode(everything[where], disallowed_special=()) + clipped_encoded = encoded[:len(encoded)-delta] + everything[where] = tokenizer.decode(clipped_encoded)[:-1] # -1 to remove the may-be illegal char + everything_token[where] = get_token_num(everything[where]) + n_token = get_token_num('\n'.join(everything)) + + history = everything[1:] + return history From 0785ff2aedabbd1f4a4aee78b6b7c070ed30a069 Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Sun, 23 Apr 2023 17:45:56 +0800 Subject: [PATCH 41/52] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E8=A3=81=E5=89=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- request_llm/bridge_chatgpt.py | 2 +- toolbox.py | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/request_llm/bridge_chatgpt.py b/request_llm/bridge_chatgpt.py index a1614b72..5e32f452 100644 --- a/request_llm/bridge_chatgpt.py +++ b/request_llm/bridge_chatgpt.py @@ -200,7 +200,7 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp if "reduce the length" in error_msg: if len(history) >= 2: history[-1] = ""; history[-2] = "" # 清除当前溢出的输入:history[-2] 是本次输入, history[-1] 是本次输出 history = clip_history(inputs=inputs, history=history, tokenizer=model_info[llm_kwargs['llm_model']]['tokenizer'], - max_token_limit=(model_info[llm_kwargs['llm_model']]['max_token'])//2) # history至少释放二分之一 + max_token_limit=(model_info[llm_kwargs['llm_model']]['max_token'])) # history至少释放二分之一 chatbot[-1] = (chatbot[-1][0], "[Local Message] Reduce the length. 本次输入过长, 或历史数据过长. 历史缓存数据已部分释放, 您可以请再次尝试. (若再次失败则更可能是因为输入过长.)") # history = [] # 清除历史 elif "does not exist" in error_msg: diff --git a/toolbox.py b/toolbox.py index 4340814c..c9dc2070 100644 --- a/toolbox.py +++ b/toolbox.py @@ -555,23 +555,26 @@ def run_gradio_in_subpath(demo, auth, port, custom_path): def clip_history(inputs, history, tokenizer, max_token_limit): """ - reduce the length of input/history by clipping. + reduce the length of history by clipping. this function search for the longest entries to clip, little by little, - until the number of token of input/history is reduced under threshold. - 通过剪辑来缩短输入/历史记录的长度。 + until the number of token of history is reduced under threshold. + 通过裁剪来缩短历史记录的长度。 此函数逐渐地搜索最长的条目进行剪辑, - 直到输入/历史记录的标记数量降低到阈值以下。 + 直到历史记录的标记数量降低到阈值以下。 """ import numpy as np from request_llm.bridge_all import model_info def get_token_num(txt): return len(tokenizer.encode(txt, disallowed_special=())) input_token_num = get_token_num(inputs) - if input_token_num < max_token_limit * 3 / 4: - # 当输入部分的token占比小于限制的3/4时,在裁剪时把input的余量留出来 + if input_token_num < max_token_limit * 3 / 4: + # 当输入部分的token占比小于限制的3/4时,裁剪时 + # 1. 把input的余量留出来 max_token_limit = max_token_limit - input_token_num + # 2. 把输出用的余量留出来 + max_token_limit = max_token_limit - 128 + # 3. 如果余量太小了,直接清除历史 if max_token_limit < 128: - # 余量太小了,直接清除历史 history = [] return history else: From f5bc58dbde52e116ac3d7599dbda09a1e0ed1f9a Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Mon, 24 Apr 2023 01:41:47 +0800 Subject: [PATCH 42/52] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d4e8539f..d4162ee8 100644 --- a/README.md +++ b/README.md @@ -27,13 +27,13 @@ If you like this project, please give it a Star. If you've come up with more use [自我程序剖析](https://www.bilibili.com/video/BV1cj411A7VW) | [函数插件] [一键读懂](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)本项目的源代码 [程序剖析](https://www.bilibili.com/video/BV1cj411A7VW) | [函数插件] 一键可以剖析其他Python/C/C++/Java/Lua/...项目树 读论文 | [函数插件] 一键解读latex论文全文并生成摘要 -Latex全文翻译、润色 | [函数插件] 一键翻译或润色latex论文 +Latex全文[翻译](https://www.bilibili.com/video/BV1nk4y1Y7Js/)、[润色](https://www.bilibili.com/video/BV1FT411H7c5/) | [函数插件] 一键翻译或润色latex论文 批量注释生成 | [函数插件] 一键批量生成函数注释 chat分析报告生成 | [函数插件] 运行后自动生成总结汇报 -Markdown中英互译 | [函数插件] 看到上面5种语言的[README](https://github.com/binary-husky/chatgpt_academic/blob/master/docs/README_EN.md)了吗? +Markdown[中英互译](https://www.bilibili.com/video/BV1yo4y157jV/) | [函数插件] 看到上面5种语言的[README](https://github.com/binary-husky/chatgpt_academic/blob/master/docs/README_EN.md)了吗? [arxiv小助手](https://www.bilibili.com/video/BV1LM4y1279X) | [函数插件] 输入arxiv文章url即可一键翻译摘要+下载PDF [PDF论文全文翻译功能](https://www.bilibili.com/video/BV1KT411x7Wn) | [函数插件] PDF论文提取题目&摘要+翻译全文(多线程) -[谷歌学术统合小助手](https://www.bilibili.com/video/BV19L411U7ia) | [函数插件] 给定任意谷歌学术搜索页面URL,让gpt帮你选择有趣的文章 +[谷歌学术统合小助手](https://www.bilibili.com/video/BV19L411U7ia) | [函数插件] 给定任意谷歌学术搜索页面URL,让gpt帮你[写relatedworks](https://www.bilibili.com/video/BV1GP411U7Az/) 公式/图片/表格显示 | 可以同时显示公式的tex形式和渲染形式,支持公式、代码高亮 多线程函数插件支持 | 支持多线调用chatgpt,一键处理海量文本或程序 启动暗色gradio[主题](https://github.com/binary-husky/chatgpt_academic/issues/173) | 在浏览器url后面添加```/?__dark-theme=true```可以切换dark主题 From e361d741c3dae56ba48c752caa48414e7d99ee34 Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Mon, 24 Apr 2023 01:44:30 +0800 Subject: [PATCH 43/52] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d4162ee8..62da5aa7 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Markdown[中英互译](https://www.bilibili.com/video/BV1yo4y157jV/) | [函数 [PDF论文全文翻译功能](https://www.bilibili.com/video/BV1KT411x7Wn) | [函数插件] PDF论文提取题目&摘要+翻译全文(多线程) [谷歌学术统合小助手](https://www.bilibili.com/video/BV19L411U7ia) | [函数插件] 给定任意谷歌学术搜索页面URL,让gpt帮你[写relatedworks](https://www.bilibili.com/video/BV1GP411U7Az/) 公式/图片/表格显示 | 可以同时显示公式的tex形式和渲染形式,支持公式、代码高亮 -多线程函数插件支持 | 支持多线调用chatgpt,一键处理海量文本或程序 +多线程函数插件支持 | 支持多线调用chatgpt,一键处理[海量文本](https://www.bilibili.com/video/BV1FT411H7c5/)或程序 启动暗色gradio[主题](https://github.com/binary-husky/chatgpt_academic/issues/173) | 在浏览器url后面添加```/?__dark-theme=true```可以切换dark主题 [多LLM模型](https://www.bilibili.com/video/BV1wT411p7yf)支持,[API2D](https://api2d.com/)接口支持 | 同时被GPT3.5、GPT4和[清华ChatGLM](https://github.com/THUDM/ChatGLM-6B)伺候的感觉一定会很不错吧? huggingface免科学上网[在线体验](https://huggingface.co/spaces/qingxu98/gpt-academic) | 登陆huggingface后复制[此空间](https://huggingface.co/spaces/qingxu98/gpt-academic) From a141c5ccdce140870c6e5be6ef92b6b9f00096b2 Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Mon, 24 Apr 2023 01:46:58 +0800 Subject: [PATCH 44/52] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62da5aa7..7c328f50 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ If you like this project, please give it a Star. If you've come up with more use 一键代码解释 | 可以正确显示代码、解释代码 [自定义快捷键](https://www.bilibili.com/video/BV14s4y1E7jN) | 支持自定义快捷键 [配置代理服务器](https://www.bilibili.com/video/BV1rc411W7Dr) | 支持配置代理服务器 -模块化设计 | 支持自定义高阶的函数插件与[函数插件],插件支持[热更新](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) +模块化设计 | 支持自定义强大的函数插件,插件支持[热更新](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) [自我程序剖析](https://www.bilibili.com/video/BV1cj411A7VW) | [函数插件] [一键读懂](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)本项目的源代码 [程序剖析](https://www.bilibili.com/video/BV1cj411A7VW) | [函数插件] 一键可以剖析其他Python/C/C++/Java/Lua/...项目树 读论文 | [函数插件] 一键解读latex论文全文并生成摘要 From 81d53d0726bcdb282ab54b6badc2b69b1c2d74e6 Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Mon, 24 Apr 2023 01:47:35 +0800 Subject: [PATCH 45/52] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c328f50..4272ce4b 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ If you like this project, please give it a Star. If you've come up with more use 一键代码解释 | 可以正确显示代码、解释代码 [自定义快捷键](https://www.bilibili.com/video/BV14s4y1E7jN) | 支持自定义快捷键 [配置代理服务器](https://www.bilibili.com/video/BV1rc411W7Dr) | 支持配置代理服务器 -模块化设计 | 支持自定义强大的函数插件,插件支持[热更新](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) +模块化设计 | 支持自定义强大的[函数插件](https://github.com/binary-husky/chatgpt_academic/tree/master/crazy_functions),插件支持[热更新](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) [自我程序剖析](https://www.bilibili.com/video/BV1cj411A7VW) | [函数插件] [一键读懂](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)本项目的源代码 [程序剖析](https://www.bilibili.com/video/BV1cj411A7VW) | [函数插件] 一键可以剖析其他Python/C/C++/Java/Lua/...项目树 读论文 | [函数插件] 一键解读latex论文全文并生成摘要 From 0512b311f89cd13670351fd91a9178062282101a Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Mon, 24 Apr 2023 01:55:10 +0800 Subject: [PATCH 46/52] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4272ce4b..c7c735f3 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ If you like this project, please give it a Star. If you've come up with more use 一键中英互译 | 一键中英互译 一键代码解释 | 可以正确显示代码、解释代码 [自定义快捷键](https://www.bilibili.com/video/BV14s4y1E7jN) | 支持自定义快捷键 -[配置代理服务器](https://www.bilibili.com/video/BV1rc411W7Dr) | 支持配置代理服务器 +[配置代理服务器](https://www.bilibili.com/video/BV1rc411W7Dr) | 支持代理连接OpenAI/Google等,秒解锁ChatGPT互联网实时信息聚合能力 模块化设计 | 支持自定义强大的[函数插件](https://github.com/binary-husky/chatgpt_academic/tree/master/crazy_functions),插件支持[热更新](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) [自我程序剖析](https://www.bilibili.com/video/BV1cj411A7VW) | [函数插件] [一键读懂](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)本项目的源代码 [程序剖析](https://www.bilibili.com/video/BV1cj411A7VW) | [函数插件] 一键可以剖析其他Python/C/C++/Java/Lua/...项目树 From 06e8e8f9a6ae3461ef5f91a4fc7556bb9639d4bd Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Mon, 24 Apr 2023 01:55:53 +0800 Subject: [PATCH 47/52] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c7c735f3..61d9240a 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ If you like this project, please give it a Star. If you've come up with more use 一键中英互译 | 一键中英互译 一键代码解释 | 可以正确显示代码、解释代码 [自定义快捷键](https://www.bilibili.com/video/BV14s4y1E7jN) | 支持自定义快捷键 -[配置代理服务器](https://www.bilibili.com/video/BV1rc411W7Dr) | 支持代理连接OpenAI/Google等,秒解锁ChatGPT互联网实时信息聚合能力 +[配置代理服务器](https://www.bilibili.com/video/BV1rc411W7Dr) | 支持代理连接OpenAI/Google等,秒解锁ChatGPT互联网[实时信息聚合](https://www.bilibili.com/video/BV1om4y127ck/)能力 模块化设计 | 支持自定义强大的[函数插件](https://github.com/binary-husky/chatgpt_academic/tree/master/crazy_functions),插件支持[热更新](https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97) [自我程序剖析](https://www.bilibili.com/video/BV1cj411A7VW) | [函数插件] [一键读懂](https://github.com/binary-husky/chatgpt_academic/wiki/chatgpt-academic%E9%A1%B9%E7%9B%AE%E8%87%AA%E8%AF%91%E8%A7%A3%E6%8A%A5%E5%91%8A)本项目的源代码 [程序剖析](https://www.bilibili.com/video/BV1cj411A7VW) | [函数插件] 一键可以剖析其他Python/C/C++/Java/Lua/...项目树 From 51424a7d08965a89938b96c0680a989dd7caa510 Mon Sep 17 00:00:00 2001 From: binary-husky <96192199+binary-husky@users.noreply.github.com> Date: Mon, 24 Apr 2023 01:57:13 +0800 Subject: [PATCH 48/52] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 61d9240a..b40282ab 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Markdown[中英互译](https://www.bilibili.com/video/BV1yo4y157jV/) | [函数 [arxiv小助手](https://www.bilibili.com/video/BV1LM4y1279X) | [函数插件] 输入arxiv文章url即可一键翻译摘要+下载PDF [PDF论文全文翻译功能](https://www.bilibili.com/video/BV1KT411x7Wn) | [函数插件] PDF论文提取题目&摘要+翻译全文(多线程) [谷歌学术统合小助手](https://www.bilibili.com/video/BV19L411U7ia) | [函数插件] 给定任意谷歌学术搜索页面URL,让gpt帮你[写relatedworks](https://www.bilibili.com/video/BV1GP411U7Az/) -公式/图片/表格显示 | 可以同时显示公式的tex形式和渲染形式,支持公式、代码高亮 +公式/图片/表格显示 | 可以同时显示公式的[tex形式和渲染形式](https://user-images.githubusercontent.com/96192199/230598842-1d7fcddd-815d-40ee-af60-baf488a199df.png),支持公式、代码高亮 多线程函数插件支持 | 支持多线调用chatgpt,一键处理[海量文本](https://www.bilibili.com/video/BV1FT411H7c5/)或程序 启动暗色gradio[主题](https://github.com/binary-husky/chatgpt_academic/issues/173) | 在浏览器url后面添加```/?__dark-theme=true```可以切换dark主题 [多LLM模型](https://www.bilibili.com/video/BV1wT411p7yf)支持,[API2D](https://api2d.com/)接口支持 | 同时被GPT3.5、GPT4和[清华ChatGLM](https://github.com/THUDM/ChatGLM-6B)伺候的感觉一定会很不错吧? From a097b6cd032cee3779af953b67b0260f5ad5ac6d Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Mon, 24 Apr 2023 11:34:47 +0800 Subject: [PATCH 49/52] =?UTF-8?q?=E5=87=8F=E5=B0=91=E6=AF=8F=E6=AC=A1?= =?UTF-8?q?=E5=A4=84=E7=90=86=E7=9A=84=E8=AE=BA=E6=96=87=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functions/谷歌检索小助手.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/crazy_functions/谷歌检索小助手.py b/crazy_functions/谷歌检索小助手.py index 786b266f..2e2d3d16 100644 --- a/crazy_functions/谷歌检索小助手.py +++ b/crazy_functions/谷歌检索小助手.py @@ -82,21 +82,22 @@ def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst history = [] meta_paper_info_list = yield from get_meta_information(txt, chatbot, history) + batchsize = 7 + for batch in range(len(meta_paper_info_list)//batchsize): + if len(meta_paper_info_list[:batchsize]) > 0: + i_say = "下面是一些学术文献的数据,提取出以下内容,使用Markdown格式输出:" + \ + "1、英文题目;2、中文题目翻译;3、作者;4、arxiv公开(is_paper_in_arxiv);4、引用数量(cite);5、中文摘要翻译。" + \ + f"以下是信息源:{str(meta_paper_info_list[:batchsize])}" - if len(meta_paper_info_list[:10]) > 0: - i_say = "下面是一些学术文献的数据,请从中提取出以下内容。" + \ - "1、英文题目;2、中文题目翻译;3、作者;4、arxiv公开(is_paper_in_arxiv);4、引用数量(cite);5、中文摘要翻译。" + \ - f"以下是信息源:{str(meta_paper_info_list[:10])}" + inputs_show_user = f"请分析此页面中出现的所有文章:{txt},这是第{batch+1}批" + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( + inputs=i_say, inputs_show_user=inputs_show_user, + llm_kwargs=llm_kwargs, chatbot=chatbot, history=[], + sys_prompt="你是一个学术翻译,请从数据中提取信息。你必须使用Markdown格式。你必须逐个文献进行处理。" + ) - inputs_show_user = f"请分析此页面中出现的所有文章:{txt}" - gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( - inputs=i_say, inputs_show_user=inputs_show_user, - llm_kwargs=llm_kwargs, chatbot=chatbot, history=[], - sys_prompt="你是一个学术翻译,请从数据中提取信息。你必须使用Markdown格式。你必须逐个文献进行处理。" - ) - - history.extend([ "第一批", gpt_say ]) - meta_paper_info_list = meta_paper_info_list[10:] + history.extend([ f"第{batch+1}批", gpt_say ]) + meta_paper_info_list = meta_paper_info_list[batchsize:] chatbot.append(["状态?", "已经全部完成,您可以试试让AI写一个Related Works,例如您可以继续输入Write a \"Related Works\" section about \"你搜索的研究领域\" for me."]) From d1efbd26da8c08f20cda792bf15ac685e461541a Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Mon, 24 Apr 2023 11:48:39 +0800 Subject: [PATCH 50/52] =?UTF-8?q?=E4=BF=AE=E6=AD=A3prompt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functions/谷歌检索小助手.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crazy_functions/谷歌检索小助手.py b/crazy_functions/谷歌检索小助手.py index 2e2d3d16..11a8da57 100644 --- a/crazy_functions/谷歌检索小助手.py +++ b/crazy_functions/谷歌检索小助手.py @@ -85,7 +85,7 @@ def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst batchsize = 7 for batch in range(len(meta_paper_info_list)//batchsize): if len(meta_paper_info_list[:batchsize]) > 0: - i_say = "下面是一些学术文献的数据,提取出以下内容,使用Markdown格式输出:" + \ + i_say = "下面是一些学术文献的数据,提取出以下内容:" + \ "1、英文题目;2、中文题目翻译;3、作者;4、arxiv公开(is_paper_in_arxiv);4、引用数量(cite);5、中文摘要翻译。" + \ f"以下是信息源:{str(meta_paper_info_list[:batchsize])}" @@ -93,7 +93,7 @@ def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( inputs=i_say, inputs_show_user=inputs_show_user, llm_kwargs=llm_kwargs, chatbot=chatbot, history=[], - sys_prompt="你是一个学术翻译,请从数据中提取信息。你必须使用Markdown格式。你必须逐个文献进行处理。" + sys_prompt="你是一个学术翻译,请从数据中提取信息。你必须使用Markdown表格。你必须逐个文献进行处理。" ) history.extend([ f"第{batch+1}批", gpt_say ]) From 6595ab813e4de8554a1eeef46e2e32429e4db0a4 Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Mon, 24 Apr 2023 11:54:15 +0800 Subject: [PATCH 51/52] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E8=AE=A1=E6=95=B0?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crazy_functions/谷歌检索小助手.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crazy_functions/谷歌检索小助手.py b/crazy_functions/谷歌检索小助手.py index 11a8da57..b9e1f8e3 100644 --- a/crazy_functions/谷歌检索小助手.py +++ b/crazy_functions/谷歌检索小助手.py @@ -70,6 +70,7 @@ def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst # 尝试导入依赖,如果缺少依赖,则给出安装建议 try: import arxiv + import math from bs4 import BeautifulSoup except: report_execption(chatbot, history, @@ -80,10 +81,9 @@ def 谷歌检索小助手(txt, llm_kwargs, plugin_kwargs, chatbot, history, syst # 清空历史,以免输入溢出 history = [] - meta_paper_info_list = yield from get_meta_information(txt, chatbot, history) - batchsize = 7 - for batch in range(len(meta_paper_info_list)//batchsize): + batchsize = 5 + for batch in range(math.ceil(len(meta_paper_info_list)/batchsize)): if len(meta_paper_info_list[:batchsize]) > 0: i_say = "下面是一些学术文献的数据,提取出以下内容:" + \ "1、英文题目;2、中文题目翻译;3、作者;4、arxiv公开(is_paper_in_arxiv);4、引用数量(cite);5、中文摘要翻译。" + \ From b3e5cdb3a54b801e2df1186aa62b98740eeecf83 Mon Sep 17 00:00:00 2001 From: binary-husky <505030475@qq.com> Date: Mon, 24 Apr 2023 12:08:42 +0800 Subject: [PATCH 52/52] =?UTF-8?q?=E5=8A=A0=E4=B8=80=E4=BA=9B=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- request_llm/bridge_chatglm.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/request_llm/bridge_chatglm.py b/request_llm/bridge_chatglm.py index 8eef3228..fb44043c 100644 --- a/request_llm/bridge_chatglm.py +++ b/request_llm/bridge_chatglm.py @@ -32,6 +32,7 @@ class GetGLMHandle(Process): return self.chatglm_model is not None def run(self): + # 子进程执行 # 第一次运行,加载参数 retry = 0 while True: @@ -53,17 +54,24 @@ class GetGLMHandle(Process): self.child.send('[Local Message] Call ChatGLM fail 不能正常加载ChatGLM的参数。') raise RuntimeError("不能正常加载ChatGLM的参数!") - # 进入任务等待状态 while True: + # 进入任务等待状态 kwargs = self.child.recv() + # 收到消息,开始请求 try: for response, history in self.chatglm_model.stream_chat(self.chatglm_tokenizer, **kwargs): self.child.send(response) + # # 中途接收可能的终止指令(如果有的话) + # if self.child.poll(): + # command = self.child.recv() + # if command == '[Terminate]': break except: self.child.send('[Local Message] Call ChatGLM fail.') + # 请求处理结束,开始下一个循环 self.child.send('[Finish]') def stream_chat(self, **kwargs): + # 主进程执行 self.parent.send(kwargs) while True: res = self.parent.recv() @@ -130,14 +138,17 @@ def predict(inputs, llm_kwargs, plugin_kwargs, chatbot, history=[], system_promp if "PreProcess" in core_functional[additional_fn]: inputs = core_functional[additional_fn]["PreProcess"](inputs) # 获取预处理函数(如果有的话) inputs = core_functional[additional_fn]["Prefix"] + inputs + core_functional[additional_fn]["Suffix"] + # 处理历史信息 history_feedin = [] history_feedin.append(["What can I do?", system_prompt] ) for i in range(len(history)//2): history_feedin.append([history[2*i], history[2*i+1]] ) + # 开始接收chatglm的回复 for response in glm_handle.stream_chat(query=inputs, history=history_feedin, max_length=llm_kwargs['max_length'], top_p=llm_kwargs['top_p'], temperature=llm_kwargs['temperature']): chatbot[-1] = (inputs, response) yield from update_ui(chatbot=chatbot, history=history) + # 总结输出 history.extend([inputs, response]) - yield from update_ui(chatbot=chatbot, history=history) \ No newline at end of file + yield from update_ui(chatbot=chatbot, history=history)