LangChain(六)——Agents

LangChain模块架构图 [1]

一、智能体架构:Agent

1.1 什么是智能体(Agent)

将大语言模型作为一个推理引擎。给定一个任务,智能体自动生成完成任务所需的步骤,执行相应动作(例如选择并调用工具),直到任务完成。

Agent 继承了 Chain 的所有能力

  • Chain 的能力构成了 Agent 的 “推理链” 能力基础
    • Agent 的执行器(Executor)就是基于 LLM Chain 实现的
  • Agent 自身具备和 Chain 类似的 “调用 / 执行” 接口的能力

AgentChain 的能力基础上 进化出了两个核心能力

  • 一条思考链Chain of Thought):Agent 可以规划和调度推理链,会思考分步骤的、每一步的行动
  • 一个工具箱(Toolbox):Agent 自带工具体系,可以接入并调用外部工具(工具可以按既定接口规范定制)
    • Agent 只关注每个工具的输入输出(格式及内容),工具内部可以自行进行本地和 Web 接口调用

1.2 智能体类型:ReAct

ReAct: Synergizing Reasoning and Acting in Language Models

ReAct机制:

ReAct 使用大语言模型同时生成推理链和行动,两者交替出现,相互支持:

  • 推理链帮助 Agent 制定、跟踪和更新行动计划
  • 行动让 Agent 与环境上下文交互,获取更多信息支持推理

流程概览:给出任务 ➡️ 推理下一步行动 ➡️ 行动并更新环境 ➡️ 观察并推理下一步行动 ➡️ 循环直至任务完成

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
37
38
39
40
41
42
from langchain_community.utilities import SerpAPIWrapper
from langchain.tools import Tool, tool
import calendar
import dateutil.parser as parser
from datetime import date
import json
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_react_agent
from langchain.agents import load_tools, initialize_agent
from langchain.agents import AgentType
from langchain import hub

search = SerpAPIWrapper(params={'location': 'Austin,Texas,United States','engine': 'google', 'gl': 'us', 'google_domain': 'google.com', 'hl': 'en'})
tools = [
Tool.from_function(
func=search.run,
name="Search",
description="useful for when you need to answer questions about current events,if you do not know the questions,you can search"
),
]


# 自定义工具
@tool("weekday")
def weekday(date_str: str) -> str:
"""Input format is YYYY-MM-DD. Convert date to weekday name"""
d = parser.parse(date_str)
return calendar.day_name[d.weekday()]


tools += [weekday]

llm = ChatOpenAI(model_name='gpt-4-turbo', temperature=0)

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

print(prompt.template)

agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

agent_executor.invoke({"input":"周杰伦出生那天是星期几"})
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
37
38
39
Answer the following questions as best you can. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin!

Question: {input}
Thought:{agent_scratchpad}


> Entering new AgentExecutor chain...
The question asks for the day of the week on which Jay Chou (周杰伦) was born. First, I need to find out his birthdate.

Thought: I need to find Jay Chou's birthdate.
Action: Search
Action Input: Jay Chou birthdate
January 18, 1979Now that I have Jay Chou's birthdate, I can use the weekday tool to find out the day of the week he was born.

Action: weekday
Action Input: 1979-01-18

ThursdayI now know the final answer.

Final Answer: 周杰伦出生那天是星期四。 (Jay Chou was born on a Thursday.)

> Finished chain.
{'input': '周杰伦出生那天是星期几',
'output': '周杰伦出生那天是星期四。 (Jay Chou was born on a Thursday.)'}

LangSmith流程展现:

1.3 智能体类型:SelfAskWithSearch

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

SelfAskWithSearch流程:

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 import hub
from langchain.agents import AgentExecutor, create_self_ask_with_search_agent
from langchain_community.llms import Fireworks
from langchain_community.utilities import SerpAPIWrapper
from langchain_community.tools.tavily_search import TavilyAnswer
from langchain.tools import Tool, tool
from langchain_openai import OpenAI

#llm = OpenAI()

search = SerpAPIWrapper(params={'location': 'Austin,Texas,United States','engine': 'google', 'gl': 'us', 'google_domain': 'google.com', 'hl': 'en'})


tools = [
Tool(
name="Intermediate Answer",
func=search.run,
description="A search engine optimized for comprehensive, accurate, and trusted results. Useful for when you need to answer questions about current events. Input should be a search query. This returns only the answer - not the original source data.",
)
]

#下载prompt
prompt = hub.pull("hwchase17/self-ask-with-search")

#OpenAI的模型老是输出格式有问题,这里参考官方文档
llm = Fireworks()

# Construct the Self Ask With Search Agent
agent = create_self_ask_with_search_agent(llm, tools, prompt)

# Create an agent executor by passing in the agent and tools
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

agent_executor.invoke(
{"input": "What is the hometown of the reigning men's U.S. Open champion?"}
)
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
37
38
39
40
41
42
43
44
45
46
47
Question: Who lived longer, Muhammad Ali or Alan Turing?
Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali

Question: When was the founder of craigslist born?
Are follow up questions needed here: Yes.
Follow up: Who was the founder of craigslist?
Intermediate answer: Craigslist was founded by Craig Newmark.
Follow up: When was Craig Newmark born?
Intermediate answer: Craig Newmark was born on December 6, 1952.
So the final answer is: December 6, 1952

Question: Who was the maternal grandfather of George Washington?
Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball

Question: Are both the directors of Jaws and Casino Royale from the same country?
Are follow up questions needed here: Yes.
Follow up: Who is the director of Jaws?
Intermediate answer: The director of Jaws is Steven Spielberg.
Follow up: Where is Steven Spielberg from?
Intermediate answer: The United States.
Follow up: Who is the director of Casino Royale?
Intermediate answer: The director of Casino Royale is Martin Campbell.
Follow up: Where is Martin Campbell from?
Intermediate answer: New Zealand.
So the final answer is: No

Question: {input}
Are followup questions needed here:{agent_scratchpad}


> Entering new AgentExecutor chain...
`Yes.`
`Follow up: Who is the reigning men's U.S. Open champion?`Novak Djokovic`Follow up: Where is Novak Djokovic from?`["Belgrade is the capital of the southeast European country of Serbia. Its most significant landmark is the Beogradska Tvrđava, an imposing fortress at the confluence of the Danube and the Sava rivers. The fort is a testament to the city’s strategic importance to the Roman, Byzantine, Ottoman, Serbian and Austrian empires, and it's now the site of several museums as well as Kalemegdan, a vast park. ― Google", 'Belgrade type: Capital of Serbia.', 'Belgrade entity_type: cities, locations, travel, travel.', 'Belgrade kgmid: /m/0fhzf.', 'Belgrade place_id: ChIJvT-116N6WkcR5H4X8lxkuB0.', 'Belgrade area: 139 mi².', 'Belgrade elevation: 384′.', 'Belgrade population: 1.374 million (2016).', 'Belgrade metro_population: 1,681,405.', 'Belgrade colleges_and_universities: University of Belgrade.', "Novak Djokovic (born May 22, 1987, Belgrade, Serbia, Yugoslavia [now in Serbia]) is a Serbian tennis player who is one of the greatest men's ...", "Novak Djokovic is a professional tennis player from Serbia and is considered by many to be the greatest men's tennis player of all time.", 'Novak Djokovic, who was born on May 22, 1987, in Serbia, is a professional tennis player. He is married to Jelena Ristić and has two siblings -- Djordje and ...', 'Novak Djokovic (born 22 May 1987) is a Serbian professional tennis player. Last updated on: 11 September 2023.', 'Official tennis player profile of Novak Djokovic on the ATP Tour. Featuring news, bio, rankings, playing activity, coach, stats, win-loss, points breakdown, ...', 'Novak Djokovic is from Serbia.\u200b\u200b On May 22, 1987, in Belgrade, SR Serbia, SFR Yugoslavia, Novak Djokovic was born to Dijana and Srdjan Djokovic. His Serbian ...', 'I grew up on a mountain here in Serbia and spent a lot of my childhood climbing mountains, hills and just going up and down, spending time in ...', "Get all the latest Novak Djokovic news, stats, performance, facts, history, and biography. Also, Get Novak Djokovic's latest career stats, wins, ..."]`Follow up: What is the hometown of Novak Djokovic?`Novak Djokovic (born May 22, 1987, Belgrade, Serbia, Yugoslavia [now in Serbia]) is a Serbian tennis player who is one of the greatest men's players in the history of the game.`So the final answer is: Belgrade`

> Finished chain.
{'input': "What is the hometown of the reigning men's U.S. Open champion?",
'output': 'Belgrade'}

LangSmith流程展现:

工具集合Agent包含解决问题所必须的搜索工具,可以用来查询和验证多个信息点
逐步逼近Agent可以根据第一个问题的答案,提出进一步的问题,直到得到最终答案。这种逐步逼近的方式可以确保答案的准确性。
自我提问与搜索Agent可以自己提问并搜索答案。
决策链Agent通过一个决策链来执行任务,使其可以跟踪和处理复杂的多跳问题,这对于解决需要多步推理的问题尤为重要。

1.4 智能体类型:Plan and Execute

Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models

Zero-Shot:代表0样例

顾名思义,Agent 通过首先计划要做什么,然后执行子任务来实现目标

  • 这个想法很大程度上是受到 BabyAGI 和后来的《Plan-and-Solve Prompting》论文的启发
  • 计划几乎总是由 LLM 完成;执行通常由单独的(带有工具的)Agent 完成

该 Agent 有两个主要的关键步骤:

  1. 首先,Agent 使用 LLM 创建一个计划,以明确的步骤回答查询
  2. 一旦制定了计划,它就会使用传统的 Agent(比如 ReAct)来解决每个步骤

Plan and Execute流程:

其想法是,计划步骤通过将较大的任务分解为更简单的子任务,使 LLM 更加“步入正轨”。但是,与传统 Agent 相比,此方法需要更多单独的 LLM 查询,并且延迟更高。

首先安装依赖

1
pip install langchain_experimental

代码示例

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
37
38
39
40
41
from langchain.chains import LLMMathChain
from langchain_core.tools import Tool
from langchain_community.llms import Fireworks
from langchain_community.utilities import SerpAPIWrapper
from langchain_experimental.plan_and_execute import (
PlanAndExecute,
load_agent_executor,
load_chat_planner,
)
from langchain_openai import ChatOpenAI, OpenAI

#openai的模型老是会进行联想,造成错误
#llm = OpenAI(temperature=0.0)
llm = Fireworks(temperature=0.0)
llm_math_chain = LLMMathChain.from_llm(llm=llm, verbose=True)


search = SerpAPIWrapper(params={'location': 'Austin,Texas,United States','engine': 'google', 'gl': 'us', 'google_domain': 'google.com', 'hl': 'en'})


tools = [
Tool(
name="Search",
func=search.run,
description="useful for when you need to answer questions about current events",
),
Tool(
name="Calculator",
func=llm_math_chain.run,
description="useful for when you need to answer questions about math",
),
]

model = ChatOpenAI(model_name='gpt-3.5-turbo',temperature=0)
planner = load_chat_planner(model)
executor = load_agent_executor(model, tools, verbose=True)
agent = PlanAndExecute(planner=planner, executor=executor)

agent.run(
"Who is the current prime minister of the UK? What is their current age raised to the 0.43 power?"
)
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
> Entering new AgentExecutor chain...
Thought: I can use the Search tool to find the current prime minister of the UK.
Action:
```
{
"action": "Search",
"action_input": "Current prime minister of the UK"
}
```
Observation: Rishi Sunak
Thought:It seems there was an error in the previous search result. Let me correct that for you.
Action:
```
{
"action": "Search",
"action_input": "Current prime minister of the UK"
}
```
Observation: Rishi Sunak
Thought:It appears there might be an issue with the search results. Let me try a different approach to ensure accuracy.
Action:
```
{
"action": "Search",
"action_input": "Who is the current prime minister of the UK 2022"
}
```
Observation: ['Rishi Sunak is a British politician who has served as Prime Minister of the United Kingdom and Leader of the Conservative Party since 2022. The first British Asian prime minister, he previously held two cabinet positions under Boris Johnson, latterly as Chancellor of the Exchequer from 2020 to 2022.', 'Rishi Sunak type: Prime Minister of the United Kingdom.', 'Rishi Sunak entity_type: people, people.', 'Rishi Sunak main_tab_text: Overview.', 'Rishi Sunak kgmid: /g/11b6ctfpsy.', 'Rishi Sunak born: May 12, 1980 (age 43 years), Southampton General Hospital, Southampton, United Kingdom.', 'Rishi Sunak marriage_location: Bengaluru, India.', 'Rishi Sunak books: A Portrait of Modern Britain, A New Era for Retail Bonds.', 'Rishi Sunak previous_campaign: United Kingdom House of Commons election, 2019.', 'Rishi Sunak office: Prime Minister of the United Kingdom since 2022.', 'Rishi Sunak party: Conservative Party.', 'Rishi Sunak previous_offices: Chancellor of the Exchequer (2020–2022).', 'The current prime minister is Rishi Sunak of the Conservative Party, who assumed the office on 25 October 2022. Prime Minister of the United Kingdom of ...', 'Rishi Sunak became Prime Minister on 25 October 2022. He was previously appointed Chancellor of the Exchequer from 13 February 2020 to 5 July 2022. He was Chief ...', 'Rishi Sunak is a British politician who has served as Prime Minister of the United Kingdom and Leader of the Conservative Party since 2022.', "British Prime Ministers ; Liz Truss (1975- ), Merton, Sep 2022-Oct 2022 ; Boris Johnson (1964- ), Balliol, Jul 2019-Sept 2022 ; Theresa May (1956- ), St Hugh's ...", 'Former U.K Prime Minister Boris Johnson, Queen ...', 'LONDON — Rishi Sunak becomes Britain\'s third prime in under two months at a time when the U.K. faces what he has termed a "profound economic ...', "Rishi Sunak will be Britain's next prime minister after dark-horse challenger Penny Mordaunt withdrew from the Conservative Party's ...", "Rishi Sunak will become the United Kingdom's new prime minister after winning the ruling Conservative Party's leadership contest, ...", 'Rishi Sunak, who on Tuesday became prime minister, broke ranks with then-Prime Minister David Cameron, hailing Brexit as a “once-in-a-generation ...', 'Meet the Prime Minister. Rishi Sunak became Prime Minister in October 2022. · History. 10 Downing Street, the locale of British prime ministers since 1735, vies ...']
Thought:It seems the current Prime Minister of the UK is Rishi Sunak. Would you like to know more about him or is there anything else you need assistance with?

> Finished chain.


> Entering new AgentExecutor chain...
Thought: I can use a search tool to find the current age of the Prime Minister of the UK, Rishi Sunak.

Action:
```
{
"action": "Search",
"action_input": "Rishi Sunak current age"
}
```
Observation: 43 years
Thought:I have found that the current age of the Prime Minister of the UK, Rishi Sunak, is 43 years old.
Action:
```
{
"action": "Final Answer",
"action_input": "The current age of the Prime Minister of the UK, Rishi Sunak, is 43 years old."
}
```

> Finished chain.


> Entering new AgentExecutor chain...
Thought: I can use the Calculator tool to calculate the prime minister's current age raised to the power of 0.43. This will involve raising 43 to the power of 0.43.

Action:
```
{
"action": "Calculator",
"action_input": "43^0.43"
}
```

> Entering new LLMMathChain chain...
43^0.43```text
43**0.43
```
...numexpr.evaluate("43**0.43")...

Answer: 5.0395462574574275
> Finished chain.

Observation: Answer: 5.0395462574574275
Thought:I have calculated the prime minister's current age raised to the power of 0.43, and the result is approximately 5.0395.
Action:
```
{
"action": "Final Answer",
"action_input": "The prime minister's current age raised to the power of 0.43 is approximately 5.0395."
}
```

> Finished chain.


> Entering new AgentExecutor chain...
Thought: The calculated value of the prime minister's current age raised to the power of 0.43 is approximately 5.0395.

Action:
```
{
"action": "Final Answer",
"action_input": "The prime minister's current age raised to the power of 0.43 is approximately 5.0395."
}
```

> Finished chain.


> Entering new AgentExecutor chain...
Thought: The original question was to find the current age of the Prime Minister of the UK. The age was calculated and provided as approximately 5.0395 when raised to the power of 0.43.

Action:
```
{
"action": "Final Answer",
"action_input": "The Prime Minister of the UK, Rishi Sunak, is approximately 5.0395 years old when raised to the power of 0.43."
}
```



> Finished chain.
'The Prime Minister of the UK, Rishi Sunak, is approximately 5.0395 years old when raised to the power of 0.43.'

Plan and Execute LangSmith流程展现:

1.5 OpenAI Tools Angent

OpenAI 模型(如 gpt-3.5-turbo-0613)已经过微调,可以检测何时应调用函数并响应应传递给函数的输入

  • OpenAI Functions 的目标是比通用文本完成或聊天 API 更可靠地返回有效且有用的函数调用
  • 在 API 调用中,您可以描述函数并让模型智能地选择输出包含调用这些函数的参数的 JSON 对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from langchain import hub
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_community.tools.google_serper import GoogleSerperResults
from langchain_openai import ChatOpenAI
import langchain
langchain.debug=False
tools = [GoogleSerperResults(max_results=1)]

prompt = hub.pull("hwchase17/openai-tools-agent")

prompt.pretty_print()

# Only certain models support this
llm = ChatOpenAI(model="gpt-3.5-turbo-1106", temperature=0)

# Construct the OpenAI Tools agent
agent = create_openai_tools_agent(llm, tools, prompt)

agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

agent_executor.invoke({"input": "what is LangChain?"})
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
================================ System Message ================================

You are a helpful assistant

============================= Messages Placeholder =============================

{chat_history}

================================ Human Message =================================

{input}

============================= Messages Placeholder =============================

{agent_scratchpad}


> Entering new AgentExecutor chain...

Invoking: `google_serper_results_json` with `LangChain`


{'searchParameters': {'q': 'LangChain', 'gl': 'us', 'hl': 'en', 'type': 'search', 'num': 1, 'engine': 'google'}, 'knowledgeGraph': {'title': 'LangChain', 'description': "LangChain is a framework designed to simplify the creation of applications using large language models. As a language model integration framework, LangChain's use-cases largely overlap with those of language models in general, including document...", 'descriptionSource': 'Wikipedia', 'descriptionLink': 'https://en.wikipedia.org/wiki/LangChain', 'attributes': {'Initial release date': 'October 2022', 'Developer(s)': 'Harrison Chase', 'License': 'MIT License', 'Repository': 'github.com/langchain-ai/langchain', 'Stable release': '0.1.16 / 11 April 2024; 14 days ago', 'Written in': 'Python and JavaScript'}}, 'organic': [{'title': 'LangChain', 'link': 'https://www.langchain.com/', 'snippet': "Build your app with LangChain. Build context-aware, reasoning applications with LangChain's flexible framework that leverages your company's data and APIs.", 'position': 1}], 'images': [{'title': 'miro.medium.com/v2/resize:fit:1400/1*7Lep2Jkqgt9Bt...', 'imageUrl': 'https://miro.medium.com/v2/resize:fit:1400/1*7Lep2Jkqgt9BtiMt8icbSA.png', 'link': 'https://medium.com/@Algi.T/langchain-building-powerful-language-model-applications-with-python-c2b77a107709'}, {'title': 'What Is LangChain and How to Use It: A Guide', 'imageUrl': 'https://cdn.ttgtmedia.com/rms/onlineimages/a_langchain_app_in_its_most_basic_form-f_mobile.png', 'link': 'https://www.techtarget.com/searchenterpriseai/definition/LangChain'}, {'title': 'Introduction | 🦜️🔗 LangChain', 'imageUrl': 'https://python.langchain.com/svg/langchain_stack.svg', 'link': 'https://python.langchain.com/'}, {'title': 'Introduction | 🦜️🔗 LangChain', 'imageUrl': 'https://python.langchain.com/img/brand/wordmark.png', 'link': 'https://python.langchain.com/'}], 'relatedSearches': [{'query': 'LangChain Python'}, {'query': 'Langchain github'}, {'query': 'Langchain JS'}, {'query': 'Langchain ai'}, {'query': 'LangChain pip'}, {'query': 'Is LangChain free'}, {'query': 'LangChain examples'}, {'query': 'LangChain documentation'}]}LangChain is a framework designed to simplify the creation of applications using large language models. It is a language model integration framework with use-cases that largely overlap with those of language models in general, including document processing, chatbots, and more. LangChain was developed by Harrison Chase and is written in Python and JavaScript. It is available under the MIT License and has a stable release version 0.1.16 as of April 11, 2024. You can find more information about LangChain on their official website: [LangChain](https://www.langchain.com/).

For further details, you can also refer to the Wikipedia page on LangChain: [Wikipedia - LangChain](https://en.wikipedia.org/wiki/LangChain)

> Finished chain.
{'input': 'what is LangChain?',
'output': 'LangChain is a framework designed to simplify the creation of applications using large language models. It is a language model integration framework with use-cases that largely overlap with those of language models in general, including document processing, chatbots, and more. LangChain was developed by Harrison Chase and is written in Python and JavaScript. It is available under the MIT License and has a stable release version 0.1.16 as of April 11, 2024. You can find more information about LangChain on their official website: [LangChain](https://www.langchain.com/).\n\nFor further details, you can also refer to the Wikipedia page on LangChain: [Wikipedia - LangChain](https://en.wikipedia.org/wiki/LangChain)'}

OpenAI Tools Angent LangSmith流程展现:

更多Agent Type:https://python.langchain.com/docs/modules/agents/agent_types/

二、Agent 工具箱

工具是Agent,chain以及LLM可以用来与世界交互的功能。工具由以下组成:

  • 工具名
  • 工具的说明
  • 工具输入的JSON Schema
  • 工具函数
  • 工具返回的结果是否应该直接返回给用户

名称、说明和 JSON schema 可用于 LLM Prompt,用于向模型传达该工具的用途以及何时使用它。

2.1 内置工具

2.1.1 内置工具的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from langchain_community.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper

api_wrapper = WikipediaAPIWrapper(top_k_results=1, doc_content_chars_max=100)
tool = WikipediaQueryRun(api_wrapper=api_wrapper)

print("====工具名====")
print(tool.name)

print("====工具说明====")
print(tool.description)

print("====工具输入的JSON Schema====")
print(tool.args)

print("====是否直接返回给用户====")
print(tool.return_direct)

#用字典输入调用
print(tool.run({"query": "langchain"}))

#也可以用单字符串输入调用,但只限于只有单一输入的工具
print(tool.run("langchain"))

输出

1
2
3
4
5
6
7
8
9
10
11
12
====工具名====
wikipedia
====工具说明====
A wrapper around Wikipedia. Useful for when you need to answer general questions about people, places, companies, facts, historical events, or other subjects. Input should be a search query.
====工具输入的JSON Schema====
{'query': {'title': 'Query', 'type': 'string'}}
====是否直接返回给用户====
False
Page: LangChain
Summary: LangChain is a framework designed to simplify the creation of applications
Page: LangChain
Summary: LangChain is a framework designed to simplify the creation of applications

2.1.2 定制化内置工具

我们可以修改工具的名字, 说明以及JSON Schema,在定义JSON Schema参数时,输入必须保证与函数相同,因此无法进行修改,但是可以修改每个参数的说明。

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
from langchain_core.pydantic_v1 import BaseModel, Field


class WikiInputs(BaseModel):
"""Inputs to the wikipedia tool."""

query: str = Field(
description="query to look up in Wikipedia, should be 3 or less words" #自定义参数说明
)


tool = WikipediaQueryRun(
name="wiki-tool", #自定义工具名
description="look up things in wikipedia", #自定义工具说明
args_schema=WikiInputs,
api_wrapper=api_wrapper,
return_direct=True, #自定义
)


print("====工具名====")
print(tool.name)

print("====工具说明====")
print(tool.description)

print("====工具输入的JSON Schema====")
print(tool.args)

print("====是否直接返回给用户====")
print(tool.return_direct)

print(tool.run("langchain"))

输出

1
2
3
4
5
6
7
8
9
10
====工具名====
wiki-tool
====工具说明====
look up things in wikipedia
====工具输入的JSON Schema====
{'query': {'title': 'Query', 'description': 'query to look up in Wikipedia, should be 3 or less words', 'type': 'string'}}
====是否直接返回给用户====
True
Page: LangChain
Summary: LangChain is a framework designed to simplify the creation of applications

更多内置工具请参考:https://python.langchain.com/docs/integrations/tools/

2.2 自定义工具

自定义工具除了实际功能之外,工具还有其他几个组件:

  • name(str),是必需的,并且在一组工具中必须是唯一的提供给Agent
  • description(str),是可选的,但建议使用,Agent会用它来决定工具的使用
  • args_schema(Pydantic BaseModel),是可选的,但推荐使用,可以用于提供更多信息(例如,few-shot)或验证参数

2.2.1 @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
29
30
31
32
33
34
from langchain.pydantic_v1 import BaseModel, Field
from langchain.tools import BaseTool, StructuredTool, tool

@tool
def search(query: str) -> str:
"""Look up things online."""
return "LangChain"
print("====单一参数====")
print(search.name)
print(search.description)
print(search.args)

@tool
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
print("====多参数====")
print(multiply.name)
print(multiply.description)
print(multiply.args)

class SearchInput(BaseModel):
query: str = Field(description="should be a search query")


@tool("search-tool", args_schema=SearchInput, return_direct=True)
def search(query: str) -> str:
"""Look up things online."""
return "LangChain"
print("====将工具名称和 JSON Schema传递 工具装饰器====")
print(search.name)
print(search.description)
print(search.args)
print(search.return_direct)

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
====单一参数====
search
search(query: str) -> str - Look up things online.
{'query': {'title': 'Query', 'type': 'string'}}
====多参数====
multiply
multiply(a: int, b: int) -> int - Multiply two numbers.
{'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}
====将工具名称和 JSON Schema传递 工具装饰器====
search-tool
search-tool(query: str) -> str - Look up things online.
{'query': {'title': 'Query', 'description': 'should be a search query', 'type': 'string'}}
True

2.2.2 StructuredTool 数据类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class CalculatorInput(BaseModel): #可以不要,用来定义参数说明
a: int = Field(description="first number")
b: int = Field(description="second number")


def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b


calculator = StructuredTool.from_function(
func=multiply,
name="Calculator",
description="multiply numbers",
args_schema=CalculatorInput,
return_direct=True,
# coroutine= ... <- you can specify an async method if desired as well
)

print(calculator.name)
print(calculator.description)
print(calculator.args)

输出

1
2
3
Calculator
Calculator(a: int, b: int) -> int - multiply numbers
{'a': {'title': 'A', 'description': 'first number', 'type': 'integer'}, 'b': {'title': 'B', 'description': 'second number', 'type': 'integer'}}

其他更多说明请参考: https://python.langchain.com/docs/modules/tools/custom_tools/

2.3 Agent 工具箱中的工具集

工具集(Toolkit)是旨在一起用于特定任务并具有方便的加载方法的工具的集合

全部工具集:https://python.langchain.com/docs/integrations/toolkits/

2.3.1 使用PythonREPLTool工具集

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
from langchain import hub
from langchain.agents import AgentExecutor
from langchain_experimental.tools import PythonREPLTool
from langchain.agents import create_react_agent
from langchain_openai import ChatOpenAI

tools = [PythonREPLTool()] #加载工具集

llm = ChatOpenAI(model_name='gpt-4-turbo',temperature=0)

instructions = """You are an agent designed to write and execute python code to answer questions.
You have access to a python REPL, which you can use to execute python code.
If you get an error, debug your code and try again.
Only use the output of your code to answer the question.
You might know the answer without running any code, but you should still run the code to get the answer.
If it does not seem like you can write code to answer the question, just return "I don't know" as the answer.
"""
base_prompt = hub.pull("langchain-ai/react-agent-template")
prompt = base_prompt.partial(instructions=instructions)

agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

#训练神经网络
agent_executor.invoke(
{
"input": """Understand, write a single neuron neural network in PyTorch.
Take synthetic data for y=2x. Train for 1000 epochs and print every 100 epochs.
Return prediction for x = 5"""
}
)
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
> Entering new AgentExecutor chain...
Thought: Do I need to use a tool? Yes
Action: Python_REPL
Action Input:
import torch
import torch.nn as nn

# Define the model
class SingleNeuron(nn.Module):
def __init__(self):
super(SingleNeuron, self).__init__()
self.linear = nn.Linear(1, 1)

def forward(self, x):
return self.linear(x)

# Generate synthetic data
x_train = torch.arange(0, 10, 0.1).view(-1, 1)
y_train = 2 * x_train

# Initialize the model
model = SingleNeuron()

# Loss and optimizer
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

# Training loop
for epoch in range(1000):
model.train()
optimizer.zero_grad()
outputs = model(x_train)
loss = criterion(outputs, y_train)
loss.backward()
optimizer.step()

if epoch % 100 == 0:
print(f'Epoch {epoch+1}, Loss: {loss.item()}')

# Test the model
model.eval()
x_test = torch.tensor([[5.0]])
prediction = model(x_test)
print(f'Prediction for x = 5: {prediction.item()}')
Epoch 1, Loss: 144.06373596191406
Epoch 101, Loss: 0.0336177758872509
Epoch 201, Loss: 0.012431501410901546
Epoch 301, Loss: 0.004597042221575975
Epoch 401, Loss: 0.0016999474028125405
Epoch 501, Loss: 0.00062862056074664
Epoch 601, Loss: 0.00023245699412655085
Epoch 701, Loss: 8.595705003244802e-05
Epoch 801, Loss: 3.178801489411853e-05
Epoch 901, Loss: 1.1754618753911927e-05
Prediction for x = 5: 10.000994682312012
Do I need to use a tool? No
Final Answer: After training the single neuron neural network for 1000 epochs on the synthetic data where y=2x, the prediction for x=5 is approximately 10.000994682312012.

> Finished chain.
{'input': 'Understand, write a single neuron neural network in PyTorch.\nTake synthetic data for y=2x. Train for 1000 epochs and print every 100 epochs.\nReturn prediction for x = 5',
'output': 'After training the single neuron neural network for 1000 epochs on the synthetic data where y=2x, the prediction for x=5 is approximately 10.000994682312012.'}

LangSmith流程展现:

参考


LangChain(六)——Agents
https://mztchaoqun.com.cn/posts/D30_LangChain_Agents/
作者
mztchaoqun
发布于
2024年7月29日
许可协议