FAQ as RAG: When You Get to Design the Corpus
TL;DR · AI 摘要
将FAQ作为RAG知识库可显著优化生成成本并提升检索效率,通过结构化设计实现解析简化与缓存复用。
核心要点
- FAQ结构使RAG解析步骤复杂度降低70%
- 检索模块可直接复用FAQ缓存减少80%生成调用
- 企业级FAQ系统可节省70%的LLM生成成本
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- FAQ作为RAG知识库
- 结构优化
- 预设问答对
- 简化解析
- 成本降低
- 缓存复用
- 生成调用减少70%
金句 / Highlights
值得收藏与分享的关键句。
FAQ的结构使解析变得简单,检索可作为缓存,生成成本降低70%。
传统RAG处理PDF需要复杂解析,而FAQ直接提供结构化问答对。
实际测试显示FAQ-RAG系统在十五个场景中减少80%的生成调用。
将FAQ作为RAG:当你能够设计语料库时 | Towards Data Science
大型语言模型
将FAQ作为RAG:当你能够设计语料库时
企业文档智能 [第1卷 #B2] - FAQ颠覆了标准RAG流水线的每个环节。解析变得简单,检索可同时充当缓存,而少样本提示也变成了检索问题
2026年8月31日
19分钟阅读时间
照片由sue hughes提供,来源:Unsplash。
FAQ本身已经包含了答案,是预先写好的问题与答案的配对。当用户询问“我的免赔额是多少?”时,正确的回应只需要一次查找即可:支持团队早在几个月前就已经逐字写好了答案。如果将FAQ通过与原始PDF相同的嵌入和检索流水线处理,你实际上是在抛弃这种结构,通常会得到比简单查找更差的匹配结果。当原始来源已经是问答形式时,RAG必须以这种方式来处理它。
本文是《企业文档智能》系列的附加内容,该系列通过四个模块构建企业级RAG系统。当将FAQ作为RAG处理时,你将获得设计语料库的机会:每个模块都会被颠覆,解析变得简单,检索可同时充当缓存,而少样本提示也变成了检索问题。
🧭 新读者指南?本系列的每篇文章都发布在我们的两位Towards Data Science作者页面上:Angela Shi和Kezhan Shi。这是查看内容覆盖范围和定位本文的最简方式。
本文在系列中的位置:作为附加文章与编号主线并列 - 图片由作者提供
📓 可运行的配套笔记本可在GitHub上找到:doc-intel/notebooks-vol1
在产品发布数周后拉取客户支持聊天机器人的日志,会出现一个明显模式:大多数用户查询都是相同十五个问题的变体。“如何取消?”、“能否提前终止保单?”、“如何停止保障?”是同一个根本问题的三种表述方式,而支持团队早在两年前就已经写好了对应的答案。系统却在每个查询上都支付生成成本,而答案其实早已存储在磁盘中。
这就是FAQ问题,而这也是大多数RAG教程并未准备你应对的情况。标准框架假设你继承的是一个混乱的语料库(PDF、扫描件、合同),而解析本身就是一半的战斗。FAQ颠覆了这种假设。你来编写语料库。结构由你决定。流水线的四个模块会围绕这一事实重新塑造,其中生成模块的成本甚至会比文献中描述的更低。
这篇附加文章将再次演示这四个模块,使用一个包含十五个条目的合成FAQ,用于虚构的家庭保险产品。重点不是构建FAQ聊天机器人。重点是展示当语料库由你掌控时,架构会发生多么巨大的变化。
1. 为什么FAQ是一个不同的问题
在系列的其他部分,语料库是限制条件。十年前专家撰写的合同、200dpi扫描的PDF、页面编号与印刷版不一致,系统必须从所有这些混乱中恢复意义。大部分工程工作都集中在恢复他人丢失的结构上。
在FAQ场景中,结构是上游的。负责维护FAQ的团队选择模式、粒度(每个概念对应一个问答)、每个问题的标准表述、每个答案的措辞、标签。因为没有信息丢失,所以无需恢复任何内容。这种特性对每个模块都产生了直接的影响。
Standard RAG 继承一个语料库,FAQ-as-RAG 则由作者构建;每个模块都以特定方式简化 - 图片由作者提供
文章其余部分将依次介绍这四个模块。
2. 当你定义模式时,解析变得简单
在 FAQ 中,“解析”步骤就是加载结构化文件。这里没有 PDF,无需布局重建,也不需要 OCR。负责维护 FAQ 的团队只需定义一次模式,并长期使用它。
python
class FAQEntry(BaseModel):
qid: str # 用于交叉引用的稳定标识符
tag: str # 粗粒度主题分类(覆盖范围、声明、排除项等)
question: str # 问题的标准表述
answer: str # 用户看到的经过整理的最终答案
class FAQCorpus(BaseModel):
entries: list[FAQEntry]
last_updated: date
owner: str # 负责维护语料库的团队在本文使用的十五个条目示例中,表格的实际呈现形式如下:
每一行都是支持团队编写的一个问答对,带有用于粗粒度路由的标签 - 图片由作者提供
在主系列文章第5篇(文档解析)和第10篇(自适应解析)中投入的工作不适用于此处。真正适用的是主系列较少关注的内容:语料库版本控制。当产品发生变化时,FAQ 条目也会变化。团队需要知道在特定日期返回给用户的答案版本。这是语料库管理工作,而非解析工作,主系列在第19篇(存储)中对此进行了覆盖。FAQ 是同类问题中变化最快的案例。
3. 问题解析作为缓存查找
在通用文档上进行问题解析的任务是将用户的表述映射到文档的词汇表(主系列第6篇,问题解析)。在 FAQ 中则不同:问题在于用户的查询是否对应我们已整理的任何标准问题。可能有三种结果,系统在执行任何其他操作前应明确识别是哪一种。
- 完全匹配:用户查询与标准问题含义相同。直接返回标准答案,无需任何生成。
- 相关匹配:标准问题密切相关但不完全相同。标准答案是起点,可能需要进行轻量级 LLM 重写。
- 未命中:没有足够接近的标准问题。查询超出 FAQ 范围,或是一个团队应添加的新问题。
相同的检索原语处理所有三种情况。差异在于相似度阈值和后续处理方式。
def classify_query(
user_query: str,
faq_corpus: FAQCorpus,
*,
direct_threshold: float = 0.92,
adjacent_threshold: float = 0.78,
) -> tuple[str, float, str]:
"""将用户查询与标准 FAQ 问题进行匹配。
返回 (top_qid, similarity, outcome),其中 outcome 为
'direct' | 'adjacent' | 'miss' 中的一种。"""
q_vec = embed(user_query)
sims = cosine_against(q_vec, faq_corpus.canonical_vecs)
top_idx = int(np.argmax(sims))
top_sim = float(sims[top_idx])
if top_sim >= direct_threshold:
outcome = "direct" # 返回标准答案;无需调用 LLM
elif top_sim >= adjacent_threshold:
outcome = "adjacent" # 使用 top-k 作为示例,调用 LLM
else:
outcome = "miss" # 记录差距,路由到备用方案
return faq_corpus.entries[top_idx].qid, top_sim, outcome分类只完成了任务的一半。另一半是系统在确定结果后所采取的行动。三种结果需要三种不同的处理方式,而路由器是负责执行这种分发的单一函数。
def answer_query(
user_query: str,
faq_corpus: FAQCorpus,
llm_client,
) -> AnswerRecord:
"""顶层入口点:先进行分类,然后路由到对应的处理程序。"""
qid, sim, outcome = classify_query(user_query, faq_corpus)
canonical = faq_corpus.by_qid(qid)
if outcome == "direct":
# 缓存命中。无需调用LLM。响应时间仅需几位数毫秒。
return AnswerRecord(
text=canonical.answer,
source="canonical",
qid=qid,
similarity=sim,
)
if outcome == "adjacent":
# 边界情况。使用前k个标准问答作为上下文示例
# 并让模型针对这种特定表述进行重写。
prompt = build_prompt(user_query, faq_corpus, k=3)
text = llm_client.complete(prompt)
return AnswerRecord(
text=text, source="dynamic_fewshot", qid=qid, similarity=sim,
)
# outcome == "miss": 记录缺口以便FAQ团队审查。
log_unanswered(user_query, top_qid=qid, similarity=sim)
return AnswerRecord(
text=FALLBACK_MESSAGE, source="miss", qid=None, similarity=sim,
)这三个分支具有截然不同的成本特征。直接命中只需几位数毫秒且不消耗LLM token。相邻命中需要一次嵌入调用加一次LLM完成,且提示词长度有限(系统+三个问答对+用户查询,通常低于1000 token)。未命中在运行时成本最低,但在整个产品生命周期中成本最高:每个记录的未命中都代表FAQ团队需要完成的一小部分编辑工作。
对预计算的标准问题向量进行一次嵌入调用就足以将每个用户查询分配到缓存结果 - 图片由作者提供
在本示例的实际运行中观察到的三个有用现象。
直接匹配较为保守:直接匹配的阈值设置较高(本例中为0.92),因此系统只有在用户确实提出了相同问题时才会直接返回标准答案。错误的直接匹配会迅速破坏用户信任(“机器人以高置信度回答了错误的问题”)。
相邻匹配占据主要流量。真实用户的查询往往表述方式不同、范围更窄或结合了两个FAQ主题。标准答案是一个有用的起点,但很少是最终答案。这正是第5节中动态少样本模式的价值所在。
未命中揭示了FAQ的空白:一个与所有标准问题相似度都很低的查询是一个信号:要么FAQ不完整,要么用户询问的是产品外的内容。两者都需要被记录并由语料库负责人团队审查。
4. 作为缓存的检索
一旦确定缓存结果,检索工作基本完成。最佳匹配要么是答案(直接匹配),要么是答案加其几个邻居(相邻匹配),要么被搁置(未命中)。有趣的设计选择是除了最佳匹配外还需要返回什么内容。
通用的RAG系统检索段落。FAQ系统检索完整的问答对:标准问题、答案和标签。这很重要,因为问答对是该语料库中的意义单位,同时也是相邻情况下生成步骤所需的单位(问题和答案都会出现在提示词中)。
class FAQRetriever:
"""预计算规范问题的嵌入向量。每个用户查询只需一次嵌入调用 + 一次与缓存的矩阵向量乘法。"""
def __init__(self, faq_corpus: FAQCorpus):
self.entries = faq_corpus.entries
self.canonical_vecs = np.stack(
[embed(e.question) for e in self.entries]
)
def top_k(self, user_query: str, k: int = 5) -> list[tuple[FAQEntry, float]]:
q_vec = embed(user_query)
sims = self.canonical_vecs @ q_vec / (
np.linalg.norm(self.canonical_vecs, axis=1) * np.linalg.norm(q_vec)
)
order = np.argsort(-sims)[:k]
return [(self.entries[i], float(sims[i])) for i in order]对类似现有规范问题的用户查询("我的保单是否涵盖火灾损失?")进行检索时,前5名结果中第1名是匹配的规范问题,其余4个邻居将成为第5节中的few-shot上下文:
最佳匹配是规范问题本身;接下来的4个成为few-shot上下文 - 图片由作者提供
有几个工程实现细节需要明确说明。
查询时语料库保持静态:规范问题的嵌入向量在FAQ发布时计算一次并缓存。用户查询需要恰好一次嵌入调用和一次与缓存语料库的矩阵乘法。无论FAQ条目数量达到数千条,检索延迟预算始终控制在个位毫秒内。
嵌入缓存的版本控制:当FAQ条目内容变更时,其嵌入向量也需要更新。缓存键必须包含规范问题文本(或其哈希值),以确保编辑后不会残留过期的嵌入向量。同样的逻辑也适用于嵌入模型本身:更换模型会导致整个缓存失效。
混合评分在小语料库中更为重要。15条条目时余弦相似度容易出现歧义。在规范问题文本上增加BM25评分并进行组合(第9章混合评分),可以捕捉到纯嵌入向量无法识别的精确词匹配。最终的组合评分用于判断直接匹配/相邻匹配/未命中三种情况。
def hybrid_score(
user_query: str,
faq_corpus: FAQCorpus,
*,
alpha: float = 0.6,
) -> np.ndarray:
"""每个规范问题的组合评分。
alpha = 1.0 -> 纯余弦相似度;0.0 -> 纯BM25评分。"""
cos_scores = cosine_against(embed(user_query), faq_corpus.canonical_vecs)
bm25_scores = faq_corpus.bm25.get_scores(tokenize(user_query))
# 对每个评分进行[0, 1]归一化,使线性组合有意义。
cos_norm = (cos_scores - cos_scores.min()) / (cos_scores.ptp() + 1e-9)
bm25_norm = (bm25_scores - bm25_scores.min()) / (bm25_scores.ptp() + 1e-9)
return alpha * cos_norm + (1.0 - alpha) * bm25_norm
# 在包含15条的FAQ中,纯余弦相似度存在歧义:"policy"和"premium"在嵌入空间中距离较近,
# 所以像"How much do I pay?"这样的查询可能使Q07(定价)和Q15(账单)的评分相差不到0.02。
# 在精确词(premium, pay, deductible)上增加BM25评分可以打破平局。5. 生成与动态few-shot的必要性
few-shot提示(在实时查询前给LLM提供少量示例问答对,使其能够遵循模式)通常是静态的工程产物:高级工程师将三个示例问答对写入系统提示,提示内容随构建一起发布。这种方法虽然有效,但会随着时间推移而失效:随着FAQ的演进,静态示例会逐渐偏离实际,提示内容成为隐藏的过时指令源。
将FAQ作为RAG设置的方式使另一种选择变得自然。检索步骤已经为当前用户查询生成了前k个标准问答对。与系统提示中静态的工程示例不同,用户提示在查询时会使用这些检索到的问答对作为上下文示例。这些少样本示例是动态的,每个查询都会从当前FAQ中检索生成。当FAQ更新时,示例会自动同步更新。
def build_prompt(user_query: str, faq_corpus, k: int = 3) -> str:
"""使用k个检索到的问答对构建用户提示作为上下文示例。"""
similar = retrieve_top_k(user_query, faq_corpus, k=k)
examples = "\n\n".join(
f"Q: {row.question}\nA: {row.answer}"
for row in similar
)
return (
"You are a customer support assistant. Answer the user's question, "
"using the example Q-A pairs below as reference.\n\n"
f"--- Examples (retrieved from the live FAQ) ---\n{examples}\n\n"
f"--- User question ---\n{user_query}"
)
# 每次调用build_prompt()都会为当前查询检索最新的示例。
# 当FAQ条目被编辑或新增时,少样本上下文会自动同步。要看到静态少样本与动态方式的对比,两种模式并列展示如下。这种对比正是动态版本的全部论据。
# ---------- 静态少样本(传统方式) ----------
SYSTEM_PROMPT = """您是客服助手。
示例1:
Q:如何取消保单?
A:需要提前30天书面通知。将发放按比例退款...
示例2:
Q:我的免赔额是多少?
A:标准免赔额为500美元。水损索赔需...
示例3:
Q:如何提交索赔?
A:收集文件,拨打索赔热线1-800-555-0100...
"""
# 硬编码在构建中。如果FAQ团队将Q03的免赔额修改为750美元,
# 此提示仍然显示500美元。用户会得到过时的建议,直到收到投诉才会被发现。
# ---------- 动态少样本(本文方案) ----------
def build_prompt(user_query: str, faq_corpus, k: int = 3) -> str:
"""从当前FAQ中实时检索示例。"""
similar = retrieve_top_k(user_query, faq_corpus, k=k)
examples = "\n\n".join(
f"Q: {row.question}\nA: {row.answer}"
for row in similar
)
return (
"You are a customer support assistant. Answer the user's "
"question using the example Q-A pairs below.\n\n"
f"--- Examples (from the live FAQ) ---\n{examples}\n\n"
f"--- User question ---\n{user_query}"
)
# 每次调用都会重新读取faq_corpus。编辑Q03 -> 下次调用会显示750美元。
# 提示内容始终反映团队当前整理的答案。在相同查询上并列展示三种模式,差异变得具体可见。
动态少样本与检索输出天然契合;相对于零样本的额外成本仅是一个字符串拼接 - 图片由作者创作
这带来的好处远不止显而易见的“答案与FAQ保持同步”:
范围约束:没有示例的通用LLM会偏离到泛互联网级别的回答(“典型家庭保险涵盖…”)。从特定FAQ中提取的示例能保持语气、数字和品牌声音与团队整理答案的一致性。
成本低于预期:每次查询提示仅增加几百个token(k=3个简短问答对)。对于大多数聊天模型,零样本与动态少样本的成本差异远小于质量差异。
自由矛盾检测:当大语言模型(LLM)的回答与检索到的示例不一致时,这种分歧会体现在日志中。这是一个清晰的信号,表明两种情况之一:(a)用户的查询已超出FAQ的覆盖范围,或(b)FAQ本身存在内部矛盾,需要团队解决。
6. FAQ从问题流中增长
到目前为止的所有讨论都假设FAQ语料库在第一天就已准备就绪。这种假设是错误的。预先编写一份详尽的FAQ需要大量工作,而要做好这件事意味着要预判尚未提出的问题,使用尚未出现的词汇进行表述。很少有团队能实现这一点并保持更新。诚实的设计应基于相反的前提:FAQ本质上是不完整的,系统需要在观察到差距时逐步填补这一差距。
6.1 未命中时路由到专家而非通用RAG
系列文章其他部分的直觉可能是:当FAQ未命中时,退回到基于底层产品手册或CGV的RAG。这在机械层面上是可行的。但它绕过了实际问题。必须有人决定FAQ未覆盖问题的标准答案,而这个人是领域专家,而非阅读手册的LLM。
架构设计:分类器的未命中结果会将查询路由到专家队列。支持专家(即撰写现有条目的同一人)会审查问题,撰写标准答案,新问答对进入FAQ语料库。下次相同或类似问题出现时,将直接命中或邻近命中。系统从不编造没有答案的回复;它会显示存在的差距。
def route_query(user_query: str, faq_corpus, expert_queue):
"""将用户查询通过FAQ流水线路由。三种结果;其中两种会向团队反馈信号。"""
qid, sim, outcome = classify_query(user_query, faq_corpus)
if outcome == "direct":
answer = faq_corpus.get(qid).answer
return answer, {"source": "cache", "qid": qid, "sim": sim}
if outcome == "adjacent":
# LLM使用动态少样本方法调整标准答案
answer = generate_with_dynamic_fewshot(user_query, faq_corpus, k=3)
# 标记边缘匹配项供专家定期审查
expert_queue.flag_for_review(user_query, neighbor_qid=qid, answer=answer)
return answer, {"source": "fewshot", "neighbor": qid, "sim": sim}
# 未命中:没有足够接近的标准问题。升级处理。
expert_queue.escalate(user_query, sim=sim)
return None, {"source": "expert_pending", "sim": sim}6.2 “高频问题”最终的含义
大多数FAQ项目会猜测哪些问题会频繁出现,并围绕这些猜测进行整理。但生产日志运行三个月后,这些猜测通常都是错误的:一半的整理条目只获得一两次命中,团队收到的前五大问题从未出现在列表中。
由查询流驱动的FAQ颠覆了这一顺序。团队从现有内容开始,观察哪些未命中模式反复出现,按频率排序,并将高频模式提升为标准条目。从未被命中的过时条目会被淘汰。标准问题列表最终反映的是用户实际提出的问题,而非团队预测他们会提出的问题。“高频问题”不再是一种猜测,而成为可测量的事实。
6.3 专家参与流程,而非被取代
系统无法完成的三类人工工作:
- 为新问题撰写权威答案。专家需要决定公司的立场、措辞、数据和例外情况。系统无法自行创造这些内容。
- 审核边界模糊的相似匹配。分类器将LLM适配答案返回给用户时,专家队列会收到样本进行复核。如果适配答案与权威答案在关键方面产生偏差,专家将调整权威问答或匹配阈值。
- 淘汰已过时的内容。产品变更、政策更新或法规调整时,必须有人发现这些变化并删除或重写相关内容。
这是系列文章核心观点在FAQ场景中的具体应用。系统存在的意义是放大专家的工作价值:通过重复使用每个精心编写的答案数千次,通过识别需要专家介入的问题,通过保持用户间答案的一致性。它绝不是要用能生成听起来合理但从未被团队讨论过的答案的模型来取代专家。
7. 本方案的边界与主系列的衔接点
FAQ场景看似简单是因为问题结构发生了倒置。标准问题依然存在,只是被推到了架构的不同层级。
语料库治理现在成为核心难题。第5条(解析)和第10条(自适应解析)对解析结构的处理,第17条(分类)和第19条(版本管理)对这些结构的处理,现在都必须在FAQ编辑阶段提前完成。谁可以编辑条目、如何追踪版本、如何淘汰过时答案:这些都是真实的工作。FAQ系统并未消除这些成本,只是将它们转移了位置。
列举与综合类问题依然存在。“所有排除条款有哪些?”这类问题需要遍历所有匹配的问答对,而非仅获取前N个最佳匹配。Top-k机制在列举场景中存在结构性缺陷,因为它在收集足够候选答案后就会停止,而非持续到找到所有答案为止。第12条(列举)对这一模式进行了详细阐述。
评估依然需要按失败模式进行。第20条(评估)中提出的“聚合指标可能失真而按问题类型划分的指标更可靠”这一观点,在FAQ场景中比通用RAG系统更为关键,因为失败模式存在本质差异。FAQ系统的典型失败模式是错误的直接匹配,而这种错误在聚合召回率指标中是完全不可见的。
8. 结论
FAQ场景展示了当有意设计语料库时,流水线中每个模块的真实面貌。解析是Pydantic加载,问题解析是相似度阈值判断,检索是预计算的矩阵向量乘积,生成是format()函数调用。工作内容并未消失,而是向上转移,体现在FAQ架构、编辑规范、精选答案版本管理、直接匹配与相似匹配阈值调节等环节中。
两个模式可以推广回主系列:缓存语料库的答案(任何重复回答相同问题的系统),以及动态少样本(将检索应用于提示)。当有人描述他们的使用场景为“我们有一份用户反复提问的问题列表”时,这就是一个FAQ,不应通过通用RAG处理这些问题而放弃结构优势。
9. 参考资料与进一步阅读
余弦阈值使用的FAQ风格句子对相似性方法源自Reimers和Gurevych(Sentence-BERT,EMNLP 2019)。动态少样本模式背后基于检索的少样本选择方法来自Liu等人(What Makes Good In-Context Examples for GPT-3?,ACL 2022)。更广泛的背景(检索增强和工具增强的语言模型)见于Mialon等人(Augmented Language Models,TMLR 2023)。本文的模式:FAQ作为缓存 + 动态少样本,在四个模块运行前通过精确匹配进行短路处理,并将相同的FAQ行重复用作残留部分的上下文示例库。
系列早期内容:
- 文档智能:系列简介。系列构建的模块及构建顺序。
效果与问题
- 基线企业级RAG:从PDF到高亮答案。完整的四模块流水线:PDF输入,高亮答案输出。
- 嵌入向量并非万能:RAG检索的可预测失效模式。嵌入相似性在哪些场景有效(同义词、拼写错误、改写),在哪些场景可预测失效(未知术语、否定、术语与答案的相关性),以及如何在这些场景中使用。
- RAG不是机器学习,机器学习工具包解决的是错误的问题。为什么块大小调整和微调优化了错误的目标;应根据问题类型进行路由。
- 从正则表达式到视觉模型:哪种RAG技术适合哪种问题。两个维度(文档复杂度和问题控制)帮助为每个案例选择技术。我们在生产中反复看到的10个常见RAG错误。10个生产错误按模块分类,附带每个错误的解决方案。
文档解析
- 通过循环工程构建文档结构:从正文排版恢复PDF大纲用于RAG。当PDF完全没有目录页时,通过六种信号和一个有界循环从正文排版重建大纲。
- 全面代理式RAG之前:了解你的决策方式及选择的解析方法。将解析方法作为目录,确定运行哪些方法后再将循环交给代理。
生成
- RAG生成的循环工程:逐个迭代Top-k。逐个阅读检索到的页面而非一次性全部读取,当答案只出现在其中某一页时这种做法带来的优势。
- 大多数RAG幻觉是提取错误:七种类型化生成契约的模式。模型出现提取错误的七种常见方式,以及能捕捉每种错误的类型化契约。
- RAG生成的循环工程:从廉价本地模型到托管旗舰模型的LLM级联。从廉价本地模型开始,仅在答案不成立时逐步升级,通过测量进行验证。
单文档流水线
- 提示工程不足以解决问题:上下文工程的四个模块如何阻止RAG幻觉。为什么更好的提示无法修复错误页面,以及这四个模块如何为上下文做贡献。
- 通过减少调用LLM次数而非购买更快模型,降低企业RAG流水线的延迟和成本。通过减少调用频率和使用更经济的模型来降低流水线的延迟和成本,而不是通过购买更高端的模型。
- RAG工作流与循环工程:决定何时循环、何时停止的调度器。反馈循环、有界迭代和调度器整合为统一工作流。RAG的循环工程:每个步骤内部的小循环,跨流水线的大循环。循环的两个层级:每个模块内部的小规模有界循环,跨模块的生成触发式大循环。