Expected Behavior

The RewriteQueryTransformer should allow custom prompt templates without requiring the {target} placeholder when the custom prompt doesn't use it.

// This should work with a custom prompt that doesn't need {target}
RewriteQueryTransformer.builder()
    .chatClientBuilder(chatClientBuilder)
    .promptTemplate(customPromptTemplate) // Custom prompt without {target}
    .build(); // Should not throw IllegalArgumentException

Current Behavior

RewriteQueryTransformer currently enforces that all prompt templates must include the {target} placeholder, even when using completely custom prompts that don't need this placeholder.

// This fails with IllegalArgumentException even though custom prompt doesn't use {target}
RewriteQueryTransformer.builder()
    .chatClientBuilder(chatClientBuilder)
    .promptTemplate(customPromptTemplate) // Custom prompt without {target}
    .build(); // Throws: "The following placeholders must be present in the prompt template: target"

Error Log:

java.lang.IllegalArgumentException: The following placeholders must be present in the prompt template: target
    at org.springframework.ai.rag.util.PromptAssert.templateHasRequiredPlaceholders(PromptAssert.java:55)
    at org.springframework.ai.rag.preretrieval.query.transformation.RewriteQueryTransformer.<init>(RewriteQueryTransformer.java:71)
    at org.springframework.ai.rag.preretrieval.query.transformation.RewriteQueryTransformer$Builder.build(RewriteQueryTransformer.java:128)

Context

How has this issue affected you? I'm implementing a custom query transformation system that performs specialized processing beyond the default query rewriting. My custom prompt template doesn't need the {target} placeholder but the framework forces me to include it, causing runtime exceptions.

What are you trying to accomplish? Create a flexible query transformation system that can handle custom business logic without being constrained by framework assumptions about required placeholders.

What other alternatives have you considered? 1. Using a different transformer class (but RewriteQueryTransformer is the most appropriate for this use case) 2. Implementing a custom transformer from scratch (overkill for this simple requirement)

Are you aware of any workarounds? Yes, I can add a dummy {target} placeholder to my custom prompt template, but this is a hack that makes the code less clean and the prompt less readable. The placeholder validation should be conditional based on what's actually used in the custom prompt.

Example Use Case:

// Custom prompt for specialized query transformation
private val customPromptTemplate = PromptTemplate("""
    You are a query processor for a specialized analysis system.

    TASK: Process the user query to extract specific information.

    INPUT: {query}

    OUTPUT FORMAT (JSON):
    {
      "rewritten_query": "processed query",
      "custom_field": "custom value"
    }

    Query: {query}
    """)

This prompt doesn't need {target} but the framework currently requires it, causing the application to crash at runtime.

Comment From: sunyuhan1998

@rkudryashov Thank you for your report! I agree that the issue you mentioned is valid. I've attempted a solution for it—could you please review this PR? https://github.com/spring-projects/spring-ai/pull/4256

Comment From: rkudryashov

@sunyuhan1998 Thank you for the quick response! The validation mode approach LGTM, but as I'm not a contributor and am not familiar with the codebase, I would appreciate any additional context or guidance on how this solution can be utilized in my project

Comment From: sunyuhan1998

@sunyuhan1998 Thank you for the quick response! The validation mode approach LGTM, but as I'm not a contributor and am not familiar with the codebase, I would appreciate any additional context or guidance on how this solution can be utilized in my project

Thank you for your review. Currently, unless you clone the repository and merge this PR into your local branch to build and use it yourself, we can only wait for the team to complete the review process.