React Agent 自定义实现代码

 更新时间:2024年10月21日 10:34:13   作者:木下瞳  
在使用langchain的ReactAgent遇到问题后,作者尝试自定义ReactAgent实现,通过详细分析langchain中的agent功能和问题,结合React思想,作者设计了新的agent逻辑并在GitHub上分享了代码,新的ReactAgent通过改进prompt和工具调用逻辑,提升了任务执行的效果和稳定性

背景

之前使用过 langchian 中的 agent 去实现过一些案例,angchian 的 React Agent 是有问题的,且内部代码有点难看懂,所以自己来根据 React 思想,灵活来实现试一下。

可以先看看我自定义实现的逻辑图,后面详细说明:

langchin 中的 agent

langchian 中的几种 agent 怎么用,我都看过了,也整理了一下了,那些能用,那些有问题的可以看注释,代码链接:https://github.com/5zjk5/prompt-engineering

langchin 中 agent 的问题

先来说说我用过的发现的问题,就是它的 React agent 有点问题,只调用一个工具就结束了,详细实验的文章:langchain 的 agent + tool 使用_langchain agent tool-CSDN博客

想去看看代码到底怎么运行的,发现太难看懂了。

后面在我自己实现 React agent 的时候,突然发现,跟 prompt 关系挺大的,langchian 那个 prompt 应该是根据 openai 的去写的,这是我目前想到只能调用一个工具的原因。

langchain 的 agent 案例

GitHub - 5zjk5/prompt-engineering: prompt 工程项目案例

自定义 React Agent

大模型

用的智谱 glm-4-air,如果换了模型,效果还不太稳定,需要调 prompt。

工具定义

定义两个工具,一个是 tavily 的搜索,去官网开通账号就可以获得一个 api,免费调用 1000 次;

一个工具是根据名字查询身高的自定义函数

from tavily import TavilyClient
from llm.llm_api_key import TAVILY_API_KEY
import time
def tavily_search(query):
    try:
        # Step 1. Instantiating your TavilyClient
        tavily_client = TavilyClient(api_key=TAVILY_API_KEY)
        # Step 2. Executing a Q&A search query
        answer = tavily_client.qna_search(query=query)
        # Step 3. That's it! Your question has been answered!
        return answer
    except:
        time.sleep(1)
        # Step 1. Instantiating your TavilyClient
        tavily_client = TavilyClient(api_key=TAVILY_API_KEY)
        # Step 2. Executing a Q&A search query
        answer = tavily_client.qna_search(query=query)
        # Step 3. That's it! Your question has been answered!
        return answer
def height_search(name):
    height_dic = {
        "张三": 180,
        "李四": 175,
        "王五": 170,
        "赵六": 165,
        "钱七": 160,
        "孙八": 175,
        "周九": 170,
        "吴十": 165,
        "郑十一": 180,
        "王十二": 175,
        "李十三": 170,
        "赵十四": 165,
        "钱十五": 180,
        "孙十六": 175,
    }
    return height_dic.get(name)

工具描述,要让大模型理解工具,需要定义描述,这里参考的智谱官方的工具的描述写法:

tavily_search_tool = {
        "type": "function",
        "function": {
            "name": 'tavily_search',
            "description": "根据用户查询,去搜索引擎,返回搜索结果",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {
                        "description": "用户搜索内容 query",
                        "type": "string"
                    },
                },
                "required": ["query"]
            }
        }
      }
height_search_tool = {
        "type": "function",
        "function": {
            "name": 'height_search',
            "description": "只要是有姓名,身高关键字,都需要使用此工具根据姓名,查询对应身高,每次只能查询一个人的身高",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {
                        "description": "指具体的姓名或名字",
                        "type": "string"
                    },
                },
                "required": ["name"]
            }
        }
      }

问题设定

设定一个问题:

这个问题潜在意图是查询钱七,李四身高,并且搜索大模型定义,是想调用身高查询工具 2 次,搜索工具 1 次。

问题改写,挖掘潜在意图

为什么加这一步呢?因为把问题传给大模型后发现一个问题,它可能发现不了潜在意图,例如这里潜在意图要查询身高,问题中没有明显提出,大模型思考结果:

这样的话就只使用搜索工具就结束了,所以加了一步问题改写,去发现潜在意图,是利用大模型能力去做的,用 prompt,改写结果成功识别出潜在意图,并思考出要调用哪个工具:

尽你所能改写以下问题,可以有多个答案,可以参照以下工具进行改写,识别用户潜在意图:
```{tools}```
Question:`{query}`
Answer 按照以下格式,每一点代表一个意图,如果需要用到工具的需要列出工具名字,不需要具体参数:
```
1. 
2. 
...
```

React Prompt

React agent 核心的 prompt 怎么让模型自动规划,先来看 langchain 中的写法:

Answer the following questions as best you can. You have access to the following tools:
{tools}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {input}
Thought:{agent_scratchpad}

传入变量 tool 为所有工具,tool_names 为所有工具名称列表,input 问题输入,agent_scratchpad 思考要做什么,怎么做。

参照进行改编:

尽你所能回答以下问题。您可以使用以下工具:
```{tools}```
严格使用以下 JSON 格式:
```
{{
    Question: 根据 thought 当前需要回答的问题,此字段必须存在
    Thought: 对于 Question 要做什么,此字段必须存在
    Action: {{'tool': 要采取的动作,应该是[{tool_names}]之一,如果不需要工具可以空着}}
    Action Input: 动作的输入,是一个 JSON 格式,此字段必须存在,如果不需要输入可以空着
    Observation: 行动的结果,此字段必须存在,默认为空
}}
```
(Question/Thought/Action/Action Input/Observation 五个字段必须存在,以上步骤只能重复 1 次)
开始吧!
Question:`{query}`
thought:`{agent_scratchpad}`

根据 agent_scratchpad 每次运行得到 json 的 action,接着提取工具名及参数,去进行工具调用,这里因为是 json,格式控制好了提取就方便了。

使用完工具后,把结果赋值给 Observation。

下一步规划

agent_scratchpad 就是下一步规划的思考,用 prompt 去进行规划,传给已经执行的 action,问题及思考,让自动规划下一步应该做什么:

# 背景
有一个问题 Question,已经有了对这个问题的思考 Thought,已执行的思考 Action,需要根据这些信息去规划出下一步应该做什么。
# 输入
## Question:`{query}`
## Thought:`{thought}`
## Action:`{all_action_res}`
# 思考推理:
- 1、参考 Question 仔细理解 Thought,思考 Action 还有哪些没有行动。
- 2、判断你下一步做什么行动,不能过于发散过多的行动,必须根据步骤 1 的思考。
- 3、确保你的回答在语义上与 Action 中的内容不重复是一个全新的步骤。
- 4、若 Thought 已经全部执行了,直接回答`no`。
# 输出要求(严格按照以下要求输出)
- 回答需要用一句话清晰的总结下一步需要做什么,不需要其他任何信息。
- 如果没有需要做的了,直接输出`no`,不需要其他任何信息,不需要解释任何理由。

这里遇到一个问题,就是可能会一直重复规划,导致死循环,在代码中加了判断,理论上开始重复规划了,说明已经没有可以给出新的规划了,那就结束吧。

问题总结

所有 action 的结果,用了一个列表保存的,最后用大模型自己去总结去回答问题就可以了。

D:\programming\dev_env\anaconda\anaconda3\python.exe "D:\Python_project\NLP\大模型学习\prompt-engineering\自定义 React Agant\run_agent.py" 
D:\programming\dev_env\anaconda\anaconda3\Lib\site-packages\langchain\callbacks\__init__.py:37: LangChainDeprecationWarning: Importing this callback from langchain is deprecated. Importing it from langchain will no longer be supported as of langchain==0.2.0. Please import from langchain-community instead:
`from langchain_community.callbacks import get_openai_callback`.
To install langchain-community run `pip install -U langchain-community`.
  warnings.warn(
输入 token:103/输出 token:268/总共 token:371/
问题改写,识别潜在意图:
1. 识别用户提到的“身高比较高的小伙子”和“长得像钱七”,可能需要查询钱七的身高信息(使用工具:height_search)。
2. 识别用户提到的“还有他跟他身高差不多的兄弟李四”,可能需要查询李四的身高信息(使用工具:height_search)。
3. 用户对“大模型”表示不清楚,需要解释或搜索“大模型”的定义和相关信息(使用工具:tavily_search)。
=====================================
输入 token:53/输出 token:376/总共 token:429/
解决此问题的思考 Thought:
根据用户的问题,我们需要查询钱七和李四的身高信息,并获取关于“大模型”的解释和相关信息。因此,我们需要使用height_search工具来查询身高信息,以及使用tavily_search工具来搜索大模型的相关内容。
=====================================
输入 token:89/输出 token:426/总共 token:515/
{'Action': {'tool': 'height_search'},
 'Action Input': {'name': '钱七'},
 'Observation': 160,
 'Question': '1. 识别用户提到的“身高比较高的小伙子”和“长得像钱七”,可能需要查询钱七的身高信息(使用工具:height_search)。',
 'Thought': '需要使用工具查询钱七的身高信息。'}
=====================================
输入 token:12/输出 token:289/总共 token:301/
下一步需要做什么:
需要使用工具查询李四的身高信息。
=====================================
输入 token:60/输出 token:435/总共 token:495/
{'Action': {'tool': 'height_search'},
 'Action Input': {'name': '李四'},
 'Observation': 175,
 'Question': '查询李四的身高信息。',
 'Thought': '使用height_search工具查询李四的身高。'}
=====================================
输入 token:14/输出 token:301/总共 token:315/
下一步需要做什么:
使用tavily_search工具搜索大模型的相关内容。
=====================================
输入 token:61/输出 token:437/总共 token:498/
{'Action': {'tool': 'tavily_search'},
 'Action Input': {'query': '大模型是什么意思'},
 'Observation': 'Based on the data provided, the term "大模型" (Big Model) refers '
                'to a method or technology used in the fields of machine '
                'learning and artificial intelligence to handle large-scale '
                'data and complex models. These models are typically '
                'constructed using deep neural networks with a large number of '
                'parameters, ranging from billions to even trillions. The '
                'purpose of big models is to improve model expressive power '
                'and predictive performance, enabling them to handle more '
                'complex tasks and datasets effectively. Big models play a '
                'crucial role in addressing challenges posed by increasing '
                'data volumes and model complexities in the field of AI and '
                'machine learning.',
 'Question': '大模型是什么意思?',
 'Thought': '使用搜索引擎查询大模型的相关信息。'}
=====================================
输入 token:10/输出 token:311/总共 token:321/
开始生成重复步骤,或已执行 action 过多,判断结束了!重复步骤:使用搜索引擎查询大模型的相关信息。
下一步需要做什么:
no
=====================================
输入 token:109/输出 token:332/总共 token:441/
最终答案:
根据您的描述,钱七的身高是160厘米,而李四的身高是175厘米。至于您提到的“大模型”,这是一种在机器学习和人工智能领域中使用的方法或技术。大模型通常指的是具有大量参数(从数十亿到数万亿不等)的深度神经网络模型。这些模型的目的是提高表达能力和预测性能,使它们能够更有效地处理大规模数据和复杂任务。
简而言之,大模型是为了应对人工智能和机器学习领域中数据量增加和模型复杂性提升的挑战而发展起来的技术。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Process finished with exit code 0

代码

prompt-engineering/自定义 React Agant at master · 5zjk5/prompt-engineering · GitHub

到此这篇关于React Agent 自定义实现的文章就介绍到这了,更多相关React Agent 自定义内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • React Fiber中面试官最关心的技术话题

    React Fiber中面试官最关心的技术话题

    这篇文章主要为大家介绍了React Fiber中面试官最关心的技术话题解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 详解React中key的作用

    详解React中key的作用

    这篇文章主要介绍了React中key的作用,帮助大家更好的理解和学习使用React,感兴趣的朋友可以了解下
    2021-04-04
  • 一文教你如何避免React中常见的8个错误

    一文教你如何避免React中常见的8个错误

    这篇文章主要来和大家一起分享在 React 开发中常见的一些错误,以及如何避免这些错误,理解这些问题背后的细节,防止犯下类似的错误,需要的可以参考下
    2023-12-12
  • 详解React之key的使用和实践

    详解React之key的使用和实践

    这篇文章主要介绍了详解React之key的使用和实践,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • react结合bootstrap实现评论功能

    react结合bootstrap实现评论功能

    这篇文章主要为大家详细介绍了react结合bootstrap实现评论功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • 封装一个最简单ErrorBoundary组件处理react异常

    封装一个最简单ErrorBoundary组件处理react异常

    这篇文章主要介绍了一个处理react异常的ErrorBoundary组件,简单实用,代码详细,对这个组件感兴趣的朋友可以参考下
    2021-04-04
  • React路由鉴权的实现方法

    React路由鉴权的实现方法

    这篇文章主要介绍了React路由鉴权的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • React、Vue中key的作用详解 (key的内部原理解析)

    React、Vue中key的作用详解 (key的内部原理解析)

    key是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据[新数据]生成[新的虚拟DOM],本文给大家介绍React、Vue中key的作用详解 (key的内部原理解析),感兴趣的朋友一起看看吧
    2023-10-10
  • Next.js实现react服务器端渲染的方法示例

    Next.js实现react服务器端渲染的方法示例

    这篇文章主要介绍了Next.js实现react服务器端渲染的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • Remix路由模块输出对象loader函数详解

    Remix路由模块输出对象loader函数详解

    这篇文章主要为大家介绍了Remix路由模块输出对象loader函数详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪<BR>
    2023-04-04

最新评论