Spaces:
Sleeping
Sleeping
| """ | |
| Engineering Knowledge Assistant: IBM Bob as a repository-aware Q&A engine. | |
| """ | |
| from __future__ import annotations | |
| from core.watsonx import watsonx_generate | |
| from utils.cache import repo_cache | |
| from utils.context_builder import build_qa_context | |
| async def answer_engineering_question(repo_id: str, question: str, chat_history: list | None = None) -> dict: | |
| """Use IBM Bob to answer repository-specific engineering questions.""" | |
| if repo_id not in repo_cache: | |
| raise ValueError("Repository not loaded. Please ingest a repository first.") | |
| chat_history = chat_history or [] | |
| repo_data = repo_cache[repo_id] | |
| context = build_qa_context(repo_data, question) | |
| history_str = "\n".join( | |
| f"{'Engineer' if message.get('role') == 'user' else 'CodeAtlas'}: {message.get('content', '')}" | |
| for message in chat_history[-4:] | |
| ) | |
| prompt = f"""You are CodeAtlas, an expert engineering intelligence system analyzing a real codebase. | |
| You have deep knowledge of this repository's architecture, business logic, and code structure. | |
| REPOSITORY INTELLIGENCE: | |
| {context} | |
| CONVERSATION HISTORY: | |
| {history_str} | |
| ENGINEER'S QUESTION: {question} | |
| Provide a precise, technical answer that: | |
| 1. Directly answers the question with specific file paths, function names, and code locations | |
| 2. Explains the implementation approach and business logic | |
| 3. Identifies related components or dependencies | |
| 4. Flags risks or important considerations | |
| 5. Suggests next files to explore if relevant | |
| Use this format: | |
| ANSWER: [Direct answer] | |
| IMPLEMENTATION: [How it's implemented with specific locations] | |
| RELATED: [Related components/files] | |
| RISKS: [Any concerns or gotchas] | |
| ###END###""" | |
| response = await watsonx_generate( | |
| prompt, | |
| max_tokens=1200, | |
| use_code_model=True, | |
| working_dir=repo_data.get("repo_path"), | |
| ) | |
| sections = {"answer": "", "implementation": "", "related": "", "risks": ""} | |
| current = "answer" | |
| for line in response.split("\n"): | |
| stripped = line.strip() | |
| if stripped.startswith("ANSWER:"): | |
| current = "answer" | |
| sections[current] = stripped[7:].strip() | |
| elif stripped.startswith("IMPLEMENTATION:"): | |
| current = "implementation" | |
| sections[current] = stripped[15:].strip() | |
| elif stripped.startswith("RELATED:"): | |
| current = "related" | |
| sections[current] = stripped[8:].strip() | |
| elif stripped.startswith("RISKS:"): | |
| current = "risks" | |
| sections[current] = stripped[6:].strip() | |
| elif stripped and not stripped.startswith("###"): | |
| sections[current] = f"{sections[current]} {stripped}".strip() | |
| return { | |
| "question": question, | |
| "answer": sections["answer"].strip() or response.strip(), | |
| "implementation": sections["implementation"].strip(), | |
| "related": sections["related"].strip(), | |
| "risks": sections["risks"].strip(), | |
| "full_response": response, | |
| } | |