iris-vector-rag 0.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. adapters/rag_templates_bridge.py +578 -0
  2. common/__init__.py +1 -0
  3. common/batch_utils.py +294 -0
  4. common/config.py +58 -0
  5. common/connection_manager.py +242 -0
  6. common/connection_pool.py +445 -0
  7. common/database.py +141 -0
  8. common/database_schema_manager.py +289 -0
  9. common/db_init_with_indexes.py +181 -0
  10. common/db_vector_utils.py +181 -0
  11. common/environment_manager.py +220 -0
  12. common/huggingface_utils.py +206 -0
  13. common/iris_client.py +92 -0
  14. common/iris_connection_manager.py +411 -0
  15. common/iris_connection_pool.py +360 -0
  16. common/iris_connector.py +71 -0
  17. common/iris_dbapi_connector.py +323 -0
  18. common/iris_index_utils.py +195 -0
  19. common/iris_sql_utils.py +704 -0
  20. common/iris_stream_reader.py +166 -0
  21. common/llm_cache_config.py +308 -0
  22. common/llm_cache_iris.py +671 -0
  23. common/llm_cache_manager.py +911 -0
  24. common/utils.py +559 -0
  25. common/vector_sql_utils.py +584 -0
  26. evaluation_framework/__init__.py +66 -0
  27. evaluation_framework/biomedical_question_generator.py +826 -0
  28. evaluation_framework/comparative_analysis_system.py +1173 -0
  29. evaluation_framework/empirical_reporting.py +1298 -0
  30. evaluation_framework/evaluation_orchestrator.py +1123 -0
  31. evaluation_framework/execute_production_evaluation.py +382 -0
  32. evaluation_framework/pmc_data_pipeline.py +1332 -0
  33. evaluation_framework/production_evaluation_config.py +353 -0
  34. evaluation_framework/ragas_metrics_framework.py +1013 -0
  35. evaluation_framework/real_production_evaluation.py +544 -0
  36. evaluation_framework/run_10k_evaluation.py +175 -0
  37. evaluation_framework/simple_test.py +364 -0
  38. evaluation_framework/statistical_evaluation_methodology.py +1016 -0
  39. evaluation_framework/test_framework.py +281 -0
  40. evaluation_framework/test_iris_connectivity.py +244 -0
  41. evaluation_framework/test_small_scale_evaluation.py +432 -0
  42. evaluation_framework/true_e2e_evaluation.py +639 -0
  43. evaluation_framework/visualization_engine.py +585 -0
  44. iris_rag/__init__.py +284 -0
  45. iris_rag/config/default_config.yaml +295 -0
  46. iris_vector_rag-0.2.1.dist-info/METADATA +499 -0
  47. iris_vector_rag-0.2.1.dist-info/RECORD +50 -0
  48. iris_vector_rag-0.2.1.dist-info/WHEEL +5 -0
  49. iris_vector_rag-0.2.1.dist-info/entry_points.txt +2 -0
  50. iris_vector_rag-0.2.1.dist-info/top_level.txt +4 -0
@@ -0,0 +1,585 @@
1
+ """
2
+ RAG Evaluation Visualization Engine
3
+ Creates beautiful interactive HTML reports with spider charts and performance dashboards
4
+ """
5
+
6
+ import json
7
+ import logging
8
+ from dataclasses import dataclass
9
+ from datetime import datetime
10
+ from pathlib import Path
11
+ from typing import Any, Dict, List, Optional, Union
12
+
13
+ import numpy as np
14
+ import pandas as pd
15
+ import plotly.express as px
16
+ import plotly.graph_objects as go
17
+ import plotly.offline as pyo
18
+ from plotly.subplots import make_subplots
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ @dataclass
24
+ class EvaluationResults:
25
+ """Container for evaluation results"""
26
+
27
+ pipeline_name: str
28
+ ragas_metrics: Dict[str, float]
29
+ performance_metrics: Dict[str, float]
30
+ timing_data: Dict[str, float]
31
+ metadata: Dict[str, Any]
32
+
33
+
34
+ class SpiderChartGenerator:
35
+ """Generates beautiful spider/radar charts for RAGAS metrics comparison"""
36
+
37
+ RAGAS_METRICS = [
38
+ "faithfulness",
39
+ "answer_relevancy",
40
+ "context_precision",
41
+ "context_recall",
42
+ "answer_correctness",
43
+ "answer_similarity",
44
+ "context_utilization",
45
+ ]
46
+
47
+ METRIC_DESCRIPTIONS = {
48
+ "faithfulness": "Factual accuracy of generated answers",
49
+ "answer_relevancy": "Relevance of answer to the question",
50
+ "context_precision": "Quality of retrieved context",
51
+ "context_recall": "Completeness of context retrieval",
52
+ "answer_correctness": "Overall correctness of answers",
53
+ "answer_similarity": "Semantic similarity to ground truth",
54
+ "context_utilization": "Effective use of provided context",
55
+ }
56
+
57
+ def __init__(self):
58
+ self.colors = {
59
+ "GraphRAG": "#FF6B6B",
60
+ "BasicRAG": "#4ECDC4",
61
+ "CRAG": "#45B7D1",
62
+ "BasicRAGReranking": "#96CEB4",
63
+ "ColBERT": "#9B59B6",
64
+ "HyDE": "#F39C12",
65
+ }
66
+
67
+ def create_spider_chart(self, results: List[EvaluationResults]) -> go.Figure:
68
+ """Create interactive spider chart comparing pipelines"""
69
+
70
+ fig = go.Figure()
71
+
72
+ for result in results:
73
+ # Extract RAGAS scores
74
+ scores = []
75
+ for metric in self.RAGAS_METRICS:
76
+ score = result.ragas_metrics.get(metric, 0.0)
77
+ scores.append(score)
78
+
79
+ # Add trace for this pipeline
80
+ fig.add_trace(
81
+ go.Scatterpolar(
82
+ r=scores,
83
+ theta=self.RAGAS_METRICS,
84
+ fill="toself",
85
+ name=result.pipeline_name,
86
+ line_color=self.colors.get(result.pipeline_name, "#333333"),
87
+ fillcolor=self.colors.get(result.pipeline_name, "#333333"),
88
+ opacity=0.6,
89
+ hovertemplate=(
90
+ "<b>%{fullData.name}</b><br>"
91
+ + "Metric: %{theta}<br>"
92
+ + "Score: %{r:.3f}<br>"
93
+ + "<extra></extra>"
94
+ ),
95
+ )
96
+ )
97
+
98
+ # Update layout
99
+ fig.update_layout(
100
+ polar=dict(
101
+ radialaxis=dict(
102
+ visible=True,
103
+ range=[0, 1],
104
+ tickmode="array",
105
+ tickvals=[0.2, 0.4, 0.6, 0.8, 1.0],
106
+ ticktext=["0.2", "0.4", "0.6", "0.8", "1.0"],
107
+ ),
108
+ angularaxis=dict(tickfont_size=12, rotation=90, direction="clockwise"),
109
+ ),
110
+ showlegend=True,
111
+ title={
112
+ "text": "RAG Pipeline Performance Comparison - RAGAS Metrics",
113
+ "x": 0.5,
114
+ "xanchor": "center",
115
+ "font": {"size": 20},
116
+ },
117
+ font_size=12,
118
+ width=800,
119
+ height=600,
120
+ )
121
+
122
+ return fig
123
+
124
+
125
+ class PerformanceDashboard:
126
+ """Creates comprehensive performance dashboards"""
127
+
128
+ def __init__(self):
129
+ self.colors = {
130
+ "GraphRAG": "#FF6B6B",
131
+ "BasicRAG": "#4ECDC4",
132
+ "CRAG": "#45B7D1",
133
+ "BasicRAGReranking": "#96CEB4",
134
+ }
135
+
136
+ def create_performance_dashboard(
137
+ self, results: List[EvaluationResults]
138
+ ) -> go.Figure:
139
+ """Create multi-panel performance dashboard"""
140
+
141
+ # Create subplots
142
+ fig = make_subplots(
143
+ rows=2,
144
+ cols=2,
145
+ subplot_titles=(
146
+ "Response Time Distribution",
147
+ "Throughput Comparison",
148
+ "Memory Usage",
149
+ "Success Rate",
150
+ ),
151
+ specs=[
152
+ [{"type": "histogram"}, {"type": "bar"}],
153
+ [{"type": "scatter"}, {"type": "pie"}],
154
+ ],
155
+ )
156
+
157
+ # Panel 1: Response Time Distribution
158
+ for result in results:
159
+ response_times = result.timing_data.get("response_times", [])
160
+ if response_times:
161
+ fig.add_trace(
162
+ go.Histogram(
163
+ x=response_times,
164
+ name=f"{result.pipeline_name} Response Time",
165
+ opacity=0.7,
166
+ marker_color=self.colors.get(result.pipeline_name, "#333333"),
167
+ ),
168
+ row=1,
169
+ col=1,
170
+ )
171
+
172
+ # Panel 2: Throughput Comparison
173
+ pipeline_names = [r.pipeline_name for r in results]
174
+ throughputs = [r.performance_metrics.get("throughput", 0) for r in results]
175
+
176
+ fig.add_trace(
177
+ go.Bar(
178
+ x=pipeline_names,
179
+ y=throughputs,
180
+ name="Throughput (queries/sec)",
181
+ marker_color=[
182
+ self.colors.get(name, "#333333") for name in pipeline_names
183
+ ],
184
+ ),
185
+ row=1,
186
+ col=2,
187
+ )
188
+
189
+ # Panel 3: Memory Usage
190
+ for result in results:
191
+ memory_usage = result.performance_metrics.get("memory_usage_mb", [])
192
+ if isinstance(memory_usage, list) and memory_usage:
193
+ fig.add_trace(
194
+ go.Scatter(
195
+ y=memory_usage,
196
+ mode="lines+markers",
197
+ name=f"{result.pipeline_name} Memory",
198
+ line_color=self.colors.get(result.pipeline_name, "#333333"),
199
+ ),
200
+ row=2,
201
+ col=1,
202
+ )
203
+
204
+ # Panel 4: Success Rate Pie Chart
205
+ avg_success_rate = np.mean(
206
+ [r.performance_metrics.get("success_rate", 0) for r in results]
207
+ )
208
+ fig.add_trace(
209
+ go.Pie(
210
+ labels=["Success", "Failure"],
211
+ values=[avg_success_rate, 1 - avg_success_rate],
212
+ marker_colors=["#2ECC71", "#E74C3C"],
213
+ ),
214
+ row=2,
215
+ col=2,
216
+ )
217
+
218
+ # Update layout
219
+ fig.update_layout(
220
+ height=800, title_text="RAG Pipeline Performance Dashboard", showlegend=True
221
+ )
222
+
223
+ return fig
224
+
225
+
226
+ class HTMLReportGenerator:
227
+ """Generates comprehensive HTML evaluation reports"""
228
+
229
+ def __init__(self):
230
+ self.spider_generator = SpiderChartGenerator()
231
+ self.dashboard_generator = PerformanceDashboard()
232
+
233
+ def generate_report(
234
+ self, results: List[EvaluationResults], output_path: str
235
+ ) -> str:
236
+ """Generate complete HTML evaluation report"""
237
+
238
+ # Generate charts
239
+ spider_chart = self.spider_generator.create_spider_chart(results)
240
+ dashboard = self.dashboard_generator.create_performance_dashboard(results)
241
+
242
+ # Convert to HTML
243
+ spider_html = pyo.plot(spider_chart, output_type="div", include_plotlyjs=False)
244
+ dashboard_html = pyo.plot(dashboard, output_type="div", include_plotlyjs=False)
245
+
246
+ # Create comprehensive HTML report
247
+ html_content = self._generate_html_template(
248
+ results, spider_html, dashboard_html
249
+ )
250
+
251
+ # Write to file
252
+ output_file = Path(output_path)
253
+ output_file.parent.mkdir(parents=True, exist_ok=True)
254
+
255
+ with open(output_file, "w", encoding="utf-8") as f:
256
+ f.write(html_content)
257
+
258
+ logger.info(f"HTML report generated: {output_file}")
259
+ return str(output_file)
260
+
261
+ def _generate_html_template(
262
+ self, results: List[EvaluationResults], spider_html: str, dashboard_html: str
263
+ ) -> str:
264
+ """Generate HTML template with embedded charts"""
265
+
266
+ # Calculate summary statistics
267
+ summary_stats = self._calculate_summary_stats(results)
268
+
269
+ # Generate results table
270
+ results_table = self._generate_results_table(results)
271
+
272
+ html_template = f"""
273
+ <!DOCTYPE html>
274
+ <html lang="en">
275
+ <head>
276
+ <meta charset="UTF-8">
277
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
278
+ <title>RAG Pipeline Evaluation Report</title>
279
+ <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
280
+ <style>
281
+ body {{
282
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
283
+ line-height: 1.6;
284
+ color: #333;
285
+ max-width: 1200px;
286
+ margin: 0 auto;
287
+ padding: 20px;
288
+ background-color: #f8f9fa;
289
+ }}
290
+
291
+ .header {{
292
+ text-align: center;
293
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
294
+ color: white;
295
+ padding: 2rem;
296
+ border-radius: 10px;
297
+ margin-bottom: 2rem;
298
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
299
+ }}
300
+
301
+ .section {{
302
+ background: white;
303
+ padding: 2rem;
304
+ margin-bottom: 2rem;
305
+ border-radius: 10px;
306
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
307
+ }}
308
+
309
+ .metric-card {{
310
+ background: #f8f9fa;
311
+ border-left: 4px solid #007bff;
312
+ padding: 1rem;
313
+ margin: 1rem 0;
314
+ border-radius: 4px;
315
+ }}
316
+
317
+ .table {{
318
+ width: 100%;
319
+ border-collapse: collapse;
320
+ margin: 1rem 0;
321
+ }}
322
+
323
+ .table th, .table td {{
324
+ padding: 12px;
325
+ text-align: left;
326
+ border-bottom: 1px solid #dee2e6;
327
+ }}
328
+
329
+ .table th {{
330
+ background-color: #e9ecef;
331
+ font-weight: 600;
332
+ }}
333
+
334
+ .pipeline-name {{
335
+ font-weight: bold;
336
+ color: #495057;
337
+ }}
338
+
339
+ .score {{
340
+ padding: 4px 8px;
341
+ border-radius: 4px;
342
+ font-weight: bold;
343
+ color: white;
344
+ }}
345
+
346
+ .score-high {{ background-color: #28a745; }}
347
+ .score-medium {{ background-color: #ffc107; color: #212529; }}
348
+ .score-low {{ background-color: #dc3545; }}
349
+
350
+ .chart-container {{
351
+ margin: 2rem 0;
352
+ text-align: center;
353
+ }}
354
+
355
+ .timestamp {{
356
+ color: #6c757d;
357
+ font-size: 0.9rem;
358
+ }}
359
+ </style>
360
+ </head>
361
+ <body>
362
+ <div class="header">
363
+ <h1>🚀 RAG Pipeline Evaluation Report</h1>
364
+ <p>Comprehensive comparison of GraphRAG vs Traditional RAG approaches</p>
365
+ <p class="timestamp">Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
366
+ </div>
367
+
368
+ <div class="section">
369
+ <h2>📊 Executive Summary</h2>
370
+ {summary_stats}
371
+ </div>
372
+
373
+ <div class="section">
374
+ <h2>🕸️ RAGAS Metrics Comparison</h2>
375
+ <p>Spider chart showing comprehensive evaluation across all 7 RAGAS metrics:</p>
376
+ <div class="chart-container">
377
+ {spider_html}
378
+ </div>
379
+ </div>
380
+
381
+ <div class="section">
382
+ <h2>⚡ Performance Dashboard</h2>
383
+ <p>Multi-dimensional performance analysis including timing, throughput, and resource usage:</p>
384
+ <div class="chart-container">
385
+ {dashboard_html}
386
+ </div>
387
+ </div>
388
+
389
+ <div class="section">
390
+ <h2>📋 Detailed Results</h2>
391
+ {results_table}
392
+ </div>
393
+
394
+ <div class="section">
395
+ <h2>🔍 Key Insights</h2>
396
+ <div class="metric-card">
397
+ <h4>Best Overall Performance</h4>
398
+ <p>Based on RAGAS metrics and performance data analysis.</p>
399
+ </div>
400
+
401
+ <div class="metric-card">
402
+ <h4>GraphRAG Advantages</h4>
403
+ <p>Knowledge graph-based retrieval shows improvements in context precision and answer correctness.</p>
404
+ </div>
405
+
406
+ <div class="metric-card">
407
+ <h4>Performance Trade-offs</h4>
408
+ <p>Analysis of computational cost vs. quality improvements across different pipeline approaches.</p>
409
+ </div>
410
+ </div>
411
+ </body>
412
+ </html>
413
+ """
414
+ return html_template
415
+
416
+ def _calculate_summary_stats(self, results: List[EvaluationResults]) -> str:
417
+ """Calculate and format summary statistics"""
418
+
419
+ stats_html = ""
420
+
421
+ for result in results:
422
+ avg_ragas = np.mean(list(result.ragas_metrics.values()))
423
+ throughput = result.performance_metrics.get("throughput", 0)
424
+
425
+ stats_html += f"""
426
+ <div class="metric-card">
427
+ <h4>{result.pipeline_name}</h4>
428
+ <p><strong>Average RAGAS Score:</strong> {avg_ragas:.3f}</p>
429
+ <p><strong>Throughput:</strong> {throughput:.2f} queries/sec</p>
430
+ </div>
431
+ """
432
+
433
+ return stats_html
434
+
435
+ def _generate_results_table(self, results: List[EvaluationResults]) -> str:
436
+ """Generate detailed results table"""
437
+
438
+ table_html = """
439
+ <table class="table">
440
+ <thead>
441
+ <tr>
442
+ <th>Pipeline</th>
443
+ <th>Faithfulness</th>
444
+ <th>Answer Relevancy</th>
445
+ <th>Context Precision</th>
446
+ <th>Context Recall</th>
447
+ <th>Answer Correctness</th>
448
+ <th>Throughput</th>
449
+ </tr>
450
+ </thead>
451
+ <tbody>
452
+ """
453
+
454
+ for result in results:
455
+ faithfulness = result.ragas_metrics.get("faithfulness", 0)
456
+ answer_relevancy = result.ragas_metrics.get("answer_relevancy", 0)
457
+ context_precision = result.ragas_metrics.get("context_precision", 0)
458
+ context_recall = result.ragas_metrics.get("context_recall", 0)
459
+ answer_correctness = result.ragas_metrics.get("answer_correctness", 0)
460
+ throughput = result.performance_metrics.get("throughput", 0)
461
+
462
+ table_html += f"""
463
+ <tr>
464
+ <td class="pipeline-name">{result.pipeline_name}</td>
465
+ <td><span class="score {self._get_score_class(faithfulness)}">{faithfulness:.3f}</span></td>
466
+ <td><span class="score {self._get_score_class(answer_relevancy)}">{answer_relevancy:.3f}</span></td>
467
+ <td><span class="score {self._get_score_class(context_precision)}">{context_precision:.3f}</span></td>
468
+ <td><span class="score {self._get_score_class(context_recall)}">{context_recall:.3f}</span></td>
469
+ <td><span class="score {self._get_score_class(answer_correctness)}">{answer_correctness:.3f}</span></td>
470
+ <td>{throughput:.2f}</td>
471
+ </tr>
472
+ """
473
+
474
+ table_html += """
475
+ </tbody>
476
+ </table>
477
+ """
478
+
479
+ return table_html
480
+
481
+ def _get_score_class(self, score: float) -> str:
482
+ """Get CSS class based on score value"""
483
+ if score >= 0.8:
484
+ return "score-high"
485
+ elif score >= 0.6:
486
+ return "score-medium"
487
+ else:
488
+ return "score-low"
489
+
490
+
491
+ class VisualizationEngine:
492
+ """Main visualization engine coordinator"""
493
+
494
+ def __init__(self):
495
+ self.html_generator = HTMLReportGenerator()
496
+ self.spider_generator = SpiderChartGenerator()
497
+ self.dashboard_generator = PerformanceDashboard()
498
+
499
+ def create_evaluation_report(
500
+ self,
501
+ results: List[EvaluationResults],
502
+ output_dir: str = "outputs/visualizations",
503
+ ) -> str:
504
+ """Create comprehensive evaluation report"""
505
+
506
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
507
+ output_path = f"{output_dir}/evaluation_report_{timestamp}.html"
508
+
509
+ report_path = self.html_generator.generate_report(results, output_path)
510
+
511
+ logger.info(f"✅ Evaluation report created: {report_path}")
512
+ return report_path
513
+
514
+ def create_demo_report(self) -> str:
515
+ """Create demo report with sample data"""
516
+
517
+ # Sample data for demonstration
518
+ demo_results = [
519
+ EvaluationResults(
520
+ pipeline_name="GraphRAG",
521
+ ragas_metrics={
522
+ "faithfulness": 0.85,
523
+ "answer_relevancy": 0.82,
524
+ "context_precision": 0.88,
525
+ "context_recall": 0.79,
526
+ "answer_correctness": 0.84,
527
+ "answer_similarity": 0.81,
528
+ "context_utilization": 0.86,
529
+ },
530
+ performance_metrics={
531
+ "throughput": 12.5,
532
+ "success_rate": 0.95,
533
+ "memory_usage_mb": [450, 480, 520, 490, 510],
534
+ },
535
+ timing_data={"response_times": [2.1, 2.3, 1.9, 2.5, 2.0, 2.2, 1.8]},
536
+ metadata={},
537
+ ),
538
+ EvaluationResults(
539
+ pipeline_name="BasicRAG",
540
+ ragas_metrics={
541
+ "faithfulness": 0.76,
542
+ "answer_relevancy": 0.78,
543
+ "context_precision": 0.72,
544
+ "context_recall": 0.85,
545
+ "answer_correctness": 0.75,
546
+ "answer_similarity": 0.79,
547
+ "context_utilization": 0.74,
548
+ },
549
+ performance_metrics={
550
+ "throughput": 18.2,
551
+ "success_rate": 0.92,
552
+ "memory_usage_mb": [320, 350, 380, 360, 340],
553
+ },
554
+ timing_data={"response_times": [1.2, 1.4, 1.1, 1.6, 1.3, 1.5, 1.0]},
555
+ metadata={},
556
+ ),
557
+ EvaluationResults(
558
+ pipeline_name="CRAG",
559
+ ragas_metrics={
560
+ "faithfulness": 0.80,
561
+ "answer_relevancy": 0.83,
562
+ "context_precision": 0.81,
563
+ "context_recall": 0.77,
564
+ "answer_correctness": 0.82,
565
+ "answer_similarity": 0.84,
566
+ "context_utilization": 0.80,
567
+ },
568
+ performance_metrics={
569
+ "throughput": 15.8,
570
+ "success_rate": 0.94,
571
+ "memory_usage_mb": [390, 420, 450, 430, 410],
572
+ },
573
+ timing_data={"response_times": [1.6, 1.8, 1.5, 2.0, 1.7, 1.9, 1.4]},
574
+ metadata={},
575
+ ),
576
+ ]
577
+
578
+ return self.create_evaluation_report(demo_results, "outputs/visualizations")
579
+
580
+
581
+ # Example usage
582
+ if __name__ == "__main__":
583
+ viz_engine = VisualizationEngine()
584
+ demo_path = viz_engine.create_demo_report()
585
+ print(f"Demo report created: {demo_path}")