spring-ai
spring-ai copied to clipboard
PromptTemplate throwing "The template string is not valid" when using Structured Output unless escaped
Bug description I have the following code...
private final BeanOutputConverter<TransactionRecord> transactionRecordConverter;
...
this.transactionRecordConverter = new BeanOutputConverter<>(TransactionRecord.class);
...
PromptTemplate promptTemplate = new PromptTemplate("""
Given the following transaction details, check if the values are correct especially the category and business name. If you can't add value to the record than just return and empty message.
Please do not include any other than the JSON string. I should be able to parse the response as json.
The transaction is: {transaction}
The response should be a json string in the following format.
{format}
""");
Map<String, Object> templateVars = new HashMap<>();
templateVars.put("transaction", transaction.toString());
templateVars.put("format", transactionRecordConverter.getFormat());
Prompt prompt = promptTemplate.create(templateVars);
String response = openAiClient.prompt(prompt).call().content();
When I run I get
org.stringtemplate.v4.compiler.STException: null
at org.stringtemplate.v4.compiler.Compiler.reportMessageAndThrowSTException(Compiler.java:224) ~[ST4-4.3.4.jar:na]
at org.stringtemplate.v4.compiler.Compiler.compile(Compiler.java:154) ~[ST4-4.3.4.jar:na]
at org.stringtemplate.v4.STGroup.compile(STGroup.java:514) ~[ST4-4.3.4.jar:na]
at org.stringtemplate.v4.ST.<init>(ST.java:162) ~[ST4-4.3.4.jar:na]
at org.stringtemplate.v4.ST.<init>(ST.java:156) ~[ST4-4.3.4.jar:na]
From this.st = new ST(this.template, '{', '}');
The full template is available here
Environment Latest 1.0 and I am running on Spring Boot with Java 23
Steps to reproduce I don't have publicly available code that reproduces it but I will try to create something soon. In the meantime you should be able to use the raw gist in the PromptTemplate here...
try {
this.st = new ST(this.template, '{', '}');
for (Entry<String, Object> entry : model.entrySet()) {
add(entry.getKey(), entry.getValue());
}
}
And you should be able to reproduce
Expected behavior I would expect to be able to run the prompt without the failure. If I remove the {format} the prompt completes.
Workaround
I can get it to work if I use...
String jsonSchema = transactionRecordConverter.getFormat()
.replace("{", "\\{")
.replace("}", "\\}");
templateVars.put("format", jsonSchema);
But in the docs it says I shouldn't need to escape
I'm running into the same/similar if my input contains Java code. The use case is applying code suggestions on Java source code, so the input contains { and } as part of the code. This confuses the ST because it's looking for { and } as part of the templating.
I encountered the same issue.
It must be possible to disable ST completely and pass a literal string. This will enable using an external template mechanism.
We are starting on this work to allow more flexible templating support in RC1.
In the meantime, if you are passing in json inside the user text that is templated as well, you will need to escape that part of the text which uses the curly brackets. There is now in snapshot a class CurlyBracketEscaper which could reduce a bit of toil in the interum.
This has now been fixed, the PR is https://github.com/spring-projects/spring-ai/pull/2920 and searching for TemplateRenderer in the docs will show you how to use it. You can provide your own TemplateRender impls.
let us know how it goes. thanks for your patience.