"""System prompts for RAG-based codebase Q&A.""" from app.embeddings.retriever import RetrievedChunk from app.memory.conversation import Message # For codebase questions WITH retrieved context CODEBASE_SYSTEM_PROMPT = """You answer questions about the Tyndale trading system using ONLY the provided YAML artifacts. HARD CONSTRAINTS: - Do NOT assume access to source code - Do NOT invent implementation details not in the artifacts - Do NOT speculate about code mechanics beyond what artifacts describe - If artifacts do not contain enough information, say so explicitly RESPONSE STYLE: - Prefer architectural and behavioral explanations over mechanics - Reference source files by path (e.g., ./trader.py) - Explain trading concepts for developers without finance background - Keep responses focused and concise""" # For general questions (no RAG context) GENERAL_SYSTEM_PROMPT = """You are an assistant for the Tyndale trading system documentation. You can answer general questions, but for specific codebase questions, you need artifact context. If the user asks about specific code without context, ask them to rephrase or be more specific.""" # For clarification/follow-ups (uses conversation history) CLARIFICATION_SYSTEM_PROMPT = """You are continuing a conversation about the Tyndale trading system. Use the conversation history to answer follow-up questions. If you need to look up new information, ask the user to rephrase as a standalone question.""" def select_system_prompt(intent: str, has_context: bool) -> str: """Select appropriate system prompt based on intent and context. Args: intent: Classified intent (codebase, general, clarification) has_context: Whether RAG context was retrieved Returns: System prompt string """ if intent == "codebase" and has_context: return CODEBASE_SYSTEM_PROMPT elif intent == "codebase" and not has_context: return CODEBASE_SYSTEM_PROMPT + "\n\nNOTE: No relevant artifacts were found for this question. Acknowledge this limitation in your response." elif intent == "clarification": return CLARIFICATION_SYSTEM_PROMPT else: return GENERAL_SYSTEM_PROMPT def format_context(chunks: list[RetrievedChunk]) -> str: """Format retrieved chunks as context for the LLM. Args: chunks: List of retrieved chunks Returns: Formatted context string """ if not chunks: return "" context_parts = ["## Retrieved Artifact Context\n"] for i, chunk in enumerate(chunks, 1): context_parts.append(f"### Source {i}: {chunk.source_file} ({chunk.chunk_type})") context_parts.append(chunk.content) context_parts.append("") # Empty line separator return "\n".join(context_parts) def format_history(history: list[Message], max_messages: int = 10) -> str: """Format conversation history for the LLM. Args: history: List of conversation messages max_messages: Maximum messages to include Returns: Formatted history string """ if not history: return "" # Take most recent messages recent = history[-max_messages:] if len(history) > max_messages else history history_parts = ["## Conversation History\n"] for msg in recent: role = "User" if msg.role == "user" else "Assistant" history_parts.append(f"**{role}**: {msg.content}") history_parts.append("") return "\n".join(history_parts) def build_rag_prompt( user_message: str, intent: str, chunks: list[RetrievedChunk], history: list[Message], ) -> tuple[str, str]: """Build complete RAG prompt with system message and user content. Args: user_message: Current user message intent: Classified intent chunks: Retrieved context chunks history: Conversation history Returns: Tuple of (system_prompt, user_content) """ # Select system prompt system_prompt = select_system_prompt(intent, bool(chunks)) # Build user content parts = [] # Add context if available if chunks: parts.append(format_context(chunks)) # Add history for clarification intent if intent == "clarification" and history: parts.append(format_history(history)) # Add current question parts.append(f"## Current Question\n{user_message}") user_content = "\n\n".join(parts) return system_prompt, user_content