spring-projects / spring-projects/spring-ai

Support for BeanOutputConverter with non-standard enum mapping

Open
#1,985 3 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

structured output
Dominant language
Java
Stars
9.5k
Forks
2.9k
Avg merge
1d 7h
Merged PRs (30d)
6

Description

Expected Behavior

I'd like to see @JsonProperty style of enums with BeanOutputConverter - it'd be great to have an ability to give AI assistant a range of constant values, which aren't just Java String names. That is, I'd love to see something like:

	@PostConstruct
	public void doSomething() {
		var myWrapper = ChatClient.create(chatModel)
				.prompt("Select randomly either \"value.a\" or \"value.b\"")
				.call()
				.entity(MyWrapper.class);
		System.out.println(myWrapper.values);
	}


	public record MyWrapper(EnumValues values) {

	}

	public enum EnumValues {
		@JsonProperty("value.a")
		A,
		@JsonProperty("value.b")
		B
	}

being a correct way to use structured outputs

Current Behavior

As far as I can see, BeanOutputConverter is not really that much customizable. All the parametrization is done inside of a private method (generateSchema). In theory, one could even use @JsonProperty - it is recognized by the underling Jackson, but not by the schema generator, leading to interesting problems.

Generated schema for the code above:

{
  "$schema" : "https://json-schema.org/draft/2020-12/schema",
  "type" : "object",
  "properties" : {
    "values" : {
      "type" : "string",
      "enum" : [ "A", "B" ]
    }
  },
  "additionalProperties" : false
}

Stack trace:

Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `xyz.SpringAiTest$EnumValues` from String "A": not one of the values accepted for Enum class: [value.a, value.b]
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 2, column: 13] (through reference chain: xyz.SpringAiTest$MyWrapper["values"])
	at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67) ~[jackson-databind-2.18.2.jar:2.18.2]

Context

I wanted to integrate with a service that uses non-standard constants directly, and to select values using AI assistant.

There are other ways this can be done, but as far as I understand, they either include:

  1. Copying BeanOutputConverter and modifying its code
  2. Implementing your own StructuredOutputConverter. For a similar case, I've tried to modify the generated schema myself to account for @JsonProperties and it works, but it's very manual and brittle
  3. Mapping this enum to a String via some different code. Not the worst thing in the world, but it means that I need to refer in the conversations with the AI to the values using Java enum values, as well, as also having some code to map them.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with BeanOutputConverter and its private generateSchema method, then compare its enum handling with Jackson's @JsonProperty behavior described in the issue. Done means the generated schema exposes the annotated values such as "value.a" and "value.b", and the resulting structured output deserializes into the enum correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
api, backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
40/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.