Retrieval-augmented generation 通常以一张简洁的示意图开场:
documents -> embeddings -> vector database -> LLM
Enter fullscreen mode Exit fullscreen mode
这是一条有用的起点,但它可能会把架构中的一小部分误当作整个系统。
优秀的 RAG 数据库设计需要覆盖的远不止向量存储。
一个生产级的 RAG 应用可能还需要存储原始文档、强制租户隔离、精确匹配产品名称、按日期过滤、记住对话、失效过时内容、组合多个数据源,并将最终 prompt 控制在 token 预算内。
仅仅因为存储了 embedding,数据库并不会自动变成“RAG 数据库”。不同的数据库模型解决检索的不同环节。
本文将探讨关系数据库、文档数据库、缓存、全文搜索引擎和向量数据库在 RAG 中的角色。随后再讨论一个仅靠相似度难以表达的检索难题:当应用已知中心、却不知答案确切边界时,如何找到有用的上下文邻域。
在实际的 AI 用例中,这一模式出现在客户支持、销售效率工具、内部知识助手、AI 编程自动化以及 AI Agent 开发中。同样的问题也适用于基于内部数据的 AI 助手开发——此时访问控制和数据新鲜度与生成答案同样重要。
RAG 的工作原理及其与微调的区别
RAG 在收到请求时检索外部信息,再把选定的证据放入模型上下文。微调则改变模型权重。因此,RAG 与微调的实际区别在于知识何时、何地被引入。
由于知识保存在模型外部,RAG 通常更容易更新、引用、过滤或移除。微调可以改变行为、风格或学习到的模式,但它并不是频繁变化的文档存储的便捷替代方案。
RAG 的主要优缺点由此分离而来:RAG 可以使用最新、私有数据源而无需重新训练模型,但它增加了摄取、检索、权限、评估、延迟和运维工作。仅理解 AI 生成原理并不足够:一个流畅的模型仍可能基于弱旧或未授权的证据作答。
数据库类型与如何构建 RAG
一个更完整的 RAG 流水线如下:
source data
-> ingestion and normalization
-> document and metadata storage
-> candidate selection
-> lexical or vector ranking
-> reranking and context assembly
-> LLM
-> answer and citations
Enter fullscreen mode Exit fullscreen mode
数据库可在多个阶段参与。
| Responsibility | Typical data |
|---|---|
| Source of truth | Documents, records, revisions, users, permissions |
| Ingestion state | Jobs, checksums, parser versions, failures |
| Exact filtering | Tenant, category, status, language, date |
| Lexical retrieval | Keywords, names, identifiers, error codes |
| Semantic retrieval | Embeddings and similarity scores |
| Session state | Recent messages, selected sources, cached results |
| Context assembly | Related records, projections, token-bounded payloads |
一个数据库可以承担其中多项职责。小型应用并不需要因为表格中有六行就使用六个数据库。关键在于在选择存储引擎之前先明确检索任务。有效的数据库比较应从这些任务出发,而非单纯的功能数量对比。
团队在研究如何构建 RAG 时,往往从 embedding 模型或 RAG 向量数据库入手。更安全的顺序是先确定真实来源、访问规则、更新流程、精确过滤、候选检索方法和评估计划。向量索引只是该设计中的一个组件。
为了具体化差异,我们假设正在构建一个京都旅行助手。它存储关于地标、餐厅、文化设施、活动、交通、营业时间、预订以及用户行程的信息。
PostgreSQL 与 MySQL:结构化真相与精确关系
关系数据库通常是保存 RAG 系统权威应用状态最不意外的选择。
对于旅行助手,关系数据库可以存储:
- 用户与账号;
- 预订与预约;
- 收藏地点与行程;
- 租户或组织边界;
- 文档版本与摄取状态;
- 权限与可见性规则;
- 结构化的营业时间与无障碍字段。
当正确性依赖于精确关系时,SQL 尤其有用。如果私人行程仅属于某一用户,或文档不得跨越租户边界,该规则不应依赖 embedding 分数。
关系查询可以先选出允许的 document ID,RAG 流水线随后仅对这些文档进行排序。
SELECT document_id
FROM travel_documents
WHERE city = 'Kyoto'
AND language = 'en'
AND published = true
AND valid_from <= CURRENT_TIMESTAMP
AND valid_until > CURRENT_TIMESTAMP;
Enter fullscreen mode Exit fullscreen mode
PostgreSQL 还支持 JSON、全文搜索和扩展。pgvector 扩展可以将向量与关系数据并存,这通常足以支撑早期或中等规模的 RAG 应用。
重要的是:添加向量列并不会消除设计权限、文档生命周期、元数据、候选选择和 prompt 构建的需求。
MongoDB 与文档数据库:灵活的内容记录
当摄取项已呈现为 JSON 对象,且不同类型拥有不同字段时,文档数据库是自然的选择。
地标记录可能包含历史、图片、坐标和营业时间。餐厅可能包含菜系、价格区间、预订规则和饮食选项。活动可能包含开始时间、场馆、票务链接和天气政策。
{
"kind": "restaurant",
"name": "Example Cafe",
"area": "Higashiyama",
"cuisine": ["Japanese", "Cafe"],
"features": {
"indoor": true,
"vegetarianOptions": true
}
}
Enter fullscreen mode Exit fullscreen mode
MongoDB documents 可以 表示这种结构,而无需将每种类型强制放入同一列。元数据与源文本可以共存,嵌套字段在已知访问模式时也可以被索引。
然而,灵活性并不消除检索设计。应用仍需决定哪些集合、字段、过滤器和记录应成为模型的候选。
经典的 RDB 与 NoSQL 差异在此依然重要。关系系统以精确关系和约束为中心;文档数据库以灵活的记录形状和面向聚合的访问为中心。对于业务系统,NoSQL 数据库选型应考虑一致性、授权、运维技能、备份和迁移,而不仅仅是传入数据是否为 JSON。
Redis:短生命周期状态与重复工作
即使不是主文档存储,Redis 在 RAG 场景中也很有用。
常见用途包括:
- 对话会话状态;
- 缓存的检索结果;
- 速率限制;
- 短生命周期 Agent 状态;
- 任务队列;
- 去重键;
- 频繁重用的上下文片段。
若许多用户对同一景点提出相似问题,缓存已验证的检索结果可能比再次运行完整流水线更省成本。
Redis 支持持久化和多种数据结构,但缓存仍需失效策略。旅行信息使这一点显而易见:关于活动、临时关闭或营业时间的答案即使在缓存文本内部一致,也可能已过时。
Redis 文档
将其描述为远不止简单的键值缓存,但在 RAG 架构中的角色仍应被明确选择。
OpenSearch:词语、字段与过滤器依然重要
embedding 搜索并非全文搜索的替代品。
用户会搜索精确的地名、线路、产品代码、法律术语、错误消息和引号短语。模型可能会为相关文本生成相似的 embedding,但精确标识符通常仍需要词法匹配。
OpenSearch 可组合:
- 全文查询;
- BM25 风格的词法相关性;
- 字段过滤;
- 聚合;
- 地理查询;
- 向量搜索;
- 面向搜索的仪表板与运维工具。
对于旅行助手,它可以回答如下问题:
Find pages containing "Kiyomizu-dera" in English,
published in the Kyoto corpus, with an opening-hours field updated this month.
Enter fullscreen mode Exit fullscreen mode
该查询包含精确文本、元数据和新鮮度要求。这些信号不应被简化为单一向量距离。
OpenSearch 文档
涵盖词法与面向向量的搜索,使其成为需要同时支持这两种检索模式的潜在单引擎选择。
Qdrant 与向量数据库:语义相似度
向量数据库围绕一个不同的问题设计:
Which stored items are closest to this query in embedding space?
当用户与文档不共享相同词汇时,这很有价值。
例如,访客可能问:
Where can I spend a quiet indoor afternoon learning about local history?
Enter fullscreen mode Exit fullscreen mode
有用的博物馆描述可能不包含该确切句子。语义检索仍可将其纳入候选集。
Qdrant 存储带 payload 元数据的向量,并支持带过滤的相似度搜索。典型请求先限制合格点,再按向量距离对剩余点排序。
metadata filter
-> approximate nearest-neighbor search
-> top candidates
-> optional reranker
-> LLM context
Enter fullscreen mode Exit fullscreen mode
这是一种有效模式,但留下一个架构问题:应用如何在相似度排序开始前决定正确的过滤器和搜索命名空间?
向量数据库的相似度搜索算法、索引类型、过滤行为、内存使用和更新模式都会影响结果。RAG 向量数据库对比(Pinecone、Qdrant、pgvector 或 OpenSearch)应使用应用自身语料和过滤器进行。推荐向量数据库的列表无法替代针对工作负载的评估。
RAG 混合搜索:BM25、向量与重排序
关键词与语义检索是互补的。RAG 混合搜索流水线可结合 BM25 与向量分数,使精确名称和标识符保持可见,同时仍能发现语义相关的文档。
metadata and permission filters
-> BM25 lexical candidates
+ vector similarity candidates
-> merge and deduplicate
-> reranker
-> token-bounded context
Enter fullscreen mode Exit fullscreen mode
对于提升 RAG 准确率,重排序集成通常比单纯增加第一阶段结果数量更有用。重排序器可更仔细地检查小型候选集,而第一阶段仍以召回率优化。
RAG chunk size 优化技术也很重要。小块可提升匹配精度但可能丢失上下文;大块保留上下文但消耗更多 token 并可能稀释相关性。合适的块大小取决于文档结构、检索方法以及需要被引用的单元。
LangChain 和 LlamaIndex 等 RAG 框架可连接加载器、embedding、retriever 和模型。LangChain RAG 设置示例可展示接线,但框架无法为应用决定正确的授权边界、新鲜度规则或候选范围。
内部搜索的开源 RAG 设置可结合 PostgreSQL、OpenSearch 或 Qdrant、本地模型以及编排框架。自托管改变了运维和隐私边界,但并未消除相同的检索与评估决策需求。
RAG 准确率提升与评估指标
检索质量与答案质量应分开衡量。实用的 RAG 评估指标包括:
- recall 和 precision at
k; - mean reciprocal rank 或 nDCG;
- context relevance 和 context precision;
- groundedness 或 faithfulness;
- citation correctness;
- answer completeness;
- retrieved tokens、latency 和 cost per request。
Ragas 等工具可帮助自动化评估的部分工作,但任何 RAG 评估工具或教程都无法为每个业务流程定义正确的预期答案。来自真实问题的小型人工审核测试集仍然有价值。
RAG 幻觉预防措施应不止于添加更多文档。更强的措施包括当前来源、显式引用、权限检查、冲突检测、弃权选项,以及针对知识库中不存在答案的问题的测试。
RAG 知识库自动更新也需要版本控制和失效策略。流水线应知道哪个源修订产生了 chunk、何时必须重建 embedding,以及已删除或过期信息如何离开缓存和索引。
RAG 安全措施与实施成本
RAG 安全措施始于检索之前。租户隔离、源授权、秘密移除、加密、审计轨迹以及针对检索文档中 prompt 注入的防御都应纳入设计。即使数据库被描述为 AI 组件,通用的数据库安全措施依然适用。
组织可能还需要使数据的收集与使用符合隐私规则、行业义务、AI 法律监管以及自身 AI 伦理准则。检索使数据对模型可用;它并不创造使用该数据的权限。
完整的 RAG 成本对比包括摄取、embedding 生成、数据库存储、缓存、网络传输、重排序、LLM 输入 token、监控、备份和工程时间。对于小企业,平均 AI 实施成本不能仅从模型 API 价格推断。
RAG 成本降低与 token 节省与候选范围密切相关。
通过检索和重排序传递更少无关记录,可同时减少数据库工作和 LLM 输入。对于本地部署,本地 LLM 设置和 PC 要求是单独的容量决策,但更小的检索上下文仍可降低下游内存和计算压力。
许多 AI 实施失败是因为 demo 仅在少数成功问题上被评估。当系统也能处理过时数据、缺失答案、访问边界、成本限制和故障恢复时,实际的 AI 实施收益才会显现。
困难的部分往往是候选范围
考虑这个问题:
I am at Kiyomizu-dera. It is raining, and I have two hours. What should I do
next?
几种检索方法都可以提供帮助:
- 词法搜索可找到提及 Kiyomizu-dera 的页面;
- 地理搜索可找到半径范围内的坐标;
- 向量搜索可找到语义相似的旅行建议;
- SQL 可强制执行营业时间、权限和预订约束;
- 重排序器可对结果候选重新排序。
挑战不在于其中任何一种方法不好。挑战在于决定哪些内容应进入候选集。
有用的答案可能需要:
- 附近地标;
- 室内博物馆或画廊;
- 当前营业的餐厅;
- 今日举办的临时活动;
- 交通信息;
- 无障碍信息;
- 用户行程中已存在的地点。
应用已知中心:访客、Kiyomizu-dera、当前日期和当前情况。它尚不知道有用答案的确切边界。
语义相似度并非运维相关性
语义最相似的文档不一定是当前请求最有用的文档。
一篇关于另一座日本寺庙的精美文章可能在 embedding 空间中接近,但在两小时内无法使用。一条简短的交通通知可能在语义上远离旅游问题,但对答案至关重要。餐厅记录可能几乎不包含用户请求中的任何词,但因其附近、营业且与行程兼容而相关。
RAG 系统通常用元数据过滤器解决此问题:
{
"city": "Kyoto",
"area": "Higashiyama",
"openNow": true,
"weather": "rain",
"categories": ["restaurant", "museum", "landmark"]
}
Enter fullscreen mode Exit fullscreen mode
这很合理。但随着产品增长,过滤器会变成应用级检索计划。必须有人维护为每个请求重建上下文所需的规则、命名空间、连接和扇出读取。
地理距离也不是完整的边界
如果问题仅仅是“1 公里内有什么?”,PostGIS 或 OpenSearch 地理搜索等地理索引是直接解决方案。
然而,有用的旅行上下文并不总是圆形。
- 河流、山丘或铁路可能使两个近点不便到达。
- 下雨会改变哪些设施有用。
- 家庭与独自旅行者可能需要不同邻域。
- 营业时间和活动日期改变可用上下文。
- “雨天京都”等编辑分组不是地理区域。
- 一个地点可同时属于区域指南、车站指南和个人行程。
距离仍然是重要信号。它只是不是定义视野的唯一关系。
应用持续重建上下文
传统技术栈可以解决此问题。它可能使用 SQL 连接、地理索引、搜索过滤器、图、应用维护的 ID 列表和向量排序。
重复的工作是重建相同的 locality:
start from the current place
-> identify the area
-> find allowed categories
-> join today's events
-> add relevant transit
-> add itinerary items
-> build candidates
-> rank candidates
Enter fullscreen mode Exit fullscreen mode
这里缺少的操作不是另一个打分算法,而是一种可复用的方式来回答这个更早的问题:
What belongs in the neighborhood of this known center for this kind of
request?
将可复用邻域视为数据
一种设计选择是将该邻域存储起来,而不是每次请求都从头重建。
这并不自动需要新数据库。应用可以使用 SQL 连接表、图边、物化视图、搜索文档或维护的 ID 列表来建模该关系。重要的概念转变是:候选范围成为具有自身生命周期的数据,而不是在排序前临时组装的查询逻辑。
对于旅游示例,可复用邻域需要几个属性:
- 每个地点应保留一条规范记录;
- 同一地点应能出现在多个上下文中;
- 将地点添加到指南不应复制其 payload;
- 读取应受类别、深度、过滤器、限制和 token 成本约束;
- 在邻域选定后仍应可进行词法或向量排序。
如果这种关系是偶发的,应用代码可能已足够。如果同一模式在用户、地点、项目、产品或时间窗口中反复出现,则将 locality 作为一等检索原语可能很有用。
KoutenDB 如何表示这种检索模式
KoutenDB 是围绕该模式设计的一种数据库。它使用类坐标的 ring 放置规范记录,并使用 stellar 可见性透镜在这些坐标上创建可复用视图。
导入器或应用可将旅游数据保存在规范 ring 中:
landmarks/kyoto/kiyomizudera
landmarks/kyoto/yasaka-pagoda
restaurants/kyoto/gion
culture/kyoto/national-museum
events/kyoto/2026-07-23
transit/kyoto/higashiyama
Enter fullscreen mode Exit fullscreen mode
然后可将有用坐标附加到以区域为中心的视图:
kouten stellar attach \
--stellar=travel/kyoto/higashiyama \
--ring=landmarks/kyoto/kiyomizudera
kouten stellar attach \
--stellar=travel/kyoto/higashiyama \
--ring=restaurants/kyoto/gion
kouten stellar attach \
--stellar=travel/kyoto/higashiyama \
--ring=culture/kyoto/national-museum
kouten stellar attach \
--stellar=travel/kyoto/higashiyama \
--ring=events/kyoto/2026-07-23
Enter fullscreen mode Exit fullscreen mode
应用可从已知中心读取周围上下文:
kouten get --stellar=travel/kyoto/higashiyama
Enter fullscreen mode Exit fullscreen mode
或将同一视野缩小到某一类别:
kouten get --stellar=travel/kyoto/higashiyama --subring=restaurants
kouten get --stellar=travel/kyoto/higashiyama --subring=culture
Enter fullscreen mode Exit fullscreen mode
同一餐厅也可通过雨天指南、车站为中心指南或用户行程可见,而无需复制其规范 payload。
KoutenDB 不会从路径名推断地理或编辑相关性。
应用、导入器或策展流程仍需决定哪些坐标属于每个邻域。数据库保留该决策,以便后续读取无需从头重建。
这不仅仅是路径前缀
ring 名称故意看起来像可读路径。当父子数据自然属于一起时,层级很有用。
然而,路径前缀本身仅表示一棵树。真实记录同时参与多个视图:
canonical catalog: restaurants/kyoto/gion/example-cafe
area guide: travel/kyoto/higashiyama
weather guide: travel/kyoto/rainy-day
personal plan: travel/users/123/today
Enter fullscreen mode Exit fullscreen mode
在每条路径下复制餐厅会产生同步工作。将其移动到一条路径会削弱其他视图。stellar 透镜则在现有坐标上存储可见性关系。
调用方提供中心和成本边界。深度、分支预算、subring、过滤器、投影、排序和限制控制返回多少上下文。调用方无需枚举答案中的每条记录。
Locality 可先于向量排序
Locality-aware 检索与向量搜索并不互斥。
组合流水线可如下:
known center: user + place + time
-> retrieve the configured local neighborhood
-> apply current constraints
-> vector-rank the smaller candidate set if needed
-> rerank and enforce a token budget
-> LLM
Enter fullscreen mode Exit fullscreen mode
向量数据库询问哪些候选在语义上接近。locality 层询问数据中哪些部分应首先被考虑。
这可减少加载的 payload 数量、比较的向量数量、重排序的记录数量、传输的字节数以及下游考虑的 token 数量。它并不保证每个查询都更快。只有当应用能够表达有意义的 locality 时,该模型才有用。
将数据库与检索问题匹配
当从问题而非当前 RAG 趋势出发时,数据库决策会变得更清晰。
| Retrieval question | Natural starting point |
|---|---|
| Which exact record or relationship is valid? | Relational query and indexes |
| Which JSON documents match known fields? | Document database or SQL/JSON |
| Which result can be reused briefly? | Cache or session store |
| Which documents contain these words? | Full-text search engine |
| Which documents are semantically similar? | Vector search |
| Which places are inside a literal radius? | Geographic index |
| Which context is useful around this known user, place, project, or time? | Locality-aware neighborhood retrieval |
这些并非互斥选择。PostgreSQL 可保留真实来源,OpenSearch 处理词法检索。向量数据库可对语义相似的 chunk 排序。KoutenDB 可作为 locality-aware 文档与检索存储,或作为更早的候选选择阶段。
较小的系统可选择覆盖足够角色的单一数据库。较大的系统可将其分离。只有当它解决了经过测量的检索、正确性或运维问题时,额外基础设施才合理。
因此,RAG 的实用数据库设计步骤是:
- 识别权威来源和更新所有者;
- 定义租户、用户和文档访问边界;
- 列出精确、词法、语义、地理和 locality-aware 查询;
- 选择覆盖这些查询的最小数据库类型集合;
- 衡量检索质量、token、延迟和失败案例;
- 记录无法重建数据的数据库备份方法和数据库迁移步骤;
- 仅在候选和访问模型正确后才进行数据库性能调优。
最终问题是应用已知什么
RAG 架构通常从询问使用哪个 embedding 模型或向量数据库开始。
另一个有用的先决问题是:
What does the application already know before retrieval begins?
它可能已经知道已认证用户、租户、订单、项目、文档组、当前位置、时间窗口或活动任务。这些信息可以定义一个比完整语料库小得多、也更相关的起始区域。
如果请求以无有意义中心开始,全局词法或向量搜索可能完全正确。如果请求以已知中心但不确定上下文边界开始,保留 locality 可在排序和 prompt 构建开始前保持更小的检索问题。
重要的选择不是 SQL 还是向量,也不是一个数据库产品还是另一个。而是决定应用需要精确真相、词法匹配、语义相似度、地理邻近还是可复用的上下文邻域——然后为每个检索阶段提供它实际需要的数据模型。
这是 RAG 数据库设计能够超越 demo 的基础。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.