weiqingy opened a new issue, #1246: URL: https://github.com/apache/flink-agents/issues/1246
### Search before asking - [x] I searched in the [issues](https://github.com/apache/flink-agents/issues) and found nothing similar. ### Description Since #1215, a Java agent's output schema is sent to the provider natively. The OpenAI, Azure OpenAI and Anthropic connections build that schema through their SDKs' structured-output builders (`toNativeResponseFormat` in `OpenAICompletionsConnection` and `AzureOpenAIChatModelConnection`, `toNativeOutputConfig` in `AnthropicChatModelConnection`). Both SDKs configure victools with a bare `JacksonModule()`. They ignore `@JsonProperty` on enum constants and `@JsonValue` methods, so the schema lists the Java constant names. When an enum's Jackson values differ from its names, the model follows the schema. The reply then fails to parse in `ChatModelAction.generateStructuredOutput` with `InvalidFormatException`, reported as a model-output parse error. Since #1120, the other Java providers (Ollama, Gemini, Bedrock, watsonx) use `PojoJsonSchemaGenerator`, which lists the Jackson values. As a result, the same enum needs opposite annotations depending on the provider: | Enum | OpenAI / Azure / Anthropic | Ollama / Gemini / Bedrock / watsonx | |---|---|---| | `@JsonProperty` on every constant | `["POSITIVE", ...]`, fails to parse | `["positive", ...]`, works | | `@JsonValue` returning a `String` | `["POSITIVE", ...]`, fails to parse | `["positive", ...]`, works | | No annotations | `["POSITIVE", ...]`, works | `["POSITIVE", ...]`, works | Upgrading the SDKs does not help. The latest openai-java (4.80.0) and anthropic-java (2.71.0) still use a bare `JacksonModule()`. Proposed fix: build these three schemas with `PojoJsonSchemaGenerator` as well. Then one enum rule holds for every Java provider, and it matches Python, where pydantic also lists enum values. Two differences need handling so the requests stay valid: - OpenAI strict mode needs every property in `required` and `additionalProperties: false`. Today the shared generator leaves `Optional` fields out of `required` and adds no `additionalProperties`. So it needs a way to require every field (an `Optional` field stays nullable), plus `FORBIDDEN_ADDITIONAL_PROPERTIES_BY_DEFAULT`. - Anthropic also needs `additionalProperties: false`. One visible side effect: properties come out in declaration order instead of alphabetical order, the same as the other providers and Python. Each of the three connections gets an enum round-trip test, like the existing `derivedSchemaFollowsJacksonEnumValues` tests. ### How to reproduce ```java enum Sentiment { @JsonProperty("positive") POSITIVE, @JsonProperty("negative") NEGATIVE } class Result { public String summary; public Sentiment sentiment; } ``` Use `Result.class` as the output schema of a Java agent on OpenAI, Azure OpenAI or Anthropic. The request carries `"sentiment": {"type": "string", "enum": ["POSITIVE", "NEGATIVE"]}`. A reply that follows it, for example `{"summary": "ok", "sentiment": "POSITIVE"}`, fails `new ObjectMapper().readValue(reply, Result.class)`. No credentials are needed to see the schema. The SDK builder the connections call returns it offline: ```java ChatCompletionCreateParams.builder() .model(ChatModel.of("")) .addUserMessage("") .responseFormat(Result.class, JsonSchemaLocalValidation.NO) .build() .rawParams() .responseFormat(); ``` ### Version and environment `main` at `6d0a261d` (after #1215), openai-java 4.8.0, anthropic-java 2.12.0, Java 11. ### Are you willing to submit a PR? - [x] I'm willing to submit a PR! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
