大语言模型(LLM)就像一个被隔离在房间里的大脑——它能思考,但没有感官接收实时信息,没有手脚执行具体任务,也缺乏持续学习的能力。

为了突破这些局限,你需要在大模型基础上构建一套完整系统,让它像业务专家一样感知环境、思考规划、执行任务并从经验中学习。

这个系统就是 Agent(智能体)。

它由以下核心模块构成:

核心模块 功能 类比
思考与规划 LLM 理解意图、拆解任务为可执行步骤 🧠 大脑
感知 接收用户输入、API 响应、系统状态 👀 感官
执行 调用 API、查询数据库、发送消息 ✋ 手脚
记忆 存储历史、经验、教训,支持决策 📚 记忆

这四个模块构成了“思考-行动-观察(ReAct范式)”的闭环。

通过这个循环,Agent 能够自主规划、执行任务、并根据现实反馈来调整行为,从而完成复杂任务。

让 Agent 学会使用工具

你的第一个工具函数

有同事正在开发一篇“大模型基本原理”的在线课程,他希望机器人可以帮他搜集互联网上最新的教学素材。

你会发现,机器人只能从公司知识库中检索信息,或者用大模型的世界知识回答问题。

硬编码方案:最简单的实现

要让机器人能获取互联网信息,最直接的思路是:为机器人编写一个联网搜索工具函数,它每次都会搜索用户的问题,并把搜索结果和问题一并发送给大模型。

假设你已经写好了一个名为 web_search 的函数,它可以通过搜索引擎查找资料。

现在,当用户提出请求时,你希望模型能够利用这个函数。

最简单的实现方式是,在收到请求后,程序“硬编码”执行这个函数,然后将执行结果与原始请求一并发送给大模型,让它生成一段总结性的回复。

# 1. 用户的原始请求
user_request = "你好,请帮我搜集一些关于 Transformer 模型的最新资料。"
# 2. “硬编码”执行工具函数
# 这里的 web_search 函数是模拟的,以聚焦于核心逻辑
def web_search(query: str):
"""模拟执行网络搜索并返回JSON格式的结果"""
print(f"--- [工具执行中] 正在搜索: {query} ---")
# 真实场景中,这里会调用一个真正的搜索引擎API
return '''{
"results": [
{"title": "Attention Is All You Need (Transformer 论文原文)", "url": "https://arxiv.org/abs/1706.03762", "snippet": "The dominant sequence transduction models are based on complex recurrent or convolutional neural networks... We propose a new simple network architecture, the Transformer, based solely on attention mechanisms..."},
{"title": "The Illustrated Transformer – Jay Alammar", "url": "https://jalammar.github.io/illustrated-transformer/", "snippet": "A visual and intuitive explanation of the Transformer model."}
]
}'''
tool_result = web_search(query=user_request)
print(f"用户请求: {user_request}")
print(f"工具结果: {tool_result}\n")
# 3. 将用户请求和工具结果拼接成一个提示,发送给大模型
#    目标是让模型基于结构化的工具输出,生成一句人类易于理解的回复。
completion = client.chat.completions.create(
model="qwen-plus",
messages=[
{'role': 'system', 'content': '你是一位课程研究助理,你的任务是根据工具的执行结果,向用户生成一句友好和清晰的回复。'},
{'role': 'user', 'content': f'用户原始请求: "{user_request}"\n工具执行结果: {tool_result}'}
]
)
# 4. 输出模型的最终回复
final_response = completion.choices[0].message.content
print(f"模型生成的最终回复:\n{final_response}")
局限性分析:为什么需要更灵活的方案

这种方式虽然简单有效,但它也有局限性:只适用于“有且仅有一个工具,且每次对话都必须调用它”的场景。

随着同事们的需求增长,你的机器人可能还要添加 search_arxiv_paper(在学术网站 Arxiv 搜索论文)、fetch_webpage_content(获取指定网页的全文内容)等更多工具。

这时,你会遇到一个更棘手的问题:如何让机器人按需调用工具呢?

意图识别:让 Agent 决定用什么工具(基于LLM的意图识别)

一个更优的思路是,你可以在提示词中列出所有工具,让大模型帮你决定调用哪个工具,使用什么入参。
这就是意图识别的一种简单实现。
def get_tool_decision_from_llm(user_request):
from textwrap import dedent
# 使用 dedent 移除为了代码美观而添加的缩进,
# 避免这些格式化用的tab/空格被传递给大模型
prompt = dedent(f"""
你是一个智能助理的路由模块。你的任务是根据用户的请求,从下面的工具列表中选择最合适的工具来解决问题,并给出入参。
[可用工具列表]
1. web_search: 用于在互联网上搜索通用信息。
2. search_arxiv_paper: 用于在 Arxiv.org 上搜索学术论文。
3. fetch_webpage_content: 用于获取指定URL的网页内容。
[用户请求]
"{user_request}"
[决策]
请告诉用户你的决定。
""")
completion = client.chat.completions.create(
model="qwen-plus",
messages=[
{'role': 'user', 'content': prompt}
],
temperature=0.0 # 使用低 temperature 以获得更确定的决策
)
decision = completion.choices[0].message.content
return decision
# --- 测试用例 ---
request = "帮我找一下那篇经典的 Transformer 论文,标题是 'Attention Is All You Need'"
decision = get_tool_decision_from_llm(request)
print(f"用户请求: \"{request}\"")
print(f"模型决策: {decision}\n")

确保可靠:结构化输出

现在你解决了“该调用哪个工具”的问题,下一步就是用代码解析和执行大模型的决策结果。

然而,你会发现大模型返回的结果夹杂着自然语言,且没有固定的格式:

  • 我将使用 search_arxiv_paper 工具来搜索标题为 "Attention Is All You Need" 的经典 Transformer 论文。
  • 好的,工具是 search_arxiv_paper
  • search_arxiv_paper(query="Attention Is All You Need")

这是因为大模型倾向于生成多样化的文本,而你需要的是一种易于解析的、确定的数据格式。

要解决这个问题,你需要反过来,要求模型必须按照你预设的、严格的结构化格式进行输出。

JSON 就是这样一种理想的格式。一份定义清晰的 JSON 输出是无歧义且易于解析的:

{

“tool_name”:“search_arxiv_paper”,

“parameters”:{

“query”:“Attention Is All You Need”

}

}

它清晰地定义了“做什么”(tool_name)和“用什么做”(parameters)。这种键值对结构,任何编程语言都能轻松解析。

构建"引导-校验-重试"闭环

接下来的任务,就是如何确保模型能够稳定、严格地按照你定义的 JSON 结构进行输出。要实现这一目标,你需要建立一套清晰的流程。

  1. 定义结构:首先,你需要精确地定义你期望的输出结构。你可以使用 JSON Schema(一种用于描述 JSON 数据结构的语言),或是在 Python 代码中通过 Pydantic 等库来定义数据模型。这个 Schema 明确了最终产出物必须包含哪些字段、每个字段的类型,是整个流程的基石。

  2. 构建提示词:在你的提示词中,除了要下达任务指令,你还应该附上完整的 Schema 定义,并提供一到两个完全符合该 Schema 的输出范例。通过这种"指令 + 范例"的方式,模型能更透彻地理解你的要求。

  3. 校验与重试:程序在收到模型的输出后,须使用相同的 Schema 进行严格验证。如果验证失败,程序应捕获验证的错误信息,并将其连同模型上一次的错误输出,作为修正线索,再次发给模型,要求它重新生成。

import json
from textwrap import dedent
from typing import Union, Literal
from pydantic import BaseModel, Field, ValidationError, TypeAdapter
# 1. 为与课程研究相关的工具定义 Pydantic 参数模型
class WebSearchParams(BaseModel):
query: str = Field(description="用于网络搜索的关键词。")
class SearchArxivParams(BaseModel):
query: str = Field(description="用于在 Arxiv.org 上搜索的论文标题或关键词。")
# 2. 定义工具调用模型,将工具名与对应的参数模型绑定
class WebSearchCall(BaseModel):
tool_name: Literal["web_search"]
parameters: WebSearchParams
class SearchArxivCall(BaseModel):
tool_name: Literal["search_arxiv_paper"]
parameters: SearchArxivParams
# 使用 Union 类型,表示模型最终的决策是这两种调用中的一种
ToolCall = Union[WebSearchCall, SearchArxivCall]
# 3. 构建提示词,包含清晰的指令、工具定义和示例
def build_prompt(user_request: str) -> str:
return dedent(f"""
你的任务是根据用户的请求,从可用工具列表中选择最合适的工具,并以严格的 JSON 格式输出调用信息。
# 可用工具:
- `web_search(query: str)`: 当需要搜索通用信息、新闻或非学术性内容时使用。
- `search_arxiv_paper(query: str)`: 当需要搜索学术论文,特别是来自 Arxiv.org 的论文时使用。
# 输出格式要求:
你必须严格按照以下 JSON 结构输出,不要包含任何额外的自然语言解释。
{{
"tool_name": "工具名称",
"parameters": {{
"参数名": "参数值"
}}
}}
# 示例:
用户请求: "最近AI领域有什么好玩的新闻?"
你的输出:
{{
"tool_name": "web_search",
"parameters": {{
"query": "AI领域最新新闻"
}}
}}
# 用户请求:
"{user_request}"
# 你的输出:
""")
# 4. 调用并验证(带重试)
def get_structured_output(user_request: str, max_retries: int = 2):
messages = [{'role': 'user', 'content': build_prompt(user_request)}]
adapter = TypeAdapter(ToolCall)
for attempt in range(max_retries):
# 此处为对大模型服务的API调用,为保证课程的通用性,具体实现已省略
# 你可以替换成自己的代码,例如 client.chat.completions.create(...)
response = client.chat.completions.create(
model="qwen-plus", messages=messages, temperature=0
)
raw_output = response.choices[0].message.content
try:
# 解析并验证
data = json.loads(raw_output.strip('```json').strip('```'))
# 使用Pydantic模型验证解析后的数据
validated_data = adapter.validate_python(data)
return validated_data.model_dump()
except (json.JSONDecodeError, ValidationError) as e:
# 如果失败,则将错误信息和原始输出都加入到对话历史中,以便模型进行修正
messages.extend([
{'role': 'assistant', 'content': raw_output},
{'role': 'user', 'content': f"格式错误: {e},请严格按照JSON格式重新输出"}
])
return None
# 使用
# 假设 client 变量已在别处初始化
user_request = "帮我找一下那篇经典的 Transformer 论文,标题是 'Attention Is All You Need'"
result = get_structured_output(user_request)
if result:
print(json.dumps(result, indent=2, ensure_ascii=False))

通过建立这样一个“引导-校验-重试”的闭环,你可以提升解析的成功率,让你的工具调用代码变得更加健壮可靠。

扩展阅读:受控解码

许多模型服务商提供的“JSON 模式”并非单纯依靠“优化训练”,而是采用了一种更精准的技术:受控解码

在模型生成每一个词元 (Token) 时,它会先计算出所有候选词元的概率分布。此时,系统会根据你提供的 Schema 编译出的语法规则,从这些候选词元中屏蔽掉所有不可能组成合法 JSON 的选项。

这就好比一个语法检查器,但它不是在事后检查,而是在你每次选择下一个字符时,就把所有会导致语法错误的选项从键盘上"隐藏"起来。

这项技术将"输出格式"从一个需要模型去"学习"的模糊任务,变成了一个由语法规则驱动的确定性过程,从根本上保证了输出的可靠性。

主流方案:函数调用

Function Calling 的工作原理

你刚刚手动实现的“意图识别 -> 结构化输出 -> 验证与重试”是一套健壮的工具调用流程,它的完整实现较为复杂。

为了简化开发过程,许多大模型服务商(阿里云、OpenAI、Anthropic、Google等)已在 API 中内置了这一能力,这就是函数调用 (Function Calling)工具调用 (Tool Calling)

以 OpenAI SDK 的函数调用为例:

  • 工具定义 (Tool Definition): 你需要在 API 的 tools 参数中定义可用的工具,使用 JSON Schema 描述每个工具的 namedescription 以及 parameters(函数所需的输入参数结构)。
  • 调用决策 (Call Decision): 模型根据用户输入和工具定义,自动决策是否需要调用工具。如果需要,模型会在响应中返回 tool_calls 字段,包含要调用的函数名和符合 Schema 的参数 JSON。
  • 执行与返回 (Execute & Return): 你需要
  1. 解析 tool_calls 中的函数名和参数
  2. 在你的代码中实际执行对应的函数
  3. 将函数执行结果包装成一条 role: "tool" 的 message
  4. 再次调用 API,将工具执行结果发送给模型
  5. 模型基于工具返回的结果,生成最终的用户回复。

import json
# 1. 定义工具列表,包含每个函数的JSON Schema描述
tools = [
{
"type": "function",
"function": {
"name": "search_arxiv_paper",
"description": "在 Arxiv.org 上搜索学术论文",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "论文的标题或关键词"},
},
"required": ["query"],
},
}
}
]
# 2. 发起第一次API调用,让模型决策
messages = [{"role": "user", "content": "帮我找一下那篇经典的 Transformer 论文 'Attention Is All You Need'"}]
response = client.chat.completions.create(
model="qwen-plus", messages=messages, tools=tools, tool_choice="auto"
)
response_message = response.choices[0].message
# 3. 检查模型是否决定调用工具并执行
if response_message.tool_calls:
tool_call = response_message.tool_calls[0]
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f"模型决定调用工具: `{function_name}`")
print(f"参数: {function_args}")
# 这里我们模拟函数执行结果
tool_result = json.dumps({"paper_id": "1706.03762", "url": "https://arxiv.org/abs/1706.03762", "title": "Attention Is All You Need"})
print(f"工具执行结果: {tool_result}")
# 4. 将模型的决策和工具的执行结果一起传回,让模型生成最终答复
messages.append(response_message)
messages.append(
{"tool_call_id": tool_call.id, "role": "tool", "name": function_name, "content": tool_result}
)
final_response = client.chat.completions.create(model="qwen-plus", messages=messages)
print("\n模型的最终回复:")
print(final_response.choices[0].message.content)
ReAct 模式:思考-行动-观察

你会发现,工具调用的结果是通过又一次调用传递给大模型的,大模型会观察工具调用的结果,然后思考任务是否完成,从而回复你最终答案或继续行动(调用工具)。

这和你之前学过的"多轮对话"很相似。

我们把这种思考——行动——观察的循环模式称为 ReAct,按照此模式工作的 Agent 称为 ReAct Agent

手动实现 ReAct Agent 的逻辑比较复杂。为了简化开发流程,我们将使用 AgentScope 这一生产级 Agent 框架——它已经帮你封装好了 ReAct Agent 和工具调用的完整逻辑。

AgentScope 是一套为开发者设计的、生产级别的 Agent 框架。它通过规范化的方式定义智能体的通信、记忆和工具调用,让你能专注于业务逻辑而非底层实现。AgentScope 的核心优势包括:

  • 开箱即用的 ReAct Agent

    :内置了完整的"思考-行动-观察"循环逻辑

  • 灵活的工具管理

    :通过 Toolkit 类统一管理工具函数,支持自动解析工具的 JSON Schema

  • 多模型支持

    :兼容 OpenAI、DashScope(千问)、Anthropic 等主流 LLM API

  • 状态管理

    :自动处理对话历史、工具调用记录等状态

  • 异步支持

    :所有核心功能都支持异步调用,提升性能

让我们来看一下 AgentScope 是怎么实现刚才的工具调用的:

import asyncio
from agentscope.agent import ReActAgent
from agentscope.tool import Toolkit, ToolResponse
from agentscope.model import DashScopeChatModel
from agentscope.message import Msg, TextBlock
from agentscope.formatter import DashScopeChatFormatter
# 1. 定义一个工具,使用 ToolResponse 返回结果
def search_arxiv_paper(query: str) -> ToolResponse:
"""在 Arxiv.org 上搜索学术论文。
Args:
query (str): 搜索关键词
"""
print(f"--- [工具执行中] 正在 Arxiv 搜索: {query} ---")
# 此处模拟搜索结果
paper_url = "https://arxiv.org/abs/1706.03762"
return ToolResponse(
content=[
TextBlock(
type="text",
text=f"已成功找到论文 '{query}',你可以在这里访问:{paper_url}",
)
]
)
async def run_agentscope_example():
# 2. 将工具函数注册到工具箱(Toolkit)中
toolkit = Toolkit()
toolkit.register_tool_function(search_arxiv_paper)
# 3. 创建一个 ReActAgent 并为其配备工具箱
agent = ReActAgent(
name="Course Research Agent",
sys_prompt="你是一个课程研究助理,擅长帮人搜集和整理学习资料。",
model=DashScopeChatModel(
model_name="qwen-plus",
api_key=os.environ.get("DASHSCOPE_API_KEY")
),
toolkit=toolkit,
formatter=DashScopeChatFormatter()
)
# 4. 向 Agent 发送消息,它会自动完成所有步骤
user_request = "帮我找一下那篇经典的 Transformer 论文 'Attention Is All You Need'"
msg = Msg(name="user", content=user_request, role="user")
print(f"用户请求: {user_request}\n")
await agent(msg)
# 运行示例
try:
# 在Jupyter Notebook环境中,可以直接await协程
await run_agentscope_example()
except NameError:
# 在普通Python脚本中,需要使用asyncio.run()来运行异步函数
asyncio.run(run_agentscope_example())

与之前手动实现的 OpenAI Function Calling 相比,AgentScope 的优势在于:

  1. 工具定义更简洁

    :只需要写带文档字符串的普通 Python 函数,框架会自动解析生成 JSON Schema

  2. 无需手动解析

    ReActAgent 内部自动处理 tool_calls 的解析、函数执行、结果包装等繁琐步骤

  3. 自动管理对话历史

    :框架会自动记录用户消息、工具调用、工具结果等,无需手动维护

  4. 支持多轮工具调用

    :如果一次工具调用不够,Agent 会自动继续思考并调用更多工具,直到完成任务

看到 AgentScope 的简洁实现,你可能会疑惑:既然有现成框架,为什么还要学习前面那套繁琐的手动实现?

这是因为:

  1. 理解底层原理:框架内部就是在执行"调用模型 → 解析 tool_calls → 执行函数 → 再次调用模型"这套流程。了解机制才能调试问题。
  2. 自定义需求:生产环境常需实现权限验证、缓存、重试、日志监控等特殊逻辑,理解底层才能扩展框架。
  3. 兼容性保障:部分模型或平台不支持标准 Function Calling 格式时,手动实现可作为降级方案。

规模化管理:MCP 协议 (Model Context Protocol)

工具复用的挑战

Function Calling 模式解决了单个应用如何调用工具的问题,但当工具需要在多个 Agent 应用中复用时,也引入了规模化维护的难题。

设想你的团队有多个 Agent,它们都需要调用互联网搜索、公司内部文档搜索等工具。如果工具的某个 API 参数发生变化,你需要修改所有依赖它的 Agent,这会产生高昂的维护成本。

问题的根源在于,工具的定义被硬编码在了每个“消费方”(Agent 应用)的代码中

MCP 的解耦思想

为解决此问题,Anthropic 公司提出了模型上下文协议 (Model Context Protocol, MCP)。其核心思想是将定义工具的职责从“消费方”转移到“提供方”。

  • 没有 MCP

    :每个 AI 应用都需要自行封装所有工具的定义。工具升级时,所有应用都需修改。

  • 使用 MCP

    :工具服务方(如搜索服务)自行“广播”其能力定义。AI 应用只需通过 MCP 协议连接到服务方,就能自动获取最新的工具定义,无需硬编码。

实践:连接远程 MCP 服务

AgentScope 提供了对 MCP 协议的直接支持。下面是一个简单示例:

开始前 运行此代码前,请先前往阿里云百炼官网开通联网搜索 MCP 服务,并了解其计费详情。

import asyncio
import os
from agentscope.agent import ReActAgent
from agentscope.mcp import HttpStatelessClient
from agentscope.tool import Toolkit
from agentscope.model import DashScopeChatModel
from agentscope.message import Msg
from agentscope.formatter import DashScopeChatFormatter
async def run_mcp_example():
# 1. 配置 MCP 客户端,指向远程工具服务
#    这里连接的是阿里云DashScope公开的联网搜索MCP服务
web_search_client = HttpStatelessClient(
name="web_search_service", # 为这个客户端起一个名字
transport="sse",
url="https://dashscope.aliyuncs.com/api/v1/mcps/WebSearch/sse",
headers={"Authorization": "Bearer " + os.environ.get("DASHSCOPE_API_KEY")},
)
# 2. 将 MCP 客户端注册到工具箱
#    Agent在启动时会自动通过客户端“发现”远程服务提供的所有工具
toolkit = Toolkit()
await toolkit.register_mcp_client(web_search_client)
# 3. 创建 Agent,并配备包含 MCP 工具的工具箱
agent = ReActAgent(
name="Research Assistant Agent",
sys_prompt="你是一个课程研究助理,擅长使用工具搜集和整理最新的教学素材。",
model=DashScopeChatModel(
model_name="qwen-plus", api_key=os.environ.get("DASHSCOPE_API_KEY")
),
toolkit=toolkit,
formatter=DashScopeChatFormatter()
)
# 4. 提出一个需要远程工具才能回答的问题
user_request = "我正在为'大模型原理'课程搜集素材,需要一个调用外部实时数据的例子,比如帮我搜索一下最近关于'大型语言模型'的最新进展。"
msg = Msg(name="user", content=user_request, role="user")
print(f"用户请求: {user_request}\n")
response_msg = await agent(msg)
try:
# 在Jupyter Notebook环境中,可以直接await协程
await run_mcp_example()
except NameError:
# 在普通Python脚本中,需要使用asyncio.run()来运行异步函数
asyncio.run(run_mcp_example())

在这个例子中,Agent 代码无需定义 WebSearch 工具,通过 MCP 协议在运行时动态地从 web_search_service 服务发现工具及其用法,从而实现了完全解耦。

MCP 通过解耦工具的定义与使用,致力于解决工具“如何被发现和管理”的规模化问题。

关联思考:USB 协议

你可以将 MCP 类比为现实世界中的 USB 协议。在 USB 出现之前,每种外设(鼠标、键盘、打印机)都有自己独特的接口,计算机需要为每一种接口都做适配。而 USB 协议统一了这一切,任何符合该协议的设备都可以即插即用。

  • Function Calling

    就像是计算机主板上的一个内部总线,它定义了 CPU 如何与某个特定组件通信。

  • MCP

    则像是外部的 USB 接口,它定义了一个开放标准,让无数第三方设备能够轻松地接入这个生态系统。

至此,你已掌握从单工具函数、可靠意图识别到规模化工具管理的完整链路。

你的 Agent 现在可以稳定高效地与外部世界交互。

由于篇幅有限,Agent部分暂时简介到这里。

下面开始讲讲大模型的微调。

-------------------------这是分隔线--------------------------

当面对特定领域的深度需求时,比如小学数学题的精准解析,靠提示工程和 RAG 往往力不从心。

针对题目中涉及的运算优先级规则、应用题单位换算逻辑等细节,模型需要掌握结构化的知识体系。

此时,微调方法展现出独特优势——通过向模型提供小学数学教育专家精心设计的解题范例,模型能够学习专家的教学方法,掌握数学思维范式,并有效提升解题能力。

大模型微调是个啥?

在实际的模型训练过程中,还面临一个挑战:标注数据的获取成本高昂,尤其是对于特定任务(如医学图像分析或小众语言处理)。

你可以尝试对模型进行“预训练”和“微调”分步训练,其中:

预训练:在一个大规模通用数据集上训练模型,使其能够学习到广泛的基础知识或特征表示。

这些知识通常是通用的,不针对任何具体任务。预训练不针对特定任务,而是为各种下游任务提供一个强大的初始模型。

典型的预训练模型:Qwen2.5-Max、DeepSeek-V3、GPT-4等。

微调:在预训练模型的基础上,使用特定任务的小规模数据集对模型进行进一步训练。其目的是让模型适应具体的下游任务(如医疗、法务等专业领域需求)。

预训练一般通过自监督/无监督方式学习 ,学习的数据来自互联网上的海量文本(如维基百科、书籍、网页),让模型自己从数据中找规律或“猜答案。”

这种学习方式因为其数据无需人工标注,省去了大量人力成本,天然适用于海量数据的学习。

而微调通过有监督学习 ,需要针对特定任务的小规模标注数据(如情感分类的标注评论、医疗文本的标注数据),并用标注数据直接教模型完成任务。

这种学习方式由于人工标注成本高,难以扩展为海量数据,因此更适合有明确场景目标的模型训练,所需要的样本数量通常只有几千或几万条。

大模型微调技术

全参微调(Full Fine Tuning) 是在预训练模型的基础上进行全量参数微调的模型优化方法,也就是在上边的模型结构中,只要有参数,就会被调整。

该方法避免消耗重新开始训练模型所有参数所需的大量计算资源,又能避免部分参数未被微调导致模型性能下降。但是,大模型训练成本高昂,需要庞大的计算资源和大量的数据,即使是全参数微调,往往也需要较高的训练成本。

高效微调技术(PEFT) 通过调整少量参数,显著降低大模型微调的计算成本,同时保持性能接近全参训练。

典型方法包括Adapter Tuning、Prompt Tuning 和 LoRA。其中,LoRA 因仅需训练适配的小参数矩阵(即低秩矩阵,仅需原模型0.1%-1%的参数),成为资源受限场景下的首选方案。以下重点解析 LoRA 如何以极低参数量实现高效微调。

LoRA微调

模型训练后的使用方式

模型训练完成后,有两种方式可以使用训练后的模型:

  1. 在调用时动态加载微调模型。

    微调后获得的低秩参数矩阵只占20MB的存储空间,这个大小非常便于做增量发布和传播,这也是工程上常用的方法。需要注意的是,用哪个基础模型微调,在加载时就需要指定使用哪个基础模型。

    在前一小节中,已经通过指定ckpt_dir尝试了这种方法。

  2. 将基础模型与微调得到的低秩参数融合,获得一个完整的、更新了参数的模型,再调用融合了的模型。

这里介绍第二种方法:融合“微调参数矩阵”与“基础模型参数矩阵”,将微调后的模型参数存储成一个完整的参数矩阵。

通过swift export方法,传入微调模型的路径(建议传入best_model_checkpoint),便可得到融合后的模型。

更多高效微调方法

  • Freeze:该方法是最早的PEFT方法。它在微调时冻结模型的大部分参数,仅训练模型中的小部分参数(比如最后几层神经网络),来快速适应特定任务的需求。特点 :
  • 参数效率高(仅训练少量参数)。
  • 适用于任务与预训练目标接近的场景(如文本分类)。
  • 对复杂任务可能效果不足。

  • Adapter Tuning:在原有的模型架构上,在某些位置之间插入Adapter层,微调时模型原有参数不会被训练,只训练这些Adapter层,而原先的参数不会参与训练。特点 :
  • 模块化设计,兼容性强。
  • 参数量略高于 LoRA,但效果稳定。
  • 需修改模型结构,推理时需额外计算。

  • Prompt Tuning:通过优化输入的可学习向量(Prompt)间接控制模型行为,冻结模型参数。特点 :
  • 无需修改模型结构,仅调整输入。
  • 对生成任务(如翻译、对话)友好。
  • 效果依赖提示设计,复杂任务可能不足。
微调数据集构建策略

一般来说,在比较复杂的场景中,微调至少需要1000+条优质的训练集数据

构建数据集时,请确认以下几点:

  • 数据质量:确保数据集准确、内容相关,剔除模糊或错误样本。
  • 多样性覆盖:包含任务全场景、多语境及专业术语,避免分布单一。
  • 类别平衡:如果任务涉及多种类别场景,确保各类别样本均衡,防止模型偏向于某一类。
  • 持续迭代:微调是一个迭代过程,根据模型在验证集上的表现反馈,不断优化和扩大数据集。

而如果你在进行模型微调时缺乏数据,建议你使用知识库检索来增强模型能力(如业务文档、FAQ)。

在很多复杂的业务场景中,可以综合采用模型调优和知识库检索相结合的技术方案。

你也可以采用以下策略扩充数据集:

人工标注:由专家扩展典型场景数据。

模型生成:用大模型模拟业务场景数据。

外部采集:通过爬虫、公开数据集、用户反馈等渠道获取。

模型评测常用指标

不同类型的任务评测指标有显著差异,如下是一些典型任务的评测指标:

分类任务

准确率(Accuracy):正确预测的比例。

精确度(Precision)、召回率(Recall)与F1分数(F1 Score):用于衡量二分类或多分类问题中正类别的识别效果。

文本生成任务

BLEU (Bilingual Evaluation Understudy) :主要用于机器翻译等自然语言处理任务中,通过比较候选翻译与一个或多个参考翻译之间的n-gram重叠来计算得分。

ROUGE (Recall-Oriented Understudy for Gisting Evaluation) :常用于自动摘要评价,它基于n-gram召回率、精确率以及F-measure。

Perplexity (困惑度):用来衡量概率分布模型预测样本的不确定程度;越低越好。

图像识别/目标检测

Intersection over Union (IoU):两个边界框相交部分面积与并集面积之比。

mAP (mean Average Precision):平均精度均值,广泛应用于物体检测任务中。

最近两年大模型发展很迅速,在理论研究方面得到很大的拓展,基础模型的能力也取得重大突破,大模型现在正在积极探索落地的方向,如果与各行各业结合起来是未来落地的一个重大研究方向

大模型应用工程师年包50w+属于中等水平,如果想要入门大模型,那现在正是最佳时机

2025年Agent的元年,2026年将会百花齐放,相应的应用将覆盖文本,视频,语音,图像等全模态

如果你对AI大模型入门感兴趣,那么你需要的话可以点击这里大模型重磅福利:入门进阶全套104G学习资源包免费分享!

扫描下方csdn官方合作二维码获取哦!

在这里插入图片描述

给大家推荐一个大模型应用学习路线

这个学习路线的具体内容如下:

第一节:提示词工程

提示词是用于与AI模型沟通交流的,这一部分主要介绍基本概念和相应的实践,高级的提示词工程来实现模型最佳效果,以现实案例为基础进行案例讲解,在企业中除了微调之外,最喜欢的就是用提示词工程技术来实现模型性能的提升

img

第二节:检索增强生成(RAG)

可能大家经常会看见RAG这个名词,这个就是将向量数据库与大模型结合的技术,通过外部知识来增强改进提升大模型的回答结果,这一部分主要介绍RAG架构与组件,从零开始搭建RAG系统,生成部署RAG,性能优化等

img

第三节:微调

预训练之后的模型想要在具体任务上进行适配,那就需要通过微调来提升模型的性能,能满足定制化的需求,这一部分主要介绍微调的基础,模型适配技术,最佳实践的案例,以及资源优化等内容

img

第四节:模型部署

想要把预训练或者微调之后的模型应用于生产实践,那就需要部署,模型部署分为云端部署和本地部署,部署的过程中需要考虑硬件支持,服务器性能,以及对性能进行优化,使用过程中的监控维护等

img

第五节:人工智能系统和项目

这一部分主要介绍自主人工智能系统,包括代理框架,决策框架,多智能体系统,以及实际应用,然后通过实践项目应用前面学习到的知识,包括端到端的实现,行业相关情景等

img

学完上面的大模型应用技术,就可以去做一些开源的项目,大模型领域现在非常注重项目的落地,后续可以学习一些Agent框架等内容

上面的资料做了一些整理,有需要的同学可以下方添加二维码获取(仅供学习使用)

在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐