🔥【Agent】应用全流程
🗓 2026年10月24日 📁 文章归类: 0x23_深度学习
版权声明:本文作者是郭飞。转载随意,标明原文链接即可。
原文链接:https://www.guofei.site/2026/10/24/agent.html
相关资料
- 已过时)【Agent】应用全流程
- 这里的 RAG、MCP 等已经过时了
- 因此重新整理一份资料
- 【LLM】提问的艺术:如何写好prompt
- 这个也多半过时了
- 【Transformer】Bert和GPT
- DNN训练
Prompt
经过十几个月的发展,提示词工程中技巧性的部分已经不重要了。现在的模型唯一刚需是把非通用的背景知识、目的等写清楚。
RTF 框架可以继续使用,这仍然是一个还不错的格式化书写方法。
调用大模型
推荐 HTTP 方式调用(使用 request)
密钥管理:
# Linux:
echo 'export LLM_API_KEY="你的真实API_KEY"' >> ~/.bashrc
source ~/.bashrc
# MacBook:
echo 'export LLM_API_KEY="你的真实API_KEY"' >> ~/.zshrc
source ~/.zshrc
# 测试已经成功设置
test -n "$LLM_API_KEY" && echo "API Key 已设置"
import os
import requests
api_key = os.environ["LLM_API_KEY"]
endpoint_url = "https://xxx.xxx.com/v1/chat/completions" # 注意结尾是 /v1/chat/completions
class LLMClient:
def __init__(self, api_key, endpoint_url):
self.endpoint_url = endpoint_url
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
def call(self, payload):
response = requests.post(
self.endpoint_url,
headers=self.headers,
json=payload,
timeout=(5, 120),
)
response.raise_for_status()
return response.json()
llm_client = LLMClient(api_key, endpoint_url)
普通调用
model_name = 'DeepSeek-V4-Flash-0731'
payload = {
'model': model_name,
'messages': [
{'role': 'system', 'content': '你的任务是一句话解释一个概念'},
{'role': 'user', 'content': '解释 yolo'}
]
}
resp = llm_client.call(payload)
print(resp)
print(resp['choices'][0]['message'])
print(resp['choices'][0]['message']['content'])
# 其它可能有用的信息:
# resp.choices[0]['message']['role']
# resp.choices[0]['message']['reasoning_content']
# resp.choices[0]['message']['function_call']
# resp.choices[0]['message']['tool_calls']
多模态
model_name = 'Qwen3-VL-235B-A22B-Instruct'
import base64
def b64_image(path):
with open(path, "rb") as f:
return base64.b64encode(f.read()).decode("ascii")
payload = {
'model': model_name,
'messages': [
{'role': 'system', 'content': "你是一个看图专家"},
{'role': 'user', 'content': [
{"type": "text", "text": "这张图里有什么?"},
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{b64_image('1.png')}"}},
# {"type": "image_url", "image_url": {"url": "https://xxx/1.png"}},
]}
]
}
resp = call_llm.call(payload)
print(resp)
embedding
# 注意,这里的 endpoint 不同
llm_client = LLMClient(api_key, endpoint_url="https://xxx.xxx.com/v1/embeddings")
model_name = 'Qwen3-Embedding-8B'
payload = {
'model': model_name,
"input": [
"外卖不好吃"
, "送的很快"
, "太油了,太辣了"],
}
resp = llm_client.call(payload)
item = resp['data'][0]
item['index'], item['embedding'] # list<float>
流式输出
import json
import requests
payload = {
"model": "DeepSeek-V3.2",
"messages": [{"role": "user", "content": "写一个Python函数,判断素数。"}],
"stream": True,
}
with requests.post(
base_url,
headers={"Authorization": f"Bearer {api_key}"},
json=payload,
stream=True,
timeout=(5, 120),
) as response:
if not response.ok:
raise RuntimeError(f"HTTP {response.status_code}: {response.text}")
for raw_line in response.iter_lines(chunk_size=1):
if not raw_line:
continue
line = raw_line.decode("utf-8")
if not line.startswith("data:"):
continue
data = line[5:].strip()
if data == "[DONE]":
break
chunk = json.loads(data)
choices = chunk.get("choices") or []
if choices:
content = (choices[0].get("delta") or {}).get("content")
if content:
print(content, end="", flush=True)
print()
一些有用的参数
# 概率相关:
"top_p": 0.2,
"temperature": 0.1,
"frequency_penalty": 0,
"presence_penalty": 0,
# 最大输出 token:
"max_tokens": 4096,
# 流式输出
"stream": false,
# 开启/关闭思考
"chat_template_kwargs": {"enable_thinking": False},
输出限制 JSON
# 输出格式限制为 json:
"response_format": {
"type": "json_object"
}
# 如果想要更多的 json 格式限制,可以这样:
payload["response_format"] = {
"type": "json_schema",
"json_schema": {
"name": "concept_explanation",
"strict": True,
"schema": {
"type": "object",
"properties": {
"概念名": {"type": "string", "description": "需要解释的概念名称"},
"解释": {"type": "string", "description": "简明解释,不超过15字"},
"归类": {"type": "string", "description": "该概念所属的知识领域"},
"难度": {"type": "string", "enum": ["入门", "基础", "中等", "进阶"], "description": "学习该概念的难度"}
},
"required": ["概念名", "解释", "归类", "难度"],
"additionalProperties": False
}
}
}
# 注意
# 1. description 也会起作用(大部分模型),与提示词的作用差不多
# 2. 不一定对所有模型都兼容,使用前注意测试
tools 的例子
import json
def get_weather(city):
# 演示数据,不代表实时天气
weather = {
"北京": {"condition": "小雨", "temperature_c": 18},
"上海": {"condition": "晴", "temperature_c": 26},
}
return weather.get(city, {"error": "暂无该城市的天气数据"})
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的天气和气温",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"}
},
"required": ["city"],
},
},
}]
messages = [
{"role": "user", "content": "查一下北京的天气,并给我一条穿衣建议。"}
]
for _ in range(3):
resp = llm_client.call({
"model": "DeepSeek-V3.2",
"messages": messages,
"tools": tools,
"tool_choice": "auto",
})
message = resp["choices"][0]["message"]
tool_calls = message.get("tool_calls") or []
if not tool_calls:
print(message["content"])
break
messages.append(message)
for tool_call in tool_calls:
function = tool_call["function"]
if function["name"] != "get_weather":
raise ValueError(f"未知工具:{function['name']}")
arguments = json.loads(function["arguments"])
result = get_weather(arguments["city"])
messages.append({
"role": "tool",
"tool_call_id": tool_call["id"],
"content": json.dumps(result, ensure_ascii=False),
})
else:
raise RuntimeError("工具调用次数过多")
Agent
Agent 是包含了 RAG、提示词、Function calling、Re-Act等一系列元素的集合
- API 调用,例如查询天气、发送邮件
- Re-Act
自主Agent
- 由 Planner 模块(也是个LLM),与其它 LLM、工具调用的配合
Agent 优化
- GEPA (Genetic-Pareto)
- 边界内收敛到最优
- 优化 prompt
- Auto Research
- 开放的边界,探索高价值改动方向
- 优化整个工作流
- Agentic RL (Agentic Reinforcement Learning)
- 根据完整轨迹,对模型做后训练
context 构建
Context 包括什么
- System Prompt
- 定义角色、能力、行为约束
- User Goal
- 用户的原始目标
- Task State
- 目前的执行状态
- Conversation History
- 历史对话,它是无限增长的,因此需要 压缩(Summarization)
- Memory:长期应该知道什么
- Profile Memory,用户画像、偏好等
- Episodic Memory,历史事件。之前解决的问题、踩过的坑
- Semantic Memory,最佳实践、python 包
- Retrieved Knowledge
- RAG 得到的信息,例如从1000个文件中检索到的 2个相关文件
- Tool Description
- 有哪些工具可供调用
- Tool Results
- 工具返回结果
- Previous Reasoning
- 上一步的推理状态
一个最小完整的 agent 例子
这一步这与前面一模一样
api_key = "xxx" # 同上的密钥管理
base_url="https://xxx.xxx.com/v1/chat/completions" # 注意结尾是 /v1/chat/completions
import requests
class LLMClient:
def __init__(self, api_key, endpoint_url):
self.endpoint_url = endpoint_url
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
def call(self, payload):
response = requests.post(
self.endpoint_url,
headers=self.headers,
json=payload,
timeout=(5, 120),
)
response.raise_for_status()
return response.json()
call_llm = LLMClient(api_key, base_url)
定义大模型可以调用的工具:
tools = [
# shell 工具,LLM 根据通用知识确定如何写 shell 命令,而不是提供大量的、地球人都知道的 Linux 命令
{
"type": "function",
"function": {
"name": "terminal",
"description": """
Execute a shell command in the local environment.
The model should generate appropriate shell commands
based on its existing knowledge of Linux CLI tools.
""",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "Shell command to execute"
}
},
"required": [
"command"
]
}
}
}
# 自定义 python 函数,明确告诉 LLM 这个函数如何使用
, {
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的天气和气温",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称"}
},
"required": ["city"],
},
},
}
]
import subprocess
import json
def terminal(command):
"""执行 shell 命令,
没有做安全过滤,请不要让 agent 执行危险动作"""
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True
)
return result.stdout + result.stderr
def get_weather(city):
"""模拟天气 API"""
return f"{city} 今天晴,温度 25℃"
def tool_routine(tool_call):
"""工具执行路由,agent 只调用此函数,由此函数配置具体的工具"""
name = tool_call["function"]["name"]
arguments = json.loads(
tool_call["function"]["arguments"]
)
if name == "terminal":
result = terminal(**arguments)
elif name == "get_weather":
result = get_weather(**arguments)
else:
result = f"Unknown tool: {name}"
print(f"准备调用工具{name}, 其入参为 {arguments}")
return result
agent:
model_name = 'DeepSeek-V4.1-Flash'
def agent(user_input, max_steps=20):
# max_steps 防止无限调用
# 首次调用 LLM 的 payload(中的 messages):
messages = [
{"role": "system", "content": "You are an intelligent assistant. Use tools when necessary."},
{"role": "user", "content": user_input}
]
for _ in range(max_steps):
payload = {
"model": model_name,
"messages": messages,
# 告诉 LLM 有哪些工具可以调用:
"tools": tools,
"tool_choice": "auto"
}
resp = call_llm.call(payload)
message = resp["choices"][0]["message"]
# 模型的回复添加到 Context
# 对于生产级别的 agent,这里还需要 Context 的压缩等
messages.append(message)
# 任务完成条件:没有 tool_calls,说明模型认为任务已经完成
if not message.get("tool_calls"):
return message["content"]
# 执行工具
for tool_call in message["tool_calls"]:
result = tool_routine(tool_call)
# 4. 将工具结果加入 Context
messages.append({
"role": "tool",
"tool_call_id": tool_call["id"],
"content": result
})
return "Agent exceeded max_steps."
调用 agent:
answer = agent("本地文件有什么?")
answer = agent("北京天气怎么样,适合旅游吗?")
# 这个会触发多轮 工具/LLM 调用:
answer = agent("先查询所有的本地文件,然后新建一个 txt 文件,把本地文件和其摘要放进去")
您的支持将鼓励我继续创作!