关于AI大模型中的LangChain ReAct框架的学习和使用

LangChain React

ReAct是Reasoning and Acting(也有一说是Reason Act)缩写,意思是LLM可以根据逻辑推理(Reason),构建完整系列行动(Act),从而达成期望目标。

ReAct方式的作用就是协调LLM模型和外部的信息获取,与其他功能交互。如果说LLM模型是大脑,那ReAct框架就是这个大脑的手脚和五官。同时具备帮助LLM模型获取信息、输出内容与执行决策的能力。对于一个指定的任务目标,ReAct框架会自动补齐LLM应该具备的知识和相关信息,然后再让LLM模型做出决策,并执行LLM的决策。

一个ReAct流程里,关键是三个概念:

  • Thought:由LLM模型生成,是LLM产生行为和依据。可以根据LLM的思考,来衡量他要采取的行为是否合理。这是一个可用来判断本次决策是否合理的关键依据。相较于人类,thought的存在可以让LLM的决策变得更加有可解释性和可信度。

  • Act:Act是指LLM判断本次需要执行的具体行为。Act一般由两部分组成:行为和对象。用编程的说法就是API名称和对应的入参。LLM模型最大的优势是,可以根据Thought的判断,选择需要使用的API并生成需要填入API的参数。从而保证了ReAct框架在执行层面的可行性。

  • Obs:LLM框架对于外界输入的获取。它就像LLM的五官,将外界的反馈信息同步给LLM模型,协助LLM模型进一步的做分析或者决策。

一个完整的ReAct的行为,包涵以下几个流程:

  • 1.输入目标:任务的起点。可以是用户的手动输入,也可以是依靠触发器(比如系统故障报警)。

  • 2.LOOP:LLM模型开始分析问题需要的步骤(Thought),按步骤执行Act,根据观察到的信息(Obs),循环执行这个过程。直到判断任务目标达成。

  • 3.Finish:任务最终执行成功,返回最终结果。

简单的ReAct示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
You are an assistant, please fully understand the user's question, choose the appropriate tool, and help the user solve the problem step by step.

### CONSTRAINTS ####
1. The tool selected must be one of the tools in the tool list.
2. When unable to find the input for the tool, please adjust immediately and use the AskHumanHelpTool to ask the user for additional parameters.
3. When you believe that you have the final answer and can respond to the user, please use the TaskCompleteTool.
5. You must response in Chinese;

### Tool List ###

[
Search: 如果需要搜索请用它.paramDescription : [{"name": "searchKey", "description": "搜索参数","type":"String"}]
AskHumanHelpTool: 如果需要人类帮助,请使用它。paramDescription : [{"name": "question", "description": "问题","type":"String"}]
TaskCompleteTool:如果你认为你已经有了最终答案,请使用它。paramDescription : [{"name": "answer", "description": "答案","type":"String"}]
]

You should only respond in JSON format as described below

### RESPONSE FORMAT ###
{

{"thought": "为什么选择这个工具的思考","tool_names": "工具名","args_list": {“工具名1”:{"参数名1": "参数值1","参数名2": "参数值2"}}}}
Make sure that the response content you return is all in JSON format and does not contain any extra content.

把它复制粘贴到ChatGPT中,就可以感受一下最初级的ReAct交互的体验。读者自己充当一个ReAct框架,去执行Act和Obs过程。

实际应用

申请api

K1.申请通义千问的api,去阿里云控制台申请

https://dashscope.console.aliyun.com/apiKey

K2.申请了APIkey也得去申请模型试用服务,不然无法正常调用model

然后编写代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from langchain.tools import BaseTool
from langchain.agents import initialize_agent
from langchain.agents import AgentType
import os
import langchain
from langchain_community.llms import Tongyi
import requests
from langchain_core.messages import HumanMessage
import dashscope
from langchain.prompts import PromptTemplate
from langchain.agents import initialize_agent, AgentType, Tool
from langchain.chains import LLMMathChain
from langchain_community.utilities import SerpAPIWrapper
import re

os.environ["DASHSCOPE_API_KEY"] = 'sk-XXX'
llm = Tongyi(model="qwen-plus")
# 默认model是qwen-plus

# 自定义工具
class Multiply(BaseTool):
name = "乘法"
description = "只做乘法运算"

def _run(self, input: str) -> str:
# 使用正则表达式匹配逗号或"和"分隔的数字
numbers_str = re.findall(r'\d+|和\d+', input)

# 将匹配到的字符串转换为数字列表
numbers = [int(number.replace('和', '')) for number in numbers_str]

# 检查输入是否为空或只有一个元素
if len(numbers) < 2:
return "请输入至少两个数字进行乘法运算"

# 计算乘积
product = 1
for number in numbers:
product *= number

# 返回结果
return f"乘法计算完毕,结果是 {product}"
def _arun(self, query: str):
raise NotImplementedError("This tool does not support async")


class Add(BaseTool):
name = "加法"
description = "只做加法运算"

def _run(self, input: str) -> str:
# 使用正则表达式匹配逗号或"和"分隔的数字
numbers_str = re.findall(r'\d+|和\d+', input)

# 将匹配到的字符串转换为数字列表
numbers = [int(number.replace('和', '')) for number in numbers_str]

# 检查输入是否为空或只有一个元素
if len(numbers) < 2:
return "请输入至少两个数字进行加法运算"

# 计算乘积
product = 0
for number in numbers:
product += number

# 返回结果
return f"加法计算完毕,结果是 {product}"

def _arun(self, query: str):
raise NotImplementedError("This tool does not support async")


class Exponentiate(BaseTool):
name = "幂运算"
description = "只做幂运算"

def _run(self, input: str) -> str:
def _run(self, input: str) -> str:
# 使用正则表达式匹配逗号或"和"分隔的数字
numbers_str = re.findall(r'\d+|和\d+', input)

# 将匹配到的字符串转换为数字列表
numbers = [int(number.replace('和', '')) for number in numbers_str]

# 检查输入是否为空
if not numbers:
return "请输入至少一个数字和它的指数进行幂运算"

# 计算每个幂
powers = [base ** exp for base, exp in numbers]

# 返回结果
result = " * ".join(str(power) for power in powers)
return f"幂运算计算完毕,结果是 {result}"

def _arun(self, query: str):
raise NotImplementedError("This tool does not support async")


tools = [Multiply(), Add(), Exponentiate()]

# agent = initialize_agent(tools, agent=AgentType.DEFAULT)
agent = initialize_agent(tools,
llm,
verbose=True)
agent("3乘以6,加上5的3次方再加上57,最后是多少?")

导入需要编写的包,langchain,Tongyi等
K3:如果需要链接自定义大模型需要自己重写llm方法

Class XXX(BassTool):
定义一个类,这个类继承BaseTool,需要实现_run方法,在_run方法中处理input输入

工具类的意义是在于可以让大模型去使用工具,可以尝试交互,处理更多复杂问题。

1
2
3
agent = initialize_agent(tools,
llm,
verbose=True)

定义一个agent
它就是我们需要用到的整体的模型+工具集

最后执行则会得到如下的执行链