sft-rag-pipelinelisted
Install: claude install-skill gznywjc/sft-rag-pipeline
# SFT + RAG 问答系统流水线
## 这个 skill 解决什么
用户给一批内部文档,要一个能准确回答这些文档内容的助手。
天真的做法是:文档切块 → 建向量库 → 或者生成 QA 微调模型。这两条路单独走都会失败,而失败方式很隐蔽——模型答得流畅、格式专业、**内容是编的**。
本 skill 编码的是一套真实项目(企业内部知识助手,19+10 个产品线、73 份制度文档、500+ 索引块、10 个模型版本)几周迭代出来的流程和踩坑记录。
## 核心原则
**SFT 负责怎么说,RAG 负责说什么。** 这不是口号,是被反复验证的分工:
- 精确事实(数字、人名、电话、型号、条款)→ **必须 RAG**。实测某事实在训练集里出现 3 次、训了 3 个 epoch,纯模型仍答错;RAG 一接上就对。
- 语气、身份、拒绝边界、回答结构 → **必须 SFT**。提示词改不动已经固化的行为模式。
**不确定就停下来问人。** 见下方每个阶段的 🛑 标记。自动推断业务事实是本流程最大的风险源。
## 六个阶段
按顺序执行。每个阶段有明确的完成标准,没达到不要进下一阶段。
完整执行剧本见 `references/workflow.md`(含时间预期和何时该推倒重来)。
### Phase 0 · 环境与摸底
读 `references/environment.md`
- 确认 Python 环境、GPU 显存、是否离线、镜像源
- 清点文档:格式、数量、体积、是否有扫描件
- 🛑 **问用户**:这批文档里有没有已经过时的?有没有两份内容冲突的?
完成标准:能列出每份文档的格式、页数/字数、大致主题。
### Phase 1 · 文档抽取
读 `references/extraction.md`,用 `scripts/doc_extract.py`
- 各格式转文本,**逐份验证抽取结果非空且合理**
- 🛑 **抽取失败的文档必须报告给用户**,不要静默跳过
完成标准:每份文档都有可读文本,且抽取字数与文档体积大致匹配。
> 最常见的事故:`.doc`(老格式)抽取失败,脚本把错误信息当正文写进索引。这类块带着文档名、相似度很高、稳排前列,然后把一条文件路径当上下文喂给模型。
### Phase 2 · 分块与建索引
读 `references/chunking.md`,用 `scripts/build_chunks.py` + `scripts/index_ops.py`
- 按文档结构设计分块,**不要无脑按固定字数切**
- 一个 source 对应一个主题,粒度和用户提问粒度对齐
- 🛑 **发现文档内容自相矛盾时停下来问用户**
完成标准:`index_ops.py --inspect` 输出的 source 清单和块长分布合理,无坏块。
### Phase 3 · 检索调优
读 `references/retrieval.md`,用 `scripts/eval_retrieval.py`
- 先建 25-40 题的检索评测集,**再**调参
- 双层评估:L1 向量排名 / L2 管线实际送入上下文
- 校准阈值、来源截断、每源上限
完成标准:L1 与 L2 通过率都达标且**两者接近**(差距大说明管线参数在误杀)。
### Phase 4 · 微调数据与训练
读 `references/training.md`
- 🛑 **绝对不要让 LLM 凭理解从文档生成 QA