Agent | langchain实战课笔记

33 阅读5分钟

1.结构化工具

2023年初,LangChain 引入了“多操作”代理框架,允许代理计划执行多个操作。在此基础上,LangChain 推出了结构化工具对话代理,允许更复杂、多方面的交互。

通过指定AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION 这个代理类型,代理能够调用包含一系列复杂工具的“结构化工具箱”,组合调用其中的多个工具,完成批次相关的任务集合。

playwright

  • 开源的自动化框架
  • 可以模拟真实用户操作网页,帮助开发者和测试者自动化网页交互和测试
  • 支持多种浏览器

安装

pip install playwright安装Playwright工具

playwright install 安装三种常用的浏览器工具

demo调用

导航到指定的URL;获取页面标题并打印页面的标题;最后关闭浏览器。

from playwright.sync_api import sync_playwright

def run():
    # 使用Playwright上下文管理器
    with sync_playwright() as p:
        # 使用Chromium,但你也可以选择firefox或webkit
        browser = p.chromium.launch()
        
        # 创建一个新的页面
        page = browser.new_page()
        
        # 导航到指定的URL
        page.goto('https://langchain.com/')
        
        # 获取并打印页面标题
        title = page.title()
        print(f"Page title is: {title}")
        
        # 关闭浏览器
        browser.close()

if __name__ == "__main__":
    run()

2. 使用结构化工具对话代理

PlayWrightBrowserToolkit:LangChain中基于PlayWrightBrowser包封装的工具箱

使用代理类型: STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION

对话提问:询问某URL的信息

from langchain.agents.agent_toolkits import PlayWrightBrowserToolkit
from langchain.tools.playwright.utils import create_async_playwright_browser

async_browser = create_async_playwright_browser()
toolkit = PlayWrightBrowserToolkit.from_browser(async_browser=async_browser)
tools = toolkit.get_tools()
print(tools)

from langchain.agents import initialize_agent, AgentType
from langchain.chat_models import ChatAnthropic, ChatOpenAI

# LLM不稳定,对于这个任务,可能要多跑几次才能得到正确结果
llm = ChatOpenAI(temperature=0.5)  

agent_chain = initialize_agent(
    tools,
    llm,
    agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True,
)

async def main():
    response = await agent_chain.arun("What are the headers on python.langchain.com?")
    print(response)

import asyncio
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

模型会选择调用 PlayWrightBrowserToolkit中的navigate_browser和get_elements工具。

debug

  • 报错1

    URL scheme must be 'http' or 'https' (type=value_error)

    解决:在question的url加上https

  • 报错2

    bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser library?

    解决: pip install lxml

  • 报错3

    from playwright.sync_api import sync_playwright ImportError: cannot import name 'sync_playwright' from 'playwright.sync_api'

    • 解决:

      1.确保playwright的安装;

      2.确保当前目录没有文件命名为playwright.py

3.Self-Ask with Search 代理

利用一种叫做 “Follow-up Question(追问)”加“Intermediate Answer(中间答案)”的技巧,来辅助大模型寻找事实性问题的过渡性答案,从而引出最终答案。

agent=AgentType.SELF_ASK_WITH_SEARCH


import os

os.environ["SERPAPI_API_KEY"] = (
    "your key"
)

llm = ChatOpenAI(
    model=os.environ["LLM_MODELEND"],
    base_url=os.environ["OPENAI_BASE_URL"],
    temperature=0,
)

search = SerpAPIWrapper()
tools = [
    Tool(
        name="Intermediate Answer",
        func=search.run,
        description="useful for when you need to ask with search",
    )
]

self_ask_with_search = initialize_agent(
    tools, llm, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True
)
self_ask_with_search.run("使用玫瑰作为国花的国家的首都是哪里?")

通过大模型的两次follow-up追问,搜索工具给出了两个中间答案,最后给出了问题的最终答案——伦敦

4.Plan and execute 代理

  • 计划由一个大语言模型代理(负责推理)完成。
  • 执行由另一个大语言模型代理(负责调用工具)完成。

提问:"在纽约,100美元能买几束玫瑰?"

报错:

ValueError: unknown format from LLM: There is no specific value provided for the average price of roses in New York, so it's not possible to provide a specific expression and output for this question.

debug

  1. “平均价格测试”

    这个问题在使用ZERO_SHOT_REACT_DESCRIPTION代理,直接调用["serpapi", "llm-math"]时是可以完成的:目前市场上玫瑰花的平均价格是多少?如果我在此基础上加价15%卖出,应该如何定价?

    而在plan&excute代理当前代码会报错ValueError: unknown format from LLM: 请你明确一下“平均价格”具体是多少,以便我能完整地进行计算和回答。

    改成“价格”偶尔能运行成功,但仍有失误。

    说明不是“平均”难以理解,而是代理没有正确触发搜索工具调用。

  2. 多运行几次,最终有结果->当前调用的llm不稳定

> Entering new PlanAndExecute chain...
steps=[Step(value='确定纽约玫瑰的平均价格。'), Step(value='用 100 美元除以玫瑰的平均价格,得到能购买的玫瑰束数。'), Step(value='给定以上步骤,回答用户关于在纽约 100 美元能买几束玫瑰的问题。\n')]

> Entering new AgentExecutor chain...
{
  "action": "Search",
  "action_input": "纽约玫瑰的平均价格"
}

> Finished chain.
*****

Step: 确定纽约玫瑰的平均价格。

Response: {
  "action": "Search",
  "action_input": "纽约玫瑰的平均价格"
}

> Entering new AgentExecutor chain...
Question:100 美元除以玫瑰的平均价格,得到能购买的玫瑰束数。
Thought: 第一步查询到纽约玫瑰的平均价格为 1.5 美元,现在需要用 100 美元除以 1.5 美元来计算能购买的玫瑰束数。
Action:
```
{
  "action": "Calculator",
  "action_input": "100 / 1.5"
}
```


> Entering new LLMMathChain chain...
100 / 1.5```text
100 / 1.5
```
...numexpr.evaluate("100 / 1.5")...

Answer: 66.66666666666667
> Finished chain.

Observation: Answer: 66.66666666666667
Thought:Action:
```
{
  "action": "Final Answer",
  "action_input": "用 100 美元除以纽约玫瑰的平均价格 1.5 美元,得到能购买的玫瑰束数约为 66.67 束。"
}
```

> Finished chain.
*****

Step:100 美元除以玫瑰的平均价格,得到能购买的玫瑰束数。

Response:100 美元除以纽约玫瑰的平均价格 1.5 美元,得到能购买的玫瑰束数约为 66.67 束。

> Entering new AgentExecutor chain...
Thought: The previous steps have already calculated that with $100, one can buy approximately 66.67 bundles of roses in New York.
Action:
```
{
  "action": "Final Answer",
  "action_input": "在纽约 100 美元大约能买 66.67 束玫瑰。"
}
```


> Finished chain.
*****

Step: 给定以上步骤,回答用户关于在纽约 100 美元能买几束玫瑰的问题。


Response: 在纽约 100 美元大约能买 66.67 束玫瑰。
> Finished chain.