Role-aware prompt and OpenRouter

The model answers as a role-specific assistant. A finance persona explains numbers in plain language. An engineering persona references architecture vocabulary. The role-aware system prompt makes this happen without giving the model any extra documents to leak.

rag_chat.py
python
system_prompt = (
    f"You are a helpful assistant with access to {role} documents.\n"
    f"Answer the user's question based only on the retrieved documents.\n"
    f"If the documents don't contain the information needed, say so clearly.\n"
    f"Use a professional, helpful tone appropriate for a {role} professional."
)

The same prompt shape works for all three roles because role is interpolated once. Swap roles without editing the prompt and the persona follows.

utils/llm_provider.py
python
class OpenRouterProvider(LLMProvider):
    def __init__(self, api_key: str, model: str) -> None:
        self.model = model
        self.client = OpenAI(
            api_key=api_key,
            base_url="https://openrouter.ai/api/v1",
            default_headers={
                "HTTP-Referer": os.getenv("OPENROUTER_HTTP_REFERER", ""),
                "X-Title": os.getenv("OPENROUTER_APP_NAME", "rbac-rag-chatbot"),
            },
            max_retries=2,
            timeout=60.0,
        )

    def chat(self, messages, temperature=0.2, max_tokens=800) -> str:
        response = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
            temperature=temperature,
            max_tokens=max_tokens,
        )
        return response.choices[0].message.content or ""


def get_llm_provider(model=None) -> LLMProvider:
    api_key = os.getenv("OPENROUTER_API_KEY")
    if not api_key:
        raise RuntimeError("OPENROUTER_API_KEY is not set.")
    chosen_model = model or os.getenv("OPENROUTER_MODEL", "minimax/minimax-m2:free")
    return OpenRouterProvider(api_key=api_key, model=chosen_model)

OpenRouter is OpenAI-compatible, so we point the OpenAI SDK at its base_url and everything else is the same. rag_chat.py only talks to the abstract LLMProvider, so swapping backends is a one-line change in the factory.

Quiz: Quiz

Loading practice…

AI prompt: Swap models without touching rag_chat.py

Loading practice…

Checkpoint: RAG chain checkpoint

Loading practice…