-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat:OpenAPI: tool_choice now anyOf (string or ChatTools), docs expanded #218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThe OpenAPI schema for OpenAIChatCompletionsIn.tool_choice was changed from a string to a polymorphic anyOf (string or ChatTools object) with an expanded description covering "none," "auto," "required," and explicit tool selection. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Client
participant API as Chat Completions API
participant Router as Tool Router
participant Tool as Tool Executor
rect rgb(240,248,255)
note right of Client: Submit chat request with tool_choice
Client->>API: POST /chat/completions<br/>tool_choice
end
alt tool_choice is "none" or "auto"
API->>Router: Determine tool call (if any)
opt auto selects a tool
Router->>Tool: Invoke selected tool
Tool-->>Router: Result
end
Router-->>API: Tool decision/result
API-->>Client: Chat completion (with/without tool call)
else tool_choice is "required"
API->>Router: Must choose a tool
Router->>Tool: Invoke required tool
Tool-->>Router: Result
API-->>Client: Chat completion with tool call
else tool_choice is ChatTools object (explicit)
note over API,Router: Object may specify a defined tool to call
API->>Router: Use provided ChatTools definition/selection
Router->>Tool: Invoke specified tool
Tool-->>Router: Result
API-->>Client: Chat completion with explicit tool call
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ 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. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (2)
src/libs/DeepInfra/openapi.yaml (2)
6401-6404: Clarify description and add examples for both formsThe current description mentions a “defined tool” but doesn’t show the object shape or the requirement that it must match tools[]. Please tighten language and add examples to reduce client ambiguity.
Apply this diff in-place:
- description: Controls which (if any) function is called by the model. none means the model will not call a function and instead generates a message. auto means the model can pick between generating a message or calling a function. required means the model must call a function. defined tool means the model must call that specific tool. none is the default when no functions are present. auto is the default if functions are present. + description: Controls tool calling behavior. + - "none": model will not call a tool and will only generate a message. + - "auto": model may choose to generate a message or call a tool. + - "required": model must call a tool (one of tools[]). + - object form: {"type":"function","function":{"name":"<toolName>"}} forces that specific tool to be called. The name must match one of tools[].function.name. + Default behavior: if tools are provided and tool_choice is omitted, providers typically default to "auto"; if no tools are provided, tool calls are not possible. + examples: + - none + - auto + - required + - {"type":"function","function":{"name":"get_weather"}}
6400-6405: Consider an explicit default for better SDK typingsIf you want codegen to surface a concrete default, set default: auto on the property (applies to the string branch). This matches common provider behavior and yields clearer client stubs.
Apply this small tweak:
tool_choice: title: Tool Choice + default: autoNote: with oneOf this default will validate against the string branch.
📜 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.
⛔ Files ignored due to path filters (5)
src/libs/DeepInfra/Generated/DeepInfra..JsonSerializerContext.g.csis excluded by!**/generated/**src/libs/DeepInfra/Generated/DeepInfra.DeepInfraClient.OpenaiChatCompletions.g.csis excluded by!**/generated/**src/libs/DeepInfra/Generated/DeepInfra.IDeepInfraClient.OpenaiChatCompletions.g.csis excluded by!**/generated/**src/libs/DeepInfra/Generated/DeepInfra.JsonSerializerContextTypes.g.csis excluded by!**/generated/**src/libs/DeepInfra/Generated/DeepInfra.Models.OpenAIChatCompletionsIn.g.csis excluded by!**/generated/**
📒 Files selected for processing (1)
src/libs/DeepInfra/openapi.yaml(1 hunks)
🔇 Additional comments (2)
src/libs/DeepInfra/openapi.yaml (2)
6401-6404: Document cross-field constraint with tools[]Schema can’t enforce “tool_choice.function.name ∈ tools[].function.name” in OAS 3.0. Add a note so server-side validation can return a 422 when the selector doesn’t match any tool.
Add this sentence at the end of the description: “If object form is used, the function name MUST match one defined in tools[].function.name; otherwise the request is invalid (422).”
6401-6404: Backward compatibility noteThis is a breaking change for generated SDKs and server request deserializers that previously treated tool_choice as a string. Please flag it in release notes and bump the API version or changelog accordingly.
I can help generate client impact notes and a migration checklist if desired.
| anyOf: | ||
| - type: string | ||
| - $ref: '#/components/schemas/ChatTools' | ||
| description: Controls which (if any) function is called by the model. none means the model will not call a function and instead generates a message. auto means the model can pick between generating a message or calling a function. required means the model must call a function. defined tool means the model must call that specific tool. none is the default when no functions are present. auto is the default if functions are present. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid reusing ChatTools in tool_choice; introduce a selector object that only needs a function name
Using ChatTools here invites redefining a tool and duplicating/contradicting entries in tools[]. OpenAI-style selection only needs the function name. Define a minimal selector object and reference that from tool_choice.
Add these schemas under components/schemas (outside this hunk):
ToolChoiceFunction:
title: ToolChoiceFunction
required: [type, function]
type: object
properties:
type:
title: Type
type: string
enum: [function]
default: function
function:
$ref: '#/components/schemas/ToolChoiceFunctionName'
ToolChoiceFunctionName:
title: ToolChoiceFunctionName
required: [name]
type: object
properties:
name:
title: Name
type: string
description: Name of the function to call. Must match one of tools[].function.name.This keeps tools[] for full definitions (parameters, descriptions) and tool_choice for selection only.
🛠️ Refactor suggestion
Constrain tool_choice to valid values and prefer oneOf for disjoint types
Right now any string is accepted, which weakens validation and SDK typings. Since object vs. string are disjoint, oneOf is a better fit and the string branch should enumerate the only allowed literals.
Apply this diff within this block:
- anyOf:
- - type: string
- - $ref: '#/components/schemas/ChatTools'
+ oneOf:
+ - type: string
+ enum: [none, auto, required]
+ - $ref: '#/components/schemas/ToolChoiceFunction'And add the supporting schema below in components/schemas (example provided in a separate block in the next comment).
🤖 Prompt for AI Agents
In src/libs/DeepInfra/openapi.yaml around lines 6401-6404, replace the anyOf
block with a oneOf that distinguishes a literal enum string branch and an object
branch referencing ChatTools, and constrain the string branch to the allowed
literals (none, auto, required, <tool-name> not allowed here — only the
enumerated keywords). Then add a new components/schemas entry (e.g.,
ToolChoiceString) that defines the enum of allowed string values and update the
oneOf to reference that schema alongside the existing ChatTools ref; ensure the
description is preserved and the oneOf usage reflects disjoint types for correct
validation and SDK typing.
💡 Verification agent
❓ Verification inconclusive
Validate the updated spec and sample payloads
Run a quick spec validation and probe example payloads for the new oneOf branch to avoid regressions.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Validate OpenAPI (Python validator)
pip -q install openapi-spec-validator==0.7.1 prance==23.6.21 >/dev/null
python - <<'PY'
from openapi_spec_validator import validate_spec
from prance import ResolvingParser
import sys, json
spec_path = "src/libs/DeepInfra/openapi.yaml"
parser = ResolvingParser(spec_path, resolve_types=ResolvingParser.RESOLVE_INTERNAL)
validate_spec(parser.specification)
print("OpenAPI spec validated OK")
# Sanity-check the tool_choice schema shape
oc = parser.specification["components"]["schemas"]["OpenAIChatCompletionsIn"]["properties"]["tool_choice"]
print("tool_choice schema keys:", list(oc.keys()))
PY
# 2) Optional: spot-check common generators parse it (no generation, just presence)
rg -nC2 'tool_choice' src/libs/DeepInfra/openapi.yaml || trueLength of output: 686
Validate the updated OpenAPI spec with a YAML-based loader
I’ve adjusted the validation approach to avoid the ResolvingParser API mismatch and directly load the YAML. Please run the following to confirm there are no schema errors and that the new anyOf branch for tool_choice is correctly recognized:
– Verify that the anyOf array includes both the string type and the ChatTools $ref.
– Spot-check any code generators or clients (e.g., your OpenAPI-driven SDKs) to ensure they parse the updated tool_choice property without errors.
– Manually craft and send a sample payload covering each anyOf option (plain string, ChatTools object) to your service endpoint to confirm runtime handling.
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
# Install validator and YAML parser
pip install -q openapi-spec-validator==0.7.1 pyyaml==6.0 >/dev/null
# Validate the full spec and inspect the tool_choice schema
python3 - <<'PY'
import yaml
from openapi_spec_validator import validate_spec
spec_path = "src/libs/DeepInfra/openapi.yaml"
with open(spec_path, "r") as f:
spec = yaml.safe_load(f)
# 1) Validate the overall OpenAPI document
validate_spec(spec)
print("✅ OpenAPI spec validated OK")
# 2) Sanity-check the new anyOf branch on tool_choice
tool_choice = spec["components"]["schemas"]["OpenAIChatCompletionsIn"]["properties"]["tool_choice"]
print("tool_choice schema keys:", list(tool_choice.keys()))
print("tool_choice anyOf entries:", tool_choice.get("anyOf"))
PYLength of output: 1101
Critical: Fix invalid parameter schema in OpenAPI spec
The OpenAPI validation failed due to an invalid cookie parameter definition for session in the /payment/checklist GET operation. The schema uses type: 'String' (capital “S”), which isn’t a valid OpenAPI primitive. It must be lowercase string. Please correct this and re-validate.
• Location to fix (in src/libs/DeepInfra/openapi.yaml):
paths:
/payment/checklist:
get:
parameters:
- name: session
in: cookie
schema:
type: string # lowercase “string” instead of “String”After updating, rerun the validation:
pip install -q openapi-spec-validator pyyaml
python3 - <<'PY'
import yaml
from openapi_spec_validator import validate_spec
spec = yaml.safe_load(open("src/libs/DeepInfra/openapi.yaml"))
validate_spec(spec)
print("✅ OpenAPI spec validated OK")
PYOnce that’s green, you can then proceed to spot-check the new tool_choice anyOf branch and sample payloads.
🤖 Prompt for AI Agents
In src/libs/DeepInfra/openapi.yaml around lines 6401-6404 (and specifically in
the /payment/checklist GET parameters), the cookie parameter "session" uses an
invalid OpenAPI primitive type "String" (capital S); change it to lowercase
"string" in the parameter's schema, save the file, then re-run the OpenAPI
validator (install openapi-spec-validator and pyyaml if needed) and run the
provided python validation snippet to ensure the spec is valid; after
validation, spot-check the new tool_choice anyOf branch and sample payloads for
any remaining schema issues.
Summary by CodeRabbit
New Features
Documentation