阶段3(下):RAG、向量数据库专题;接入 BOSS直聘调研(research/、岗位对照和延伸技术栈);新增 cs 领域和 12 个技术栈骨架;面试题全部补齐追问并加入校验
This commit is contained in:
1 parent
7f52513ffc
commit
6650f7eb6d
52 files changed
+2777
-38
No files matched your search
@@ -0,0 +1,109 @@
|
||||
---
|
||||
id: ai.rag.generation-eval
|
||||
title: 生成与评测:带引用的提示词、拒答、检索评测和答案评测
|
||||
type: lesson
|
||||
domain: ai
|
||||
stack: [rag]
|
||||
tags: [提示词, 引用, 拒答, 幻觉, Recall@k, MRR, 评测集]
|
||||
level: intermediate
|
||||
prerequisites: [ai.rag.hybrid-rerank]
|
||||
est_hours: 3
|
||||
related: [ai.rag.scenario.permission-aware-kb, ai.prompt-engineering.index, ai.agent-ops.index, ai.rag.interview]
|
||||
week: [6]
|
||||
order: 3
|
||||
---
|
||||
|
||||
# 生成与评测:带引用的提示词、拒答、检索评测和答案评测
|
||||
|
||||
## 解释说明
|
||||
|
||||
**提示词的关键要素**
|
||||
|
||||
1. 角色和任务:“你是公司制度问答助手”;
|
||||
2. **只依据资料回答**,资料中没有就明确说没有(减少幻觉);
|
||||
3. 资料编号 + 要求用 `[编号]` 标注依据(可追溯、可校验);
|
||||
4. 输出格式和长度要求;
|
||||
5. 资料放在问题前面,并用清晰的分隔符包起来。
|
||||
|
||||
**拒答**:检索结果的最高相似度低于阈值、或者重排分数太低时,不调用大模型,直接回答“知识库中没有找到相关内容”,并引导到人工渠道。宁可不答,不要编。阈值需要用评测数据调。
|
||||
|
||||
**引用校验**:检查答案中的 `[编号]` 是否都在给出的资料范围内;可以进一步检查被引用的资料里是否包含答案中的关键数字。
|
||||
|
||||
**评测**——没有评测就无法判断改动是变好还是变坏:
|
||||
|
||||
| 层面 | 指标 | 怎么做 |
|
||||
| --- | --- | --- |
|
||||
| 检索 | Recall@k(正确资料是否在前 k 个里)、MRR(正确资料的排名倒数的平均值) | 人工标注“问题 → 应命中的文档 / 块”,几十到几百条 |
|
||||
| 生成 | 忠实度(答案是否都有资料支撑)、相关性、正确性 | 人工抽查 + 用大模型按评分标准打分(LLM-as-judge) |
|
||||
| 线上 | 点赞 / 点踩、转人工率、无答案率 | 埋点、定期分析差评样本 |
|
||||
|
||||
评测集要覆盖:常见问题、需要精确匹配的问题(编号、数字)、多轮追问、**知识库里没有答案的问题**(测试拒答)、无权限的问题。
|
||||
|
||||
工具:Ragas 等框架提供了忠实度、上下文召回等指标的实现,接口变化较快,以官方文档为准(https://docs.ragas.io/)。
|
||||
|
||||
## 案例
|
||||
|
||||
制度问答助手上线前建立了 9 条以上的检索评测集([examples/mini-rag](examples/mini-rag/) 中的 `EVAL`,真实项目要几十到上百条),比较纯向量、纯 BM25、混合三种检索的 Recall@3 和 MRR;之后每次调整切分或检索参数都跑一遍,指标下降就不合并。
|
||||
|
||||
## 代码示例
|
||||
|
||||
检索评测(Recall@k、MRR):
|
||||
|
||||
```python
|
||||
def recall_and_mrr(results: dict[str, list[str]], expected: dict[str, str], k: int = 3) -> tuple[float, float]:
|
||||
"""results:问题 → 检索出的文档 ID(已排序);expected:问题 → 应命中的文档 ID。"""
|
||||
hit, rr = 0, 0.0
|
||||
for q, gold in expected.items():
|
||||
top = results[q][:k]
|
||||
if gold in top:
|
||||
hit += 1
|
||||
rr += 1 / (top.index(gold) + 1)
|
||||
n = len(expected)
|
||||
return hit / n, rr / n
|
||||
|
||||
|
||||
results = {"年假几天": ["hr-leave", "fin"], "VPN 连不上": ["hr-leave", "it-vpn"], "报销时限": ["it-vpn", "x", "y"]}
|
||||
expected = {"年假几天": "hr-leave", "VPN 连不上": "it-vpn", "报销时限": "fin"}
|
||||
print(recall_and_mrr(results, expected)) # (0.666..., 0.5):第 1 题排第 1,第 2 题排第 2,第 3 题没命中
|
||||
```
|
||||
|
||||
带引用的提示词和拒答、引用校验:
|
||||
|
||||
```python
|
||||
import re
|
||||
|
||||
|
||||
def build_prompt(question: str, chunks: list[str]) -> str:
|
||||
context = "\n".join(f"[{i}] {c}" for i, c in enumerate(chunks, start=1))
|
||||
return ("你是公司制度问答助手。只根据<资料>回答;资料中没有的内容,回答“资料中没有相关规定”。"
|
||||
"每个结论后用 [编号] 标注依据。\n"
|
||||
f"<资料>\n{context}\n</资料>\n问题:{question}")
|
||||
|
||||
|
||||
def answer_or_refuse(question: str, hits: list[tuple[str, float]], min_score: float = 0.3) -> str:
|
||||
if not hits or hits[0][1] < min_score:
|
||||
return "知识库中没有找到相关内容,建议咨询 HR 或提交工单。"
|
||||
return build_prompt(question, [text for text, _ in hits]) # 交给大模型
|
||||
|
||||
|
||||
def citations_valid(answer: str, n_chunks: int) -> bool:
|
||||
cited = {int(x) for x in re.findall(r"\[(\d+)\]", answer)}
|
||||
return bool(cited) and cited <= set(range(1, n_chunks + 1))
|
||||
|
||||
|
||||
print(answer_or_refuse("股票期权怎么行权", [("差旅住宿标准……", 0.12)]))
|
||||
print(citations_valid("满十年年假 10 天 [1]。", 3), citations_valid("答案 [5]", 3)) # True False
|
||||
```
|
||||
|
||||
## 易错点
|
||||
|
||||
- **没有评测集,靠几个问题“感觉效果不错”**:改了参数也不知道变好还是变坏。
|
||||
- **评测集里没有“无答案”的问题**:拒答能力从未被测试。
|
||||
- **拒答阈值拍脑袋**:要用评测数据画出“阈值 vs 准确率 / 拒答率”来选。
|
||||
- **完全依赖 LLM 打分**:评分模型本身有偏差,要和人工标注对比校准。
|
||||
- **提示词里资料和指令混在一起**:资料里的内容可能被模型当成指令(提示词注入),用分隔符包裹并在指令中说明。
|
||||
- **引用编号不校验**:模型可能引用不存在的编号,或者引用了但内容对不上。
|
||||
|
||||
## 面试常问
|
||||
|
||||
见 [RAG 面试题](interview.md):怎么减少幻觉、怎么评测 RAG、拒答怎么做、线上效果怎么监控。
|
||||
Reference in new issue
Block a user