Proposal: EvalPort reporter for portable evaluation ResultSets #671
adhabnr-ux
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
TL;DR
deepfabric.evaluationalready produces a well-typed, structured evaluation result (EvaluationResult→EvaluationMetrics+list[SampleEvaluation]), and the reporter layer (BaseReporter→FileReporter/CloudReporter) is already the seam where output format is decided. I'd like to propose adding one more reporter that serializes to EvalPort — an open, framework-agnostic JSON format for evalTestCase/Grader/EvalSuite/ResultSetdocuments — so a DeepFabric evaluation run can be consumed by other tools (dashboards, benchmark aggregators, CI gates) without them needing to understand DeepFabric's internal schema.I'm not affiliated with DeepFabric — just proposing this as someone maintaining the interop spec, based on actually reading
deepfabric/evaluation/. Posting here rather than opening a PR straight away, per CONTRIBUTING's "discuss before changing" guidance.What I looked at
Specifically, in
deepfabric/evaluation/:evaluator.py—Evaluator,EvaluatorConfig,EvaluationResultmetrics.py—EvaluationMetrics,SampleEvaluation,compute_metrics()parser.py—GroundTruth,ExpectedToolCall(tool_name+parameters)evaluators/base.py,evaluators/builtin/tool_calling.py—BaseEvaluator,ToolCallingEvaluator,EvaluatorResultreporters/base.py,reporters/file_reporter.py—BaseReporter,FileReporter(writesresult.model_dump_json(indent=2))The mapping
EvaluationResultalready lines up closely with EvalPort'sResultSetdocument:SampleEvaluation.sample_idResult.test_case_id(stringified)SampleEvaluation.queryTestCase.input, carried through)SampleEvaluation.predicted_answer/predicted_tool+predicted_parametersResult.actual_outputSampleEvaluation.tool_selection_correctGraderResult(score1.0/0.0,passed)SampleEvaluation.parameters_correctGraderResultSampleEvaluation.execution_validGraderResultSampleEvaluation.errorResult.error.messageEvaluationMetrics.tool_selection_accuracy/.parameter_accuracy/.execution_success_rateResultSet.summary.by_grader.<id>.avg_scoreEvaluationMetrics.overall_scoreResultSet.summary.avg_scoreEvaluationMetrics.samples_evaluated/samples_processed/processing_errorsResultSet.summary.total/ derivedpassed/failedA sketch of the reporter, following the exact shape of
FileReporter/CloudReporter:Wiring it into
Evaluator._initialize_reporters()would be a one-line addition next to the existing"file"/"cloud"branches (reporters=["openeval"]orreporters={"openeval": {"path": "..."}}inEvaluatorConfig) — no change needed toevaluator.py's evaluation loop itself, sincereport()/report_sample()is exactly the seamBaseReporteralready defines.Honest gaps / open questions
ExpectedToolCall.parametershas no first-class EvalPort home. EvalPort'sTestCase.expected_toolsis an array of tool names only (agent-eval field, no per-tool parameter schema) — there's noTestCase.expected_parametersin the spec at all. So round-tripping DeepFabric's rich per-tool ground truth (GroundTruth.expected_tools: list[ExpectedToolCall], each withtool_name+parameters) into a spec-cleanTestCaseisn't fully lossless; it has to live undermetadata, same as the opik-adapter's approach to Opik's schema-less dataset items.EvaluationResult→ResultSet. A full round-trip would also need aConversation→EvalSuite/TestCaseexporter on the dataset-generation side (deepfabric/schemas.py), which I haven't audited in depth — happy to look at that as a follow-up if there's interest.EvaluationMetrics.overall_scoreis a fixed-weight composite (40% tool selection / 35% params / 25% execution, percompute_overall_score), while EvalPort'ssummary.avg_scoreis conventionally a flat mean over grader scores. The sketch above reportsoverall_scoredirectly rather than recomputing a flat mean, which is defensible but worth being explicit about in any real implementation.evaluators(which go throughEvaluatorRegistry),reportersin_initialize_reporters()are matched by hardcoded string branches rather than a registry — adding"openeval"fits the existing pattern fine, just noting it's not as pluggable as the evaluator side.Why bother
If this is interesting, I'd be glad to either open a PR with the
OpenEvalReporterabove (tests included) directly againstdeepfabric/evaluation/reporters/, or — if you'd rather keep DeepFabric's reporter surface minimal — ship it as a standalonedeepfabric-openeval-adapterpackage the way I did for Opik, AutoGen, and CrewAI: zero changes to DeepFabric core, built only against the publicEvaluationResult/SampleEvaluationsurface. Either way, no obligation — flagging it because the data model here is already unusually clean for this kind of conversion, and I wanted to check appetite before writing code.Full EvalPort spec: https://github.com/adhabnr-ux/evalport/blob/main/spec/SPEC.md
— Sahi, independent contributor (not affiliated with this project)
All reactions