""" crew.py — NeuralDocs Agentic RAG --------------------------------- Assembles the CrewAI crew from config files and registered tools. Written from scratch for the NeuralDocs project. """ from crewai import Agent, Crew, Process, Task from crewai.project import CrewBase, agent, crew, task from crewai_tools import SerperDevTool from src.agentic_rag.tools.custom_tool import DocumentSearchTool @CrewBase class NeuralDocsCrew: """ Two-agent crew for Agentic RAG: 1. retriever_agent — searches document then web 2. response_synthesizer_agent — writes the final answer """ agents_config = "config/agents.yaml" tasks_config = "config/tasks.yaml" def __init__(self, file_path: str | None = None): """ Args: file_path: Path to the uploaded document. If None, the crew operates in web-search-only mode. """ super().__init__() self._doc_tool = DocumentSearchTool(file_path=file_path) if file_path else None self._web_tool = SerperDevTool() # ── Agents ────────────────────────────────────────────────────────────── @agent def retriever_agent(self) -> Agent: tools = [t for t in [self._doc_tool, self._web_tool] if t] return Agent( config=self.agents_config["retriever_agent"], tools=tools, verbose=True, allow_delegation=False, ) @agent def response_synthesizer_agent(self) -> Agent: return Agent( config=self.agents_config["response_synthesizer_agent"], verbose=True, allow_delegation=False, ) # ── Tasks ──────────────────────────────────────────────────────────────── @task def retrieval_task(self) -> Task: return Task(config=self.tasks_config["retrieval_task"]) @task def synthesis_task(self) -> Task: return Task(config=self.tasks_config["synthesis_task"]) # ── Crew ───────────────────────────────────────────────────────────────── @crew def crew(self) -> Crew: return Crew( agents=self.agents, tasks=self.tasks, process=Process.sequential, verbose=True, )