Langchain中ReAct开发

在Langchian中开发ReAct自定义智能体

先需要熟悉几种对象

  • PromptTemplate这是一个模版,可以用来装自定义的prompt,一般作为userPrompt的一部分使用。
  • llm: 这是一个LLM对象,用来生成回复。
  • outputParser: 这是一个输出解析器,用来解析LLM的输出。
  • agent: 这是一个智能体对象,用来管理智能体的行为。

需要明白的使用逻辑为

  1. 创建一个llm对象,用来生成回复。
  2. 创建一个PromptTemplate对象,用来装自定义的prompt。
  3. 创建一个outputParser对象,用来解析LLM的输出。
  4. 创建一个agent对象,用来使用agent的功能。

llm的代码分为两种,一种为直接调用langchain内部对于一些大模型的接入,另一种为使用自定义的LLM。

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
from langchain.llms import OpenAI
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.agents import Tool
from langchain.agents import ZeroShotAgent
from langchain.agents import AgentExecutor
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate
from langchain.prompts.chat import (
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
ChatPromptTemplate,
MessagesPlaceholder,
AIMessagePromptTemplate,
HumanMessagePromptTemplate,
SystemMessagePromptTemplate,
ChatMessagePromptTemplate,
)
## 创建一个LLM对象且需要在环境变量中定义openapikey
llm = OpenAI(temperature=0)

## 创建一个自定义的LLM对象
llm2 = HuggingFaceHub(repo_id="google/flan-t5-xxl", model_kwargs={"temperature":0.5, "max_length":512})

## 定义大模型可能需要用到的工具,可以使用内置的,也可以直接自己编写
tools = ["serpapi", "llm-math"]
## 使用llm创建一个agent对象
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)

## 使用agent对象进行任务
agent.run("What is the weather in San Francisco today?")

## 使用自定义的LLM对象创建一个agent对象
agent2 = initialize_agent(tools, llm2, agent2=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
agent2.run("What is the weather in San Francisco today?")

需要apikey的内置大模型有Openai,Gemini,Qwen等

当使用自定义的llm及自定的tool时需要规范如下

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

## 自定义大模型继承LLM类
class CustomLLM(LLM):
## 默认的callback方法,agent及langchain链会回调此方法
def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
## 一般在这里编写调用自定义大模型的api比如使用requests等库向大模型发送消息
return "Hello world"
## 在类内部的参数定义
def _identifying_params(self) -> Dict[str, Any]:
return {"name_of_model": "gpt-3.5-turbo"}
## llm_type方法用来定义大模型的类型
def _llm_type(self) -> str:
return "custom"


## 自定义工具继承BaseTool类
class CustomTool(BaseTool):
## 工具名,会在langchain的prompt中调用
name = "Custom Tool"
## 工具的描述,大模型会读这里
description = "A tool that does something"
## 工具的调用方法
def _run(self, query: str) -> str:
return "Hello world"
## 异步调用
def _arun(self, query: str) -> str:
return "Hello world"

建议整体的流程为,确认使用的LLM,确认使用的工具,然后根据需求编写prompt,然后根据prompt创建agent,最后使用agent进行任务。

尤其是对于自定义的LLM,需要定义callback方法,以及llm_type方法,以及_identifying_params方法,以及_llm_type方法。
最终的prompt需要定义为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
## 自定义提示词模版
PromptTemplate(
## 传入的参数
input_variables=["input", "agent_scratchpad"],
## 模版
template="""
You are a helpful assistant. Use the following pieces of context to answer the users question.
If you don't know the answer, just say that you don't know, don't try to make up an answer.
{input}
{agent_scratchpad}
"""
)
## 尝试创建一个memory对象,用来保存上下文
memory = ConversationBufferMemory(memory_key="agent_scratchpad", return_messages=True)

所以最终的自定义流程为

  1. 自定义实现LLM类的_call方法,完成自定义大模型的调用。
  2. 编写模板提示词,如果使用Langchain时需要包含{tools},{tool_names},{agent_scratchpad},{input}(input可选)
  3. 编写工具类,继承BaseTool类,实现_run方法,_arun方法,name,description等方法。在描述中尽可能清楚的描述其接受参数,输出参数,以及在什么情况下使用。
  4. 编写agent,使用initialize_agent方法,传入工具列表,LLM对象,agent类型,memory对象,verbose等参数。