【大模型LLM学习】function call/agent学习记录

【大模型LLM学习】function call/agent学习记录

  • 0 前言
  • 1 langchain实现function call
  • 2 调用本地模型
  • 3 微调本地模型
    • 3.1 few-shot调用Claude生成Q-A对
    • 3.2 tools格式
    • 3.3 agent微调格式
    • 3.4 swift微调
  • p.s.

0 前言

  记录一下使用langchain做简单的function call/agent(或者说意图识别,如果函数有返回值再进行summary即可),以及冷启动的场景下造训练数据+微调的过程。

1 langchain实现function call

  预期是,用户输入一段话,判断应该调用哪个函数来解决这个问题,返回函数名+函数的参数,以正确调用函数。如果这个函数能直接解决问题,模型不用关心返回值是什么,本质上就是一个意图识别+槽填充。
在这里插入图片描述
  对于agent的模板,选用ReACT的回复模版,要求模型按照ReACT的格式来回答问题。一个具体的给模型看到的ReACT的提问模版如下,{tools}会填充funciton的描述,{input}会填充问模型的问题(或者说用户输入)。

react_template="""
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 questionBegin!Question: {input}
"""

  一个完整的ReACT过程包括Question->Thought->Action->Action Input->Observation->Thought->Final Answer这几个步骤:

  • Action对应的就是要调用的函数,Action input就是要调用的函数的参数。
  • 如果回答这个问题,模型觉得需要调用多个工具,就会有多个Action和Action Input。
  • Observation是调用的函数的返回结果,如果模型要对返回结果处理后给出回答,最后的Final Answer是模型的结果;如果模型只需要做function call,具体功能函数会去完成,函数的返回结果模型也不需要处理,在Observation这里停下来就可以了.

2 调用本地模型

  如果场景是函数/意图数量比较少,但是对准确率对要求比较高,可以微调一个本地模型来实现。调用本地模型需要先用swift部署一下:

# deploy.sh
CUDA_VISIBLE_DEVICES=0 # gpu卡号 \
swift deploy \--model /modelsavepath/Qwen/Qwen3-8b # 模型存储路径 \--infer_backend vllm--agent_template react_en  # agent的template的格式,使用ReACT的格式 --port 9123  # 模型部署到的端口# nohup bash deploy.sh > log_deploy.txt 2>&1

  在langchain中,调用本地的qwen模型使用ChatOpenAI来调用

from langchain_openai import ChatOpenAI
model = ChatOpenAI(model_name='Qwen3-8b', # 模型名字,如果是微调后的模型,名字例如checkpoint-378-merged,部署的时候可以在log_deploy.txt里面查到;openai_api_key='EMPTY', # 本地的模型base_url='http://本机ip:9123/v1',stop=['Observation:','\nObservation: ','Observation:\n']  # 用于识别意图,ReACT的格式在Observation这里就停下来就可以
)

  使用langchain完成模型端的代码,再Flask包装一个HTTP服务:

from flask import Flask, request, jsonify
import requests
from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent, Tool
from typing import Dict, Any
from typing_extensions import Annotated, TypedDict
import json
from langchain_core.messages import AIMessage, HumanMessage, ToolMessage,SystemMessage
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from typing import Dict, Optional, Literal
from pydantic import BaseModel, Field
from langchain.tools import BaseTool
import astclass chat_with_user(TypedDict):
"""判断用户的意图是闲聊,调用这个函数完成与用户的闲聊"""user_question:Annoted[str,"","用户问的问题"]class get_weather(BaseModel):
"""判断用户的意图是问天气怎么样,调用这个函数帮用户查天气"""date:int = Field(default=0,description="用户想查天气的时间距离今天的天数,如果查今天,这个值为0,如果查明天,这个值为1",ge=0)city:str = Field(default="北京",description="用户想查天气的城市名")model = ChatOpenAI(model_name='Qwen3-8b', # 模型名字,如果是微调后的模型,名字例如checkpoint-378-merged,部署的时候可以在log_deploy.txt里面查到;openai_api_key='EMPTY', # 本地的模型base_url='http://本机ip:9123/v1',stop=['Observation:','\nObservation: ','Observation:\n']  # 用于识别意图,ReACT的格式在Observation这里就停下来就可以
)
tools = [chat_with_user,get_weather]
model_with_tool = model.bind_tools(tools)
app=Flask(__name__)@app.route('/api/predict/',method=['POST'])
def predict():gloal model_with_tooluser_input = request.jsoninput = user_input.get('user') # 如果是没微调的qwen3可以拼接加入"/no_think"字符串避免模型思考model_with_tool.invoke(input)print(response.tool_calls[0]['name']) # 函数名print(response.tool_calls[0]['args']) # 函数参数if __name__=='__main__':app.run(host='本地ip',port=1234)

  可以使用HTTP的方式调用:

import requests
url = 'http//上面的本地ip:1234/api/predict'
data = {'user':'你好呀'}
response = requests.post(url,json=data)url = 'http//上面的本地ip:1234/api/predict'
data = {'user':'明天洛阳天气怎么样'}
response = requests.post(url,json=data)

3 微调本地模型

  专有业务场景下,如果之前就收集了很多问答数据,可以构造出对应的agent训练数据来微调本地模型。但是如果是一个新的业务场景,冷启动的情况下,可以借助闭源大模型的能力构造问答数据,可以参考OpenBMB的给出的一个开源的方案AutoPlan。AutoPlan可以实现冷启动场景下,复杂的长链条的问题的生成,因为目前还没有接触到类似的场景,简化版的流程如下:

  1. 给定tool+问题示例,生成模拟的问题,模仿用户的各种输入:(可以一次只针对一个function call)给Claude提供几条示例的用户输入数据+function的描述,把Claude的temperature调高,让Claude给出X条类似的问题能触发这个function call/被这个funciton解决的,尽量生成多样化的问题,可以人工筛选一下或者AI质检提升质量,记录好funciton名+问题便于后面调用生成回答
  2. Q-A对获取:把前面生成的问题让Claude来回答,给定tools+问题,生成答案,获得Q-A对
  3. (可选)根据函数返回值,再次调用Claude整合出最终返回用户的结果

3.1 few-shot调用Claude生成Q-A对

  调用Claude时,直接让Claude回答的效果不一定好,可以给一些few-shot示例。如果函数多,可以利用前面记录下的函数名,针对性的给few shot示例。Claude模型是支持langchain里面的toolmessage的,有的模型例如qwen可能不支持。本质上这些few shot最后都是以字符串的形式传递的,如果不支持,以字符串的形式传递也可。
  使用langchain的few-shot的template,需要注意examples是一个list[]而不是嵌套的list。本质上few-shot是字符串的形式,需要让模型这道这一段是few-shot,而不是正式的上下文,所以可以加上写system prompt来区分。对于同一个Toolmessage和对应的tool_calls,通过id来进行对应,需要让它们的id一致。

examples = [SystemMessage(content="为了便于你识别要调用的工具,给你提供几个示例\n--- 示例开始 ---"),)HumanMessage("早上好",name="example_user"),AIMessage("用户在打招呼,属于闲聊。根据工具描述,chat_with_user适用于这种情况。",name="example_assisstant",tool_calls={"name":"chat_with_user","args":{"user_question":"早上好"},"id":"1"}),ToolMessage("",tool_call_id="1"),HumanMessage("查明天南京天气",name="example_user"),AIMessage("用户想查天气,城市为南京,日期为明天。",name="example_assisstant",tool_calls={"name":"get_weather","args":{"date":"1","city":"南京"},"id":"2"}),ToolMessage("",tool_call_id="2"),SystemMessage(content="\n--- 示例结束 ---\n"),)
]
few_shot_prompt = ChatPromptTemplate.from_messages([("system", "你是一个专业的用户助手。"),*examples,("human", "{query}"),]
)llm = ChatOpenAI()# claude的API
tools = [chat_with_user,get_weather]
llm_claude = few_shot_prompt|tools

3.2 tools格式

  关于微调时tools的格式问题,有一种最简单的方式是,直接导出langchain里面的tools的描述,这样就能保证一致性了。

tools_desc = model_with_tool.kwargs.get('tools')
json.dump(tools_desc,open('tool_desc.json','w'),ensure_ascii=False,indent=4)
with open('tool_desc.json','r',encoding='utf-8') as f:tools_list = json.load(f)
tools_d = [tools_list[i] for i in range(len(tools_list)]
tools_str = json.dump(tools_d,ensure_ascii=False) # 变成字符串格式

3.3 agent微调格式

  使用swift来训练微调,主要是要整理成对应的格式,tools使用上面dump的拼上来即可,swift的agent微调格式为

{'id':'123',
'tools':'[{"type":"function","funciton":{"name":"chat_with_user","description":"判断用户的意图是闲聊,调用这个函数完成与用户的闲聊","parameters":{...}}}]', 
'conversation':[{'from':'user','value':'早上好'},{'from':'assisstant','value':'Thought: 用户在打招呼,是在闲聊,我将使用chat_with_user来和用户闲聊。\nAction: chat_with_user\nAction Input: {"user_question":"早上好"}\nObservation '}]
}

3.4 swift微调

  与常规微调一致,指定agent_template为react_en

source activate swiftCUDA_VISIBLE_DEVICES=2,3 swift sft \
--model /data/coding/llm_model/Qwen/Qwen3-8B \
--dataset /data/coding/xxxx.jsonl \
--train_type lora \
--device_map auto \
--agent_template react_en \
--per_device_train_batch_size 2 \
--per_device_eval_batch_size 1 \
--split_dataset_ratio 0.1 \
--output_dir /data/coding/lora_qwen3_8b/ \
--num_train_epochs 5 \
--lorap_lr_ratio 10 \
--save_steps 50 \
--eval_steps 50 \
--save_total_limit 2 \
--logging_steps 10 \
--seed 42 \
--learning_rate 1e-4 \
--init_weights true \
--lora_rank 8 \
--lora_alpha 32 \
--adam_beta1 0.9 \
--adam_beta2 0.95 \
--adam_epsilon 1e-08 \
--weight_decay 0.1 \
--gradient_accumulation_steps 8 \
--max_grad_norm 1 \
--lr_scheduler_type cosine \
--warmup_ratio 0.05 \
--warmup_steps 0 \
--gradient_checkpointing false

p.s.

  最近mcp很火,mcp是用另一种风格包装了一下函数接口,最后本质上和模型交互还是用比如ReACT的方式,能力上限由function的能力和模型的能力决定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/908702.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…

Puppeteer测试框架 - Node.js

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】

compose 组件 ---无ui组件

在 Jetpack Compose 中,确实存在不直接参与 UI 渲染的组件,它们主要用于逻辑处理、状态管理或副作用控制。这些组件虽然没有视觉界面,但在架构中扮演重要角色。以下是常见的非 UI 组件及其用途: 1. 无 UI 的 Compose 组件分类 (…

图像超分辨率

图像超分辨率 用AI当“像素侦探”,从模糊中重建合理高清细节,让看不见的细节“无中生有”。 举个生活例子 假设你有一张模糊的老照片,通过超分辨率技术,它能变成清晰的高清照片: 低分辨率图像超分辨率结果 传统放…

多线程语音识别工具

软件介绍 本文介绍一款支持大厂接口的语音转文字工具,具备免配置、免费使用的特点。 软件特性 该工具是一款完全免费的桌面端应用程序,部署于开源社区平台,其核心优势在于整合了多家技术供应商的接口资源。 操作方式 用户只需将音频…

金融预测模型开发:数据预处理、机器学习预测与交易策略优化

金融预测模型开发:数据预处理、机器学习预测与交易策略优化 概述 本文将详细介绍一个完整的金融预测模型开发流程,包含数据预处理、机器学习预测和交易策略优化三个核心模块。我们使用Python实现一个端到端的解决方案,适用于股票价格预测和量化交易策略开发。 # 导入必要…

triton学习笔记7: GEMM相关

这是之前的学习笔记 triton puzzles part1triton puzzles part2triton puzzles part3triton tutorials part1triton tutorials: part2triton tutorails: part3 这是triton tutorials里最后一篇关于GEMM的系列了 GEMM的知识可以参考这篇,写的非常详细具体https://…

食养有方:进行性核上性麻痹患者的健康饮食指南

进行性核上性麻痹是一种罕见的神经系统变性疾病,患者常出现吞咽困难、肢体运动障碍等症状,合理的饮食安排不仅能保证营养供给,还能缓解不适,提高生活质量。以下是适合这类患者的健康饮食建议。 ​患者饮食应遵循 “均衡、细软、易…

使用ORM Bee (ormbee) ,如何利用SQLAlchemy的模型生成数据库表.

使用ORM Bee (ormbee) ,如何利用SQLAlchemy的模型生成数据库表. 将原来SQLAlchemy的模型,修改依赖为: from bee.helper import SQLAlchemy 然后就可以开始生成了。很简单,主要是两个接口。 db.create_all(True) #创建所有模型的表…

C# 使用正则表达式

C# 使用正则表达式 /// <summary> /// 测试正则表达式 /// </summary> private static void test022() {//检查是否匹配&#xff1a;Regex.IsMatch(currencyValue, pattern); 或 new Regex(...).IsMatch(currencyValue)string pattern "\d{3,}";bool b…

LLMs之RLVR:《Absolute Zero: Reinforced Self-play Reasoning with Zero Data》翻译与解读

LLMs之RLVR&#xff1a;《Absolute Zero: Reinforced Self-play Reasoning with Zero Data》翻译与解读 导读&#xff1a;Absolute Zero范式通过让模型在没有外部数据的情况下&#xff0c;自主提出和解决任务&#xff0c;实现了推理能力的显著提升。Absolute Zero Reasoner (AZ…

信息最大化(Information Maximization)

信息最大化在目标域无标签的域自适应任务中&#xff0c;它迫使模型在没有真实标签的情况下&#xff0c;对未标记数据产生高置信度且类别均衡的预测。此外&#xff0c;这些预测也可以作为伪标签用于自训练。 例如&#xff0c;在目标域没有标签时&#xff0c;信息最大化损失可以…

AUTOSAR实战教程--标准协议栈实现DoIP转DoCAN的方法

目录 软件架构 关键知识点 第一:PDUR的缓存作用 第二:CANTP的组包拆包功能 第三:流控帧的意义 配置过程 步骤0:ECUC模块中PDU创建 步骤1:SoAD模块维持不变 步骤2:DoIP模块为Gateway功能添加Connection ​步骤3:DoIP模块为Gateway新增LA/TA/SA ​步骤4:PDUR模…

设备驱动与文件系统:05 文件使用磁盘的实现

从文件使用磁盘的实现逻辑分享 我们现在讲第30讲&#xff0c;内容是文件使用磁盘的具体实现&#xff0c;也就是相关代码是如何编写的。上一节我们探讨了如何从字符流位置算出盘块号&#xff0c;这是文件操作磁盘的核心。而这节课&#xff0c;我们将深入研究实现这一核心功能的…

【PCIe总线】-- inbound、outbound配置

PCI、PCIe相关知识整理汇总 【PCIe总线】 -- PCI、PCIe相关实现 由之前的PCIe基础知识可知&#xff0c;pcie的组成有&#xff1a;RC&#xff08;根节点&#xff09;、siwtch&#xff08;pcie桥&#xff09;、EP&#xff08;设备&#xff09;。 RC和EP&#xff0c;以及EP和EP能…

20250607在荣品的PRO-RK3566开发板的Android13系统下实现长按开机之后出现插入适配器不会自动启动的问题的解决

20250607在荣品的PRO-RK3566开发板的Android13系统下实现长按开机之后出现插入适配器不会自动启动的问题的解决 2025/6/7 17:20 缘起&#xff1a; 1、根据RK809的DATASHEET&#xff0c;短按开机【100ms/500ms】/长按关机&#xff0c;长按关机。6s/8s/10s 我在网上找到的DATASHE…

AIGC 基础篇 Python基础 02

1.bool类型 书接上回&#xff0c;我们上次最后讲了三大数据类型&#xff0c;除了这三个之外&#xff0c;Python也有bool类型&#xff0c;也就是True和False。 a 2 print(a1) print(a2) 像这里&#xff0c;输出的内容第一个是False&#xff0c;因为a的值为2&#xff0c;而第…

华为大规模——重塑生产力

华为大模型通过以下几个方面重塑生产力&#xff1a; 提供强大算力支持 华为致力于构建领先的昇腾人工智能算力平台&#xff0c;推出高性能昇腾AI集群&#xff0c;支持月级长期稳定训练&#xff0c;可靠性业界领先。同时打造开放的昇腾计算平台&#xff0c;兼容主流算子、框…

iOS上传应用包错误问题 “Invalid bundle. The “UIInterfaceOrientationPortrait”“

引言 在开发 iOS 应用的整个生命周期中&#xff0c;打包上传到 App Store 是一个至关重要的步骤。每一次提交&#xff0c;Xcode 都会在后台执行一系列严格的校验流程&#xff0c;包括对 Info.plist 配置的检查、架构兼容性的验证、资源完整性的审查等。如果某些关键项配置不当…

【计算机组成原理】缓冲技术SPOOLing技术

缓冲技术 单缓冲区&#xff1a;初始&#xff1a;工作区满&#xff0c;缓冲区空 每块用时max(处理时间, 输入时间) 传送时间双缓冲区&#xff1a;先装1&#xff0c;1满才装2。初始&#xff1a;工作区空&#xff0c;1空&#xff0c;2满 每块用时max(处理时间, 传送时间) 输入时…