Skip to content

feat: report OpenAI finish reason distribution#422

Open
hvagadia wants to merge 2 commits into
mlcommons:mainfrom
hvagadia:agent/finish-reason-reporting
Open

feat: report OpenAI finish reason distribution#422
hvagadia wants to merge 2 commits into
mlcommons:mainfrom
hvagadia:agent/finish-reason-reporting

Conversation

@hvagadia

@hvagadia hvagadia commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Capture OpenAI-compatible finish_reason values and surface their distribution in existing benchmark artifacts. This does not introduce a new artifact.

Report visibility

Finish reasons are available in:

  • events.jsonl: the raw reason is added as a top-level finish_reason field on applicable sample.complete events.
  • metrics/final_snapshot.json: fixed counters record stop, length, tool_calls, content_filter, function_call, and other.
  • performance/result_summary.json: all supported finish reasons are exposed under finish_reason_counts, including zero counts.

report.txt is unchanged. Unknown values remain unchanged in events.jsonl and are aggregated under other. If an OpenAI-compatible response has no string finish reason, the event field is omitted and no distribution counter is incremented.

Experiment data

Validated against Kimi-K2.6 served with SGLang through its OpenAI-compatible endpoint:

Workload Successful requests Finish-reason distribution
Agentic coding trajectory 38/38 tool_calls: 36, length: 2
Single-turn AIME sample 1/1 stop: 1
Full local SQuAD-pruned dataset 100/100 stop: 100

For every experiment, events.jsonl, metrics/final_snapshot.json, and performance/result_summary.json reported matching counts for observed reasons.

Type of change

  • Bug fix
  • New feature
  • Documentation update
  • Refactor/cleanup

Related issues

None.

Testing

  • Tests added/updated
  • All tests pass locally (1,317 passed, 5 skipped with pytest -m unit)
  • Manual testing completed against a real SGLang server

Checklist

  • Code follows project style
  • Pre-commit hooks pass
  • Documentation updated (not applicable: no configuration or workflow change)

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@github-actions

Copy link
Copy Markdown

MLCommons CLA bot All contributors have signed the MLCommons CLA ✍️ ✅

@hvagadia
hvagadia marked this pull request as ready for review July 17, 2026 21:07
@hvagadia
hvagadia requested a review from a team July 17, 2026 21:07
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@codecov-commenter

codecov-commenter commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@598dbfd). Learn more about missing BASE report.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #422   +/-   ##
=======================================
  Coverage        ?   80.69%           
=======================================
  Files           ?      133           
  Lines           ?    17657           
  Branches        ?        0           
=======================================
  Hits            ?    14249           
  Misses          ?     3408           
  Partials        ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

TRACKED_FINISH_REASON_TOOL_CALLS = "tracked_finish_reason_tool_calls"
TRACKED_FINISH_REASON_CONTENT_FILTER = "tracked_finish_reason_content_filter"
TRACKED_FINISH_REASON_FUNCTION_CALL = "tracked_finish_reason_function_call"
TRACKED_FINISH_REASON_OTHER = "tracked_finish_reason_other"

@nvzhihanj nvzhihanj Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would the server disconnection (or timeout) be categorized in OTHER? that was one of the pain points of endpoints collection earlier - not sure if there's a way to expose it to help debug server. cc: @nv-alicheng

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that would be handled by the accumulator or worker on a disconnect. Would be nice to integrate the errors counted there with this set in a followup.

@nv-alicheng nv-alicheng Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with Rashid, if a server disconnects, then it's not finished cleanly and therefore would not have a reason from the server - that should be surfaced in the HTTP error code by accumulator / client worker.

edit for clarity - this would be surfaced in MetricsAggregator via TRACKED_SAMPLES_FAILED, which requires the accumulator to send an error event - handled by this block below in the same file:

            # --- Error events ---
            # Counted BEFORE the COMPLETE event (session.py emits ERROR
            # first), so the tracked row still exists for tracked-failed
            # detection.
            if isinstance(ev, ErrorEventType):
                registry.increment(MetricCounterKey.TOTAL_SAMPLES_FAILED.value)
                if record.sample_uuid and table.get_row(record.sample_uuid) is not None:
                    registry.increment(MetricCounterKey.TRACKED_SAMPLES_FAILED.value)
                logger.debug("Error event: %s", record)
                continue

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing setup does count disconnections as failed request. Overall stats would show as:
image
Do yoy want me to modify this behavior in some way?

Comment thread src/inference_endpoint/metrics/report.py Outdated

@nv-alicheng nv-alicheng left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@hvagadia
hvagadia force-pushed the agent/finish-reason-reporting branch from 9f1c948 to ef15278 Compare July 18, 2026 02:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants