Files
ProfessorNovaandClaude Opus 5 784b76baf7 Pablan, as it stands
Self-hosted knowledge management for SMEs: a split-screen Markdown editor
whose sections an LLM refines while you write, and RAG question answering
over the documents that result. FastAPI + Postgres/pgvector on the back,
SvelteKit on the front, everything OpenAI-compatible and self-hostable.

Squashed into a single commit; the development history stays local.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CA43ZJda8Rbp2hKXNy8f6b
2026-09-04 09:21:37 +02:00

32 lines
1.5 KiB
Python

"""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}"