在构建生产级 AI Agent 时,记忆系统是决定 Agent 智能程度的核心组件。我在过去一年中为多个大型企业项目设计了 Agent 记忆架构,从日均百万级查询的客服机器人到实时文档分析的智能助手,踩过的坑比代码行数还多。今天这篇文章,我将完整分享向量数据库选型、API 集成架构、性能调优实战经验,以及如何在有限预算下实现企业级的记忆系统。

为什么 AI Agent 需要记忆系统

没有记忆的 Agent 就像只有 5 秒记忆的金鱼——每次交互都是全新的开始。用户问到"上次的方案怎么样了",Agent 只能一脸茫然。记忆系统让 Agent 能够跨对话保持上下文、学习用户偏好、积累业务知识,从而提供真正有价值的个性化服务。

记忆系统在 Agent 架构中的位置至关重要:

向量数据库选型对比

选择向量数据库是记忆系统设计的第一步。市场上主流方案各有优劣,我根据实际项目经验整理了以下对比:

数据库部署方式百万向量延迟元数据过滤月费估算适合场景
Pinecone云托管15-25ms✅ 强大$70+快速上线、免运维
Milvus自建/云10-20ms✅ 强大$50-500大规模数据、定制需求
Qdrant自建/云8-15ms✅ 强大$40-400高性能、实时场景
Weaviate云托管20-35ms✅ 强大$60+混合搜索、多媒体
Chroma本地5-15ms⚠️ 基础免费原型验证、小规模
pgvector自建25-50ms✅ 强大$30-300已有PostgreSQL

我的实战经验是:初期快速验证选 Chroma 或 Qdrant Cloud,生产级大规模部署选 Milvus 或 Qdrant。Pinecone 虽然体验最好,但按量计费模式下月账单很容易超出预期,尤其是向量数量突破千万级时。

记忆系统核心架构设计

一个完整的 Agent 记忆系统包含以下核心模块:

2.1 记忆存储层

记忆存储采用向量数据库 + 结构化数据库的混合架构。向量数据库存储语义嵌入,PostgreSQL/MySQL 存储元数据、关系信息和用户画像。这种分离设计让我在多个项目中的查询性能提升了 3-5 倍。

import hashlib
import json
from datetime import datetime
from typing import List, Dict, Any, Optional
import numpy as np

class MemoryStore:
    """
    Agent 记忆存储核心类
    支持向量存储 + 元数据存储的混合架构
    """
    
    def __init__(
        self,
        vector_store,      # 向量数据库客户端
        metadata_db,       # 结构化数据库连接
        embedding_model    # 嵌入模型
    ):
        self.vector_store = vector_store
        self.metadata_db = metadata_db
        self.embedding_model = embedding_model
        # 记忆分代:避免重复存储相似内容
        self.dedup_window = 0.85  # 余弦相似度阈值
    
    async def store_memory(
        self,
        content: str,
        memory_type: str,  # "short_term", "long_term", "episodic"
        user_id: str,
        metadata: Optional[Dict[str, Any]] = None
    ) -> str:
        """存储单条记忆"""
        
        # 生成内容哈希用于去重
        content_hash = hashlib.sha256(content.encode()).hexdigest()
        
        # 检查是否已存在相似记忆
        existing = await self._check_duplicate(content_hash, user_id)
        if existing:
            return existing["id"]
        
        # 生成向量嵌入
        vector = await self.embedding_model.encode(content)
        
        # 构建记忆对象
        memory_id = f"mem_{user_id}_{datetime.utcnow().timestamp()}"
        memory_data = {
            "id": memory_id,
            "content": content,
            "content_hash": content_hash,
            "vector": vector.tolist(),
            "memory_type": memory_type,
            "user_id": user_id,
            "created_at": datetime.utcnow().isoformat(),
            "access_count": 0,
            "importance_score": self._calculate_importance(content),
            **(metadata or {})
        }
        
        # 双写:向量库 + 关系库
        await self.vector_store.insert(memory_data)
        await self.metadata_db.insert("memories", memory_data)
        
        # 触发记忆压缩检查
        if memory_type == "short_term":
            await self._check_consolidation(user_id)
        
        return memory_id
    
    def _calculate_importance(self, content: str) -> float:
        """
        基于规则的重要性评分
        实战中建议接入 LLM 做意图识别
        """
        score = 0.5
        keywords_high = ["紧急", "重要", "deadline", "必须", "取消", "投诉"]
        keywords_mid = ["记得", "偏好", "习惯", "喜欢", "不喜欢"]
        
        for kw in keywords_high:
            if kw in content:
                score += 0.2
        for kw in keywords_mid:
            if kw in content:
                score += 0.1
        
        return min(score, 1.0)
    
    async def retrieve_memories(
        self,
        query: str,
        user_id: str,
        memory_types: List[str] = ["short_term", "long_term"],
        top_k: int = 10,
        recency_weight: float = 0.3
    ) -> List[Dict[str, Any]]:
        """检索相关记忆,支持多类型组合"""
        
        # 向量相似度检索
        query_vector = await self.embedding_model.encode(query)
        
        results = await self.vector_store.search(
            vector=query_vector,
            filter={
                "user_id": user_id,
                "memory_type": {"$in": memory_types}
            },
            top_k=top_k * 2  # 预留重排空间
        )
        
        # 重排:结合相关性 + 时效性 + 重要性
        reranked = self._rerank_results(
            results,
            recency_weight=recency_weight
        )
        
        # 更新访问统计
        await