Want to Become a Sponsor? Contact Us Now!🎉

langchain-tutorials
如何利用LangChain代理进行强大的自动化任务

如何利用LangChain代理进行强大的自动化任务

Published on

在魅力十足的语言模型和自动化的世界中,LangChain代理作为创新的标志尤为突出,它使开发人员和技术爱好者能够创建复杂的、自动化的任务,这些任务看起来就像科幻小说中的情节。如果您想要深入了解LangChain代理的世界,但不知道从哪里开始,那么您来对地方了。本指南将揭示这个过程的秘密,使其变得易于理解和简单。所以,请泡一杯咖啡,我们一起踏上这个激动人心的旅程吧。

Anakin AI - The Ultimate No-Code AI App Builder

如何使用LangChain代理:快速入门

为了更好地了解代理框架,让我们构建一个具有两个工具的代理:一个用于在线查找信息,一个用于查找我们加载到索引中的特定数据。

在此之前,需要了解LLMs和检索的知识,如果您还没有探索这些部分,建议您先了解一下。

设置:LangSmith
根据定义,代理在返回用户可见的输出之前,会根据自身决定的、与输入相关的步骤序列执行。这使得调试这些系统尤其棘手,观测性尤为重要。在这种情况下,使用LangSmith尤为有用。

在使用LangChain构建时,所有步骤都将自动在LangSmith中进行跟踪。要设置LangSmith,我们只需要设置以下环境变量:

export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="<your-api-key>"

定义工具
首先,我们需要创建要使用的工具。我们将使用两个工具:Tavily(用于在线搜索)和我们将创建的本地索引上的检索器。

  • Tavily
    在LangChain中有一个内置的工具,可以方便地将Tavily搜索引擎作为工具使用。请注意,这需要一个API密钥-他们有一个免费的套餐,但如果您没有其中一个或不想创建一个,您可以随时忽略这一步。

创建您的API密钥后,您需要将其导出为:

export TAVILY_API_KEY="..."
from langchain_community.tools.tavily_search import TavilySearchResults
 
search = TavilySearchResults()
 
search.invoke("what is the weather in SF")
  • 检索器
    我们还将为我们自己的一些数据创建一个检索器。有关此处每个步骤的更详细说明,请参阅此部分。
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
 
loader = WebBaseLoader("https://docs.smith.langchain.com/overview")
docs = loader.load()
documents = RecursiveCharacterTextSplitter(
    chunk_size=1000, chunk_overlap=200
).split_documents(docs)
vector = FAISS.from_documents(documents, OpenAIEmbeddings())
retriever = vector.as_retriever()
 
retriever.get_relevant_documents("how to upload a dataset")[0]

现在,我们已经填充了要进行检索的索引,我们可以很容易地将其转换为工具(代理正常使用的格式)。

from langchain.tools.retriever import create_retriever_tool
 
retriever_tool = create_retriever_tool(
    retriever,
    "langsmith_search",
    "Search for information about LangSmith. For any questions about LangSmith, you must use this tool!",
)

工具
现在,我们已经创建了这两个工具,我们可以创建一个工具列表,我们将在下游中使用。

tools = [search, retriever_tool]

如何创建LangChain代理

现在,我们已经定义了工具,我们可以创建代理了。我们将使用OpenAI函数代理-有关此类型代理以及其他选项的更多信息,请参阅本指南。

首先,我们选择我们希望引导代理的LLM。

from langchain_openai import ChatOpenAI
 
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

接下来,我们选择要用于引导代理的提示。

from langchain import hub
 
# 获取要使用的提示 - 您可以修改这个!
prompt = hub.pull("hwchase17/openai-functions-agent")
prompt.messages

现在,我们可以使用LLM、提示和工具初始化代理。代理负责接收输入并决定采取什么操作。至关重要的是,代理不执行这些操作-由代理执行器(下一步)执行。有关如何思考这些组件的更多信息,请参阅我们的概念指南。

from langchain.agents import create_openai_functions_agent
 
agent = create_openai_functions_agent(llm, tools, prompt)

最后,我们将代理(大脑)与AgentExecutor内部的工具组合在一起(AgentExecutor将重复调用代理并执行工具)。有关如何思考这些组件的更多信息,请参阅我们的概念指南。

from langchain.agents import AgentExecutor
 
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

运行代理
现在,我们可以在几个查询上运行代理!请注意,就目前而言,这些都是无状态查询(它不会记住先前的交互)。

agent_executor.invoke({"input": "hi!"})
agent_executor.invoke({"input": "how can langsmith help with testing?"})
agent_executor.invoke({"input": "what's the weather in sf?"})

添加内存

如前所述,此代理程序是无状态的。这意味着它不会记住先前的交互。为了给它记忆,我们需要传入先前的chat_history。注意:由于我们使用的提示,它需要被称为chat_history。如果我们使用不同的提示,我们可以更改变量名。

# 这里我们传入一个空的消息列表chat_history,因为这是聊天中的第一条消息
agent_executor.invoke({"input": "hi! my name is bob", "chat_history": []})
from langchain_core.messages import AIMessage, HumanMessage
 
agent_executor.invoke(
    {
        "chat_history": [
            HumanMessage(content="hi! my name is bob"),
            AIMessage(content="Hello Bob! How can I assist you today?"),
        ],
        "input": "what's my name?",
    }
)

如果我们想自动跟踪这些消息,我们可以将它包装在一个RunnableWithMessageHistory中。有关如何使用它的更多信息,请参阅此指南。

from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
 
message_history = ChatMessageHistory()
 
agent_with_chat_history = RunnableWithMessageHistory(
    agent_executor,
    # 这是必需的,因为在大多数现实世界的情况下,需要一个会话ID
    # 在这里没有真正使用,因为我们使用的是简单的内存ChatMessageHistory
    lambda session_id: message_history,
    input_messages_key="input",
    history_messages_key="chat_history",
)
 
agent_with_chat_history.invoke(
    {"input": "hi! I'm bob"},
    # 这是必需的,因为在大多数现实世界的情况下,需要一个会话ID
    # 在这里没有真正使用,因为我们使用的是简单的内存ChatMessageHistory
    config={"configurable": {"session_id": "<foo>"}},
)

LangChain代理的类型

代理类型

在LangChain代理的领域中,多样性是游戏的名字。这些代理以各种不同的方式出现,每一种都适合不同的任务和能力。让我们探索Agent类型的细微差别,分解它们的模型类型、聊天历史支持、多输入工具、并行函数调用和所需的模型参数。了解这些类别将帮助您选择适合您需求的完美代理。

  • OpenAI工具: 这是针对最新的OpenAI模型(从1106开始)进行优化的前沿代理。它专为处理聊天互动、支持多输入工具和执行并行函数调用而设计,需要'工具'模型参数。非常适合利用OpenAI最新产品的人士。

  • OpenAI函数: 定制用于模仿OpenAI函数调用能力的OpenAI或经过微调的开源模型。它在聊天环境中表现出色,处理多输入工具,并需要'函数'模型参数。对于擅长函数调用的模型来说是一个不错的选择。

  • XML: 这个代理适用于擅长XML的模型,比如Anthropic的模型。它为LLM(而不是聊天模型)构建,支持聊天历史,并最适合与需要单个字符串输入的非结构化工具一起使用。当与精通XML的模型一起工作时,请选择这个代理。

  • 结构化聊天: 这是一个多才多艺的代理,在基于聊天的应用中表现出色,并支持具有多个输入的工具。它不需要额外的模型参数,是需要处理复杂工具互动的项目的好选择。

  • JSON聊天: 这针对在JSON方面表现出色的模型而设计,适用于聊天应用程序。它简化了与友好的JSON模型一起工作的过程,简化了基于聊天的应用程序的开发。

  • ReAct: 这是一个简单但有效的代理,专为基本的LLM应用程序量身定制。对于需要简单实现的简单模型来说是一个很好的起点。

  • 自问自答与搜索: 这是适用于具有单个搜索工具的简单模型的理想选择,适用于需要简洁、集中的工具集的项目。

每种代理类型都有其自己的优势,因此将代理与您项目的特定要求匹配起来非常重要。无论您需要聊天历史记录、多输入工具还是并行函数调用的支持,都有一个适合满足这些需求的代理。考虑任务的复杂性、选择的语言模型的能力以及应用程序处理的交互性质。通过将这些因素与正确的代理类型相匹配,您可以发挥LangChain代理在项目中的全部潜力,为创新性的解决方案和简化的工作流程铺平道路。

通过深入了解LangChain代理的细微差别,本指南旨在提供对不同代理类型的深入理解和实际应用。通过探索详细的示例代码和场景,您将获得有关选择和实施最适合项目需求的代理的见解。让我们深入研究LangChain代理的核心,通过示例突出其独特功能和能力。

LangChain代理 #1:OpenAI工具代理

OpenAI工具代理专为与最新的OpenAI模型无缝配合工作而设计,方便同时执行多个函数或“工具”。当您的应用程序需要与多个外部API进行交互或并行执行多个任务时,这个代理特别有用,从而减少总体处理时间。

示例代码:

# 导入所需库和工具
from langchain import hub
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_openai import ChatOpenAI
 
# 初始化Tavily Search工具
tools = [TavilySearchResults(max_results=1)]
 
# 检索提示并设置LLM
prompt = hub.pull("hwchase17/openai-tools-agent")
llm = ChatOpenAI(model="gpt-3.5-turbo-1106", temperature=0)
 
# 创建OpenAI工具代理
 
agent = create_openai_tools_agent(llm, tools, prompt)
 
# 使用样例输入执行代理
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
response = agent_executor.invoke({"input": "LangChain是什么?"})
print(response)

在这个示例中,create_openai_tools_agent 函数构建了一个代理,该代理可以利用OpenAI模型根据输入智能地决定何时调用一个或多个工具。这里使用了Tavily Search工具来演示Web搜索的功能。

LangChain Agents #2:OpenAI Functions Agent

OpenAI Functions代理最适合需要模型根据输入决定是否以及调用哪个函数的任务。虽然与Tools代理类似,但它专门针对函数调用是任务的核心的场景进行设计,OpenAI在较新的模型中已经弃用了这种方法,而更倾向于使用工具。

示例代码:

# 配置OpenAI Functions代理
from langchain import hub
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_openai import ChatOpenAI
 
# 初始化工具并选择LLM
tools = [TavilySearchResults(max_results=1)]
prompt = hub.pull("hwchase17/openai-functions-agent")
llm = ChatOpenAI(model="gpt-3.5-turbo-1106")
 
# 构建并运行OpenAI Functions代理
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
response = agent_executor.invoke({"input": "LangChain是什么?"})
print(response)

这个示例展示了如何设置和使用OpenAI Functions代理,利用Tavily Search作为工具来演示代理根据用户查询调用特定函数的能力。

LangChain Agents #3:XML Agent

XML Agent专为擅长生成和解释XML结构的模型进行优化。当处理结构化数据或者模型与代理之间的互动从结构化的XML格式中获益时,该代理类型具有优势。

示例代码:

# 初始化XML Agent
from langchain import hub
from langchain.agents import AgentExecutor, create_xml_agent
from langchain_community.chat_models import ChatAnthropic
from langchain_community.tools.tavily_search import TavilySearchResults
 
tools = [TavilySearchResults(max_results=1)]
prompt = hub.pull("hwchase17/xml-agent-convo")
llm = ChatAnthropic(model="claude-2")
 
# 创建并运行XML代理
agent = create_xml_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
response = agent_executor.invoke({"input": "LangChain是什么?"})
print(response)

这个设置展示了如何使用XML代理与Claude-2进行交互,Claude-2是一个擅长处理XML的Anthropic模型。XML格式提供了代理与模型之间结构化交流的一种方式,促进了复杂数据处理。

LangChain Agents #4:JSON Chat Agent

JSON Chat Agent利用JSON格式进行输出,使其适用于需要结构化响应数据的应用程序。该代理非常适用于擅长处理和生成JSON结构的聊天模型。

示例代码:

# 配置JSON Chat Agent
from langchain import hub
from langchain.agents import AgentExecutor, create_json_chat_agent
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_openai import ChatOpenAI
 
tools = [TavilySearchResults(max_results=1)]
prompt = hub.pull("hwchase17/react-chat-json")
llm = ChatOpenAI()
 
# 创建并执行JSON Chat Agent
agent = create_json_chat_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)
response = agent_executor.invoke({"input": "LangChain是什么?"})
print(response)

这里使用JSON Chat Agent来处理输入并生成JSON结构化响应,利用Tavily Search工具进行Web搜索功能。该代理特别适用于需要进一步处理的结构化响应或与用户进行更结构化交互的场景。

LangChain Agents #5:Structured Chat Agent

Structured Chat Agent在需要多输入工具的情况下表现出色,使复杂交互能够考虑到每个工具调用所需的多个参数。该代理旨在促进需要考虑每个工具调用的多个参数的复杂工作流。

示例代码:

# 初始化Structured Chat Agent
from langchain import hub
from langchain.agents import AgentExecutor, create_structured_chat_agent
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_openai import ChatOpenAI
 
tools = [TavilySearchResults(max_results=1)]
prompt = hub.pull("hwchase17/structured-chat-agent")
llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-1106")
 
# 构建并运行Structured Chat Agent
agent = create_structured_chat_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)
response = agent_executor.invoke({"input": "LangChain是什么?"})
print(response)

这个示例演示了如何使用Structured Chat Agent有效地与多输入工具进行交互。通过指定详细的提示并选择适当的语言模型,该代理可以无缝地处理复杂的查询和工具交互。 通过了解LangChain代理商的区别和功能,开发人员可以更好地定制他们的应用程序,以利用语言模型和自动化任务的全部潜力。无论您的应用程序需要简单的函数调用、结构化数据处理还是复杂的多工具交互,都有适合的LangChain代理商。有了这些示例作为基础,您将准备好开始构建更智能、高效和响应更灵敏的应用程序之旅。

结论

总而言之,LangChain代理商为开发人员提供了一个多功能、强大的工具包,用于将先进的语言模型功能集成到他们的应用程序中。通过了解每种代理类型的细微差别 --- 从OpenAI工具和函数代理到XML、JSON Chat和结构化Chat代理--- 您可以选择适合您项目特定需求的正确工具。这些代理商可以处理广泛的任务,从简单的函数调用到涉及多个输入和结构化数据格式的复杂交互。