(18-3-02)Agents(智能代理):创建并使用Agents

6.3.2  创建并使用Agents

为了更好地理解Agents,接下来将构建一个含有两种工具的代理:一种是用于在线搜索信息的工具,另一种是用于检索我们已经加载到索引中的特定数据的工具。

1. 设置LangSmith

在实际应用中,Agents代理在返回面向用户的输出之前,会根据输入自主决定采取一系列步骤。这使得调试这些系统特别棘手,同时使得可观察性变得尤为重要。LangSmith在这类情况下尤其有用,在使用LangChain构建代理时,所有步骤都将自动在LangSmith中进行跟踪。要设置LangSmith,只需要设置以下环境变量即可:

export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="你的API密钥"

通过这些设置,LangSmith将帮助开发者监控和审查代理的行为,从而提高系统的可观察性和调试能力,这对于构建可靠和高效的代理系统至关重要。

2. 定义工具

在LangChain中构建Agents代理时,首先需要创建想要使用的工具。在接下来的内容中将使用两个工具:Tavily(用于在线搜索)和检索器。

(1)Tavily

在LangChain中,通过使用其内置工具TavilySearchResults,可以非常轻松的使用Tavily搜索引擎作为工具。TavilySearchResults允许开发者将Tavily搜索引擎集成到他们构建的代理中,以便执行网络搜索任务。下面是在LangChain中使用TavilySearchResults工具的基本步骤:

  1. API密钥:首先需要准备一个Tavily的API密钥。
  2. 设置环境变量:一旦获得了API密钥,需要将其导出为环境变量,以便LangChain可以使用它:
export TAVILY_API_KEY="你的Tavily API密钥"
  1. 导入工具,需要在代码中导入TavilySearchResults工具:
from langchain_community.tools.tavily_search import TavilySearchResults
  1. 创建工具实例:然后可以创建TavilySearchResults的一个实例:
search = TavilySearchResults()
  1. 执行搜索:可以使用上述实例执行搜索查询:
search.invoke("你想要搜索的关键词")

执行后会展示查询结果:

[{'url': 'https://www.weatherapi.com/',
  'content': "{'location': {'name': 'San Francisco', 'region': 'California', 'country': 'United States of America', 'lat': 37.78, 'lon': -122.42, 'tz_id': 'America/Los_Angeles', 'localtime_epoch': 1712847697, 'localtime': '2024-04-11 8:01'}, 'current': {'last_updated_epoch': 1712847600, 'last_updated': '2024-04-11 08:00', 'temp_c': 11.1, 'temp_f': 52.0, 'is_day': 1, 'condition': {'text': 'Partly cloudy', 'icon': '//cdn.weatherapi.com/weather/64x64/day/116.png', 'code': 1003}, 'wind_mph': 2.2, 'wind_kph': 3.6, 'wind_degree': 10, 'wind_dir': 'N', 'pressure_mb': 1015.0, 'pressure_in': 29.98, 'precip_mm': 0.0, 'precip_in': 0.0, 'humidity': 97, 'cloud': 25, 'feelslike_c': 11.5, 'feelslike_f': 52.6, 'vis_km': 14.0, 'vis_miles': 8.0, 'uv': 4.0, 'gust_mph': 2.8, 'gust_kph': 4.4}}"},
 {'url': 'https://www.yahoo.com/news/april-11-2024-san-francisco-122026435.html',
  'content': "2024 NBA Mock Draft 6.0: Projections for every pick following March Madness With the NCAA tournament behind us, here's an updated look at Yahoo Sports' first- and second-round projections for the ..."},
 {'url': 'https://world-weather.info/forecast/usa/san_francisco/april-2024/',
  'content': 'Extended weather forecast in San Francisco. Hourly Week 10 days 14 days 30 days Year. Detailed ⚡ San Francisco Weather Forecast for April 2024 - day/night 🌡️ temperatures, precipitations - World-Weather.info.'},
 {'url': 'https://www.wunderground.com/hourly/us/ca/san-francisco/94144/date/date/2024-4-11',
  'content': 'Personal Weather Station. Inner Richmond (KCASANFR1685) Location: San Francisco, CA. Elevation: 207ft. Nearby Weather Stations. Hourly Forecast for Today, Thursday 04/11Hourly for Today, Thu 04/11 ...'},
 {'url': 'https://weatherspark.com/h/y/557/2024/Historical-Weather-during-2024-in-San-Francisco-California-United-States',
  'content': 'San Francisco Temperature History 2024\nHourly Temperature in 2024 in San Francisco\nCompare San Francisco to another city:\nCloud Cover in 2024 in San Francisco\nDaily Precipitation in 2024 in San Francisco\nObserved Weather in 2024 in San Francisco\nHours of Daylight and Twilight in 2024 in San Francisco\nSunrise & Sunset with Twilight and Daylight Saving Time in 2024 in San Francisco\nSolar Elevation and Azimuth in 2024 in San Francisco\nMoon Rise, Set & Phases in 2024 in San Francisco\nHumidity Comfort Levels in 2024 in San Francisco\nWind Speed in 2024 in San Francisco\nHourly Wind Speed in 2024 in San Francisco\nHourly Wind Direction in 2024 in San Francisco\nAtmospheric Pressure in 2024 in San Francisco\nData Sources\n See all nearby weather stations\nLatest Report — 3:56 PM\nWed, Jan 24, 2024\xa0\xa0\xa0\xa013 min ago\xa0\xa0\xa0\xa0UTC 23:56\nCall Sign KSFO\nTemp.\n60.1°F\nPrecipitation\nNo Report\nWind\n6.9 mph\nCloud Cover\nMostly Cloudy\n1,800 ft\nRaw: KSFO 242356Z 18006G19KT 10SM FEW015 BKN018 BKN039 16/12 A3004 RMK AO2 SLP171 T01560122 10156 20122 55001\n While having the tremendous advantages of temporal and spatial completeness, these reconstructions: (1) are based on computer models that may have model-based errors, (2) are coarsely sampled on a 50 km grid and are therefore unable to reconstruct the local variations of many microclimates, and (3) have particular difficulty with the weather in some coastal areas, especially small islands.\n We further caution that our travel scores are only as good as the data that underpin them, that weather conditions at any given location and time are unpredictable and variable, and that the definition of the scores reflects a particular set of preferences that may not agree with those of any particular reader.\n 2024 Weather History in San Francisco California, United States\nThe data for this report comes from the San Francisco International Airport.'}]

TavilySearchResults封装了与Tavily搜索引擎的交互,使得在LangChain代理中集成在线搜索功能变得更加简单和直接。通过这种方式,代理可以利用网络搜索来获取信息,并将这些信息用于决策或回答用户的查询。

(2)检索器

在LangChain中,创建检索器(Retriever)是一个重要的步骤,它允许代理从自有数据中检索特定信息。创建检索器的基本步骤如下所示:

  1. 导入必要的库:首先,需要从LangChain社区库中导入文档加载器、向量存储、嵌入生成器和文本分割器。
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
  1. 加载文档:使用WebBaseLoader加载指定URL的文档内容。
loader = WebBaseLoader("https://docs.smith.langchain.com/overview")
docs = loader.load()
  1. 文本分割:为了处理长文档,使用RecursiveCharacterTextSplitter将文档分割成较小的块,同时保留一定的重叠部分以维持上下文。
documents = RecursiveCharacterTextSplitter(
    chunk_size=1000, chunk_overlap=200
).split_documents(docs)
  1. 创建向量存储:利用FAISS(一种高效的相似性搜索和密集向量聚类库)和OpenAI生成的嵌入,从文档中创建向量存储。
vector = FAISS.from_documents(documents, OpenAIEmbeddings())
  1. 生成检索器:从向量存储创建检索器,该检索器能够根据查询返回相关的文档。
retriever = vector.as_retriever()
  1. 执行检索:使用检索器执行一个简单的查询,以验证其功能。
retriever.invoke("how to upload a dataset")[0]

执行后会返回检索结果:

{
  "Document": {
    "page_content": "import Clientfrom langsmith.evaluation import evaluateclient = Client()# Define dataset: these are your test casesdataset_name = 'Sample Dataset'dataset = client.create_dataset(dataset_name, description='A sample dataset in LangSmith.')client.create_examples(    inputs=[        {'postfix': 'to LangSmith'},        {'postfix': 'to Evaluations in LangSmith'},    ],    outputs=[        {'output': 'Welcome to LangSmith'},        {'output': 'Welcome to Evaluations in LangSmith'},    ],    dataset_id=dataset.id,)# Define your evaluatordef exact_match(run, example):    return {'score': run.outputs['output'] == example.outputs['output']}experiment_results = evaluate(    lambda input: 'Welcome ' + input['postfix'], # Your AI system goes here    data=dataset_name, # The data to predict and grade over    evaluators=[exact_match], # The evaluators to score the results    experiment_prefix='sample-experiment', # The name of the experiment    metadata={      'version': '1.0.0',      'revision_id':",
    "metadata": {
      "source": "https://docs.smith.langchain.com/overview",
      "title": "Getting started with LangSmith | 🦜️🛠️ LangSmith",
      "description": "Introduction",
      "language": "en"
    }
  }
}
  1. 创建检索器工具:现在已经填充了将要检索的索引,可以轻松地将其转换为工具(代理正确使用的格式)。接下来将检索器封装成一个工具,这样代理就可以在执行任务时使用这个检索器。
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!",
)
  1. 工具列表:现在已经创建了两个工具,我们可以创建一个工具列表,以便在下游使用。下面的代码创建了一个包含所有工具的列表,这些工具将被代理在后续操作中使用。
tools = [search, retriever_tool]

通过上述步骤创建了两个工具:一个用于在线搜索,另一个用于从我们的本地数据检索信息。这使得代理能够更智能地处理信息检索任务,提高了代理的功能性和效率。

3. 创建代理

现在已经定义了工具,接下来可以创建一个代理。请看下面的实现步骤,将创建一个OpenAI Functions类型的代理。

(1)首先,需要选择一个引导代理行为的LLM,此处使用ChatOpenAI。

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

在上述代码中,参数model指定了使用的OpenAI模型,而参数temperature控制了生成响应的随机性。

(2)选择引导代理的提示(prompt):接下来,需要选择或创建一个提示来引导代理的行为。、

#如果获取要使用的提示,可以修改此处
prompt = hub.pull("hwchase17/openai-functions-agent")
prompt.messages

上述代码从LangChain的Hub中拉取了一个预定义的提示模板。

(3)初始化代理:现在,可以使用选定的LLM、提示和工具来初始化代理,代理负责接收输入并决定采取什么行动。比较重要的是,代理本身不执行这些行动(这一点将由下一步的AgentExecutor来完成)。

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

在上述代码中,函数create_tool_calling_agent创建了一个代理,将根据接收到的输入和提示来调用相应的工具。

(4)结合代理与AgentExecutor:最后,将代理(大脑)与AgentExecutor(将重复调用代理并执行工具)内的工具结合起来。

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

在上述代码中,AgentExecutor负责根据代理的决策来执行具体的工具调用,并且可以设置为详细模式(verbose=True),以便在执行过程中提供更多的输出信息。

通过上述步骤,构建了一个完整的代理系统,它结合了先进的语言模型、定制的提示和有用的工具,以实现复杂的任务自动化。

4. 运行代理

接下来将介绍使用LangChain中的代理来执行实际查询的过程,并介绍了如何通过AgentExecutor来运行和观察代理的行为的用法。通过这种方式,代理可以被用来自动化各种基于信息检索和数据处理的任务。

(1)现在可以在前面创建的几个查询的基础上运行代理,例如下面的查询:

agent_executor.invoke({"input": "hi!"})

请注意,目前这些查询都是无状态的(即代理不会记住之前的交互),上述查询将触发代理的响应,例如:

> Entering new AgentExecutor chain...
Hello! How can I assist you today?
> Finished chain.
{'input': 'hi!', 'output': 'Hello! How can I assist you today?'}

(2)查询LangSmith的帮助:可以使用代理解答有关LangSmith如何帮助测试的问题。

agent_executor.invoke({"input": "how can langsmith help with testing?"})

上述代理将调用langsmith_search工具,并返回有关LangSmith如何辅助测试的详细信息。

(3)检索天气信息:还可以使用代理检索关于特定地点(如旧金山)的天气信息。

agent_executor.invoke({"input": "whats the weather in sf?"})

执行上述代码,代理将调用tavily_search_results_json工具来搜索并返回旧金山的天气情况,在通过代理获取的输出结果中可能包括当前天气状况、温度、风速和湿度等信息,如:

{'input': 'whats the weather in sf?', 'output': 'The current weather in San Francisco is partly cloudy with a temperature of 52.0°F (11.1°C). The wind speed is 3.6 kph coming from the north, and the humidity is at 97%.'}

(4)代理执行器(AgentExecutor):AgentExecutor是执行代理决策并运行工具的组件,它将重复调用代理并执行所需的工具,同时提供了详细的执行过程输出。

5. 添加记忆功能

到目前为止,前面创建的代理是无状态的,这意味着它不会记住之前的交互,在接下来将介绍为代理添加记忆功能的方法。通过添加记忆功能,代理能够根据之前的交互来提供更加个性化和连贯的回答,这对于构建能够进行复杂对话和提供个性化服务的智能代理系统是非常重要的。

(1)为了让代理具有记忆功能,需要在每次调用时传入先前的chat_history(对话历史)。例如在下面的代码中传入了一个空的消息列表作为chat_history。

agent_executor.invoke({"input": "hi! my name is bob", "chat_history": []})

这意味着这是与代理的第一次交互,所以没有先前的对话消息。尽管是空的,这仍然为将来可能的交互建立了一个框架,使得代理能够开始跟踪消息历史。例如下面可能是此时代理的响应例子:

> Entering new AgentExecutor chain...
Hello Bob! How can I assist you today?

> Finished chain.

{'input': 'hi! my name is bob',
 'chat_history': [],
 'output': 'Hello Bob! How can I assist you today?'}

在后续的交互中,chat_history 将包含之前交换的消息,这样代理就可以根据之前的对话内容来提供更加相关和连贯的响应。这种设计允许代理随着时间的推移而“记忆”用户的交互,从而模拟更自然和个性化的对话体验。

(2)使用消息类:为了在后续的交互中使用对话历史,需要从langchain_core.message中导入类AIMessage和类HumanMessage。

from langchain_core.messages import AIMessage, HumanMessage

(3)调用带有对话历史的代理:接下来传递包含之前对话消息的列表和新的输入给代理。

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?",
    }
)

下面是此时上述代理的响应例子:

> Entering new AgentExecutor chain...
Your name is Bob. How can I assist you, Bob?

> Finished chain.

{'chat_history': [HumanMessage(content='hi! my name is bob'),
  AIMessage(content='Hello Bob! How can I assist you today?')],
 'input': "what's my name?",
 'output': 'Your name is Bob. How can I assist you, Bob?'}

(4)自动跟踪消息:如果想要自动跟踪这些消息,可以将代理包装在一个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,
    lambda session_id: message_history,
    input_messages_key="input",
    history_messages_key="chat_history",
)

(5)使用包装后的代理:现在我们可以调用agent_with_chat_history,它将自动包含对话历史。

agent_with_chat_history.invoke(
    {"input": "hi! I'm bob"},
    config={"configurable": {"session_id": "<foo>"}}
)

下面是此时上述代理的响应例子:

> Entering new AgentExecutor chain...
Hello Bob! How can I assist you today?

> Finished chain.

{'input': "hi! I'm bob",
 'chat_history': [],
 'output': 'Hello Bob! How can I assist you today?'}

(6)再次使用一个具有记忆功能的代理来处理查询。

agent_with_chat_history.invoke(
    {"input": "what's my name?"},
    # 这是因为在大多数真实场景中,需要一个会话ID
    # 在这里并没有真正使用它,因为我们使用的是一个简单的、在内存中的ChatMessageHistory
    config={"configurable": {"session_id": "<foo>"}},
)

上面代码中的注释部分解释了为什么在调用invoke方法时传递了一个config参数,其中包含了一个session_id。下面是此时上述代理的响应例子:

> Entering new AgentExecutor chain...
Your name is Bob! How can I help you, Bob?

> Finished chain.

{'input': "what's my name?",
 'chat_history': [HumanMessage(content="hi! I'm bob"),
  AIMessage(content='Hello Bob! How can I assist you today?')],
 'output': 'Your name is Bob! How can I help you, Bob?'}

在实际应用中,会话ID通常用于跟踪和管理特定的用户会话,但在当前的示例中,由于使用了简单的、在内存中的ChatMessageHistory,会话ID并没有被实际使用。<foo>是一个占位符,表示在实际使用时应该替换为一个有效的会话ID。

未完待续

  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
ML-Agents报错"AttributeError: 'str' object has no attribute '_key'"通常是由于对象没有定义"_key"属性导致的。根据引用中的信息,我们可以推断出可能是在比较两个对象时使用了"_key"方法,而其中一个对象是字符串类型而不是一个带有"_key"属性的对象。 为了解决这个问题,我们可以检查代码中的比较操作,确保在比较之前两个对象都是正确的类型。特别是,检查涉及到"_key"属性的代码部分,确保它们正确使用并且预期的对象类型是正确的。 如果问题仍然存在,我们可以尝试使用调试工具来进一步检查代码执行过程中的变量值和对象类型。这可以帮助我们确定问题所在并找到解决方法。 另外,根据引用中的信息,还有可能在运行过程中遇到了Unity环境响应超时的问题。这可能导致与ML-Agents相关的操作无法顺利进行。要解决这个问题,可以检查Unity环境是否需要用户交互才能启动,确保代理与脑部的链接正确,以及环境和Python接口的版本是否兼容。 最后,引用中提到了一些可能导致问题的原因和解决方法,例如ML-Agents安装不完全或防火墙阻止了通信端口。如果以上解决方法不起作用,您可以尝试重新下载并安装ML-Agents,确保按照正确的方式进行安装,并且关闭防火墙再次尝试。 综上所述,要解决ML-Agents报错"AttributeError: 'str' object has no attribute '_key'",我们可以按照以下步骤进行操作: 1. 检查比较操作的代码,确保涉及"_key"属性的部分使用正确并且对象类型正确。 2. 使用调试工具检查变量值和对象类型,以确定问题所在。 3. 检查Unity环境响应超时问题,确保环境启动不需要用户交互,代理与脑部的链接正确,以及环境和Python接口的版本兼容。 4. 尝试重新下载并安装ML-Agents,确保按照正确的方式进行安装。 5. 如果防火墙阻止了通信端口,关闭防火墙再次尝试。 希望以上信息对您有帮助!如果问题仍然存在,请提供更多详细信息,以便我们能够更准确地为您解答。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值