LangChain 19 Agents Reason+Action自定义agent处理OpenAI的计算缺陷
LangChain系列文章
- LangChain 实现给动物取名字,
- LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字
- LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄
- LangChain 4用向量数据库Faiss存储,读取YouTube的视频文本搜索Indexes for information retrieve
- LangChain 5易速鲜花内部问答系统
- LangChain 6根据图片生成推广文案HuggingFace中的image-caption模型
- LangChain 7 文本模型TextLangChain和聊天模型ChatLangChain
- LangChain 8 模型Model I/O:输入提示、调用模型、解析输出
- LangChain 9 模型Model I/O 聊天提示词ChatPromptTemplate, 少量样本提示词FewShotPrompt
- LangChain 10思维链Chain of Thought一步一步的思考 think step by step
- LangChain 11实现思维树Implementing the Tree of Thoughts in LangChain’s Chain
- LangChain 12调用模型HuggingFace中的Llama2和Google Flan t5
- LangChain 13输出解析Output Parsers 自动修复解析器
- LangChain 14 SequencialChain链接不同的组件
- LangChain 15根据问题自动路由Router Chain确定用户的意图
- LangChain 16 通过Memory记住历史对话的内容
- LangChain 17 LangSmith调试、测试、评估和监视基于任何LLM框架构建的链和智能代理
- LangChain 18 LangSmith监控评估Agent并创建对应的数据库
1. Agents 代理
Agents的核心理念是利用语言模型选择一系列要采取的行动。在Chains中,一系列行动是硬编码的(在代码中)。在Agents中,语言模型被用作推理引擎,以确定要采取哪些行动以及顺序。
概念 这里有几个关键组成部分:
1.1 Agent
这是负责决定下一步该采取什么步骤的链条。这由语言模型和提示驱动。这个链条的输入包括:
- 工具:可用工具的描述
- 用户输入:高层次目标
- 中间步骤:为了实现用户输入而先前执行的任何(动作,工具输出)对
输出是下一步要采取的行动或发送给用户的最终响应(代理动作或代理完成)。动作指定一个工具和该工具的输入。
不同的代理有不同的推理提示风格,不同的编码输入方式和不同的解析输出方式。有关内置代理的完整列表,请参见代理类型。您还可以轻松构建自定义代理,我们将在下面的入门部分中展示如何操作。
1.2 工具
工具是代理可以调用的函数。围绕工具有两个重要的设计考虑:
- 为代理提供访问正确工具的权限
- 以对代理最有帮助的方式描述工具
如果没有同时考虑这两个方面,你将无法构建一个可工作的代理。如果你不给代理访问正确的工具集,它将永远无法完成你给它的目标。如果你没有很好地描述工具,代理将不知道如何正确使用它们。
LangChain 提供了广泛的内置工具集,但也使定义自己的工具(包括自定义描述)变得容易。有关内置工具的完整列表,请参见工具集成部分。
1.3 工具包
对于许多常见任务,代理将需要一组相关工具。为此,LangChain提供了工具包的概念 - 大约3-5个工具组成,用于实现特定目标。例如,GitHub工具包中有一个用于搜索GitHub问题的工具,一个用于读取文件的工具,一个用于评论的工具等等。
LangChain提供了广泛的工具包供您使用。有关内置工具包的完整列表,请参阅工具包集成部分。
1.4 AgentExecutor
代理执行器是代理的运行时。这实际上是调用代理,执行它选择的动作,将动作输出传递回代理,并重复。在伪代码中,大致如下:
next_action = agent.get_action(...)
while next_action != AgentFinish:observation = run(next_action)next_action = agent.get_action(..., next_action, observation)
return next_action
虽然这可能看起来很简单,但这个运行时为您处理了几个复杂情况,包括:
- 处理代理选择不存在的工具的情况
- 处理工具出错的情况
- 处理代理产生的无法解析为工具调用的输出的情况
- 在所有级别(代理决策,工具调用)记录和观察到标准输出和/或LangSmith。
1.5 其他类型的代理运行时
AgentExecutor类是LangChain支持的主要代理运行时。但是,我们还支持其他更实验性的运行时。这些包括:
- 计划并执行代理
- Baby AGI
- Auto GPT
您也可以始终创建自己的自定义执行逻辑,我们将在下面展示如何做到这一点。
2. 开始代码实现
为了更好地理解代理框架,让我们使用LangChain表达语言(LCEL)从头开始构建一个代理。我们需要构建代理本身,定义自定义工具,并在自定义循环中运行代理和工具。最后,我们将展示如何使用标准的LangChain
AgentExecutor
来使执行更容易。
一些重要的术语(和模式)需要知道:
- AgentAction:这是一个表示代理应该采取的行动的数据类。它有一个工具属性(这是应调用的工具的名称)和一个tool_input属性(该工具的输入)
- AgentFinish:这是一个表示代理已经完成并应该返回给用户的数据类。它有一个return_values参数,是一个要返回的字典。它通常只有一个键 - 输出 - 是一个字符串,因此通常只返回这个键。
- intermediate_steps:这些代表传递的先前代理操作和相应的输出。这些对于将来的迭代非常重要,这样代理就知道它已经做了什么工作。这被定义为List[Tuple[AgentAction, Any]]。请注意,observation目前被保留为Any类型,以便最大程度地灵活。实际上,这通常是一个字符串。
2.1 设置:LangSmith
根据定义,代理在返回用户可见的输出之前会采取一系列自主确定的、依赖输入的步骤。这使得调试这些系统特别棘手,观察特别重要。LangSmith在这种情况下特别有用。
在使用LangChain构建时,任何使用LCEL构建的内置代理或自定义代理都将自动在LangSmith中被追踪。如果我们使用AgentExecutor,不仅会得到代理规划步骤的完整追踪,还会得到工具的输入和输出的追踪。
要设置LangSmith,我们只需要设置以下环境变量:
export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="<your-api-key>"
2.2 定义代理
我们首先需要创建我们的代理。这是负责决定下一步采取什么行动的链条。
在这个例子中,我们将使用OpenAI函数调用来创建这个代理。这通常是创建代理的最可靠方式。
在本指南中,我们将构建一个具有自定义工具访问权限的自定义代理。我们选择这个例子是因为在大多数实际用例中,您将需要自定义代理或工具。我们将创建一个简单的工具,用于计算单词的长度。这很有用,因为由于标记化,LLMs实际上可能会搞砸这个。我们将首先创建它而不带有记忆,但然后我们将展示如何添加记忆。记忆是为了启用对话而必需的。
首先,让我们加载我们将用来控制代理的语言模型。
from langchain.chat_models import ChatOpenAIllm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
我们可以看到它在尝试计算字符串"educa"中的字母时遇到了困难。
llm.invoke("how many letters in the word educa?")
AIMessage(content='There are 6 letters in the word "educa".')
接下来,让我们定义一些要使用的工具。让我们编写一个非常简单的Python函数来计算传入的单词的长度。
from langchain.agents import tool@tool
def get_word_length(word: str) -> int:"""Returns the length of a word."""return len(word)tools = [get_word_length]
现在让我们创建提示。因为OpenAI函数调用是为工具使用而优化的,我们几乎不需要任何关于如何推理或如何输出格式的指令。我们只需要两个输入变量:输入和agent_scratchpad
。输入应该是包含用户目标的字符串。agent_scratchpad
应该是包含先前代理工具调用和相应工具输出的消息序列。
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholderprompt = ChatPromptTemplate.from_messages([("system","You are very powerful assistant, but bad at calculating lengths of words.",),("user", "{input}"),MessagesPlaceholder(variable_name="agent_scratchpad"),]
)
代理如何知道它可以使用哪些工具?在这种情况下,我们依赖于OpenAI调用LLMs的功能,它们将函数作为单独的参数,并经过专门训练,知道何时调用这些函数。
要将我们的工具传递给代理,我们只需要将它们格式化为OpenAI函数格式,并将它们传递给我们的模型。(通过绑定函数,我们确保它们在每次调用模型时被传递。)
from langchain.tools.render import format_tool_to_openai_functionllm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])
将这些部分组合在一起,我们现在可以创建代理。我们将导入最后两个实用程序函数:一个用于格式化中间步骤(代理动作、工具输出对)以将其转换为可以发送到模型的输入消息的组件,以及一个用于将输出消息转换为代理动作/代理完成的组件。
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParseragent = ({"input": lambda x: x["input"],"agent_scratchpad": lambda x: format_to_openai_function_messages(x["intermediate_steps"]),}| prompt| llm_with_tools| OpenAIFunctionsAgentOutputParser()
)
现在我们有了我们的代理,让我们来玩一下吧!让我们传递一个简单的问题和空的中间步骤,看看它返回什么:
agent.invoke({"input": "how many letters in the word educa?", "intermediate_steps": []})
AgentActionMessageLog(tool='get_word_length', tool_input={'word': 'educa'}, log="\nInvoking: `get_word_length` with `{'word': 'educa'}`\n\n\n", message_log=[AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\n "word": "educa"\n}', 'name': 'get_word_length'}})])
我们可以看到它响应一个AgentAction以采取行动(实际上是AgentActionMessageLog - AgentAction的子类,还跟踪完整的消息日志)。
如果我们设置了LangSmith,我们将看到一个跟踪,让我们检查每个步骤中的输入和输出的序列。https://smith.langchain.com/public/04110122-01a8-413c-8cd0-b4df6eefa4b7/r
2.3 定义运行时
所以这只是第一步 - 现在我们需要为此编写一个运行时。最简单的方法就是不断循环调用代理,然后执行动作,直到返回AgentFinish为止。让我们在下面编写代码:
from langchain.schema.agent import AgentFinishuser_input = "how many letters in the word educa?"
intermediate_steps = []
while True:output = agent.invoke({"input": user_input,"intermediate_steps": intermediate_steps,})if isinstance(output, AgentFinish):final_result = output.return_values["output"]breakelse:print(f"TOOL NAME: {output.tool}")print(f"TOOL INPUT: {output.tool_input}")tool = {"get_word_length": get_word_length}[output.tool]observation = tool.run(output.tool_input)intermediate_steps.append((output, observation))
print(final_result)
TOOL NAME: get_word_lengthTOOL INPUT: {'word': 'educa'}There are 5 letters in the word "educa".
Woo! It’s working.
整合代码实现
# 导入与 OpenAI 语言模型交互的模块。
from langchain.llms import OpenAI # 导入用于创建和管理提示模板的模块。
from langchain.prompts import PromptTemplate # 导入用于构建基于大型语言模型的处理链的模块。
from langchain.chains import LLMChain # 导入从 .env 文件加载环境变量的库。
from dotenv import load_dotenv # 导入创建和管理 OpenAI 聊天模型实例的类。
from langchain.chat_models import ChatOpenAI# 加载 .env 文件中的环境变量。
load_dotenv() # 设置环境变量,包括项目 ID 和 Langchain API 的相关设置。
import os
from uuid import uuid4
unique_id = uuid4().hex[0:8]
os.environ["LANGCHAIN_PROJECT"] = f"Tracing word length - {unique_id}"# 初始化 LangSmith 客户端。
from langsmith import Client
client = Client()# 创建 ChatOpenAI 实例。
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0, verbose=True)# 定义一个自定义工具,用于获取单词的长度。
from langchain.agents import tool@tool
def get_word_length(word: str) -> int:"""Returns the length of a word."""return len(word)tools = [get_word_length]# 创建聊天提示模板。
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholderprompt = ChatPromptTemplate.from_messages([("system", "You are very powerful assistant, but bad at calculating lengths of words."),("user", "{input}"),MessagesPlaceholder(variable_name="agent_scratchpad"),]
)# 将 ChatOpenAI 实例与工具绑定。
from langchain.tools.render import format_tool_to_openai_functionllm_with_tools = llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])# 定义代理。
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParseragent = ({"input": lambda x: x["input"],"agent_scratchpad": lambda x: format_to_openai_function_messages(x["intermediate_steps"]),}| prompt| llm_with_tools| OpenAIFunctionsAgentOutputParser()
)# 处理用户输入,使用代理执行循环,直到获取最终结果。
from langchain.schema.agent import AgentFinishuser_input = "how many letters in the word educa?"
intermediate_steps = []
while True:output = agent.invoke({"input": user_input,"intermediate_steps": intermediate_steps,})if isinstance(output, AgentFinish):final_result = output.return_values["output"]breakelse:print(f"TOOL NAME: {output.tool}")print(f"TOOL INPUT: {output.tool_input}")tool = {"get_word_length": get_word_length}[output.tool]observation = tool.run(output.tool_input)intermediate_steps.append((output, observation))
print(final_result)
输出结果
(develop)⚡ % python Agents/chat_agents_word_length.py ~/Workspace/LLM/langchain-llm-app
TOOL NAME: get_word_length
TOOL INPUT: {'word': 'educa'}
There are 5 letters in the word "educa".
代码
https://github.com/zgpeace/pets-name-langchain/tree/develop
参考
https://python.langchain.com/docs/modules/agents/
相关文章:

LangChain 19 Agents Reason+Action自定义agent处理OpenAI的计算缺陷
LangChain系列文章 LangChain 实现给动物取名字,LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储,读取YouTube的视频文本搜索I…...
12.整数转罗马数字
C不能像Python那样使用c*num的形式,重复字符,老老实实减吧。 class Solution { public:string intToRoman(int num) {string ans "";int res num;while (res ! 0) {if (res > 1000) {ans M;res - 1000;} else if (res > 900) {ans …...

免费AI洗稿软件【2023最新】
很多时候我们需要通过文字来表达观点、推广产品或服务。然而,长时间的文稿创作不仅费时费力,还容易陷入表达瓶颈。许多写手和从业者纷纷寻找一款方便、高效的AI洗稿工具。 文心一言洗稿软件。这款软件以其独特的文风生成和洗稿功能而备受瞩目。用户只需…...
PTA:平方回文数
题干 在数学里面,有一种数字正着读和反着读结果都一样,我们把这种数称为回文数。如果一个回文数,它同时还是某一个数的平方,这样的数字叫做平方回数。 本题要求输出小于正整数N的所有平方回数。 (注:个位数…...

从“AI证件照”到“AI译制片”,爆款AIGC应用的商业化迷思
让郭德纲飙英文、让霉霉说中文的翻译视频生成工具HeyGen和掀起AI证件照热潮的“妙鸭相机”一样,在一阵疯狂刷屏之后,又迅速在各大群里销声匿迹了。 十月份,由HeyGen制作的各种明星跨语言翻译视频,在全网疯传,大家震撼于…...

JAVA代码优化:Easy Excel(操作Excel文件的开源工具)
Easy Excel官网: EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel (alibaba.com) https://easyexcel.opensource.alibaba.com/ Easy Excel的特点和优势: 简单易用:Easy Excel提供了简洁的API,使用起来非常方便。开发…...
Linux Python ping3库使用教程(ping3命令、ping命令)
文章目录 Linux Python ping3库使用教程1. 环境准备2. ping3库安装3. ping3基本使用4. ping3进阶使用5. 常见问题解答5.1 ping3库可以在Windows系统中使用吗?5.2 如何处理ping操作超时的情况?5.3 ping3库支持IPv6吗? Linux Python ping3库使用…...
分享一些基于php商城案例
案例1: http://www.9520.xin/ 案例2: http://ptll.hasbuy.com/ 案例3: http://likeshop.9520.xin/mobile 案例4: http://www.hasbuy.com/...

SpringSecurity 三更草堂 学习笔记
SpringSecurity从入门到精通 0. 简介 Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的…...
基于Java SSM仓库管理系统
企业仓库有多个库房,用来分别存放生产需要的各种零件,仓库管理系统对此进行科学的管理。仓库管理系统管理的对象及操作如下: 管理员信息:工号、姓名、性别、年龄、电话、工资等。 库房信息:编号、地址、面积等。 零件信…...

基于Spark对消费者行为数据进行数据分析开发案例
原创/朱季谦 本文适合入门Spark RDD的计算处理。 在日常工作当中,经常遇到基于Spark去读取存储在HDFS中的批量文件数据进行统计分析的案例,这些文件一般以csv或者txt文件格式存在。例如,存在这样一份消费者行为数据,字段包括消费…...

Docker镜像制作与推送
目录 Docker镜像制作 搭建私服 将本地镜像推送到私有库 Docker镜像制作 以创建一个新ubuntu镜像,并安装vim命令示例 运行一个ubuntu镜像,发现在镜像里面无法使用vim命令,因为该ubuntu镜像只包括了其最基本的内核命令 [rootlocalhost ~]…...

Pandas时序数据分析实践—基础(1)
目录 1. Pandas基本结构2. Pandas数据类型2.1. 类型概述2.1.1. 整数类型(int):2.1.2. 浮点数类型(float):2.1.3. 布尔类型(bool):2.1.4. 字符串类型(object&a…...

5.C转python
新始: 13.列表可被改变(数据),元组不可被改变(数据),二者皆与C中的数组的大致相同 14.创建列表方法: 1.一个[ ]就是一个空的列表 2.使用list函数来创建列表 如: 15.可以在[ ]内部指定列表的初始值,打印方法: 如: 16.在python中,在同一个列表中,可以放不同类型的变量(也可…...
输出SearchFacesResponse对象的JSON格式字符串回包乱码解决方案
输出SearchFacesResponse对象的JSON格式字符串设置响应内容类型为"application/json;charsetutf-8"获取响应的字符输出流将SearchFacesResponse对象转化为JSON字符串并输出。 代码片段 System.out.println(SearchFacesResponse.toJsonString(resp)); response.setC…...

P7 链表 链表头前方插入新节点
目录 前言 01 链表头插入数据 示例代码 02 指定节点前方插入新节点 测试代码 前言 🎬 个人主页:ChenPi 🐻推荐专栏1: 《C》✨✨✨ 🔥 推荐专栏2: 《 Linux C应用编程(概念类)_ChenPi的博客-CSDN博客》✨…...
SCAU:主对角线上的元素之和
主对角线上的元素之和 Time Limit:1000MS Memory Limit:65535K 题型: 编程题 语言: G;GCC 描述 输入一个3行4列的整数矩阵,计算并输出主对角线上的元素之和输入格式 3行4列整数矩阵输出格式 主对角线上的元素之和输入样例 1 2 3 4 5 6 7 8 9 10 11 12输出…...
c语言——简单客户端demo
以下是一个简单的C语言客户端示例,用于连接到服务器并发送和接收数据: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h…...
日志检索场景ES->Doris迁移最佳实践:函数篇
函数列表 函数:term函数功能说明:查询某个字段里含有某个关键词的文档参数说明:返回值说明:ES使用示例: {"query": {"term": {"title": "blog"}} }Doris使用示例…...

【高效开发工具系列】jackson入门使用
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...