fix: correct Gemini channel model retrieval logic - #1486
Conversation
WalkthroughThe code introduces support for a new "Gemini" channel type in the Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller
participant Upstream (Gemini/OpenAI/Ali)
Client->>Controller: FetchUpstreamModels(channelType)
Controller->>Upstream: HTTP GET (URL & headers based on channelType)
Upstream-->>Controller: Response (Gemini or OpenAI format)
alt Gemini response
Controller->>Controller: Parse as Gemini format
Controller->>Controller: Convert to OpenAI-compatible format
else OpenAI response
Controller->>Controller: Parse as OpenAI format
end
Controller-->>Client: Model list (OpenAI-compatible)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~15 minutes Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
controller/channel.go (2)
205-205: Clarify the comment about Gemini's authentication method.The comment "I don't know why" can be improved to explain that Gemini uses API key as a query parameter instead of an Authorization header.
- body, err = GetResponseBody("GET", url, channel, nil) // I don't know why, but Gemini requires no AuthHeader + body, err = GetResponseBody("GET", url, channel, nil) // Gemini uses API key in URL query parameter instead of Authorization header
239-239: Use English for error messages for consistency.Error messages should be in English to maintain consistency and improve international compatibility.
- "message": fmt.Sprintf("解析响应失败: %s", err.Error()), + "message": fmt.Sprintf("Failed to parse response: %s", err.Error()),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
controller/channel.go(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: 9Ninety
PR: QuantumNous/new-api#1273
File: relay/channel/gemini/relay-gemini.go:97-116
Timestamp: 2025-06-21T03:37:41.726Z
Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior.
📚 Learning: in relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the maxout...
Learnt from: 9Ninety
PR: QuantumNous/new-api#1273
File: relay/channel/gemini/relay-gemini.go:97-116
Timestamp: 2025-06-21T03:37:41.726Z
Learning: In relay/channel/gemini/relay-gemini.go, the thinking budget calculation logic (including the MaxOutputTokens multiplication) was introduced in PR #1247. PR #1273 focused specifically on decoupling the thoughts summary feature from thinking budget settings and did not modify the existing thinking budget behavior.
Applied to files:
controller/channel.go
| type GoogleOpenAICompatibleModels []struct { | ||
| Name string `json:"name"` | ||
| Version string `json:"version"` | ||
| DisplayName string `json:"displayName"` | ||
| Description string `json:"description,omitempty"` | ||
| InputTokenLimit int `json:"inputTokenLimit"` | ||
| OutputTokenLimit int `json:"outputTokenLimit"` | ||
| SupportedGenerationMethods []string `json:"supportedGenerationMethods"` | ||
| Temperature float64 `json:"temperature,omitempty"` | ||
| TopP float64 `json:"topP,omitempty"` | ||
| TopK int `json:"topK,omitempty"` | ||
| MaxTemperature int `json:"maxTemperature,omitempty"` | ||
| } |
There was a problem hiding this comment.
Fix incorrect type definition causing unnecessary nesting.
The type GoogleOpenAICompatibleModels is already defined as a slice, but in GoogleOpenAICompatibleResponse, it's used as []GoogleOpenAICompatibleModels, creating a slice of slices. This appears to be a mistake based on the usage pattern.
Apply this diff to fix the type definitions:
-type GoogleOpenAICompatibleModels []struct {
+type GoogleOpenAICompatibleModel struct {
Name string `json:"name"`
Version string `json:"version"`
DisplayName string `json:"displayName"`
Description string `json:"description,omitempty"`
InputTokenLimit int `json:"inputTokenLimit"`
OutputTokenLimit int `json:"outputTokenLimit"`
SupportedGenerationMethods []string `json:"supportedGenerationMethods"`
Temperature float64 `json:"temperature,omitempty"`
TopP float64 `json:"topP,omitempty"`
TopK int `json:"topK,omitempty"`
MaxTemperature int `json:"maxTemperature,omitempty"`
}
type GoogleOpenAICompatibleResponse struct {
- Models []GoogleOpenAICompatibleModels `json:"models"`
+ Models []GoogleOpenAICompatibleModel `json:"models"`
NextPageToken string `json:"nextPageToken"`
}Also applies to: 58-61
🤖 Prompt for AI Agents
In controller/channel.go around lines 39 to 51 and 58 to 61, the type
GoogleOpenAICompatibleModels is defined as a slice of structs, but it is used as
a slice of GoogleOpenAICompatibleModels elsewhere, causing an unintended slice
of slices. To fix this, redefine GoogleOpenAICompatibleModels as a single struct
instead of a slice, and update all references to use a slice of this struct
type, eliminating the extra nesting.
| for _, model := range googleResult.Models { | ||
| for _, gModel := range model { | ||
| result.Data = append(result.Data, OpenAIModel{ | ||
| ID: gModel.Name, | ||
| }) | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Simplify the nested loop after fixing the type definition.
Once the type definition is fixed as suggested above, this double nested loop should be simplified.
After applying the struct fix, update this code:
- for _, model := range googleResult.Models {
- for _, gModel := range model {
- result.Data = append(result.Data, OpenAIModel{
- ID: gModel.Name,
- })
- }
- }
+ for _, model := range googleResult.Models {
+ result.Data = append(result.Data, OpenAIModel{
+ ID: model.Name,
+ })
+ }📝 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.
| for _, model := range googleResult.Models { | |
| for _, gModel := range model { | |
| result.Data = append(result.Data, OpenAIModel{ | |
| ID: gModel.Name, | |
| }) | |
| } | |
| } | |
| for _, model := range googleResult.Models { | |
| result.Data = append(result.Data, OpenAIModel{ | |
| ID: model.Name, | |
| }) | |
| } |
🤖 Prompt for AI Agents
In controller/channel.go around lines 223 to 229, after correcting the type
definition of googleResult.Models as suggested, simplify the nested loops by
iterating directly over the corrected slice or map structure without the
unnecessary inner loop. Adjust the loop to a single level that appends
OpenAIModel instances to result.Data using the corrected type elements.
fix: correct Gemini channel model retrieval logic
Summary by CodeRabbit
New Features
Bug Fixes