diff --git a/crazy_functional.py b/crazy_functional.py index f63bca26..317bdce0 100644 --- a/crazy_functional.py +++ b/crazy_functional.py @@ -36,7 +36,7 @@ def get_crazy_functions(): from crazy_functions.Latex全文润色 import Latex英文纠错 from crazy_functions.Markdown_Translate import Markdown中译英 from crazy_functions.虚空终端 import 虚空终端 - from crazy_functions.生成多种Mermaid图表 import 生成多种Mermaid图表 + from crazy_functions.生成多种Mermaid图表 import Mermaid_Gen from crazy_functions.PDF_Translate_Wrap import PDF_Tran from crazy_functions.Latex_Function import Latex英文纠错加PDF对比 from crazy_functions.Latex_Function import Latex翻译中文并重新编译PDF @@ -84,9 +84,8 @@ def get_crazy_functions(): "Color": "stop", "AsButton": False, "Info" : "基于当前对话或文件生成多种Mermaid图表,图表类型由模型判断", - "Function": HotReload(生成多种Mermaid图表), - "AdvancedArgs": True, - "ArgsReminder": "请输入图类型对应的数字,不输入则为模型自行判断:1-流程图,2-序列图,3-类图,4-饼图,5-甘特图,6-状态图,7-实体关系图,8-象限提示图,9-思维导图", + "Function": None, + "Class": Mermaid_Gen }, "批量总结Word文档": { "Group": "学术", diff --git a/crazy_functions/生成多种Mermaid图表.py b/crazy_functions/生成多种Mermaid图表.py index a53fad5e..677ddf8f 100644 --- a/crazy_functions/生成多种Mermaid图表.py +++ b/crazy_functions/生成多种Mermaid图表.py @@ -1,8 +1,11 @@ from toolbox import CatchException, update_ui, report_exception from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive -import datetime +from crazy_functions.plugin_template.plugin_class_template import ( + GptAcademicPluginTemplate, +) +from crazy_functions.plugin_template.plugin_class_template import ArgProperty -#以下是每类图表的PROMPT +# 以下是每类图表的PROMPT SELECT_PROMPT = """ “{subject}” ============= @@ -17,22 +20,24 @@ SELECT_PROMPT = """ 8 象限提示图 不需要解释原因,仅需要输出单个不带任何标点符号的数字。 """ -#没有思维导图!!!测试发现模型始终会优先选择思维导图 -#流程图 +# 没有思维导图!!!测试发现模型始终会优先选择思维导图 +# 流程图 PROMPT_1 = """ -请你给出围绕“{subject}”的逻辑关系图,使用mermaid语法,mermaid语法举例: +请你给出围绕“{subject}”的逻辑关系图,使用mermaid语法,注意需要使用双引号将内容括起来。 +mermaid语法举例: ```mermaid graph TD - P(编程) --> L1(Python) - P(编程) --> L2(C) - P(编程) --> L3(C++) - P(编程) --> L4(Javascipt) - P(编程) --> L5(PHP) + P("编程") --> L1("Python") + P("编程") --> L2("C") + P("编程") --> L3("C++") + P("编程") --> L4("Javascipt") + P("编程") --> L5("PHP") ``` """ -#序列图 +# 序列图 PROMPT_2 = """ -请你给出围绕“{subject}”的序列图,使用mermaid语法,mermaid语法举例: +请你给出围绕“{subject}”的序列图,使用mermaid语法。 +mermaid语法举例: ```mermaid sequenceDiagram participant A as 用户 @@ -43,9 +48,10 @@ sequenceDiagram B->>A: 返回数据 ``` """ -#类图 +# 类图 PROMPT_3 = """ -请你给出围绕“{subject}”的类图,使用mermaid语法,mermaid语法举例: +请你给出围绕“{subject}”的类图,使用mermaid语法。 +mermaid语法举例: ```mermaid classDiagram Class01 <|-- AveryLongClass : Cool @@ -63,9 +69,10 @@ classDiagram Class08 <--> C2: Cool label ``` """ -#饼图 +# 饼图 PROMPT_4 = """ -请你给出围绕“{subject}”的饼图,使用mermaid语法,mermaid语法举例: +请你给出围绕“{subject}”的饼图,使用mermaid语法,注意需要使用双引号将内容括起来。 +mermaid语法举例: ```mermaid pie title Pets adopted by volunteers "狗" : 386 @@ -73,38 +80,41 @@ pie title Pets adopted by volunteers "兔子" : 15 ``` """ -#甘特图 +# 甘特图 PROMPT_5 = """ -请你给出围绕“{subject}”的甘特图,使用mermaid语法,mermaid语法举例: +请你给出围绕“{subject}”的甘特图,使用mermaid语法,注意需要使用双引号将内容括起来。 +mermaid语法举例: ```mermaid gantt - title 项目开发流程 + title "项目开发流程" dateFormat YYYY-MM-DD - section 设计 - 需求分析 :done, des1, 2024-01-06,2024-01-08 - 原型设计 :active, des2, 2024-01-09, 3d - UI设计 : des3, after des2, 5d - section 开发 - 前端开发 :2024-01-20, 10d - 后端开发 :2024-01-20, 10d + section "设计" + "需求分析" :done, des1, 2024-01-06,2024-01-08 + "原型设计" :active, des2, 2024-01-09, 3d + "UI设计" : des3, after des2, 5d + section "开发" + "前端开发" :2024-01-20, 10d + "后端开发" :2024-01-20, 10d ``` """ -#状态图 +# 状态图 PROMPT_6 = """ -请你给出围绕“{subject}”的状态图,使用mermaid语法,mermaid语法举例: +请你给出围绕“{subject}”的状态图,使用mermaid语法,注意需要使用双引号将内容括起来。 +mermaid语法举例: ```mermaid stateDiagram-v2 - [*] --> Still - Still --> [*] - Still --> Moving - Moving --> Still - Moving --> Crash - Crash --> [*] + [*] --> "Still" + "Still" --> [*] + "Still" --> "Moving" + "Moving" --> "Still" + "Moving" --> "Crash" + "Crash" --> [*] ``` """ -#实体关系图 +# 实体关系图 PROMPT_7 = """ -请你给出围绕“{subject}”的实体关系图,使用mermaid语法,mermaid语法举例: +请你给出围绕“{subject}”的实体关系图,使用mermaid语法。 +mermaid语法举例: ```mermaid erDiagram CUSTOMER ||--o{ ORDER : places @@ -124,118 +134,173 @@ erDiagram } ``` """ -#象限提示图 +# 象限提示图 PROMPT_8 = """ -请你给出围绕“{subject}”的象限图,使用mermaid语法,mermaid语法举例: +请你给出围绕“{subject}”的象限图,使用mermaid语法,注意需要使用双引号将内容括起来。 +mermaid语法举例: ```mermaid graph LR - A[Hard skill] --> B(Programming) - A[Hard skill] --> C(Design) - D[Soft skill] --> E(Coordination) - D[Soft skill] --> F(Communication) + A["Hard skill"] --> B("Programming") + A["Hard skill"] --> C("Design") + D["Soft skill"] --> E("Coordination") + D["Soft skill"] --> F("Communication") ``` """ -#思维导图 +# 思维导图 PROMPT_9 = """ {subject} ========== -请给出上方内容的思维导图,充分考虑其之间的逻辑,使用mermaid语法,mermaid语法举例: +请给出上方内容的思维导图,充分考虑其之间的逻辑,使用mermaid语法,注意需要使用双引号将内容括起来。 +mermaid语法举例: ```mermaid mindmap root((mindmap)) - Origins - Long history + ("Origins") + ("Long history") ::icon(fa fa-book) - Popularisation - British popular psychology author Tony Buzan - Research - On effectiveness
and features - On Automatic creation - Uses - Creative techniques - Strategic planning - Argument mapping - Tools - Pen and paper - Mermaid + ("Popularisation") + ("British popular psychology author Tony Buzan") + ::icon(fa fa-user) + ("Research") + ("On effectiveness
and features") + ::icon(fa fa-search) + ("On Automatic creation") + ::icon(fa fa-robot) + ("Uses") + ("Creative techniques") + ::icon(fa fa-lightbulb-o) + ("Strategic planning") + ::icon(fa fa-flag) + ("Argument mapping") + ::icon(fa fa-comments) + ("Tools") + ("Pen and paper") + ::icon(fa fa-pencil) + ("Mermaid") + ::icon(fa fa-code) ``` """ -def 解析历史输入(history,llm_kwargs,file_manifest,chatbot,plugin_kwargs): + +def 解析历史输入(history, llm_kwargs, file_manifest, chatbot, plugin_kwargs): ############################## <第 0 步,切割输入> ################################## # 借用PDF切割中的函数对文本进行切割 TOKEN_LIMIT_PER_FRAGMENT = 2500 - txt = str(history).encode('utf-8', 'ignore').decode() # avoid reading non-utf8 chars - from crazy_functions.pdf_fns.breakdown_txt import breakdown_text_to_satisfy_token_limit - txt = breakdown_text_to_satisfy_token_limit(txt=txt, limit=TOKEN_LIMIT_PER_FRAGMENT, llm_model=llm_kwargs['llm_model']) + txt = ( + str(history).encode("utf-8", "ignore").decode() + ) # avoid reading non-utf8 chars + from crazy_functions.pdf_fns.breakdown_txt import ( + breakdown_text_to_satisfy_token_limit, + ) + + txt = breakdown_text_to_satisfy_token_limit( + txt=txt, limit=TOKEN_LIMIT_PER_FRAGMENT, llm_model=llm_kwargs["llm_model"] + ) ############################## <第 1 步,迭代地历遍整个文章,提取精炼信息> ################################## results = [] MAX_WORD_TOTAL = 4096 n_txt = len(txt) last_iteration_result = "从以下文本中提取摘要。" - if n_txt >= 20: print('文章极长,不能达到预期效果') + if n_txt >= 20: + print("文章极长,不能达到预期效果") for i in range(n_txt): NUM_OF_WORD = MAX_WORD_TOTAL // n_txt i_say = f"Read this section, recapitulate the content of this section with less than {NUM_OF_WORD} words in Chinese: {txt[i]}" i_say_show_user = f"[{i+1}/{n_txt}] Read this section, recapitulate the content of this section with less than {NUM_OF_WORD} words: {txt[i][:200]} ...." - gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive(i_say, i_say_show_user, # i_say=真正给chatgpt的提问, i_say_show_user=给用户看的提问 - llm_kwargs, chatbot, - history=["The main content of the previous section is?", last_iteration_result], # 迭代上一次的结果 - sys_prompt="Extracts the main content from the text section where it is located for graphing purposes, answer me with Chinese." # 提示 - ) + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( + i_say, + i_say_show_user, # i_say=真正给chatgpt的提问, i_say_show_user=给用户看的提问 + llm_kwargs, + chatbot, + history=[ + "The main content of the previous section is?", + last_iteration_result, + ], # 迭代上一次的结果 + sys_prompt="Extracts the main content from the text section where it is located for graphing purposes, answer me with Chinese.", # 提示 + ) results.append(gpt_say) last_iteration_result = gpt_say ############################## <第 2 步,根据整理的摘要选择图表类型> ################################## - if ("advanced_arg" in plugin_kwargs) and (plugin_kwargs["advanced_arg"] == ""): plugin_kwargs.pop("advanced_arg") - gpt_say = plugin_kwargs.get("advanced_arg", "") #将图表类型参数赋值为插件参数 - results_txt = '\n'.join(results) #合并摘要 - if gpt_say not in ['1','2','3','4','5','6','7','8','9']: #如插件参数不正确则使用对话模型判断 - i_say_show_user = f'接下来将判断适合的图表类型,如连续3次判断失败将会使用流程图进行绘制'; gpt_say = "[Local Message] 收到。" # 用户提示 - chatbot.append([i_say_show_user, gpt_say]); yield from update_ui(chatbot=chatbot, history=[]) # 更新UI + gpt_say = str(plugin_kwargs) # 将图表类型参数赋值为插件参数 + results_txt = "\n".join(results) # 合并摘要 + if gpt_say not in [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + ]: # 如插件参数不正确则使用对话模型判断 + i_say_show_user = ( + f"接下来将判断适合的图表类型,如连续3次判断失败将会使用流程图进行绘制" + ) + gpt_say = "[Local Message] 收到。" # 用户提示 + chatbot.append([i_say_show_user, gpt_say]) + yield from update_ui(chatbot=chatbot, history=[]) # 更新UI i_say = SELECT_PROMPT.format(subject=results_txt) i_say_show_user = f'请判断适合使用的流程图类型,其中数字对应关系为:1-流程图,2-序列图,3-类图,4-饼图,5-甘特图,6-状态图,7-实体关系图,8-象限提示图。由于不管提供文本是什么,模型大概率认为"思维导图"最合适,因此思维导图仅能通过参数调用。' for i in range(3): gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( inputs=i_say, inputs_show_user=i_say_show_user, - llm_kwargs=llm_kwargs, chatbot=chatbot, history=[], - sys_prompt="" + llm_kwargs=llm_kwargs, + chatbot=chatbot, + history=[], + sys_prompt="", ) - if gpt_say in ['1','2','3','4','5','6','7','8','9']: #判断返回是否正确 + if gpt_say in [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + ]: # 判断返回是否正确 break - if gpt_say not in ['1','2','3','4','5','6','7','8','9']: - gpt_say = '1' + if gpt_say not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]: + gpt_say = "1" ############################## <第 3 步,根据选择的图表类型绘制图表> ################################## - if gpt_say == '1': + if gpt_say == "1": i_say = PROMPT_1.format(subject=results_txt) - elif gpt_say == '2': + elif gpt_say == "2": i_say = PROMPT_2.format(subject=results_txt) - elif gpt_say == '3': + elif gpt_say == "3": i_say = PROMPT_3.format(subject=results_txt) - elif gpt_say == '4': + elif gpt_say == "4": i_say = PROMPT_4.format(subject=results_txt) - elif gpt_say == '5': + elif gpt_say == "5": i_say = PROMPT_5.format(subject=results_txt) - elif gpt_say == '6': + elif gpt_say == "6": i_say = PROMPT_6.format(subject=results_txt) - elif gpt_say == '7': - i_say = PROMPT_7.replace("{subject}", results_txt) #由于实体关系图用到了{}符号 - elif gpt_say == '8': + elif gpt_say == "7": + i_say = PROMPT_7.replace("{subject}", results_txt) # 由于实体关系图用到了{}符号 + elif gpt_say == "8": i_say = PROMPT_8.format(subject=results_txt) - elif gpt_say == '9': + elif gpt_say == "9": i_say = PROMPT_9.format(subject=results_txt) - i_say_show_user = f'请根据判断结果绘制相应的图表。如需绘制思维导图请使用参数调用,同时过大的图表可能需要复制到在线编辑器中进行渲染。' + i_say_show_user = f"请根据判断结果绘制相应的图表。如需绘制思维导图请使用参数调用,同时过大的图表可能需要复制到在线编辑器中进行渲染。" gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( inputs=i_say, inputs_show_user=i_say_show_user, - llm_kwargs=llm_kwargs, chatbot=chatbot, history=[], - sys_prompt="" + llm_kwargs=llm_kwargs, + chatbot=chatbot, + history=[], + sys_prompt="", ) history.append(gpt_say) - yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新 + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新 + @CatchException -def 生成多种Mermaid图表(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port): +def 生成多种Mermaid图表( + txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, web_port +): """ txt 输入栏用户输入的文本,例如需要翻译的一段话,再例如一个包含了待处理文件的路径 llm_kwargs gpt模型参数,如温度和top_p等,一般原样传递下去就行 @@ -248,15 +313,21 @@ def 生成多种Mermaid图表(txt, llm_kwargs, plugin_kwargs, chatbot, history, import os # 基本信息:功能、贡献者 - chatbot.append([ - "函数插件功能?", - "根据当前聊天历史或指定的路径文件(文件内容优先)绘制多种mermaid图表,将会由对话模型首先判断适合的图表类型,随后绘制图表。\ - \n您也可以使用插件参数指定绘制的图表类型,函数插件贡献者: Menghuan1918"]) - yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + chatbot.append( + [ + "函数插件功能?", + "根据当前聊天历史或指定的路径文件(文件内容优先)绘制多种mermaid图表,将会由对话模型首先判断适合的图表类型,随后绘制图表。\ + \n您也可以使用插件参数指定绘制的图表类型,函数插件贡献者: Menghuan1918", + ] + ) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 - if os.path.exists(txt): #如输入区无内容则直接解析历史记录 + if os.path.exists(txt): # 如输入区无内容则直接解析历史记录 from crazy_functions.pdf_fns.parse_word import extract_text_from_files - file_exist, final_result, page_one, file_manifest, excption = extract_text_from_files(txt, chatbot, history) + + file_exist, final_result, page_one, file_manifest, excption = ( + extract_text_from_files(txt, chatbot, history) + ) else: file_exist = False excption = "" @@ -264,33 +335,104 @@ def 生成多种Mermaid图表(txt, llm_kwargs, plugin_kwargs, chatbot, history, if excption != "": if excption == "word": - report_exception(chatbot, history, - a = f"解析项目: {txt}", - b = f"找到了.doc文件,但是该文件格式不被支持,请先转化为.docx格式。") + report_exception( + chatbot, + history, + a=f"解析项目: {txt}", + b=f"找到了.doc文件,但是该文件格式不被支持,请先转化为.docx格式。", + ) elif excption == "pdf": - report_exception(chatbot, history, - a = f"解析项目: {txt}", - b = f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade pymupdf```。") + report_exception( + chatbot, + history, + a=f"解析项目: {txt}", + b=f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade pymupdf```。", + ) elif excption == "word_pip": - report_exception(chatbot, history, - a=f"解析项目: {txt}", - b=f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade python-docx pywin32```。") + report_exception( + chatbot, + history, + a=f"解析项目: {txt}", + b=f"导入软件依赖失败。使用该模块需要额外依赖,安装方法```pip install --upgrade python-docx pywin32```。", + ) - yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 else: if not file_exist: - history.append(txt) #如输入区不是文件则将输入区内容加入历史记录 - i_say_show_user = f'首先你从历史记录中提取摘要。'; gpt_say = "[Local Message] 收到。" # 用户提示 - chatbot.append([i_say_show_user, gpt_say]); yield from update_ui(chatbot=chatbot, history=history) # 更新UI - yield from 解析历史输入(history,llm_kwargs,file_manifest,chatbot,plugin_kwargs) + history.append(txt) # 如输入区不是文件则将输入区内容加入历史记录 + i_say_show_user = f"首先你从历史记录中提取摘要。" + gpt_say = "[Local Message] 收到。" # 用户提示 + chatbot.append([i_say_show_user, gpt_say]) + yield from update_ui(chatbot=chatbot, history=history) # 更新UI + yield from 解析历史输入( + history, llm_kwargs, file_manifest, chatbot, plugin_kwargs + ) else: file_num = len(file_manifest) - for i in range(file_num): #依次处理文件 - i_say_show_user = f"[{i+1}/{file_num}]处理文件{file_manifest[i]}"; gpt_say = "[Local Message] 收到。" # 用户提示 - chatbot.append([i_say_show_user, gpt_say]); yield from update_ui(chatbot=chatbot, history=history) # 更新UI - history = [] #如输入区内容为文件则清空历史记录 + for i in range(file_num): # 依次处理文件 + i_say_show_user = f"[{i+1}/{file_num}]处理文件{file_manifest[i]}" + gpt_say = "[Local Message] 收到。" # 用户提示 + chatbot.append([i_say_show_user, gpt_say]) + yield from update_ui(chatbot=chatbot, history=history) # 更新UI + history = [] # 如输入区内容为文件则清空历史记录 history.append(final_result[i]) - yield from 解析历史输入(history,llm_kwargs,file_manifest,chatbot,plugin_kwargs) \ No newline at end of file + yield from 解析历史输入( + history, llm_kwargs, file_manifest, chatbot, plugin_kwargs + ) + + +class Mermaid_Gen(GptAcademicPluginTemplate): + def __init__(self): + pass + + def define_arg_selection_menu(self): + gui_definition = { + "Type_of_Mermaid": ArgProperty( + title="绘制的Mermaid图表类型", + options=[ + "由LLM决定", + "流程图", + "序列图", + "类图", + "饼图", + "甘特图", + "状态图", + "实体关系图", + "象限提示图", + "思维导图", + ], + default_value="由LLM决定", + description="选择'由LLM决定'时将由对话模型判断适合的图表类型(不包括思维导图),选择其他类型时将直接绘制指定的图表类型。", + type="dropdown", + ).model_dump_json(), + } + return gui_definition + + def execute( + txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, user_request + ): + options = [ + "由LLM决定", + "流程图", + "序列图", + "类图", + "饼图", + "甘特图", + "状态图", + "实体关系图", + "象限提示图", + "思维导图", + ] + plugin_kwargs = options.index(plugin_kwargs['Type_of_Mermaid']) + yield from 生成多种Mermaid图表( + txt, + llm_kwargs, + plugin_kwargs, + chatbot, + history, + system_prompt, + user_request, + )