Files
siemens_ragas/docs/superpowers/specs/2026-06-22-dify-score-api-design.md

4.7 KiB
Raw Blame History

Dify 集成 — 单题实时评分 API 设计

日期: 2026-06-22
状态: 已批准,待实现
范围: 在现有 FastAPI 服务中新增 POST /api/score 端点,供 Dify 外部 Tool 调用,实现单条问答记录的实时 RAGAS 指标评分。


1. 目标

让 Dify Agent 能在回答完问题后,将 (question, answer, contexts, ground_truth) 发给 siemens_ragas 服务,实时获取各 RAGAS 指标得分,用于质量监控或 Agent 自我改进。


2. API 规范

POST /api/score

请求体:

{
  "question":          "双源CT的时间分辨率是多少?",
  "answer":            "双源CT的单扇区时间分辨率为75ms。",
  "contexts":          "片段1双源CT采用两套管-探测器系统... |||| 片段2单扇区采集旋转135度...",
  "ground_truth":      "双源CT单扇区时间分辨率为75ms需旋转135度。",
  "context_separator": " |||| ",
  "metrics":           ["faithfulness", "answer_relevancy"],
  "judge_model":       "deepseek-v4-flash",
  "embedding_model":   "text-embedding-v3"
}

字段说明:

字段 类型 必填 说明
question str 问题文本
answer str 待评分的回答
contexts str 检索到的上下文,多段用 context_separator 拼接
ground_truth str 标准答案缺失时跳过依赖它的指标context_recall、factual_correctness、semantic_similarity
context_separator str 默认 " |||| "(四个竖线,两侧各一空格)
metrics list[str] 默认 ["faithfulness", "answer_relevancy", "context_recall", "context_precision"]
judge_model str 默认读 .envRAGAS_JUDGE_MODEL
embedding_model str 默认读 .envRAGAS_EMBEDDING_MODEL

响应体200 OK

{
  "scores": {
    "faithfulness":     0.8750,
    "answer_relevancy": 0.9200
  },
  "weighted_score": 0.8975,
  "latency_ms": 3420
}

错误响应:

状态码 场景
400 必填字段缺失、metrics 名称不合法
401 配置了 SCORE_API_TOKEN 但请求未携带有效 Bearer Token
422 请求体 JSON 格式错误Pydantic 校验)
500 RAGAS 内部评分异常,附带 error 字段

鉴权(可选):
.envSCORE_API_TOKEN 非空,则要求请求头携带 Authorization: Bearer <token>。为空则不鉴权(内网部署场景)。


3. 架构与文件改动

新文件

文件 职责
webapp/api/score.py 路由定义,请求验证,调用 InlineScorer
webapp/services/inline_scorer.py LLM 客户端缓存 + RAGAS 评分逻辑封装

修改文件

文件 改动
webapp/models.py 新增 ScoreRequestScoreResponse
webapp/server.py 注册 score.router,更新 openapi_tags
rag_eval/settings.py 新增 `score_api_token: str

4. inline_scorer.py 设计

class InlineScorer:
    """同步执行 RAGAS 单题评分,内部缓存 LLM 客户端。"""

    def score(
        self,
        question: str,
        answer: str,
        contexts: list[str],
        ground_truth: str | None,
        metrics: list[str],
        judge_model: str,
        embedding_model: str,
        settings: EvaluationSettings,
    ) -> dict[str, float | None]:
        """返回 {metric_name: score} 字典NaN 记为 None。"""

客户端缓存策略:
(judge_model, embedding_model) 为 key缓存 (llm, embeddings) 对象,避免每次请求都重建 AsyncOpenAI 连接。缓存为模块级单例(_scorer_cache: dict),线程安全(加 threading.Lock)。

评分执行:
复用 build_metric_pipeline 构建 MetricPipeline,然后 asyncio.run(pipeline.score_sample(sample)) 执行。与现有 evaluator.py 模式一致。

ground_truth 为空时的指标跳过逻辑:
context_recallfactual_correctnesssemantic_similaritynoise_sensitivity 需要 ground_truth若请求中未提供自动从 metrics 列表中移除这些指标,并在响应中对应字段返回 null


5. Dify 侧配置方法

  1. 在 Dify 「工具」→「自定义工具」中创建新工具
  2. 填写 OpenAPI Schema/api/score 端点对齐)
  3. 鉴权方式API KeyBearer或无鉴权
  4. 在 Agent / Workflow 节点中引用该工具,将 questionanswercontexts 变量映射到工具输入

6. 不在范围内

  • 批量评分接口(异步 job
  • Dify Workflow 节点插件(需要 Dify 插件开发框架)
  • 评分结果持久化到 scores.csv
  • 与现有 report_builder 集成展示