Skip to content

[Feature] Add Anthropic and Google (Gemini) response format support to requestcostmetadata extractor#234

Merged
github-actions[bot] merged 1 commit into
llm-d:mainfrom
abdallahsamabd:feature/issue-230-multi-format-extractor
Jul 15, 2026
Merged

[Feature] Add Anthropic and Google (Gemini) response format support to requestcostmetadata extractor#234
github-actions[bot] merged 1 commit into
llm-d:mainfrom
abdallahsamabd:feature/issue-230-multi-format-extractor

Conversation

@abdallahsamabd

Copy link
Copy Markdown
Contributor

What type of PR is this?

/kind feature
/kind test

What this PR does / why we need it:

The requestcostmetadata extractor currently only parses OpenAI-formatted responses (usage.prompt_tokens / usage.completion_tokens). This PR adds auto-detection and extraction support for Anthropic (usage.input_tokens / usage.output_tokens) and Google/Gemini (usageMetadata.promptTokenCount / usageMetadata.candidatesTokenCount) response formats.

The extractor inspects the response body structure to determine the format — no user configuration needed. This ensures CostGuard can observe actual inference costs from all major LLM providers.

Which issue(s) this PR fixes:

Fixes #230

Release note (write NONE if no user-facing change):

NONE

@github-actions github-actions Bot added kind/feature Categorizes issue or PR as related to a new feature. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. kind/test Categorizes issue or PR as related to tests. labels Jul 12, 2026
@abdallahsamabd
abdallahsamabd marked this pull request as draft July 12, 2026 14:40
@abdallahsamabd
abdallahsamabd marked this pull request as ready for review July 13, 2026 10:16
@abdallahsamabd
abdallahsamabd force-pushed the feature/issue-230-multi-format-extractor branch from d2259a9 to 1fbae59 Compare July 13, 2026 10:16
@github-actions github-actions Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jul 13, 2026
@abdallahsamabd
abdallahsamabd force-pushed the feature/issue-230-multi-format-extractor branch from 1fbae59 to 4aae3db Compare July 13, 2026 10:18
@github-actions github-actions Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jul 13, 2026
@abdallahsamabd
abdallahsamabd force-pushed the feature/issue-230-multi-format-extractor branch from 4aae3db to 8491ce2 Compare July 13, 2026 10:21
@abdallahsamabd

Copy link
Copy Markdown
Contributor Author

@shmuelk @davidbreitgand

@davidbreitgand davidbreitgand left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@abdallahsamabd : Nice! Thanks for this PR.

}

func extractOpenAI(body map[string]any) (prompt, completion float64, ok bool) {
usage := body["usage"].(map[string]any)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: potentially confusing usage of unchecked type assertion

Suggested change
usage := body["usage"].(map[string]any)
// Safe: detectFormat() verified "usage" key exists and is map[string]any
usage := body["usage"].(map[string]any)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@abdallahsamabd , actually, thinking more about this... I'm not sure why you need this type assertion at all. detectFormat() already validated the structure, the extract functions seem to re-validate the exact same structure. No mutation occurs between detectFormat() and extractOpenAI()/extractAnthropic()/extractGoogle() calls. Why do we need this additional assertion?
The same question for Lines 290 and 303.

}

func extractAnthropic(body map[string]any) (prompt, completion float64, ok bool) {
usage := body["usage"].(map[string]any)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ditto

}

func extractGoogle(body map[string]any) (prompt, completion float64, ok bool) {
usageMetadata := body["usageMetadata"].(map[string]any)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ditto.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I refactored to inline the detection and pass the validated sub-map directly to each extractor, eliminating both the redundant assertions and the separate detectFormat function

…metadata extractor

The extractTokenCounts function now auto-detects the response format by inspecting the response body structure and dispatches to format-specific extraction helpers for OpenAI, Anthropic, and Google/Gemini.

This enables CostGuard to observe actual inference costs from all major LLM providers without any user configuration.

Fixes llm-d#230

Signed-off-by: Abdallah Samara <abdallahsamabd@gmail.com>
@abdallahsamabd
abdallahsamabd force-pushed the feature/issue-230-multi-format-extractor branch from 8491ce2 to e229a5b Compare July 14, 2026 21:48
@shmuelk

shmuelk commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

/lgtm
/approve

@github-actions github-actions Bot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jul 15, 2026
@github-actions
github-actions Bot merged commit 4da7f0e into llm-d:main Jul 15, 2026
10 of 11 checks passed
@ronenkat ronenkat mentioned this pull request Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/feature Categorizes issue or PR as related to a new feature. kind/test Categorizes issue or PR as related to tests. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Add Anthropic and Google (Gemini) response format support to requestcostmetadata extractor

3 participants