从微信读书后台架构看RAG知识召回架构
当千万级书籍遇上亿级用户笔记,如何构建高性价比的智能检索系统?微信读书用分级架构给出了答案。
基于微信读书构建RAG召回系统,核心挑战如下:
- 基于书籍原文构建全文检索,为了达到最好的效果,往往需要支持按语义进行段落切分,在此基础上构建embedding进行语义召回。微信读书拥有百万级书籍原文数据,此外,对于用户导入书,更是达到亿级别规模。现有架构无论从成本还是耗时上都无法解决。
- 为了支持更多维度的召回,需要对UGC内容进行召回,部分UGC内容属于私密信息,并不向全网公开,只需要满足用户个人检索即可。此时如果用常规的检索系统构建常驻索引,访问率太低,成本难以收敛。
我们把数据划分成两类:全局公开可搜以及用户个人可搜。
对于全局公开可搜索的数据,如库内电子书的全文、书籍大纲、书评、人工知识库等,我们构建了一套入库流程,能对源信息进行语义分段、生成正排倒排,语义分段基于开源的chunk模型进行微调,正排基于fkv,倒排则基于ES构建,ES提供了DiskANN方案,通过设置合理的缓存和分片,能在存储成本和召回效率之间取得不错的平衡。对于App 内主搜等低时延场景,为了满足多种定制化检索需求,我们自建了基于内存索引的Searchsvr服务,支持索引落盘,可以在毫秒级返回电子书搜索结果。
对于用户个人数据,如导入书全文、个人想法等,特点是数据量大但使用频率不高,不需要针对全网用户进行检索,如果采用上述方案,会带来成本灾难,性价比极低。为此,我们按用户及物料的维度,基于USearch、Xapian等方案构建了向量及文本索引,这些组件的优势在于可以把单个索引存储成文件的形式,便于落盘,配合一些量化的方法,可以把大大压缩索引大小。在构建索引阶段,按用户+类型构建出不同的索引,并存储在低成本的COS上,当用户需要检索召回时,采用读时加载的方式实时进行召回,结合CFS进行预热可以大大提升检索速度。当检索完成后,定时淘汰策略会把长期不用的索引从CFS中清理,降低存储成本。
一、数据分类:全局公开 vs 用户私有
微信读书将数据划分为两大类型,采用完全不同的技术路线:
数据类型 | 典型场景 | 技术挑战 |
---|---|---|
全局公开数据 | 电子书全文/书评/知识库 | 高并发检索+语义理解 |
用户私有数据 | 导入书籍/个人笔记 | 低成本存储+动态加载 |
二、文本处理流水线
1. 语义分段:喂AI吃“书”
- 基于开源chunk模型微调,突破传统按规则分段的局限
- 支持段落级语义理解,使"红楼梦主要人物关系"能精准定位到相关章节
- 处理百万级书籍时,分段耗时从小时级优化至分钟级
2. 双索引构建
索引类型 | 技术方案 | 优化点 |
---|---|---|
正排索引 | 自研fkv存储 | 支持毫秒级文档内容获取 |
倒排索引 | ES+DiskANN | 存储成本降低40%,召回率提升15% |
三、检索方案设计
1. 全局数据
# 内存索引服务核心逻辑示例
class SearchSvr:
def __init__(self):
self.memory_index = LoadIndex() # 内存加载索引
self.disk_backup = DiskCache() # 落盘备份
def search(self, query):
# 毫秒级响应
return self.memory_index.search(query)
关键点:
- 内存索引+异步落盘
- 动态分片策略
- 热点数据预加载
2. 用户数据
关键点:
- USearch量化压缩:索引体积减少60%
- COS+CFS二级存储:存储成本降低75%
- 动态加载机制:冷启动延迟<200ms
四、总结RAG检索方案
首行文章链接-图6.1
微信读书的RAG检索方案,其核心点在于看重前端用户体验,设计分级索引架构,数据先通过IndexBuilder的“加工线”变成向量、分词等索引,存进COS仓库;当用户发起搜索时,RecallSvr同时从MemSearch(内存快查)、COS的不同货架(向量/分词/正排)、ES(专业检索)调取数据,综合排序后返回结果,达到高效和精准的目标。