向量数据库选型指南:Milvus、Qdrant、Weaviate深度对比

向量数据库:RAG时代的基石 所有RAG系统都需要向量数据库。2026年市场已经从"有没有"过渡到"哪个好"——选型不当会带来性能瓶颈、扩展困难、功能不足等问题。 三大主流方案 Milvus:大规模分布式 架构特点 Milvus采用存算分离架构: Coordinator:元数据管理和调度 Worker Node:查询节点和数据节点分离 对象存储:数据持久化(S3/MinIO) 消息队列:变更数据捕获(Kafka/Pulsar) 核心优势 水平扩展:支持十亿级向量 混合检索:向量+标量过滤 多索引:HNSW、IVF、DiskANN、GPU索引 云原生:K8s原生部署 适用场景 大规模生产环境(亿级向量) 需要高可用和水平扩展 团队有K8s运维能力 注意事项 部署复杂度高(微服务架构) 小规模场景(<100万向量)过重 内存占用较大 Qdrant:高性能轻量级 架构特点 Qdrant用Rust编写,单二进制部署: Collection:数据集合 Payload:向量关联的元数据 量化支持:标量量化(SQ8)、乘积量化(PQ)、二进制量化 磁盘索引:支持大于内存的数据集 核心优势 简单部署:单二进制+Docker 高性能:Rust实现,无GC暂停 丰富过滤:Payload过滤能力强大 量化压缩:内存占用极低 适用场景 中小规模(<1亿向量) 快速原型开发 对延迟敏感的场景 运维资源有限的团队 注意事项 分布式能力不如Milvus 不支持多租户隔离 生态插件较少 Weaviate:AI原生设计 架构特点 Weaviate定位为"AI原生数据库": GraphQL API:内置API层 模块化向量化:内置多种embedding模型 对象存储+向量索引:一体化设计 多模态支持:图像/文本/视频嵌入 核心优势 开箱即用:内置embedding模型 GraphQL接口:前端友好 多模态:原生支持多种数据类型 混合检索:BM25+向量融合 适用场景 快速构建AI应用 需要多模态检索 前端团队主导的项目 不想单独管理embedding流程 注意事项 性能不如Qdrant极致 大规模部署经验较少 Go实现,性能依赖GC调优 性能对比 写入性能 数据库 单线程写入 批量写入(10K) 索引构建速度 Milvus 5K/s 50K/s 中等 Qdrant 8K/s 80K/s 快 Weaviate 3K/s 30K/s 中等 查询性能 数据库 p50延迟 p99延迟 并发QPS Milvus 5ms 20ms 10K+ Qdrant 2ms 8ms 5K+ Weaviate 8ms 30ms 3K+ 注:测试条件为1M向量,768维,HNSW索引,单节点。实际性能受数据规模、硬件、配置影响。 ...

2026-07-16 · 2 min · 230 words · 硅基 AGI 探索者

向量数据库选型指南:从原理对比到生产实践

向量数据库:AI应用的基础设施 RAG系统、语义搜索、推荐系统——这些AI应用的核心基础设施都是向量数据库。2026年的向量数据库市场已经从早期的"够用就行"进化到"精打细算"的阶段,选型直接影响系统性能和成本。 核心技术维度 索引算法 向量数据库的性能核心在于近似最近邻搜索(ANN)算法: HNSW(Hierarchical Navigable Small World): 原理:多层图结构,顶层稀疏快速导航,底层密集精确搜索 优势:查询速度快,召回率高 劣势:内存占用大,构建慢 适合:中小规模(<1000万),高召回需求 IVF(Inverted File Index): 原理:将向量空间聚类为N个桶,查询时只搜索最近的几个桶 优势:内存效率好,支持大规模数据 劣势:需要训练聚类模型,召回率受桶数影响 适合:大规模(>1000万),召回率可接受场景 PQ(Product Quantization): 原理:将高维向量分成子向量,每个子向量量化编码 优势:存储压缩比高(10-100倍) 劣势:精度损失 适合:超大规模,成本敏感场景 组合索引:IVF+PQ或HNSW+PQ结合各自优势: # Milvus中的组合索引配置 collection_config = { "index_type": "IVF_PQ", "params": { "nlist": 1024, # IVF聚类中心数 "m": 16, # PQ子向量数 "nbits": 8, # 每个子向量的编码位数 }, "metric_type": "COSINE" } 量化与压缩 class QuantizationComparison: """不同量化方案的效果对比""" results = { "FP32 (无压缩)": { "recall": 1.0, "memory": "100%", "speed": "基准" }, "FP16": { "recall": 0.999, "memory": "50%", "speed": "1.2x" }, "INT8 (标量量化)": { "recall": 0.99, "memory": "25%", "speed": "1.5x" }, "PQ8 (乘积量化8bit)": { "recall": 0.95, "memory": "12.5%", "speed": "2.0x" }, "PQ4 (乘积量化4bit)": { "recall": 0.88, "memory": "6.25%", "speed": "2.5x" } } 主流方案对比 Milvus from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType # 连接Milvus connections.connect(host="localhost", port="19530") # 创建Collection fields = [ FieldSchema(name="id", dtype=DataType.INT64, is_primary=True), FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1024), FieldSchema(name="metadata", dtype=DataType.JSON), ] schema = CollectionSchema(fields, "文档向量集合") collection = Collection("documents", schema) # 创建索引 collection.create_index( field_name="embedding", index_params={ "index_type": "HNSW", "metric_type": "COSINE", "params": {"M": 16, "efConstruction": 256} } ) # 搜索 results = collection.search( data=[query_vector], anns_field="embedding", param={"params": {"ef": 64}}, limit=10, expr='department == "engineering"' # 标量过滤 ) 优势: ...

2026-07-16 · 3 min · 563 words · 硅基 AGI 探索者

AI Agent记忆系统架构深度解析:从短期记忆到持久化知识库

记忆系统:智能体的"海马体" 人类大脑的海马体负责将短期记忆转化为长期记忆,AI Agent同样需要一套完善的记忆机制才能实现真正意义上的智能行为。当前主流的Agent框架中,记忆系统设计往往是最被低估却又最关键的组件。 三层记忆架构模型 1. 工作记忆(Working Memory) 工作记忆对应Agent的上下文窗口,是当前正在处理的信息。以GPT-4 Turbo为例,128K token的上下文窗口就是其工作记忆容量。但工作记忆存在两个核心问题: 容量限制:即使是128K也有上限,长对话会丢失早期信息 注意力衰减:研究表明,LLM在上下文中间位置的信息处理能力显著下降(Lost in the Middle现象) 工程实践中,我们通常采用滑动窗口策略配合摘要压缩来管理工作记忆: class WorkingMemory: def __init__(self, max_tokens=128000): self.max_tokens = max_tokens self.messages = [] self.current_tokens = 0 def add(self, message): self.messages.append(message) self.current_tokens += count_tokens(message) if self.current_tokens > self.max_tokens * 0.8: self._compress() def _compress(self): # 保留最近N条消息,将早期消息摘要化 recent = self.messages[-10:] old = self.messages[:-10] summary = llm_summarize(old) self.messages = [{"role": "system", "content": summary}] + recent 2. 情景记忆(Episodic Memory) 情景记忆记录Agent过去的交互经历,包括具体对话、决策过程和结果反馈。这一层通常通过向量数据库实现,如Chroma、Pinecone或Weaviate。 关键设计点在于索引策略。单纯按语义相似度检索往往不够,还需要加入时间衰减因子,因为更近的交互经验通常更具参考价值: def retrieve_episodic(query, top_k=5, alpha=0.7): # 语义相似度 semantic_scores = vector_db.search(query, top_k=20) # 时间衰减 for item in semantic_scores: days_ago = (datetime.now() - item.timestamp).days time_score = math.exp(-0.05 * days_ago) item.final_score = alpha * item.similarity + (1 - alpha) * time_score return sorted(semantic_scores, key=lambda x: x.final_score, reverse=True)[:top_k] 3. 语义记忆(Semantic Memory) 语义记忆是Agent的长期知识库,存储经过验证的事实、规则和概念。与情景记忆的区别在于:情景记忆是"经历",语义记忆是"知识"。 典型的语义记忆构建流程包括: 从多次交互中提取共性知识 通过知识图谱建立实体间关系 定期进行知识一致性检查和冲突消解 记忆检索的工程优化 在实际项目中,记忆检索的延迟是用户体验的关键瓶颈。以下是一些经过验证的优化策略: 分层检索:先从语义记忆中快速过滤(关键词匹配),再进行向量相似度精确排序,可以将检索延迟从500ms降低到50ms以内。 预计算缓存:对于高频查询,预先计算并缓存检索结果。利用用户意图分类器判断是否命中缓存。 异步写入:记忆写入不应阻塞主流程。采用写前日志(WAL)模式,先快速持久化到本地,再异步同步到向量数据库。 记忆遗忘机制 好的记忆系统不仅需要记住,还需要遗忘。参考Ebbinghaus遗忘曲线,我们可以设计自适应遗忘策略: 高频访问的记忆:保留权重高,不易遗忘 被验证为错误的记忆:主动降低权重 超过30天未访问的非核心记忆:降级到冷存储 结语 记忆系统是AI Agent从"工具"向"助手"跃迁的关键基础设施。随着Agent应用场景的复杂化,记忆架构的设计将越来越接近人类认知模型。下一篇文章我们将探讨基于MCP协议的记忆共享机制,实现多Agent间的知识传递。 ...

2026-07-16 · 1 min · 134 words · 硅基 AGI 探索者

向量数据库横评:Milvus vs Qdrant vs Weaviate

向量数据库:RAG时代的基础设施 向量数据库是RAG系统的核心组件。选择合适的向量数据库直接影响检索性能、扩展性和运维成本。 2026年,向量数据库赛道已经从"百花齐放"走向"头部集中"。Milvus、Qdrant和Weaviate是三个最主流的开源选择,各自有不同的设计哲学和适用场景。 三者简介 Milvus:由Zilliz开发,CNCF毕业项目。定位为云原生向量数据库,强调大规模和水平扩展。 Qdrant:Rust编写,轻量高效。定位为高性能向量搜索引擎,强调简洁和速度。 Weaviate:Go编写,GraphQL API。定位为AI原生数据库,内置向量化模块和混合检索。 功能对比 功能 Milvus Qdrant Weaviate 纯向量搜索 ✅ ✅ ✅ 标量过滤 ✅ ✅ ✅ 混合搜索(BM25+向量) ✅ (2.4+) ✅ ✅ (内置) 多向量搜索 ✅ ✅ ✅ 内置Embedding ❌ ❌ ✅ 动态Schema ✅ (2.4+) ✅ ✅ 分片 ✅ ✅ ✅ 副本 ✅ ✅ ✅ 云托管 Zilliz Cloud Qdrant Cloud Weaviate Cloud 关键差异 Weaviate的内置Embedding模块是一个独特优势——可以直接输入文本,数据库自动进行向量化。Milvus和Qdrant需要外部Embedding服务。 Milvus的混合搜索实现最成熟,支持多种索引类型和复杂的过滤条件。Qdrant的混合搜索是后来加的,但在简单场景下性能优异。 Qdrant的Rust实现带来了天然的内存安全和性能优势。部署二进制只有一个文件,运维极简。 性能测试 测试设置 数据集:100万、1000万、1亿条768维向量 硬件:单机(64核CPU,256GB RAM,NVMe SSD) 指标:QPS(每秒查询数)、P99延迟、召回率、内存占用 100万向量 指标 Milvus Qdrant Weaviate QPS 12,500 18,200 8,300 P99延迟 8ms 4ms 15ms 召回率@10 98.5% 98.2% 97.8% 内存占用 4.2GB 3.1GB 5.8GB 在小数据量下,Qdrant全面领先——更快的速度、更低的延迟、更少的内存。 ...

2026-07-12 · 1 min · 190 words · 硅基 AGI 探索者

向量数据库横评:Milvus vs Qdrant vs Weaviate

向量数据库:RAG时代的基础设施 向量数据库是RAG系统的核心组件。选择合适的向量数据库直接影响检索性能、扩展性和运维成本。 2026年,向量数据库赛道已经从"百花齐放"走向"头部集中"。Milvus、Qdrant和Weaviate是三个最主流的开源选择,各自有不同的设计哲学和适用场景。 三者简介 Milvus:由Zilliz开发,CNCF毕业项目。定位为云原生向量数据库,强调大规模和水平扩展。 Qdrant:Rust编写,轻量高效。定位为高性能向量搜索引擎,强调简洁和速度。 Weaviate:Go编写,GraphQL API。定位为AI原生数据库,内置向量化模块和混合检索。 功能对比 功能 Milvus Qdrant Weaviate 纯向量搜索 ✅ ✅ ✅ 标量过滤 ✅ ✅ ✅ 混合搜索(BM25+向量) ✅ (2.4+) ✅ ✅ (内置) 多向量搜索 ✅ ✅ ✅ 内置Embedding ❌ ❌ ✅ 动态Schema ✅ (2.4+) ✅ ✅ 分片 ✅ ✅ ✅ 副本 ✅ ✅ ✅ 云托管 Zilliz Cloud Qdrant Cloud Weaviate Cloud 关键差异 Weaviate的内置Embedding模块是一个独特优势——可以直接输入文本,数据库自动进行向量化。Milvus和Qdrant需要外部Embedding服务。 Milvus的混合搜索实现最成熟,支持多种索引类型和复杂的过滤条件。Qdrant的混合搜索是后来加的,但在简单场景下性能优异。 Qdrant的Rust实现带来了天然的内存安全和性能优势。部署二进制只有一个文件,运维极简。 性能测试 测试设置 数据集:100万、1000万、1亿条768维向量 硬件:单机(64核CPU,256GB RAM,NVMe SSD) 指标:QPS(每秒查询数)、P99延迟、召回率、内存占用 100万向量 指标 Milvus Qdrant Weaviate QPS 12,500 18,200 8,300 P99延迟 8ms 4ms 15ms 召回率@10 98.5% 98.2% 97.8% 内存占用 4.2GB 3.1GB 5.8GB 在小数据量下,Qdrant全面领先——更快的速度、更低的延迟、更少的内存。 ...

2026-07-12 · 1 min · 190 words · 硅基 AGI 探索者

从零搭建企业级RAG系统:完整方案设计

为什么大多数RAG项目都失败了 2026年,几乎所有企业都在尝试RAG,但真正在生产环境中稳定运行的比例不到30%。失败的原因惊人地一致——把RAG当作一个简单的"文档问答"系统,忽视了工程化部署中的无数细节。 本文将分享我们从多个企业RAG项目中总结的完整方案。 整体架构 一个生产级RAG系统包含以下七个核心模块: 1. 数据接入层 文档解析:支持PDF、Word、PPT、Excel、HTML、Markdown等格式。关键挑战是表格和图片的解析——我们采用Unstructured.io做基础解析,对表格使用专门的Table Transformer模型,对图片使用VLM生成描述。 数据源连接器:企业数据散落在各种系统中——SharePoint、Confluence、Jira、数据库、邮件服务器。我们为每个数据源开发专用连接器,支持增量同步和变更检测。 权限映射:企业数据有严格的权限控制。RAG系统必须在检索时尊重原始文档的访问权限。我们的方案是为每个文档片段标记ACL(Access Control List),检索时根据用户身份过滤。 2. 文档处理管道 分块策略:分块质量直接决定检索质量。我们采用三级分块策略: 语义分块:按段落和章节边界分块,保持语义完整性 重叠窗口:相邻块之间保留10-20%的重叠,避免边界信息丢失 层级分块:同时生成小块(256 Token)和大块(1024 Token),检索时小块匹配、大块提供上下文 元数据标注:为每个块标注来源文档、章节标题、文档类型、创建时间、作者等元数据。这些元数据在检索时用于过滤和重排序。 3. 索引层 嵌入模型选择:中文场景推荐BGE-M3或Qwen3-Embedding,英文场景推荐text-embedding-3-large。关键是选择支持长文本的嵌入模型——我们的块最大1024 Token,嵌入模型必须能处理这个长度。 向量数据库:根据数据规模选择: <100万块:Qdrant单机版足够,部署简单 100万-1000万块:Milvus集群版,支持水平扩展 1000万块:需要考虑分片策略和混合检索 混合索引:纯向量检索在精确匹配场景(如产品型号、人名搜索)效果差。我们同时建立BM25全文索引,检索时融合向量检索和BM25的结果。 4. 检索层 多路召回: 向量召回:语义相似度检索Top-K 关键词召回:BM25检索Top-K 元数据过滤:根据用户权限和时间范围预过滤 重排序:使用Cross-Encoder模型(如bge-reranker-v2)对召回的50-100个候选项重排序,取Top-5-10送入生成模型。重排序是RAG质量提升的关键一步——在我们的实验中,加入重排序后答案准确率提升约15%。 查询改写:用户的原始query往往不是最佳的检索query。我们使用LLM对query进行改写——扩展缩写、添加同义词、分解复合问题为子问题。 5. 生成层 Prompt模板:精心设计的Prompt模板对RAG质量至关重要。我们的模板包含: 系统指令:定义AI的角色和回答边界 检索上下文:格式化的检索结果,包含来源标注 用户问题:原始用户问题 输出要求:要求引用来源、不确定时说明 幻觉抑制:在Prompt中明确要求"仅基于提供的上下文回答,如果上下文没有相关信息请明确说明"。同时使用Self-Reflection机制——生成后让模型自检答案是否有上下文支撑。 6. 反馈与优化层 用户反馈收集:每个答案提供"有用/无用"反馈按钮和修正建议入口。这些反馈用于持续优化。 A/B测试框架:对索引参数、检索策略、Prompt模板的变更进行A/B测试,用数据驱动优化决策。 自动评估流水线:定期使用测试集自动评估系统质量,监控质量回归。 7. 监控与运维层 关键指标: 检索质量:召回率、精确率、MRR 生成质量:答案准确率、幻觉率、引用准确率 系统性能:端到端延迟、吞吐量、错误率 用户满意度:反馈评分、重试率 告警机制:当检索质量或生成质量低于阈值时自动告警,触发排查流程。 部署建议 起步阶段(1-2个月):单机部署,Qdrant + 基础文档解析 + 单一嵌入模型。目标是验证核心流程跑通。 扩展阶段(3-6个月):引入混合检索、重排序、查询改写。建立监控和反馈体系。 成熟阶段(6个月+):集群化部署、多数据源接入、权限体系完善、持续优化闭环。 常见踩坑 过早优化:一开始就上复杂的GraphRAG或Agentic RAG,连基础RAG都没跑稳 忽视文档质量:垃圾进垃圾出,再好的检索算法也救不了低质量输入 分块策略一刀切:不同类型文档需要不同分块策略 不做重排序:仅靠向量检索的Top-K效果往往不够 没有评估体系:没有量化指标就无法判断优化是否有效 RAG不是一个项目,而是一个持续优化的工程。做好长期投入的准备,才能真正让它成为企业的知识引擎。 ...

2026-07-12 · 1 min · 78 words · 硅基 AGI 探索者

从零搭建企业级RAG系统:完整方案设计

为什么大多数RAG项目都失败了 2026年,几乎所有企业都在尝试RAG,但真正在生产环境中稳定运行的比例不到30%。失败的原因惊人地一致——把RAG当作一个简单的"文档问答"系统,忽视了工程化部署中的无数细节。 本文将分享我们从多个企业RAG项目中总结的完整方案。 整体架构 一个生产级RAG系统包含以下七个核心模块: 1. 数据接入层 文档解析:支持PDF、Word、PPT、Excel、HTML、Markdown等格式。关键挑战是表格和图片的解析——我们采用Unstructured.io做基础解析,对表格使用专门的Table Transformer模型,对图片使用VLM生成描述。 数据源连接器:企业数据散落在各种系统中——SharePoint、Confluence、Jira、数据库、邮件服务器。我们为每个数据源开发专用连接器,支持增量同步和变更检测。 权限映射:企业数据有严格的权限控制。RAG系统必须在检索时尊重原始文档的访问权限。我们的方案是为每个文档片段标记ACL(Access Control List),检索时根据用户身份过滤。 2. 文档处理管道 分块策略:分块质量直接决定检索质量。我们采用三级分块策略: 语义分块:按段落和章节边界分块,保持语义完整性 重叠窗口:相邻块之间保留10-20%的重叠,避免边界信息丢失 层级分块:同时生成小块(256 Token)和大块(1024 Token),检索时小块匹配、大块提供上下文 元数据标注:为每个块标注来源文档、章节标题、文档类型、创建时间、作者等元数据。这些元数据在检索时用于过滤和重排序。 3. 索引层 嵌入模型选择:中文场景推荐BGE-M3或Qwen3-Embedding,英文场景推荐text-embedding-3-large。关键是选择支持长文本的嵌入模型——我们的块最大1024 Token,嵌入模型必须能处理这个长度。 向量数据库:根据数据规模选择: <100万块:Qdrant单机版足够,部署简单 100万-1000万块:Milvus集群版,支持水平扩展 1000万块:需要考虑分片策略和混合检索 混合索引:纯向量检索在精确匹配场景(如产品型号、人名搜索)效果差。我们同时建立BM25全文索引,检索时融合向量检索和BM25的结果。 4. 检索层 多路召回: 向量召回:语义相似度检索Top-K 关键词召回:BM25检索Top-K 元数据过滤:根据用户权限和时间范围预过滤 重排序:使用Cross-Encoder模型(如bge-reranker-v2)对召回的50-100个候选项重排序,取Top-5-10送入生成模型。重排序是RAG质量提升的关键一步——在我们的实验中,加入重排序后答案准确率提升约15%。 查询改写:用户的原始query往往不是最佳的检索query。我们使用LLM对query进行改写——扩展缩写、添加同义词、分解复合问题为子问题。 5. 生成层 Prompt模板:精心设计的Prompt模板对RAG质量至关重要。我们的模板包含: 系统指令:定义AI的角色和回答边界 检索上下文:格式化的检索结果,包含来源标注 用户问题:原始用户问题 输出要求:要求引用来源、不确定时说明 幻觉抑制:在Prompt中明确要求"仅基于提供的上下文回答,如果上下文没有相关信息请明确说明"。同时使用Self-Reflection机制——生成后让模型自检答案是否有上下文支撑。 6. 反馈与优化层 用户反馈收集:每个答案提供"有用/无用"反馈按钮和修正建议入口。这些反馈用于持续优化。 A/B测试框架:对索引参数、检索策略、Prompt模板的变更进行A/B测试,用数据驱动优化决策。 自动评估流水线:定期使用测试集自动评估系统质量,监控质量回归。 7. 监控与运维层 关键指标: 检索质量:召回率、精确率、MRR 生成质量:答案准确率、幻觉率、引用准确率 系统性能:端到端延迟、吞吐量、错误率 用户满意度:反馈评分、重试率 告警机制:当检索质量或生成质量低于阈值时自动告警,触发排查流程。 部署建议 起步阶段(1-2个月):单机部署,Qdrant + 基础文档解析 + 单一嵌入模型。目标是验证核心流程跑通。 扩展阶段(3-6个月):引入混合检索、重排序、查询改写。建立监控和反馈体系。 成熟阶段(6个月+):集群化部署、多数据源接入、权限体系完善、持续优化闭环。 常见踩坑 过早优化:一开始就上复杂的GraphRAG或Agentic RAG,连基础RAG都没跑稳 忽视文档质量:垃圾进垃圾出,再好的检索算法也救不了低质量输入 分块策略一刀切:不同类型文档需要不同分块策略 不做重排序:仅靠向量检索的Top-K效果往往不够 没有评估体系:没有量化指标就无法判断优化是否有效 RAG不是一个项目,而是一个持续优化的工程。做好长期投入的准备,才能真正让它成为企业的知识引擎。 ...

2026-07-12 · 1 min · 78 words · 硅基 AGI 探索者
向量数据库基准

向量数据库基准2026:存储与检索的极致优化

引言 向量数据库是RAG系统的核心基础设施。2026年,随着嵌入维度的增加(从768维到3072维)和数据规模的扩大(从百万到十亿级),向量数据库的性能变得至关重要。本文将全面对比主流向量数据库。 参评数据库 数据库 类型 部署方式 特点 Milvus 2.5 专用 分布式 最强大,可扩展 Qdrant 1.10 专用 单机/分布式 性能优秀,Rust编写 Chroma 0.6 轻量 嵌入式 开发友好,轻量 Weaviate 1.25 专用 分布式 GraphQL API pgvector 0.7 扩展 PostgreSQL SQL兼容 Pinecone 云服务 SaaS 全托管,零运维 Elasticsearch 8 通用 分布式 全文+向量混合 FAISS 库 进程内 最快,无服务 性能基准 测试设置 数据集:1000万条1024维向量 硬件:A100 80GB + 256GB RAM 索引:HNSW(统一参数) 索引速度 数据库 索引1000万条(s) 吞吐量(条/s) Milvus 320 31250 Qdrant 280 35714 Chroma 850 11764 Weaviate 350 28571 pgvector 1200 8333 FAISS 180 55555 查询延迟 数据库 P50(ms) P95(ms) P99(ms) Milvus 2.1 5.5 8.2 Qdrant 1.8 4.2 6.5 Chroma 8.5 15.2 22.0 Weaviate 3.2 7.8 12.1 pgvector 12.5 25.0 38.0 FAISS 0.8 1.5 2.2 Pinecone 5.0 12.0 18.0 召回率 top-10召回率(与精确搜索对比): ...

2026-07-02 · 3 min · 501 words · 硅基 AGI 探索者
Agent记忆持久化

Agent记忆持久化实现

Agent记忆的三层架构 Agent需要像人类一样管理不同类型的记忆: 工作记忆:当前对话的上下文(短期) 情景记忆:过去交互的具体经历(中期) 语义记忆:从交互中提炼的知识(长期) 工作记忆:对话窗口管理 from collections import deque class WorkingMemory: def __init__(self, max_messages=20, max_tokens=4096): self.messages = deque(maxlen=max_messages) self.max_tokens = max_tokens self.token_counter = 0 def add(self, role, content): tokens = len(content) // 4 self.messages.append({"role": role, "content": content, "tokens": tokens}) self.token_counter += tokens # 超出token限制时移除最早的消息 while self.token_counter > self.max_tokens and len(self.messages) > 2: old = self.messages.popleft() self.token_counter -= old["tokens"] def get_context(self): return list(self.messages) def summarize_old_context(self): """当记忆过长时,摘要旧对话""" if len(self.messages) < 10: return old_messages = list(self.messages)[:len(self.messages)//2] summary = await self.summarize(old_messages) # 用摘要替换旧消息 for _ in range(len(old_messages)): self.messages.popleft() self.messages.appendleft({"role": "system", "content": f"之前的对话摘要:{summary}"}) 情景记忆:交互历史存储 class EpisodicMemory: def __init__(self, vector_store, llm): self.store = vector_store # 向量数据库 self.llm = llm async def save_interaction(self, user_id, user_message, assistant_response, metadata=None): """保存一次交互记录""" interaction = { "user_id": user_id, "user_message": user_message, "assistant_response": assistant_response, "timestamp": datetime.now().isoformat(), "metadata": metadata or {}, } # 生成摘要用于检索 summary = await self.llm.generate( f"用一句话概括这次交互:\n用户:{user_message}\n助手:{assistant_response}" ) # 向量化并存储 embedding = await self.llm.embed(summary) await self.store.add( id=generate_uuid(), embedding=embedding, document=json.dumps(interaction, ensure_ascii=False), metadata={"user_id": user_id, "summary": summary} ) async def recall(self, user_id, query, top_k=5): """检索相关的历史交互""" query_embedding = await self.llm.embed(query) results = await self.store.search( query_embedding, filter={"user_id": user_id}, top_k=top_k ) return [json.loads(r.document) for r in results] 语义记忆:知识图谱 class SemanticMemory: def __init__(self, graph_store): self.graph = graph_store # 图数据库(如Neo4j) async def learn(self, user_id, fact): """从交互中提取并存储知识""" # 使用LLM提取结构化知识 extracted = await self.extract_facts(fact) for fact_data in extracted: await self.graph.add_triple( subject=fact_data["subject"], predicate=fact_data["predicate"], object=fact_data["object"], metadata={"user_id": user_id, "source": "interaction"} ) async def query(self, user_id, entity): """查询关于某实体的知识""" triples = await self.graph.query( "MATCH (s)-[p]->(o) WHERE s.name = $entity RETURN s, p, o", {"entity": entity} ) knowledge = [] for triple in triples: knowledge.append(f"{triple['s']} {triple['p']} {triple['o']}") return knowledge async def extract_facts(self, text): """从文本中提取三元组""" prompt = f"""从以下文本中提取知识三元组(主语-谓语-宾语): 文本:{text} 输出JSON数组: [{{"subject": "...", "predicate": "...", "object": "..."}}]""" result = await self.llm.generate(prompt) return json.loads(result) 记忆整合 class AgentMemorySystem: def __init__(self, working, episodic, semantic): self.working = working # 工作记忆 self.episodic = episodic # 情景记忆 self.semantic = semantic # 语义记忆 async def build_context(self, user_id, current_message): """构建完整的记忆上下文""" context_parts = [] # 1. 工作记忆(当前对话) working_ctx = self.working.get_context() context_parts.append({"type": "working", "messages": working_ctx}) # 2. 情景记忆(相关历史交互) episodic_results = await self.episodic.recall( user_id, current_message, top_k=3 ) if episodic_results: context_parts.append({ "type": "episodic", "memories": [r["summary"] for r in episodic_results] }) # 3. 语义记忆(相关知识) entities = await self.extract_entities(current_message) for entity in entities: knowledge = await self.semantic.query(user_id, entity) if knowledge: context_parts.append({ "type": "semantic", "entity": entity, "facts": knowledge }) return self.format_context(context_parts) def format_context(self, parts): """格式化记忆上下文""" context = "" for part in parts: if part["type"] == "working": context += "## 当前对话\n" for msg in part["messages"]: context += f"{msg['role']}: {msg['content']}\n" elif part["type"] == "episodic": context += "\n## 相关历史\n" for mem in part["memories"]: context += f"- {mem}\n" elif part["type"] == "semantic": context += f"\n## 关于{part['entity']}的知识\n" for fact in part["facts"]: context += f"- {fact}\n" return context 遗忘机制 class ForgettingMechanism: def __init__(self, decay_rate=0.01): self.decay_rate = decay_rate async def decay(self, memory_store): """时间衰减:降低旧记忆的重要性""" now = datetime.now() memories = await memory_store.get_all() for mem in memories: age_days = (now - mem["timestamp"]).days importance = mem.get("importance", 1.0) importance *= (1 - self.decay_rate) ** age_days if importance < 0.1: await memory_store.delete(mem["id"]) else: await memory_store.update(mem["id"], importance=importance) async def consolidate(self, memory_store): """记忆整合:将频繁出现的情景记忆转为语义记忆""" # 找出高频出现的事实 memories = await memory_store.get_all(min_importance=0.5) # 聚类相似记忆 clusters = self.cluster_memories(memories) for cluster in clusters: if len(cluster) >= 3: # 出现3次以上的模式转为知识 summary = await self.summarize_cluster(cluster) await self.semantic_memory.learn(summary) # 降低原始记忆的重要性 for mem in cluster: await memory_store.update(mem["id"], importance=mem["importance"] * 0.3) 存储选择 记忆类型 推荐存储 特点 工作记忆 内存(Redis) 快速读写,无需持久化 情景记忆 向量数据库 语义检索,按相似度召回 语义记忆 图数据库 关系查询,知识推理 结语 Agent记忆系统是构建长期智能助手的核心基础设施。工作记忆处理当前对话,情景记忆保存交互历史,语义记忆积累结构化知识。三层记忆的协同工作加上遗忘和整合机制,让Agent像人类一样"记得住该记的,忘得掉该忘的"。 加入讨论 这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。 ...

2026-07-02 · 3 min · 552 words · 硅基 AGI 探索者
RAG管线优化

RAG管线优化2026实战

RAG的核心挑战 RAG(检索增强生成)让LLM能够基于私有知识回答问题。但一个简单的RAG原型——文档切块→向量化→相似度检索→拼接到prompt——在实际使用中往往效果不佳。2026年的RAG优化需要从文档处理、检索质量、上下文管理和生成控制四个维度系统提升。 文档处理优化 智能分块 from langchain.text_splitter import RecursiveCharacterTextSplitter, MarkdownHeaderTextSplitter class SmartChunker: def __init__(self, chunk_size=512, chunk_overlap=64): self.chunk_size = chunk_size self.chunk_overlap = chunk_overlap # 通用分割器 self.general_splitter = RecursiveCharacterTextSplitter( chunk_size=chunk_size, chunk_overlap=chunk_overlap, separators=["\n\n", "\n", "。", "!", "?", ".", "!", "?", " ", ""] ) # Markdown分割器 self.md_splitter = MarkdownHeaderTextSplitter( headers_to_split_on=[ ("#", "Header 1"), ("##", "Header 2"), ("###", "Header 3"), ] ) def chunk(self, text, doc_type="auto"): if doc_type == "auto": doc_type = self.detect_type(text) if doc_type == "markdown": # 先按标题分块,再按大小细分 md_chunks = self.md_splitter.split_text(text) final_chunks = [] for chunk in md_chunks: if len(chunk.page_content) > self.chunk_size * 2: sub_chunks = self.general_splitter.split_text(chunk.page_content) for sc in sub_chunks: sc.metadata = chunk.metadata final_chunks.append(sc) else: final_chunks.append(chunk) return final_chunks else: return self.general_splitter.split_text(text) def detect_type(self, text): md_indicators = ["# ", "## ", "- [", "```", "| "] if any(ind in text[:500] for ind in md_indicators): return "markdown" return "text" 表格与代码处理 class TableAwareChunker: """避免在表格中间切分""" def chunk(self, text): # 识别表格区域 table_pattern = r'(\|[^\n]+\|\n)+' chunks = [] last_end = 0 for match in re.finditer(table_pattern, text): # 表格前的文本正常切分 pre_text = text[last_end:match.start()] if pre_text.strip(): chunks.extend(self.split_text(pre_text)) # 表格作为完整块 chunks.append(text[match.start():match.end()]) last_end = match.end() # 剩余文本 if last_end < len(text): chunks.extend(self.split_text(text[last_end:])) return chunks 向量化优化 多向量表示 from sentence_transformers import SentenceTransformer class MultiVectorEncoder: def __init__(self): self.dense_model = SentenceTransformer('BAAI/bge-large-zh-v1.5') # 稀疏向量用于关键词匹配 self.sparse_model = None # 使用BM25或SPLADE def encode(self, text): # 密集向量:语义相似度 dense_vec = self.dense_model.encode(text, normalize_embeddings=True) # 稀疏向量:精确匹配 sparse_vec = self.sparse_model.encode(text) if self.sparse_model else None return { "dense": dense_vec, "sparse": sparse_vec, "text": text } 查询扩展 class QueryExpander: def __init__(self, llm): self.llm = llm async def expand(self, query): """使用LLM扩展查询""" prompt = f"""将以下查询改写为3个不同角度的表述,用于检索: 原始查询:{query} 输出格式: 1. [改写1] 2. [改写2] 3. [改写3]""" response = await self.llm.ainvoke(prompt) expansions = self.parse_expansions(response) expansions.append(query) # 保留原始查询 return expansions def parse_expansions(self, text): lines = text.strip().split('\n') return [line.split('.', 1)[1].strip() for line in lines if '.' in line] 检索优化 混合检索 import numpy as np class HybridRetriever: def __init__(self, vector_store, bm25_store, alpha=0.7): self.vector_store = vector_store # 密集向量检索 self.bm25_store = bm25_store # BM25稀疏检索 self.alpha = alpha # 混合权重 async def retrieve(self, query, k=5): # 密集检索 dense_results = await self.vector_store.asimilarity_search_with_score( query, k=k*2 ) # 稀疏检索 sparse_results = self.bm25_store.search(query, k=k*2) # 分数归一化 dense_scores = self.normalize_scores([s for _, s in dense_results]) sparse_scores = self.normalize_scores([s for _, s in sparse_results]) # 混合排序 combined = {} for (doc, _), score in zip(dense_results, dense_scores): doc_id = doc.metadata["id"] combined[doc_id] = combined.get(doc_id, 0) + self.alpha * score combined.setdefault(f"{doc_id}_doc", doc) for (doc, _), score in zip(sparse_results, sparse_scores): doc_id = doc.metadata["id"] combined[doc_id] = combined.get(doc_id, 0) + (1 - self.alpha) * score combined.setdefault(f"{doc_id}_doc", doc) # 排序返回top-k sorted_ids = sorted( [k for k in combined if not k.endswith("_doc")], key=lambda x: combined[x], reverse=True )[:k] return [combined[f"{did}_doc"] for did in sorted_ids] def normalize_scores(self, scores): if not scores: return [] scores = np.array(scores) if scores.max() > scores.min(): return (scores - scores.min()) / (scores.max() - scores.min()) return np.ones_like(scores) 重排序 from sentence_transformers import CrossEncoder class Reranker: def __init__(self, model_name="BAAI/bge-reranker-large"): self.model = CrossEncoder(model_name) def rerank(self, query, documents, top_k=5): # 构建query-document对 pairs = [(query, doc.page_content) for doc in documents] # 计算相关性分数 scores = self.model.predict(pairs) # 排序 ranked = sorted(zip(documents, scores), key=lambda x: x[1], reverse=True) return [doc for doc, _ in ranked[:top_k]] 上下文管理 动态上下文窗口 class ContextManager: def __init__(self, max_tokens=4096): self.max_tokens = max_tokens def build_context(self, query, retrieved_docs, conversation_history=None): # 预留生成空间 context_budget = self.max_tokens - 512 # 分配:历史对话30%,检索文档70% history_budget = int(context_budget * 0.3) docs_budget = context_budget - history_budget # 构建历史上下文 history_text = self.build_history(conversation_history, history_budget) # 构建文档上下文(按相关性排序) docs_text = self.build_docs(retrieved_docs, docs_budget) # 组装最终prompt context = f""" ## 历史对话 {history_text} ## 相关知识 {docs_text} ## 用户问题 {query} """ return context def build_docs(self, docs, budget): result = [] current_tokens = 0 for i, doc in enumerate(docs): doc_text = f"[{i+1}] {doc.page_content}\n" doc_tokens = len(doc_text) // 4 # 粗略估计 if current_tokens + doc_tokens > budget: break result.append(doc_text) current_tokens += doc_tokens return "\n".join(result) 引用标注 class CitationGenerator: def __init__(self, llm): self.llm = llm async def generate_with_citations(self, query, retrieved_docs): # 为每个文档分配编号 docs_context = "\n\n".join([ f"[{i+1}] {doc.page_content}" for i, doc in enumerate(retrieved_docs) ]) prompt = f"""基于以下参考资料回答问题。在回答中使用 [编号] 标注信息来源。 参考资料: {docs_context} 问题:{query} 要求: 1. 只使用参考资料中的信息 2. 用 [编号] 标注每条信息的来源 3. 如果资料中没有相关信息,说明"根据现有资料无法回答" """ response = await self.llm.ainvoke(prompt) return response 评估与迭代 RAG评估指标 class RAGEvaluator: def __init__(self, llm): self.llm = llm async def evaluate(self, query, response, retrieved_docs, ground_truth=None): metrics = {} # 1. 检索相关性 metrics["retrieval_relevance"] = await self.eval_retrieval( query, retrieved_docs ) # 2. 回答忠实度(是否基于检索内容) metrics["faithfulness"] = await self.eval_faithfulness( response, retrieved_docs ) # 3. 回答完整性 if ground_truth: metrics["completeness"] = await self.eval_completeness( response, ground_truth ) return metrics async def eval_faithfulness(self, response, docs): """评估回答是否忠实于检索内容""" prompt = f"""判断以下回答是否完全基于给定的参考资料。 参考资料:{' '.join(d.page_content[:200] for d in docs)} 回答:{response} 请输出: 1. 忠实/不忠实 2. 不忠实的部分(如有) """ result = await self.llm.ainvoke(prompt) return "忠实" in result 结语 RAG管线优化是一个系统性工程,从文档分块到检索策略、从上下文管理到生成控制,每个环节都需要精心设计。2026年的RAG最佳实践强调混合检索、重排序、动态上下文管理和引用标注——这些技术组合使用可以显著提升RAG系统的准确性和可靠性。 加入讨论 这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。 ...

2026-07-02 · 4 min · 748 words · 硅基 AGI 探索者
鲁ICP备2026018361号