feat: openai custom tool - #2157
Conversation
WalkthroughAdded support for OpenAI's custom tool type in the Chat Completion API by introducing a CustomType constant and a new optional Custom field to the ToolCallRequest struct, while making the existing Function field optional. Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
dto/openai_request.go (1)
186-201: Update token counting logic to handle custom tools.The token counting logic doesn't account for the new custom tool type. Currently, it unconditionally accesses
tool.Functionfields for all tools, which means:
- Custom tools (with empty Function fields) will add empty strings to the token count
- The
Customfield content is completely ignored, potentially leading to inaccurate token counts and billingApply this diff to properly handle custom tools in token counting:
if r.Tools != nil { openaiTools := r.Tools for _, tool := range openaiTools { tokenCountMeta.ToolsCount++ - texts = append(texts, tool.Function.Name) - if tool.Function.Description != "" { - texts = append(texts, tool.Function.Description) - } - if tool.Function.Parameters != nil { - texts = append(texts, fmt.Sprintf("%v", tool.Function.Parameters)) + if tool.Type == CustomType { + // Include custom tool data in token counting + if tool.Custom != nil { + texts = append(texts, string(tool.Custom)) + } + } else { + // Handle function tools + texts = append(texts, tool.Function.Name) + if tool.Function.Description != "" { + texts = append(texts, tool.Function.Description) + } + if tool.Function.Parameters != nil { + texts = append(texts, fmt.Sprintf("%v", tool.Function.Parameters)) + } } } - //toolTokens := CountTokenInput(countStr, request.Model) - //tkm += 8 - //tkm += toolTokens }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
dto/openai_request.go(1 hunks)
🔇 Additional comments (1)
dto/openai_request.go (1)
235-235: LGTM! Consider using this constant for validation.The constant declaration follows Go conventions and provides a clear reference for the custom tool type. Consider using this constant in validation logic to ensure type safety when checking tool types.
| type ToolCallRequest struct { | ||
| ID string `json:"id,omitempty"` | ||
| Type string `json:"type"` | ||
| Function FunctionRequest `json:"function"` | ||
| Function FunctionRequest `json:"function,omitempty"` | ||
| Custom json.RawMessage `json:"custom,omitempty"` | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Add validation to ensure proper field population based on Type.
The struct changes correctly support both function and custom tools, but there's no validation to ensure:
- When
Typeis "function",Functionshould be populated - When
Typeis "custom",Customshould be populated - Invalid combinations are rejected
Consider adding a validation method to ToolCallRequest to enforce these constraints and prevent malformed requests.
Example validation method you could add after the struct definition:
// Validate checks that the tool call request is properly formed
func (t *ToolCallRequest) Validate() error {
if t.Type == CustomType {
if t.Custom == nil {
return fmt.Errorf("custom tool requires 'custom' field")
}
} else if t.Type == "function" {
if t.Function.Name == "" {
return fmt.Errorf("function tool requires 'function' field with name")
}
}
return nil
}🤖 Prompt for AI Agents
In dto/openai_request.go around lines 237-242, the ToolCallRequest struct lacks
validation for Type-specific fields; add a Validate() error method that
enforces: when Type == "custom" ensure Custom is non-nil and not empty
(len(Custom)>0), when Type == "function" ensure Function is populated (e.g.,
Function.Name != ""), otherwise return a descriptive error (use fmt.Errorf). Use
existing constants for types if available, make the method receiver pointer
(*ToolCallRequest) and ensure callers invoke Validate() before processing the
request.
* main: (77 commits) refactor(adaptor): Comment out enable_thinking logic for clarity and future adjustments fix GetChannelKey AdminAuth -> RootAuth fix GetChannelKey AdminAuth -> RootAuth feat: vidu reference2video only viduq2 feat: vidu specify reference2video via metadata action 同步多语言README文档 chore: Update README.md for improved structure and clarity, including new sections for partners, acknowledgments, and deployment instructions feat: replicate channel flux model feat: ShouldPreserveThinkingSuffix (#2189) fix(channel): 当没有可用密钥时返回错误而不是第一个密钥 fix: update tag normalization regex feat: restrict automatic channel testing to master node only feat: EditTagModal header && param (#2159) add custom tool (#2157) fix playground (#2153) feat: add TASK_PRICE_PATCH environment variable for per-task billing configuration feat: EditTokenModal 中针对用户创建的 token 默认无限额度 feat: add environment variable switch for critical rate limit feat: enhance Ali video request processing with resolution mapping and size validation fix: logger ...
fix #2144
Summary by CodeRabbit