小黑一层层削苹果皮式大模型应用探索:langchain中智能体思考和执行工具的demo
引言
小黑黑通过探索langchain源码,设计了一个关于agent使用工具
的一个简化版小demo(代码可以跑通),主要流程:
1.问题输入给大模型。
2.大模型进行思考,输出需要执行的action和相关思考信息。
3.通过代理
(demo中为perform_action函数)执行action进行工具调用,并返回工具调用结果(res)。
4.将action和res进行记录,继续喂给大模型进行思考,让大模型输出下一步action,以此类推…
demo准备工作
导包
from langchain_core.tools import BaseTool
from typing import Sequence, Optional, List
from langchain_core.prompts import BasePromptTemplate
import re
from langchain_core.tools import tool
from langchain_core.prompts.chat import (ChatPromptTemplate,HumanMessagePromptTemplate,SystemMessagePromptTemplate,
)
from langchain.agents import StructuredChatAgent
from langchain.chains.llm import LLMChain
from langchain_openai import ChatOpenAI
# 导入智能体
from langchain.agents.agent import Agent
from langchain.agents.structured_chat.output_parser import StructuredChatOutputParserWithRetries
from pydantic import Field
from langchain.agents.agent import Agent, AgentOutputParser
from typing import Any, List, Optional, Sequence, Tuple, Union
from langchain_core.agents import AgentAction
from langchain_core.language_models import BaseLanguageModel
from langchain_core.callbacks import BaseCallbackManager
from langchain_core.agents import AgentAction, AgentFinish, AgentStep
from langchain.agents.tools import InvalidTool
定义prompt模板(提示大模型思考和调用工具)
前缀部分(任务说明)
PREFIX = 'Respond to the human as helpfully and accurately as possible. You have access to the following tools:'
后缀部分(输出格式定义)
SUFFIX = 'Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation:.\nThought:'
输入提示
HUMAN_MESSAGE_TEMPLATE = '''{input}{agent_scratchpad}'''
引导部分
FORMAT_INSTRUCTIONS = '''Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).Valid "action" values: "Final Answer" or {tool_names}Provide only ONE action per $JSON_BLOB, as shown:
{{{{
“action”: $TOOL_NAME,
“action_input”: $INPUT
}}}}
Follow this format:Question: input question to answer
Thought: consider previous and subsequent steps
Action:
$JSON_BLOB
Observation: action result
... (repeat Thought/Action/Observation N times)
Thought: I know what to respond
Action:
{{{{
“action”: “Final Answer”,
“action_input”: “Final response to human”
}}}}
大模型定义(key脱敏处理,可以免费申请)
zhipu_key = '111111111111111111111111111111111111111111111'
llm = ChatOpenAI(temperature=0.01,model="glm-4-flash",openai_api_key=zhipu_key,openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
)
组合prompt
def create_prompt(tools: Sequence[BaseTool],prefix: str = PREFIX,suffix: str = SUFFIX,human_message_template: str = HUMAN_MESSAGE_TEMPLATE,format_instructions: str = FORMAT_INSTRUCTIONS,input_variables: Optional[List[str]] = None,memory_prompts: Optional[List[BasePromptTemplate]] = None,
) -> BasePromptTemplate:tool_strings = []for tool in tools:args_schema = re.sub("}", "}}", re.sub("{", "{{", str(tool.args)))tool_strings.append(f"{tool.name}: {tool.description}, args: {args_schema}")formatted_tools = "\n".join(tool_strings)tool_names = ", ".join([tool.name for tool in tools])format_instructions = format_instructions.format(tool_names=tool_names)template = "\n\n".join([prefix, formatted_tools, format_instructions, suffix])if input_variables is None:input_variables = ["input", "agent_scratchpad"]_memory_prompts = memory_prompts or []messages = [SystemMessagePromptTemplate.from_template(template),*_memory_prompts,HumanMessagePromptTemplate.from_template(human_message_template),]return ChatPromptTemplate(input_variables=input_variables, messages=messages) # type: ignore[arg-type]
工具函数定义
@tool
def multiply(first_int: int, second_int: int) -> int:"""将两个整数相乘。"""print('---------multiply-----------------')return first_int * second_int@tool
def add(first_int: int, second_int: int) -> int:"将两个整数相加。"print('---------add-----------------')return first_int + second_int@tool
def exponentiate(base: int, exponent: int) -> int:"指数运算"print('---------exponentiate-----------------')with open('小黑黑.txt', 'w', encoding='utf-8') as f:f.write('小黑黑')return base**exponenttools = [multiply, add, exponentiate]
prompt = create_prompt(tools=tools)
定义chain和智能体
# 定义chain
llm_chain = LLMChain(llm=llm,prompt=prompt,callback_manager=None,
)
# 定义智能体
structuredChatAgent = StructuredChatAgent(llm_chain=llm_chain,allowed_tools=[tool.name for tool in tools],output_parser=StructuredChatOutputParserWithRetries())
demo核心代码
代理函数
# 执行智能体
def perform_action(agent, name_to_tool_map, agent_action, run_manager=None):# 如果选择的工具在工具箱里if agent_action.tool in name_to_tool_map:# 获取所有工具tool = name_to_tool_map[agent_action.tool]# 判断是否直接返回工具return_direct = tool.return_direct# 获取智能体的输出前缀,例如思考内容用“Thought”,观察内容用“Observation:”,{'llm_prefix': 'Thought:', 'observation_prefix': 'Observation: '}tool_run_kwargs = agent.tool_run_logging_kwargs()# 执行工具observation = tool.run(agent_action.tool_input,verbose=None,color=None,callbacks=run_manager.get_child() if run_manager else None,**tool_run_kwargs,)# 选择的工具不在工具箱内,返回“无效工具相关信息给大模型”else:tool_run_kwargs = agent.tool_run_logging_kwargs()observation = InvalidTool().run({"requested_tool_name": agent_action.tool,"available_tool_names": list(name_to_tool_map.keys()),},verbose=self.verbose,color=None,callbacks=run_manager.get_child() if run_manager else None,**tool_run_kwargs,)# 以AgentStep的形式返回return AgentStep(action=agent_action, observation=observation)
大模型通过思考,一步步调用工具
# 历史动作和工具调用结果
intermediate_steps=[]
# 输入问题
question = '调用api计算3加5乘2等于多少?'
# 如果action为AgentFinish,则为最后一步,跳出循环
action = None
# 如果action为AgentFinish,则为最后一步,跳出循环
while True:# 大语言模型通过思考给出actionaction = structuredChatAgent.plan(intermediate_steps=intermediate_steps, input=question)print('[[[action]]]:', action)# 跳出循环if isinstance(action, AgentFinish):print('执行结束,得到答案')break# 通过 代理 执行actionagent_step = perform_action(structuredChatAgent, dict((tool.name,tool) for tool in tools), action)print('[[[agent_step]]]:', agent_step)# 将action和执行结果保存intermediate_steps.append((agent_step.action, agent_step.observation))print('*****************************************************************************************')
程序运行结果:
[[[action]]]: tool=‘multiply’ tool_input={‘first_int’: 5, ‘second_int’: 2} log=‘Thought: The user wants to calculate 3 + 5 * 2. According to the order of operations, multiplication should be performed before addition. So, I will first multiply 5 by 2 and then add 3 to the result.\nAction:\njson\n{\n "action": "multiply",\n "action_input": {\n "first_int": 5,\n "second_int": 2\n }\n}\n
’
---------multiply-----------------
[[[agent_step]]]: action=AgentAction(tool=‘multiply’, tool_input={‘first_int’: 5, ‘second_int’: 2}, log=‘Thought: The user wants to calculate 3 + 5 * 2. According to the order of operations, multiplication should be performed before addition. So, I will first multiply 5 by 2 and then add 3 to the result.\nAction:\njson\n{\n "action": "multiply",\n "action_input": {\n "first_int": 5,\n "second_int": 2\n }\n}\n
’) observation=10
[[[action]]]: tool=‘add’ tool_input={‘first_int’: 3, ‘second_int’: 10} log=‘Action:\njson\n{\n "action": "add",\n "action_input": {\n "first_int": 3,\n "second_int": 10\n }\n}\n
’
---------add-----------------
[[[agent_step]]]: action=AgentAction(tool=‘add’, tool_input={‘first_int’: 3, ‘second_int’: 10}, log=‘Action:\njson\n{\n "action": "add",\n "action_input": {\n "first_int": 3,\n "second_int": 10\n }\n}\n
’) observation=13
[[[action]]]: return_values={‘output’: ‘13’} log=‘Action:\njson\n{\n "action": "Final Answer",\n "action_input": "13"\n}\n
’
执行结束,得到答案
小黑黑下一步探索方向:
通过上述的action信息,自己手搓一个prompt,得以熟悉提示工程。
加油小黑黑,一步步手搓,享受其中!!与AI对话
相关文章:

小黑一层层削苹果皮式大模型应用探索:langchain中智能体思考和执行工具的demo
引言 小黑黑通过探索langchain源码,设计了一个关于agent使用工具的一个简化版小demo(代码可以跑通),主要流程: 1.问题输入给大模型。 2.大模型进行思考,输出需要执行的action和相关思考信息。 3.通过代理&…...
CppCon 2015 学习:Intro to the C++ Object Model
这段代码展示了使用 make 工具来编译 C 程序的简单过程。 代码和步骤解析: C 代码(intro.cpp):#include <iostream> int main() { std::cout<<"hello world\n"; } 这是一个简单的 C 程序,它包…...
Go 语言中的 make 函数详解
Go 语言中的 make 函数详解 make 是 Go 语言中的一个内置函数,用于初始化切片(slice)、映射(map)和通道(channel)这些引用类型。这些类型必须在使用前通过 make 初始化&#x…...

阿里云ACP云计算备考笔记 (4)——企业应用服务
目录 第一章 企业应用概览 第二章 云解析 1、云解析基本概念 2、域名管理流程 3、云解析记录类型 4、域名管理 ① 开启注册局安全锁 ② 域名赎回 第二章 内容分发网络CDN 1、CDN概念 2、使用CDN前后对比 3、使用CDN的优势 4、阿里云CDN的优势 5、配置网页性能优化…...
用 NGINX 构建高效 SMTP 代理`ngx_mail_smtp_module`
一、模块定位与作用 协议代理 NGINX 监听指定端口(如 25、587、465 等),接收客户端的 SMTP 会话请求。代理层在会话中透明转发客户端的 EHLO、MAIL FROM、RCPT TO、DATA 等命令到后端 MTA。 认证控制 通过 smtp_auth 指令指定允许的 SASL 认…...
【前端】常用组件的CSS
1. button的样式修改 每个环节有五个不同的状态:link,hover,active,focus和visited. Link是正常的外观,hover当你鼠标悬停时,active是单击它时的状态,focus跟随活动状态,visited是你在最近点击的链接未聚焦时结束的状态。 纯CSS 以下为例子,按下后从浅紫到深紫。注…...
【华为云学习与认证】以华为云物联网为基座的全栈开发(从物联网iot平台模块到应用展示、数据分析、机器学习、嵌入式开发等)的系统性学习与认证路线
总目标 学习以华为云物联网为基座的全栈开发(从物联网iot平台模块到应用展示、数据分析、机器学习、嵌入式开发等)的系统性学习与认证路线。计划包含阶段学习、技术文档、实操实际操作、开发路径与考证规划,提供职业生涯基础性规划。 注意&…...
OpenCV 键盘响应来切换图像
一、知识点 1、int waitKey(int delay 0); (1)、等待按键。 等待指定的毫秒数,返回按键的ASCII码。 (2)、返回值: int型,表示按键ASCII码。 若没有按键,指定时间过去,返回-1。 (3)、参数delay: 等待时间,单位毫…...

ARM SMMUv3简介(一)
1.概述 SMMU(System Memory Management Unit,系统内存管理单元)是ARM架构中用于管理设备访问系统内存的硬件模块。SMMU和MMU的功能类似,都是将虚拟地址转换成物理地址,不同的是MMU转换的虚拟地址来自CPU,S…...
C#提取CAN ASC文件时间戳:实现与性能优化
C#提取CAN ASC文件时间戳:实现与性能优化 在汽车电子和工业控制领域,CAN总线是最常用的通信协议之一。而ASC(ASCII)文件作为CAN总线数据的标准日志格式,广泛应用于数据记录和分析场景。本文将深入探讨如何高效地从CAN…...

hadoop集群datanode启动显示init failed,不能解析hostname
三个datanode集群,有一个总是起不起来。去查看log显示 Initialization failed for Block pool BP-1920852191-192.168.115.154-1749093939738 (Datanode Uuid 89d9df36-1c01-4f22-9905-517fee205a8e) service to node154/192.168.115.154:8020 Datanode denied com…...
Android 视图系统入门指南
1. View:界面的最小单位 本质:屏幕上的一个矩形区域,能显示内容或接收触摸。比喻:就像乐高积木,是组成界面的最小单位。常见子类: TextView(文字积木)、Button(按钮积木…...

浏览器工作原理05 [#] 渲染流程(上):HTML、CSS和JavaScript是如何变成页面的
引用 浏览器工作原理与实践 一、提出问题 在上一篇文章中我们介绍了导航相关的流程,那导航被提交后又会怎么样呢?就进入了渲染阶段。这个阶段很重要,了解其相关流程能让你“看透”页面是如何工作的,有了这些知识,你可…...
青少年编程与数学 01-011 系统软件简介 03 NetWare操作系统
青少年编程与数学 01-011 系统软件简介 03 NetWare操作系统 一、历史背景二、核心架构三、关键功能四、管理工具五、客户端支持六、版本演变七、衰落原因八、遗产与影响总结 摘要:NetWare 是早期网络操作系统的巅峰之作,其高性能文件服务、目录管理和容错…...
AI编程提示词
你是 IDE 的 AI 编程助手,遵循核心工作流(研究 -> 构思 -> 计划 -> 执行 -> 评审)用中文协助用户,面向专业程序员,交互应简洁专业,避免不必要解释。[沟通守则] 1. 响应以模式标签 [模式&#…...
Android学习总结-GetX库常见问题和解决方案
GetX库的常见问题 路由管理:Get.to() 后页面不跳转或卡顿? 问题: 明明调用了 Get.to(NextPage()),但页面没反应,或者感觉有延迟卡顿。这可能发生在较复杂的页面树或低端设备上。原因: …...

|从零开始的Pyside2界面编程| 用Pyside2打造一个AI助手界面
🐑 |从零开始的Pyside2界面编程| 用Pyside2打造一个AI助手界面 🐑 文章目录 🐑 |从零开始的Pyside2界面编程| 用Pyside2打造一个AI助手界面 🐑♈前言♈♈调取Deepseek大模型♈♒准备工作♒♒调用API♒ ♈将模型嵌入到ui界面中♈♈…...
React 中 HTML 插入的全场景实践与安全指南
在 React 开发过程中,我们常常会遇到需要插入 HTML 内容的场景。比如将服务端返回的富文本渲染到页面,还有处理复杂的 UI 结构,正确的 HTML 插入方式不仅影响页面展示效果,更关乎应用的安全性。 本文将详细探讨 React 中插入 HTM…...
一键更新依赖全指南:Flutter、Node.js、Kotlin、Java、Go、Python 等主流语言全覆盖
在现代软件开发中,依赖项扮演着至关重要的角色。保持依赖的最新状态不仅可以获得新特性和性能优化,还能修复已知安全漏洞。但在不同语言和框架中,依赖管理的方式差异很大。本篇文章将系统性讲解如何在各主流语言中实现“一键更新依赖”。 &am…...
Java异步编程难题拆解技术
异步编程基础与核心概念 异步编程模型与同步模型的对比 Java中异步编程的常见场景(IO密集型、高并发任务等) 关键术语:Future、CompletableFuture、回调、事件循环 Java异步编程的核心API与框架 Future接口的局限性及基本用法 Completable…...
NoSQL 之 Redis 配置与优化
目录 一、 前置知识点 1. 关系数据库与非关系型数据库 (1)关系型数据库 (2)非关系型数据库 (3)非关系型数据库产生背景 (4)两者对比 2. Redis 基础 (1࿰…...

pikachu靶场通关笔记20 SQL注入03-搜索型注入(GET)
目录 一、SQL注入 二、搜索型注入 三、源码分析 1、渗透思路1 2、渗透思路2 四、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入百分号单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取…...

产品笔试专业名词梳理
目录 产品常识 四种常见广告形式 贴片广告 中插广告 信息流广告 横幅广告 BAT和TMD BAT TMD 付费渗透率 蓝海市场、红海市场 蓝海市场 红海市场 竞品研究 SWOT分析 SWOT分析的核心目的: SWOT分析的优点: SWOT分析的局限与注意事项&…...

【前端】es6相关,柯里化
0. 严格模式 严格模式的概念从ES6引进。通过严格模式,可以在函数内部选择进行较为严格的全局或局部的错误条件检测。 MDN中严格模式的描述 严格模式通过抛出错误来消除了一些原有静默错误严格模式修复了一些导致 JavaScript引擎难以执行优化的缺陷:有时…...

51单片机基础部分——矩阵按键检测
前言 上一节,我们说到了独立按键的检测以及使用,但是独立按键每一个按键都要对应一个IO口进行检测,在一些需要多按键的情况下,使用过多的独立按键会过多的占用单片机的IO资源,为了解决这个问题的出现,我们…...
onSaveInstanceState() 和 ViewModel 在数据保存能力差异
一、设计目标差异 维度onSaveInstanceState()ViewModel核心目的保存 瞬态 UI 状态(如用户输入、滚动位置),应对进程意外终止或配置变更。管理 业务逻辑相关数据,在配置变更时保留数据࿰…...

SpringBoot2.3.1集成Knife4j接口文档
首先要查看项目中pom文件里面有没有swagger和knife4j的依赖,如果有的话删除,加入以下依赖 <!-- swagger --><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter</…...
Java Fork/Join框架:三大核心组件深度解析
ForkJoinTask、ForkJoinWorkerThread 和 ForkJoinPool 构成了 Java 中 Fork/Join 框架的三个核心组件,它们之间形成了紧密的协作关系,共同提供了高效的并行计算能力。 三者关系概述 ForkJoinPool:执行环境,管理工作线程和任务调…...
【envoy】-1.安装与下载源码
1.安装 建议使用ubuntu2004,对glibc有要求。上个ti子更快。 wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg $ echo "deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/envo…...
B站的视频怎么下载下来——Best Video下载器
B站(哔哩哔哩)作为国内最受欢迎的视频平台之一,聚集了无数优质内容:动漫番剧、游戏实况、学习课程、纪录片、Vlog、鬼畜剪辑……总有那么些视频让人想反复观看、离线观看,甚至剪辑创作。 但你是否遇到过这样的烦恼&am…...