spec: OpenAI-Compatible Native Tool Return - #115
Open
Leoyzen wants to merge 3 commits into
Open
Conversation
Subclass OpenAIChatModel in agentpool to send native list tool return content instead of JSON strings for OpenAI-compatible models (GLM-5, vLLM). Includes profile flag openai_chat_tool_return_as_list, openai_* kwarg passthrough for arbitrary profile overrides, and comprehensive test plan. Closes #112
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
) * feat: implement OpenAICompatibleModel with native list tool return Subclass OpenAIChatModel to emit native list tool return content instead of JSON strings for OpenAI-compatible models (GLM-5, vLLM). - OpenAICompatibleModel(OpenAIChatModel) with _map_user_message override - Profile flag openai_chat_tool_return_as_list (default False) - openai_* kwarg passthrough with string→bool coercion - ImportModelConfig support with base_url, api_key, tool_return_as_list - 25 tests covering all spec scenarios Implements: openspec/changes/openai-compatible-native-tool-return/ * fix: validate openai_* kwargs before OpenAIProvider construction Move profile override validation before OpenAIProvider init so invalid kwargs raise TypeError without requiring OPENAI_API_KEY credentials. Fixes CI failure in test_import_model_config_non_openai_kwarg_raises.
…117) * fix: resolve flaky test_nested_subagents_create_recursive_toolparts Add 200ms sleep before publishing depth=2 spawn event to ensure the parent consumer is fully started. Without this, the event can be missed on slow CI runners, causing the test to hang until timeout. * fix: increase sleep in test_child_done_events_timeout_continues Increase wait from 150ms to 300ms to avoid timing flakiness on slow CI runners where 50ms timeout + two turn executions exceed 150ms. * refactor: use polling loop instead of hardcoded sleep for race condition Replace fixed 200ms sleep with a polling loop that waits for the parent consumer to register in integration._contexts before publishing the depth=2 spawn event. Faster on local machines, more robust on slow CI. Accepts Gemini Code Assist review suggestion.
Collaborator
Author
|
@Million-mo 这里我们需要在重构中考虑,去掉llmming-models的依赖,是直接使用pydantic-ai models 定义,还是我们自己封装一套?尤其是对于模型更细粒度的配置,包括标示是否支持多模态等 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Subclass
OpenAIChatModelin agentpool to send native list tool return content instead of JSON strings for OpenAI-compatible models (GLM-5, vLLM, etc.) whose chat templates natively render list-type tool message content.Problem
pydantic-ai's
OpenAIChatModelalways serializes list-type tool return values to JSON strings viatool_return_ta.dump_json(value).decode(). For models like GLM-5 whose chat templates branch onm.content is stringvs list, this causes:["result1", "result2"]→'["result1", "result2"]')<|tool_return|>block with escaped JSON instead of multiple native blocksSolution
Create
OpenAICompatibleModel(OpenAIChatModel)in agentpool:_map_user_message()— whenopenai_chat_tool_return_as_listflag isTrueand tool return content is a non-empty list with no files, emitlist[ChatCompletionContentPartTextParam]instead of JSON stringopenai_chat_tool_return_as_list: bool(defaults toFalsefor backward compat)openai_*kwarg passthrough — anyopenai_*prefixed key in YAMLkw_argsis auto-merged into the profile dict with type coercion (string→bool for known boolean keys)base_url,api_key,tool_return_as_listas constructor paramsYAML Example
Artifacts
openspec/changes/openai-compatible-native-tool-return/proposal.md— motivation, problem, proposalopenspec/changes/openai-compatible-native-tool-return/design.md— 7 decisions with pseudocodeopenspec/changes/openai-compatible-native-tool-return/specs/openai-compatible-model/spec.md— 5 requirements, 11 scenariosopenspec/changes/openai-compatible-native-tool-return/tasks.md— 3 task groups, 18 subtasksReferences
model_response_strpydantic/pydantic-ai#3888Closes #112
@Million-mo 请实现这个 spec 🙏