"""Prompt rendering for modes — always natural language, never raw YAML or JSON dumps. The base texts (the assistant's system prompt, the no-sources note) are admin-editable via `app/prompts/overrides.py::get_prompt`; the query mode reads `query_system` directly and `render_context_turn` reads `query_no_sources`. """ from app.prompts.overrides import get_prompt from app.rag.retrieval import SearchResult def render_context_turn(results: list[SearchResult], question: str) -> str: """The final user turn: the retrieval for THIS question, then the question. Deliberately NOT part of the system prompt: keeping the excerpts here lets the system prompt AND the conversation history stay byte-identical across a conversation's turns, so the endpoint's prompt cache reuses them and only this turn's excerpts are fresh work (docs/architecture.md, prompt caching). """ if not results: # Refusing to answer a greeting because retrieval found nothing makes the # assistant feel broken. It answers from general knowledge, just never as # if that were company policy (the UI labels these source-free). return f"{get_prompt('query_no_sources')}\n\n{question}" blocks = [ f"[{index}] {result.heading_path or result.title}\n{result.content}" for index, result in enumerate(results, start=1) ] excerpts = "\n\n---\n\n".join(blocks) return f"Knowledge base excerpts:\n\n{excerpts}\n\nQuestion:\n{question}"