news 2026/7/4 12:53:22

python-langchain框架(3-23-OpenAI Functions风格Tool Calling智能助手)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
python-langchain框架(3-23-OpenAI Functions风格Tool Calling智能助手)

一、先搞懂:OpenAI Functions 核心特点是什么?

很多同学会把Tool Calling和普通对话混淆,其实OpenAI Functions风格的工具调用,有三个不可替代的核心优势,也是我们本次实现的重点:

1. 需求识别自动化

模型能自动识别用户输入中需要调用工具的场景,无需人工指定“该用哪个工具”。比如用户问“现在几点”,模型会自动匹配“时间查询工具”;问“123乘以456是多少”,则自动触发“计算器工具”,完全无需额外的判断逻辑。

2. 工具调用标准化

遵循OpenAI Functions的规范,将自定义工具(如计算器、时间查询)封装成统一格式,模型能快速识别工具的功能、参数要求,避免因工具格式不统一导致的调用失败,降低开发成本。

3. 多轮交互连贯化

结合对话记忆功能,模型能记住上下文交互记录。比如用户先问“现在几点”,再问“30分钟后是几点”,模型会结合上一轮获取的当前时间,调用计算器完成计算,实现连贯的对话体验,而非孤立的单次工具调用。

二、核心实现思路:4步搭建,无复杂依赖

本次实现不依赖第三方API(除本地模型外),核心基于LangChain框架,将“模型初始化、工具定义、提示词构建、Agent封装”四大步骤串联,全程极简,重点突出OpenAI Functions的实现逻辑。

第一步:模型适配——对接兼容OpenAI规范的本地模型

OpenAI Functions的核心是“模型能识别工具描述、生成符合规范的调用指令”,因此我们无需直接使用OpenAI官方模型,只要本地部署的模型兼容OpenAI的工具调用格式(如通义千问、DeepSeek等),即可通过LangChain的ChatOpenAI封装类完成对接。

这一步的关键是配置模型的接口地址、密钥(部分本地模型无需真实密钥)、温度系数和最大生成token数,确保模型输出稳定、符合工具调用规范。

第二步:工具定义——按OpenAI Functions规范封装本地工具

按照OpenAI Functions的要求,我们将自定义工具(计算器、时间查询)封装成“名称+功能+参数描述”的标准格式,让模型能清晰识别工具的用途和调用方式。

比如计算器工具,需要明确说明“用于执行简单数学运算,输入必须是合法的算术表达式”;时间查询工具则说明“无需参数,直接返回当前系统时间”。同时,为了保证安全性,我们还会对工具的输入进行校验(如计算器的表达式白名单),避免恶意代码注入。

第三步:提示词构建——融入对话记忆与工具调用逻辑

提示词是模型触发工具调用的关键,我们需要构建包含“系统提示、对话历史、用户输入、工具调用中间步骤”的完整模板。其中,系统提示明确告知模型“需用中文回答、可自动调用工具”;对话历史占位符用于保存多轮交互记录,实现记忆功能;工具调用中间步骤占位符则用于存储模型调用工具的过程和结果,确保交互连贯。

第四步:Agent封装——整合模型、工具与记忆,实现自动流转

这是实现OpenAI Functions风格工具调用的核心步骤:通过LangChain的create_tool_calling_agent方法,将模型、封装好的工具、提示词模板整合,创建一个能自动触发工具调用的Agent;再搭配对话记忆组件和Agent执行器,实现“用户输入→模型识别→工具调用→结果返回”的全流程自动化,同时限制最大工具调用次数,避免无限循环。

三、实际体验:轻量化交互,适配多种场景

搭建完成后,启动程序即可进行交互式对话,体验完全贴合OpenAI Functions的核心逻辑:

- 基础对话:用户输入“你好”,模型直接返回问候,无需调用工具;

- 工具调用:用户输入“123乘以456是多少”,模型自动调用计算器工具,返回计算结果;输入“现在几点”,自动调用时间查询工具,返回格式化时间;

- 多轮连贯:用户先问“现在几点”,再问“1小时后是几点”,模型结合上一轮的时间结果,调用计算器完成计算,实现连贯交互。

整个过程无需人工干预,模型能自主判断是否需要调用工具、调用哪个工具,完全复刻OpenAI Functions的使用体验,且纯本地运行,无需担心网络延迟和API调用成本。

四、总结与延伸

本次实现的核心价值,在于“用极简方式复刻OpenAI Functions的工具调用逻辑”——无需复杂的代码开发,借助LangChain的封装能力,快速对接本地模型,实现自动化工具调用和多轮对话记忆。

其实,OpenAI Functions的本质不是“调用工具”,而是“让模型学会判断需求、选择工具、处理结果”,这也是大模型从“语言生成”向“实际应用”落地的关键一步。

后续我们还可以基于这个框架,扩展更多工具(如天气查询、文件读取、API调用等),只需按照相同的规范封装工具,即可实现更多场景的自动化处理,真正让大模型成为高效的辅助工具。

代码实现:

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

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

# -*- coding: utf-8 -*-

"""

基于 LangChain 的 Tool Calling 智能助手

- 对接兼容 OpenAI 工具调用格式的本地大模型(qwen3.5-27b-awq)

- 内置工具:数学计算器、获取当前时间(纯本地实现,无外部依赖)

- 支持多轮对话记忆,可连贯交互

- 核心架构:OpenAI 风格函数调用(Tool Calling)Agent

"""

importos

fromdatetimeimportdatetime

fromdotenvimportload_dotenv

# 导入 LangChain 核心组件:工具调用 Agent、执行器

fromlangchain.agentsimportcreate_tool_calling_agent, AgentExecutor

# 导入工具封装类

fromlangchain_core.toolsimportTool

# 导入兼容 OpenAI 接口的聊天模型

fromlangchain_openaiimportChatOpenAI

# 导入提示词模板、对话占位符

fromlangchain.promptsimportChatPromptTemplate, MessagesPlaceholder

# 导入对话记忆组件,用于保存历史对话

fromlangchain.memoryimportConversationBufferMemory

# 加载 .env 文件中的环境变量(当前代码未使用,保留以支持扩展)

load_dotenv()

# ========================

# 1. 初始化大语言模型

# 说明:使用 ChatOpenAI 封装对接本地模型,因本地模型兼容 OpenAI 工具调用协议

# ========================

# 本地模型 API Key(按需替换,部分本地部署无需真实密钥)

DEEPSEEK_API_KEY="123"

llm=ChatOpenAI(

api_key=DEEPSEEK_API_KEY,

base_url="http://192.168.0.100:8085/v1",# 本地模型接口地址

model="qwen3.5-27b-awq",# 模型名称

temperature=0.3,# 温度系数,值越低回答越确定

max_tokens=1024,# 最大生成 token 数

)

# ========================

# 2. 定义本地工具函数

# 工具会被 Agent 自动调用,用于处理模型无法直接完成的任务

# ========================

defcalculate(expression:str)->str:

"""

安全计算简单数学表达式

:param expression: 数学表达式字符串,例如 '2 + 3 * 4'

:return: 计算结果或错误信息

"""

try:

# 白名单校验:仅允许数字、运算符、括号和空格,防止恶意代码执行

allowed=set("0123456789+-*/(). ")

ifnotall(cinallowedforcinexpression):

return"错误:表达式包含非法字符"

# 安全执行表达式,禁用内置函数防止代码注入

result=eval(expression, {"__builtins__": {}}, {})

returnstr(result)

exceptException as e:

returnf"计算失败: {str(e)}"

defget_current_time(dummy:str="")->str:

"""

获取当前系统日期和时间

:param dummy: 占位参数,适配工具调用格式

:return: 格式化的当前时间字符串

"""

returndatetime.now().strftime("%Y年%m%d %H:%M:%S")

# 将自定义函数注册为 LangChain 标准工具

tools=[

Tool(

name="calculate",

func=calculate,

description="执行简单数学运算。输入必须是合法的算术表达式字符串,如 '15 * 6'。",

),

Tool(

name="get_current_time",

func=get_current_time,

description="获取当前系统时间。无需传入实际参数。",

),

]

# ========================

# 3. 构建提示词模板

# 包含系统提示、对话历史、用户输入、工具调用中间步骤

# ========================

prompt=ChatPromptTemplate.from_messages([

("system","你是一个智能助手,能调用工具完成用户请求。请始终用中文回答。"),

MessagesPlaceholder("chat_history"),# 对话历史占位符,实现多轮记忆

("human","{input}"),# 用户当前输入占位符

MessagesPlaceholder("agent_scratchpad"),# 工具调用过程占位符,Agent 内部使用

])

# ========================

# 4. 创建 Tool Calling Agent 及执行器

# ========================

# 创建支持工具调用的 Agent(OpenAI 函数调用格式)

agent=create_tool_calling_agent(llm, tools, prompt)

# 初始化对话记忆:存储聊天历史,保持多轮交互连贯性

memory=ConversationBufferMemory(

memory_key="chat_history",# 与提示词中占位符名称一致

return_messages=True,# 返回消息对象而非字符串,保证格式兼容

)

# 创建 Agent 执行器:负责运行 Agent、调用工具、管理记忆

agent_executor=AgentExecutor(

agent=agent,

tools=tools,

memory=memory,

verbose=True,# 打印详细执行过程,方便调试

handle_parsing_errors=True,# 自动处理解析错误,提升稳定性

max_iterations=5,# 最大工具调用次数,防止无限循环

)

# ========================

# 5. 启动交互式对话

# 循环接收用户输入,调用 Agent 并输出回答

# ========================

if__name__=="__main__":

print("🤖 本地模型 Tool Calling 助手启动!")

print("💡 示例:你好、现在几点?、123 乘以 456 等于多少?")

print("🛑 输入 quit / exit 可退出程序。\n")

whileTrue:

user_input=input("👤 你: ").strip()

# 退出条件判断

ifnotuser_inputoruser_input.lower()in["quit","exit"]:

print("👋 再见!")

break

try:

# 调用 Agent 执行器获取回答

response=agent_executor.invoke({"input": user_input})

# 打印原始响应(调试用)

print("原始模型响应:", response)

# 输出最终回答

print(f"🤖 助手: {response['output']}\n")

exceptException as e:

print(f"❌ 错误: {e}\n")

对话内容:

🤖 本地模型 Tool Calling 助手启动!
💡 示例:你好、现在几点?、123 乘以 456 等于多少?
🛑 输入 quit / exit 可退出程序。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 12:50:00

APIAuto接口测试集成CI/CD流水线:构建自动化质量门禁的完整实践

1. 项目概述:为什么我们需要在流水线里“焊死”接口回归测试?干了这么多年开发和测试,我见过太多团队在CI/CD这条高速公路上飙车,结果却在“接口回归”这个老路障上翻车。代码提交了,镜像打包了,容器也部署…

作者头像 李华
网站建设 2026/7/4 12:49:14

基于Dlib与泊松融合的人脸交换技术实现

1. 人脸融合技术概述 人脸融合是计算机视觉领域的一项重要技术,它能够将一张人脸的特征区域无缝融合到另一张人脸上,同时保持目标人脸的原有结构和背景。这项技术在影视特效、美颜应用、创意设计等领域有着广泛的应用场景。 传统的人脸交换技术往往存在…

作者头像 李华
网站建设 2026/7/4 12:49:11

3步搞定B站缓存视频合并:零门槛导出完整MP4视频的终极指南

3步搞定B站缓存视频合并:零门槛导出完整MP4视频的终极指南 【免费下载链接】BilibiliCacheVideoMerge 🔥🔥Android上将bilibili缓存视频合并导出为mp4,支持安卓5.0 ~ 13,视频挂载弹幕播放(Android consolidates and ex…

作者头像 李华
网站建设 2026/7/4 12:48:59

STM32智能温控系统设计与实现

1. 项目背景与核心需求 在嵌入式电子系统设计中,散热管理一直是工程师面临的关键挑战之一。特别是对于汽车电子、工业控制等场景,系统长时间高负载运行产生的热量若不能有效散发,轻则导致性能降频,重则引发硬件损坏。我曾参与过一…

作者头像 李华
网站建设 2026/7/4 12:48:44

LlamaIndex向量检索实战:从原理到优化全解析

1. LlamaIndex核心价值解析 LlamaIndex作为当前最热门的向量检索工具之一,正在彻底改变我们处理非结构化数据的方式。我在实际项目中用它处理过百万级PDF文档检索,相比传统方案查询速度提升近20倍。这个开源框架最吸引人的地方在于,它能将任意…

作者头像 李华
网站建设 2026/7/4 12:47:25

基于WebAuthn的无密码登录实战:从awesome-webauthn到完整应用

1. 项目概述:为什么我们需要WebAuthn? 如果你和我一样,在过去十年里处理过无数用户登录、密码重置和双因素认证的工单,那你一定对“密码疲劳”和“钓鱼攻击”这两个词深恶痛绝。用户总爱用“123456”,或者把公司邮箱密…

作者头像 李华