Skip to content

feat: improve OpenAI response handling and token usage reporting#246

Merged
appleboy merged 1 commit intomainfrom
patch
Aug 10, 2025
Merged

feat: improve OpenAI response handling and token usage reporting#246
appleboy merged 1 commit intomainfrom
patch

Conversation

@appleboy
Copy link
Owner

@appleboy appleboy commented Aug 10, 2025

  • Ignore errors when determining if the config file exists before creating it
  • Add support for returning detailed prompt token usage in OpenAI responses
  • Use MaxCompletionTokens instead of MaxTokens when specifying completion limits
  • Remove redundant handling for O-series OpenAI models in completion requests

Signed-off-by: appleboy [email protected]

Summary by CodeRabbit

  • New Features

    • Enhanced token usage reporting by including detailed prompt token information in usage statistics for OpenAI completions.
  • Refactor

    • Updated handling of token limits for OpenAI completions to use a unified approach, ensuring consistency across all supported models.
  • Bug Fixes

    • Improved error handling related to configuration file creation.

- Ignore errors when determining if the config file exists before creating it
- Add support for returning detailed prompt token usage in OpenAI responses
- Use MaxCompletionTokens instead of MaxTokens when specifying completion limits
- Remove redundant handling for O-series OpenAI models in completion requests

Signed-off-by: appleboy <[email protected]>
@coderabbitai
Copy link

coderabbitai bot commented Aug 10, 2025

Walkthrough

The updates revise error handling in configuration file existence checks within the command logic and enhance OpenAI provider integration by updating token usage reporting and standardizing the use of the MaxCompletionTokens field in API requests. Deprecated or model-specific logic for token limits is removed, and more detailed token usage is now included in responses.

Changes

Cohort / File(s) Change Summary
Command Config File Error Handling
cmd/cmd.go
Error handling for config file existence check is simplified by ignoring errors from the file existence check and removing the explicit error handling branch. The overall logic for file creation and fatal logging remains unchanged.
OpenAI Provider Token Usage and Request Updates
provider/openai/openai.go
Adds detailed prompt token usage reporting (PromptTokensDetails) to the core.Usage struct. Updates all ChatCompletionRequest constructions to use MaxCompletionTokens instead of the deprecated MaxTokens, and removes legacy model-specific token handling logic.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~7 minutes

Poem

A bunny with code on its mind,
Found config checks streamlined,
And tokens now counted with care—
More details in OpenAI’s lair!
Old logic is gone,
The new flow hops on,
This rabbit approves with a flair! 🐇✨

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch patch

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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
  • 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 src/utils.ts and explain its main purpose.
    • @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 comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai 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

Documentation and Community

  • 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.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @appleboy, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

I've focused on refining the interaction with the OpenAI API and improving configuration file handling. This pull request introduces more detailed token usage reporting, standardizes the use of MaxCompletionTokens for setting completion limits, and streamlines config file creation by ignoring non-critical errors during the existence check. The goal is to make the API integration more robust and provide better insights into token consumption.

Highlights

  • Configuration File Handling: Improved robustness when creating the configuration file by ignoring errors during the initial check for file existence, allowing for smoother setup.
  • OpenAI Token Usage Reporting: Enhanced OpenAI API responses to include detailed prompt token usage, providing more granular insights into API consumption and cost analysis.
  • OpenAI Completion Limits: Standardized the use of MaxCompletionTokens instead of MaxTokens for specifying completion limits in OpenAI requests, aligning with current API best practices and ensuring correct token management.
  • OpenAI Model Handling Simplification: Removed redundant conditional logic specifically for O-series OpenAI models, simplifying the codebase and potentially improving maintainability and clarity.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several improvements. It updates the OpenAI integration to use MaxCompletionTokens instead of MaxTokens, removes redundant logic for specific models, and adds support for detailed prompt token usage in responses. These changes align with recent API updates and enhance reporting capabilities.

Additionally, the logic for handling config file creation is modified to ignore errors when checking for the file's existence. While this simplifies the code, I've provided a suggestion in cmd/cmd.go to log these errors instead of swallowing them completely. This will improve the application's observability and make it easier to diagnose potential file system issues without altering the core logic.

// Config file status could not be determined; handle or ignore as needed
// Optionally: log.Fatalf("failed to check if config file %s is a file: %v", cfgFile, err)
}
exists, _ := file.IsFile(cfgFile)

Choose a reason for hiding this comment

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

medium

Ignoring errors by using the blank identifier _ can hide underlying problems, such as permission issues, that might prevent the application from working correctly. While the subsequent os.Create might also fail and report an error, it's a Go best practice to handle or at least log errors to provide more context for debugging when things go wrong.

    exists, err := file.IsFile(cfgFile)
    if err != nil {
      log.Printf("warning: could not check for config file %s: %v", cfgFile, err)
    }

@appleboy appleboy merged commit b6af6b1 into main Aug 10, 2025
16 of 17 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
cmd/cmd.go (1)

74-81: Don’t ignore IsFile errors; ensure parent dir exists; close the created file

Ignoring the error from file.IsFile can hide permission/path issues. Also, os.Create returns a file handle that isn’t closed, leaking FDs. Finally, creating a user-specified cfgFile should ensure its parent directory exists.

Apply:

-        viper.SetConfigFile(cfgFile)
-        exists, _ := file.IsFile(cfgFile)
-        if !exists {
-            // Config file not found; ignore error if desired
-            _, err := os.Create(cfgFile)
-            if err != nil {
-                log.Fatal(err)
-            }
-        }
+        viper.SetConfigFile(cfgFile)
+        exists, err := file.IsFile(cfgFile)
+        if err != nil && !os.IsNotExist(err) {
+            log.Fatalf("failed to stat config file %s: %v", cfgFile, err)
+        }
+        if !exists {
+            // Ensure parent directory exists for user-provided cfgFile
+            if err := os.MkdirAll(filepath.Dir(cfgFile), os.ModePerm); err != nil {
+                log.Fatalf("failed to create config directory for %s: %v", cfgFile, err)
+            }
+            f, err := os.Create(cfgFile)
+            if err != nil {
+                log.Fatal(err)
+            }
+            defer f.Close()
+        }

And add the missing import:

 import (
     "context"
     "fmt"
     "log"
     "os"
     "path"
+    "path/filepath"
     "strings"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 166cd70 and 543d8f6.

📒 Files selected for processing (2)
  • cmd/cmd.go (1 hunks)
  • provider/openai/openai.go (4 hunks)
⏰ 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). (3)
  • GitHub Check: windows-latest @ Go stable
  • GitHub Check: Analyze (go)
  • GitHub Check: windows-latest @ Go stable
🔇 Additional comments (2)
provider/openai/openai.go (2)

45-53: Include prompt token details in usage: verified

Forwarding PromptTokensDetails significantly improves observability of prompt-side costs.

Confirmed that core.Usage in core/openai.go defines:

  • PromptTokensDetails *openai.PromptTokensDetails
    matching the type from the OpenAI SDK, and that it’s correctly mapped in provider/openai/openai.go.

LGTM!


73-80: Approve Usage details forwarding

Both CompletionTokensDetails and PromptTokensDetails are defined on core.Usage (core/openai.go:18–19), so forwarding them in provider/openai/openai.go is safe and keeps reporting consistent.

Comment on lines 108 to 115
req := openai.ChatCompletionRequest{
Model: c.model,
MaxTokens: c.maxTokens,
Temperature: c.temperature,
TopP: c.topP,
FrequencyPenalty: c.frequencyPenalty,
PresencePenalty: c.presencePenalty,
Model: c.model,
MaxCompletionTokens: c.maxTokens,
Temperature: c.temperature,
TopP: c.topP,
FrequencyPenalty: c.frequencyPenalty,
PresencePenalty: c.presencePenalty,
Messages: []openai.ChatCompletionMessage{
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Switch to MaxCompletionTokens: verify library support and gate zero values

Using MaxCompletionTokens aligns with newer OpenAI APIs. Two follow-ups:

  • Verify the go-openai version in use supports ChatCompletionRequest.MaxCompletionTokens and maps it correctly for both OpenAI and Azure.
  • If c.maxTokens can be 0, avoid sending a zero value unless the JSON tag uses omitempty; otherwise conditionally set it only when > 0.

Check library support and JSON tags:

Additionally, confirm minimal supported version via web search:

Suggested change (apply in both CreateFunctionCall and CreateChatCompletion):

-    req := openai.ChatCompletionRequest{
-        Model:               c.model,
-        MaxCompletionTokens: c.maxTokens,
-        Temperature:         c.temperature,
-        TopP:                c.topP,
-        FrequencyPenalty:    c.frequencyPenalty,
-        PresencePenalty:     c.presencePenalty,
-        ...
-    }
+    req := openai.ChatCompletionRequest{
+        Model:            c.model,
+        Temperature:      c.temperature,
+        TopP:             c.topP,
+        FrequencyPenalty: c.frequencyPenalty,
+        PresencePenalty:  c.presencePenalty,
+        ...
+    }
+    if c.maxTokens > 0 {
+        req.MaxCompletionTokens = c.maxTokens
+    }

Note: If the library lacks MaxCompletionTokens or its JSON tag omitempty is missing, this change may break requests or send an invalid zero; please verify first.

Also applies to: 143-149


🏁 Script executed:

#!/bin/bash
set -e
echo "go-openai version in go.mod/go.sum:"
rg -n "github.com/sashabaranov/go-openai" go.mod go.sum || true

echo "Occurrences of MaxCompletionTokens in repo (and vendored code if present):"
rg -n "MaxCompletionTokens" || true

echo "Definition of ChatCompletionRequest (if vendored):"
rg -n "type ChatCompletionRequest struct" -A 60 vendor 2>/dev/null || true

Length of output: 901


🌐 Web query:

What version of github.com/sashabaranov/go-openai introduced ChatCompletionRequest.MaxCompletionTokens and Usage.PromptTokensDetails?

💡 Result:

ChatCompletionRequest.MaxCompletionTokens and Usage.PromptTokensDetails were both introduced in version v1.39.0 of github.com/sashabaranov/go-openai.

Supporting details:

  • The current API documentation and common.go show PromptTokensDetails as part of the Usage struct5, and recent test code (e.g., chat_test.go) references MaxCompletionTokens in ChatCompletionRequest[3].
  • These fields are absent from the older v1.38.x documentation and changelogs1, but clearly present in the code, tests, and types corresponding with v1.39.0 and newer.
  • Specifically, the releases page shows that v1.39.0 (released April 21, 2025) added features related to detailed tokens accounting, matching these new fields. The changelog for v1.39.0 directly mentions "Add MaxCompletionTokens to ChatCompletionRequest and support detailed token usage," covering both fields.

Summary Table:

Feature Introduced in Version
ChatCompletionRequest.MaxCompletionTokens v1.39.0
Usage.PromptTokensDetails v1.39.0

Reference: See the go-openai releases page and common.go for current field definitions.

Citations:


Switch to MaxCompletionTokens: v1.40.5 supports it; guard zero values

We’re on v1.40.5 (introduced in v1.39.0), so ChatCompletionRequest.MaxCompletionTokens is available for both OpenAI and Azure backends. To avoid sending an explicit 0 when c.maxTokens isn’t set, only assign it when > 0. If the library’s JSON tag for MaxCompletionTokens isn’t omitempty, this guard is required; otherwise it’s optional.

• Locations to update:

  • provider/openai/openai.go, lines 108–115
  • provider/openai/openai.go, lines 143–149

Suggested refactor in both CreateChatCompletion and CreateFunctionCall:

@@ -108,8 +108,6 @@ func (c *Client) CreateChatCompletion(ctx context.Context, messages []openai.Ch
-   req := openai.ChatCompletionRequest{
-       Model:               c.model,
-       MaxCompletionTokens: c.maxTokens,
-       Temperature:         c.temperature,
-       TopP:                c.topP,
-       FrequencyPenalty:    c.frequencyPenalty,
-       PresencePenalty:     c.presencePenalty,
-       Messages:            messages,
-   }
+   req := openai.ChatCompletionRequest{
+       Model:            c.model,
+       Temperature:      c.temperature,
+       TopP:             c.topP,
+       FrequencyPenalty: c.frequencyPenalty,
+       PresencePenalty:  c.presencePenalty,
+       Messages:         messages,
+   }
+   if c.maxTokens > 0 {
+       req.MaxCompletionTokens = c.maxTokens
+   }

Apply the same change at lines 143–149.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
req := openai.ChatCompletionRequest{
Model: c.model,
MaxTokens: c.maxTokens,
Temperature: c.temperature,
TopP: c.topP,
FrequencyPenalty: c.frequencyPenalty,
PresencePenalty: c.presencePenalty,
Model: c.model,
MaxCompletionTokens: c.maxTokens,
Temperature: c.temperature,
TopP: c.topP,
FrequencyPenalty: c.frequencyPenalty,
PresencePenalty: c.presencePenalty,
Messages: []openai.ChatCompletionMessage{
req := openai.ChatCompletionRequest{
Model: c.model,
Temperature: c.temperature,
TopP: c.topP,
FrequencyPenalty: c.frequencyPenalty,
PresencePenalty: c.presencePenalty,
Messages: messages,
}
if c.maxTokens > 0 {
req.MaxCompletionTokens = c.maxTokens
}
🤖 Prompt for AI Agents
In provider/openai/openai.go at lines 108 to 115 and 143 to 149, the
MaxCompletionTokens field in ChatCompletionRequest is always set, which can send
an explicit zero value if c.maxTokens is not set. To fix this, modify the code
to assign MaxCompletionTokens only when c.maxTokens is greater than zero,
preventing sending zero values unnecessarily. Apply this conditional assignment
in both the CreateChatCompletion and CreateFunctionCall functions at the
specified lines.

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