""" Interactive Research Agent Session This example demonstrates real-time learning and interaction with the Research Agent. Users can make requests, provide examples, and see the agent learn and generate code. Author: Atomizer Development Team Version: 0.1.0 (Phase 3) Last Updated: 2025-01-16 """ import sys from pathlib import Path from typing import Optional, Dict, Any # Set UTF-8 encoding for Windows console if sys.platform == 'win32': import codecs # Only wrap if not already wrapped if not isinstance(sys.stdout, codecs.StreamWriter): if hasattr(sys.stdout, 'buffer'): sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer, errors='replace') sys.stderr = codecs.getwriter('utf-8')(sys.stderr.buffer, errors='replace') # Add project root to path project_root = Path(__file__).parent.parent sys.path.insert(0, str(project_root)) from optimization_engine.future.research_agent import ( ResearchAgent, ResearchFindings, KnowledgeGap, CONFIDENCE_LEVELS ) class InteractiveResearchSession: """Interactive session manager for Research Agent conversations.""" def __init__(self, auto_mode: bool = False): self.agent = ResearchAgent() self.conversation_history = [] self.current_gap: Optional[KnowledgeGap] = None self.current_findings: Optional[ResearchFindings] = None self.auto_mode = auto_mode # For automated testing def print_header(self, text: str, char: str = "="): """Print formatted header.""" print(f"\n{char * 80}") print(text) print(f"{char * 80}\n") def print_section(self, text: str): """Print section divider.""" print(f"\n{'-' * 80}") print(text) print(f"{'-' * 80}\n") def display_knowledge_gap(self, gap: KnowledgeGap): """Display detected knowledge gap in user-friendly format.""" print(" Knowledge Gap Analysis:") print(f"\n Missing Features ({len(gap.missing_features)}):") for feature in gap.missing_features: print(f" - {feature}") print(f"\n Missing Knowledge ({len(gap.missing_knowledge)}):") for knowledge in gap.missing_knowledge: print(f" - {knowledge}") print(f"\n Confidence Level: {gap.confidence:.0%}") if gap.confidence < 0.5: print(" Status: New domain - Learning required") elif gap.confidence < 0.8: print(" Status: Partial knowledge - Some research needed") else: print(" Status: Known domain - Can reuse existing knowledge") def display_research_plan(self, plan): """Display research plan in user-friendly format.""" # Handle both ResearchPlan objects and lists steps = plan.steps if hasattr(plan, 'steps') else plan print(" Research Plan Created:") print(f"\n Will gather knowledge in {len(steps)} steps:\n") for i, step in enumerate(steps, 1): action = step['action'].replace('_', ' ').title() confidence = step['expected_confidence'] print(f" Step {i}: {action}") print(f" Expected confidence: {confidence:.0%}") if 'details' in step: if 'prompt' in step['details']: print(f" What I'll ask: \"{step['details']['prompt'][:60]}...\"") elif 'query' in step['details']: print(f" Search query: \"{step['details']['query']}\"") print() def ask_for_example(self, prompt: str, file_types: list) -> Optional[str]: """Ask user for an example file or content.""" print(f" {prompt}\n") print(f" Suggested file types: {', '.join(file_types)}\n") print(" Options:") print(" 1. Enter file path to existing example") print(" 2. Paste example content directly") print(" 3. Skip (type 'skip')\n") user_input = input(" Your choice: ").strip() if user_input.lower() == 'skip': return None # Check if it's a file path file_path = Path(user_input) if file_path.exists() and file_path.is_file(): try: content = file_path.read_text(encoding='utf-8') print(f"\n Loaded {len(content)} characters from {file_path.name}") return content except Exception as e: print(f"\n Error reading file: {e}") return None # Otherwise, treat as direct content if len(user_input) > 10: # Minimum reasonable example size print(f"\n Received {len(user_input)} characters of example content") return user_input print("\n Input too short to be a valid example") return None def execute_research_plan(self, gap: KnowledgeGap) -> ResearchFindings: """Execute research plan interactively.""" plan = self.agent.create_research_plan(gap) self.display_research_plan(plan) # Handle both ResearchPlan objects and lists steps = plan.steps if hasattr(plan, 'steps') else plan sources = {} raw_data = {} confidence_scores = {} for i, step in enumerate(steps, 1): action = step['action'] print(f"\n Executing Step {i}/{len(steps)}: {action.replace('_', ' ').title()}") print(" " + "-" * 76) if action == 'ask_user_for_example': prompt = step['details']['prompt'] file_types = step['details'].get('suggested_file_types', ['.xml', '.py']) example_content = self.ask_for_example(prompt, file_types) if example_content: sources['user_example'] = 'user_provided_example' raw_data['user_example'] = example_content confidence_scores['user_example'] = CONFIDENCE_LEVELS['user_validated'] print(f" Step {i} completed with high confidence ({CONFIDENCE_LEVELS['user_validated']:.0%})") else: print(f" Step {i} skipped by user") elif action == 'search_knowledge_base': query = step['details']['query'] print(f" Searching knowledge base for: \"{query}\"") result = self.agent.search_knowledge_base(query) if result and result['confidence'] > 0.7: sources['knowledge_base'] = result['session_id'] raw_data['knowledge_base'] = result confidence_scores['knowledge_base'] = result['confidence'] print(f" Found existing knowledge! Session: {result['session_id']}") print(f" Confidence: {result['confidence']:.0%}, Relevance: {result['relevance_score']:.0%}") else: print(f" No reliable existing knowledge found") elif action == 'query_nx_mcp': query = step['details']['query'] print(f" Would query NX MCP server: \"{query}\"") print(f" ℹ️ (MCP integration pending - Phase 3)") confidence_scores['nx_mcp'] = 0.0 # Not yet implemented elif action == 'web_search': query = step['details']['query'] print(f" Would search web: \"{query}\"") print(f" ℹ️ (Web search integration pending - Phase 3)") confidence_scores['web_search'] = 0.0 # Not yet implemented elif action == 'search_nxopen_tse': query = step['details']['query'] print(f" Would search NXOpen TSE: \"{query}\"") print(f" ℹ️ (TSE search pending - Phase 3)") confidence_scores['tse_search'] = 0.0 # Not yet implemented return ResearchFindings( sources=sources, raw_data=raw_data, confidence_scores=confidence_scores ) def display_learning_results(self, knowledge): """Display what the agent learned.""" print(" Knowledge Synthesized:") print(f"\n Overall Confidence: {knowledge.confidence:.0%}\n") if knowledge.schema: if 'xml_structure' in knowledge.schema: xml_schema = knowledge.schema['xml_structure'] print(f" Learned XML Structure:") print(f" Root element: <{xml_schema['root_element']}>") if xml_schema.get('attributes'): print(f" Attributes: {xml_schema['attributes']}") print(f" Required fields ({len(xml_schema['required_fields'])}):") for field in xml_schema['required_fields']: print(f" • {field}") if xml_schema.get('optional_fields'): print(f" Optional fields ({len(xml_schema['optional_fields'])}):") for field in xml_schema['optional_fields']: print(f" • {field}") if knowledge.patterns: print(f"\n Patterns Identified: {len(knowledge.patterns)}") if isinstance(knowledge.patterns, dict): for pattern_type, pattern_list in knowledge.patterns.items(): print(f" {pattern_type}: {len(pattern_list)} found") else: print(f" Total patterns: {len(knowledge.patterns)}") def generate_and_save_feature(self, feature_name: str, knowledge) -> Optional[Path]: """Generate feature code and save to file.""" print(f"\n Designing feature: {feature_name}") feature_spec = self.agent.design_feature(knowledge, feature_name) print(f" Category: {feature_spec['category']}") print(f" Lifecycle stage: {feature_spec['lifecycle_stage']}") print(f" Input parameters: {len(feature_spec['interface']['inputs'])}") print(f"\n Generating Python code...") generated_code = self.agent.generate_feature_code(feature_spec, knowledge) print(f" Generated {len(generated_code)} characters ({len(generated_code.split(chr(10)))} lines)") # Validate syntax try: compile(generated_code, '', 'exec') print(f" Code is syntactically valid Python") except SyntaxError as e: print(f" Syntax error: {e}") return None # Save to file output_file = feature_spec['implementation']['file_path'] output_path = project_root / output_file output_path.parent.mkdir(parents=True, exist_ok=True) output_path.write_text(generated_code, encoding='utf-8') print(f"\n Saved to: {output_file}") return output_path def handle_request(self, user_request: str): """Handle a user request through the full research workflow.""" self.print_header(f"Processing Request: {user_request[:60]}...") # Step 1: Identify knowledge gap self.print_section("[Step 1] Analyzing Knowledge Gap") gap = self.agent.identify_knowledge_gap(user_request) self.display_knowledge_gap(gap) self.current_gap = gap # Check if we can skip research if not gap.research_needed: print("\n I already have the knowledge to handle this!") print(" Proceeding directly to generation...\n") # In a full implementation, would generate directly here return # Step 2: Execute research plan self.print_section("[Step 2] Executing Research Plan") findings = self.execute_research_plan(gap) self.current_findings = findings # Step 3: Synthesize knowledge self.print_section("[Step 3] Synthesizing Knowledge") knowledge = self.agent.synthesize_knowledge(findings) self.display_learning_results(knowledge) # Step 4: Generate feature if knowledge.confidence > 0.5: self.print_section("[Step 4] Generating Feature Code") # Extract feature name from request feature_name = user_request.lower().replace(' ', '_')[:30] if not feature_name.isidentifier(): feature_name = "generated_feature" output_file = self.generate_and_save_feature(feature_name, knowledge) if output_file: # Step 5: Document session self.print_section("[Step 5] Documenting Research Session") topic = feature_name session_path = self.agent.document_session( topic=topic, knowledge_gap=gap, findings=findings, knowledge=knowledge, generated_files=[str(output_file)] ) print(f" Session documented: {session_path.name}") print(f" Files created:") for file in session_path.iterdir(): if file.is_file(): print(f" • {file.name}") self.print_header("Request Completed Successfully!", "=") print(f" Generated file: {output_file.relative_to(project_root)}") print(f" Knowledge confidence: {knowledge.confidence:.0%}") print(f" Session saved: {session_path.name}\n") else: print(f"\n ️ Confidence too low ({knowledge.confidence:.0%}) to generate reliable code") print(f" Try providing more examples or information\n") def run(self): """Run interactive session.""" self.print_header("Interactive Research Agent Session", "=") print(" Welcome! I'm your Research Agent. I can learn from examples and") print(" generate code for optimization features.\n") print(" Commands:") print(" • Type your request in natural language") print(" • Type 'demo' for a demonstration") print(" • Type 'quit' to exit\n") while True: try: user_input = input("\nYour request: ").strip() if not user_input: continue if user_input.lower() in ['quit', 'exit', 'q']: print("\n Goodbye! Session ended.\n") break if user_input.lower() == 'demo': self.run_demo() continue # Process the request self.handle_request(user_input) except KeyboardInterrupt: print("\n\n Goodbye! Session ended.\n") break except Exception as e: print(f"\n Error: {e}") import traceback traceback.print_exc() def run_demo(self): """Run a demonstration of the Research Agent capabilities.""" self.print_header("Research Agent Demonstration", "=") print(" This demo will show:") print(" 1. Learning from a user example (material XML)") print(" 2. Generating Python code from learned pattern") print(" 3. Reusing knowledge for a second request\n") if not self.auto_mode: input(" Press Enter to start demo...") # Demo request 1: Learn from steel example demo_request_1 = "Create an NX material XML generator for steel" print(f"\n Demo Request 1: \"{demo_request_1}\"\n") # Provide example automatically for demo example_xml = """ 7850 200 0.29 1.17e-05 295 """ print(" [Auto-providing example for demo]\n") gap1 = self.agent.identify_knowledge_gap(demo_request_1) self.display_knowledge_gap(gap1) findings1 = ResearchFindings( sources={'user_example': 'steel_material.xml'}, raw_data={'user_example': example_xml}, confidence_scores={'user_example': CONFIDENCE_LEVELS['user_validated']} ) knowledge1 = self.agent.synthesize_knowledge(findings1) self.display_learning_results(knowledge1) output_file1 = self.generate_and_save_feature("nx_material_generator_demo", knowledge1) if output_file1: print(f"\n First request completed!") print(f" Generated: {output_file1.name}\n") if not self.auto_mode: input(" Press Enter for second request (knowledge reuse demo)...") # Demo request 2: Reuse learned knowledge demo_request_2 = "Create aluminum 6061-T6 material XML" print(f"\n Demo Request 2: \"{demo_request_2}\"\n") gap2 = self.agent.identify_knowledge_gap(demo_request_2) self.display_knowledge_gap(gap2) if gap2.confidence > 0.7: print("\n Knowledge Reuse Success!") print(" I already learned the material XML structure from your first request.") print(" No need to ask for another example!\n") print("\n Demo completed! Notice how:") print(" • First request: Low confidence, asked for example") print(" • Second request: High confidence, reused learned template") print(" • This is the power of learning and knowledge accumulation!\n") def main(): """Main entry point for interactive research session.""" session = InteractiveResearchSession() session.run() if __name__ == '__main__': main()