RAG 完全指南:从一次"AI 把公司根本没有的制度讲得头头是道"看懂检索增强生成

2024 年我给公司做内部知识助手,让员工用自然语言问规章制度、报销流程,AI 直接给答案。第一版直接把问题发给大模型,Demo 惊艳,推广后反馈变味:它把一个我们公司根本不存在的"弹性工时制度"讲得有条有理,引用早已废止的旧报销流程,年假说法和 HR 手册完全对不上。我以为是模型不够聪明,换更大更贵的模型,照样编。盯着回答我才想明白:模型不是不够聪明,是没有资料——它的知识停在训练截止那一刻,只覆盖公开互联网,你公司的 HR 手册它一个字都没读过。要让 AI 准确回答"你自己的"问题,必须把相关资料喂给它,这就是 RAG。本文把 RAG 从头梳理。为什么需要:大模型有时间边界和范围边界,私有的、最新的信息它无从知晓,且面对不知道的事默认不沉默而是流畅地编。整体流程:索引(离线切块向量化)、检索(按相似度找资料)、生成(基于资料回答)三阶段。文档切分:整篇做检索向量太模糊,按固定字符数硬切会拦腰斩断句子,要沿语义边界切并让相邻 chunk 留重叠。向量检索:embedding 把文本映射成向量,语义相近的向量距离也近,用余弦相似度度量,问题和 chunk 必须用同一个模型向量化。拼 prompt:必须有强约束,只依据资料回答、资料没有就说没有,否则模型会掺入可能错误的常识。工程坑:只靠向量检索召回不够准要加 rerank 重排,检索最高分低于阈值要直接兜底答"资料中未提及"别硬答,对比/汇总型问题要靠元数据过滤和混合检索。核心一句:RAG 不是"搜一下再拿去问",而是一条切块、向量化、检索、重排、约束环环相扣的链路,任何一环偷懒它都会以"该检索的没检索到"或"检索到了还乱答"漏掉。

2024 年我给公司做一个内部知识助手——让员工能用自然语言问规章制度、产品文档、报销流程,AI 直接给答案。第一版做得很直接:把员工的问题原样发给大模型,等它回答。Demo 那天它答得特别流畅,产品经理很满意。可推广到部门里真用起来,反馈很快就变味了:有人问"我们公司年假怎么算",AI 给了一套听起来非常正规、却和我们 HR 手册完全对不上的说法;有人问报销流程,它讲的是一个我们公司早就废止的旧版本;最离谱的一次,它把一个我们公司根本不存在的"弹性工时制度"讲得有条有理,连申请步骤都编得像模像样。我一开始以为是模型不够聪明,想换个更大更贵的模型试试。换了,没用,它照样编。盯着这些回答我才终于想明白:模型不是"不够聪明",它是"没有资料"。大模型的知识,停在它训练数据截止的那一刻,而且只覆盖公开的互联网内容——我们公司的 HR 手册、内部流程文档,它从来没读过,一个字都没有。你问它公司的事,它不会说"我不知道",它会用最像那么回事的语气给你编一个出来——这就是幻觉。要让 AI 准确回答"你自己的"问题,光靠模型本身是不可能的,你必须想办法把相关的资料喂给它。这就是 RAG(Retrieval-Augmented Generation,检索增强生成)要做的事:回答之前,先从你的知识库里检索出相关资料,再把资料连同问题一起塞进 prompt,让模型基于这些资料来回答。我以为 RAG 不过是"先搜一下、再拿去问",结果真做下来,坑一个接一个冒出来:把整篇文档塞进去做检索,效果差到不可用;文档切块,切大了噪声多、切小了语义断;检索回来的明明是一堆不相关的段落;就算把对的资料喂给它了,它有时还是无视资料、继续编……那次之后我才认真把 RAG 从头搞明白。这篇文章就把它梳理一遍:为什么需要 RAG、它整体怎么转、文档怎么切、向量检索怎么做、资料怎么拼进 prompt,以及把 RAG 真正做准要避开的那些坑。

问题背景

先把那次的现象和我的误判讲清楚,后面所有的设计都是冲着纠正这个误判去的。

现象:内部知识助手直接用大模型回答公司问题,出现一连串幻觉——把根本不存在的制度讲得头头是道、引用早已废止的旧流程、答案与 HR 手册对不上。换用更大更贵的模型,问题依旧。

我当时的错误认知:"模型答错是因为不够聪明,换个更强的模型就好了;就算要喂资料,RAG 也无非就是把文档搜一下、再拿去问模型。"

真相:模型答错公司问题,根本不是智力问题,是它压根没有你的资料——它的知识停在训练截止那一刻,且只有公开内容。RAG 是把"私有的、最新的资料"补给模型的标准方法,但它真正的难点不在"搜一下"那一步,而在整条链路的每一环都会影响最终准度:文档怎么切成 chunk、怎么把"语义相似"变成可计算的"向量距离"、检索回来的结果怎么去噪重排、怎么约束模型老老实实只依据资料回答。任何一环偷懒,RAG 都会以"该检索的没检索到"或"检索到了模型还是乱答"的方式漏掉。

要把 RAG 做准,需要几块认知:

  • 为什么大模型答不了"你自己的"问题,RAG 到底补的是什么;
  • RAG 的整体流程——索引、检索、生成三个阶段;
  • 文档为什么不能整篇塞、也不能乱切,chunk 怎么切才对;
  • 怎么把"语义相似"变成"向量距离相近",向量检索怎么做;
  • 检索召回、重排、幻觉兜底这些工程坑怎么处理。

一、为什么需要 RAG:大模型的知识边界

先看清大模型不知道什么,才明白 RAG 是来补什么的。

大模型的知识来自训练。这意味着它有两条清晰的边界。第一,时间边界:它的知识停在训练数据截止的那一刻,那之后发生的事、更新的文档,它一概不知道。第二,范围边界:它训练用的是公开的互联网数据,你公司内网里的 HR 手册、产品 wiki、流程文档,从来不在它的训练集里。这两条边界一叠加,结论就很硬:任何"私有的"或"最新的"信息,模型本质上无从知晓。下面这段代码,就是直接拿一个它不可能知道的问题去问它:

from openai import OpenAI

client = OpenAI()

# 反面教材:直接拿大模型回答公司内部问题。
resp = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user",
               "content": "我们公司的年假是怎么规定的?"}],
)
print(resp.choices[0].message.content)

# 问题:模型的知识停在训练截止那一刻,它从没读过你公司的规章制度。
# 它【不会】说"我不知道",而会用最像那么回事的语气编一套出来 ——
# 这就是幻觉。模型缺的不是智力,是你公司的那份资料。

这里有个特别要命的细节:模型面对自己不知道的事,默认行为不是沉默或承认无知,而是用流畅的语言生成一个最可能的答案。它本质上是个"预测下一个词"的模型,"我不知道"这种回答在训练语料里出现得太少,所以它倾向于编一个完整、自信、看起来很专业的回答——这恰恰是最危险的,因为用户很难分辨它是答对了还是编得好。

既然问题是"模型没有资料",那解法就自然浮现了:在它回答之前,把资料给它。大模型有一个很强的能力——你在 prompt 里给它一段资料,它能基于这段资料来理解和回答问题。RAG 就是把这件事系统化:它不改造模型本身,而是在模型外面套一层"检索"——用户来问问题时,先去你的知识库里把相关资料找出来,塞进 prompt,模型于是从一个"凭记忆瞎答的人",变成一个"开卷答题、照着资料回答的人"。

二、RAG 的整体流程:索引、检索、生成

把 RAG 拆开看,它其实是三个阶段,理解了这三段,后面每一节的细节才有归属。

第一阶段是索引(Indexing),它离线发生、只做一次。你把知识库里所有文档拿出来,切成一小段一小段(chunk),给每一段算出一个能代表它语义的"向量",然后把这些"文本片段 + 向量"全部存进一个库里。这一步是在为后面的检索提前备料——它不在用户提问时发生,而是事先就准备好的。

第二阶段是检索(Retrieval),它在用户每次提问时发生。用户问了一个问题,你把这个问题也算成一个向量,拿它去索引库里比对,找出向量"最接近"的那几个文本片段——这几段,就是和用户问题语义上最相关的资料。

第三阶段是生成(Generation)。把上一步检索到的资料,连同用户的原始问题,一起拼成一个 prompt 发给大模型,并明确要求它"只依据这些资料回答"。模型于是给出一个有据可查的答案。

这三段里,"生成"那一步调用模型,反而是最简单的;真正决定 RAG 好不好用的,是前面"索引"和"检索"的质量——而它们的质量,又是从最底层一个看似不起眼的动作开始的:怎么把文档切块

三、文档切分:chunk 不是越大越好,也不是越小越好

为什么文档要切块,不能整篇直接用?两个原因。其一,模型的 prompt 长度有上限,你不可能把一本几十页的手册整个塞进去。其二,也是更关键的——检索的精度要求你切块。如果你拿"一整篇文档"去算一个向量,这个向量是这篇文档所有内容的"平均语义",非常模糊;用户问一个具体问题,根本匹配不上这个模糊的平均值。只有把文档切成话题集中的小片段,每段的向量才足够"聚焦",检索才能精准命中。

那直接按固定字符数硬切呢?这是新手最容易踩的坑:

# 反面教材:按固定字符数硬切,完全不管语义边界。
def naive_split(text: str, size: int = 500):
    return [text[i:i + size] for i in range(0, len(text), size)]

# 问题:一刀切下去,极可能把一句完整的话、一条完整的规定从中间劈开 ——
# "年假天数为" 留在了上一个 chunk,"10 天" 落到了下一个 chunk。
# 这样切出来的 chunk,语义是残缺的,拿去做向量检索准度大打折扣。

固定长度硬切的问题是它对语义完全无知:它不知道哪里是句号、哪里是段落结束,它只会数到 500 个字符就一刀下去,经常把一个完整的语义单元拦腰斩断。被斩断的两半,各自的向量都是残缺的,检索时谁也匹配不准。

正确的切分要做到两件事。第一,尊重语义边界——优先沿着段落、句子这些天然的分界去切,让每个 chunk 都是一个相对完整的意思。第二,让相邻 chunk 之间留一点重叠(overlap)——把上一个 chunk 结尾的一小段,也带到下一个 chunk 的开头。这样即使一个关键句恰好落在两个 chunk 的交界处,靠着这段重叠,它仍然能完整地出现在某一个 chunk 里:

def split_with_overlap(text: str, size: int = 500, overlap: int = 80):
    """按段落聚合成 chunk,并让相邻 chunk 重叠一段,避免语义被切断。"""
    paras = [p.strip() for p in text.split("\n") if p.strip()]
    chunks, buf = [], ""
    for para in paras:
        # 当前段落还能并进这个 chunk —— 累加上去
        if len(buf) + len(para) <= size:
            buf += para + "\n"
        else:
            if buf:
                chunks.append(buf.strip())
            # 新 chunk 的开头,带上上一块结尾的一小段,保住上下文不断裂
            tail = buf[-overlap:] if buf else ""
            buf = tail + para + "\n"
    if buf.strip():
        chunks.append(buf.strip())
    return chunks

chunk 的大小是个需要权衡的参数,它没有放之四海的最优值。切得太大,一个 chunk 里混进了好几个话题,它的向量又会变模糊,而且检索命中后塞进 prompt 的无关内容(噪声)也多;切得太小,一个完整的意思被拆得七零八落,每个 chunk 都只剩半句话,上下文严重不足。一般从几百字符起步,再根据你的文档类型(条款类的可以小些,叙述类的需要大些)去调。记住:chunk 的质量,是整个 RAG 准度的地基——地基这里切坏了,后面的向量检索再精妙也救不回来。

四、向量化与向量检索:把"语义相似"变成"距离相近"

chunk 切好了,接下来要解决一个核心问题:用户问"年假怎么算",知识库里的相关 chunk 写的可能是"员工带薪休假天数规定"——这两句话没有一个字相同,但意思高度相关。传统的关键词搜索在这里会失灵。RAG 靠的是语义检索,而语义检索的基石,是 embedding(向量化)

embedding 模型能把一段文本,映射成一个由几百上千个数字组成的向量。它的神奇之处在于:它训练出来的这个映射,会让语义相近的文本,落在向量空间里相近的位置。"年假怎么算"和"带薪休假天数规定"这两句话,字面毫不相同,但它们的向量会靠得很近。于是"判断两段文本意思像不像"这个模糊的语言问题,就被转化成了"计算两个向量的距离"这个精确的数学问题。索引阶段要做的,就是给每个 chunk 都算出并存下它的向量:

def embed(texts: list[str]) -> list[list[float]]:
    """把一批文本送进 embedding 模型,得到每段文本对应的语义向量。"""
    resp = client.embeddings.create(
        model="text-embedding-3-small",
        input=texts,
    )
    return [d.embedding for d in resp.data]


def build_index(chunks: list[str]) -> list[dict]:
    """索引阶段:把每个 chunk 连同它的向量一起存起来,供检索时比对。"""
    vectors = embed(chunks)
    return [{"text": c, "vector": v} for c, v in zip(chunks, vectors)]

有了索引,检索就清晰了:把用户的问题也用同一个 embedding 模型转成向量,然后逐一计算它和库里每个 chunk 向量的"接近程度",取最接近的几个。衡量两个向量接近程度,最常用的是余弦相似度——它度量两个向量方向的一致性,值越接近 1 表示语义越像:

import math


def cosine(a: list[float], b: list[float]) -> float:
    """余弦相似度:度量两个向量方向的一致性,越接近 1 语义越相近。"""
    dot = sum(x * y for x, y in zip(a, b))
    na = math.sqrt(sum(x * x for x in a))
    nb = math.sqrt(sum(y * y for y in b))
    return dot / (na * nb + 1e-9)


def search(index: list[dict], query: str, top_k: int = 3) -> list[dict]:
    """检索阶段:把问题向量化,按余弦相似度取最接近的 top_k 个 chunk。"""
    q_vec = embed([query])[0]
    scored = [{"text": item["text"], "score": cosine(q_vec, item["vector"])}
              for item in index]
    scored.sort(key=lambda x: x["score"], reverse=True)
    return scored[:top_k]

这里的 search 为了讲清原理,用的是"和每个 chunk 逐一比对"的暴力算法。chunk 少时这没问题,但知识库一旦有几十万段,每次提问都全量算一遍就太慢了。生产环境会用专门的向量数据库(如 Milvus、Qdrant、pgvector),它们用近似最近邻(ANN)算法,能在海量向量里飞快地找出最接近的几个——但其内核思想,和上面这段 cosine + 排序完全一样。还有一个极易忽略的点:问题和 chunk 必须用同一个 embedding 模型向量化,不同模型生成的向量空间不通用,混用等于拿两把不同的尺子量东西。

五、把检索结果拼进 Prompt:让模型基于资料回答

检索拿到了最相关的几个 chunk,最后一步是把它们和用户问题拼成 prompt。这一步看着简单,却藏着 RAG 成败的另一半——怎么拼,直接决定模型会不会老实

关键在于 prompt 里要有一句强约束:明确告诉模型"只准依据下面给的资料回答,资料里没有的,就说没有"。少了这句,模型很可能把你给的资料只当成参考,然后掺进自己训练时记下的"常识"一起作答——而它的常识,恰恰可能就是错的。下面这个 prompt 模板和拼装函数,核心就是那句约束:

RAG_PROMPT = """你是公司知识助手。请【只依据】下面提供的资料回答问题。
如果资料中没有相关信息,必须如实回答"资料中未提及",绝不允许自行编造。

【资料】
{context}

【问题】
{question}
"""


def build_prompt(question: str, chunks: list[dict]) -> str:
    # 把检索到的 chunk 拼成 context,并标上编号,方便模型在答案里引用
    context = "\n\n".join(
        f"[资料{i + 1}] {c['text']}" for i, c in enumerate(chunks))
    return RAG_PROMPT.format(context=context, question=question)

把三个阶段——检索、增强(拼 prompt)、生成——串成一个完整的函数,RAG 的主干就成型了:

def rag_answer(index: list[dict], question: str) -> str:
    # 1. 检索:从知识库里找出和问题最相关的几段资料
    hits = search(index, question, top_k=3)
    # 2. 增强:把资料拼进带强约束的 prompt
    prompt = build_prompt(question, hits)
    # 3. 生成:让模型【基于资料】回答,而不是凭记忆
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
    )
    return resp.choices[0].message.content

这个 rag_answer 就是文章开头那个问题的答案:它不再让模型凭记忆瞎答,而是先把公司真实的资料检索出来、塞进 prompt,模型于是"开卷答题"。但请注意——它能不能答对,完全押在 search 那一步检索得准不准上。如果检索回来的三段资料压根不相关,这个 prompt 就是在拿错误的资料逼模型作答,结果只会更糟。所以最后一节,全是关于怎么让检索这一环更稳。

六、工程坑:检索召回、重排、幻觉兜底

RAG 的主干通了,但要让它在真实知识库上准起来,还有几个绕不开的工程坑。

坑 1:只靠向量检索,召回不够准——要加一层重排(rerank)。embedding 向量检索速度快,但它的相似度判断比较"粗",有时排在前面的几条并不是真正最相关的。成熟的做法是两段式:第一段用向量检索宽召回,多捞一些候选(比如 20 条);第二段再用一个更强、更慢、但更准的 rerank 模型(交叉编码器),对这 20 条候选逐一精打分,取真正最相关的 3 条。召回阶段要"宁可错收、不可漏掉",精排阶段才"优中选优":

from sentence_transformers import CrossEncoder

# rerank 模型:交叉编码器,直接对(问题, 文档)整体打相关性分,
# 比向量检索的"各自向量算距离"更准 —— 代价是更慢,所以只用于精排。
reranker = CrossEncoder("BAAI/bge-reranker-base")


def search_with_rerank(index, query, recall_k=20, top_k=3):
    # 第一段:向量检索宽召回 —— 多捞候选,宁可错收不可漏掉
    candidates = search(index, query, top_k=recall_k)
    # 第二段:rerank 模型对每个候选精打分 —— 优中选优
    pairs = [[query, c["text"]] for c in candidates]
    scores = reranker.predict(pairs)
    for c, s in zip(candidates, scores):
        c["score"] = float(s)
    candidates.sort(key=lambda x: x["score"], reverse=True)
    return candidates[:top_k]

坑 2:检索不到相关资料时,要主动兜底,不能硬答。设想用户问了一个知识库里根本没有答案的问题。search 依然会返回 top_k 条——它只会返回"最接近的",哪怕最接近的也根本不相关。如果你把这几条不相关的资料照样塞进 prompt,模型就被架在了一个尴尬的位置上,很可能又开始编。解法是设一个相关度阈值:连最相关的那条得分都低于阈值,就说明知识库里确实没有,这时应当直接回答"资料中未提及",根本不要进入生成那一步。同时,把答案依据的资料编号附在后面,让回答可溯源、可核查:

def rag_answer_safe(index, question, min_score=0.35):
    hits = search_with_rerank(index, question, top_k=3)
    # 兜底一:连最相关的资料得分都过低 —— 知识库里确实没有,别硬答
    if not hits or hits[0]["score"] < min_score:
        return "资料中未提及该问题,建议咨询相关部门。"
    prompt = build_prompt(question, hits)
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
    )
    answer = resp.choices[0].message.content
    # 兜底二:把这次依据的资料编号附在答案后,让回答可溯源、可核查
    sources = "、".join(f"[资料{i + 1}]" for i in range(len(hits)))
    return f"{answer}\n\n(依据:{sources})"

坑 3:有些问题,向量检索天然抓不准。比如对比型问题("A 方案和 B 方案有什么不同")、汇总型问题("一共有几类假期")、或者答案散落在多篇文档里的问题——这类问题的"答案",并不集中在某一两个 chunk 里,单纯的向量检索很难一次命中。这没有银弹,但有几个常用手段:给 chunk 打上元数据标签(文档来源、日期、分类),检索时先按元数据过滤再算相似度,能挡掉大量噪声、也能天然排除掉那些"过期"的旧文档;对复杂问题,先让模型把它拆成几个子问题分别检索;以及把向量检索和传统关键词检索混合使用(hybrid search),让精确的词和模糊的语义互补。下面这张图,把 RAG 从离线索引到在线问答的完整链路串起来:

关键概念速查

概念 / 手段 说明
RAG 回答前先从知识库检索相关资料,再塞进 prompt 让模型基于资料作答
知识边界 模型只知训练截止前的公开知识,你的私有 / 最新文档它从未读过
三阶段 索引(离线切块向量化)、检索(按相似度找资料)、生成(基于资料回答)
chunk 切分 沿语义边界切、相邻块留重叠,别按固定字符数硬切断句子
embedding 把文本映射成向量,语义相近的文本向量距离也相近
余弦相似度 度量两向量方向一致性,越接近 1 语义越相关
向量数据库 用近似最近邻算法在海量向量里快速检索,内核同 cosine + 排序
召回与重排 向量检索宽召回候选,再用 rerank 模型精排取最相关的几条
prompt 强约束 明确要求模型只依据资料回答,资料没有就说没有,压制幻觉
相关度阈值 最高分低于阈值就直接答"资料中未提及",不进入生成

避坑清单

  1. 模型答错"你公司的问题"不是智力问题,是它没有你的资料;换更大的模型无效,要补的是资料不是参数。
  2. 模型面对不知道的事默认不沉默而是流畅地编一个,幻觉最危险之处在于它自信、专业、难以分辨真假。
  3. RAG 是索引、检索、生成三阶段;调模型那步最简单,决定成败的是索引与检索的质量。
  4. 文档不能整篇做检索——整篇的向量是模糊的平均语义,必须切成话题集中的小 chunk。
  5. chunk 别按固定字符数硬切,会拦腰斩断句子;要沿段落 / 句子边界切,并让相邻 chunk 留一段重叠。
  6. chunk 太大向量模糊、噪声多,太小语义残缺、上下文不足;从几百字符起步按文档类型调。
  7. 问题和 chunk 必须用同一个 embedding 模型向量化,不同模型的向量空间不通用,混用必错。
  8. prompt 里必须有强约束:只依据资料回答、资料没有就说没有,否则模型会掺入可能错误的"常识"。
  9. 只靠向量检索召回不够准,要加 rerank:向量检索宽召回候选,再用交叉编码器精排取 top-k。
  10. 检索最高相关分低于阈值时直接答"资料中未提及",别拿不相关资料硬逼模型作答;答案附资料编号便于溯源。

总结

回头看那个把不存在的制度讲得头头是道的内部助手,以及我后来在 RAG 这条路上接连踩的坑,最该记住的不是某一段向量检索代码,而是我动手前那两个想当然的判断。第一个是"模型答错是因为不够聪明"——错了,它答错是因为没有资料,你公司的文档它一个字都没读过,再聪明的模型也变不出它没见过的信息。第二个是"RAG 就是搜一下再拿去问"——也错了,RAG 是一条有好几个环节的链路,搜只是其中一环,而且是被前面"切块、向量化"和后面"重排、约束"共同决定的一环。

所以做 RAG,真正的工程量根本不在"调用大模型"那一下。embeddings.createchat.completions.create 谁都会写,Demo 里它也确实能像模像样地开卷答题。真正的工程量在这两个调用之间:文档怎么切,切坏了向量就是模糊的;向量怎么检索,检索偏了喂进去的就是错资料;检索回来怎么重排,不排序前几条可能全是噪声;prompt 怎么约束,不约束模型照样无视资料去编;检索不到怎么兜底,不兜底它就硬着头皮答。这篇文章的几节,其实就是顺着 RAG 这条链路一环一环展开的:先想清楚它补的是"资料"而非"智力",再看索引、检索、生成三阶段,然后是切块这个地基、向量检索这个核心,最后是重排和幻觉兜底这几个把它真正做准的工程细节。

你会发现,RAG 的思路和我们做任何"问答系统"的工程经验都是相通的。一个负责任的人回答专业问题,不会全凭脑子里的记忆张口就来,他会先去翻手册、查文档、找最新的规定,然后照着资料回答,资料里没有的就老实说"我得再查查"。RAG 做的,正是把这套"先查证、再回答、查不到就承认"的严谨,装到了大模型身上。大模型负责的是它最擅长的——理解问题、组织语言;而"答案的依据"从哪来、对不对、新不新,这件事的责任,从来都在你搭的这条检索链路上。

最后想说,RAG 做没做扎实,差距永远不会在 Demo 里暴露——Demo 里你问的都是知识库里明明白白写着、一句话就能命中的问题,怎么切、怎么检索都答得漂亮。它只在真实用户五花八门的提问面前才显形:那些换了说法的问题、那些答案散落在多篇文档里的问题、那些知识库里压根没有的问题。那时候它会用最难堪的方式给你结账——把一个废止的旧流程当成现行规定讲给员工,或者把一个根本不存在的制度编得有鼻子有眼。所以别等员工拿着错误的答案去做了错误的事再来找你,在你切下第一个 chunk 的时候就该想清楚:这个 chunk 的语义完整吗?检索偏了我重排了吗?知识库里没有时我兜底了吗?模型想编时我约束住它了吗?这几个问题都有了答案,你的 RAG 才不只是 Demo 里那个对答如流的演示,而是一个真正"言之有据"、可以放心交给员工去用的知识助手。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

限流算法完全指南:从一次"促销把数据库打挂"看懂固定窗口、滑动窗口、令牌桶

2026-5-21 18:59:43

技术教程

接口幂等性完全指南:从一次"网络抖动让用户被扣了两次款"看懂幂等设计

2026-5-21 19:13:55

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索