This was tested with Spring AI 0.7.0-SNAPSHOT.

Once a PromptTemplate has been created without model data and then used once via the render() method that takes model data, it cannot be reused with different model data. Attempting to do so will result in a prompt that contains the original model data. For example, I would expect the following test to pass. But it does not as described in the comments.

    @Test
    public void testPromptTemplate() {
        PromptTemplate pt = new PromptTemplate("Here is the input: {input}");

        String output1 = pt.render(Map.of("input", "Hello, world!"));
        Assertions.assertThat(output1).isEqualTo("Here is the input: Hello, world!");

        String output2 = pt.render(Map.of("input", "Goodbye, world!"));
        // This next assertion fails!!!
        // The rendered output is the "Hello world" from the first time!!!
        Assertions.assertThat(output2).isEqualTo("Here is the input: Goodbye, world!");
    }

This is appears to be because of the if statement at https://github.com/spring-projects-experimental/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/prompt/PromptTemplate.java#L141 that prevents new model data from being given to the ST instance unless that key is null.

Note that I've tested the same thing with both the Python and Node.js implementations of PromptTemplate from Langchain and they both work as I'd expect. That is, the PromptTemplate can be reused with new model data. For the sake of clarity, here's what I did in Python:

from langchain.prompts import PromptTemplate

prompt_template = PromptTemplate.from_template(
    "Here is the input: {input}"
)

output1 = prompt_template.format(input="Hello, world!")
print(output1)
# Here is the input: Hello, world!

output2 = prompt_template.format(input="Goodbye, world!")
print(output2)
# Here is the input: Goodbye, world!

And here is what I did in Node.js:

import { PromptTemplate } from "langchain/prompts";

const pt = PromptTemplate.fromTemplate('Here is the input: {input}');

const output1 = await pt.format({input: "Hello, world!"});
console.log(output1);
// Here is the input: Hello, world!

const output2 = await pt.format({input: "Goodbye, world!"});
console.log(output2);
// Here is the input: Goodbye, world!

In both cases, the result was (as expected):

Here is the input: Hello, world!
Here is the input: Goodbye, world!

I'd expect Spring AI's PromptTemplate to be reusable in the same way.