From 0ca9120eabf02fc5cf8238568d6500fb2193c2d9 Mon Sep 17 00:00:00 2001 From: dhirenmathur Date: Fri, 8 Nov 2024 15:48:00 +0530 Subject: [PATCH 1/7] basic code gen --- .../agents/agent_injector_service.py | 4 + .../agents/agentic_tools/code_gen_agent.py | 197 ++++++++++++ .../agentic_tools/multi_agent_code_gen.py | 282 ++++++++++++++++++ .../intelligence/agents/agents_service.py | 5 + .../agents/chat_agents/code_gen.py | 229 ++++++++++++++ 5 files changed, 717 insertions(+) create mode 100644 app/modules/intelligence/agents/agentic_tools/code_gen_agent.py create mode 100644 app/modules/intelligence/agents/agentic_tools/multi_agent_code_gen.py create mode 100644 app/modules/intelligence/agents/chat_agents/code_gen.py diff --git a/app/modules/intelligence/agents/agent_injector_service.py b/app/modules/intelligence/agents/agent_injector_service.py index 014d24cf..3de9d0e3 100644 --- a/app/modules/intelligence/agents/agent_injector_service.py +++ b/app/modules/intelligence/agents/agent_injector_service.py @@ -3,6 +3,7 @@ from sqlalchemy.orm import Session +from app.modules.intelligence.agents.chat_agents.code_gen import CodeGenerationAgent from app.modules.intelligence.agents.chat_agents.code_changes_agent import ( CodeChangesAgent, ) @@ -38,6 +39,9 @@ def _initialize_agents(self) -> Dict[str, Any]: mini_llm, reasoning_llm, self.sql_db ), "LLD_agent": LLDAgent(mini_llm, reasoning_llm, self.sql_db), + "code_generation_agent": CodeGenerationAgent( + mini_llm, reasoning_llm, self.sql_db + ), } def get_agent(self, agent_id: str) -> Any: diff --git a/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py b/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py new file mode 100644 index 00000000..cdbaff3a --- /dev/null +++ b/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py @@ -0,0 +1,197 @@ +import os +from typing import Any, Dict, List + +from crewai import Agent, Crew, Process, Task + +from app.modules.conversations.message.message_schema import NodeContext +from app.modules.intelligence.tools.code_query_tools.get_node_neighbours_from_node_id_tool import ( + get_node_neighbours_from_node_id_tool, +) +from app.modules.intelligence.tools.kg_based_tools.get_code_from_multiple_node_ids_tool import ( + GetCodeFromMultipleNodeIdsTool, + get_code_from_multiple_node_ids_tool, +) +from app.modules.intelligence.tools.kg_based_tools.get_code_from_node_id_tool import ( + get_code_from_node_id_tool, +) + + +class CodeGenerationAgent: + def __init__(self, sql_db, llm, mini_llm, user_id): + self.openai_api_key = os.getenv("OPENAI_API_KEY") + self.max_iter = os.getenv("MAX_ITER", 5) + self.sql_db = sql_db + self.get_code_from_node_id = get_code_from_node_id_tool(sql_db, user_id) + self.get_code_from_multiple_node_ids = get_code_from_multiple_node_ids_tool( + sql_db, user_id + ) + self.get_node_neighbours = get_node_neighbours_from_node_id_tool(sql_db) + self.llm = llm + self.mini_llm = mini_llm + self.user_id = user_id + + + async def create_agents(self): + code_generator = Agent( + role="Code Generation Agent", + goal="Generate precise, copy-paste ready code modifications that maintain project consistency", + backstory=f""" + You are an expert code generation agent specialized in creating production-ready, + immediately usable code modifications. Your primary responsibilities include: + 1. Analyzing existing codebase context and understanding dependencies + 2. Planning code changes that maintain exact project patterns and style + 3. Implementing changes with copy-paste ready output + 4. Following existing code conventions exactly as shown in the input files + 5. Never modifying string literals, escape characters, or formatting unless specifically requested + + Key principles: + - Provide required new imports in a separate code block + - Output only the specific functions/classes being modified + - Never change existing string formats or escape characters + - Maintain exact indentation and spacing patterns from original code + - Include clear section markers for where code should be inserted/modified + + Maintain efficiency within {self.max_iter} iterations while ensuring production-ready output. + """, + tools=[ + self.get_code_from_node_id, + self.get_code_from_multiple_node_ids, + self.get_node_neighbours, + ], + allow_delegation=False, + verbose=True, + llm=self.llm, + max_iter=self.max_iter, + ) + + return code_generator + + async def create_tasks( + self, + query: str, + project_id: str, + node_ids: List[NodeContext], + code_results: List[Dict[str, Any]], + code_generator, + ): + code_generation_task = Task( + description=f""" + Work within {self.max_iter} iterations to generate copy-paste ready code based on: + - Query: {query} + - Project ID: {project_id} + - Target Node IDs: {[node.model_dump() for node in node_ids]} + - Existing Code Context: {code_results} + + Follow this structured approach: + + 1. Context Analysis: + - Review existing code style precisely + - Note exact indentation patterns + - Identify string literal formats + - Review import organization patterns + + 2. Implementation Planning: + - Plan changes that maintain exact formatting + - Never modify existing patterns unless requested + - Identify required new imports + + 3. Code Generation Format: + Required imports (if any): + ```python + from new.module import NewClass + ``` + + Modified/New Code: + ```python + def modified_function(): + # Your code here + pass + ``` + + Location Guide: + ``` + File: path/to/file.py + Replace function/class: name_of_function + - or - + Insert after line: X + ``` + + Important Output Rules: + 1. Always separate new imports from main code changes + 2. Never modify existing string literals or escape characters + 3. Follow existing indentation exactly + 4. Include only the specific functions/classes being modified + 5. Provide clear location markers for each code block + 6. Maintain exact spacing patterns from original code + 7. For new files, provide complete file content with imports at top + 8. Format code blocks with language specification for syntax highlighting + + Your response format should be: + + Brief explanation of changes (2-3 lines max) + + Required Imports: + [code block with imports] + + Code Changes: + [code block with changes] + + Location: + [location details] + + Keep responses focused and formatted for easy copy-paste into an IDE. + No conversation or unnecessary explanation - just clear, actionable code blocks. + """, + expected_output="Copy-paste ready code changes with clear location markers and required imports", + agent=code_generator, + ) + + return code_generation_task + + + async def run( + self, + query: str, + project_id: str, + node_ids: List[NodeContext], + ) -> str: + os.environ["OPENAI_API_KEY"] = self.openai_api_key + + code_results = [] + if len(node_ids) > 0: + code_results = await GetCodeFromMultipleNodeIdsTool( + self.sql_db, self.user_id + ).run_multiple(project_id, [node.node_id for node in node_ids]) + + code_generator = await self.create_agents() + generation_task = await self.create_tasks( + query, + project_id, + node_ids, + code_results, + code_generator, + ) + + crew = Crew( + agents=[code_generator], + tasks=[generation_task], + process=Process.sequential, + verbose=False, + ) + + result = await crew.kickoff_async() + return result + + +async def kickoff_code_generation_crew( + query: str, + project_id: str, + node_ids: List[NodeContext], + sql_db, + llm, + mini_llm, + user_id: str, +) -> str: + code_gen_agent = CodeGenerationAgent(sql_db, llm, mini_llm, user_id) + result = await code_gen_agent.run(query, project_id, node_ids) + return result \ No newline at end of file diff --git a/app/modules/intelligence/agents/agentic_tools/multi_agent_code_gen.py b/app/modules/intelligence/agents/agentic_tools/multi_agent_code_gen.py new file mode 100644 index 00000000..2b056b77 --- /dev/null +++ b/app/modules/intelligence/agents/agentic_tools/multi_agent_code_gen.py @@ -0,0 +1,282 @@ +import os +from typing import Any, Dict, List +from dataclasses import dataclass + +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel, Field + +from app.modules.conversations.message.message_schema import NodeContext +from app.modules.intelligence.tools.code_query_tools.get_node_neighbours_from_node_id_tool import ( + get_node_neighbours_from_node_id_tool, +) +from app.modules.intelligence.tools.kg_based_tools.get_code_from_multiple_node_ids_tool import ( + GetCodeFromMultipleNodeIdsTool, + get_code_from_multiple_node_ids_tool, +) +from app.modules.intelligence.tools.kg_based_tools.get_code_from_node_id_tool import ( + get_code_from_node_id_tool, +) + + +class CodeGenerationPlan(BaseModel): + affected_files: List[str] = Field(..., description="Files that need modification") + changes_required: Dict[str, str] = Field(..., description="Required changes per file") + dependencies: List[str] = Field(..., description="Related dependencies to consider") + implementation_steps: List[str] = Field(..., description="Ordered steps for implementation") + + +class CodeModification(BaseModel): + file_path: str + original_code: str + updated_code: str + changes_description: str + + +class CodeGenerationResult(BaseModel): + plan: CodeGenerationPlan + modifications: List[CodeModification] + validation_notes: List[str] + + +@dataclass +class AgentContext: + query: str + project_id: str + node_ids: List[NodeContext] + code_results: List[Dict[str, Any]] + max_iter: int + + +class MultiAgentCodeGenerator: + def __init__(self, sql_db, llm, mini_llm, user_id): + self.openai_api_key = os.getenv("OPENAI_API_KEY") + self.max_iter = os.getenv("MAX_ITER", 5) + self.sql_db = sql_db + self.get_code_from_node_id = get_code_from_node_id_tool(sql_db, user_id) + self.get_code_from_multiple_node_ids = get_code_from_multiple_node_ids_tool( + sql_db, user_id + ) + self.get_node_neighbours = get_node_neighbours_from_node_id_tool(sql_db) + self.llm = llm + self.mini_llm = mini_llm + self.user_id = user_id + + def create_analyzer_agent(self) -> Agent: + return Agent( + role="Code Context Analyzer", + goal="Analyze existing codebase and create comprehensive context for modifications", + backstory=""" + You are an expert code analyst specialized in understanding codebases and their structures. + You excel at: + 1. Analyzing code patterns and architecture + 2. Identifying dependencies and relationships + 3. Understanding the scope and impact of changes + 4. Creating detailed context for other agents + """, + tools=[ + self.get_code_from_node_id, + self.get_code_from_multiple_node_ids, + self.get_node_neighbours, + ], + allow_delegation=True, + verbose=True, + llm=self.llm, + ) + + def create_planner_agent(self) -> Agent: + return Agent( + role="Implementation Planner", + goal="Create detailed implementation plan based on analysis", + backstory=""" + You are a strategic code planner who excels at: + 1. Breaking down complex changes into manageable steps + 2. Identifying potential risks and dependencies + 3. Creating clear implementation roadmaps + 4. Ensuring minimal impact on existing functionality + """, + tools=[], # Planner uses context from analyzer + allow_delegation=True, + verbose=True, + llm=self.llm, + ) + + def create_implementer_agent(self) -> Agent: + return Agent( + role="Code Implementer", + goal="Generate and modify code according to the implementation plan", + backstory=""" + You are an expert code implementer who: + 1. Writes clean, efficient code + 2. Follows existing patterns and conventions + 3. Implements changes with precision + 4. Maintains code quality and consistency + """, + tools=[ + self.get_code_from_node_id, + self.get_code_from_multiple_node_ids, + ], + allow_delegation=True, + verbose=True, + llm=self.llm, + ) + + def create_validator_agent(self) -> Agent: + return Agent( + role="Code Validator", + goal="Validate generated code for correctness and consistency", + backstory=""" + You are a thorough code validator who: + 1. Reviews code changes for correctness + 2. Ensures consistency with existing codebase + 3. Identifies potential issues or edge cases + 4. Provides validation feedback + """, + tools=[ + self.get_code_from_node_id, + self.get_node_neighbours, + ], + allow_delegation=True, + verbose=True, + llm=self.llm, + ) + + def create_analysis_task(self, context: AgentContext, analyzer: Agent) -> Task: + return Task( + description=f""" + Analyze the codebase context within {context.max_iter} iterations: + - Query: {context.query} + - Project ID: {context.project_id} + - Target Nodes: {[node.model_dump() for node in context.node_ids]} + - Existing Code: {context.code_results} + + Provide: + 1. Detailed analysis of affected code sections + 2. Identification of patterns and conventions + 3. List of dependencies and relationships + 4. Potential impact areas + + Return analysis in structured format focusing on technical details. + """, + agent=analyzer, + expected_output="Return analysis in structured format focusing on technical details.", + ) + + def create_planning_task(self, context: AgentContext, planner: Agent) -> Task: + return Task( + description=f""" + Create implementation plan based on analysis: + - Break down the query: {context.query} + - Consider provided analysis + - Design step-by-step implementation approach + + Provide CodeGenerationPlan with: + 1. List of affected files + 2. Specific changes needed per file + 3. Dependencies to consider + 4. Ordered implementation steps + + Focus on technical accuracy and implementation details. + """, + agent=planner, + expected_output=f"{CodeGenerationPlan.model_json_schema()}", + ) + + def create_implementation_task(self, context: AgentContext, implementer: Agent) -> Task: + return Task( + description=f""" + Implement code changes following the provided plan: + - Follow implementation steps precisely + - Maintain consistent code style + - Generate/modify code as needed + + For each file: + 1. Generate complete function/class if new + 2. Show only modified sections if updating + 3. Include necessary imports and dependencies + 4. Add/update docstrings as needed + + Return CodeModification objects for each change. + Use markdown code blocks with language specification. + """, + agent=implementer, + expected_output=f"{CodeModification.model_json_schema()}", + ) + + def create_validation_task(self, context: AgentContext, validator: Agent) -> Task: + return Task( + description=f""" + Validate implemented code changes: + - Review against original requirements + - Check consistency with existing code + - Verify proper handling of edge cases + + Provide validation notes including: + 1. Correctness of implementation + 2. Consistency with codebase + 3. Potential issues or concerns + 4. Suggestions for improvements + + Return list of validation notes. + """, + agent=validator, + expected_output=f"Return list of validation notes.", + ) + + async def run( + self, + query: str, + project_id: str, + node_ids: List[NodeContext], + ) -> CodeGenerationResult: + os.environ["OPENAI_API_KEY"] = self.openai_api_key + + code_results = [] + if len(node_ids) > 0: + code_results = await GetCodeFromMultipleNodeIdsTool( + self.sql_db, self.user_id + ).run_multiple(project_id, [node.node_id for node in node_ids]) + + context = AgentContext( + query=query, + project_id=project_id, + node_ids=node_ids, + code_results=code_results, + max_iter=self.max_iter, + ) + + # Create agents + analyzer = self.create_analyzer_agent() + planner = self.create_planner_agent() + implementer = self.create_implementer_agent() + validator = self.create_validator_agent() + + # Create tasks + analysis_task = self.create_analysis_task(context, analyzer) + planning_task = self.create_planning_task(context, planner) + implementation_task = self.create_implementation_task(context, implementer) + validation_task = self.create_validation_task(context, validator) + + # Create and run crew + crew = Crew( + agents=[analyzer, planner, implementer, validator], + tasks=[analysis_task, planning_task, implementation_task, validation_task], + process=Process.sequential, + verbose=False, + ) + + result = await crew.kickoff_async() + return result + + +async def kickoff_multi_agent_code_generation( + query: str, + project_id: str, + node_ids: List[NodeContext], + sql_db, + llm, + mini_llm, + user_id: str, +) -> CodeGenerationResult: + generator = MultiAgentCodeGenerator(sql_db, llm, mini_llm, user_id) + result = await generator.run(query, project_id, node_ids) + return result \ No newline at end of file diff --git a/app/modules/intelligence/agents/agents_service.py b/app/modules/intelligence/agents/agents_service.py index 24da9488..54ab7fb4 100644 --- a/app/modules/intelligence/agents/agents_service.py +++ b/app/modules/intelligence/agents/agents_service.py @@ -45,6 +45,11 @@ async def list_available_agents(self) -> List[AgentInfo]: name="Code Changes Agent", description="An agent specialized in generating detailed analysis of code changes in your current branch compared to default branch. Works best with Py, JS, TS", ), + AgentInfo( + id="code_generation_agent", + name="Code Generation Agent", + description="An agent specialized in generating code for new features or fixing bugs.", + ), ] def format_citations(self, citations: List[str]) -> List[str]: diff --git a/app/modules/intelligence/agents/chat_agents/code_gen.py b/app/modules/intelligence/agents/chat_agents/code_gen.py new file mode 100644 index 00000000..8071190e --- /dev/null +++ b/app/modules/intelligence/agents/chat_agents/code_gen.py @@ -0,0 +1,229 @@ +import json +import logging +import time +from functools import lru_cache +from typing import Any, AsyncGenerator, Dict, List + +from crewai import Agent, Task +from langchain.schema import HumanMessage, SystemMessage + +from sqlalchemy.orm import Session + +from app.modules.conversations.message.message_model import MessageType +from app.modules.conversations.message.message_schema import NodeContext +from app.modules.intelligence.agents.agentic_tools.code_gen_agent import kickoff_code_generation_crew + +from app.modules.intelligence.agents.agents_service import AgentsService +from app.modules.intelligence.memory.chat_history_service import ChatHistoryService + +from app.modules.intelligence.prompts.prompt_service import PromptService + +logger = logging.getLogger(__name__) + + +class CodeGenerationAgent: + def __init__(self, mini_llm, llm, db: Session): + self.mini_llm = mini_llm + self.llm = llm + self.history_manager = ChatHistoryService(db) + self.prompt_service = PromptService(db) + self.agents_service = AgentsService(db) + self.chain = None + self.db = db + +# [Previous imports and class definitions remain the same until the agent creation] + + async def create_agents(self): + code_generator = Agent( + role="Code Generation Agent", + goal="Generate precise, copy-paste ready code modifications that maintain project consistency", + backstory=f""" + You are an expert code generation agent specialized in creating production-ready, + immediately usable code modifications. Your primary responsibilities include: + 1. Analyzing existing codebase context and understanding dependencies + 2. Planning code changes that maintain exact project patterns and style + 3. Implementing changes with copy-paste ready output + 4. Following existing code conventions exactly as shown in the input files + 5. Never modifying string literals, escape characters, or formatting unless specifically requested + + Key principles: + - Provide required new imports in a separate code block + - Output only the specific functions/classes being modified + - Never change existing string formats or escape characters + - Maintain exact indentation and spacing patterns from original code + - Include clear section markers for where code should be inserted/modified + + Maintain efficiency within {self.max_iter} iterations while ensuring production-ready output. + """, + tools=[ + self.get_code_from_node_id, + self.get_code_from_multiple_node_ids, + self.get_node_neighbours, + ], + allow_delegation=False, + verbose=True, + llm=self.llm, + max_iter=self.max_iter, + ) + + return code_generator + + async def create_tasks( + self, + query: str, + project_id: str, + node_ids: List[NodeContext], + code_results: List[Dict[str, Any]], + code_generator, + ): + code_generation_task = Task( + description=f""" + Work within {self.max_iter} iterations to generate copy-paste ready code based on: + - Query: {query} + - Project ID: {project_id} + - Target Node IDs: {[node.model_dump() for node in node_ids]} + - Existing Code Context: {code_results} + + Follow this structured approach: + + 1. Context Analysis: + - Review existing code structure and patterns + - Use the get node neighbours tool to get the code context for nodes when required. + - Identify dependencies and relationships + - Understand the scope of required changes + - Review existing code style precisely + - Note exact indentation patterns + - Identify string literal formats + - Review import organization patterns + + 2. Implementation Planning: + Break down the required changes into discrete steps + - Identify potential impacts on other code sections + - Plan the most efficient implementation approach + - Plan changes that maintain exact formatting + - Never modify existing patterns or escape characters unless requested + - Identify required new imports + + 3. Code Generation Format: + File: `path/to/file.py` + Replace function/class: `name_of_function` + - or - + Insert after line: `X` + + Required imports (if any): + ```python + from new.module import NewClass + ``` + + Modified/New Code: + ```language + modified_function_name(): + # Your code here + + ``` + + Important Output Rules: + 1. Always separate new imports from main code changes + 2. Never modify existing string literals or escape characters + 3. Follow existing indentation exactly + 4. Include only the specific functions/classes being modified + 5. Provide clear location markers for each code block + 6. Maintain exact spacing patterns from original code + 7. For new files, provide complete file content with imports at top + 8. Format code blocks with language specification for syntax highlighting. + + + Keep responses focused and formatted for easy copy-paste into an IDE. + No conversation or unnecessary explanation - just clear, actionable code blocks. + """, + expected_output="Copy-paste ready code changes with clear location markers and required imports", + agent=code_generator, + ) + + return code_generation_task + +# [Rest of the implementation remains the same] + async def run( + self, + query: str, + project_id: str, + user_id: str, + conversation_id: str, + node_ids: List[NodeContext], + ) -> AsyncGenerator[str, None]: + start_time = time.time() + try: + history = self.history_manager.get_session_history(user_id, conversation_id) + validated_history = [ + ( + HumanMessage(content=str(msg)) + if isinstance(msg, (str, int, float)) + else msg + ) + for msg in history + ] + + tool_results = [] + citations = [] + code_gen_start_time = time.time() + + # Call multi-agent code generation instead of RAG + code_gen_result = await kickoff_code_generation_crew( + query, + project_id, + node_ids, + self.db, + self.llm, + self.mini_llm, + user_id, + ) + + code_gen_duration = time.time() - code_gen_start_time + logger.info( + f"Time elapsed since entering run: {time.time() - start_time:.2f}s, " + f"Duration of Code Generation: {code_gen_duration:.2f}s" + ) + + # Format the result for the response + # result = { + # "plan": code_gen_result.plan.dict(), + # "modifications": [mod.dict() for mod in code_gen_result.modifications], + # "validation_notes": code_gen_result.validation_notes + # } + result = code_gen_result.raw + + tool_results = [SystemMessage(content=result)] + + # Timing for adding message chunk + add_chunk_start_time = time.time() + self.history_manager.add_message_chunk( + conversation_id, + tool_results[0].content, + MessageType.AI_GENERATED, + citations=citations, + ) + add_chunk_duration = time.time() - add_chunk_start_time + logger.info( + f"Time elapsed since entering run: {time.time() - start_time:.2f}s, " + f"Duration of adding message chunk: {add_chunk_duration:.2f}s" + ) + + # Timing for flushing message buffer + flush_buffer_start_time = time.time() + self.history_manager.flush_message_buffer( + conversation_id, MessageType.AI_GENERATED + ) + flush_buffer_duration = time.time() - flush_buffer_start_time + logger.info( + f"Time elapsed since entering run: {time.time() - start_time:.2f}s, " + f"Duration of flushing message buffer: {flush_buffer_duration:.2f}s" + ) + + yield json.dumps({"citations": citations, "message": result}) + + except Exception as e: + logger.error(f"Error in code generation: {str(e)}") + error_message = f"An error occurred during code generation: {str(e)}" + yield json.dumps({"error": error_message}) + + From 3f8aa209df58e39310fc1872188931f4f39365cb Mon Sep 17 00:00:00 2001 From: dhirenmathur Date: Fri, 8 Nov 2024 18:27:46 +0530 Subject: [PATCH 2/7] added neighbours and knowledge graph query tool --- .../agents/agentic_tools/code_gen_agent.py | 248 ++++++++++++------ .../agents/agentic_tools/rag_agent.py | 2 +- .../agents/chat_agents/code_gen.py | 1 + 3 files changed, 165 insertions(+), 86 deletions(-) diff --git a/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py b/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py index cdbaff3a..3ea4fb97 100644 --- a/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py +++ b/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py @@ -2,7 +2,7 @@ from typing import Any, Dict, List from crewai import Agent, Crew, Process, Task - +import agentops from app.modules.conversations.message.message_schema import NodeContext from app.modules.intelligence.tools.code_query_tools.get_node_neighbours_from_node_id_tool import ( get_node_neighbours_from_node_id_tool, @@ -11,52 +11,45 @@ GetCodeFromMultipleNodeIdsTool, get_code_from_multiple_node_ids_tool, ) -from app.modules.intelligence.tools.kg_based_tools.get_code_from_node_id_tool import ( - get_code_from_node_id_tool, +from app.modules.intelligence.tools.kg_based_tools.get_code_from_probable_node_name_tool import ( + get_code_from_probable_node_name_tool, +) +from app.modules.intelligence.tools.kg_based_tools.ask_knowledge_graph_queries_tool import ( + get_ask_knowledge_graph_queries_tool, ) +from app.modules.intelligence.tools.kg_based_tools.get_nodes_from_tags_tool import get_nodes_from_tags_tool class CodeGenerationAgent: def __init__(self, sql_db, llm, mini_llm, user_id): self.openai_api_key = os.getenv("OPENAI_API_KEY") - self.max_iter = os.getenv("MAX_ITER", 5) + self.max_iter = os.getenv("MAX_ITER", 15) self.sql_db = sql_db - self.get_code_from_node_id = get_code_from_node_id_tool(sql_db, user_id) self.get_code_from_multiple_node_ids = get_code_from_multiple_node_ids_tool( sql_db, user_id ) self.get_node_neighbours = get_node_neighbours_from_node_id_tool(sql_db) + self.get_code_from_probable_node_name = get_code_from_probable_node_name_tool(sql_db, user_id) + self.query_knowledge_graph = get_ask_knowledge_graph_queries_tool(sql_db, user_id) + self.get_nodes_from_tags = get_nodes_from_tags_tool(sql_db, user_id) self.llm = llm self.mini_llm = mini_llm self.user_id = user_id async def create_agents(self): + # [Previous create_agents code remains the same until the task description] code_generator = Agent( role="Code Generation Agent", - goal="Generate precise, copy-paste ready code modifications that maintain project consistency", + goal="Generate precise, copy-paste ready code modifications that maintain project consistency and handle all dependencies", backstory=f""" - You are an expert code generation agent specialized in creating production-ready, - immediately usable code modifications. Your primary responsibilities include: - 1. Analyzing existing codebase context and understanding dependencies - 2. Planning code changes that maintain exact project patterns and style - 3. Implementing changes with copy-paste ready output - 4. Following existing code conventions exactly as shown in the input files - 5. Never modifying string literals, escape characters, or formatting unless specifically requested - - Key principles: - - Provide required new imports in a separate code block - - Output only the specific functions/classes being modified - - Never change existing string formats or escape characters - - Maintain exact indentation and spacing patterns from original code - - Include clear section markers for where code should be inserted/modified - - Maintain efficiency within {self.max_iter} iterations while ensuring production-ready output. + [Previous backstory remains the same] """, tools=[ - self.get_code_from_node_id, self.get_code_from_multiple_node_ids, self.get_node_neighbours, + self.get_code_from_probable_node_name, + self.query_knowledge_graph, ], allow_delegation=False, verbose=True, @@ -69,7 +62,8 @@ async def create_agents(self): async def create_tasks( self, query: str, - project_id: str, + project_id: str, + history: str, node_ids: List[NodeContext], code_results: List[Dict[str, Any]], code_generator, @@ -79,80 +73,159 @@ async def create_tasks( Work within {self.max_iter} iterations to generate copy-paste ready code based on: - Query: {query} - Project ID: {project_id} + - History: {history} - Target Node IDs: {[node.model_dump() for node in node_ids]} - Existing Code Context: {code_results} Follow this structured approach: - 1. Context Analysis: - - Review existing code style precisely - - Note exact indentation patterns - - Identify string literal formats - - Review import organization patterns - - 2. Implementation Planning: - - Plan changes that maintain exact formatting - - Never modify existing patterns unless requested - - Identify required new imports - - 3. Code Generation Format: - Required imports (if any): - ```python - from new.module import NewClass - ``` - - Modified/New Code: - ```python - def modified_function(): - # Your code here - pass - ``` - - Location Guide: - ``` - File: path/to/file.py - Replace function/class: name_of_function - - or - - Insert after line: X - ``` - - Important Output Rules: - 1. Always separate new imports from main code changes - 2. Never modify existing string literals or escape characters - 3. Follow existing indentation exactly - 4. Include only the specific functions/classes being modified - 5. Provide clear location markers for each code block - 6. Maintain exact spacing patterns from original code - 7. For new files, provide complete file content with imports at top - 8. Format code blocks with language specification for syntax highlighting - - Your response format should be: - - Brief explanation of changes (2-3 lines max) - - Required Imports: - [code block with imports] - - Code Changes: - [code block with changes] - - Location: - [location details] + 1. Query Analysis: + - Identify ALL file names or function names mentioned in the query + - For files without node_ids, use get_code_from_probable_node_name tool + - Example: "Update file1.py and config.py" -> fetch config.py and file1.py using tool if you dont already have their code + - Look for words that could be file names or function names based on the query (e.g., requirements, utils, update document etc.) + - Identify any data storage or schema changes that might affect multiple files + + 2. Dependency Analysis: + - Use get_node_neighbours tool on EACH function or file to be modified (works best with function names) + - Analyze import relationships and dependencies EXHAUSTIVELY + - Identify ALL files that import the modified files + - Identify ALL files that interact with the modified functionality + - Map the complete chain of dependencies: + * Direct importers + * Interface implementations + * Shared data structures + * Database interactions + * API consumers + - Document required changes in ALL dependent files + - Flag any file that touches the modified functionality, even if changes seem minor + + 3. Context Analysis: + - Review existing code precisely to maintain standard formatting + - Note exact indentation patterns + - Identify string literal formats + - Review import organization patterns + - Ensure ALL required files are fetched before proceeding + - Check dependency compatibility + - Analyze database schemas and interactions + - Review API contracts and interfaces + + 4. Implementation Planning: + - Plan changes that maintain exact formatting + - Never modify existing patterns unless requested + - Identify required new imports + - Plan changes for ALL files identified in steps 1 and 2 + - Consider impact on dependent files + - Ensure changes maintain dependency compatibility + - CRITICAL: Create concrete changes for EVERY impacted file + - Map all required database schema updates + - Detail API changes and version impacts + + 5. Code Generation Format: + Structure your response in this user-friendly format: + + 📝 Overview + ----------- + A 2-3 line summary of the changes to be made. + + 🔍 Dependency Analysis + -------------------- + • Primary Changes: + - file1.py: [brief reason] + - file2.py: [brief reason] + + • Required Dependency Updates: + - dependent1.py: [specific changes needed] + - dependent2.py: [specific changes needed] + + • Database Changes: + - Schema updates + - Migration requirements + - Data validation changes + + 📦 Changes by File + ---------------- + [REPEAT THIS SECTION FOR EVERY IMPACTED FILE, INCLUDING DEPENDENCIES] + + ### 📄 [filename.py] - Keep responses focused and formatted for easy copy-paste into an IDE. - No conversation or unnecessary explanation - just clear, actionable code blocks. + **Purpose of Changes:** + Brief explanation of what's being changed and why + + **Required Imports:** + ```python + from new.module import NewClass + ``` + + **Code Changes:** + ```python + def modified_function(): + # Your code here + pass + ``` + + [IMPORTANT: Include ALL dependent files with their complete changes] + + ⚠️ Important Notes + ---------------- + • Breaking Changes: [if any] + • Required Manual Steps: [if any] + • Testing Recommendations: [if any] + • Database Migration Steps: [if any] + + 🔄 Verification Steps + ------------------ + 1. [Step-by-step verification process] + 2. [Expected outcomes] + 3. [How to verify the changes work] + 4. [Database verification steps] + 5. [API testing steps] + + Important Response Rules: + 1. Use clear section emojis and headers for visual separation + 2. Keep each section concise but informative + 3. Use bullet points and numbering for better readability + 4. Include only relevant information in each section + 5. Use code blocks with language specification + 6. Highlight important warnings or notes + 7. Provide clear, actionable verification steps + 8. Keep formatting consistent across all files + 9. Use emojis sparingly and only for section headers + 10. Maintain a clean, organized structure throughout + 11. NEVER skip dependent file changes + 12. Always include database migration steps when relevant + 13. Detail API version impacts and migration paths + + Remember to: + - Format code blocks for direct copy-paste + - Highlight breaking changes prominently + - Make location instructions crystal clear + - Include all necessary context for each change + - Keep the overall structure scannable and navigable + - MUST provide concrete changes for ALL impacted files + - Include specific database migration steps when needed + - Detail API versioning requirements + + The output should be easy to: + - Read in a chat interface + - Copy-paste into an IDE + - Understand at a glance + - Navigate through multiple files + - Use as a checklist for implementation + - Execute database migrations + - Manage API versioning """, - expected_output="Copy-paste ready code changes with clear location markers and required imports", + expected_output="User-friendly, clearly structured code changes with comprehensive dependency analysis, implementation details for ALL impacted files, and complete verification steps", agent=code_generator, ) return code_generation_task - - + async def run( self, query: str, project_id: str, + history: str, node_ids: List[NodeContext], ) -> str: os.environ["OPENAI_API_KEY"] = self.openai_api_key @@ -167,6 +240,7 @@ async def run( generation_task = await self.create_tasks( query, project_id, + history, node_ids, code_results, code_generator, @@ -178,14 +252,18 @@ async def run( process=Process.sequential, verbose=False, ) - + agentops.init( + os.getenv("AGENTOPS_API_KEY") + ) result = await crew.kickoff_async() + agentops.end_session("Success") return result async def kickoff_code_generation_crew( query: str, project_id: str, + history: str, node_ids: List[NodeContext], sql_db, llm, @@ -193,5 +271,5 @@ async def kickoff_code_generation_crew( user_id: str, ) -> str: code_gen_agent = CodeGenerationAgent(sql_db, llm, mini_llm, user_id) - result = await code_gen_agent.run(query, project_id, node_ids) + result = await code_gen_agent.run(query, project_id, history, node_ids) return result \ No newline at end of file diff --git a/app/modules/intelligence/agents/agentic_tools/rag_agent.py b/app/modules/intelligence/agents/agentic_tools/rag_agent.py index cc1942b4..5e9a2613 100644 --- a/app/modules/intelligence/agents/agentic_tools/rag_agent.py +++ b/app/modules/intelligence/agents/agentic_tools/rag_agent.py @@ -196,7 +196,7 @@ async def run( os.environ["OPENAI_API_KEY"] = self.openai_api_key agentops.init( - os.getenv("AGENTOPS_API_KEY"), default_tags=["openai-gpt-notebook"] + os.getenv("AGENTOPS_API_KEY") ) code_results = [] if len(node_ids) > 0: diff --git a/app/modules/intelligence/agents/chat_agents/code_gen.py b/app/modules/intelligence/agents/chat_agents/code_gen.py index 8071190e..709eb345 100644 --- a/app/modules/intelligence/agents/chat_agents/code_gen.py +++ b/app/modules/intelligence/agents/chat_agents/code_gen.py @@ -171,6 +171,7 @@ async def run( code_gen_result = await kickoff_code_generation_crew( query, project_id, + validated_history[-5:], node_ids, self.db, self.llm, From 9263662a5d1c74435961ebc5bf0f4cb76935fcd9 Mon Sep 17 00:00:00 2001 From: dhirenmathur Date: Sat, 9 Nov 2024 11:37:24 +0530 Subject: [PATCH 3/7] file structure tool --- .../agents/agentic_tools/code_gen_agent.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py b/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py index 3ea4fb97..1ba7c862 100644 --- a/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py +++ b/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py @@ -18,7 +18,7 @@ get_ask_knowledge_graph_queries_tool, ) from app.modules.intelligence.tools.kg_based_tools.get_nodes_from_tags_tool import get_nodes_from_tags_tool - +from app.modules.intelligence.tools.code_query_tools.get_code_file_structure import get_code_file_structure_tool class CodeGenerationAgent: def __init__(self, sql_db, llm, mini_llm, user_id): @@ -32,6 +32,7 @@ def __init__(self, sql_db, llm, mini_llm, user_id): self.get_code_from_probable_node_name = get_code_from_probable_node_name_tool(sql_db, user_id) self.query_knowledge_graph = get_ask_knowledge_graph_queries_tool(sql_db, user_id) self.get_nodes_from_tags = get_nodes_from_tags_tool(sql_db, user_id) + self.get_file_structure = get_code_file_structure_tool(sql_db) self.llm = llm self.mini_llm = mini_llm self.user_id = user_id @@ -50,6 +51,8 @@ async def create_agents(self): self.get_node_neighbours, self.get_code_from_probable_node_name, self.query_knowledge_graph, + self.get_nodes_from_tags, + self.get_file_structure, ], allow_delegation=False, verbose=True, @@ -109,7 +112,10 @@ async def create_tasks( - Check dependency compatibility - Analyze database schemas and interactions - Review API contracts and interfaces - + - IF NO SPECIFIC FILES ARE FOUND: + * FIRST Use get_file_structure tool to get the file structure of the project and get any relevant file context + * THEN IF STILL NO SPECIFIC FILES ARE FOUND, use get_nodes_from_tags tool to search by relevant tags + 4. Implementation Planning: - Plan changes that maintain exact formatting - Never modify existing patterns unless requested @@ -120,6 +126,9 @@ async def create_tasks( - CRITICAL: Create concrete changes for EVERY impacted file - Map all required database schema updates - Detail API changes and version impacts + + CRITICAL: If any file that is REQUIRED to propose changes is missing, stop and request the user to provide the file using "@filename" or "@functionname". NEVER create hypothetical files. + 5. Code Generation Format: Structure your response in this user-friendly format: From 9197ed74b7e2498d9c53b73a29b5692cb9ff6134 Mon Sep 17 00:00:00 2001 From: dhirenmathur Date: Wed, 13 Nov 2024 19:23:20 +0530 Subject: [PATCH 4/7] update code gen agent --- .../agents/agentic_tools/code_gen_agent.py | 16 ++- .../agents/chat_agents/code_gen.py | 109 ------------------ 2 files changed, 14 insertions(+), 111 deletions(-) diff --git a/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py b/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py index 1ba7c862..62f1778c 100644 --- a/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py +++ b/app/modules/intelligence/agents/agentic_tools/code_gen_agent.py @@ -44,8 +44,20 @@ async def create_agents(self): role="Code Generation Agent", goal="Generate precise, copy-paste ready code modifications that maintain project consistency and handle all dependencies", backstory=f""" - [Previous backstory remains the same] - """, + You are an expert code generation agent specialized in creating production-ready, + immediately usable code modifications. Your primary responsibilities include: + 1. Analyzing existing codebase context and understanding dependencies + 2. Planning code changes that maintain exact project patterns and style + 3. Implementing changes with copy-paste ready output + 4. Following existing code conventions exactly as shown in the input files + 5. Never modifying string literals, escape characters, or formatting unless specifically requested + + Key principles: + - Provide required new imports in a separate code block + - Output only the specific functions/classes being modified + - Never change existing string formats or escape characters + - Maintain exact indentation and spacing patterns from original code + - Include clear section markers for where code should be inserted/modified """, tools=[ self.get_code_from_multiple_node_ids, self.get_node_neighbours, diff --git a/app/modules/intelligence/agents/chat_agents/code_gen.py b/app/modules/intelligence/agents/chat_agents/code_gen.py index 709eb345..21d00770 100644 --- a/app/modules/intelligence/agents/chat_agents/code_gen.py +++ b/app/modules/intelligence/agents/chat_agents/code_gen.py @@ -31,116 +31,7 @@ def __init__(self, mini_llm, llm, db: Session): self.chain = None self.db = db -# [Previous imports and class definitions remain the same until the agent creation] - - async def create_agents(self): - code_generator = Agent( - role="Code Generation Agent", - goal="Generate precise, copy-paste ready code modifications that maintain project consistency", - backstory=f""" - You are an expert code generation agent specialized in creating production-ready, - immediately usable code modifications. Your primary responsibilities include: - 1. Analyzing existing codebase context and understanding dependencies - 2. Planning code changes that maintain exact project patterns and style - 3. Implementing changes with copy-paste ready output - 4. Following existing code conventions exactly as shown in the input files - 5. Never modifying string literals, escape characters, or formatting unless specifically requested - - Key principles: - - Provide required new imports in a separate code block - - Output only the specific functions/classes being modified - - Never change existing string formats or escape characters - - Maintain exact indentation and spacing patterns from original code - - Include clear section markers for where code should be inserted/modified - - Maintain efficiency within {self.max_iter} iterations while ensuring production-ready output. - """, - tools=[ - self.get_code_from_node_id, - self.get_code_from_multiple_node_ids, - self.get_node_neighbours, - ], - allow_delegation=False, - verbose=True, - llm=self.llm, - max_iter=self.max_iter, - ) - - return code_generator - - async def create_tasks( - self, - query: str, - project_id: str, - node_ids: List[NodeContext], - code_results: List[Dict[str, Any]], - code_generator, - ): - code_generation_task = Task( - description=f""" - Work within {self.max_iter} iterations to generate copy-paste ready code based on: - - Query: {query} - - Project ID: {project_id} - - Target Node IDs: {[node.model_dump() for node in node_ids]} - - Existing Code Context: {code_results} - - Follow this structured approach: - - 1. Context Analysis: - - Review existing code structure and patterns - - Use the get node neighbours tool to get the code context for nodes when required. - - Identify dependencies and relationships - - Understand the scope of required changes - - Review existing code style precisely - - Note exact indentation patterns - - Identify string literal formats - - Review import organization patterns - - 2. Implementation Planning: - Break down the required changes into discrete steps - - Identify potential impacts on other code sections - - Plan the most efficient implementation approach - - Plan changes that maintain exact formatting - - Never modify existing patterns or escape characters unless requested - - Identify required new imports - - 3. Code Generation Format: - File: `path/to/file.py` - Replace function/class: `name_of_function` - - or - - Insert after line: `X` - - Required imports (if any): - ```python - from new.module import NewClass - ``` - - Modified/New Code: - ```language - modified_function_name(): - # Your code here - - ``` - - Important Output Rules: - 1. Always separate new imports from main code changes - 2. Never modify existing string literals or escape characters - 3. Follow existing indentation exactly - 4. Include only the specific functions/classes being modified - 5. Provide clear location markers for each code block - 6. Maintain exact spacing patterns from original code - 7. For new files, provide complete file content with imports at top - 8. Format code blocks with language specification for syntax highlighting. - - Keep responses focused and formatted for easy copy-paste into an IDE. - No conversation or unnecessary explanation - just clear, actionable code blocks. - """, - expected_output="Copy-paste ready code changes with clear location markers and required imports", - agent=code_generator, - ) - - return code_generation_task # [Rest of the implementation remains the same] async def run( From b4583bd8b0c7ad86b75988cd4e0b12d1113cb856 Mon Sep 17 00:00:00 2001 From: dhirenmathur Date: Wed, 20 Nov 2024 23:12:27 +0530 Subject: [PATCH 5/7] delete unused file --- .../agentic_tools/multi_agent_code_gen.py | 282 ------------------ 1 file changed, 282 deletions(-) delete mode 100644 app/modules/intelligence/agents/agentic_tools/multi_agent_code_gen.py diff --git a/app/modules/intelligence/agents/agentic_tools/multi_agent_code_gen.py b/app/modules/intelligence/agents/agentic_tools/multi_agent_code_gen.py deleted file mode 100644 index 2b056b77..00000000 --- a/app/modules/intelligence/agents/agentic_tools/multi_agent_code_gen.py +++ /dev/null @@ -1,282 +0,0 @@ -import os -from typing import Any, Dict, List -from dataclasses import dataclass - -from crewai import Agent, Crew, Process, Task -from pydantic import BaseModel, Field - -from app.modules.conversations.message.message_schema import NodeContext -from app.modules.intelligence.tools.code_query_tools.get_node_neighbours_from_node_id_tool import ( - get_node_neighbours_from_node_id_tool, -) -from app.modules.intelligence.tools.kg_based_tools.get_code_from_multiple_node_ids_tool import ( - GetCodeFromMultipleNodeIdsTool, - get_code_from_multiple_node_ids_tool, -) -from app.modules.intelligence.tools.kg_based_tools.get_code_from_node_id_tool import ( - get_code_from_node_id_tool, -) - - -class CodeGenerationPlan(BaseModel): - affected_files: List[str] = Field(..., description="Files that need modification") - changes_required: Dict[str, str] = Field(..., description="Required changes per file") - dependencies: List[str] = Field(..., description="Related dependencies to consider") - implementation_steps: List[str] = Field(..., description="Ordered steps for implementation") - - -class CodeModification(BaseModel): - file_path: str - original_code: str - updated_code: str - changes_description: str - - -class CodeGenerationResult(BaseModel): - plan: CodeGenerationPlan - modifications: List[CodeModification] - validation_notes: List[str] - - -@dataclass -class AgentContext: - query: str - project_id: str - node_ids: List[NodeContext] - code_results: List[Dict[str, Any]] - max_iter: int - - -class MultiAgentCodeGenerator: - def __init__(self, sql_db, llm, mini_llm, user_id): - self.openai_api_key = os.getenv("OPENAI_API_KEY") - self.max_iter = os.getenv("MAX_ITER", 5) - self.sql_db = sql_db - self.get_code_from_node_id = get_code_from_node_id_tool(sql_db, user_id) - self.get_code_from_multiple_node_ids = get_code_from_multiple_node_ids_tool( - sql_db, user_id - ) - self.get_node_neighbours = get_node_neighbours_from_node_id_tool(sql_db) - self.llm = llm - self.mini_llm = mini_llm - self.user_id = user_id - - def create_analyzer_agent(self) -> Agent: - return Agent( - role="Code Context Analyzer", - goal="Analyze existing codebase and create comprehensive context for modifications", - backstory=""" - You are an expert code analyst specialized in understanding codebases and their structures. - You excel at: - 1. Analyzing code patterns and architecture - 2. Identifying dependencies and relationships - 3. Understanding the scope and impact of changes - 4. Creating detailed context for other agents - """, - tools=[ - self.get_code_from_node_id, - self.get_code_from_multiple_node_ids, - self.get_node_neighbours, - ], - allow_delegation=True, - verbose=True, - llm=self.llm, - ) - - def create_planner_agent(self) -> Agent: - return Agent( - role="Implementation Planner", - goal="Create detailed implementation plan based on analysis", - backstory=""" - You are a strategic code planner who excels at: - 1. Breaking down complex changes into manageable steps - 2. Identifying potential risks and dependencies - 3. Creating clear implementation roadmaps - 4. Ensuring minimal impact on existing functionality - """, - tools=[], # Planner uses context from analyzer - allow_delegation=True, - verbose=True, - llm=self.llm, - ) - - def create_implementer_agent(self) -> Agent: - return Agent( - role="Code Implementer", - goal="Generate and modify code according to the implementation plan", - backstory=""" - You are an expert code implementer who: - 1. Writes clean, efficient code - 2. Follows existing patterns and conventions - 3. Implements changes with precision - 4. Maintains code quality and consistency - """, - tools=[ - self.get_code_from_node_id, - self.get_code_from_multiple_node_ids, - ], - allow_delegation=True, - verbose=True, - llm=self.llm, - ) - - def create_validator_agent(self) -> Agent: - return Agent( - role="Code Validator", - goal="Validate generated code for correctness and consistency", - backstory=""" - You are a thorough code validator who: - 1. Reviews code changes for correctness - 2. Ensures consistency with existing codebase - 3. Identifies potential issues or edge cases - 4. Provides validation feedback - """, - tools=[ - self.get_code_from_node_id, - self.get_node_neighbours, - ], - allow_delegation=True, - verbose=True, - llm=self.llm, - ) - - def create_analysis_task(self, context: AgentContext, analyzer: Agent) -> Task: - return Task( - description=f""" - Analyze the codebase context within {context.max_iter} iterations: - - Query: {context.query} - - Project ID: {context.project_id} - - Target Nodes: {[node.model_dump() for node in context.node_ids]} - - Existing Code: {context.code_results} - - Provide: - 1. Detailed analysis of affected code sections - 2. Identification of patterns and conventions - 3. List of dependencies and relationships - 4. Potential impact areas - - Return analysis in structured format focusing on technical details. - """, - agent=analyzer, - expected_output="Return analysis in structured format focusing on technical details.", - ) - - def create_planning_task(self, context: AgentContext, planner: Agent) -> Task: - return Task( - description=f""" - Create implementation plan based on analysis: - - Break down the query: {context.query} - - Consider provided analysis - - Design step-by-step implementation approach - - Provide CodeGenerationPlan with: - 1. List of affected files - 2. Specific changes needed per file - 3. Dependencies to consider - 4. Ordered implementation steps - - Focus on technical accuracy and implementation details. - """, - agent=planner, - expected_output=f"{CodeGenerationPlan.model_json_schema()}", - ) - - def create_implementation_task(self, context: AgentContext, implementer: Agent) -> Task: - return Task( - description=f""" - Implement code changes following the provided plan: - - Follow implementation steps precisely - - Maintain consistent code style - - Generate/modify code as needed - - For each file: - 1. Generate complete function/class if new - 2. Show only modified sections if updating - 3. Include necessary imports and dependencies - 4. Add/update docstrings as needed - - Return CodeModification objects for each change. - Use markdown code blocks with language specification. - """, - agent=implementer, - expected_output=f"{CodeModification.model_json_schema()}", - ) - - def create_validation_task(self, context: AgentContext, validator: Agent) -> Task: - return Task( - description=f""" - Validate implemented code changes: - - Review against original requirements - - Check consistency with existing code - - Verify proper handling of edge cases - - Provide validation notes including: - 1. Correctness of implementation - 2. Consistency with codebase - 3. Potential issues or concerns - 4. Suggestions for improvements - - Return list of validation notes. - """, - agent=validator, - expected_output=f"Return list of validation notes.", - ) - - async def run( - self, - query: str, - project_id: str, - node_ids: List[NodeContext], - ) -> CodeGenerationResult: - os.environ["OPENAI_API_KEY"] = self.openai_api_key - - code_results = [] - if len(node_ids) > 0: - code_results = await GetCodeFromMultipleNodeIdsTool( - self.sql_db, self.user_id - ).run_multiple(project_id, [node.node_id for node in node_ids]) - - context = AgentContext( - query=query, - project_id=project_id, - node_ids=node_ids, - code_results=code_results, - max_iter=self.max_iter, - ) - - # Create agents - analyzer = self.create_analyzer_agent() - planner = self.create_planner_agent() - implementer = self.create_implementer_agent() - validator = self.create_validator_agent() - - # Create tasks - analysis_task = self.create_analysis_task(context, analyzer) - planning_task = self.create_planning_task(context, planner) - implementation_task = self.create_implementation_task(context, implementer) - validation_task = self.create_validation_task(context, validator) - - # Create and run crew - crew = Crew( - agents=[analyzer, planner, implementer, validator], - tasks=[analysis_task, planning_task, implementation_task, validation_task], - process=Process.sequential, - verbose=False, - ) - - result = await crew.kickoff_async() - return result - - -async def kickoff_multi_agent_code_generation( - query: str, - project_id: str, - node_ids: List[NodeContext], - sql_db, - llm, - mini_llm, - user_id: str, -) -> CodeGenerationResult: - generator = MultiAgentCodeGenerator(sql_db, llm, mini_llm, user_id) - result = await generator.run(query, project_id, node_ids) - return result \ No newline at end of file From ba18db3721fc93b4a5c51c8036d0ed7ed98387ba Mon Sep 17 00:00:00 2001 From: dhirenmathur Date: Wed, 27 Nov 2024 12:19:25 +0530 Subject: [PATCH 6/7] rename --- .../intelligence/agents/agent_injector_service.py | 4 ++-- .../{code_gen.py => code_gen_chat_agent.py} | 11 +---------- 2 files changed, 3 insertions(+), 12 deletions(-) rename app/modules/intelligence/agents/chat_agents/{code_gen.py => code_gen_chat_agent.py} (90%) diff --git a/app/modules/intelligence/agents/agent_injector_service.py b/app/modules/intelligence/agents/agent_injector_service.py index 3de9d0e3..8775087d 100644 --- a/app/modules/intelligence/agents/agent_injector_service.py +++ b/app/modules/intelligence/agents/agent_injector_service.py @@ -3,7 +3,7 @@ from sqlalchemy.orm import Session -from app.modules.intelligence.agents.chat_agents.code_gen import CodeGenerationAgent +from app.modules.intelligence.agents.chat_agents.code_gen_chat_agent import CodeGenerationChatAgent from app.modules.intelligence.agents.chat_agents.code_changes_agent import ( CodeChangesAgent, ) @@ -39,7 +39,7 @@ def _initialize_agents(self) -> Dict[str, Any]: mini_llm, reasoning_llm, self.sql_db ), "LLD_agent": LLDAgent(mini_llm, reasoning_llm, self.sql_db), - "code_generation_agent": CodeGenerationAgent( + "code_generation_agent": CodeGenerationChatAgent( mini_llm, reasoning_llm, self.sql_db ), } diff --git a/app/modules/intelligence/agents/chat_agents/code_gen.py b/app/modules/intelligence/agents/chat_agents/code_gen_chat_agent.py similarity index 90% rename from app/modules/intelligence/agents/chat_agents/code_gen.py rename to app/modules/intelligence/agents/chat_agents/code_gen_chat_agent.py index 21d00770..39b8b29c 100644 --- a/app/modules/intelligence/agents/chat_agents/code_gen.py +++ b/app/modules/intelligence/agents/chat_agents/code_gen_chat_agent.py @@ -21,7 +21,7 @@ logger = logging.getLogger(__name__) -class CodeGenerationAgent: +class CodeGenerationChatAgent: def __init__(self, mini_llm, llm, db: Session): self.mini_llm = mini_llm self.llm = llm @@ -32,8 +32,6 @@ def __init__(self, mini_llm, llm, db: Session): self.db = db - -# [Rest of the implementation remains the same] async def run( self, query: str, @@ -76,17 +74,10 @@ async def run( f"Duration of Code Generation: {code_gen_duration:.2f}s" ) - # Format the result for the response - # result = { - # "plan": code_gen_result.plan.dict(), - # "modifications": [mod.dict() for mod in code_gen_result.modifications], - # "validation_notes": code_gen_result.validation_notes - # } result = code_gen_result.raw tool_results = [SystemMessage(content=result)] - # Timing for adding message chunk add_chunk_start_time = time.time() self.history_manager.add_message_chunk( conversation_id, From da4687aee5144878bd27faa2c3098fd4e0093401 Mon Sep 17 00:00:00 2001 From: dhirenmathur Date: Wed, 27 Nov 2024 12:25:18 +0530 Subject: [PATCH 7/7] add status to code gen agent --- app/modules/intelligence/agents/agents_service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/app/modules/intelligence/agents/agents_service.py b/app/modules/intelligence/agents/agents_service.py index 0dc10211..7619ad3b 100644 --- a/app/modules/intelligence/agents/agents_service.py +++ b/app/modules/intelligence/agents/agents_service.py @@ -59,6 +59,7 @@ async def list_available_agents( id="code_generation_agent", name="Code Generation Agent", description="An agent specialized in generating code for new features or fixing bugs.", + status="SYSTEM", ), ]