用langchain构建传统agent

声明

本篇博客将会说明以AgentExecutor启动的比较传统的agent的构建。而langgraph是用来构建比较重的单agent或者多agent的构建。如果我们只是想实现一个小的功能,用langgraph的话大可不必。

agent的系统组成

用langchain构建传统agent_第1张图片
理论的东西我不想深入太多去解释,我用一段话来概括agent里面的四个元素(下面的结论是我通过实际的工程和代码总结出来的,和论文可能并不完全相同,这一点其实也很好理解,论文是死的,但是工程落地是活的,定义这些都是可以灵活变通的):

  • memory:短期记忆就是prompt里面的信息,比如最简单的system里面的内容。长期记忆就是通过rag等检索手段获取的信息。我个人认为,历史记录也算是短期记忆,它的特征更像是类似于规定好的内容。
  • tools和action:agent可以调用的所有工具,比如计算的工具,此时计算的工具被称作tool,而计算的这个过程,叫做action。那么可能你会疑问,为什么agent可以直接不通过tool而去执行action呢?如果给你将文字,我觉得大部分人还是没办法百分比领会到。我用一个工程上的例子来进一步解释:
    • 如果我们在构建一个多agent的时候,必然存在一个主agent,这个主agent也必然会有一个路由函数,路由函数的作用就是控制下一步应该走向哪一个子agent。那么走向这个子agent的行为,就是Action,但是我们并没有调用tools(实现路由的功能我们不在这里讨论,可能下一篇博客我会进一步说明)
  • planning:下一步的计划,听起来好像还是有点像Action,我还是举个例子,如果我们通过rag获取了相关的文档,这个时候可以选择增加一条审判幻觉的节点,这个节点可以判断我们通过检索的文档是否和query相关,或者说是否可以解答query,如果不行,那么可能会去回退query或者改写query等等,然后再进行检索,如果可以解答,那么进行传统的rag问答。那么这个过程,就是planning,你可以说它的本质还是Action,完全没问题,但是这种带有思考性质的Action,也可以说是在planning。

代码工具

langchain对于构建传统的agent有两个主要的工具
create_tool_calling_agent和AgentExecutor。

create_tool_calling_agent是用来创建agent的,AgentExecutor是用来管理agent的。
create_tool_calling_agent本质上就是一个绑定了tool的llm:

    agent_chain = create_react_agent(tools=tools, llm=llm_qwen, prompt=prompt)
    
    #下面是create_react_agent的核心源码
	llm_with_tools = llm.bind_tools(tools)

    agent = (
        RunnablePassthrough.assign(
            agent_scratchpad=lambda x: message_formatter(x["intermediate_steps"])
        )
        | prompt
        | llm_with_tools
        | ToolsAgentOutputParser()
    )
    return agent
  • prompt是采用的专门的从hub上扒下来的promptprompt = hub.pull("hwchase17/react") 你也可以自己来构建,但是必须满足里面的变量是相同的,因为create_react_agent会用到这些特定的变量。intermediate_steps这个参数我们并没有提供,这是AgentExecutor包装以后提供的,用来记录此时agent的状态:需要继续执行,还是已经完成。

各位可以选择去看里面的源码,但是我个人觉得作用不大,因为一环套一环,短时间内不太容易看懂(当然看懂以后收获还是很大的),我这里说一下AgentExcutor的缺点,第一个是它一次只能调用一个tool,第二个就是程序执行以后无法人为控制(因为缺少可能和人的交互,所以会大大限制agent的作用)

我给一个完整的代码可以跑一下:

from langchain_openai import ChatOpenAI
from langchain.chat_models.tongyi import ChatTongyi
from dotenv import load_dotenv
from langchain.tools import Tool
from langchain.agents import create_react_agent

load_dotenv()
llm = ChatOpenAI(model='gpt-3.5-turbo-1106', temperature=0)
llm_qwen = ChatTongyi(model_name='qwen2.5-72b-instruct')

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder,PromptTemplate

command = '请回答用户的问题:\n{query}'
template = PromptTemplate.from_template(command)

def generic_func(query):
    print('未采用搜索引擎')
    # prompt = template.invoke({'query':query})
    llm_chain = template|llm_qwen
    return llm_chain.invoke(query)

from langchain_community.tools.tavily_search import TavilySearchResults

search_engine = TavilySearchResults(max_results=1)

def search_func(query):
    print('采用了搜索引擎')
    
    seach_result = search_engine.invoke(query)[0]['content']
    prompt_template = PromptTemplate.from_template('''
    请根据以下搜索结果,回答用户问题。
    搜索结果:
    {requests_result}
    问题:{query}
    ''')

    llm_chain = prompt_template|llm_qwen
    # llm_chain.invoke({'requests_result':seach_result,'query':query}).content
    return llm_chain.invoke({'requests_result':seach_result,'query':query}).content

tools = [
    Tool(
        name='通用大模型',
        func=generic_func,
        description='利用大模型自身能力,回答问题。'
    ),
    Tool(
        name='搜索引擎',
        func=search_func,
        description='其他模型没有正确答案时,使用该工具。'
    ),
]

from langchain import hub

prompt = hub.pull("hwchase17/react")

agent_chain = create_react_agent(tools=tools, llm=llm_qwen, prompt=prompt)

from langchain.agents import AgentExecutor

agent_executor = AgentExecutor(agent=agent_chain, tools=tools)

agent_executor.invoke({'input':'最近有什么重大新闻?请你先调用搜索引擎来获取答案,然后再调用一次通用大模型来总结获取的答案'})

'''
采用了搜索引擎
未采用搜索引擎

{'input': '最近有什么重大新闻?请你先调用搜索引擎来获取答案,然后再调用一次通用大模型来总结获取的答案',
 'output': '总结如下:\n\n亚马逊云计算CEO近期宣布将推出重大的AI产品更新,显示了亚马逊在人工智能领域的持续投入与创新。这一消息突显了AI技术在当今科技竞赛中的重要性和核心地位,也反映了整个科技行业对人工智能的高度关注及激烈竞争。'}
'''

PS:除了creat_react_agent可以用来构建agent,还有其他很多不同的agent构造的方法,比如
create_react_agent, create_json_agent, create_structured_chat_agent(它们实际上只是prompt不同而已)

你可能感兴趣的:(langchain,android,数据库)