From ca238daa8ca362080feee631c3e5f723ac0a268d Mon Sep 17 00:00:00 2001 From: Menghuan1918 Date: Tue, 23 Jul 2024 00:55:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E8=81=94=E7=BD=91=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=8F=92=E4=BB=B6-=E6=96=B0=E5=A2=9E=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=A8=A1=E5=BC=8F=EF=BC=8C=E6=90=9C=E7=B4=A2=E5=A2=9E?= =?UTF-8?q?=E5=BC=BA=20(#1874)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change default to Mixed option * Add option optimizer * Add search optimizer prompts * Enhanced Processing * Finish search_optimizer part * prompts bug fix * Bug fix --- crazy_functions/Internet_GPT.py | 171 +++++++++++++++++++++--- crazy_functions/Internet_GPT_Wrap.py | 9 +- crazy_functions/prompts/Internet_GPT.py | 87 ++++++++++++ 3 files changed, 244 insertions(+), 23 deletions(-) create mode 100644 crazy_functions/prompts/Internet_GPT.py diff --git a/crazy_functions/Internet_GPT.py b/crazy_functions/Internet_GPT.py index 840990fd..b43cdd48 100644 --- a/crazy_functions/Internet_GPT.py +++ b/crazy_functions/Internet_GPT.py @@ -3,10 +3,106 @@ from .crazy_utils import request_gpt_model_in_new_thread_with_ui_alive, input_cl import requests from bs4 import BeautifulSoup from request_llms.bridge_all import model_info -import urllib.request import random from functools import lru_cache from check_proxy import check_proxy +from request_llms.bridge_all import predict_no_ui_long_connection +from .prompts.Internet_GPT import Search_optimizer, Search_academic_optimizer +import time +import re +import json +from itertools import zip_longest + +def search_optimizer( + query, + proxies, + history, + llm_kwargs, + optimizer=1, + categories="general", + searxng_url=None, + engines=None, +): + # ------------- < 第1步:尝试进行搜索优化 > ------------- + # * 增强优化,会尝试结合历史记录进行搜索优化 + if optimizer == 2: + his = " " + if len(history) == 0: + pass + else: + for i, h in enumerate(history): + if i % 2 == 0: + his += f"Q: {h}\n" + else: + his += f"A: {h}\n" + if categories == "general": + sys_prompt = Search_optimizer.format(query=query, history=his, num=4) + elif categories == "science": + sys_prompt = Search_academic_optimizer.format(query=query, history=his, num=4) + else: + his = " " + if categories == "general": + sys_prompt = Search_optimizer.format(query=query, history=his, num=3) + elif categories == "science": + sys_prompt = Search_academic_optimizer.format(query=query, history=his, num=3) + + mutable = ["", time.time(), ""] + llm_kwargs["temperature"] = 0.8 + try: + querys_json = predict_no_ui_long_connection( + inputs=query, + llm_kwargs=llm_kwargs, + history=[], + sys_prompt=sys_prompt, + observe_window=mutable, + ) + except Exception: + querys_json = "1234" + #* 尝试解码优化后的搜索结果 + querys_json = re.sub(r"```json|```", "", querys_json) + try: + querys = json.loads(querys_json) + except Exception: + #* 如果解码失败,降低温度再试一次 + try: + llm_kwargs["temperature"] = 0.4 + querys_json = predict_no_ui_long_connection( + inputs=query, + llm_kwargs=llm_kwargs, + history=[], + sys_prompt=sys_prompt, + observe_window=mutable, + ) + querys_json = re.sub(r"```json|```", "", querys_json) + querys = json.loads(querys_json) + except Exception: + #* 如果再次失败,直接返回原始问题 + querys = [query] + links = [] + success = 0 + Exceptions = "" + for q in querys: + try: + link = searxng_request(q, proxies, categories, searxng_url, engines=engines) + if len(link) > 0: + links.append(link[:-5]) + success += 1 + except Exception: + Exceptions = Exception + pass + if success == 0: + raise ValueError(f"在线搜索失败!\n{Exceptions}") + # * 清洗搜索结果,依次放入每组第一,第二个搜索结果,并清洗重复的搜索结果 + seen_links = set() + result = [] + for tuple in zip_longest(*links, fillvalue=None): + for item in tuple: + if item is not None: + link = item["link"] + if link not in seen_links: + seen_links.add(link) + result.append(item) + return result @lru_cache def get_auth_ip(): @@ -21,8 +117,8 @@ def searxng_request(query, proxies, categories='general', searxng_url=None, engi else: url = searxng_url - if engines is None: - engines = 'bing' + if engines == "Mixed": + engines = None if categories == 'general': params = { @@ -95,7 +191,7 @@ def scrape_text(url, proxies) -> str: @CatchException def 连接网络回答问题(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, user_request): - + optimizer_history = history[:-8] history = [] # 清空历史,以免输入溢出 chatbot.append((f"请结合互联网信息回答以下问题:{txt}", "检索中...")) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 @@ -106,16 +202,23 @@ def 连接网络回答问题(txt, llm_kwargs, plugin_kwargs, chatbot, history, s categories = plugin_kwargs.get('categories', 'general') searxng_url = plugin_kwargs.get('searxng_url', None) engines = plugin_kwargs.get('engine', None) - urls = searxng_request(txt, proxies, categories, searxng_url, engines=engines) + optimizer = plugin_kwargs.get('optimizer', 0) + if optimizer == 0: + urls = searxng_request(txt, proxies, categories, searxng_url, engines=engines) + else: + urls = search_optimizer(txt, proxies, optimizer_history, llm_kwargs, optimizer, categories, searxng_url, engines) history = [] if len(urls) == 0: chatbot.append((f"结论:{txt}", "[Local Message] 受到限制,无法从searxng获取信息!请尝试更换搜索引擎。")) yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 return + # ------------- < 第2步:依次访问网页 > ------------- max_search_result = 5 # 最多收纳多少个网页的结果 - chatbot.append([f"联网检索中 ...", None]) + if optimizer == 2: + max_search_result = 8 + chatbot.append(["联网检索中 ...", None]) for index, url in enumerate(urls[:max_search_result]): res = scrape_text(url['link'], proxies) prefix = f"第{index}份搜索结果 [源自{url['source'][0]}搜索] ({url['title'][:25]}):" @@ -125,18 +228,46 @@ def 连接网络回答问题(txt, llm_kwargs, plugin_kwargs, chatbot, history, s yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # ------------- < 第3步:ChatGPT综合 > ------------- - i_say = f"从以上搜索结果中抽取信息,然后回答问题:{txt}" - i_say, history = input_clipping( # 裁剪输入,从最长的条目开始裁剪,防止爆token - inputs=i_say, - history=history, - max_token_limit=min(model_info[llm_kwargs['llm_model']]['max_token']*3//4, 8192) - ) - gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( - inputs=i_say, inputs_show_user=i_say, - llm_kwargs=llm_kwargs, chatbot=chatbot, history=history, - sys_prompt="请从给定的若干条搜索结果中抽取信息,对最相关的两个搜索结果进行总结,然后回答问题。" - ) - chatbot[-1] = (i_say, gpt_say) - history.append(i_say);history.append(gpt_say) - yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新 + if (optimizer == 0 or optimizer == 1): + i_say = f"从以上搜索结果中抽取信息,然后回答问题:{txt}" + i_say, history = input_clipping( # 裁剪输入,从最长的条目开始裁剪,防止爆token + inputs=i_say, + history=history, + max_token_limit=min(model_info[llm_kwargs['llm_model']]['max_token']*3//4, 8192) + ) + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( + inputs=i_say, inputs_show_user=i_say, + llm_kwargs=llm_kwargs, chatbot=chatbot, history=history, + sys_prompt="请从给定的若干条搜索结果中抽取信息,对最相关的两个搜索结果进行总结,然后回答问题。" + ) + chatbot[-1] = (i_say, gpt_say) + history.append(i_say);history.append(gpt_say) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新 + #* 或者使用搜索优化器,这样可以保证后续问答能读取到有效的历史记录 + else: + i_say = f"从以上搜索结果中抽取与问题:{txt} 相关的信息:" + i_say, history = input_clipping( # 裁剪输入,从最长的条目开始裁剪,防止爆token + inputs=i_say, + history=history, + max_token_limit=min(model_info[llm_kwargs['llm_model']]['max_token']*3//4, 8192) + ) + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( + inputs=i_say, inputs_show_user=i_say, + llm_kwargs=llm_kwargs, chatbot=chatbot, history=history, + sys_prompt="请从给定的若干条搜索结果中抽取信息,对最相关的三个搜索结果进行总结" + ) + chatbot[-1] = (i_say, gpt_say) + history = [] + history.append(i_say);history.append(gpt_say) + yield from update_ui(chatbot=chatbot, history=history) # 刷新界面 # 界面更新 + # ------------- < 第4步:根据综合回答问题 > ------------- + i_say = f"请根据以上搜索结果回答问题:{txt}" + gpt_say = yield from request_gpt_model_in_new_thread_with_ui_alive( + inputs=i_say, inputs_show_user=i_say, + llm_kwargs=llm_kwargs, chatbot=chatbot, history=history, + sys_prompt="请根据给定的若干条搜索结果回答问题" + ) + chatbot[-1] = (i_say, gpt_say) + history.append(i_say);history.append(gpt_say) + yield from update_ui(chatbot=chatbot, history=history) \ No newline at end of file diff --git a/crazy_functions/Internet_GPT_Wrap.py b/crazy_functions/Internet_GPT_Wrap.py index 8d3aa43f..dbc13af9 100644 --- a/crazy_functions/Internet_GPT_Wrap.py +++ b/crazy_functions/Internet_GPT_Wrap.py @@ -22,11 +22,13 @@ class NetworkGPT_Wrap(GptAcademicPluginTemplate): """ gui_definition = { "main_input": - ArgProperty(title="输入问题", description="待通过互联网检索的问题", default_value="", type="string").model_dump_json(), # 主输入,自动从输入框同步 + ArgProperty(title="输入问题", description="待通过互联网检索的问题,会自动读取输入框内容", default_value="", type="string").model_dump_json(), # 主输入,自动从输入框同步 "categories": ArgProperty(title="搜索分类", options=["网页", "学术论文"], default_value="网页", description="无", type="dropdown").model_dump_json(), "engine": - ArgProperty(title="选择搜索引擎", options=["bing", "google", "duckduckgo"], default_value="bing", description="无", type="dropdown").model_dump_json(), + ArgProperty(title="选择搜索引擎", options=["Mixed", "bing", "google", "duckduckgo"], default_value="Mixed", description="无", type="dropdown").model_dump_json(), + "optimizer": + ArgProperty(title="搜索优化", options=["关闭", "开启", "开启(增强)"], default_value="关闭", description="是否使用搜索增强。注意这可能会消耗较多token", type="dropdown").model_dump_json(), "searxng_url": ArgProperty(title="Searxng服务地址", description="输入Searxng的地址", default_value=get_conf("SEARXNG_URL"), type="string").model_dump_json(), # 主输入,自动从输入框同步 @@ -39,6 +41,7 @@ class NetworkGPT_Wrap(GptAcademicPluginTemplate): """ if plugin_kwargs["categories"] == "网页": plugin_kwargs["categories"] = "general" if plugin_kwargs["categories"] == "学术论文": plugin_kwargs["categories"] = "science" - + optimizer_options=["关闭", "开启", "开启(增强)"] + plugin_kwargs["optimizer"] = optimizer_options.index(plugin_kwargs["optimizer"]) yield from 连接网络回答问题(txt, llm_kwargs, plugin_kwargs, chatbot, history, system_prompt, user_request) diff --git a/crazy_functions/prompts/Internet_GPT.py b/crazy_functions/prompts/Internet_GPT.py new file mode 100644 index 00000000..a623808d --- /dev/null +++ b/crazy_functions/prompts/Internet_GPT.py @@ -0,0 +1,87 @@ +Search_optimizer="""作为一个网页搜索助手,你的任务是结合历史记录,从不同角度,为“原问题”生成个不同版本的“检索词”,从而提高网页检索的精度。生成的问题要求指向对象清晰明确,并与“原问题语言相同”。例如: +历史记录: +" +Q: 对话背景。 +A: 当前对话是关于 Nginx 的介绍和在Ubuntu上的使用等。 +" +原问题: 怎么下载 +检索词: ["Nginx 下载","Ubuntu Nginx","Ubuntu安装Nginx"] +---------------- +历史记录: +" +Q: 对话背景。 +A: 当前对话是关于 Nginx 的介绍和使用等。 +Q: 报错 "no connection" +A: 报错"no connection"可能是因为…… +" +原问题: 怎么解决 +检索词: ["Nginx报错"no connection" 解决","Nginx'no connection'报错 原因","Nginx提示'no connection'"] +---------------- +历史记录: +" + +" +原问题: 你知道 Python 么? +检索词: ["Python","Python 使用教程。","Python 特点和优势"] +---------------- +历史记录: +" +Q: 列出Java的三种特点? +A: 1. Java 是一种编译型语言。 + 2. Java 是一种面向对象的编程语言。 + 3. Java 是一种跨平台的编程语言。 +" +原问题: 介绍下第2点。 +检索词: ["Java 面向对象特点","Java 面向对象编程优势。","Java 面向对象编程"] +---------------- +现在有历史记录: +" +{history} +" +有其原问题: {query} +直接给出最多{num}个检索词,必须以json形式给出,不得有多余字符: +""" + +Search_academic_optimizer="""作为一个学术论文搜索助手,你的任务是结合历史记录,从不同角度,为“原问题”生成个不同版本的“检索词”,从而提高学术论文检索的精度。生成的问题要求指向对象清晰明确,并与“原问题语言相同”。例如: +历史记录: +" +Q: 对话背景。 +A: 当前对话是关于深度学习的介绍和在图像识别中的应用等。 +" +原问题: 怎么下载相关论文 +检索词: ["深度学习 图像识别 论文下载","图像识别 深度学习 研究论文","深度学习 图像识别 论文资源","Deep Learning Image Recognition Paper Download","Image Recognition Deep Learning Research Paper"] +---------------- +历史记录: +" +Q: 对话背景。 +A: 当前对话是关于深度学习的介绍和应用等。 +Q: 报错 "模型不收敛" +A: 报错"模型不收敛"可能是因为…… +" +原问题: 怎么解决 +检索词: ["深度学习 模型不收敛 解决方案 论文","深度学习 模型不收敛 原因 研究","深度学习 模型不收敛 论文","Deep Learning Model Convergence Issue Solution Paper","Deep Learning Model Convergence Problem Research"] +---------------- +历史记录: +" + +" +原问题: 你知道 GAN 么? +检索词: ["生成对抗网络 论文","GAN 使用教程 论文","GAN 特点和优势 研究","Generative Adversarial Network Paper","GAN Usage Tutorial Paper"] +---------------- +历史记录: +" +Q: 列出机器学习的三种应用? +A: 1. 机器学习在图像识别中的应用。 + 2. 机器学习在自然语言处理中的应用。 + 3. 机器学习在推荐系统中的应用。 +" +原问题: 介绍下第2点。 +检索词: ["机器学习 自然语言处理 应用 论文","机器学习 自然语言处理 研究","机器学习 NLP 应用 论文","Machine Learning Natural Language Processing Application Paper","Machine Learning NLP Research"] +---------------- +现在有历史记录: +" +{history} +" +有其原问题: {query} +直接给出最多{num}个检索词,必须以json形式给出,不得有多余字符: +""" \ No newline at end of file