Spandan Roy commited on
Commit
dc673ed
Β·
1 Parent(s): 23046d5

Phase 1 Complete: Triage Agent with zero-shot classification

Browse files

- Added Neo4j schema and client
- Added Qdrant vector store setup
- Implemented Triage Agent with BART model
- Updated Gradio UI with bug classification tab
- Added sample bug dataset
- Project structure complete

agents/triage/triage_agent.py ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Triage Agent: Automated Bug Classification and Priority Assignment
3
+ """
4
+ import pandas as pd
5
+ from transformers import pipeline
6
+ from typing import Dict, List
7
+ import logging
8
+
9
+ logging.basicConfig(level=logging.INFO)
10
+ logger = logging.getLogger(__name__)
11
+
12
+ class TriageAgent:
13
+ """
14
+ Agent responsible for:
15
+ 1. Classifying bugs into categories (UI, API, Database, Performance)
16
+ 2. Assigning priority levels (P0-P4)
17
+ 3. Determining severity (Critical, High, Medium, Low)
18
+ """
19
+
20
+ def __init__(self):
21
+ """Initialize the triage agent with ML models"""
22
+ self.classifier = None
23
+ self.categories = ['UI', 'API', 'Database', 'Performance', 'Backend']
24
+ self.priorities = ['P0', 'P1', 'P2', 'P3', 'P4']
25
+ self.severities = ['Critical', 'High', 'Medium', 'Low']
26
+
27
+ def load_model(self):
28
+ """Load pre-trained classification model"""
29
+ try:
30
+ # Using zero-shot classification for now
31
+ # Later: Fine-tune BERT on bug data
32
+ self.classifier = pipeline(
33
+ "zero-shot-classification",
34
+ model="facebook/bart-large-mnli",
35
+ device=-1 # CPU
36
+ )
37
+ logger.info("βœ… Triage model loaded successfully")
38
+ return True
39
+ except Exception as e:
40
+ logger.error(f"❌ Model loading failed: {e}")
41
+ return False
42
+
43
+ def classify_bug(self, title: str, description: str) -> Dict:
44
+ """
45
+ Classify a bug based on title and description
46
+
47
+ Args:
48
+ title: Bug title
49
+ description: Bug description
50
+
51
+ Returns:
52
+ Dict with category, priority, severity, confidence
53
+ """
54
+ if not self.classifier:
55
+ logger.error("Model not loaded!")
56
+ return None
57
+
58
+ # Combine title and description
59
+ bug_text = f"{title}. {description}"
60
+
61
+ # Classify category
62
+ category_result = self.classifier(
63
+ bug_text,
64
+ candidate_labels=self.categories
65
+ )
66
+
67
+ # Determine priority based on keywords
68
+ priority = self._determine_priority(bug_text)
69
+
70
+ # Determine severity
71
+ severity = self._determine_severity(bug_text, priority)
72
+
73
+ result = {
74
+ 'category': category_result['labels'][0],
75
+ 'category_confidence': category_result['scores'][0],
76
+ 'priority': priority,
77
+ 'severity': severity,
78
+ 'reasoning': self._generate_reasoning(
79
+ category_result['labels'][0],
80
+ priority,
81
+ severity
82
+ )
83
+ }
84
+
85
+ logger.info(f"βœ… Classified bug as {result['category']} / {result['priority']}")
86
+ return result
87
+
88
+ def _determine_priority(self, text: str) -> str:
89
+ """Determine priority based on keywords"""
90
+ text_lower = text.lower()
91
+
92
+ # Critical keywords -> P0
93
+ critical_keywords = ['crash', 'critical', 'security', 'data loss', 'payment']
94
+ if any(keyword in text_lower for keyword in critical_keywords):
95
+ return 'P0'
96
+
97
+ # High priority keywords -> P1
98
+ high_keywords = ['broken', 'not working', 'error', 'fail', 'timeout']
99
+ if any(keyword in text_lower for keyword in high_keywords):
100
+ return 'P1'
101
+
102
+ # Medium priority keywords -> P2
103
+ medium_keywords = ['slow', 'incorrect', 'missing', 'wrong']
104
+ if any(keyword in text_lower for keyword in medium_keywords):
105
+ return 'P2'
106
+
107
+ # Low priority keywords -> P3
108
+ low_keywords = ['cosmetic', 'color', 'spacing', 'typo']
109
+ if any(keyword in text_lower for keyword in low_keywords):
110
+ return 'P3'
111
+
112
+ # Default
113
+ return 'P2'
114
+
115
+ def _determine_severity(self, text: str, priority: str) -> str:
116
+ """Map priority to severity"""
117
+ severity_map = {
118
+ 'P0': 'Critical',
119
+ 'P1': 'High',
120
+ 'P2': 'Medium',
121
+ 'P3': 'Low',
122
+ 'P4': 'Low'
123
+ }
124
+ return severity_map.get(priority, 'Medium')
125
+
126
+ def _generate_reasoning(self, category: str, priority: str, severity: str) -> str:
127
+ """Generate explanation for classification"""
128
+ return f"""
129
+ This bug has been classified as a {category} issue with {priority} priority
130
+ and {severity} severity based on the content analysis and keyword detection.
131
+ """
132
+
133
+ def batch_classify(self, bugs_df: pd.DataFrame) -> pd.DataFrame:
134
+ """Classify multiple bugs from a DataFrame"""
135
+ results = []
136
+
137
+ for idx, row in bugs_df.iterrows():
138
+ result = self.classify_bug(row['title'], row['description'])
139
+ results.append(result)
140
+
141
+ # Add results to dataframe
142
+ bugs_df['predicted_category'] = [r['category'] for r in results]
143
+ bugs_df['predicted_priority'] = [r['priority'] for r in results]
144
+ bugs_df['predicted_severity'] = [r['severity'] for r in results]
145
+ bugs_df['confidence'] = [r['category_confidence'] for r in results]
146
+
147
+ return bugs_df
148
+
149
+ # Example usage and testing
150
+ if __name__ == "__main__":
151
+ agent = TriageAgent()
152
+
153
+ if agent.load_model():
154
+ # Test single bug
155
+ result = agent.classify_bug(
156
+ title="Login button not responding",
157
+ description="Users cannot click the login button on mobile devices"
158
+ )
159
+ print("Classification Result:")
160
+ print(result)
161
+
162
+ # Test batch classification
163
+ bugs_df = pd.read_csv('../../data/sample/bugs_sample.csv')
164
+ classified_df = agent.batch_classify(bugs_df)
165
+ print("\nBatch Classification Results:")
166
+ print(classified_df[['bug_id', 'category', 'predicted_category', 'confidence']])
app.py CHANGED
@@ -1,51 +1,81 @@
1
  import gradio as gr
2
  import os
 
3
  from dotenv import load_dotenv
 
 
 
 
4
 
5
  # Load environment variables
6
  load_dotenv()
7
-
8
- # Set HF_HOME to persist model caches
9
  os.environ['HF_HOME'] = os.getenv('HF_HOME', '/data/.huggingface')
10
 
 
 
 
 
 
 
 
 
11
  def welcome_message():
12
- """Initial welcome message"""
13
  return """
14
  # πŸ› Intelligent Bug Triage System
15
 
16
- Welcome to the AI-powered bug triage and resolution system.
17
 
18
- ## Current Status: Phase 1 - Foundation Setup
 
 
 
 
19
 
20
- ### System Capabilities (Coming Soon):
21
- - 🎯 Automated bug classification and priority assignment
22
- - πŸ‘₯ Intelligent developer assignment with workload balancing
23
- - πŸ’‘ Solution recommendations using RAG
24
- - πŸ“Š Real-time analytics and performance tracking
25
 
26
- ### Next Steps:
27
- 1. Set up Neo4j knowledge graph
28
- 2. Configure vector database (Qdrant)
29
- 3. Train classification models
30
- 4. Build multi-agent system
31
-
32
- **Project Status**: Development Environment Ready βœ…
33
  """
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  def test_space_storage():
36
- """Test available storage in the Space"""
37
  import shutil
38
  disk_usage = shutil.disk_usage('/')
39
  total_gb = disk_usage.total / (1024**3)
40
- used_gb = disk_usage.used / (1024**3)
41
  free_gb = disk_usage.free / (1024**3)
42
-
43
- return f"""
44
- **Space Storage Information:**
45
- - Total: {total_gb:.2f} GB
46
- - Used: {used_gb:.2f} GB
47
- - Free: {free_gb:.2f} GB
48
- """
49
 
50
  # Create Gradio Interface
51
  with gr.Blocks(theme=gr.themes.Soft(), title="Bug Triage System") as demo:
@@ -53,41 +83,85 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Bug Triage System") as demo:
53
  gr.Markdown("*AI-Powered Bug Management with Knowledge Graphs & Multi-Agent RAG*")
54
 
55
  with gr.Tab("Home"):
56
- welcome_output = gr.Markdown(welcome_message())
 
 
 
 
 
57
 
58
- with gr.Tab("System Info"):
59
- gr.Markdown("## Development Environment Status")
60
- storage_btn = gr.Button("Check Storage")
61
- storage_output = gr.Textbox(label="Storage Status", lines=6)
62
- storage_btn.click(test_space_storage, outputs=storage_output)
 
 
 
 
 
 
 
 
 
 
 
63
 
64
- with gr.Tab("Documentation"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  gr.Markdown("""
66
- ## Project Documentation
67
 
68
- ### Architecture Overview
69
- This system uses a **multi-agent architecture** with:
70
- - **Triage Agent**: Classifies bugs and assigns priorities
71
- - **Assignment Agent**: Routes bugs to appropriate developers
72
- - **Resolution Agent**: Provides solution recommendations
73
- - **Analytics Agent**: Tracks metrics and performance
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
  ### Technology Stack
76
- - **Backend**: FastAPI
77
- - **Knowledge Graph**: Neo4j Community Edition
78
  - **Vector DB**: Qdrant
79
  - **Agent Framework**: LangChain
80
- - **ML Models**: Transformers (BERT)
81
  - **Frontend**: Gradio
 
82
 
83
- ### Development Phases
84
- 1. **Phase 1**: Foundation (4-6 weeks) - Current
85
- 2. **Phase 2**: Multi-Agent System (4-6 weeks)
86
- 3. **Phase 3**: RAG Implementation (4-6 weeks)
87
- 4. **Phase 4**: Integration & Deployment (3-4 weeks)
88
  """)
89
 
90
- # Launch the app
91
  if __name__ == "__main__":
92
  port = int(os.environ.get('PORT', 7860))
93
  demo.launch(
 
1
  import gradio as gr
2
  import os
3
+ import sys
4
  from dotenv import load_dotenv
5
+ import pandas as pd
6
+
7
+ # Add project root to Python path
8
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
9
 
10
  # Load environment variables
11
  load_dotenv()
 
 
12
  os.environ['HF_HOME'] = os.getenv('HF_HOME', '/data/.huggingface')
13
 
14
+ # Import agents (will handle import errors gracefully)
15
+ try:
16
+ from agents.triage.triage_agent import TriageAgent
17
+ TRIAGE_AVAILABLE = True
18
+ except ImportError as e:
19
+ print(f"Triage agent not available: {e}")
20
+ TRIAGE_AVAILABLE = False
21
+
22
  def welcome_message():
23
+ """Welcome message"""
24
  return """
25
  # πŸ› Intelligent Bug Triage System
26
 
27
+ ## Phase 1: Foundation - Triage Agent Ready! πŸŽ‰
28
 
29
+ ### Current Features:
30
+ - βœ… **Automated Bug Classification** (UI, API, Database, Performance, Backend)
31
+ - βœ… **Priority Assignment** (P0-P4)
32
+ - βœ… **Severity Detection** (Critical, High, Medium, Low)
33
+ - βœ… **Confidence Scoring**
34
 
35
+ ### Try It Now:
36
+ Navigate to the "Bug Triage" tab to classify your first bug!
 
 
 
37
 
38
+ **Status**: Triage Agent Online βœ…
 
 
 
 
 
 
39
  """
40
 
41
+ def classify_single_bug(title, description):
42
+ """Classify a single bug"""
43
+ if not TRIAGE_AVAILABLE:
44
+ return "❌ Triage agent not loaded. Please check dependencies."
45
+
46
+ if not title or not description:
47
+ return "⚠️ Please provide both title and description."
48
+
49
+ try:
50
+ agent = TriageAgent()
51
+ if not agent.load_model():
52
+ return "❌ Failed to load triage model."
53
+
54
+ result = agent.classify_bug(title, description)
55
+
56
+ output = f"""
57
+ ## Classification Results 🎯
58
+
59
+ **Category:** {result['category']}
60
+ **Priority:** {result['priority']}
61
+ **Severity:** {result['severity']}
62
+ **Confidence:** {result['category_confidence']:.2%}
63
+
64
+ ### Reasoning:
65
+ {result['reasoning']}
66
+ """
67
+ return output
68
+
69
+ except Exception as e:
70
+ return f"❌ Classification failed: {str(e)}"
71
+
72
  def test_space_storage():
73
+ """Test storage"""
74
  import shutil
75
  disk_usage = shutil.disk_usage('/')
76
  total_gb = disk_usage.total / (1024**3)
 
77
  free_gb = disk_usage.free / (1024**3)
78
+ return f"**Storage:** {free_gb:.2f} GB free of {total_gb:.2f} GB total"
 
 
 
 
 
 
79
 
80
  # Create Gradio Interface
81
  with gr.Blocks(theme=gr.themes.Soft(), title="Bug Triage System") as demo:
 
83
  gr.Markdown("*AI-Powered Bug Management with Knowledge Graphs & Multi-Agent RAG*")
84
 
85
  with gr.Tab("Home"):
86
+ gr.Markdown(welcome_message())
87
+ storage_output = gr.Markdown(test_space_storage())
88
+
89
+ with gr.Tab("Bug Triage 🎯"):
90
+ gr.Markdown("## Classify a New Bug")
91
+ gr.Markdown("Enter bug details below to get automated classification:")
92
 
93
+ with gr.Row():
94
+ with gr.Column():
95
+ bug_title = gr.Textbox(
96
+ label="Bug Title",
97
+ placeholder="e.g., Login button not responding",
98
+ lines=2
99
+ )
100
+ bug_description = gr.Textbox(
101
+ label="Bug Description",
102
+ placeholder="Detailed description of the issue...",
103
+ lines=5
104
+ )
105
+ classify_btn = gr.Button("πŸ” Classify Bug", variant="primary")
106
+
107
+ with gr.Column():
108
+ classification_output = gr.Markdown(label="Classification Results")
109
 
110
+ classify_btn.click(
111
+ fn=classify_single_bug,
112
+ inputs=[bug_title, bug_description],
113
+ outputs=classification_output
114
+ )
115
+
116
+ # Examples
117
+ gr.Examples(
118
+ examples=[
119
+ ["Login button not responding", "Users cannot click the login button on mobile devices. Issue occurs on iOS Safari only."],
120
+ ["API timeout on large queries", "Database queries taking over 30 seconds to complete when fetching user data."],
121
+ ["Memory leak in background service", "Application consuming 8GB RAM after running for 24 hours continuously."],
122
+ ],
123
+ inputs=[bug_title, bug_description]
124
+ )
125
+
126
+ with gr.Tab("Documentation πŸ“š"):
127
  gr.Markdown("""
128
+ ## Project Architecture
129
 
130
+ ### Multi-Agent System
131
+ 1. **Triage Agent** βœ… (ACTIVE)
132
+ - Classifies bugs into categories
133
+ - Assigns priority levels
134
+ - Determines severity
135
+
136
+ 2. **Assignment Agent** (Coming in Phase 2)
137
+ - Routes bugs to developers
138
+ - Balances workload
139
+ - Considers expertise
140
+
141
+ 3. **Resolution Agent** (Coming in Phase 3)
142
+ - Provides solution recommendations
143
+ - Uses RAG for knowledge retrieval
144
+
145
+ 4. **Analytics Agent** (Coming in Phase 4)
146
+ - Tracks performance metrics
147
+ - Generates insights
148
 
149
  ### Technology Stack
150
+ - **ML Models**: Transformers (BART, BERT)
151
+ - **Knowledge Graph**: Neo4j
152
  - **Vector DB**: Qdrant
153
  - **Agent Framework**: LangChain
 
154
  - **Frontend**: Gradio
155
+ - **Backend**: FastAPI
156
 
157
+ ### Development Progress
158
+ - βœ… Phase 1: Foundation (Week 1-2)
159
+ - πŸ”„ Phase 2: Multi-Agent (Week 3-4)
160
+ - ⏳ Phase 3: RAG System (Week 5-6)
161
+ - ⏳ Phase 4: Deployment (Week 7-8)
162
  """)
163
 
164
+ # Launch
165
  if __name__ == "__main__":
166
  port = int(os.environ.get('PORT', 7860))
167
  demo.launch(
data/sample/bugs_sample.csv ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ bug_id,title,description,category,priority,severity
2
+ BUG-001,Login button not responding,User cannot click login button on mobile devices,UI,P1,High
3
+ BUG-002,API timeout on large queries,Database queries taking >30 seconds,API,P0,Critical
4
+ BUG-003,Memory leak in background service,Application consuming 8GB RAM after 24hrs,Performance,P1,High
5
+ BUG-004,Incorrect tax calculation,Shopping cart shows wrong tax amount,Backend,P0,Critical
6
+ BUG-005,Dark mode colors incorrect,Text not visible in dark mode,UI,P3,Low
7
+ BUG-006,Search returns empty results,Search functionality broken for certain queries,Backend,P2,Medium
8
+ BUG-007,Image upload fails for PNG,PNG files cannot be uploaded to profile,UI,P2,Medium
9
+ BUG-008,Database connection pool exhausted,App crashes during high traffic,Database,P0,Critical
10
+ BUG-009,Email notifications not sent,Users not receiving password reset emails,Backend,P1,High
11
+ BUG-010,Pagination breaks on page 10,Cannot navigate beyond page 10 in results,UI,P3,Low
knowledge-graph/neo4j_client.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Neo4j Knowledge Graph Client"""
2
+ import os
3
+ from neo4j import GraphDatabase
4
+ from typing import List, Dict, Any
5
+ import logging
6
+
7
+ logging.basicConfig(level=logging.INFO)
8
+ logger = logging.getLogger(__name__)
9
+
10
+ class Neo4jClient:
11
+ """Client for interacting with Neo4j Knowledge Graph"""
12
+
13
+ def __init__(self):
14
+ """Initialize Neo4j connection"""
15
+ self.uri = os.getenv('NEO4J_URI', 'bolt://localhost:7687')
16
+ self.user = os.getenv('NEO4J_USER', 'neo4j')
17
+ self.password = os.getenv('NEO4J_PASSWORD', 'password')
18
+ self.driver = None
19
+
20
+ def connect(self):
21
+ """Establish connection to Neo4j"""
22
+ try:
23
+ self.driver = GraphDatabase.driver(
24
+ self.uri,
25
+ auth=(self.user, self.password)
26
+ )
27
+ logger.info("βœ… Connected to Neo4j")
28
+ return True
29
+ except Exception as e:
30
+ logger.error(f"❌ Neo4j connection failed: {e}")
31
+ return False
32
+
33
+ def close(self):
34
+ """Close Neo4j connection"""
35
+ if self.driver:
36
+ self.driver.close()
37
+ logger.info("Neo4j connection closed")
38
+
39
+ def execute_query(self, query: str, parameters: Dict = None):
40
+ """Execute a Cypher query"""
41
+ if not self.driver:
42
+ logger.error("Not connected to Neo4j")
43
+ return None
44
+
45
+ with self.driver.session() as session:
46
+ result = session.run(query, parameters or {})
47
+ return [record.data() for record in result]
48
+
49
+ def create_bug(self, bug_data: Dict[str, Any]):
50
+ """Create a new bug node"""
51
+ query = """
52
+ CREATE (b:Bug {
53
+ id: $id,
54
+ title: $title,
55
+ description: $description,
56
+ priority: $priority,
57
+ category: $category,
58
+ status: 'Open',
59
+ created_at: datetime()
60
+ })
61
+ RETURN b
62
+ """
63
+ return self.execute_query(query, bug_data)
64
+
65
+ def get_developer_by_expertise(self, expertise: str):
66
+ """Find developers with specific expertise"""
67
+ query = """
68
+ MATCH (d:Developer)
69
+ WHERE $expertise IN d.expertise
70
+ AND d.current_workload < d.max_capacity
71
+ RETURN d
72
+ ORDER BY d.current_workload ASC
73
+ LIMIT 5
74
+ """
75
+ return self.execute_query(query, {'expertise': expertise})
76
+
77
+ # Example usage
78
+ if __name__ == "__main__":
79
+ client = Neo4jClient()
80
+ if client.connect():
81
+ print("Neo4j client ready!")
82
+ client.close()
knowledge-graph/schemas/bug_schema.cypher ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Bug Triage Knowledge Graph Schema
2
+ // Nodes: Bug, Developer, Component, Team, Resolution
3
+
4
+ // Create Constraints
5
+ CREATE CONSTRAINT bug_id IF NOT EXISTS FOR (b:Bug) REQUIRE b.id IS UNIQUE;
6
+ CREATE CONSTRAINT dev_id IF NOT EXISTS FOR (d:Developer) REQUIRE d.id IS UNIQUE;
7
+ CREATE CONSTRAINT component_id IF NOT EXISTS FOR (c:Component) REQUIRE c.name IS UNIQUE;
8
+ CREATE CONSTRAINT team_id IF NOT EXISTS FOR (t:Team) REQUIRE t.name IS UNIQUE;
9
+
10
+ // Create Indexes
11
+ CREATE INDEX bug_priority IF NOT EXISTS FOR (b:Bug) ON (b.priority);
12
+ CREATE INDEX bug_status IF NOT EXISTS FOR (b:Bug) ON (b.status);
13
+ CREATE INDEX bug_category IF NOT EXISTS FOR (b:Bug) ON (b.category);
14
+ CREATE INDEX dev_expertise IF NOT EXISTS FOR (d:Developer) ON (d.expertise);
15
+
16
+ // Sample Node Creation
17
+ CREATE (b:Bug {
18
+ id: 'BUG-001',
19
+ title: 'Sample Bug',
20
+ description: 'This is a sample bug for testing',
21
+ priority: 'P2',
22
+ severity: 'Medium',
23
+ category: 'UI',
24
+ status: 'Open',
25
+ created_at: datetime(),
26
+ reporter: 'user@example.com'
27
+ });
28
+
29
+ CREATE (d:Developer {
30
+ id: 'DEV-001',
31
+ name: 'John Doe',
32
+ email: 'john@example.com',
33
+ expertise: ['Python', 'FastAPI', 'React'],
34
+ current_workload: 3,
35
+ max_capacity: 5
36
+ });
37
+
38
+ CREATE (c:Component {
39
+ name: 'Authentication',
40
+ description: 'User authentication module',
41
+ language: 'Python',
42
+ repository: 'backend'
43
+ });
44
+
45
+ CREATE (t:Team {
46
+ name: 'Backend Team',
47
+ description: 'Handles backend services',
48
+ size: 5
49
+ });
50
+
51
+ // Sample Relationships
52
+ MATCH (d:Developer {id: 'DEV-001'}), (t:Team {name: 'Backend Team'})
53
+ CREATE (d)-[:BELONGS_TO]->(t);
54
+
55
+ MATCH (d:Developer {id: 'DEV-001'}), (c:Component {name: 'Authentication'})
56
+ CREATE (d)-[:EXPERT_IN {proficiency: 0.9}]->(c);
rag-system/vectorstore/qdrant_client.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Qdrant Vector Database Client for RAG"""
2
+ import os
3
+ from qdrant_client import QdrantClient
4
+ from qdrant_client.models import Distance, VectorParams, PointStruct
5
+ from sentence_transformers import SentenceTransformer
6
+ import logging
7
+
8
+ logging.basicConfig(level=logging.INFO)
9
+ logger = logging.getLogger(__name__)
10
+
11
+ class QdrantVectorStore:
12
+ """Vector database for semantic search in bug resolution"""
13
+
14
+ def __init__(self, collection_name: str = "bug_solutions"):
15
+ """Initialize Qdrant client"""
16
+ self.host = os.getenv('QDRANT_HOST', 'localhost')
17
+ self.port = int(os.getenv('QDRANT_PORT', 6333))
18
+ self.collection_name = collection_name
19
+ self.client = None
20
+ self.encoder = None
21
+
22
+ def connect(self):
23
+ """Establish connection to Qdrant"""
24
+ try:
25
+ # For local development, use in-memory mode
26
+ self.client = QdrantClient(":memory:")
27
+ logger.info("βœ… Connected to Qdrant (in-memory mode)")
28
+
29
+ # Initialize sentence transformer for embeddings
30
+ self.encoder = SentenceTransformer('all-MiniLM-L6-v2')
31
+ logger.info("βœ… Loaded embedding model")
32
+
33
+ return True
34
+ except Exception as e:
35
+ logger.error(f"❌ Qdrant connection failed: {e}")
36
+ return False
37
+
38
+ def create_collection(self, vector_size: int = 384):
39
+ """Create a new collection for bug solutions"""
40
+ try:
41
+ self.client.create_collection(
42
+ collection_name=self.collection_name,
43
+ vectors_config=VectorParams(
44
+ size=vector_size,
45
+ distance=Distance.COSINE
46
+ )
47
+ )
48
+ logger.info(f"βœ… Created collection: {self.collection_name}")
49
+ return True
50
+ except Exception as e:
51
+ logger.error(f"❌ Collection creation failed: {e}")
52
+ return False
53
+
54
+ def add_solution(self, solution_id: str, text: str, metadata: dict):
55
+ """Add a bug solution to vector store"""
56
+ try:
57
+ # Generate embedding
58
+ vector = self.encoder.encode(text).tolist()
59
+
60
+ # Create point
61
+ point = PointStruct(
62
+ id=solution_id,
63
+ vector=vector,
64
+ payload={
65
+ "text": text,
66
+ **metadata
67
+ }
68
+ )
69
+
70
+ self.client.upsert(
71
+ collection_name=self.collection_name,
72
+ points=[point]
73
+ )
74
+ logger.info(f"βœ… Added solution: {solution_id}")
75
+ return True
76
+ except Exception as e:
77
+ logger.error(f"❌ Failed to add solution: {e}")
78
+ return False
79
+
80
+ def search_similar(self, query: str, limit: int = 5):
81
+ """Search for similar bug solutions"""
82
+ try:
83
+ # Generate query embedding
84
+ query_vector = self.encoder.encode(query).tolist()
85
+
86
+ # Search
87
+ results = self.client.search(
88
+ collection_name=self.collection_name,
89
+ query_vector=query_vector,
90
+ limit=limit
91
+ )
92
+
93
+ return results
94
+ except Exception as e:
95
+ logger.error(f"❌ Search failed: {e}")
96
+ return []
97
+
98
+ # Example usage
99
+ if __name__ == "__main__":
100
+ store = QdrantVectorStore()
101
+ if store.connect():
102
+ store.create_collection()
103
+ print("Qdrant vector store ready!")