diff --git a/erniebot-agent/cookbook/langchain_function_agent_with_retrieval.ipynb b/erniebot-agent/cookbook/langchain_function_agent_with_retrieval.ipynb index 0628da4cc..0d11ed921 100644 --- a/erniebot-agent/cookbook/langchain_function_agent_with_retrieval.ipynb +++ b/erniebot-agent/cookbook/langchain_function_agent_with_retrieval.ipynb @@ -482,9 +482,9 @@ ], "metadata": { "kernelspec": { - "display_name": "python310", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "py310" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -496,7 +496,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.9.12" } }, "nbformat": 4, diff --git a/erniebot-agent/cookbook/retrieval_agent.ipynb b/erniebot-agent/cookbook/retrieval_agent.ipynb new file mode 100644 index 000000000..4180a1da6 --- /dev/null +++ b/erniebot-agent/cookbook/retrieval_agent.ipynb @@ -0,0 +1,441 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "4d02aa9a-d7bb-4242-909c-7e41d05af1b8", + "metadata": {}, + "source": [ + "# 1. 使用langchain" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea8ea79b-4637-4a56-a169-d5947c9b0763", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install langchain" + ] + }, + { + "cell_type": "markdown", + "id": "32846bb2-6f4e-40a8-9171-57ba82bd6a1c", + "metadata": {}, + "source": [ + "# 2. 导入第三方库" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1af83f85-a984-44f7-b425-bd13367d68e1", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import tarfile\n", + "\n", + "from erniebot_agent.agents import RetrievalAgent\n", + "from erniebot_agent.chat_models import ERNIEBot\n", + "from erniebot_agent.memory import WholeMemory\n", + "from erniebot_agent.retrieval import BaizhongSearch\n", + "from erniebot_agent.tools.baizhong_tool import BaizhongSearchTool\n", + "from erniebot_agent.tools.langchain_retrieval_tool import LangChainRetrievalTool\n", + "from langchain.docstore.document import Document\n", + "from langchain.embeddings.openai import OpenAIEmbeddings\n", + "from langchain_community.vectorstores import FAISS\n", + "from langchain.document_loaders import PyPDFDirectoryLoader\n", + "from langchain.text_splitter import SpacyTextSplitter\n", + "from erniebot_agent.utils.common import download_file" + ] + }, + { + "cell_type": "markdown", + "id": "16f36ec4-912d-471c-ac76-f8b2e12530ce", + "metadata": {}, + "source": [ + "# 3. 预处理\n", + "\n", + "## 3.1 下载数据集" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "152e7da5-d124-46e9-b049-1be30c5259ab", + "metadata": {}, + "outputs": [], + "source": [ + "if not os.path.exists(\"construction_regulations\"):\n", + " file_path = \"construction_regulations.tar\"\n", + " download_file(\n", + " url=\"https://paddlenlp.bj.bcebos.com/datasets/examples/construction_regulations.tar\",\n", + " save_path=file_path,\n", + " )\n", + "\n", + " files = tarfile.open(file_path, \"r:*\")\n", + " file_dir = os.path.dirname(file_path)\n", + " files.extractall(file_dir, files.getmembers())\n", + "# ! wget https://paddlenlp.bj.bcebos.com/datasets/examples/construction_regulations.tar\n", + "# ! tar xvf construction_regulations.tar" + ] + }, + { + "cell_type": "markdown", + "id": "bbab23b1-679d-49f7-b763-d9b7cf1bd51a", + "metadata": {}, + "source": [ + "## 3.2 构建知识库" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "119fdb2b-7716-48be-a444-a2437ff55033", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/root/anaconda3/envs/py39/lib/python3.9/site-packages/langchain_core/_api/deprecation.py:115: LangChainDeprecationWarning: The class `OpenAIEmbeddings` was deprecated in LangChain 0.1.0 and will be removed in 0.2.0. Use langchain_openai.OpenAIEmbeddings instead.\n", + " warn_deprecated(\n" + ] + } + ], + "source": [ + "embeddings = OpenAIEmbeddings(deployment=\"text-embedding-ada\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "1a05a9e9-579e-440a-a87a-22fab69b61e3", + "metadata": {}, + "outputs": [], + "source": [ + "faiss_name = \"faiss_index\"\n", + "if os.path.exists(faiss_name):\n", + " db = FAISS.load_local(faiss_name, embeddings)\n", + "else:\n", + " loader = PyPDFDirectoryLoader(\"construction_regulations\")\n", + " documents = loader.load()\n", + " text_splitter = SpacyTextSplitter(pipeline=\"zh_core_web_sm\", chunk_size=320, chunk_overlap=0)\n", + " docs = text_splitter.split_documents(documents)\n", + " db = FAISS.from_documents(docs, embeddings)\n", + " db.save_local(faiss_name)" + ] + }, + { + "cell_type": "markdown", + "id": "09bdae76-4022-4688-ac0c-25e21095d59d", + "metadata": {}, + "source": [ + "# 4. 基于复杂Query分解的RetrievalAgent\n", + "## 4.1 复杂任务规划" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "716e4494-38fe-43f8-a4ff-6e02fc031fd4", + "metadata": {}, + "outputs": [], + "source": [ + "search_tool = LangChainRetrievalTool(db=db, threshold=0.0)\n", + "llm = ERNIEBot(model=\"ernie-3.5\", api_type=\"aistudio\")\n", + "memory = WholeMemory()\n", + "agent = RetrievalAgent(\n", + " knowledge_base=search_tool,\n", + " use_compressor=False,\n", + " llm=llm,\n", + " top_k=3,\n", + " tools=[],\n", + " memory=memory,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "84319cca-ad91-41e3-bc58-60b2437297c6", + "metadata": {}, + "outputs": [], + "source": [ + "query = \"住房和城乡建设部发布城市设计管理办法有哪些?\"\n", + "response = await agent.run(query)\n", + "response" + ] + }, + { + "cell_type": "markdown", + "id": "3c383106-96aa-4cd0-9d85-a1a97fef3726", + "metadata": {}, + "source": [ + "## 4.2 使用compressor压缩子query检索结果" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "8841c9a9-93dc-4b79-869f-fe538de57fa7", + "metadata": {}, + "outputs": [], + "source": [ + "memory = WholeMemory()\n", + "agent = RetrievalAgent(\n", + " knowledge_base=search_tool,\n", + " use_compressor=True,\n", + " llm=llm,\n", + " top_k=3,\n", + " tools=[],\n", + " memory=memory,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "59bbe7b4-5781-425b-bfdb-9e5b4e533431", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AgentResponse(text='住房和城乡建设部发布的城市设计管理办法包括以下内容:\\n\\n1. 第一条:为提高城市建设水平,塑造城市风貌特色,推进城市设计工作,完善城市规划建设管理,依据《中华人民共和国城乡规划法》等法律法规,制定本办法。\\n2. 第二条:城市、县人民政府所在地建制镇开展城市设计管理工作,适用本办法。\\n3. 第三条:城市设计是落实城市规划、指导建筑设计、塑造城市特色风貌的有效手段,贯穿于城市规划建设管理全过程。\\n4. 第五条:重点地区的控制性详细规划未体现城市设计内容和要求的,应当及时修改完善。\\n5. 第十五条:单体建筑设计和景观、市政工程方案设计应当符合城市设计要求。\\n6. 第二十条:城市、县人民政府城乡规划主管部门进行建筑设计方案审查和规划核实时,应当审核城市设计要求落实情况。\\n7. 第二十一条:城市、县人民政府城乡规划主管部门开展城市规划实施评估时,应当同时评估城市设计工作实施情况。\\n8. 第二十二条:城市设计的技术管理规定由国务院城乡规划主管部门另行制定。\\n9. 第二十三条:各地可根据本办法,按照实际情况,制定实施细则和技术导则。\\n10. 第二十四条:县人民政府所在地以外的镇可以参照本办法开展城市设计工作。\\n11. 第二十五条:本办法自2017年6月1日起施行。', chat_history=[, ], steps=[AgentStep(info={'query': '住房和城乡建设部发布城市设计管理办法有哪些内容?', 'name': 'sub query compressor 0'}, result={'content': '城市设计管理办法的内容包括:\\n\\n1. 第一条:为提高城市建设水平,塑造城市风貌特色,推进城市设计工作,完善城市规划建设管理,依据《中华人民共和国城乡规划法》等法律法规,制定本办法。\\n2. 第二条:城市、县人民政府所在地建制镇开展城市设计管理工作,适用本办法。\\n3. 第三条:城市设计是落实城市规划、指导建筑设计、塑造城市特色风貌的有效手段,贯穿于城市规划建设管理全过程。\\n4. 第五条:重点地区的控制性详细规划未体现城市设计内容和要求的,应当及时修改完善。\\n5. 第十五条:单体建筑设计和景观、市政工程方案设计应当符合城市设计要求。\\n6. 第二十条:城市、县人民政府城乡规划主管部门进行建筑设计方案审查和规划核实时,应当审核城市设计要求落实情况。\\n7. 第二十一条:城市、县人民政府城乡规划主管部门开展城市规划实施评估时,应当同时评估城市设计工作实施情况。\\n8. 第二十二条:城市设计的技术管理规定由国务院城乡规划主管部门另行制定。\\n9. 第二十三条:各地可根据本办法,按照实际情况,制定实施细则和技术导则。\\n10. 第二十四条:县人民政府所在地以外的镇可以参照本办法开展城市设计工作。\\n11. 第二十五条:本办法自2017年6月1日起施行。', 'score': 0.8939634392544421, 'meta': {'source': 'construction_regulations/城市设计管理办法.pdf', 'page': 0}, 'sub_query': '住房和城乡建设部发布城市设计管理办法有哪些内容?'}), AgentStep(info={'query': '城市设计管理办法有哪些?', 'name': 'sub query compressor 1'}, result={'content': '1. 城市设计管理办法有:\\n* 建立城市设计管理辅助决策系统\\n* 将城市设计要求纳入城市规划管理信息平台\\n* 城市设计分为总体城市设计和重点地区城市设计\\n* 总体城市设计应当确定城市风貌特色,保护自然山水格局,优化城市形态格局,明确公共空间体系,并可与城市(县人民政府所在地建制镇)总体规划一并报批\\n* 编制城市设计时,组织编制机关应当通过座谈、论证、网络等多种形式及渠道,广泛征求专家和公众意见,审批前应依法进行公示,公示时间不少于30日\\n* 重点地区城市设计的内容和要求应当纳入控制性详细规划,并落实到控制性详细规划的相关指标中\\n* 以出让方式提供国有土地使用权,以及在城市、县人民政府所在地建制镇规划区内的大型公共建筑项目,应当将城市设计要求纳入规划条件\\n* 城市、县人民政府城乡规划主管部门负责组织编制本行政区域内总体城市设计、重点地区的城市设计,并报本级人民政府审批\\n* 城市、县人民政府城乡规划主管部门组织编制城市设计所需的经费,应列入城乡规划的编制经费预算\\n* 城市、县人民政府城乡规划主管部门开展城乡规划监督检查时,应当加强监督检查城市设计工作情况\\n* 国务院和省、自治区人民政府城乡规划主管部门应当定期对各地的城市设计工作和风貌管理情况进行检查。', 'score': 0.861940853811744, 'meta': {'source': 'construction_regulations/城市设计管理办法.pdf', 'page': 1}, 'sub_query': '城市设计管理办法有哪些?'}), AgentStep(info={'query': '住房和城乡建设部发布城市设计管理办法的目的是什么?', 'name': 'sub query compressor 2'}, result={'content': '根据提供的背景,与问题“住房和城乡建设部发布城市设计管理办法的目的是什么?”相关的部分如下:\\n\\n第一条为提高城市建设水平,塑造城市风貌特色,推进城市设计工作,完善城市规划建设管理,依据《中华人民共和国城乡规划法》等法律法规,制定本办法。\\n\\n这段话明确指出了住房和城乡建设部发布城市设计管理办法的目的,即提高城市建设水平、塑造城市风貌特色、推进城市设计工作、完善城市规划建设管理。', 'score': 0.892462737492939, 'meta': {'source': 'construction_regulations/城市设计管理办法.pdf', 'page': 0}, 'sub_query': '住房和城乡建设部发布城市设计管理办法的目的是什么?'})], status='FINISHED')" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "query = \"住房和城乡建设部发布城市设计管理办法有哪些?\"\n", + "response = await agent.run(query)\n", + "response" + ] + }, + { + "cell_type": "markdown", + "id": "9210e882-9ce6-4bc6-8ae2-ef78ad336dd3", + "metadata": {}, + "source": [ + "## 4.3 使用few shot example 来引导子query分解" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "a2158292-9959-4896-8f63-5d51b6294aa0", + "metadata": {}, + "outputs": [], + "source": [ + "data_map = {\n", + " \"电动汽车的品牌有哪些?各有什么特点?\": [\n", + " \"当前市场上的主要电动汽车品牌。\",\n", + " \"每个品牌的电动汽车品牌的基本技术规格,如续航里程、充电速度等。\",\n", + " \"每个品牌的电动汽车型号,包括轿车、SUV、卡车等。\",\n", + " \"每个品牌的充电基础设施和网络覆盖情况。\",\n", + " \"每个品牌的电池技术和电动驱动系统。\",\n", + " ],\n", + " \"智能家居科技趋势及其在提高生活效率中的应用\": [\"当前最新的智能家居科技趋势是什么\", \"智能家居科技趋势的工作原理和特性\", \"哪些公司或产品正在引领这些智能家居科技趋势\"],\n", + " \"人工智能技术在医疗诊断中的应用案例和效果分析\": [\n", + " \"人工智能技术在医疗诊断领域中的主要应用案例\",\n", + " \"收集每个应用案例中使用的具体人工智能技术,如深度学习、机器学习等\",\n", + " \"分析这些应用案例中人工智能技术对诊断准确性的影响。\",\n", + " \"研究人工智能技术在医疗诊断中的效果,特别关注是否提高了患者的治疗成功率。\",\n", + " ],\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "9793a8cc-0596-49b2-87f6-2482c3919eb2", + "metadata": {}, + "outputs": [], + "source": [ + "few_shot_examples = []\n", + "for key, values in data_map.items():\n", + " meta_data = {}\n", + " for i in range(len(values)):\n", + " meta_data[f\"sub_query_{i+1}\"] = values[i]\n", + " doc = Document(page_content=key, metadata={\"sub_queries\": meta_data})\n", + " few_shot_examples.append(doc)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "db22ba5a-385d-4e5a-81db-3dbf031082f0", + "metadata": {}, + "outputs": [], + "source": [ + "few_shot_retriever = FAISS.from_documents(few_shot_examples, embeddings)\n", + "few_shot_search = LangChainRetrievalTool(few_shot_retriever)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "b68478bb-3abd-4a5a-9025-ce6b28d36966", + "metadata": {}, + "outputs": [], + "source": [ + "memory = WholeMemory()\n", + "agent = RetrievalAgent(\n", + " knowledge_base=search_tool,\n", + " few_shot_retriever=few_shot_search,\n", + " use_compressor=True,\n", + " llm=llm,\n", + " top_k=3,\n", + " tools=[],\n", + " memory=memory,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "5d5f0fc1-e416-479b-aa34-39ddd01d7a64", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AgentResponse(text='很抱歉,根据您提供的信息,我无法直接回答“住房和城乡建设部发布城市设计管理办法”的问题。如果您想了解更多关于该《城市设计管理办法》的信息,建议您查阅相关法律法规和官方文件。', chat_history=[, ], steps=[AgentStep(info={'query': '住房和城乡建设部发布城市设计管理办法', 'name': 'few shot retriever'}, result=[{'content': '智能家居科技趋势及其在提高生活效率中的应用', 'sub_queries': {'sub_query_1': '当前最新的智能家居科技趋势是什么', 'sub_query_2': '智能家居科技趋势的工作原理和特性', 'sub_query_3': '哪些公司或产品正在引领这些智能家居科技趋势'}, 'score': 0.7228106086888564}, {'content': '人工智能技术在医疗诊断中的应用案例和效果分析', 'sub_queries': {'sub_query_1': '人工智能技术在医疗诊断领域中的主要应用案例', 'sub_query_2': '收集每个应用案例中使用的具体人工智能技术,如深度学习、机器学习等', 'sub_query_3': '分析这些应用案例中人工智能技术对诊断准确性的影响。', 'sub_query_4': '研究人工智能技术在医疗诊断中的效果,特别关注是否提高了患者的治疗成功率。'}, 'score': 0.6594227389794118}, {'content': '电动汽车的品牌有哪些?各有什么特点?', 'sub_queries': {'sub_query_1': '当前市场上的主要电动汽车品牌。', 'sub_query_2': '每个品牌的电动汽车品牌的基本技术规格,如续航里程、充电速度等。', 'sub_query_3': '每个品牌的电动汽车型号,包括轿车、SUV、卡车等。', 'sub_query_4': '每个品牌的充电基础设施和网络覆盖情况。', 'sub_query_5': '每个品牌的电池技术和电动驱动系统。'}, 'score': 0.6270684999857814}]), AgentStep(info={'query': '住房和城乡建设部发布城市设计管理办法的背景和原因是什么', 'name': 'sub query compressor 0'}, result={'content': '根据《城市设计管理办法》第一条,制定本办法的背景和原因是为了提高城市建设水平,塑造城市风貌特色,推进城市设计工作,完善城市规划建设管理,依据《中华人民共和国城乡规划法》等法律法规。', 'score': 0.8660674833595821, 'meta': {'source': 'construction_regulations/城市设计管理办法.pdf', 'page': 0}, 'sub_query': '住房和城乡建设部发布城市设计管理办法的背景和原因是什么'}), AgentStep(info={'query': '该管理办法的主要内容和条款是什么', 'name': 'sub query compressor 1'}, result={'content': '该管理办法的主要内容和条款有:\\n1. 第一章 总 则:规定了城市管理执法工作的目的、执法和服务水平的提高、城市管理秩序的维护、公民法人和其他组织的合法权益的保护等。\\n2. 第二条:明确规定了城市管理执法的适用范围和定义,即城市、县人民政府所在地镇建成区内的城市管理执法活动以及执法监督活动,以及城市管理执法主管部门在城市管理领域根据法律法规规章规定履行行政处罚、行政强制等行政执法职责的行为。\\n3. 第三十条:城市管理执法主管部门不得对罚款、没收违法所得设定任务和目标,罚款、没收违法所得的款项,应当按照规定全额上缴。\\n4. 第三十一条:城市管理执法主管部门应当确定法制审核机构,配备一定比例符合条件的法制审核人员,对重大执法决定在执法主体、管辖权限、执法程序、事实认定、法律适用等方面进行法制审核。\\n5. 第三十二条:城市管理执法主管部门开展执法活动,应当使用统一格式的行政执法文书。\\n6. 第三十三条:行政执法文书的送达,依照民事诉讼法等法律规定执行。\\n7. 第三十四条:城市管理执法主管部门应当通过门户网站、办事窗口等渠道或者场所,公开行政执法职责、权限、依据、监督方式等行政执法信息。\\n8. 第六章 协作与配合:第三十五条、第三十六条和第三十七条分别规定了城市管理执法主管部门应当与有关部门建立行政执法信息互通共享机制,及时通报行政执法信息和相关行政管理信息;实行网格化管理;以及在执法活动中发现依法应当由其他部门查处的违法行为,应当及时告知或者移送有关部门。\\n9. 第七章 执法监督:未提供具体条款内容。', 'score': 0.7594137347011427, 'meta': {'source': 'construction_regulations/城市管理执法办法.pdf', 'page': 0}, 'sub_query': '该管理办法的主要内容和条款是什么'}), AgentStep(info={'query': '该管理办法的实施和影响是什么', 'name': 'sub query compressor 2'}, result={'content': '该管理办法的实施和影响是:\\n1. 规范城市管理执法工作,提高执法和服务水平,维护城市管理秩序,保护公民、法人和其他组织的合法权益。\\n2. 城市管理执法主管部门在城市管理领域根据法律法规规章规定履行行政处罚、行政强制等行政执法职责的行为。\\n3. 城市管理执法的行政处罚权范围依照法律法规和国务院有关规定确定,包括住房城乡建设领域法律法规规章规定的行政处罚权,以及环境保护管理、工商管理、交通管理、水务管理、食品药品监管方面与城市管理相关部分的行政处罚权。\\n4. 需要集中行使的城市管理执法事项,应当同时具备下列条件:与城市管理密切相关;与群众生产生活密切相关、多头执法扰民问题突出;执法频率高、专业技术要求适宜;确实需要集中行使的。', 'score': 0.746756108862654, 'meta': {'source': 'construction_regulations/城市管理执法办法.pdf', 'page': 2}, 'sub_query': '该管理办法的实施和影响是什么'}), AgentStep(info={'query': '住房和城乡建设部发布城市设计管理办法后,其他相关部门的反应和行动是什么', 'name': 'sub query compressor 3'}, result={'content': '其他有关部门,应当通过省、自治区、直辖市人民政府住房城乡建设主管部门或者国务院有关部门,将违法事实、处理建议及时报送国务院住房城乡建设主管部门。', 'score': 0.8642921843433182, 'meta': {'source': 'construction_regulations/城市设计管理办法.pdf', 'page': 0}, 'sub_query': '住房和城乡建设部发布城市设计管理办法后,其他相关部门的反应和行动是什么'})], status='FINISHED')" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "query = \"住房和城乡建设部发布城市设计管理办法\"\n", + "response = await agent.run(query)\n", + "response" + ] + }, + { + "cell_type": "markdown", + "id": "37232e51-7030-4732-aa86-2534cfe6dd14", + "metadata": {}, + "source": [ + "## 4.4 使用先验背景信息来引导子query分解" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "2cc0257d-e5a8-46b2-b4bd-2dceec8517ee", + "metadata": {}, + "outputs": [], + "source": [ + "background_data = [\n", + " \"《城市管理执法办法》主要规定了城市管理执法的范围、主管部门、执法人员资格与行为准则、执法措施与程序,以及监督与责任追究机制,旨在确保城市管理执法活动规范、公正、文明,维护城市公共秩序和市容环境。\",\n", + " \"《城市设计管理办法》主要内容是规定了城市设计的编制、审批、实施和管理的相关要求,旨在通过科学、合理的城市设计,塑造城市特色风貌,提升城市环境质量,促进城市可持续发展。该办法强调了城市设计的综合性、整体性和长远性,明确了各级政府和相关部门在城市设计中的职责和作用,为城市设计工作的规范化、制度化提供了保障。\",\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "5a1906c9-c73d-48f3-8cd6-09c51965879f", + "metadata": {}, + "outputs": [], + "source": [ + "background_info = []\n", + "for item in background_data:\n", + " meta_data = {}\n", + " doc = Document(page_content=item)\n", + " background_info.append(doc)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "a307d503-757f-48fd-bc25-ba70d4c2a755", + "metadata": {}, + "outputs": [], + "source": [ + "context_retriever = FAISS.from_documents(background_info, embeddings)\n", + "context_search = LangChainRetrievalTool(context_retriever)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "b6c5b4df-ae5b-4d76-913d-112f68d7f9fd", + "metadata": {}, + "outputs": [], + "source": [ + "memory = WholeMemory()\n", + "agent = RetrievalAgent(\n", + " knowledge_base=search_tool,\n", + " context_retriever=context_search,\n", + " use_compressor=True,\n", + " llm=llm,\n", + " top_k=3,\n", + " tools=[],\n", + " memory=memory,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "105a2183-9fa3-4a14-825d-c555fcfa7748", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AgentResponse(text='很抱歉,文中没有提及住房和城乡建设部发布城市设计管理办法。\\n\\n城市设计是落实城市规划、指导建筑设计、塑造城市特色风貌的有效手段,贯穿于城市规划建设管理全过程。\\n\\n重点地区的控制性详细规划未体现城市设计内容和要求的,应当及时修改完善。\\n\\n单体建筑设计和景观、 市政工程方案设计应当符合城市设计要求。\\n\\n城市、 县人民政府城乡规划主管部门进行建筑设计方案审查和规划核实时,应当审核城市设计要求落实情况。\\n\\n城市、 县人民政府城乡规划主管部门开展城市规划实施评估时,应当同时评估城市设计工作实施情况。\\n\\n城市设计的技术管理规定由国务院城乡规划主管部门另行制定。\\n\\n各地可根据本办法,按照实际情况,制定实施细则和技术导则。\\n\\n县人民政府所在地以外的镇可以参照本办法开展城市设计工作。', chat_history=[, ], steps=[AgentStep(info={'query': '住房和城乡建设部发布城市设计管理办法', 'name': 'context retriever'}, result={'documents': [{'content': '《城市设计管理办法》主要内容是规定了城市设计的编制、审批、实施和管理的相关要求,旨在通过科学、合理的城市设计,塑造城市特色风貌,提升城市环境质量,促进城市可持续发展。该办法强调了城市设计的综合性、整体性和长远性,明确了各级政府和相关部门在城市设计中的职责和作用,为城市设计工作的规范化、制度化提供了保障。', 'score': 0.8577222703771674, 'meta': {}}, {'content': '《城市管理执法办法》主要规定了城市管理执法的范围、主管部门、执法人员资格与行为准则、执法措施与程序,以及监督与责任追究机制,旨在确保城市管理执法活动规范、公正、文明,维护城市公共秩序和市容环境。', 'score': 0.8024841892503045, 'meta': {}}]}), AgentStep(info={'query': '住房和城乡建设部发布城市设计管理办法的具体要求有哪些', 'name': 'sub query compressor 0'}, result={'content': '城市设计是落实城市规划、指导建筑设计、塑造城市特色风貌的有效手段,贯穿于城市规划建设管理全过程。\\n\\n重点地区的控制性详细规划未体现城市设计内容和要求的,应当及时修改完善。\\n\\n单体建筑设计和景观、 市政工程方案设计应当符合城市设计要求。\\n\\n城市、 县人民政府城乡规划主管部门进行建筑设计方案审查和规划核实时,应当审核城市设计要求落实情况。\\n\\n城市、 县人民政府城乡规划主管部门开展城市规划实施评估时,应当同时评估城市设计工作实施情况。\\n\\n城市设计的技术管理规定由国务院城乡规划主管部门另行制定。\\n\\n各地可根据本办法,按照实际情况,制定实施细则和技术导则。\\n\\n县人民政府所在地以外的镇可以参照本办法开展城市设计工作。', 'score': 0.8885268013611886, 'meta': {'source': 'construction_regulations/城市设计管理办法.pdf', 'page': 0}, 'sub_query': '住房和城乡建设部发布城市设计管理办法的具体要求有哪些'}), AgentStep(info={'query': '住房和城乡建设部在城市设计管理办法中提出的重点措施有哪些', 'name': 'sub query compressor 1'}, result={'content': '重点地区城市设计应当塑造城市风貌特色, 注重与山水自然的共生关系,协调市政工程,组织城市公共空间功能,注重建筑空间尺度,提出建筑高度、体量、风格、色彩等控制要求。', 'score': 0.8694623171767254, 'meta': {'source': 'construction_regulations/城市设计管理办法.pdf', 'page': 0}, 'sub_query': '住房和城乡建设部在城市设计管理办法中提出的重点措施有哪些'})], status='FINISHED')" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "query = \"住房和城乡建设部发布城市设计管理办法\"\n", + "response = await agent.run(query)\n", + "response" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22f52651-522a-4783-b7ca-bb135e6e9233", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/erniebot-agent/cookbook/tools_intro.ipynb b/erniebot-agent/cookbook/tools_intro.ipynb index 38b8150ee..56777d779 100644 --- a/erniebot-agent/cookbook/tools_intro.ipynb +++ b/erniebot-agent/cookbook/tools_intro.ipynb @@ -293,7 +293,7 @@ ], "metadata": { "kernelspec": { - "display_name": "eb-sdk", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -307,9 +307,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.18" + "version": "3.9.12" }, - "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "8a19f367f79553e5cd49921fbfd8af2792f58f47b1c0c637c2b65217dfab81ed" @@ -317,5 +316,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/erniebot-agent/src/erniebot_agent/agents/retrieval_agent.py b/erniebot-agent/src/erniebot_agent/agents/retrieval_agent.py index 4d807d20d..ca7bb6fe0 100644 --- a/erniebot-agent/src/erniebot_agent/agents/retrieval_agent.py +++ b/erniebot-agent/src/erniebot_agent/agents/retrieval_agent.py @@ -6,6 +6,7 @@ from erniebot_agent.file import File from erniebot_agent.memory.messages import HumanMessage, Message from erniebot_agent.prompt import PromptTemplate +from erniebot_agent.tools.langchain_retrieval_tool import LangChainRetrievalTool ZERO_SHOT_QUERY_DECOMPOSITION = """请把下面的问题分解成子问题,每个子问题必须足够简单,要求: 1.严格按照【JSON格式】的形式输出:{"sub_query_1":"具体子问题1","sub_query_2":"具体子问题2"} @@ -48,38 +49,12 @@ """ -class FewShotSearch: - def __init__(self, db): - self.db = db - - def search(self, query: str, top_k: int = 10, **kwargs): - docs = self.db.similarity_search_with_relevance_scores(query, top_k) - retrieval_results = [] - for doc, score in docs: - retrieval_results.append( - {"content": doc.page_content, "sub_queries": doc.metadata["sub_queries"], "score": score} - ) - return retrieval_results - - -class ContextSearch: - def __init__(self, db): - self.db = db - - def search(self, query: str, top_k: int = 10, **kwargs): - docs = self.db.similarity_search_with_relevance_scores(query, top_k) - retrieval_results = [] - for doc, score in docs: - retrieval_results.append({"content": doc.page_content, "score": score}) - return retrieval_results - - class RetrievalAgent(Agent): def __init__( self, knowledge_base, - few_shot_retriever: Optional[FewShotSearch] = None, - context_retriever: Optional[ContextSearch] = None, + few_shot_retriever: Optional[LangChainRetrievalTool] = None, + context_retriever: Optional[LangChainRetrievalTool] = None, top_k: int = 2, threshold: float = 0.1, use_compressor: bool = False, @@ -112,7 +87,16 @@ async def _run(self, prompt: str, files: Optional[Sequence[File]] = None) -> Age steps_taken: List[AgentStep] = [] if self.few_shot_retriever: # Get few shot examples - few_shots = self.few_shot_retriever.search(prompt, 3) + docs = await self.few_shot_retriever(prompt, 3) + few_shots = [] + for doc in docs["documents"]: + few_shots.append( + { + "content": doc["content"], + "sub_queries": doc["meta"]["sub_queries"], + "score": doc["score"], + } + ) steps_input = HumanMessage( content=self.query_transform.format(query=prompt, documents=few_shots) ) @@ -120,9 +104,8 @@ async def _run(self, prompt: str, files: Optional[Sequence[File]] = None) -> Age AgentStep(info={"query": prompt, "name": "few shot retriever"}, result=few_shots) ) elif self.context_retriever: - res = self.context_retriever.search(prompt, 3) - - context = [item["content"] for item in res] + res = await self.context_retriever(prompt, 3) + context = [item["content"] for item in res["documents"]] steps_input = HumanMessage( content=self.query_transform.format(query=prompt, context="\n".join(context)) ) diff --git a/erniebot-agent/tests/unit_tests/agents/test_retrieval_agent.py b/erniebot-agent/tests/unit_tests/agents/test_retrieval_agent.py index 42c4951ab..47718067e 100644 --- a/erniebot-agent/tests/unit_tests/agents/test_retrieval_agent.py +++ b/erniebot-agent/tests/unit_tests/agents/test_retrieval_agent.py @@ -2,11 +2,13 @@ from unittest.mock import MagicMock import pytest +from langchain.docstore.document import Document from erniebot_agent.agents import RetrievalAgent from erniebot_agent.memory import AIMessage from erniebot_agent.retrieval import BaizhongSearch from erniebot_agent.tools.baizhong_tool import BaizhongSearchTool +from erniebot_agent.tools.langchain_retrieval_tool import LangChainRetrievalTool from tests.unit_tests.agents.common_util import EXAMPLE_RESPONSE from tests.unit_tests.testing_utils.mocks.mock_chat_models import ( FakeERNIEBotWithPresetResponses, @@ -15,28 +17,27 @@ class FakeFewShotSearch: - def search(self, query: str, top_k: int = 10, **kwargs): - retrieval_results = [ - { - "content": "电动汽车的品牌有哪些?各有什么特点?", - "sub_queries": { - "sub_query_1": "当前市场上的主要电动汽车品牌。", - "sub_query_2": "每个品牌的电动汽车品牌的基本技术规格,如续航里程、充电速度等。", + def similarity_search_with_relevance_scores(self, query: str, top_k: int = 10, **kwargs): + doc = ( + Document( + page_content="电动汽车的品牌有哪些?各有什么特点?", + metadata={ + "sub_queries": { + "sub_query_1": "当前市场上的主要电动汽车品牌。", + "sub_query_2": "每个品牌的电动汽车品牌的基本技术规格,如续航里程、充电速度等。", + } }, - "score": 0.5, - } - ] + ), + 0.5, + ) + retrieval_results = [doc] return retrieval_results class FakeAbstractSearch: - def search(self, query: str, top_k: int = 10, **kwargs): - retrieval_results = [ - { - "content": "住房和城乡建设部规章城市管理执法办法的摘要", - "score": 0.5, - } - ] + def similarity_search_with_relevance_scores(self, query: str, top_k: int = 10, **kwargs): + doc = (Document(page_content="住房和城乡建设部规章城市管理执法办法的摘要"), 0.5) + retrieval_results = [doc] return retrieval_results @@ -54,7 +55,7 @@ async def test_retrieval_agent_run_few_shot(): search_tool = BaizhongSearchTool( name="city_design_management", description="提供城市设计管理办法的信息", db=baizhong_db, threshold=0.0 ) - few_shot_retriever = FakeFewShotSearch() + few_shot_retriever = LangChainRetrievalTool(FakeFewShotSearch()) llm = FakeERNIEBotWithPresetResponses( responses=[ AIMessage('{"sub_query_":"具体子问题1","sub_query_2":"具体子问题2"}', function_call=None), @@ -106,7 +107,7 @@ async def test_retrieval_agent_run_context_planning(): AIMessage("Text response", function_call=None), ] ) - context_retriever = FakeAbstractSearch() + context_retriever = LangChainRetrievalTool(FakeAbstractSearch()) agent = RetrievalAgent( knowledge_base=search_tool, llm=llm, @@ -126,7 +127,6 @@ async def test_retrieval_agent_run_context_planning(): "检索语句: Hello, world!\n请根据以上检索结果回答检索语句的问题" ) assert response.chat_history[1].content == "Text response" - assert response.steps[0].info == {"query": "Hello, world!", "name": "context retriever"} assert response.steps[1].info == {"query": "具体子问题1", "name": "sub query results 0"} assert response.steps[2].info == {"query": "具体子问题2", "name": "sub query results 1"}