流水线

RAG 分成 索引(离线)查询(在线)。索引把文档变成可检索的向量;查询把问题变成向量,取出块,可选重排,再交给 LLM。

官方-ish 的一条链是:

flowchart LR
  D[documents] --> C[chunk]
  C --> E[embed]
  E --> V[vector store]
  V --> R[retrieve]
  R --> RR[optional rerank]
  RR --> L[LLM]

查询时,用户问题走同一套 embed,再进入 retrieve。不要用聊天模型去「embed」。


两阶段分别做什么

阶段何时跑输入输出
Index文档变更时文件 / 表 / URL块 ID、原文、向量、元数据
Query每个用户问题问题字符串top-k 块 →(可选 rerank)→ 回答

索引可以批量、异步、夜间跑。查询要快:向量搜索是毫秒到几十毫秒;LLM 才是延迟大头。

flowchart TB
  subgraph offline [Index]
    D[documents] --> C[chunk]
    C --> E[embed]
    E --> V[vector store]
  end
  subgraph online [Query]
    Q[question] --> EQ[embed]
    EQ --> R[retrieve]
    V --> R
    R --> RR[optional rerank]
    RR --> P[prompt + context]
    P --> L[LLM]
  end

每一跳的职责

  1. documents — Markdown、PDF 文本层、数据库字段。先能 print 出纯文本,再谈检索。
  2. chunk — 切成语义完整、长度可控的块。见 切块
  3. embed — 块 → 向量。见 Embeddings
  4. vector store — 持久化并做近邻搜索:ChromapgvectorQdrant
  5. retrieve — 取 k 条;可加元数据过滤或关键词混合。
  6. optional rerank — 交叉编码器或规则,把「真相关」提前。见 检索与重排
  7. LLM — 提示词写明「只根据上下文;没有依据就说不知道」。

框架课里的 Loader / Splitter / Retriever 只是这七步的包装:LangChain RAGLlamaIndexDify 知识库


最小可运行草图(内存,无数据库)

把「切 → 嵌 → 搜 → 拼提示词」串起来。嵌入可换成 OpenAI 或 Ollama;向量库章节再把 store 换成磁盘或 Postgres。

from numpy import dot
from numpy.linalg import norm

def split(text: str, size: int = 80, overlap: int = 20) -> list[str]:
    chunks, i = [], 0
    while i < len(text):
        chunks.append(text[i : i + size])
        i += max(size - overlap, 1)
    return chunks

def fake_embed(s: str) -> list[float]:
    # 教学用:生产代码调用 embeddings 章的 API
    vowels = sum(s.lower().count(c) for c in "aeiou")
    return [float(len(s)), float(vowels), float(s.count("退"))]

def cos(a, b) -> float:
    return float(dot(a, b) / ((norm(a) * norm(b)) or 1.0))

raw = "退款须在到货 7 日内申请。客服在线 09:00–18:00。"
chunks = split(raw)
store = [(c, fake_embed(c)) for c in chunks]
q = fake_embed("多久能退款?")
top = sorted(store, key=lambda x: cos(q, x[1]), reverse=True)[:2]
context = "\n".join(c for c, _ in top)
prompt = f"只根据上下文回答。不知道就说不知道。\n\n{context}\n\n问题:多久能退款?"
print(prompt)

fake_embed 不能上线。它只证明数据流;真实向量来自 Embeddings


哪一跳最容易坏

症状先查
完全检不中嵌入模型是否一致;块是否切碎;语言是否中英混用未测
检中了但答非所问k 太小、缺 rerank、提示词没写「仅依据 context」
答案编造工号 / 数字评估章的忠实度检查;提示词禁止编造
很慢先看 LLM;向量库在万级文档内通常不是瓶颈

下一步

评论