在 1 万条客服 query 上,如何自动搜索 k=0,1,5,10 的 F1 并绘制边际收益曲线?
解读
面试官想验证三件事:
- 你对检索增强生成(RAG)k 值召回策略的理解是否到位;
- 能否用自动化脚本在真实业务数据上快速实验,而不是手动跑;
- 是否具备指标计算 + 可视化 + 成本意识的闭环思维,最终用“边际收益”告诉老板“再往上加 k 不值”。
1 万条客服 query 是典型高并发、低延迟场景,k 越大延迟越高,所以必须给出可复现、可解释、可落地的端到端方案。
知识点
- RAG 召回粒度:k=0 代表纯模型参数记忆,k=1/5/10 代表外挂知识库返回 TopK 片段。
- F1 计算方式:客服场景采用答案级 F1(Answer-level F1),先由人工标注“标准答案集合”,再与模型输出做字符级 Rouge-L 或分词级 F1对齐,最终取宏观平均。
- 自动搜索:用单因子网格扫描即可,k 取值 0、1、5、10 四个点,循环外只改召回参数,其余链路不变。
- 边际收益曲线:ΔF1/Δk 随 k 增大而递减,当 ΔF1<0.5% 且延迟增加>20 ms 时可判定收益拐点到来。
- 工程实现:
- 数据层:把 1 万条 query 落Hive 表,字段含 query_id、user_query、gold_answer。
- 召回层:Milvus 建索引,段落向量用bge-large-zh-v1.5,M 值 768,IVF_SQ8 量化。
- 生成层:Qwen-14B-Chat 做 4-bit 量化,推理用 vLLM 框架,batch=32,tp=1。
- 实验层:Airflow 写 DAG,4 个 task 顺序执行,每个 task 只改 k 值,输出结果写回MySQL表(schema:k、tp、fp、fn、precision、recall、f1、latency_p99)。
- 可视化:Streamlit + ECharts 画折线图,x 轴 k,双 y 轴左侧 F1、右侧 latency,再用红色虚线标出边际收益<1% 的拐点。
- 合规:客服数据属PII,全程在公司离线机房 GPU 集群执行,不走公网,结果表脱敏后导出。
答案
步骤一:环境初始化
- 申请离线 Yarn 队列 8×A100 40G,镜像内置 vLLM 0.4.2、Milvus 2.3、py3.9。
- 把 1 万条 query 采样后让业务专家标注答案,形成 gold.jsonl,每行含 query_id、gold_answers(列表形式)。
步骤二:索引构建
- 用bge-large-zh-v1.5把客服知识库 50 万段文本灌入 Milvus,建 IVF_SQ8 索引,nlist=4096,nprobe=64,保证 k=10 时召回率>95%。
步骤三:自动化实验脚本
- 写 run_exp.py,伪代码如下:
for k in [0,1,5,10]: pred_answers=[] for batch in DataLoader(gold.jsonl, batch=32): if k>0: docs=milvus.search(batch['query'], topk=k) context='\n'.join(docs) prompt=f'基于以下内容回答问题:\n{context}\n问题:{query}\n答案:' else: prompt=f'问题:{query}\n答案:' ans=model.generate(prompt, max_new_tokens=128) pred_answers.append(ans) tp,fp,fn=compute_f1_batch(pred_answers, gold_answers) f1=2*tp/(2*tp+fp+fn) latency=collect_p99() write_mysql(k, f1, latency) - 用Airflow 每日凌晨调度,4 个 k 值串行跑,避免 GPU 抢占,总耗时约 2.5 h。
步骤四:边际收益计算
- 读取 MySQL 结果,计算
ΔF1(k)=F1(k)−F1(k−1),Δk=1,
当 ΔF1<0.5% 且 Δlatency>20 ms 时触发收益拐点告警。 - 用Streamlit 画双轴折线,并输出 Markdown 报告到飞书群机器人,方便产品拍板。
步骤五:结论示例
k=0 时 F1=62.3%,latency=120 ms;
k=1 提升到 71.8%,ΔF1=+9.5%;
k=5 到 74.1%,ΔF1=+2.3%;
k=10 到 74.4%,ΔF1=+0.3%,latency=185 ms。
拐点出现在 k=5,后续不再扩容。
拓展思考
- 如果 1 万条 query 里存在长尾分布,可先做分层采样(头部 2k、腰部 5k、尾部 3k),再分别画边际收益曲线,防止头部 query 掩盖尾部提升。
- 当 k 继续增大到 20、50 时,可考虑重排序(rerank)用bge-reranker-large,把 ΔF1 提升上限再抬高 1.2%,但延迟会增加 60 ms,需用并发池 + 缓存抵消。
- 若老板要求“零标注”,可用无参考指标如BERTScore或NLI 自洽,但需验证与人工 F1 的Pearson 系数>0.85才能替代。
- 最终上线时,把 k 做成动态可调的运行时特征,结合用户等级、query 复杂度实时路由,既保证体验又省成本,这才是LLMOps的完整闭环。