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.
- adapters/rag_templates_bridge.py +578 -0
- common/__init__.py +1 -0
- common/batch_utils.py +294 -0
- common/config.py +58 -0
- common/connection_manager.py +242 -0
- common/connection_pool.py +445 -0
- common/database.py +141 -0
- common/database_schema_manager.py +289 -0
- common/db_init_with_indexes.py +181 -0
- common/db_vector_utils.py +181 -0
- common/environment_manager.py +220 -0
- common/huggingface_utils.py +206 -0
- common/iris_client.py +92 -0
- common/iris_connection_manager.py +411 -0
- common/iris_connection_pool.py +360 -0
- common/iris_connector.py +71 -0
- common/iris_dbapi_connector.py +323 -0
- common/iris_index_utils.py +195 -0
- common/iris_sql_utils.py +704 -0
- common/iris_stream_reader.py +166 -0
- common/llm_cache_config.py +308 -0
- common/llm_cache_iris.py +671 -0
- common/llm_cache_manager.py +911 -0
- common/utils.py +559 -0
- common/vector_sql_utils.py +584 -0
- evaluation_framework/__init__.py +66 -0
- evaluation_framework/biomedical_question_generator.py +826 -0
- evaluation_framework/comparative_analysis_system.py +1173 -0
- evaluation_framework/empirical_reporting.py +1298 -0
- evaluation_framework/evaluation_orchestrator.py +1123 -0
- evaluation_framework/execute_production_evaluation.py +382 -0
- evaluation_framework/pmc_data_pipeline.py +1332 -0
- evaluation_framework/production_evaluation_config.py +353 -0
- evaluation_framework/ragas_metrics_framework.py +1013 -0
- evaluation_framework/real_production_evaluation.py +544 -0
- evaluation_framework/run_10k_evaluation.py +175 -0
- evaluation_framework/simple_test.py +364 -0
- evaluation_framework/statistical_evaluation_methodology.py +1016 -0
- evaluation_framework/test_framework.py +281 -0
- evaluation_framework/test_iris_connectivity.py +244 -0
- evaluation_framework/test_small_scale_evaluation.py +432 -0
- evaluation_framework/true_e2e_evaluation.py +639 -0
- evaluation_framework/visualization_engine.py +585 -0
- iris_rag/__init__.py +284 -0
- iris_rag/config/default_config.yaml +295 -0
- iris_vector_rag-0.2.1.dist-info/METADATA +499 -0
- iris_vector_rag-0.2.1.dist-info/RECORD +50 -0
- iris_vector_rag-0.2.1.dist-info/WHEEL +5 -0
- iris_vector_rag-0.2.1.dist-info/entry_points.txt +2 -0
- 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}")
|