defmodule CMDCRAGArcana.Pipeline.RunSummary do
@moduledoc """
`rag_pipeline_answer` 的运行摘要。
摘要只记录治理和调试需要的计数、阈值、step 与 provenance 信息,不保存
chunk 原文或长 prompt。
"""
@derive Jason.Encoder
@type t :: %__MODULE__{
preset_id: String.t(),
steps: [atom()],
collections: [String.t()],
fail_mode: atom(),
grounding_score: float() | nil,
citation_count: non_neg_integer(),
result_count: non_neg_integer(),
degraded?: boolean(),
review_required?: boolean(),
blocked?: boolean(),
warnings: [term()],
metadata: map()
}
@enforce_keys [:preset_id]
defstruct [
:preset_id,
:fail_mode,
:grounding_score,
steps: [],
collections: [],
citation_count: 0,
result_count: 0,
degraded?: false,
review_required?: false,
blocked?: false,
warnings: [],
metadata: %{}
]
@doc "转换为 JSON 友好 map。"
@spec to_map(t()) :: map()
def to_map(%__MODULE__{} = summary) do
%{
preset_id: summary.preset_id,
steps: summary.steps,
collections: summary.collections,
fail_mode: summary.fail_mode,
grounding_score: summary.grounding_score,
citation_count: summary.citation_count,
result_count: summary.result_count,
degraded?: summary.degraded?,
review_required?: summary.review_required?,
blocked?: summary.blocked?,
warnings: Enum.map(summary.warnings, &normalize_warning/1),
metadata: summary.metadata
}
end
defp normalize_warning(:missing_citations), do: %{reason: :missing_citations}
defp normalize_warning({:missing_grounding_score, min_score}) do
%{reason: :missing_grounding_score, min_score: min_score}
end
defp normalize_warning({:grounding_below_threshold, score, min_score}) do
%{reason: :grounding_below_threshold, score: score, min_score: min_score}
end
defp normalize_warning(other), do: %{reason: inspect(other)}
end