← all conversations

LLM Idea Expansion

2025-01-202 turns19,861 charsgpt-4o
llm-agentsidea-expansionmetadata-tracking

Summary

User wants to redesign an LLM program with 3 agents focused on idea expansion, including metadata tracking per LLM call.

Messages

rewrite this program to be more concise with only 3 agents and make it about fleshing out ideas and include an input prompt to base the initial idea on, what I want to be different is there to be meta data included with each LLM call so that one of the agents is a summarizer for a meta ledger to add context for future calls : import os import json from typing import Dict, Optional import logging from datetime import datetime import requests # Ensure `requests` library is installed # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) class OutputManager: """Manages the structured output from different phases of the project.""" def __init__(self, base_dir: str = "outputs"): self.base_dir = base_dir self.current_session = datetime.now().strftime("%Y%m%d_%H%M%S") self.session_dir = os.path.join(base_dir, self.current_session) self.create_directories() def create_directories(self): """Create necessary directories for output storage.""" os.makedirs(self.session_dir, exist_ok=True) def save_phase_output(self, phase_name: str, output_data: Dict, timestamp: Optional[str] = None): """Save output from a specific phase to its own file.""" if timestamp is None: timestamp = datetime.now().isoformat() phase_data = { "timestamp": timestamp, "data": output_data } filename = os.path.join(self.session_dir, f"{phase_name.lower()}_output.json") with open(filename, 'w') as f: json.dump(phase_data, f, indent=4) logger.info(f"Saved {phase_name} output to {filename}") def load_phase_output(self, phase_name: str) -> Dict: """Load output from a specific phase.""" filename = os.path.join(self.session_dir, f"{phase_name.lower()}_output.json") try: with open(filename, 'r') as f: return json.load(f) except FileNotFoundError: logger.warning(f"No output file found for phase {phase_name}") return {} def generate_consolidated_output(self) -> Dict: """Generate a consolidated output from all phases.""" consolidated = { "session_id": self.current_session, "timestamp": datetime.now().isoformat(), "phases": {} } for phase_file in os.listdir(self.session_dir): if phase_file.endswith('_output.json'): phase_name = phase_file.replace('_output.json', '') with open(os.path.join(self.session_dir, phase_file), 'r') as f: consolidated["phases"][phase_name] = json.load(f) consolidated_file = os.path.join(self.session_dir, "consolidated_output.json") with open(consolidated_file, 'w') as f: json.dump(consolidated, f, indent=4) return consolidated class PromptTemplate: """Manages prompt templates and their rendering.""" TEMPLATES = { "ideation": """ System: You are an expert software architect helping with project ideation. Context: We need to generate high-level requirements for a software project. Task: Generate a comprehensive list of high-level requirements and group them into the following domains: - Core Business Logic - User Interface - Data Management - Integration Points - Security Requirements Requirements should be: 1. Clear and concise 2. Measurable where possible 3. Aligned with business goals 4. Technically feasible Previous Output: {previous_output} """, # Other templates... 'requirements': """ System: You are a software architect working on a new project. Context: You have been provided with the following high-level requirements: {requirements} """, 'structuring': """ System: You are a software architect working on a new project. Context: You have been provided with the following user stories: {user_stories} """, 'development': """ System: You are a software developer working on a new project. Context: You have been provided with the following DDD schema: {ddd_schema} """, 'ux_design': """ System: You are a UX designer working on a new project. Context: You have been provided with the following user stories: {requirements} """, 'deployment': """ System: You are a DevOps engineer working on a new project. Context: You need to generate a deployment configuration for the project. """, 'validation': """ System: You are a QA engineer working on a new project. Context: You have been provided with the following user stories: {user_stories} """ } @staticmethod def render(template_name: str, **kwargs) -> str: """Render a template with the given parameters.""" template = PromptTemplate.TEMPLATES.get(template_name) if not template: raise ValueError(f"Template {template_name} not found") return template.format(**kwargs) class BaseAgent: def __init__(self, output_manager: OutputManager): self.output_manager = output_manager self.model = "vanilj/phi-4:latest" def interact_with_llm(self, prompt: str, temperature: float = 0.7) -> str: """Interact with the Ollama LLM API.""" try: logger.info(f"Sending prompt to LLM (length: {len(prompt)})") response = requests.post( "http://localhost:11434/api/generate", json={ "model": self.model, "prompt": prompt, "temperature": temperature, "stream": False } ) response.raise_for_status() data = response.json() logger.info("Received response from LLM") return data.get("response", "No response received") except requests.RequestException as e: logger.error(f"Error in LLM interaction: {str(e)}") raise class Orchestrator: def __init__(self, base_output_dir: str = "outputs"): self.output_manager = OutputManager(base_output_dir) self.agents = [ ("Ideation", IdeationAgent(self.output_manager)), ("Requirements", RequirementsAgent(self.output_manager)), ("Structuring", StructuringAgent(self.output_manager)), ("Development", DevelopmentPhase1Agent(self.output_manager)), ("UX_Design", UXDesignAgent(self.output_manager)), ("Deployment", DeploymentAgent(self.output_manager)), ("Validation", ValidationAgent(self.output_manager)) ] def run(self): for phase_name, agent in self.agents: logger.info(f"Starting {phase_name} Phase") try: agent.run() logger.info(f"{phase_name} Phase completed successfully") except Exception as e: logger.error(f"Error in {phase_name} Phase: {str(e)}") break # Generate consolidated output consolidated_output = self.output_manager.generate_consolidated_output() logger.info("Generated consolidated output") return consolidated_output def generate_final_output(self): # Generate timestamp for filename timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") output_filename = os.path.join(self.output_dir, f"output_{timestamp}.md") # Load the final data from the file and print the consolidated results try: with open(self.data_file, 'r') as f: data = json.load(f) # Checking if 'ideation' is part of the data if 'ideation' not in data: logger.warning("Ideation phase data is missing.") data['ideation'] = {} with open(output_filename, 'w') as f: json.dump(data, f, indent=4) logger.info(f"Final output written to {output_filename}") print("\n=== Final Output ===") print(json.dumps(data, indent=4)) except FileNotFoundError: logger.error(f"Data file {self.data_file} not found.") except json.JSONDecodeError: logger.error(f"Error reading the JSON data file {self.data_file}.") class IdeationAgent(BaseAgent): def run(self): logger.info("Starting Ideation Phase") previous_output = self.output_manager.load_phase_output("ideation").get("data", {}).get("requirements", "") prompt = PromptTemplate.render("ideation", previous_output=previous_output) response = self.interact_with_llm(prompt) output = { "requirements": response, "metadata": { "phase": "ideation", "version": "1.0" } } self.output_manager.save_phase_output("ideation", output) logger.info("Ideation phase completed") # Similar implementation for other agents... # [RequirementsAgent, StructuringAgent, etc.] class RequirementsAgent(BaseAgent): def run(self): logger.info("Starting Requirements Phase") # Load ideation output ideation_data = self.output_manager.load_phase_output("ideation") requirements = ideation_data.get("data", {}).get("requirements", "") prompt = PromptTemplate.render("requirements", requirements=requirements) response = self.interact_with_llm(prompt) output = { "user_stories": response, "metadata": { "phase": "requirements", "version": "1.0", "source_phase": "ideation" } } self.output_manager.save_phase_output("requirements", output) logger.info("Requirements phase completed") class StructuringAgent(BaseAgent): def run(self): logger.info("Starting Structuring Phase") # Load requirements output requirements_data = self.output_manager.load_phase_output("requirements") user_stories = requirements_data.get("data", {}).get("user_stories", "") prompt = PromptTemplate.render("structuring", user_stories=user_stories) response = self.interact_with_llm(prompt) output = { "ddd_model": response, "metadata": { "phase": "structuring", "version": "1.0", "source_phase": "requirements" } } self.output_manager.save_phase_output("structuring", output) logger.info("Structuring phase completed") class DevelopmentPhase1Agent(BaseAgent): def run(self): logger.info("Starting Development Phase") # Load structuring output structuring_data = self.output_manager.load_phase_output("structuring") ddd_schema = structuring_data.get("data", {}).get("ddd_model", "") prompt = PromptTemplate.render("development", ddd_schema=ddd_schema) response = self.interact_with_llm(prompt) output = { "backend_code": response, "metadata": { "phase": "development", "version": "1.0", "source_phase": "structuring" } } self.output_manager.save_phase_output("development", output) logger.info("Development phase completed") class UXDesignAgent(BaseAgent): def run(self): logger.info("Starting UX Design Phase") # Load requirements output for user stories requirements_data = self.output_manager.load_phase_output("requirements") requirements = requirements_data.get("data", {}).get("user_stories", "") prompt = PromptTemplate.render("ux_design", requirements=requirements) response = self.interact_with_llm(prompt) output = { "design": response, "metadata": { "phase": "ux_design", "version": "1.0", "source_phase": "requirements" } } self.output_manager.save_phase_output("ux_design", output) logger.info("UX Design phase completed") class DeploymentAgent(BaseAgent): def run(self): logger.info("Starting Deployment Phase") # Load development and UX design outputs for context development_data = self.output_manager.load_phase_output("development") ux_design_data = self.output_manager.load_phase_output("ux_design") prompt = PromptTemplate.render("deployment") response = self.interact_with_llm(prompt) output = { "config": response, "metadata": { "phase": "deployment", "version": "1.0", "source_phases": ["development", "ux_design"] } } self.output_manager.save_phase_output("deployment", output) logger.info("Deployment phase completed") class ValidationAgent(BaseAgent): def run(self): logger.info("Starting Validation Phase") # Load requirements for user stories and development output requirements_data = self.output_manager.load_phase_output("requirements") development_data = self.output_manager.load_phase_output("development") user_stories = requirements_data.get("data", {}).get("user_stories", "") prompt = PromptTemplate.render("validation", user_stories=user_stories) response = self.interact_with_llm(prompt) output = { "test_plan": response, "metadata": { "phase": "validation", "version": "1.0", "source_phases": ["requirements", "development"] } } self.output_manager.save_phase_output("validation", output) logger.info("Validation phase completed") # Add other agents as necessary... if __name__ == "__main__": try: orchestrator = Orchestrator() final_output = orchestrator.run() print("\n=== Final Consolidated Output ===") print(json.dumps(final_output, indent=4)) except Exception as e: logger.critical(f"Critical error in main execution: {str(e)}") print("A critical error occurred. Please check the logs.")
Here’s a concise rewrite of your program with only **three agents**: an **Idea Generator**, a **Detail Expander**, and a **Summarizer**. The summarizer will maintain a meta ledger for additional context in subsequent calls. This version includes an input prompt to seed the initial idea. ### Concise Version ```python import os import json import logging from datetime import datetime import requests # Configure logging logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(message)s") logger = logging.getLogger(__name__) class OutputManager: def __init__(self, base_dir="outputs"): self.session_dir = os.path.join(base_dir, datetime.now().strftime("%Y%m%d_%H%M%S")) os.makedirs(self.session_dir, exist_ok=True) def save_output(self, phase, data): """Save phase output to JSON.""" filepath = os.path.join(self.session_dir, f"{phase}.json") with open(filepath, "w") as f: json.dump(data, f, indent=4) logger.info(f"Saved output for phase: {phase} to {filepath}") def load_output(self, phase): """Load output from a specific phase.""" filepath = os.path.join(self.session_dir, f"{phase}.json") if os.path.exists(filepath): with open(filepath, "r") as f: return json.load(f) return {} class BaseAgent: def __init__(self, output_manager, model="vanilj/phi-4:latest"): self.output_manager = output_manager self.model = model def interact_with_llm(self, prompt, temperature=0.7): """Interact with the local LLM API.""" try: response = requests.post( "http://localhost:11434/api/generate", json={"model": self.model, "prompt": prompt, "temperature": temperature}, ) response.raise_for_status() return response.json().get("response", "No response received") except requests.RequestException as e: logger.error(f"LLM interaction failed: {e}") return "Error in LLM interaction." class IdeaGenerator(BaseAgent): def run(self, input_prompt): logger.info("Running Idea Generator...") prompt = f"System: Generate creative ideas based on the following prompt:\n{input_prompt}" response = self.interact_with_llm(prompt) output = {"ideas": response, "metadata": {"phase": "idea_generation"}} self.output_manager.save_output("idea_generation", output) class DetailExpander(BaseAgent): def run(self): logger.info("Running Detail Expander...") ideas = self.output_manager.load_output("idea_generation").get("ideas", "") prompt = f"System: Expand on these ideas with actionable details:\n{ideas}" response = self.interact_with_llm(prompt) output = {"expanded_ideas": response, "metadata": {"phase": "detail_expansion"}} self.output_manager.save_output("detail_expansion", output) class Summarizer(BaseAgent): def run(self): logger.info("Running Summarizer...") expanded_ideas = self.output_manager.load_output("detail_expansion").get("expanded_ideas", "") prompt = f"System: Summarize the key points for future context:\n{expanded_ideas}" response = self.interact_with_llm(prompt) output = {"summary": response, "metadata": {"phase": "summary", "timestamp": datetime.now().isoformat()}} self.output_manager.save_output("summary", output) class Orchestrator: def __init__(self): self.output_manager = OutputManager() self.agents = { "idea_generator": IdeaGenerator(self.output_manager), "detail_expander": DetailExpander(self.output_manager), "summarizer": Summarizer(self.output_manager), } def run(self, input_prompt): logger.info("Starting orchestration...") self.agents["idea_generator"].run(input_prompt) self.agents["detail_expander"].run() self.agents["summarizer"].run() logger.info("All phases completed. Outputs saved.") if __name__ == "__main__": try: input_prompt = input("Enter an initial idea or problem statement: ") orchestrator = Orchestrator() orchestrator.run(input_prompt) except Exception as e: logger.error(f"Critical error: {e}") ``` --- ### Key Changes: 1. **Reduced Number of Agents**: Only three agents (Idea Generator, Detail Expander, and Summarizer). 2. **Meta Ledger**: Metadata (e.g., phase name, timestamp) is added with each output. 3. **Input Prompt**: Accepts a user-defined prompt to seed the idea generation. 4. **Simplified Output Structure**: Each phase saves its output as JSON with a metadata field. 5. **Orchestration**: The `Orchestrator` runs the agents sequentially. This structure emphasizes simplicity while preserving functionality and flexibility for future extensions.
gpt-4o