在 1 万条客服 query 上,如何自动搜索 k=0,1,5,10 的 F1 并绘制边际收益曲线?

解读

面试官想验证三件事:

  1. 你对检索增强生成(RAG)k 值召回策略的理解是否到位;
  2. 能否用自动化脚本在真实业务数据上快速实验,而不是手动跑;
  3. 是否具备指标计算 + 可视化 + 成本意识的闭环思维,最终用“边际收益”告诉老板“再往上加 k 不值”。

1 万条客服 query 是典型高并发、低延迟场景,k 越大延迟越高,所以必须给出可复现、可解释、可落地的端到端方案。

知识点

  1. RAG 召回粒度:k=0 代表纯模型参数记忆,k=1/5/10 代表外挂知识库返回 TopK 片段。
  2. F1 计算方式:客服场景采用答案级 F1(Answer-level F1),先由人工标注“标准答案集合”,再与模型输出做字符级 Rouge-L 或分词级 F1对齐,最终取宏观平均。
  3. 自动搜索:用单因子网格扫描即可,k 取值 0、1、5、10 四个点,循环外只改召回参数,其余链路不变。
  4. 边际收益曲线:ΔF1/Δk 随 k 增大而递减,当 ΔF1<0.5% 且延迟增加>20 ms 时可判定收益拐点到来。
  5. 工程实现
    • 数据层:把 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% 的拐点。
  6. 合规:客服数据属PII,全程在公司离线机房 GPU 集群执行,不走公网,结果表脱敏后导出。

答案

步骤一:环境初始化

  1. 申请离线 Yarn 队列 8×A100 40G,镜像内置 vLLM 0.4.2、Milvus 2.3、py3.9。
  2. 把 1 万条 query 采样后让业务专家标注答案,形成 gold.jsonl,每行含 query_id、gold_answers(列表形式)。

步骤二:索引构建

  1. bge-large-zh-v1.5把客服知识库 50 万段文本灌入 Milvus,建 IVF_SQ8 索引,nlist=4096,nprobe=64,保证 k=10 时召回率>95%。

步骤三:自动化实验脚本

  1. 写 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)
    
  2. Airflow 每日凌晨调度,4 个 k 值串行跑,避免 GPU 抢占,总耗时约 2.5 h。

步骤四:边际收益计算

  1. 读取 MySQL 结果,计算
    ΔF1(k)=F1(k)−F1(k−1),Δk=1,
    当 ΔF1<0.5% 且 Δlatency>20 ms 时触发收益拐点告警
  2. 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. 如果 1 万条 query 里存在长尾分布,可先做分层采样(头部 2k、腰部 5k、尾部 3k),再分别画边际收益曲线,防止头部 query 掩盖尾部提升。
  2. 当 k 继续增大到 20、50 时,可考虑重排序(rerank)bge-reranker-large,把 ΔF1 提升上限再抬高 1.2%,但延迟会增加 60 ms,需用并发池 + 缓存抵消。
  3. 若老板要求“零标注”,可用无参考指标BERTScoreNLI 自洽,但需验证与人工 F1 的Pearson 系数>0.85才能替代。
  4. 最终上线时,把 k 做成动态可调运行时特征,结合用户等级、query 复杂度实时路由,既保证体验又省成本,这才是LLMOps的完整闭环。