kyorlin2001/code-analysis-tool
0
1from __future__ import annotations2 3from dataclasses import dataclass4from typing import Any5 6from models.retrieval_chunk import RetrievalChunk7 8 9@dataclass(frozen=True)10class PromptBundle:11 """12 Structured prompt payload for the hosted model.13 """14 15 system_prompt: str16 user_prompt: str17 18 19class PromptBuilder:20 """21 Builds prompts for RAG-based repository analysis.22 """23 24 def build(25 self,26 question: str,27 chunks: list[RetrievalChunk],28 repo_name: str | None = None,29 findings: list[dict[str, Any]] | None = None,30 ) -> PromptBundle:31 system_prompt = (32 "You are an expert software analysis assistant.\n"33 "Use the repository context provided in the user prompt.\n"34 "If the context is insufficient, say exactly what is missing.\n"35 "Be specific, practical, and grounded in the evidence.\n"36 "Prefer file names, code snippets, and concrete suggestions."37 )38 39 user_prompt = self._build_user_prompt(40 question=question,41 chunks=chunks,42 repo_name=repo_name,43 findings=findings or [],44 )45 46 return PromptBundle(47 system_prompt=system_prompt,48 user_prompt=user_prompt,49 )50 51 def _build_user_prompt(52 self,53 question: str,54 chunks: list[RetrievalChunk],55 repo_name: str | None,56 findings: list[dict[str, Any]],57 ) -> str:58 lines: list[str] = []59 60 lines.append(f"Question: {question}")61 62 if repo_name:63 lines.append(f"Repository: {repo_name}")64 65 if findings:66 lines.append("")67 lines.append("Existing analysis findings:")68 for finding in findings:69 severity = finding.get("severity", "info")70 message = finding.get("message", "")71 lines.append(f"- [{severity}] {message}")72 73 lines.append("")74 lines.append("Repository context:")75 76 if not chunks:77 lines.append("- No relevant chunks were retrieved.")78 else:79 for index, chunk in enumerate(chunks, start=1):80 lines.append("")81 lines.append(f"Context block {index}:")82 lines.append(f"File: {chunk.file_path}")83 if chunk.start_line is not None and chunk.end_line is not None:84 lines.append(f"Lines: {chunk.start_line}-{chunk.end_line}")85 if chunk.language:86 lines.append(f"Language: {chunk.language}")87 lines.append("Content:")88 lines.append(chunk.text)89 90 lines.append("")91 lines.append("Instructions:")92 lines.append("- Answer using the repository context above.")93 lines.append("- If you suggest improvements, make them specific and actionable.")94 lines.append("- If the context is insufficient, explain what is missing.")95 lines.append("- Do not ask for repository files again unless no context was retrieved.")96 return "\n".join(lines)