fix(model): delegate supportsNativeStructuredOutput to formatter#1832
fix(model): delegate supportsNativeStructuredOutput to formatter#1832chickenlj wants to merge 1 commit into
Conversation
OpenAIChatModel.supportsNativeStructuredOutput() hardcoded true, but many OpenAI-compatible backends (DeepSeek, vLLM, Ollama, GLM) do not support response_format with json_schema. This caused structured output calls (agent.call(msg, OutputClass.class)) to fail with HTTP 400. Add supportsNativeStructuredOutput() to OpenAIChatFormatter (default true) and override to false in DeepSeekFormatter, GLMFormatter, and their multi-agent variants. OpenAIChatModel now delegates to the formatter, so the agent automatically falls back to the generate_response tool approach for unsupported backends. Fixes #1742 Fixes #1720
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
AgentScopeJavaBot
left a comment
There was a problem hiding this comment.
🤖 AI Review
This PR fixes a bug where OpenAIChatModel.supportsNativeStructuredOutput() was hardcoded to true, causing HTTP 400 errors on OpenAI-compatible backends (DeepSeek, GLM) that don't support response_format with json_schema. The fix introduces supportsNativeStructuredOutput() to OpenAIChatFormatter (defaulting to true) and overrides it to false in DeepSeek/GLM formatters. OpenAIChatModel now delegates to the formatter via instanceof check. This correctly resolves issues #1742 and #1720. The approach is sound — pushing the capability query to the formatter layer where provider-specific knowledge belongs. Suggestion: consider adding supportsNativeStructuredOutput() to the Formatter interface as a default method to eliminate the instanceof dependency. Unit tests for the new method are recommended.
| * | ||
| * @return true if native structured output is supported, false otherwise | ||
| */ | ||
| public boolean supportsNativeStructuredOutput() { |
There was a problem hiding this comment.
[recommended] Architecture improvement: supportsNativeStructuredOutput() is defined on OpenAIChatFormatter concrete class rather than the Formatter interface, requiring OpenAIChatModel to use instanceof check. Consider adding default boolean supportsNativeStructuredOutput() { return false; } to the Formatter interface, eliminating the instanceof dependency and making it easier for custom formatters to declare their capabilities.
| @@ -193,7 +193,10 @@ public String getModelName() { | |||
|
|
|||
| @Override | |||
| public boolean supportsNativeStructuredOutput() { | |||
There was a problem hiding this comment.
[recommended] Missing unit tests: No tests were added for the new supportsNativeStructuredOutput() delegation. Recommended coverage: (1) OpenAIChatFormatter default returns true; (2) DeepSeekFormatter / GLMFormatter return false; (3) OpenAIChatModel correctly delegates to the formatter; (4) Non-OpenAIChatFormatter formatters return false.
AgentScopeJavaBot
left a comment
There was a problem hiding this comment.
🤖 AI Review
This PR fixes a bug where OpenAIChatModel.supportsNativeStructuredOutput() was hardcoded to true, causing HTTP 400 errors on OpenAI-compatible backends (DeepSeek, GLM) that don't support response_format with json_schema. The fix introduces supportsNativeStructuredOutput() to OpenAIChatFormatter (defaulting to true) and overrides it to false in DeepSeek/GLM formatters. OpenAIChatModel now delegates to the formatter via instanceof check. This correctly resolves issues #1742 and #1720. The approach is sound — pushing the capability query to the formatter layer where provider-specific knowledge belongs. Suggestion: consider adding supportsNativeStructuredOutput() to the Formatter interface as a default method to eliminate the instanceof dependency. Unit tests for the new method are recommended.
| * | ||
| * @return true if native structured output is supported, false otherwise | ||
| */ | ||
| public boolean supportsNativeStructuredOutput() { |
There was a problem hiding this comment.
[recommended] Architecture improvement: supportsNativeStructuredOutput() is defined on OpenAIChatFormatter concrete class rather than the Formatter interface, requiring OpenAIChatModel to use instanceof check. Consider adding default boolean supportsNativeStructuredOutput() { return false; } to the Formatter interface, eliminating the instanceof dependency and making it easier for custom formatters to declare their capabilities.
| @@ -193,7 +193,10 @@ public String getModelName() { | |||
|
|
|||
| @Override | |||
| public boolean supportsNativeStructuredOutput() { | |||
There was a problem hiding this comment.
[recommended] Missing unit tests: No tests were added for the new supportsNativeStructuredOutput() delegation. Recommended coverage: (1) OpenAIChatFormatter default returns true; (2) DeepSeekFormatter / GLMFormatter return false; (3) OpenAIChatModel correctly delegates to the formatter; (4) Non-OpenAIChatFormatter formatters return false.
Summary
OpenAIChatModel.supportsNativeStructuredOutput()hardcodedtrue, but many OpenAI-compatible backends (DeepSeek, vLLM, Ollama, GLM) don't supportresponse_formatwithjson_schema. This causedagent.call(msg, OutputClass.class)to fail with HTTP 400 on these backends.supportsNativeStructuredOutput()toOpenAIChatFormatter(defaulttrue) and overrode tofalseinDeepSeekFormatter,DeepSeekMultiAgentFormatter,GLMFormatter, andGLMMultiAgentFormatter.OpenAIChatModelnow delegates to the formatter, so the agent automatically falls back to thegenerate_responsetool approach for unsupported backends.Fixes #1742
Fixes #1720