Skip to content

feat(models): add metadata - #716

Merged
steebchen merged 2 commits into
mainfrom
terragon/implement-feature-issue-714
Sep 2, 2025
Merged

steebchen merged 2 commits into
mainfrom
terragon/implement-feature-issue-714

Conversation

@steebchen

@steebchen steebchen commented Sep 2, 2025 •

Copy link
Copy Markdown
Member

Summary

  • Enhances the chat completion response format by including detailed metadata about the requested and used models and providers.
  • Updates the transformToOpenAIFormat function to append metadata fields such as requested_model, requested_provider, used_model, used_provider, and underlying_used_model.
  • Modifies the model field in responses to use a combined format ${usedProvider}/${baseModelName} for clarity.
  • Extends the response schema to validate the new metadata structure.

Changes

Core Functionality

  • Added parameters requestedModel, requestedProvider, and baseModelName to the transformToOpenAIFormat function.
  • Updated all relevant response constructions to include the new metadata object.
  • Changed the model field in responses to a combined string format reflecting provider and base model.
  • Added metadata validation schema in the chat completions route.

Code Quality

  • Improved consistency in response formatting across different providers.
  • Ensured metadata is added even for default and unknown providers.

Test plan

  • Verify that chat completion responses include the new metadata fields.
  • Confirm that the model field is correctly formatted as ${usedProvider}/${baseModelName}.
  • Validate that the new metadata schema is enforced without breaking existing functionality.
  • Test with multiple providers to ensure metadata is consistently applied.

🌿 Generated by Terry


ℹ️ Tag @terragon-labs to ask questions and address PR feedback

📎 Task: https://www.terragonlabs.com/task/3bcaaf42-29c4-4bd9-a837-6a97ee302ddf

Summary by CodeRabbit

  • New Features

    • Responses now include a metadata object with requested_model, requested_provider, used_model, used_provider, and underlying_used_model.
    • Standardized model naming for non-OpenAI providers to provider/baseModelName in the response.
  • Documentation

    • Updated OpenAPI schema for the completions endpoint to document the new metadata field and the standardized model naming in 200 responses.
  • Refactor

    • Consistent metadata emission and model naming applied across all supported providers.

- Add metadata object with requested_model, requested_provider, used_model, used_provider, and underlying_used_model fields
- Update model field format to use provider/model pattern (e.g. openai/gpt-4o-mini)
- Implement metadata for all provider response transformations
- All unit tests passing with new metadata structure

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 2, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

Adds requestedModel/requestedProvider/baseModelName to transformToOpenAIFormat and call site. Normalizes model string to provider/baseModelName for non-OpenAI providers. Injects metadata (requested/used models/providers and underlying_used_model) into all OpenAI-format responses. Updates OpenAPI 200 response schema to include metadata. Applies changes across multiple provider branches.

Changes

Cohort / File(s) Summary
Chat transformation and OpenAPI schema
apps/gateway/src/chat/chat.ts
- transformToOpenAIFormat signature extended with requestedModel, requestedProvider, baseModelName
- Call site passes modelInput, requestedProvider||null, baseModelName
- Model normalization: non-OpenAI model set to ${usedProvider}/${baseModelName}; original kept as underlying_used_model in metadata
- Response augmented with metadata: requested_model, requested_provider, used_model, used_provider, underlying_used_model
- OpenAPI: completions 200 response schema includes metadata object with the above fields
- Applied across google-vertex, google-ai-studio, anthropic, inference.net, together.ai, groq, openai branches

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant G as Gateway Chat Handler
  participant P as Provider Adapter (OpenAI/Anthropic/Google/... )
  participant T as transformToOpenAIFormat

  C->>G: POST /chat/completions (modelInput, provider, ...)
  G->>P: Execute request (usedProvider, usedModel, ...)
  P-->>G: Provider response (json, tokens, ...)
  Note over G: Compute baseModelName
  G->>T: Transform(json, content, tokens,<br/>requestedModel, requestedProvider, baseModelName)
  T-->>G: OpenAI-format response<br/>- model: provider/baseModelName (non-OpenAI)<br/>- metadata{requested_*, used_*, underlying_used_model}
  G-->>C: 200 OK OpenAI-format response (+metadata)

  rect rgba(230,245,255,0.5)
  Note over T: New/changed behavior:<br/>model normalization + metadata emission
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–60 minutes

Possibly related PRs

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch terragon/implement-feature-issue-714

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions Bot changed the title Add detailed model metadata to chat completion responses feat(models): add metadata Sep 2, 2025
@steebchen
steebchen marked this pull request as ready for review September 2, 2025 18:36
@steebchen
steebchen enabled auto-merge September 2, 2025 18:40
@steebchen
steebchen added this pull request to the merge queue Sep 2, 2025

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 0

🧹 Nitpick comments (4)
apps/gateway/src/chat/chat.ts (4)

831-833: Tighten the type of requestedProvider

Use the Provider union instead of a plain string for better type-safety.

 function transformToOpenAIFormat(
   usedProvider: Provider,
   usedModel: string,
@@
-  requestedModel: string,
-  requestedProvider: string | null,
+  requestedModel: string,
+  requestedProvider: Provider | null,
   baseModelName: string,
 )

844-844: Normalize streaming model too for consistency

Non-streaming responses set model to ${usedProvider}/${baseModelName}, but streaming chunks still emit usedModel/upstream values. This can surprise clients switching between stream=false/true.

Minimal approach:

  • Compute once: const normalizedModel = ${usedProvider}/${baseModelName};
  • Pass it to the streaming transformer and use it for the model field in emitted chunks.

Example changes:

@@
- function transformStreamingChunkToOpenAIFormat(
-   usedProvider: Provider,
-   usedModel: string,
-   data: any,
-   messages: any[],
- ): any {
+ function transformStreamingChunkToOpenAIFormat(
+   usedProvider: Provider,
+   usedModel: string,
+   data: any,
+   messages: any[],
+   normalizedModel: string,
+ ): any {
@@
-  model: data.model || usedModel,
+  model: normalizedModel,

And at the call site:

- const transformedData = transformStreamingChunkToOpenAIFormat(
-   usedProvider, usedModel, data, messages
- );
+ const normalizedModel = `${usedProvider}/${baseModelName}`;
+ const transformedData = transformStreamingChunkToOpenAIFormat(
+   usedProvider, usedModel, data, messages, normalizedModel
+ );

Also applies to: 896-896, 950-950, 994-994, 1013-1013, 1055-1055, 1070-1070


881-887: Great: unified metadata across providers; consider parity for streaming

The new metadata object looks solid and consistent across providers for non-streaming. For parity, emit a one-time SSE “metadata” event at stream start so streaming consumers can access the same fields.

Add after obtaining the reader in the streaming branch:

@@
- const reader = res.body.getReader();
+ const reader = res.body.getReader();
+ // Emit metadata once so streaming clients get the same context as non-streaming
+ await writeSSEAndCache({
+   event: "metadata",
+   data: JSON.stringify({
+     requested_model: modelInput,
+     requested_provider: requestedProvider ?? null,
+     used_model: baseModelName,
+     used_provider: usedProvider,
+     underlying_used_model: usedModel,
+   }),
+   id: String(eventId++),
+ });

Also applies to: 932-938, 975-981, 995-1001, 1044-1051, 1055-1063, 1070-1076


1897-1903: Schema update LGTM; add example for better docs

The metadata schema addition is correct. Consider adding an OpenAPI example to improve generated docs.

- metadata: z.object({
+ metadata: z.object({
     requested_model: z.string(),
     requested_provider: z.string().nullable(),
     used_model: z.string(),
     used_provider: z.string(),
     underlying_used_model: z.string(),
- }),
+ }).openapi({
+   example: {
+     requested_model: "openai/gpt-4o",
+     requested_provider: "openai",
+     used_model: "gpt-4o",
+     used_provider: "openai",
+     underlying_used_model: "gpt-4o-2024-08-06",
+   },
+ }),
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5a94303 and 5dbbf3b.

📒 Files selected for processing (1)
  • apps/gateway/src/chat/chat.ts (12 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use localStorage instead of cookies for client-side data persistence

Files:

  • apps/gateway/src/chat/chat.ts
**/*.{js,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,ts}: Use drizzle with the latest object syntax for database operations
For read queries, always use db().query.<table>.findMany() or db().query.<table>.findFirst()

Files:

  • apps/gateway/src/chat/chat.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Never use as any or : any in TypeScript files.

Files:

  • apps/gateway/src/chat/chat.ts
apps/{api,gateway}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

apps/{api,gateway}/**/*.{ts,tsx}: Use Drizzle with the latest object syntax for database operations
For read queries, use db().query.

.findMany() or db().query.
.findFirst()

apps/{api,gateway}/**/*.{ts,tsx}: Use the Hono framework for backend HTTP services in apps/api and apps/gateway
Use Zod for request/response validation in backend routes and handlers
Maintain OpenAPI/Swagger documentation for backend APIs

Files:

  • apps/gateway/src/chat/chat.ts
apps/gateway/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

In apps/gateway (Hono), always use Hono + Zod + OpenAPI for validation and typesafety

Files:

  • apps/gateway/src/chat/chat.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: e2e / run
  • GitHub Check: build / run
🔇 Additional comments (1)
apps/gateway/src/chat/chat.ts (1)

4400-4403: Passing raw requested inputs is correct

Forwarding the user’s raw model/provider/baseModelName into the transformer matches the new metadata contract.

Merged via the queue into main with commit 5cd1c92 Sep 2, 2025
11 of 12 checks passed
@steebchen
steebchen deleted the terragon/implement-feature-issue-714 branch September 2, 2025 18:42
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.

1 participant