AI Agent 进阶:添加记忆和多工具协作

0 阅读10分钟

上一篇我们搭建了基础的 AI Agent,这篇文章将带你进阶:让 Agent 拥有记忆,支持多工具协作,变得更加智能。

🎯 你将学到什么

  • 如何给 Agent 添加短期和长期记忆
  • 如何实现多工具协作
  • 如何处理复杂的多步骤任务
  • 如何优化 Agent 的决策能力
  • 实战案例:智能项目管理助手

前置知识: 需要先阅读第 1 篇基础教程


一、为什么需要记忆?

1.1 没有记忆的 Agent

# 第一次对话
用户: "帮我查看今天的邮件"
Agent: "好的,你有 3 封邮件..."

# 第二次对话
用户: "帮我回复第一封"
Agent: "抱歉,我不知道你说的是哪封邮件"

问题: Agent 不记得之前的对话,每次都是全新开始。

1.2 有记忆的 Agent

# 第一次对话
用户: "帮我查看今天的邮件"
Agent: "好的,你有 3 封邮件..."
[记忆:用户查看了邮件列表]

# 第二次对话
用户: "帮我回复第一封"
Agent: "好的,我记得第一封是关于项目进度的..." ✅
[记忆:用户要回复第一封邮件]

优势: Agent 能记住上下文,支持连续对话。


二、记忆系统设计

2.1 记忆类型

记忆类型存储时长用途实现方式
短期记忆当前会话上下文理解ConversationBufferMemory
工作记忆最近 N 轮任务执行ConversationBufferWindowMemory
长期记忆永久知识积累VectorStore + Embeddings
实体记忆永久人物/事件EntityMemory

2.2 记忆架构

┌─────────────────────────────────────┐
│         用户输入                     │
└──────────────┬──────────────────────┘
               │
               ▼
┌─────────────────────────────────────┐
│      短期记忆(当前对话)              │
│  - 最近 5 轮对话                      │
│  - 快速访问                           │
└──────────────┬──────────────────────┘
               │
               ▼
┌─────────────────────────────────────┐
│      工作记忆(任务上下文)            │
│  - 当前任务相关信息                   │
│  - 中等容量                           │
└──────────────┬──────────────────────┘
               │
               ▼
┌─────────────────────────────────────┐
│      长期记忆(知识库)                │
│  - 向量数据库                         │
│  - 语义检索                           │
└─────────────────────────────────────┘

三、实现短期记忆

3.1 基础对话记忆

from langchain.memory import ConversationBufferMemory
from langchain_openai import ChatOpenAI
from langchain.chains import ConversationChain

# 创建记忆
memory = ConversationBufferMemory()

# 创建对话链
llm = ChatOpenAI(model="gpt-4-turbo-preview")
conversation = ConversationChain(
    llm=llm,
    memory=memory,
    verbose=True
)

# 对话示例
print(conversation.predict(input="我叫张三"))
# 输出: "你好张三!很高兴认识你。"

print(conversation.predict(input="我叫什么名字?"))
# 输出: "你叫张三。"

3.2 滑动窗口记忆

from langchain.memory import ConversationBufferWindowMemory

# 只保留最近 5 轮对话
memory = ConversationBufferWindowMemory(k=5)

conversation = ConversationChain(
    llm=llm,
    memory=memory
)

# 超过 5 轮后,旧的对话会被自动丢弃

3.3 摘要记忆

from langchain.memory import ConversationSummaryMemory

# 自动总结历史对话
memory = ConversationSummaryMemory(llm=llm)

conversation = ConversationChain(
    llm=llm,
    memory=memory
)

# Agent 会自动总结之前的对话,节省 token

四、实现长期记忆

4.1 向量数据库

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter

class LongTermMemory:
    def __init__(self, persist_directory="./memory_db"):
        self.embeddings = OpenAIEmbeddings()
        self.vectorstore = Chroma(
            embedding_function=self.embeddings,
            persist_directory=persist_directory
        )
        self.text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=1000,
            chunk_overlap=200
        )
    
    def remember(self, content: str, metadata: dict = None):
        """保存到长期记忆"""
        chunks = self.text_splitter.split_text(content)
        self.vectorstore.add_texts(
            texts=chunks,
            metadatas=[metadata] * len(chunks) if metadata else None
        )
        self.vectorstore.persist()
    
    def recall(self, query: str, k: int = 3):
        """从长期记忆中检索"""
        docs = self.vectorstore.similarity_search(query, k=k)
        return [doc.page_content for doc in docs]
    
    def forget(self, query: str):
        """删除相关记忆"""
        # Chroma 不直接支持删除,需要重建索引
        pass

4.2 实体记忆

from langchain.memory import ConversationEntityMemory

# 自动提取和记住实体(人名、地名、事件)
entity_memory = ConversationEntityMemory(llm=llm)

conversation = ConversationChain(
    llm=llm,
    memory=entity_memory
)

# 示例
conversation.predict(input="我的老板叫李四,他很严格")
# Agent 会记住:李四 = 老板,性格严格

conversation.predict(input="李四怎么样?")
# Agent 会回忆:李四是你的老板,性格严格

五、多工具协作

5.1 工具定义

from langchain.tools import tool
from typing import List, Dict
import json

@tool
def search_emails(keywords: str, folder: str = "inbox") -> List[Dict]:
    """
    搜索邮件
    
    Args:
        keywords: 搜索关键词
        folder: 邮箱文件夹
    
    Returns:
        匹配的邮件列表
    """
    # 模拟搜索
    return [
        {"id": "001", "subject": f"包含 {keywords} 的邮件"}
    ]

@tool
def read_calendar(date: str) -> List[Dict]:
    """
    读取日历
    
    Args:
        date: 日期(YYYY-MM-DD)
    
    Returns:
        当天的日程列表
    """
    return [
        {"time": "10:00", "event": "团队会议"},
        {"time": "14:00", "event": "客户演示n
@tool
def create_task(title: str, description: str, deadline: str) -> str:
    """
    创建任务
    
    Args:
        title: 任务标题
        description: 任务描述
        deadline: 截止日期
    
    Returns:
        任务 ID
    """
    task_id = "TASK-001"
    print(f"✅ 任务已创建: {title}")
    return task_id

@tool
def search_documents(query: str, doc_type: str = "all") -> List[Dict]:
    """
    搜索文档
    
    Args:
        query: 搜索关键词
        doc_type: 文档类型(pdf, docx, all)
    
    Returns:
        匹配的文档列表
    """
    return [
        {"name": 案.pdf", "path": "/docs/project.pdf"}
    ]

# 工具列表
tools = [
    search_emails,
    read_calendar,
    create_task,
    search_documents
]

5.2 工具协作示例

from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder

# 定义 Prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", """你是一个智能项目管理助手。

你可以:
1. 搜索邮件(search_emails)
2. 查看日历(read_calendar)
3. 创建任务(create_task)
4. 搜索文档(search_documents)

工作流程:
1. 理解用户需求
2. 选择合适的工具
3. 按顺序执行多个工具
4. 整合结果反馈给用户

示例:
用户: "帮我n你应该:
1. 调用 read_calendar 查看今天的日程
2. 调用 search_emails 查看今天的邮件
3. 整合信息,给出今日工作清单
"""),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"),
])

# 创建 Agent
llm = ChatOpenAI(model="gpt-4-turbo-preview", temperature=0)
agent = create_openai_functions_agent(llm=llm, tools=tools, prompt=prompt)

# 创建 Executor
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,
    max_iterations=10
)

# 测试
result = agent_executor.invoke({
    "input": "帮我整理今天的工作,并创建一个任务提醒我下午的会议"
})

执行过程:

> Entering new AgentExecutor chain...

Invoking: `recalendar` with `{'date': '2026-02-22'}`

[{'time': '10:00', 'event': '团队会议'}, {'time': '14:00', 'event': '客户演示'}]

Invoking: `search_emails` with `{'keywords': '今天', 'folder': 'inbox'}`

[{'id': '001', 'subject': '包含 今天 的邮件'}]

Invoking: `create_task` with `{'title': '下午客户演示提醒', 'description': '14:00 客户演示', 'deadline': '2026-02-22 13:30'}`

✅ 任务已创建: 下午客户演示提醒

今天的工作安排:

📅 日程:
- 10:00 团队会议
- 14:00 客户演示

📧 邮件:
- 1 封待处理邮件

✅ 已创建任务提醒:下午客户演示(13:30 提醒)

六、复杂任务处理

6.1 任务分解

from langchain.chains import LLMChainfrom langchain.prompts import PromptTemplate

class TaskDecom:
    def __init__(self, llm):
        self.llm = llm
        self.prompt = PromptTemplate(
            input_variables=["task"],
            template="""将以下任务分解为具体的步骤:

任务:{task}

请按照以下格式输出:
1. [步骤1]
2. [步骤2]
3. [步骤3]
...

每个步骤应该:
- 具体可执行
- 有明确的输入输出
- 按逻辑顺序排列
"""
        )
        self.chain = LLMChain(llm=self.llm, prompt=self.prompt)
    
    def decompose(self, task: str) -> List[str]:
        """分解任务"""
        result = self.chain.run(task=task)
        steps = [line.strip() for line in result.split('\n') if line.strip()]
        return steps

# 使用示例
decomposer = TaskDecomposer(llm)
steps = decomposer.decompose("准备下周的项目演示")

# 输出:
# 1. 查看项目当前进度
# 2. 整理项目成果和数据
# 3. 制作演示 PPT
# 4. 准备演示脚本
# 5. 预演练习

6.2 任务执行器

class TaskExecutor:
    def __init__(self, agent_executor, memory):
        self.agent = agent_executor
        self.memory = memory
    
    def execute_steps(self, steps: List[str]) -> Dict:
        """按步骤执行任务"""
        results = []
        
        for i, step in enumerate(steps, 1):
            print(f"\n📍 执行步骤 {i}/{len(steps)}: {step}")
            
            try:
                result = self.agent.invoke({"input": step})
                results.append({
                    "step": step,
                    "status": "success",
                    "output": result["output"]
                })
                
                # 保存到记忆
                self.memory.remember(
                    f"步骤 {i}: {step}\n结果: {result['output']}",
                    metadata={"type": "task_step", "step_number": i}
                )
                
            except Exception as e:
                results.append({
                    "step": step,
                    "status": "failed",
                    "error": str(e)
                })
                print(f"❌ 步骤失败: {e}")
                break
        
        return {
            "total_steps": len(steps),
            "completed": len([r for r in results if r["status"] == "success"]),
            "results": results
        }

# 使用示例
executor = TaskExecutor(agent_executor, long_term_memory)
results = executor.execute_steps(steps)

七、完整示例:智能项目管理助手

7.1 系统架构

from langchain.memory import ConversationBufferMemory
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain_openai import ChatOpenAI

class ProjectManagementAgent:
    def __init__(self):
        # 初始化 LLM
        self.llm = ChatOpenAI(
            model="gpt-4-turbo-preview",
            temperature=0.7
        )
        
        # 短期记忆
        self.short_term_memory = ConversationBufferMemory(
            memory_key="chat_history",
            return_messages=True
        )
        
        # 长期记忆
        self.long_term_memory = LongTermMemory()
        
        # 任务分解器
        self.task_decomposer = TaskDecomposer(self.llm)
        
        # 创建 Agent
        self.agent = self._create_agent()
        
        # 任务执行器
        self.task_executor = TaskExecutor(
            self.agent,
            self.long_term_memory
        )
    
    def _create_agent(self):
        """创建 Agent"""
        prompt = ChatPromptTemplate.from_messages([
            ("system", """你是一个智能项目管理助手。

核心能力:
1. 任务管理(创建、查询、更新)
2. 日程管理(查看、安排)
3. 邮件处理(搜索、回复)
4. 文档管理(搜索、整理)

工作原则:
- 主动思考,提供建议
- 记住用户的偏好和习惯
- 复杂任务自动分解
- 定期总结和提醒
"""),
            MessagesPlaceholder(variable_name="chat_history"),
            ("human", "{input}"),
            MessagesPlaceholder(variable_name="agent_scratchpad"),
        ])
        
        agent = create_openai_functions_agent(
            llm=self.llm,
            tools=tools,
            prompt=prompt
        )
        
        return AgentExecutor(
            agent=agent,
            tools=tools,
            memory=self.short_term_memory,
            verbose=True
        )
    
    def run(self, user_input: str) -> str:
        """执行用户请求"""
        # 检查是否是复杂任务
        if self._is_complex_task(user_input):
            # 分解任务
            steps = self.task_decomposer.decompose(user_input)
            print(f"\n📋 任务已分解为 {len(steps)} 个步骤")
            
            # 执行任务
            results = self.task_executor.execute_steps(steps)
            
            # 生成总结
            summary = self._generate_summary(results)
            return summary
        else:
            # 直接执行
            result = self.agent.invoke({"input": user_input})
            return result["output"]
    
    def _is_complex_task(self, task: str) -> bool:
        """判断是否是复杂任务"""
        complex_keywords = ["准备", "整理", "完成", "项目", "报告"]
        return any(ked in task for keyword in complex_keywords)
    
    def _generate_summary(self, results: Dict) -> str:
        """生成任务总结"""
        completed = results["completed"]
        total = results["total_steps"]
        
        summary = f"\n✅ 任务完成情况:{completed}/{total}\n\n"
        
        for i, result in enumerate(results["results"], 1):
            status_icon = "✅" if result["status"] == "success" else "❌"
            summary += f"{status_icon} 步骤 {i}: {result['step']}\n"
            
            if result["status"] == "success":
                summary += f"   结果: {result['output'][:100]}...\n"
            else:
                summary += f"   错误: {result['error']}\n"
        
        return summary

7.2 使用示例

# 创建助手
assistant = ProjectManagementAgent()

# 简单任务
print(assistant.run("帮我查看今天的日程"))

# 复杂任务
print(assistant.run("帮我准备下周一的项目汇报"))

# 输出:
# 📋 任务已分解为 5 个步骤
# 
# 📍 执行步骤 1/5: 查看项目当前进度
# ✅ 完成
# 
# 📍 执行步骤 2/5: 整理项目成果和数据
# ✅ 完成
# 
# ...
# 
# ✅ 任务完成情况:5/5

八、性能优化

8.1 记忆压缩

from langchain.memory import ConversationSummaryBufferMemory

# 自动压缩历史对话
memory = ConversationSummaryBufferMemory(
    llm=llm,
    max_token_limit=2000  # 超过 2000 tokens 自动总结
)

8.2 缓存机制

from langchain.cache import InMemoryCache
from langchain.globals import set_llm_cache
import hashlib

# 启用缓存
set_llm_cache(InMemoryCache())

class CachedLongTermMemory(LongTermMemory):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.cache = {}
    
    def recall(self, query: str, k: int = 3):
        """带缓存的检索"""
        cache_key = hashlib.md5(f"{query}_{k}".encode()).hexdigest()
        
        if cache_key in self.cache:
            print("📦 使用缓存")
            return self.cache[cache_key]
        
        results = super().recall(query, k)
        self.cache[cache_key] = results
        return results

8.3 异步处理

import asyncio

class AsyncProjectManagementAgent(ProjectManagementAgent):
    async def arun(self, user_input: str) -> str:
        """异步执行"""
        if self._is_complex_task(user_input):
            steps = self.task_decomposer.decompose(user_input)
            
            # 并行执行独立的步骤
            tasks = [
                self._execute_step_async(step)
                for step in steps
            ]
            
            results = await asyncio.gather(*tasks)
            return self._generate_summary({"results": results})
        else:
            result = await self.agent.ainvoke({"input": user_input})
            return result["output"]
    
    async def _execute_step_async(self, step: str):
        """异步执行单个步骤"""
        try:
            result = await self.agent.ainvoke({"input": step})
            return {
                "step": step,
                "status": "n                "output": result["output"]
            }
        except Exception as e:
            return {
                "step": step,
                "status": "failed",
                "error": str(e)
            }

九、最佳实践

9.1 记忆管理

DO ✅:

  • 定期清理短期记忆
  • 重要信息保存到长期记忆
  • 使用元数据标记记忆类型
  • 实现记忆过期机制

DON'T ❌:

  • 不要无限制保存所有对话
  • 不要在短期记忆中存储敏感信息
  • 不要忽略记忆检索的性能

9.2 工具设计

DO ✅:

  • 工具功能单一明确
  • 提供详细的文档字符串
  • 实现错误处理
  • 返回结构化数据

DON'T ❌:

  • 不要让一个工具做太多事情
  • 不要返回非结构化的文本
  • 不要忽略异常情况

9.3 任务分解

DO ✅:

  • 步骤具体可执行
  • 考虑的依赖
  • 提供失败重试机制
  • 记录执行过程

DON'T ❌:

  • 不要分解得过于细碎
  • 不要忽略步骤之间的关联
  • 不要在失败后继续执行

十、总结

10.1 关键要点

  1. 记忆是 Agent 智能的基础

    • 短期记忆:上下文理解
    • 长期记忆:知识积累
    • 实体记忆:关系管理
  2. 多工具协作提升能力

    • 工具设计要单一职责
    • Agent 自动选择和组合工具
    • 实现工具之间的数据传递
  3. 复杂任务需要分解

    • 自动分解为可执行步骤
    • 按顺序或并行执行
    • 记录和总结执行结果

10.2 下一步

  • 🚀 第 3 篇:生产环境部署 — 如何部署到真实环境
  • 📊 第 4 篇:性能优化和成本控制 — 如何降低成本提高性能

关注我,不错过后续更新! 🚀


如果觉得有帮助,欢迎点赞、收藏、转发! ❤️