| # MVP 2 - Sprint 1: Define Prompt Ontology & Enhance KG for Prompts | |
| **Sprint Created:** 2025-06-08 | |
| **Builds Upon:** MVP 1 (Successfully Completed - 100%) | |
| **Sprint Duration:** 3-4 hours | |
| **Priority:** HIGH (Foundation for all MVP 2 development) | |
| **Development Environment:** Claude 4.0 + Cursor IDE | |
| --- | |
| ## π― Sprint 1 Objectives | |
| ### **Primary Goals** | |
| 1. **Define MCPPrompt Ontology** - Create comprehensive data structure for prompt templates | |
| 2. **Create Rich Prompt Metadata** - Build sample prompt dataset for testing and demonstration | |
| 3. **Extend InMemoryKG for Prompts** - Add structured prompt storage and retrieval | |
| 4. **Implement Prompt Vector Indexing** - Enable semantic search across prompt templates | |
| 5. **Update Application Initialization** - Integrate prompt loading into startup process | |
| ### **Success Criteria** | |
| - [x] MCPPrompt dataclass defined with comprehensive fields | |
| - [x] 4+ diverse prompt templates created in JSON format | |
| - [x] InMemoryKG enhanced for dual tool+prompt management | |
| - [x] Vector indexing supports both tools and prompts seamlessly | |
| - [x] Application startup includes prompt loading and indexing | |
| - [x] All new functionality covered by unit tests (20+ new tests) | |
| - [x] No regression in existing MVP 1 functionality | |
| - [x] All quality checks passing (lint, format, type-check, test) | |
| --- | |
| ## π Task Breakdown | |
| ### **Task 1: Define MCPPrompt Ontology & Associated Tests** | |
| **Estimated Time:** 60-75 minutes | |
| **Priority:** HIGH | |
| **Dependencies:** None | |
| #### **Sub-Task 1.1: Create MCPPrompt Dataclass** | |
| - **Status:** Todo | |
| - **Estimated Time:** 30-45 minutes | |
| - **Description:** Define comprehensive MCPPrompt dataclass with all required fields | |
| - **Acceptance Criteria:** | |
| 1. MCPPrompt dataclass with proper type hints and defaults | |
| 2. JSON serialization compatibility | |
| 3. Validation for required fields | |
| 4. Integration with existing ontology module | |
| **Claude/Cursor Prompt:** | |
| ```cursor | |
| **TASK: Define MCPPrompt Dataclass and Initial Tests** | |
| **Objective:** Create the foundational MCPPrompt dataclass and comprehensive unit tests. | |
| **Action 1: Modify `kg_services/ontology.py`** | |
| 1. Open `@kg_services/ontology.py` | |
| 2. Add necessary imports if not present: | |
| ```python | |
| from dataclasses import dataclass, field | |
| from typing import List, Dict, Optional | |
| ``` | |
| 3. Below the existing `MCPTool` dataclass, add a new `MCPPrompt` dataclass with these fields: | |
| ```python | |
| @dataclass | |
| class MCPPrompt: | |
| """Represents a prompt template for MCP tool usage.""" | |
| prompt_id: str | |
| name: str | |
| description: str | |
| target_tool_id: str # Links to MCPTool.tool_id | |
| template_string: str # Template with {{variable}} placeholders | |
| tags: List[str] = field(default_factory=list) | |
| input_variables: List[str] = field(default_factory=list) | |
| use_case: str = "" # Specific use case description | |
| difficulty_level: str = "beginner" # beginner, intermediate, advanced | |
| example_inputs: Dict[str, str] = field(default_factory=dict) # Example values | |
| def __post_init__(self): | |
| """Validate prompt data after initialization.""" | |
| if not self.prompt_id: | |
| raise ValueError("prompt_id cannot be empty") | |
| if not self.name: | |
| raise ValueError("name cannot be empty") | |
| if not self.target_tool_id: | |
| raise ValueError("target_tool_id cannot be empty") | |
| if not self.template_string: | |
| raise ValueError("template_string cannot be empty") | |
| ``` | |
| **Action 2: Create/Update `tests/kg_services/test_ontology.py`** | |
| 1. Open or create `@tests/kg_services/test_ontology.py` | |
| 2. Add comprehensive test methods: | |
| ```python | |
| def test_mcp_prompt_creation(): | |
| """Test MCPPrompt basic creation with all fields.""" | |
| prompt = MCPPrompt( | |
| prompt_id="test_prompt_v1", | |
| name="Test Prompt", | |
| description="A test prompt for validation", | |
| target_tool_id="test_tool_v1", | |
| template_string="Process this: {{input_text}}", | |
| tags=["test", "validation"], | |
| input_variables=["input_text"], | |
| use_case="Testing purposes", | |
| difficulty_level="beginner", | |
| example_inputs={"input_text": "sample text"} | |
| ) | |
| assert prompt.prompt_id == "test_prompt_v1" | |
| assert prompt.name == "Test Prompt" | |
| assert prompt.description == "A test prompt for validation" | |
| assert prompt.target_tool_id == "test_tool_v1" | |
| assert prompt.template_string == "Process this: {{input_text}}" | |
| assert prompt.tags == ["test", "validation"] | |
| assert prompt.input_variables == ["input_text"] | |
| assert prompt.use_case == "Testing purposes" | |
| assert prompt.difficulty_level == "beginner" | |
| assert prompt.example_inputs == {"input_text": "sample text"} | |
| def test_mcp_prompt_defaults(): | |
| """Test MCPPrompt creation with minimal required fields.""" | |
| prompt = MCPPrompt( | |
| prompt_id="minimal_prompt", | |
| name="Minimal Prompt", | |
| description="A minimal prompt", | |
| target_tool_id="tool_id", | |
| template_string="{{input}}" | |
| ) | |
| assert prompt.tags == [] | |
| assert prompt.input_variables == [] | |
| assert prompt.use_case == "" | |
| assert prompt.difficulty_level == "beginner" | |
| assert prompt.example_inputs == {} | |
| def test_mcp_prompt_validation(): | |
| """Test MCPPrompt validation in __post_init__.""" | |
| import pytest | |
| # Test empty prompt_id | |
| with pytest.raises(ValueError, match="prompt_id cannot be empty"): | |
| MCPPrompt(prompt_id="", name="Test", description="Test", | |
| target_tool_id="tool", template_string="{{input}}") | |
| # Test empty name | |
| with pytest.raises(ValueError, match="name cannot be empty"): | |
| MCPPrompt(prompt_id="test", name="", description="Test", | |
| target_tool_id="tool", template_string="{{input}}") | |
| # Test empty target_tool_id | |
| with pytest.raises(ValueError, match="target_tool_id cannot be empty"): | |
| MCPPrompt(prompt_id="test", name="Test", description="Test", | |
| target_tool_id="", template_string="{{input}}") | |
| # Test empty template_string | |
| with pytest.raises(ValueError, match="template_string cannot be empty"): | |
| MCPPrompt(prompt_id="test", name="Test", description="Test", | |
| target_tool_id="tool", template_string="") | |
| ``` | |
| Apply coding standards from `@.cursor/rules/python_gradio_basic.mdc`. | |
| Generate the complete code for both files. | |
| ``` | |
| #### **Sub-Task 1.2: Create Rich Initial Prompt Metadata** | |
| - **Status:** Todo | |
| - **Estimated Time:** 45-60 minutes | |
| - **Dependencies:** Sub-Task 1.1 | |
| - **Description:** Create comprehensive prompt dataset with diverse, high-quality templates | |
| - **Acceptance Criteria:** | |
| 1. 6+ diverse prompt templates covering all MVP 1 tools | |
| 2. Multiple prompt styles per tool (concise, detailed, specialized) | |
| 3. Rich descriptions optimized for semantic embedding | |
| 4. Valid JSON structure matching MCPPrompt schema | |
| **Claude/Cursor Prompt:** | |
| ```cursor | |
| **TASK: Create Rich Initial Prompt Metadata** | |
| **Objective:** Create a comprehensive `data/initial_prompts.json` file with diverse, high-quality prompt templates. | |
| **Action: Create `data/initial_prompts.json`** | |
| 1. Create the file `@data/initial_prompts.json` | |
| 2. Structure as a JSON array containing 6 MCPPrompt objects | |
| 3. Ensure coverage of all tools from MVP 1: | |
| - sentiment_analyzer_v1 | |
| - summarizer_v1 | |
| - image_caption_generator_stub_v1 | |
| - code_quality_linter_v1 | |
| 4. Create multiple prompt styles for variety: | |
| ```json | |
| [ | |
| { | |
| "prompt_id": "sentiment_customer_feedback_v1", | |
| "name": "Customer Feedback Sentiment Analysis", | |
| "description": "Analyzes customer feedback for business insights, focusing on actionable sentiment patterns, emotional indicators, and customer satisfaction levels. Optimized for business decision-making.", | |
| "target_tool_id": "sentiment_analyzer_v1", | |
| "template_string": "Analyze the sentiment of this customer feedback and provide actionable business insights:\n\nCustomer Feedback: {{customer_feedback}}\n\nPlease provide:\n1. Overall sentiment (positive/negative/neutral) with confidence score\n2. Key emotional indicators and specific language patterns\n3. Actionable business insights and recommendations\n4. Areas for improvement based on the feedback", | |
| "tags": ["sentiment", "customer", "business", "feedback", "analysis", "actionable"], | |
| "input_variables": ["customer_feedback"], | |
| "use_case": "Business customer feedback analysis for actionable insights", | |
| "difficulty_level": "intermediate", | |
| "example_inputs": { | |
| "customer_feedback": "The product arrived late and the packaging was damaged, but the customer service team was very helpful in resolving the issue quickly. Overall satisfied but shipping needs improvement." | |
| } | |
| }, | |
| { | |
| "prompt_id": "sentiment_social_media_v1", | |
| "name": "Social Media Sentiment Monitor", | |
| "description": "Quick sentiment analysis for social media posts, comments, and reviews. Focuses on immediate emotional tone detection and viral content assessment.", | |
| "target_tool_id": "sentiment_analyzer_v1", | |
| "template_string": "Analyze the sentiment of this social media content: {{social_content}}\n\nProvide: sentiment (positive/negative/neutral), intensity (low/medium/high), and key emotional words.", | |
| "tags": ["sentiment", "social", "media", "quick", "viral", "emotions"], | |
| "input_variables": ["social_content"], | |
| "use_case": "Real-time social media monitoring and content moderation", | |
| "difficulty_level": "beginner", | |
| "example_inputs": { | |
| "social_content": "Just tried the new coffee shop downtown - amazing latte art and perfect temperature! βοΈβ¨ #coffeelover" | |
| } | |
| }, | |
| { | |
| "prompt_id": "summarizer_executive_v1", | |
| "name": "Executive Summary Generator", | |
| "description": "Creates concise executive summaries for business documents, reports, and lengthy content. Focuses on key decisions, financial impacts, and strategic recommendations.", | |
| "target_tool_id": "summarizer_v1", | |
| "template_string": "Create an executive summary of the following document:\n\n{{document_content}}\n\nExecutive Summary should include:\n- Key findings and conclusions\n- Critical decisions or recommendations\n- Financial or strategic impacts\n- Next steps or action items\n\nLimit to 3-4 bullet points maximum.", | |
| "tags": ["summary", "executive", "business", "decisions", "strategic", "concise"], | |
| "input_variables": ["document_content"], | |
| "use_case": "Executive briefings and board presentations", | |
| "difficulty_level": "advanced", | |
| "example_inputs": { | |
| "document_content": "Q3 Financial Report: Revenue increased 15% year-over-year to $2.3M, primarily driven by new product launches..." | |
| } | |
| }, | |
| { | |
| "prompt_id": "summarizer_academic_v1", | |
| "name": "Academic Research Summarizer", | |
| "description": "Summarizes academic papers, research articles, and scholarly content with focus on methodology, findings, and implications for further research.", | |
| "target_tool_id": "summarizer_v1", | |
| "template_string": "Summarize this academic content with focus on research methodology and findings:\n\n{{research_content}}\n\nSummary should cover:\n1. Research question and methodology\n2. Key findings and data insights\n3. Implications and future research directions\n4. Limitations and considerations", | |
| "tags": ["summary", "academic", "research", "methodology", "findings", "scholarly"], | |
| "input_variables": ["research_content"], | |
| "use_case": "Academic literature review and research synthesis", | |
| "difficulty_level": "advanced", | |
| "example_inputs": { | |
| "research_content": "This study examined the impact of machine learning algorithms on natural language processing tasks using a dataset of 50,000 text samples..." | |
| } | |
| }, | |
| { | |
| "prompt_id": "image_caption_detailed_v1", | |
| "name": "Detailed Image Caption Generator", | |
| "description": "Generates comprehensive, descriptive captions for images with focus on visual elements, composition, context, and accessibility. Suitable for detailed documentation and accessibility purposes.", | |
| "target_tool_id": "image_caption_generator_stub_v1", | |
| "template_string": "Generate a detailed, descriptive caption for this image:\n\nImage: {{image_reference}}\n\nInclude:\n- Main subjects and objects in the scene\n- Setting, lighting, and composition details\n- Colors, textures, and visual style\n- Any text or signage visible\n- Overall mood or atmosphere\n\nMake it accessible and informative for visually impaired users.", | |
| "tags": ["image", "caption", "detailed", "accessibility", "descriptive", "visual", "documentation"], | |
| "input_variables": ["image_reference"], | |
| "use_case": "Accessibility compliance and detailed image documentation", | |
| "difficulty_level": "intermediate", | |
| "example_inputs": { | |
| "image_reference": "A photograph of a busy coffee shop interior with customers at wooden tables" | |
| } | |
| }, | |
| { | |
| "prompt_id": "code_review_security_v1", | |
| "name": "Security-Focused Code Review", | |
| "description": "Performs comprehensive code quality analysis with emphasis on security vulnerabilities, best practices, and maintainability. Provides actionable recommendations for improvement.", | |
| "target_tool_id": "code_quality_linter_v1", | |
| "template_string": "Review this code for quality and security issues:\n\n```{{programming_language}}\n{{code_content}}\n```\n\nProvide analysis for:\n1. Security vulnerabilities and potential exploits\n2. Code quality and maintainability issues\n3. Performance optimization opportunities\n4. Best practice violations\n5. Specific recommendations for improvement\n\nPrioritize security concerns and provide actionable fixes.", | |
| "tags": ["code", "review", "security", "quality", "vulnerability", "best-practices", "maintainability"], | |
| "input_variables": ["programming_language", "code_content"], | |
| "use_case": "Security audits and code quality assurance for production systems", | |
| "difficulty_level": "advanced", | |
| "example_inputs": { | |
| "programming_language": "python", | |
| "code_content": "def authenticate_user(username, password):\n if username == 'admin' and password == 'password123':\n return True\n return False" | |
| } | |
| } | |
| ] | |
| ``` | |
| Ensure: | |
| - All prompt_ids are unique | |
| - All target_tool_ids match existing tools from MVP 1 | |
| - Descriptions are rich and suitable for semantic embedding | |
| - Templates use clear {{variable}} syntax | |
| - Example inputs are realistic and helpful | |
| - Difficulty levels are appropriately assigned | |
| ``` | |
| --- | |
| ### **Task 2: Extend InMemoryKG for Prompts (Structured & Vector Parts)** | |
| **Estimated Time:** 90-120 minutes | |
| **Priority:** HIGH | |
| **Dependencies:** Task 1 completion | |
| #### **Sub-Task 2.1: Add Prompt Storage and Retrieval (Structured)** | |
| - **Status:** Todo | |
| - **Estimated Time:** 45-60 minutes | |
| - **Dependencies:** Sub-Task 1.2 | |
| - **Description:** Extend InMemoryKG to handle MCPPrompt objects for structured storage and retrieval | |
| - **Acceptance Criteria:** | |
| 1. Prompt loading from JSON with error handling | |
| 2. Prompt retrieval by ID and by tool ID | |
| 3. Integration with existing KG structure | |
| 4. Comprehensive unit test coverage | |
| **Claude/Cursor Prompt:** | |
| ```cursor | |
| **TASK: Extend InMemoryKG for Structured Prompt Storage and Retrieval** | |
| **Objective:** Modify `InMemoryKG` to handle loading, storing, and retrieving `MCPPrompt` objects alongside existing tool functionality. | |
| **Action 1: Modify `kg_services/knowledge_graph.py`** | |
| 1. Open `@kg_services/knowledge_graph.py` | |
| 2. Add import for MCPPrompt: | |
| ```python | |
| from .ontology import MCPTool, MCPPrompt | |
| ``` | |
| 3. In `InMemoryKG.__init__` method, add: | |
| ```python | |
| self.prompts: Dict[str, MCPPrompt] = {} | |
| ``` | |
| 4. Add new method `load_prompts_from_json`: | |
| ```python | |
| def load_prompts_from_json(self, filepath: str) -> None: | |
| """Load MCPPrompt objects from JSON file.""" | |
| try: | |
| with open(filepath, 'r', encoding='utf-8') as f: | |
| prompts_data = json.load(f) | |
| self.prompts.clear() # Clear existing prompts | |
| for prompt_data in prompts_data: | |
| prompt = MCPPrompt(**prompt_data) | |
| self.prompts[prompt.prompt_id] = prompt | |
| print(f"Loaded {len(self.prompts)} prompts into structured KG.") | |
| except FileNotFoundError: | |
| print(f"Warning: Prompt file '{filepath}' not found. No prompts loaded.") | |
| except json.JSONDecodeError as e: | |
| print(f"Warning: Invalid JSON in prompt file '{filepath}': {e}. No prompts loaded.") | |
| except Exception as e: | |
| print(f"Warning: Error loading prompts from '{filepath}': {e}. No prompts loaded.") | |
| ``` | |
| 5. Add new method `get_prompt_by_id`: | |
| ```python | |
| def get_prompt_by_id(self, prompt_id: str) -> Optional[MCPPrompt]: | |
| """Retrieve prompt by ID.""" | |
| return self.prompts.get(prompt_id) | |
| ``` | |
| 6. Add new method `get_prompts_for_tool`: | |
| ```python | |
| def get_prompts_for_tool(self, tool_id: str) -> List[MCPPrompt]: | |
| """Get all prompts targeting a specific tool.""" | |
| return [prompt for prompt in self.prompts.values() | |
| if prompt.target_tool_id == tool_id] | |
| ``` | |
| **Action 2: Update `tests/kg_services/test_knowledge_graph.py`** | |
| 1. Open `@tests/kg_services/test_knowledge_graph.py` | |
| 2. Add import for MCPPrompt: | |
| ```python | |
| from kg_services.ontology import MCPTool, MCPPrompt | |
| ``` | |
| 3. Add test methods: | |
| ```python | |
| def test_kg_initialization_includes_prompts(): | |
| """Test that InMemoryKG initializes with empty prompts dictionary.""" | |
| kg = InMemoryKG() | |
| assert isinstance(kg.prompts, dict) | |
| assert len(kg.prompts) == 0 | |
| def test_load_prompts_from_json_success(tmp_path): | |
| """Test successful loading of prompts from JSON.""" | |
| kg = InMemoryKG() | |
| # Create test prompt data | |
| test_prompts = [ | |
| { | |
| "prompt_id": "test_prompt_1", | |
| "name": "Test Prompt 1", | |
| "description": "First test prompt", | |
| "target_tool_id": "test_tool_1", | |
| "template_string": "Process: {{input}}", | |
| "tags": ["test"], | |
| "input_variables": ["input"] | |
| }, | |
| { | |
| "prompt_id": "test_prompt_2", | |
| "name": "Test Prompt 2", | |
| "description": "Second test prompt", | |
| "target_tool_id": "test_tool_2", | |
| "template_string": "Analyze: {{data}}", | |
| "tags": ["test", "analyze"], | |
| "input_variables": ["data"] | |
| } | |
| ] | |
| # Write test data to temporary file | |
| test_file = tmp_path / "test_prompts.json" | |
| test_file.write_text(json.dumps(test_prompts)) | |
| # Load prompts | |
| kg.load_prompts_from_json(str(test_file)) | |
| # Verify loading | |
| assert len(kg.prompts) == 2 | |
| assert "test_prompt_1" in kg.prompts | |
| assert "test_prompt_2" in kg.prompts | |
| prompt1 = kg.prompts["test_prompt_1"] | |
| assert prompt1.name == "Test Prompt 1" | |
| assert prompt1.target_tool_id == "test_tool_1" | |
| assert prompt1.template_string == "Process: {{input}}" | |
| def test_get_prompt_by_id(): | |
| """Test prompt retrieval by ID.""" | |
| kg = InMemoryKG() | |
| # Add test prompt directly | |
| test_prompt = MCPPrompt( | |
| prompt_id="test_id", | |
| name="Test Prompt", | |
| description="Test description", | |
| target_tool_id="tool_1", | |
| template_string="{{input}}" | |
| ) | |
| kg.prompts["test_id"] = test_prompt | |
| # Test existing ID | |
| retrieved = kg.get_prompt_by_id("test_id") | |
| assert retrieved is not None | |
| assert retrieved.name == "Test Prompt" | |
| # Test non-existent ID | |
| assert kg.get_prompt_by_id("non_existent") is None | |
| def test_get_prompts_for_tool(): | |
| """Test retrieving prompts by tool ID.""" | |
| kg = InMemoryKG() | |
| # Add test prompts for different tools | |
| prompt1 = MCPPrompt("p1", "Prompt 1", "Desc 1", "tool_a", "{{input}}") | |
| prompt2 = MCPPrompt("p2", "Prompt 2", "Desc 2", "tool_a", "{{data}}") | |
| prompt3 = MCPPrompt("p3", "Prompt 3", "Desc 3", "tool_b", "{{text}}") | |
| kg.prompts["p1"] = prompt1 | |
| kg.prompts["p2"] = prompt2 | |
| kg.prompts["p3"] = prompt3 | |
| # Test tool with multiple prompts | |
| tool_a_prompts = kg.get_prompts_for_tool("tool_a") | |
| assert len(tool_a_prompts) == 2 | |
| assert all(p.target_tool_id == "tool_a" for p in tool_a_prompts) | |
| # Test tool with single prompt | |
| tool_b_prompts = kg.get_prompts_for_tool("tool_b") | |
| assert len(tool_b_prompts) == 1 | |
| assert tool_b_prompts[0].prompt_id == "p3" | |
| # Test tool with no prompts | |
| assert kg.get_prompts_for_tool("tool_c") == [] | |
| def test_load_prompts_handles_file_not_found(capsys): | |
| """Test handling of missing prompt file.""" | |
| kg = InMemoryKG() | |
| kg.load_prompts_from_json("non_existent_file.json") | |
| assert len(kg.prompts) == 0 | |
| captured = capsys.readouterr() | |
| assert "Warning: Prompt file 'non_existent_file.json' not found" in captured.out | |
| def test_load_prompts_handles_invalid_json(tmp_path, capsys): | |
| """Test handling of invalid JSON in prompt file.""" | |
| kg = InMemoryKG() | |
| # Create file with invalid JSON | |
| test_file = tmp_path / "invalid.json" | |
| test_file.write_text("{ invalid json content") | |
| kg.load_prompts_from_json(str(test_file)) | |
| assert len(kg.prompts) == 0 | |
| captured = capsys.readouterr() | |
| assert "Warning: Invalid JSON" in captured.out | |
| ``` | |
| Apply coding standards from `@.cursor/rules/python_gradio_basic.mdc`. | |
| Generate the complete modifications and test methods. | |
| ``` | |
| #### **Sub-Task 2.2: Extend Vector Indexing for Prompts** | |
| - **Status:** Todo | |
| - **Estimated Time:** 60-75 minutes | |
| - **Dependencies:** Sub-Task 2.1 | |
| - **Description:** Add prompt embedding generation and semantic search capabilities | |
| - **Acceptance Criteria:** | |
| 1. Prompt embeddings generated and stored alongside tool embeddings | |
| 2. Semantic search functionality for prompts | |
| 3. Integration with existing vector search infrastructure | |
| 4. Performance optimization for dual indexing | |
| **Claude/Cursor Prompt:** | |
| ```cursor | |
| **TASK: Extend InMemoryKG for Prompt Embedding Indexing and Search** | |
| **Objective:** Enhance `InMemoryKG` to generate embeddings for prompts and enable semantic search across prompt templates. | |
| **Action 1: Modify `kg_services/knowledge_graph.py` (InMemoryKG class)** | |
| 1. Open `@kg_services/knowledge_graph.py` | |
| 2. In `InMemoryKG.__init__`, add new attributes: | |
| ```python | |
| # Existing tool embedding attributes remain... | |
| # Add prompt embedding attributes | |
| self.prompt_embeddings: List[List[float]] = [] | |
| self.prompt_ids_for_vectors: List[str] = [] | |
| ``` | |
| 3. Modify `build_vector_index` method to include prompt processing: | |
| ```python | |
| def build_vector_index(self, embedder: EmbeddingService) -> None: | |
| """Build vector index for both tools and prompts.""" | |
| # Clear existing embeddings | |
| self.tool_embeddings.clear() | |
| self.tool_ids_for_vectors.clear() | |
| self.prompt_embeddings.clear() | |
| self.prompt_ids_for_vectors.clear() | |
| # Index tools (existing logic) | |
| print(f"Indexing {len(self.tools)} tools...") | |
| for tool_id, tool in self.tools.items(): | |
| text_to_embed = f"{tool.name} - {tool.description} Tags: {', '.join(tool.tags)}" | |
| embedding = embedder.get_embedding(text_to_embed) | |
| if embedding is not None: | |
| self.tool_embeddings.append(embedding) | |
| self.tool_ids_for_vectors.append(tool_id) | |
| else: | |
| print(f"Warning: Could not generate embedding for tool {tool.name}") | |
| # Index prompts (new logic) | |
| print(f"Indexing {len(self.prompts)} prompts...") | |
| for prompt_id, prompt in self.prompts.items(): | |
| # Create rich text for embedding | |
| text_to_embed = self._create_prompt_embedding_text(prompt) | |
| embedding = embedder.get_embedding(text_to_embed) | |
| if embedding is not None: | |
| self.prompt_embeddings.append(embedding) | |
| self.prompt_ids_for_vectors.append(prompt_id) | |
| else: | |
| print(f"Warning: Could not generate embedding for prompt {prompt.name}") | |
| print(f"Vector index built: {len(self.tool_embeddings)} tools, {len(self.prompt_embeddings)} prompts indexed.") | |
| ``` | |
| 4. Add helper method for prompt embedding text: | |
| ```python | |
| def _create_prompt_embedding_text(self, prompt: MCPPrompt) -> str: | |
| """Create descriptive text for prompt embedding.""" | |
| parts = [ | |
| prompt.name, | |
| prompt.description, | |
| f"Use case: {prompt.use_case}" if prompt.use_case else "", | |
| f"Tags: {', '.join(prompt.tags)}" if prompt.tags else "", | |
| f"Difficulty: {prompt.difficulty_level}", | |
| f"Variables: {', '.join(prompt.input_variables)}" if prompt.input_variables else "" | |
| ] | |
| return " - ".join(part for part in parts if part) | |
| ``` | |
| 5. Add `find_similar_prompts` method: | |
| ```python | |
| def find_similar_prompts(self, query_embedding: List[float], top_k: int = 3) -> List[str]: | |
| """Find prompts similar to query using cosine similarity.""" | |
| if not self.prompt_embeddings or not query_embedding: | |
| return [] | |
| similarities = [] | |
| for i, prompt_embedding in enumerate(self.prompt_embeddings): | |
| similarity = self._cosine_similarity(query_embedding, prompt_embedding) | |
| similarities.append((similarity, self.prompt_ids_for_vectors[i])) | |
| # Sort by similarity (descending) and return top_k prompt IDs | |
| similarities.sort(key=lambda x: x[0], reverse=True) | |
| return [prompt_id for _, prompt_id in similarities[:top_k]] | |
| ``` | |
| **Action 2: Update `tests/kg_services/test_knowledge_graph.py`** | |
| 1. Open `@tests/kg_services/test_knowledge_graph.py` | |
| 2. Update existing `build_vector_index` tests to include prompt verification | |
| 3. Add new prompt-specific tests: | |
| ```python | |
| def test_build_vector_index_includes_prompts(): | |
| """Test that build_vector_index processes both tools and prompts.""" | |
| kg = InMemoryKG() | |
| mock_embedder = MockEmbeddingService() | |
| # Add test tool | |
| test_tool = MCPTool("tool1", "Test Tool", "A test tool", ["test"]) | |
| kg.tools["tool1"] = test_tool | |
| # Add test prompt | |
| test_prompt = MCPPrompt( | |
| prompt_id="prompt1", | |
| name="Test Prompt", | |
| description="A test prompt", | |
| target_tool_id="tool1", | |
| template_string="{{input}}", | |
| tags=["test"], | |
| use_case="testing" | |
| ) | |
| kg.prompts["prompt1"] = test_prompt | |
| # Configure mock to return different embeddings | |
| mock_embedder.set_embedding_for_text( | |
| "Test Tool - A test tool Tags: test", | |
| [0.1, 0.2, 0.3] | |
| ) | |
| mock_embedder.set_embedding_for_text( | |
| "Test Prompt - A test prompt - Use case: testing - Tags: test - Difficulty: beginner", | |
| [0.4, 0.5, 0.6] | |
| ) | |
| kg.build_vector_index(mock_embedder) | |
| # Verify both tools and prompts are indexed | |
| assert len(kg.tool_embeddings) == 1 | |
| assert len(kg.prompt_embeddings) == 1 | |
| assert kg.tool_ids_for_vectors == ["tool1"] | |
| assert kg.prompt_ids_for_vectors == ["prompt1"] | |
| def test_create_prompt_embedding_text(): | |
| """Test prompt embedding text creation.""" | |
| kg = InMemoryKG() | |
| prompt = MCPPrompt( | |
| prompt_id="test", | |
| name="Test Prompt", | |
| description="A comprehensive test prompt", | |
| target_tool_id="tool1", | |
| template_string="{{input}}", | |
| tags=["test", "example"], | |
| input_variables=["input"], | |
| use_case="testing purposes", | |
| difficulty_level="intermediate" | |
| ) | |
| text = kg._create_prompt_embedding_text(prompt) | |
| expected = "Test Prompt - A comprehensive test prompt - Use case: testing purposes - Tags: test, example - Difficulty: intermediate - Variables: input" | |
| assert text == expected | |
| def test_find_similar_prompts_empty_index(): | |
| """Test find_similar_prompts with empty index.""" | |
| kg = InMemoryKG() | |
| result = kg.find_similar_prompts([0.1, 0.2, 0.3]) | |
| assert result == [] | |
| def test_find_similar_prompts_logic(): | |
| """Test find_similar_prompts similarity ranking.""" | |
| kg = InMemoryKG() | |
| # Manually set up prompt embeddings and IDs | |
| kg.prompt_embeddings = [ | |
| [1.0, 0.0, 0.0], # prompt_a | |
| [0.0, 1.0, 0.0], # prompt_b | |
| [0.0, 0.0, 1.0], # prompt_c | |
| ] | |
| kg.prompt_ids_for_vectors = ["prompt_a", "prompt_b", "prompt_c"] | |
| # Query most similar to prompt_a | |
| query_embedding = [0.9, 0.1, 0.0] | |
| results = kg.find_similar_prompts(query_embedding, top_k=2) | |
| # Should return prompt_a first, then prompt_b | |
| assert len(results) == 2 | |
| assert results[0] == "prompt_a" | |
| assert results[1] == "prompt_b" | |
| def test_find_similar_prompts_respects_top_k(): | |
| """Test that find_similar_prompts respects top_k parameter.""" | |
| kg = InMemoryKG() | |
| # Set up 3 prompt embeddings | |
| kg.prompt_embeddings = [[1, 0], [0, 1], [0.5, 0.5]] | |
| kg.prompt_ids_for_vectors = ["p1", "p2", "p3"] | |
| # Test different top_k values | |
| results_1 = kg.find_similar_prompts([1, 0], top_k=1) | |
| assert len(results_1) == 1 | |
| results_2 = kg.find_similar_prompts([1, 0], top_k=2) | |
| assert len(results_2) == 2 | |
| results_all = kg.find_similar_prompts([1, 0], top_k=10) | |
| assert len(results_all) == 3 # Can't return more than available | |
| ``` | |
| Apply coding standards from `@.cursor/rules/python_gradio_basic.mdc`. | |
| Generate all code modifications and comprehensive test methods. | |
| ``` | |
| --- | |
| ### **Task 3: Update Application Initialization** | |
| **Estimated Time:** 20-30 minutes | |
| **Priority:** MEDIUM | |
| **Dependencies:** Task 2 completion | |
| #### **Sub-Task 3.1: Integrate Prompt Loading in app.py** | |
| - **Status:** Todo | |
| - **Estimated Time:** 20-30 minutes | |
| - **Dependencies:** Sub-Task 2.2 | |
| - **Description:** Update application startup to load prompts and include them in vector indexing | |
| - **Acceptance Criteria:** | |
| 1. Prompts loaded during application startup | |
| 2. Vector index includes both tools and prompts | |
| 3. Proper error handling and logging | |
| 4. No breaking changes to existing functionality | |
| **Claude/Cursor Prompt:** | |
| ```cursor | |
| **TASK: Update app.py Initialization to Include Prompt Loading** | |
| **Objective:** Modify the global service initialization in `app.py` to load prompts and include them in the vector indexing process. | |
| **Action: Modify `app.py`** | |
| 1. Open `@app.py` | |
| 2. Locate the global service initialization section (around line 20-50) | |
| 3. After the line that loads tools, add prompt loading: | |
| ```python | |
| # Existing tool loading | |
| print("Loading tools from data/initial_tools.json...") | |
| knowledge_graph_instance.load_tools_from_json("data/initial_tools.json") | |
| print(f"β Loaded {len(knowledge_graph_instance.tools)} tools.") | |
| # Add prompt loading | |
| print("Loading prompts from data/initial_prompts.json...") | |
| knowledge_graph_instance.load_prompts_from_json("data/initial_prompts.json") | |
| print(f"β Loaded {len(knowledge_graph_instance.prompts)} prompts.") | |
| ``` | |
| 4. Update the vector index building message: | |
| ```python | |
| # Update existing message | |
| print("Building vector index for tools and prompts (may take a moment for first run)...") | |
| knowledge_graph_instance.build_vector_index(embedding_service_instance) | |
| print(f"β Vector index built successfully: {len(knowledge_graph_instance.tool_embeddings)} tools, {len(knowledge_graph_instance.prompt_embeddings)} prompts indexed.") | |
| ``` | |
| 5. Ensure the initialization block has proper error handling that covers prompt loading: | |
| ```python | |
| try: | |
| # ... existing initialization code ... | |
| # Tool loading | |
| print("Loading tools from data/initial_tools.json...") | |
| knowledge_graph_instance.load_tools_from_json("data/initial_tools.json") | |
| print(f"β Loaded {len(knowledge_graph_instance.tools)} tools.") | |
| # Prompt loading | |
| print("Loading prompts from data/initial_prompts.json...") | |
| knowledge_graph_instance.load_prompts_from_json("data/initial_prompts.json") | |
| print(f"β Loaded {len(knowledge_graph_instance.prompts)} prompts.") | |
| # Vector indexing | |
| print("Building vector index for tools and prompts (may take a moment for first run)...") | |
| knowledge_graph_instance.build_vector_index(embedding_service_instance) | |
| print(f"β Vector index built successfully: {len(knowledge_graph_instance.tool_embeddings)} tools, {len(knowledge_graph_instance.prompt_embeddings)} prompts indexed.") | |
| # ... rest of initialization ... | |
| except FileNotFoundError as e: | |
| print(f"β FATAL: Data file not found: {e}") | |
| print("Please ensure both data/initial_tools.json and data/initial_prompts.json exist.") | |
| except Exception as e: | |
| print(f"β FATAL: Error during service initialization: {e}") | |
| print("The application may not function correctly.") | |
| ``` | |
| **Verification Requirements:** | |
| - No changes to existing tool loading logic | |
| - Prompt loading integrated seamlessly | |
| - Enhanced logging for better debugging | |
| - Proper error messages that mention both files | |
| - No regression in MVP 1 functionality | |
| Generate the modified initialization section with proper error handling and logging. | |
| ``` | |
| --- | |
| ### **Task 4: Sprint Wrap-up & Final Checks** | |
| **Estimated Time:** 30-45 minutes | |
| **Priority:** HIGH | |
| **Dependencies:** Task 3 completion | |
| #### **Sub-Task 4.1: Dependencies and Environment Update** | |
| - **Status:** Todo | |
| - **Estimated Time:** 10-15 minutes | |
| - **Description:** Update dependency files and regenerate lock file | |
| - **Acceptance Criteria:** | |
| 1. requirements.lock updated and synchronized | |
| 2. No new runtime dependencies (this sprint adds no external libs) | |
| 3. Development environment properly configured | |
| #### **Sub-Task 4.2: Comprehensive Quality Checks** | |
| - **Status:** Todo | |
| - **Estimated Time:** 15-20 minutes | |
| - **Dependencies:** Sub-Task 4.1 | |
| - **Description:** Execute all quality assurance checks | |
| - **Acceptance Criteria:** | |
| 1. All linting rules pass | |
| 2. Code properly formatted | |
| 3. Type checking passes | |
| 4. All unit tests pass (target: 60+ tests total) | |
| #### **Sub-Task 4.3: Integration Testing** | |
| - **Status:** Todo | |
| - **Estimated Time:** 10-15 minutes | |
| - **Dependencies:** Sub-Task 4.2 | |
| - **Description:** Manual verification of full integration | |
| - **Acceptance Criteria:** | |
| 1. Application starts successfully | |
| 2. Both tools and prompts load correctly | |
| 3. Vector index builds for both types | |
| 4. No regressions in existing functionality | |
| **Final Quality Check Commands:** | |
| ```bash | |
| # Update dependencies | |
| just lock | |
| just install | |
| # Run all quality checks | |
| just lint | |
| just format | |
| just type-check | |
| just test | |
| # Manual integration test | |
| python app.py | |
| # Verify console output shows both tools and prompts loading | |
| # Final commit | |
| git add -A | |
| python scripts/smart_commit.py "feat: implement MVP 2 Sprint 1 - MCPPrompt ontology and KG integration" | |
| git push origin main | |
| ``` | |
| --- | |
| ## π Sprint 1 Success Metrics | |
| ### **Functional Metrics** | |
| - **New Data Structures:** 1 (MCPPrompt dataclass) | |
| - **New Data Files:** 1 (initial_prompts.json with 6+ prompts) | |
| - **Enhanced KG Methods:** 5 (load, retrieve, index, search for prompts) | |
| - **New Unit Tests:** 20+ (comprehensive test coverage) | |
| ### **Technical Metrics** | |
| - **Code Quality:** A+ (maintained from MVP 1) | |
| - **Test Coverage:** >80% for new code | |
| - **Type Safety:** 100% (full type hints) | |
| - **Integration:** Seamless with existing MVP 1 code | |
| ### **Performance Metrics** | |
| - **Startup Time:** <5 seconds (including prompt loading) | |
| - **Vector Index Build:** <30 seconds (for 4 tools + 6 prompts) | |
| - **Memory Usage:** <50MB increase (for prompt data) | |
| - **API Response Time:** Maintained MVP 1 performance | |
| --- | |
| ## π Risk Assessment | |
| ### **Technical Risks** | |
| | Risk | Probability | Impact | Mitigation | | |
| |------|-------------|--------|------------| | |
| | Prompt JSON Schema Changes | Low | Medium | Comprehensive validation in MCPPrompt.__post_init__ | | |
| | Vector Index Performance | Low | Low | Small dataset, proven embedding approach | | |
| | Test Complexity | Medium | Low | Incremental testing, clear test separation | | |
| ### **Integration Risks** | |
| | Risk | Probability | Impact | Mitigation | | |
| |------|-------------|--------|------------| | |
| | MVP 1 Regression | Low | High | Extensive existing test coverage, no changes to tool logic | | |
| | Startup Time Increase | Medium | Low | Monitor startup performance, optimize if needed | | |
| | Memory Usage Growth | Low | Low | Small prompt dataset, efficient storage | | |
| --- | |
| ## π Sprint 1 Deliverables | |
| ### **Code Artifacts** | |
| 1. **Enhanced kg_services/ontology.py** - MCPPrompt dataclass with validation | |
| 2. **Rich data/initial_prompts.json** - 6+ diverse, high-quality prompt templates | |
| 3. **Extended kg_services/knowledge_graph.py** - Dual tool+prompt management | |
| 4. **Updated app.py** - Integrated prompt loading in initialization | |
| 5. **Comprehensive Test Suite** - 20+ new unit tests for all new functionality | |
| ### **Quality Assurance** | |
| 1. **100% Type Coverage** - All new code with proper type hints | |
| 2. **Comprehensive Testing** - Unit tests for all new methods and edge cases | |
| 3. **Documentation** - Clear docstrings and inline comments | |
| 4. **Performance Validation** - No regression in MVP 1 performance | |
| 5. **Integration Verification** - End-to-end testing of enhanced system | |
| --- | |
| ## π― Sprint 1 Definition of Done | |
| ### **Technical Completion** | |
| - [x] MCPPrompt dataclass implemented with validation | |
| - [x] 6+ diverse prompt templates created and validated | |
| - [x] InMemoryKG enhanced for dual tool+prompt management | |
| - [x] Vector indexing supports semantic search across prompts | |
| - [x] Application initialization includes prompt loading | |
| - [x] All new functionality covered by unit tests | |
| ### **Quality Standards** | |
| - [x] All quality checks passing (lint, format, type-check, test) | |
| - [x] No regressions in existing MVP 1 functionality | |
| - [x] Code follows project standards and conventions | |
| - [x] Comprehensive error handling and logging | |
| - [x] Performance targets maintained | |
| ### **Integration Readiness** | |
| - [x] Application starts successfully with enhanced initialization | |
| - [x] Both tools and prompts load and index correctly | |
| - [x] System ready for Sprint 2 (enhanced planner development) | |
| - [x] All changes committed and CI pipeline green | |
| --- | |
| ## π Post-Sprint 1 Review | |
| ### **What's Complete** | |
| - Foundational prompt ontology established | |
| - Rich prompt metadata created for all MVP 1 tools | |
| - Knowledge graph enhanced for dual tool+prompt management | |
| - Vector indexing supports semantic search across both types | |
| - Application initialization seamlessly includes prompts | |
| - Comprehensive test coverage for all new functionality | |
| ### **What's Next (Sprint 2)** | |
| - Enhance SimplePlannerAgent to suggest tool+prompt pairs | |
| - Implement intelligent prompt selection logic | |
| - Create PlannedStep data structure | |
| - Maintain backward compatibility with MVP 1 interface | |
| ### **Key Success Factors** | |
| 1. **Solid Foundation** - Comprehensive data structures and validation | |
| 2. **Rich Data** - High-quality prompt templates for effective testing | |
| 3. **Seamless Integration** - No disruption to existing MVP 1 functionality | |
| 4. **Quality First** - Extensive testing and error handling | |
| 5. **Future Ready** - Architecture prepared for advanced planning logic | |
| --- | |
| **Sprint 1 Start Date:** TBD | |
| **Estimated Completion:** 3-4 hours | |
| **Confidence Level:** HIGH (building on proven MVP 1 architecture) | |
| **Risk Level:** LOW (additive changes, no breaking modifications) | |
| *This comprehensive Sprint 1 plan provides the foundation for transforming KGraph-MCP from a tool discovery system into an intelligent tool+prompt suggestion platform.* |