Skip to content

RewriteQueryTransformer should allow custom prompts without {target} placeholder #4232

@rkudryashov

Description

@rkudryashov

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions