需求与约束
客户的 HR SaaS 产品里,每家企业都会上传自己的员工手册、考勤制度、报销规则。员工经常为「年假怎么算」「差旅住宿标准多少」这类问题咨询 HR,而答案其实都写在制度文档里。
产品侧想做一个内嵌的问答助手。核心约束有三个:一是不同企业的文档绝对不能串(一次泄露就是重大事故);二是答案必须带出处,员工能点开看原文,否则 HR 不敢用;三是成本要能覆盖,按每租户每月的定价倒推,单次问答成本有上限。
多租户 RAG 架构
接入
编排
检索
模型
数据
运营
租户隔离做在三层:S3 前缀 + IAM 策略、OpenSearch 索引级过滤、以及应用层的强制 tenant_id 校验。任一层失效还有另两层兜住。
成本怎么控住
按定价倒推,单次问答的模型成本有明确上限。直接全部用 Sonnet 会超。我们的做法是分层:先用 Haiku 做意图分类和查询改写(便宜且够用),只有最终答案生成才用 Sonnet。
另一个大头是系统提示词与检索上下文。这部分内容在同一租户内高度重复,开启提示词缓存后命中率超过 70%,缓存部分的成本大幅下降。再配合严格控制注入的文档块数量(Top 5 而不是 Top 20),整体成本降了 44%。
- 意图分类与查询改写走 Haiku,成本约为 Sonnet 的 1/12
- 系统提示词与租户上下文启用提示词缓存,命中率 70%+
- 召回 50 条后重排到 Top 5,控制注入 token 量
- 简单问题(打招呼、无关问题)直接短路返回,不调用生成模型
- 按租户计量 token,异常用量自动告警与限流
- 分层路由节省约 28%
- 提示词缓存节省约 12%
- 上下文精简节省约 4%
- 综合降本44%
准确率优化过程
| 阶段 | 做法 | 评测集准确率 |
|---|---|---|
| 基线 | 纯向量检索 Top 5 + Sonnet 生成 | 68% |
| 加关键词通道 | 向量 + BM25,RRF 融合 | 79% |
| 加重排 | 召回 50 条后 Rerank 到 Top 5 | 87% |
| 父子块策略 | 小块检索、大块生成,保留上下文 | 90% |
| 表格单独处理 | 表格解析成 Markdown 整块入索引 | 92% |
每一步都在同一个 300 题评测集上测量。没有评测集的话,这些优化根本无法验证是否有效。
上线前的隔离验证
我们做了专项的隔离测试:构造 200 组跨租户查询,验证任何租户的查询都不可能召回其他租户的文档。同时做了越权尝试测试(伪造 tenant_id、篡改 JWT)。这类测试必须在上线前做完,出事之后再补就晚了。
他们坚持要先做评测集再动手,当时我们觉得是浪费两周。后来每次优化都能看到准确率数字变化,才明白没有这个东西根本不知道自己在往哪个方向走。
技术栈
- Bedrock
- Claude
- Titan Embeddings
- OpenSearch Serverless
- Lambda
- Step Functions
- DynamoDB
- S3
- API Gateway
- Guardrails