1. LLM Agent的核心架构解析
在人工智能领域,大型语言模型(LLM)已经展现出惊人的文本生成和理解能力。然而,传统LLM存在明显的局限性——它们缺乏记忆能力、无法主动使用工具,也难以进行复杂任务的规划。这正是LLM Agent技术诞生的背景。LLM Agent通过三大核心模块的协同工作,实现了比基础LLM更强大的自主性和实用性。
1.1 从LLM到LLM Agent的演进
传统LLM的工作原理是基于概率预测下一个词元(token)。这种机制虽然能生成连贯的文本,但存在两个根本性缺陷:
- 无记忆性:模型无法记住之前的对话内容,每次交互都是独立的
- 能力局限:在数学运算等需要精确计算的场景中表现不佳
python复制# 传统LLM的简单示例
prompt = "5乘以3等于多少?"
response = llm.generate(prompt) # 可能得到错误答案如"16"
为解决这些问题,研究者提出了"增强型LLM"(Augmented LLM)的概念。这种增强主要体现在:
- 工具调用:识别需要使用计算器的场景,自动调用外部工具
- 记忆机制:保存对话历史和中间结果
- 规划能力:将复杂任务分解为可执行的步骤
当这些能力被整合到一个统一的框架中时,就形成了真正意义上的LLM Agent。根据Russell和Norvig在《AI: A Modern Approach》中的定义,智能体应具备:
- 感知环境的能力(传感器)
- 对环境产生影响的能力(执行器)
- 基于感知做出决策的能力(效应器)
LLM Agent通过文本输入实现感知,通过工具调用实现执行,通过LLM本身的推理能力实现决策,完全符合这一定义。
1.2 LLM Agent的三大支柱
一个完整的LLM Agent架构建立在三个核心模块上:
| 模块 | 功能 | 关键技术 |
|---|---|---|
| 记忆 | 保存和检索信息 | 向量数据库、RAG |
| 工具 | 扩展模型能力 | 函数调用、API集成 |
| 规划 | 任务分解和决策 | ReAct、Reflexion |
这三大模块相互配合,使得LLM Agent能够:
- 记住长期对话历史和用户偏好
- 使用计算器、搜索引擎等外部工具
- 制定多步骤计划完成复杂任务
在接下来的章节中,我们将深入探讨每个模块的实现原理和最佳实践。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 记忆系统:从短期缓存到长期知识库
记忆是LLM Agent区别于传统LLM的最显著特征。一个设计良好的记忆系统应该同时包含短期记忆和长期记忆机制,以支持不同时间跨度的信息存储和检索。
2.1 短期记忆的实现方案
短期记忆(工作记忆)负责保存当前的对话上下文和最近的操作记录。实现短期记忆主要有两种方法:
2.1.1 上下文窗口利用
现代LLM通常具有较大的上下文窗口(8k-128k token),可以直接将对话历史包含在提示中:
python复制# 利用上下文窗口实现短期记忆
conversation_history = [] # 保存对话历史
def chat_with_agent(user_input):
conversation_history.append(f"用户: {user_input}")
prompt = "\n".join(conversation_history[-10:]) # 保留最近10轮对话
response = llm.generate(prompt)
conversation_history.append(f"Agent: {response}")
return response
这种方法简单直接,但存在三个限制:
- 上下文长度有限
- 随着对话轮数增加,计算成本上升
- 模型可能对早期信息关注度下降
2.1.2 动态摘要压缩
对于长对话场景,可以使用另一个LLM来定期生成对话摘要:
python复制def summarize_conversation(history):
summary_prompt = f"""
请将以下对话内容压缩为简洁的摘要,保留关键信息:
{history}
"""
return llm.generate(summary_prompt)
# 每5轮对话生成一次摘要
if len(conversation_history) % 5 == 0:
current_summary = summarize_conversation(conversation_history)
conversation_history = [current_summary] # 用摘要替换详细历史
这种方法能有效控制token消耗,但需要注意:
- 摘要可能丢失细节信息
- 摘要质量依赖摘要模型的性能
- 需要合理设置摘要频率
2.2 长期记忆的架构设计
长期记忆使LLM Agent能够跨会话保存和检索信息。典型的实现方式是结合向量数据库和检索增强生成(RAG)技术。
2.2.1 向量数据库集成
python复制from sentence_transformers import SentenceTransformer
from qdrant_client import QdrantClient
# 初始化嵌入模型和向量数据库
embedder = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
client = QdrantClient(":memory:") # 使用内存数据库
def store_memory(text):
embedding = embedder.encode(text)
client.upsert(
collection_name="memories",
points=[{
"id": hash(text),
"vector": embedding.tolist(),
"payload": {"text": text}
}]
)
def retrieve_memories(query, top_k=3):
query_embedding = embedder.encode(query)
results = client.search(
collection_name="memories",
query_vector=query_embedding,
top=top_k
)
return [hit.payload["text"] for hit in results]
2.2.2 记忆分类体系
根据认知科学理论,LLM Agent的记忆可以分为四类:
- 工作记忆:当前任务的上下文缓存
- 程序性记忆:工具使用方法和问题解决策略
- 语义记忆:事实性知识和概念理解
- 情景记忆:具体的交互经历和用户偏好
mermaid复制graph TD
A[记忆系统] --> B[工作记忆]
A --> C[长期记忆]
C --> D[程序性记忆]
C --> E[语义记忆]
C --> F[情景记忆]
实际应用中,可以为每类记忆设计独立的存储和检索策略:
- 工作记忆:使用上下文窗口或Redis缓存
- 程序性记忆:存储在结构化文档中
- 语义记忆:使用知识图谱或向量数据库
- 情景记忆:时间序列数据库+向量检索
实践经验:记忆系统的设计应遵循"分层存储,按需检索"原则。高频访问的信息放在快速存储中,低频信息可以存在较慢但容量大的存储里。同时要注意设置记忆的过期机制,避免存储过时或错误的信息。
3. 工具调用:扩展LLM的能力边界
工具调用是LLM Agent与外部世界交互的关键途径。通过工具,LLM可以突破纯文本处理的限制,执行计算、查询、操作等实际任务。
3.1 工具调用的实现模式
3.1.1 函数调用(Function Calling)
主流LLM API都支持函数调用功能。以下是一个完整示例:
python复制import json
from math import sqrt
# 定义工具集
tools = [
{
"name": "calculate",
"description": "执行数学计算",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "数学表达式,如'3 + 5'或'sqrt(16)'"
}
},
"required": ["expression"]
}
}
]
# 工具实现
def use_tool(tool_name, parameters):
if tool_name == "calculate":
try:
return eval(parameters["expression"])
except:
return "计算错误"
return "未知工具"
# 与LLM交互
def chat_with_tools(user_input):
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": user_input}],
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
if hasattr(message, "tool_calls"):
tool_call = message.tool_calls[0]
result = use_tool(tool_call.function.name, json.loads(tool_call.function.arguments))
return result
else:
return message.content
3.1.2 自主工具调用模式
更高级的LLM Agent可以采用自主决策模式,动态决定工具使用顺序。这种模式通常需要以下组件:
- 工具注册表:记录所有可用工具的描述和调用方式
- 工具选择器:基于当前上下文选择最合适的工具
- 执行引擎:实际调用工具并处理结果
python复制class AutonomousAgent:
def __init__(self):
self.tools = {} # 工具注册表
self.memory = [] # 对话记忆
def register_tool(self, name, description, func):
self.tools[name] = {
"description": description,
"function": func
}
def select_tool(self, query):
# 使用LLM选择最合适的工具
prompt = f"""
根据用户请求选择最合适的工具。可用工具:
{json.dumps([{"name":k, "desc":v["description"]} for k,v in self.tools.items()])}
用户请求:{query}
返回工具名称和调用参数,如:{"tool": "calculator", "args": "3+4"}
"""
selection = llm.generate(prompt)
return json.loads(selection)
def execute(self, user_input):
self.memory.append(user_input)
tool_info = self.select_tool(user_input)
if tool_info["tool"] in self.tools:
result = self.tools[tool_info["tool"]]["function"](tool_info["args"])
self.memory.append(result)
return result
return "无法处理该请求"
3.2 工具学习的高级技术
3.2.1 Toolformer训练方法
Toolformer是一种通过微调让LLM学会自主调用工具的技术。其核心步骤包括:
- 数据收集:构建工具使用示例数据集
- 标注训练:在输入输出中插入特殊标记表示工具调用
- 模型微调:训练模型预测工具调用位置和参数
训练后的模型输出会包含类似以下结构的工具调用:
code复制[calculator→5*3→]15
3.2.2 模型上下文协议(MCP)
MCP是Anthropic提出的工具集成标准,主要组件包括:
- MCP主机:用户直接交互的应用
- MCP客户端:连接主机和服务器的桥梁
- MCP服务器:提供工具服务的后端
mermaid复制sequenceDiagram
participant User
participant MCP_Host
participant MCP_Client
participant MCP_Server
User->>MCP_Host: 请求GitHub提交记录
MCP_Host->>MCP_Client: 查询可用工具
MCP_Client->>MCP_Server: 获取工具列表
MCP_Server-->>MCP_Client: 返回工具信息
MCP_Client-->>MCP_Host: 返回工具列表
MCP_Host->>LLM: 决定使用GitHub工具
LLM-->>MCP_Host: 工具选择结果
MCP_Host->>MCP_Client: 调用GitHub工具
MCP_Client->>MCP_Server: 执行API调用
MCP_Server-->>MCP_Client: 返回提交记录
MCP_Client-->>MCP_Host: 返回结果
MCP_Host->>User: 显示提交记录
工具使用经验:在实际应用中,工具描述的质量直接影响LLM的选择准确性。好的工具描述应包含:1) 工具功能 2) 适用场景 3) 输入输出示例。同时建议为每个工具提供3-5个典型用例,帮助LLM更好地理解何时使用该工具。
4. 规划能力:从单步响应到多步推理
规划能力是LLM Agent处理复杂任务的核心。通过有效的规划,Agent可以将一个高层目标分解为可执行的动作序列,并在执行过程中动态调整策略。
4.1 推理能力的培养方法
4.1.1 链式思维(Chain-of-Thought)
链式思维通过展示推理步骤来引导模型:
code复制问题:如果食堂有3个苹果,买了5个,吃了2个,还剩几个?
思考过程:
1. 最初有3个苹果
2. 买了5个,现在有3 + 5 = 8个
3. 吃了2个,剩下8 - 2 = 6个
答案:6
在提示中明确要求分步思考可以显著提升模型表现:
python复制prompt = """
请逐步思考并回答以下问题:
问题:{question}
让我们一步步思考:
"""
4.1.2 自洽性采样(Self-Consistency)
通过多次采样并投票选择最一致的答案:
python复制def self_consistent_answer(question, samples=5):
answers = []
for _ in range(samples):
response = llm.generate(f"{question}\n让我们一步步思考:")
final_answer = extract_answer(response) # 从响应中提取最终答案
answers.append(final_answer)
return max(set(answers), key=answers.count)
4.2 规划执行框架
4.2.1 ReAct框架
ReAct(Reason + Act)结合了推理和行动:
code复制问题:现任英国首相是谁?
思考:我需要查找现任英国首相的信息
行动:使用搜索引擎查询"现任英国首相"
观察:搜索结果:Rishi Sunak
思考:根据最新信息,现任英国首相是Rishi Sunak
答案:现任英国首相是Rishi Sunak
Python实现示例:
python复制def react_cycle(initial_question, max_steps=5):
history = []
current_state = initial_question
for _ in range(max_steps):
# 思考阶段
thought = llm.generate(f"""
当前状态:{current_state}
对话历史:{history}
请思考下一步应该做什么?
""")
# 行动阶段
action = llm.generate(f"""
根据思考:{thought}
生成一个行动命令,格式为"行动:<动作类型> <参数>"
""")
if "行动:结束" in action:
return llm.generate(f"""
根据以下信息回答问题:{initial_question}
历史记录:{history}
""")
# 执行行动并观察结果
observation = execute_action(action)
history.append(f"{thought}\n{action}\n观察:{observation}")
current_state = observation
return "达到最大步数仍未解决"
4.2.2 Reflexion框架
Reflexion在ReAct基础上增加了自我反思:
python复制def reflexion_cycle(question, max_episodes=3):
best_answer = None
best_score = -1
for episode in range(max_episodes):
# 执行阶段
answer, history = execute_episode(question)
# 评估阶段
score = evaluator.evaluate(question, answer)
# 反思阶段
reflection = llm.generate(f"""
问题:{question}
尝试的解决方案:{history}
得分:{score}/10
请分析可以改进的地方:
""")
# 更新最佳答案
if score > best_score:
best_score = score
best_answer = answer
# 将反思加入记忆
memory.add(reflection)
return best_answer
4.3 规划优化技术
4.3.1 思维树(Tree of Thought)
通过树形结构探索多种推理路径:
python复制class TreeNode:
def __init__(self, state, parent=None):
self.state = state # 当前状态描述
self.parent = parent
self.children = []
self.value = 0 # 节点评估值
def tree_of_thought(initial_question, breadth=3, depth=3):
root = TreeNode(initial_question)
# 广度优先扩展
for _ in range(depth):
current_level = get_leaves(root)
for node in current_level:
for _ in range(breadth):
new_state = llm.generate(f"""
当前状态:{node.state}
请提出一个可能的下一步思考或行动:
""")
child = TreeNode(new_state, parent=node)
node.children.append(child)
# 评估路径
best_path = evaluate_paths(root)
return construct_answer(best_path)
4.3.2 算法蒸馏(Algorithm Distillation)
通过训练使LLM内化规划算法:
- 在多个任务上运行规划算法(如ReAct)
- 记录输入输出轨迹
- 用这些轨迹微调LLM
- 微调后的模型可以直接输出规划步骤
规划实践建议:对于复杂任务,建议结合多种规划技术。例如先用思维树探索可能路径,再用ReAct执行具体步骤,期间定期使用Reflexion进行反思调整。同时要注意设置合理的超时和最大步数限制,避免陷入无限循环。
5. 多智能体系统:协作解决复杂问题
当单个LLM Agent能力有限时,可以构建多智能体系统,通过分工协作处理更复杂的任务。多智能体系统通常由多个专业Agent和一个协调者组成,每个Agent专注于特定领域。
5.1 多智能体架构设计
5.1.1 角色定义
典型的多智能体系统包含以下角色:
- 协调者Agent:任务分解和结果整合
- 研究Agent:信息检索和验证
- 编程Agent:代码生成和执行
- 审查Agent:质量检查和错误发现
python复制class MultiAgentSystem:
def __init__(self):
self.agents = {
"coordinator": CoordinatorAgent(),
"researcher": ResearchAgent(),
"programmer": ProgrammingAgent(),
"reviewer": ReviewAgent()
}
def solve_problem(self, problem):
# 协调者分解任务
subtasks = self.agents["coordinator"].decompose(problem)
results = []
for task in subtasks:
# 分配给最适合的Agent
agent_type = self.agents["coordinator"].assign_agent(task)
result = self.agents[agent_type].process(task)
# 结果审查
reviewed_result = self.agents["reviewer"].review(result)
results.append(reviewed_result)
# 整合最终答案
return self.agents["coordinator"].integrate(results)
5.1.2 通信机制
Agent间通信可以采用以下模式:
- 黑板模式:共享工作区存储中间结果
- 消息传递:直接Agent-to-Agent通信
- 发布订阅:事件驱动架构
mermaid复制graph LR
A[协调者] -->|分配任务| B[研究Agent]
A -->|分配任务| C[编程Agent]
B -->|提交结果| D[黑板]
C -->|提交结果| D
D --> E[审查Agent]
E -->|反馈| B
E -->|反馈| C
E -->|最终结果| A
5.2 典型多智能体框架
5.2.1 CAMEL框架
CAMEL采用角色扮演模式,两个Agent分别扮演"AI用户"和"AI助手"进行对话:
code复制AI用户:我需要分析某公司近三年的财务数据
AI助手:我可以帮您获取和分析数据。您有具体公司名称吗?
AI用户:是Apple公司
AI助手:好的,我将先获取Apple公司2020-2022的财务报表
[使用工具查询财务数据...]
AI助手:已获取数据,接下来您想分析哪些指标?
AI用户:请计算每年的营收增长率和利润率
[执行计算...]
5.2.2 AutoGen框架
AutoGen支持自定义Agent工作流:
python复制from autogen import AssistantAgent, UserProxyAgent, GroupChat
# 创建Agent
assistant = AssistantAgent("assistant")
user_proxy = UserProxyAgent("user_proxy")
reviewer = AssistantAgent("reviewer")
# 定义群组聊天
groupchat = GroupChat(
agents=[user_proxy, assistant, reviewer],
messages=[],
max_round=10
)
# 启动对话
user_proxy.initiate_chat(
groupchat,
message="帮我开发一个Python脚本,分析CSV数据并生成可视化报告"
)
5.3 多智能体系统优化
5.3.1 角色专业化
通过微调或提示工程使每个Agent高度专业化:
python复制# 专业研究Agent提示
research_agent_prompt = """
你是一个专业研究Agent,擅长:
- 精确的信息检索
- 事实核查
- 多来源信息对比
请严格按照以下步骤工作:
1. 明确研究问题
2. 设计搜索策略
3. 评估信息来源可靠性
4. 提取关键信息
5. 标注信息来源
当前任务:{task}
"""
# 专业编程Agent提示
programming_agent_prompt = """
你是一个资深Python开发Agent,遵循:
1. 先分析需求
2. 设计函数接口
3. 实现核心逻辑
4. 添加错误处理
5. 编写单元测试
任务:{task}
代码实现:
"""
5.3.2 冲突解决机制
当Agent间出现分歧时,可以采用:
- 投票机制:多个Agent投票决定
- 权威裁决:由特定Agent(如协调者)最终决定
- 证据辩论:Agent提供支持证据进行辩论
python复制def resolve_conflict(opinions):
if len(set(opinions)) == 1:
return opinions[0]
# 收集支持证据
evidences = []
for agent, opinion in opinions.items():
evidence = agent.provide_evidence(opinion)
evidences.append((opinion, evidence))
# 由协调者裁决
return coordinator_agent.decide(evidences)
多Agent开发经验:在实际应用中,要注意控制Agent数量——太少无法体现分工优势,太多会增加协调成本。通常3-5个专业Agent加1个协调者的组合比较理想。同时要确保每个Agent有清晰的责任边界,避免功能重叠导致的冲突。
