Troubleshoot prompts
Before you start
build_augmented_prompt assembles a grounded LLM prompt by combining a user query with retrieved passages wrapped in <passage>...</passage> sentinels. The variant argument selects the prompt style; invalid values raise immediately. If context assembly is the issue, the problem is more likely in join_context or join_context_numbered than in the prompt renderer itself.
Symptom table
| If you observe | Check |
|---|---|
ValueError: query must be a non-empty string |
The query argument passed to build_augmented_prompt — it is None, "", or a non-string type. |
ValueError: unknown prompt variant {...}; valid: {...} |
The variant argument passed to build_augmented_prompt — the error message lists the accepted values. |
| Context block is empty or missing from the rendered prompt | Whether join_context or join_context_numbered received a non-empty hits iterable; the iterable may be exhausted before being passed in. |
Passages appear without [P1]/[P2] labels |
You are calling join_context instead of join_context_numbered. The numbered variant wraps each hit in <passage>[Pn] …</passage> form. |
| Context is truncated unexpectedly | The max_chars argument — it defaults to DEFAULT_MAX_CONTEXT_CHARS. Passages are cut off once the concatenated output reaches that limit. |
| Injected text appears to override the system prompt | The _INJECTION_DEFENSE_CLAUSE is missing from the rendered prompt, which means the wrong variant or a custom template path is being used. |
Step-by-step diagnosis
-
Reproduce the failure with a minimal call. Strip the call to its required arguments and confirm the failure still occurs:
from attune_rag.prompts import build_augmented_prompt print(build_augmented_prompt(query="test", context="test context"))If this succeeds, the problem is in how your application builds
queryorcontextbefore passing them in. -
Check the ValueError message. Both
ValueErrorcases inbuild_augmented_promptinclude the offending value in the message. Read it before going further — it names the bad input directly. -
Inspect the context string before it reaches
build_augmented_prompt. If the rendered prompt is missing passages, print the output ofjoin_contextorjoin_context_numberedseparately:from attune_rag.prompts import join_context_numbered ctx = join_context_numbered(hits=your_hits) print(repr(ctx))Confirm the output contains
<passage>and</passage>sentinels and is not an empty string. -
Verify the
hitsiterable is not exhausted. Generators in Python can only be consumed once. Ifhitsis a generator that was already iterated (for example, for logging), it will be empty when passed tojoin_context. Materialize it first:hits = list(hits) # consume once, reuse freely -
Check
max_charsif context is shorter than expected. The default cap isDEFAULT_MAX_CONTEXT_CHARS. If your passages are large, pass a higher limit explicitly:join_context(hits=hits, max_chars=8000) -
Run the prompts tests.
pytest -k "prompts" -vA failing test that exercises your code path will show you the expected inputs and outputs and give you a fixture to work against.
Common fixes
-
Empty or
Nonequery: Validate the query before callingbuild_augmented_prompt:if not query or not isinstance(query, str): raise ValueError(f"Expected a non-empty string, got {query!r}") -
Invalid
variant: The error message frombuild_augmented_promptlists valid variant names. Pass one of those exactly — the argument is case-sensitive. -
Exhausted hits iterable: Wrap the iterable in
list()before passing it tojoin_contextorjoin_context_numbered(see step 4 above). -
Context truncated too aggressively: Pass a larger
max_charsvalue tojoin_contextorjoin_context_numbered. Note that a very large context may exceed your LLM's token limit — this is a trade-off you control at the call site, not within the prompts module. -
Prompt injection defense missing: If you are constructing
contextstrings manually and bypassingjoin_context_numbered, the_INJECTION_DEFENSE_CLAUSEwill not be present. Usejoin_context_numberedso that passages are wrapped correctly and the defense clause can be applied by the prompt template.
Source files
src/attune_rag/prompts.py
Tags: prompts, templates, augmentation, citation