Jackie
Jackie

Reputation: 23607

Why is StringTemplate throwing "org.stringtemplate.v4.compiler.STException: null" for my Spring AI prompt

I have the following code...

    private TransactionRecord validateTransactionWithOpenAI(TransactionRecord transaction) {
        // Construct the prompt for OpenAI
        // Create a PromptTemplate with placeholders
        PromptTemplate promptTemplate = new PromptTemplate("""
                    Given the following transaction details, check if the values are correct especially the category and business name based on the context data:
                    Transaction: {transaction}
                    {format}
                """);

        Prompt prompt = promptTemplate.create(Map.of(
                "transaction", transaction.toString(),
                "format", transactionRecordConverter.getFormat()
        ));

        log.debug("Prompt: {} \n {}", prompt.getContents(), prompt.getInstructions());
        String response = openAiClient.prompt(prompt).call().content();
        try {
            return transactionRecordConverter.convert(response);
        } catch (Exception e) {
            log.error("Failed to parse OpenAI response as TransactionRecord", e);
            return transaction;
        }
    }

The log I see says...

---2024-11-30 00:14:28.325 -DEBUG 73770 --- [nio-8019-exec-7] o.e.service.TransactionServiceImpl       : Prompt:     Given the following transaction details, check if the values are correct especially the category and business name based on the context data:
    Transaction: TransactionRecord(id=null, date=2024-01-01, originalDate=2024-01-01, accountType=Cash, accountName=..., accountNumber=null, institutionName=..., name=..., customName=null, amount=8.59, description=..., category=Internal Transfers, note=null, ignoredFrom=null, taxDeductible=false)
    Your response should be in JSON format.
    Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.
    Do not include markdown code blocks in your response.
    Remove the ```json markdown from the output.
    Here is the JSON Schema instance your output must adhere to:
    ```{
      "$schema" : "https://json-schema.org/draft/2020-12/schema",
      "type" : "object",
      "properties" : {
        "accountName" : {
          "type" : "string"
        },
        "accountNumber" : {
          "type" : "string"
        },
        "accountType" : {
          "type" : "string"
        },
        "amount" : {
          "type" : "number"
        },
        "category" : {
          "type" : "string"
        },
        "customName" : {
          "type" : "string"
        },
        "date" : {
          "type" : "string",
          "format" : "date"
        },
        "description" : {
          "type" : "string"
        },
        "id" : {
          "type" : "integer"
        },
        "ignoredFrom" : {
          "type" : "string"
        },
        "institutionName" : {
          "type" : "string"
        },
        "name" : {
          "type" : "string"
        },
        "note" : {
          "type" : "string"
        },
        "originalDate" : {
          "type" : "string",
          "format" : "date"
        },
        "taxDeductible" : {
          "type" : "boolean"
        }
      },
      "additionalProperties" : false
    }```

 
 [UserMessage{content='    Given the following transaction details, check if the values are correct especially the category and business name based on the context data:
    Transaction: TransactionRecord(id=null, date=2024-01-01, originalDate=2024-01-01, accountType=Cash, accountName=PayPal, accountNumber=null, institutionName=PayPal, name=Payment to Microsoft Corporation, customName=null, amount=8.59, description=Payment to Microsoft Corporation, category=Internal Transfers, note=null, ignoredFrom=null, taxDeductible=false)
    Your response should be in JSON format.
    Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.
    Do not include markdown code blocks in your response.
    Remove the ```json markdown from the output.
    Here is the JSON Schema instance your output must adhere to:
    ```{
      "$schema" : "https://json-schema.org/draft/2020-12/schema",
      "type" : "object",
      "properties" : {
        "accountName" : {
          "type" : "string"
        },
        "accountNumber" : {
          "type" : "string"
        },
        "accountType" : {
          "type" : "string"
        },
        "amount" : {
          "type" : "number"
        },
        "category" : {
          "type" : "string"
        },
        "customName" : {
          "type" : "string"
        },
        "date" : {
          "type" : "string",
          "format" : "date"
        },
        "description" : {
          "type" : "string"
        },
        "id" : {
          "type" : "integer"
        },
        "ignoredFrom" : {
          "type" : "string"
        },
        "institutionName" : {
          "type" : "string"
        },
        "name" : {
          "type" : "string"
        },
        "note" : {
          "type" : "string"
        },
        "originalDate" : {
          "type" : "string",
          "format" : "date"
        },
        "taxDeductible" : {
          "type" : "boolean"
        }
      },
      "additionalProperties" : false
    }```

', properties={messageType=USER}, messageType=USER}]

Which seems to basically look correct but when I try to run String response = openAiClient.prompt(prompt).call().content(); fails with

java.lang.IllegalArgumentException: The template string is not valid.
    at org.springframework.ai.chat.prompt.PromptTemplate.<init>(PromptTemplate.java:85) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at org.springframework.ai.chat.client.advisor.api.AdvisedRequest.toPrompt(AdvisedRequest.java:228) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultChatClientRequestSpec$1.aroundCall(DefaultChatClient.java:598) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at org.springframework.ai.chat.client.advisor.DefaultAroundAdvisorChain.lambda$nextAroundCall$1(DefaultAroundAdvisorChain.java:93) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at io.micrometer.observation.Observation.observe(Observation.java:565) ~[micrometer-observation-1.13.4.jar:1.13.4]
    at org.springframework.ai.chat.client.advisor.DefaultAroundAdvisorChain.nextAroundCall(DefaultAroundAdvisorChain.java:93) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor.aroundCall(QuestionAnswerAdvisor.java:174) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at org.springframework.ai.chat.client.advisor.DefaultAroundAdvisorChain.lambda$nextAroundCall$1(DefaultAroundAdvisorChain.java:93) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at io.micrometer.observation.Observation.observe(Observation.java:565) ~[micrometer-observation-1.13.4.jar:1.13.4]
    at org.springframework.ai.chat.client.advisor.DefaultAroundAdvisorChain.nextAroundCall(DefaultAroundAdvisorChain.java:93) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.doGetChatResponse(DefaultChatClient.java:389) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.lambda$doGetObservableChatResponse$1(DefaultChatClient.java:375) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at io.micrometer.observation.Observation.observe(Observation.java:565) ~[micrometer-observation-1.13.4.jar:1.13.4]
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.doGetObservableChatResponse(DefaultChatClient.java:374) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.doGetChatResponse(DefaultChatClient.java:359) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.content(DefaultChatClient.java:399) ~[spring-ai-core-1.0.0-M3.jar:1.0.0-M3]
    at org.example.service.TransactionServiceImpl.validateTransactionWithOpenAI(TransactionServiceImpl.java:193) ~[main/:na]

What am I missing why is the string template failing? Do I need to escape something?

Update

If I debug into the template engine I see it is failing here this.st = new ST(this.template, '{', '}'); So I am not sure what is up but it seems like it might be an escaping issue. The full value of this.template is available in this gist

Upvotes: 2

Views: 93

Answers (1)

janbnz
janbnz

Reputation: 61

I also had this error which was caused by sending messages with non-closed curly braces. You can also see it in this SpringAI test. I solved this by escaping curly braces in the text I'm sending, before adding it to the prompt or PromptTemplate.

text.replace("{", "\\{").replace("}", "\\}")

Upvotes: 0

Related Questions