CapStoneRAG10 / archived_scripts /create_architecture_diagram.py
Developer
Initial commit for HuggingFace Spaces - RAG Capstone Project with Qdrant Cloud
1d10b0a
"""Create a comprehensive architecture diagram for RAG Capstone Project."""
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
import matplotlib.lines as mlines
from matplotlib.patches import Rectangle
import numpy as np
# Create figure with larger size for detailed diagram
fig, ax = plt.subplots(1, 1, figsize=(18, 14))
ax.set_xlim(0, 20)
ax.set_ylim(0, 16)
ax.axis('off')
# Color palette
COLOR_INPUT = '#E8F4F8'
COLOR_PROCESS = '#B3E5FC'
COLOR_STORAGE = '#81D4FA'
COLOR_EVAL = '#FFE0B2'
COLOR_JUDGE = '#FFCC80'
COLOR_OUTPUT = '#C8E6C9'
COLOR_ARROW = '#424242'
COLOR_TEXT = '#212121'
def draw_box(ax, x, y, width, height, text, color, fontsize=9, bold=False):
"""Draw a rounded rectangle box with text."""
box = FancyBboxPatch(
(x - width/2, y - height/2), width, height,
boxstyle="round,pad=0.1",
edgecolor='#424242', facecolor=color, linewidth=2
)
ax.add_patch(box)
weight = 'bold' if bold else 'normal'
ax.text(x, y, text, ha='center', va='center', fontsize=fontsize,
weight=weight, color=COLOR_TEXT, wrap=True)
def draw_arrow(ax, x1, y1, x2, y2, label='', style='->', color=COLOR_ARROW, linewidth=2.5):
"""Draw an arrow between two points."""
arrow = FancyArrowPatch(
(x1, y1), (x2, y2),
arrowstyle=style, mutation_scale=25,
color=color, linewidth=linewidth
)
ax.add_patch(arrow)
if label:
mid_x, mid_y = (x1 + x2) / 2, (y1 + y2) / 2
ax.text(mid_x + 0.3, mid_y + 0.2, label, fontsize=8,
bbox=dict(boxstyle='round,pad=0.3', facecolor='white', alpha=0.8))
def draw_section_header(ax, x, y, text, color):
"""Draw a section header."""
header = Rectangle((x - 3, y - 0.3), 6, 0.6,
facecolor=color, edgecolor='#424242', linewidth=2)
ax.add_patch(header)
ax.text(x, y, text, ha='center', va='center', fontsize=11,
weight='bold', color='white')
# Title
ax.text(10, 15.2, 'RAG Capstone Project - Architecture Diagram',
ha='center', va='top', fontsize=18, weight='bold', color=COLOR_TEXT)
ax.text(10, 14.7, 'Collection Creation & TRACE Evaluation Framework',
ha='center', va='top', fontsize=12, style='italic', color='#666')
# ============================================================================
# SECTION 1: DATA INGESTION & COLLECTION CREATION (Left Side)
# ============================================================================
draw_section_header(ax, 3.5, 13.8, '1. COLLECTION CREATION', COLOR_INPUT)
# Data sources
draw_box(ax, 1.5, 12.8, 2, 0.8, 'RAGBench\nDatasets\n(15+)', COLOR_INPUT, 8, True)
draw_box(ax, 5.5, 12.8, 2, 0.8, 'User\nDocuments', COLOR_INPUT, 8, True)
# Data loading
draw_arrow(ax, 1.5, 12.4, 3.5, 11.5)
draw_arrow(ax, 5.5, 12.4, 3.5, 11.5)
draw_box(ax, 3.5, 11.1, 2.5, 0.8, 'Data Loader\n(dataset_loader.py)', COLOR_PROCESS, 9, True)
# Chunking strategies
draw_arrow(ax, 3.5, 10.7, 3.5, 9.9)
draw_section_header(ax, 3.5, 9.6, 'Chunking Strategies', '#FFD54F')
chunking_strategies = [
('Dense', 0.8),
('Sparse', 2.0),
('Hybrid', 3.2),
('Re-rank', 4.4),
('Row-based', 5.6),
('Entity', 6.8)
]
for i, (name, x_offset) in enumerate(chunking_strategies):
x = 0.5 + x_offset
draw_box(ax, x, 8.8, 1.2, 0.7, name, '#FFF9C4', 8)
if i < 3:
draw_arrow(ax, x, 8.45, x, 7.9)
else:
draw_arrow(ax, x, 8.45, x, 7.9)
# Embedding models
draw_section_header(ax, 3.5, 7.6, 'Embedding Models', '#BBDEFB')
embedding_models = [
('MPNet', 0.5),
('MiniLM', 1.5),
('BioClinical\nBERT', 2.8),
('PubMedBERT', 4.2),
('Specter', 5.4),
('Multilingual', 6.6)
]
for name, x_offset in embedding_models:
x = 0.5 + x_offset
draw_box(ax, x, 6.8, 1.1, 0.8, name, COLOR_STORAGE, 7)
draw_arrow(ax, x, 6.4, x - 0.3, 5.7, color='#1976D2')
# Vector Storage
draw_arrow(ax, 2, 5.3, 1.5, 4.5, color='#1976D2')
draw_arrow(ax, 3, 5.3, 3.5, 4.5, color='#1976D2')
draw_arrow(ax, 4, 5.3, 4, 4.5, color='#1976D2')
draw_arrow(ax, 5, 5.3, 5.5, 4.5, color='#1976D2')
draw_arrow(ax, 6, 5.3, 6.5, 4.5, color='#1976D2')
draw_arrow(ax, 7, 5.3, 7, 4.5, color='#1976D2')
draw_box(ax, 4.5, 3.8, 3.5, 1, 'ChromaDB Vector Store\n(Persistent Storage)', COLOR_STORAGE, 10, True)
draw_box(ax, 1.5, 2.5, 2.2, 0.8, 'SQLite Index\n(Metadata)', '#E0BEE7', 9)
draw_arrow(ax, 3.2, 3.4, 1.5, 2.9)
# Collection Output
draw_arrow(ax, 4.5, 3.3, 4.5, 2.4)
draw_box(ax, 4.5, 1.8, 3.5, 0.8, 'Named Collections\n(Collection Registry)', COLOR_OUTPUT, 10, True)
ax.text(4.5, 0.9, 'Ready for Chat & Evaluation', ha='center', fontsize=8, style='italic')
# ============================================================================
# SECTION 2: TRACE EVALUATION FRAMEWORK (Center)
# ============================================================================
draw_section_header(ax, 10, 13.8, '2. EVALUATION FRAMEWORK (TRACE)', COLOR_EVAL)
# Query & Response Input
draw_box(ax, 8, 12.5, 1.8, 0.8, 'User\nQuery', COLOR_INPUT, 9, True)
draw_box(ax, 12, 12.5, 1.8, 0.8, 'LLM\nResponse', COLOR_INPUT, 9, True)
draw_arrow(ax, 8, 12.1, 9.5, 11.3)
draw_arrow(ax, 12, 12.1, 10.5, 11.3)
draw_box(ax, 10, 10.9, 3.5, 0.8, 'Evaluation Input Preparation', COLOR_PROCESS, 9, True)
# TRACE Metrics (4 columns)
draw_arrow(ax, 10, 10.5, 10, 9.7)
# Create 4 TRACE metric boxes
metrics = [
('RELEVANCE\n(R)', 7.5, '#FF6B6B', 'Fraction of retrieved\ncontext relevant\nto query'),
('UTILIZATION\n(T)', 9.5, '#4ECDC4', 'Fraction of retrieved\ncontext used in\nresponse'),
('ADHERENCE\n(A)', 11.5, '#45B7D1', 'Is response fully\ngrounded in\ndocuments?'),
('COMPLETENESS\n(C)', 13.5, '#FFA07A', 'Fraction of relevant\ninfo covered by\nresponse')
]
metric_y = 9.2
for name, x, color, desc in metrics:
draw_box(ax, x, metric_y + 0.5, 1.6, 0.8, name, color, 10, True)
draw_box(ax, x, metric_y - 0.8, 1.8, 1.2, desc, '#F5F5F5', 8)
draw_arrow(ax, x, metric_y + 0.1, x, metric_y - 0.2)
# Calculation formulas
formula_y = 6.8
ax.text(7.5, formula_y + 0.3, 'R = Σ Len(Relevant)\n/ Σ Len(All Docs)',
ha='center', fontsize=7, bbox=dict(boxstyle='round,pad=0.3',
facecolor='#FFE0B2', alpha=0.7), family='monospace')
ax.text(9.5, formula_y + 0.3, 'T = Σ Len(Used)\n/ Σ Len(All Docs)',
ha='center', fontsize=7, bbox=dict(boxstyle='round,pad=0.3',
facecolor='#FFE0B2', alpha=0.7), family='monospace')
ax.text(11.5, formula_y + 0.3, 'A = Boolean\n(Hallucination\nDetection)',
ha='center', fontsize=7, bbox=dict(boxstyle='round,pad=0.3',
facecolor='#FFE0B2', alpha=0.7), family='monospace')
ax.text(13.5, formula_y + 0.3, 'C = Len(R ∩ T)\n/ Len(R)',
ha='center', fontsize=7, bbox=dict(boxstyle='round,pad=0.3',
facecolor='#FFE0B2', alpha=0.7), family='monospace')
# Arrows converging to evaluation
draw_arrow(ax, 7.5, 6.3, 9.5, 5.7, color='#E91E63')
draw_arrow(ax, 9.5, 6.3, 9.5, 5.7, color='#E91E63')
draw_arrow(ax, 11.5, 6.3, 10.5, 5.7, color='#E91E63')
draw_arrow(ax, 13.5, 6.3, 11.5, 5.7, color='#E91E63')
# ============================================================================
# SECTION 3: JUDGE - LLM-BASED EVALUATION (Right Side)
# ============================================================================
draw_section_header(ax, 15.5, 13.8, '3. JUDGE EVALUATION', COLOR_JUDGE)
# Judge component
draw_box(ax, 15.5, 11.5, 3.5, 1.2, 'GPT Labeling\nJudge\n(advanced_rag_evaluator.py)',
COLOR_JUDGE, 10, True)
draw_arrow(ax, 12.5, 11, 14, 11.5)
ax.text(12.8, 11.3, 'Retrieved\nDocs', fontsize=8, ha='center',
bbox=dict(boxstyle='round,pad=0.2', facecolor='white', alpha=0.8))
draw_arrow(ax, 13.5, 11, 14, 11.5)
ax.text(13.8, 11.3, 'Question\n& Response', fontsize=8, ha='center',
bbox=dict(boxstyle='round,pad=0.2', facecolor='white', alpha=0.8))
# Sentencizer
draw_arrow(ax, 15.5, 10.9, 15.5, 10.2)
draw_box(ax, 15.5, 9.7, 3.5, 0.8, 'DocumentSentencizer\n(Split into sentences with keys)', COLOR_PROCESS, 8)
# Prompt Generator
draw_arrow(ax, 15.5, 9.3, 15.5, 8.6)
draw_box(ax, 15.5, 8.1, 3.5, 0.8, 'GPTLabelingPromptGenerator\n(Create structured prompt)', COLOR_PROCESS, 8)
# LLM Call
draw_arrow(ax, 15.5, 7.7, 15.5, 7.0)
draw_box(ax, 15.5, 6.3, 3.2, 1, 'Groq LLM\nAPI Call\n(llm_client.py)', '#C5CAE9', 10, True)
# JSON Parsing
draw_arrow(ax, 15.5, 5.8, 15.5, 5.1)
draw_box(ax, 15.5, 4.6, 3.5, 0.8, 'JSON Response Parsing\n(Extract metrics & mapping)', COLOR_PROCESS, 8)
# Output metrics
draw_arrow(ax, 15.5, 4.2, 15.5, 3.5)
output_metrics = [
'Sentence Support Map',
'RMSE Metrics',
'AUC-ROC Metrics',
'Audit Trail'
]
draw_section_header(ax, 15.5, 3.1, 'Judge Output', COLOR_OUTPUT)
for i, metric in enumerate(output_metrics):
y = 2.5 - (i * 0.5)
draw_box(ax, 15.5, y, 3, 0.4, f'• {metric}', COLOR_OUTPUT, 8)
# ============================================================================
# SECTION 4: INTEGRATION & DATA FLOW
# ============================================================================
# Arrow from collection to evaluation
draw_arrow(ax, 6.5, 1.8, 8, 11, style='->', color='#00796B', linewidth=2)
ax.text(6.8, 6.5, 'Loaded\nCollection', fontsize=9, weight='bold', ha='center',
bbox=dict(boxstyle='round,pad=0.4', facecolor='#B2DFDB', alpha=0.9))
# Arrow from TRACE to Judge
draw_arrow(ax, 11.5, 5.3, 13.5, 6.3, style='->', color='#C62828', linewidth=2)
ax.text(11.8, 5.7, 'Metric\nCalculation', fontsize=9, weight='bold', ha='center',
bbox=dict(boxstyle='round,pad=0.4', facecolor='#FFCDD2', alpha=0.9))
# Final output
draw_arrow(ax, 15.5, 0.5, 10, -0.5)
draw_box(ax, 10, -1.2, 5, 1,
'Comprehensive Evaluation Report\n(Metrics + Audit Trail + JSON Export)',
COLOR_OUTPUT, 11, True)
# ============================================================================
# Legend and Notes
# ============================================================================
# Legend position
legend_y = -2.5
ax.text(0.5, legend_y, 'Legend:', fontsize=10, weight='bold')
legend_items = [
(COLOR_INPUT, 'Input Data'),
(COLOR_PROCESS, 'Processing'),
(COLOR_STORAGE, 'Storage'),
(COLOR_EVAL, 'Evaluation'),
(COLOR_JUDGE, 'Judge'),
(COLOR_OUTPUT, 'Output')
]
for i, (color, label) in enumerate(legend_items):
x = 0.5 + (i % 3) * 3.5
y = legend_y - 0.6 - ((i // 3) * 0.5)
rect = Rectangle((x, y - 0.15), 0.3, 0.3, facecolor=color, edgecolor='#424242')
ax.add_patch(rect)
ax.text(x + 0.5, y, label, fontsize=9, va='center')
# Key features
features_y = -4.2
ax.text(0.5, features_y, 'Key Features:', fontsize=10, weight='bold')
features = [
'✓ 6 Chunking Strategies ✓ 8 Embedding Models ✓ 15+ RAGBench Datasets',
'✓ Sentence-Level Support Mapping ✓ Hallucination Detection ✓ Complete Audit Trail'
]
for i, feature in enumerate(features):
ax.text(0.5, features_y - 0.5 - (i * 0.4), feature, fontsize=9)
plt.tight_layout()
plt.savefig('RAG_Architecture_Diagram.png', dpi=300, bbox_inches='tight',
facecolor='white', edgecolor='none')
print("✅ Architecture diagram created: RAG_Architecture_Diagram.png")
print(f"📊 Diagram size: 18x14 inches at 300 DPI")
print("📋 Includes: Collection Creation → TRACE Metrics → Judge Evaluation")
plt.close()
# ============================================================================
# Create a second detailed diagram focusing on data flow
# ============================================================================
fig2, ax2 = plt.subplots(1, 1, figsize=(16, 12))
ax2.set_xlim(0, 16)
ax2.set_ylim(0, 14)
ax2.axis('off')
# Title
ax2.text(8, 13.5, 'Detailed Data Flow: From Query to Evaluation',
ha='center', va='top', fontsize=16, weight='bold', color=COLOR_TEXT)
# Define stages
stages = [
{
'y': 12.5,
'title': '1. Query Processing',
'items': [
('User Query', 'What is COVID-19?', 1),
('Collection Selected', 'CovidQA Dataset', 6),
]
},
{
'y': 11,
'title': '2. Retrieval',
'items': [
('Vector Search', 'Query → Embeddings\n↓\nChromaDB Search', 1),
('Top-K Results', 'Retrieved 5 documents\nwith similarity scores', 6),
]
},
{
'y': 9.3,
'title': '3. Response Generation',
'items': [
('Context', 'Ranked documents\nas context', 1),
('LLM Generation', 'Groq LLM\n(llm_client.py)', 6),
('Response', 'Generated answer\ngrounded in docs', 11),
]
},
{
'y': 7.4,
'title': '4. Evaluation Setup',
'items': [
('Sentencize', 'Split docs &\nresponse into\nsentences', 1),
('Create Keys', 'doc_0_s0, doc_0_s1\nresp_s0, resp_s1...', 5),
('Generate Prompt', 'GPTLabelingPrompt\nGenerator', 10),
]
},
{
'y': 5.3,
'title': '5. Judge Evaluation',
'items': [
('LLM Prompt', 'Send prompt +\nsentencized data\nto Groq', 1),
('LLM Response', 'JSON with\nsentence mapping\n& support info', 6),
]
},
{
'y': 3.3,
'title': '6. Metric Calculation',
'items': [
('Parse JSON', 'Extract support\nmapping', 1),
('Calculate TRACE', 'R, T, A, C\nmetrics', 5),
('RMSE & AUC', 'Additional\nmetrics', 9),
]
},
{
'y': 1.3,
'title': '7. Output',
'items': [
('Report', 'JSON with all metrics\n+ audit trail', 3),
('Visualization', 'Charts & tables\nin Streamlit', 8),
('Export', 'Download results', 13),
]
}
]
# Draw stages
for stage in stages:
# Stage header
header_rect = Rectangle((0.2, stage['y'] - 0.15), 15.6, 0.3,
facecolor='#1976D2', alpha=0.8)
ax2.add_patch(header_rect)
ax2.text(0.5, stage['y'], stage['title'], fontsize=11, weight='bold',
color='white', va='center')
# Stage items
for item in stage['items']:
if len(item) == 3:
title, desc, x = item
box = FancyBboxPatch(
(x - 1.8, stage['y'] - 0.7), 3.6, 0.5,
boxstyle="round,pad=0.08",
edgecolor='#424242', facecolor='#E3F2FD', linewidth=1.5
)
ax2.add_patch(box)
ax2.text(x, stage['y'] - 0.45, f'{title}\n{desc}', ha='center', va='center',
fontsize=8, weight='bold')
# Arrow to next stage
if stage != stages[-1]:
next_y = stage['y'] - 1
arrow = FancyArrowPatch(
(8, stage['y'] - 0.85), (8, next_y + 0.15),
arrowstyle='->', mutation_scale=30,
color='#1976D2', linewidth=2.5
)
ax2.add_patch(arrow)
# Add code file references on the side
code_refs = [
('dataset_loader.py', 12.5),
('vector_store.py', 11),
('llm_client.py', 9.3),
('chunking_strategies.py\nembedding_models.py', 7.4),
('advanced_rag_evaluator.py', 5.3),
('trace_evaluator.py', 3.3),
('streamlit_app.py', 1.3),
]
for ref, y in code_refs:
ax2.text(15.2, y, ref, fontsize=7, style='italic', ha='right',
bbox=dict(boxstyle='round,pad=0.3', facecolor='#F5F5F5',
edgecolor='#757575', linewidth=1))
plt.tight_layout()
plt.savefig('RAG_Data_Flow_Diagram.png', dpi=300, bbox_inches='tight',
facecolor='white', edgecolor='none')
print("\n✅ Data flow diagram created: RAG_Data_Flow_Diagram.png")
print(f"📊 Diagram size: 16x12 inches at 300 DPI")
print("📋 Shows: 7-step data flow from query to evaluation results")
plt.close()
print("\n" + "="*60)
print("Architecture Diagrams Created Successfully!")
print("="*60)
print("\n📁 Files Generated:")
print(" 1. RAG_Architecture_Diagram.png - Full system architecture")
print(" 2. RAG_Data_Flow_Diagram.png - Detailed data flow diagram")
print("\n✨ Both diagrams are ready for presentations and documentation!")