Skip to content

RAG 深入:从关键词 Demo 到真实检索系统

问题场景

Demo 05 用关键词重叠模拟 RAG,能讲清楚「先检索、再生成」。但真实资料库会遇到更多问题:

  • 文档太长,chunk 切得不好会丢上下文。
  • embedding 维度和向量索引不匹配。
  • topK 太小漏资料,太大浪费上下文。
  • 向量相似度命中相关但不够精确。
  • 检索结果没有来源,回答无法验证。

Mastra RAG 文档把这些拆成文档处理、chunk、embedding、vector store、retrieval、rerank。

完整流程

mermaid
flowchart LR
  A[原始资料] --> B[MDocument]
  B --> C[chunk 策略]
  C --> D[embedding model]
  D --> E[vector store index]
  Q[用户问题] --> F[query embedding]
  F --> G[vector query topK]
  E --> G
  G --> H[metadata filter]
  H --> I[rerank]
  I --> J[context package]
  J --> K[Agent 回答 + 引用来源]

Chunk 策略怎么选

官方文档列出多种 chunk 策略:recursivecharactertokenmarkdownsemantic-markdownhtmljsonsentence 等。

资料类型推荐策略原因
普通文本recursive尽量按结构分割
Markdown 教程markdownsemantic-markdown保留标题层级
FAQ 或短句sentence保留句子完整性
JSON 配置json避免破坏结构
HTML 文档html按页面结构切分

chunk 参数不是越大越好。maxSize 太大,检索结果占满上下文;太小,答案缺前后文。overlap 能保留跨 chunk 的连续信息,但会增加存储和检索噪音。

Embedding 和向量库

官方文档提醒:向量索引维度必须和 embedding 模型输出维度一致。换模型时,不能直接复用旧 index。

ts
await store.createIndex({
  indexName: 'course_materials',
  dimension: 1536,
})

选择向量库时先看项目约束:

选择适合
libSQL vector本地开发、轻量教学
PostgreSQL + pgvector已有 PostgreSQL 的团队
Qdrant / Pinecone独立向量检索服务
MongoDB Atlas Vector Search资料已在 MongoDB
Cloudflare VectorizeEdge / Cloudflare 体系

Retrieval 和 rerank

初始 vector query 只解决「语义相似」。如果资料多或问题细,建议分两步:

  1. 先用向量检索取 topK = 10 或更多候选。
  2. 再用 rerank 选出真正要放进 prompt 的 topK = 35

Mastra RAG 文档提供 rerankWithScorer 方案。教学项目不默认接入 rerank,是为了保持离线可跑;生产替换时应保留 searchCourseTool 的输入输出,只替换内部实现。

RAG Tool 的输出结构

RAG Tool 不应该只返回纯文本。建议保留可验证来源:

ts
outputSchema: z.object({
  hits: z.array(
    z.object({
      id: z.string(),
      title: z.string(),
      excerpt: z.string(),
      source: z.string(),
      score: z.number(),
      metadata: z.record(z.string(), z.unknown()).optional(),
    }),
  ),
})

Agent instructions 应要求回答引用 titlesource,资料不足时明确说明不足。

Vibe coding 提示词

text
请把教学版 searchCourseTool 升级为真实 RAG 设计。
先不要直接改代码,先输出方案。
要求:
- 说明 chunk 策略、embedding 模型、vector store 选择。
- 说明 index dimension 如何确定。
- Tool 输入输出保持兼容。
- 输出 hits 必须包含 title、excerpt、source、score。
- 给出 ingestion 脚本和 query tool 的文件边界。
- 标明哪些步骤需要 API Key。

验证方式

验证项方法
chunk 不破坏标题关系抽样查看 chunk 文本和 metadata
向量维度正确createIndex 维度匹配 embedding 模型
查询可解释每个 hit 有 title/source/score
不相关问题不硬答低分或空命中时拒绝编造
rerank 有收益比较 rerank 前后 top3 是否更贴题

常见错误

错误后果修复
改 embedding 模型但不重建索引查询报错或结果异常删除并重建 index
chunk 没 metadata无法引用来源写入 title、url、section
topK 固定很大prompt 变长、成本上升按问题类型动态调整
RAG 结果直接拼成回答缺少模型整合把检索结果作为上下文交给 Agent

小练习

course-materials.ts 里的每条资料设计成可入库文档:写出 idtitlesectionsourcetextmetadata。再判断使用 recursive 还是 markdown chunk 策略。