jackspace / index.html
Kobish44's picture
Add 3 files
a256a8d verified
Raw
History Blame Contribute Delete
33.7 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RAG Chunking Calculator</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: {
50: '#f5f3ff',
100: '#ede9fe',
200: '#ddd6fe',
300: '#c4b5fd',
400: '#a78bfa',
500: '#8b5cf6',
600: '#7c3aed',
700: '#6d28d9',
800: '#5b21b6',
900: '#4c1d95',
},
secondary: {
50: '#fffbeb',
100: '#fef3c7',
200: '#fde68a',
300: '#fcd34d',
400: '#fbbf24',
500: '#f59e0b',
600: '#d97706',
700: '#b45309',
800: '#92400e',
900: '#78350f',
}
}
}
}
}
</script>
<style>
.chunk-highlight {
background-color: rgba(167, 139, 250, 0.15);
border-left: 3px solid rgb(139, 92, 246);
padding: 12px 16px;
margin: 8px 0;
border-radius: 6px;
transition: all 0.2s ease;
}
.chunk-highlight:hover {
background-color: rgba(167, 139, 250, 0.25);
transform: translateX(2px);
}
.overlap-highlight {
background-color: rgba(251, 191, 36, 0.15);
border-left: 3px solid rgb(245, 158, 11);
padding: 12px 16px;
margin: 8px 0;
border-radius: 6px;
transition: all 0.2s ease;
}
.overlap-highlight:hover {
background-color: rgba(251, 191, 36, 0.25);
transform: translateX(2px);
}
.slider-thumb::-webkit-slider-thumb {
-webkit-appearance: none;
width: 20px;
height: 20px;
border-radius: 50%;
background: #8b5cf6;
cursor: pointer;
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
transition: all 0.2s ease;
}
.slider-thumb::-webkit-slider-thumb:hover {
transform: scale(1.1);
box-shadow: 0 3px 8px rgba(0,0,0,0.3);
}
.slider-thumb::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 50%;
background: #8b5cf6;
cursor: pointer;
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
transition: all 0.2s ease;
}
.slider-thumb::-moz-range-thumb:hover {
transform: scale(1.1);
box-shadow: 0 3px 8px rgba(0,0,0,0.3);
}
.text-area-container {
position: relative;
}
.word-counter {
position: absolute;
bottom: 12px;
right: 12px;
background: rgba(255,255,255,0.9);
padding: 3px 10px;
border-radius: 12px;
font-size: 12px;
color: #4b5563;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.stat-card {
transition: all 0.3s ease;
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltip-text {
visibility: hidden;
width: 200px;
background-color: #333;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 8px;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -100px;
opacity: 0;
transition: opacity 0.3s;
font-size: 13px;
}
.tooltip:hover .tooltip-text {
visibility: visible;
opacity: 1;
}
.fade-in {
animation: fadeIn 0.3s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.scrollbar-custom::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.scrollbar-custom::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
.scrollbar-custom::-webkit-scrollbar-thumb {
background: #c4b5fd;
border-radius: 10px;
}
.scrollbar-custom::-webkit-scrollbar-thumb:hover {
background: #8b5cf6;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen font-sans antialiased">
<div class="container mx-auto px-4 py-8 max-w-6xl">
<!-- Header Section -->
<div class="text-center mb-10">
<div class="inline-flex items-center justify-center bg-gradient-to-r from-primary-500 to-secondary-500 text-white px-6 py-3 rounded-full shadow-md mb-4">
<i class="fas fa-brain mr-2"></i>
<span class="font-bold">RAG CHUNKING CALCULATOR</span>
</div>
<h1 class="text-4xl font-bold text-gray-800 mb-3">Optimize Your Document Chunks</h1>
<p class="text-gray-600 max-w-2xl mx-auto text-lg">
Enhance your Retrieval-Augmented Generation pipeline by experimenting with different chunking strategies.
</p>
</div>
<!-- Input Section -->
<div class="bg-white rounded-xl shadow-lg overflow-hidden mb-8 border border-gray-100">
<div class="p-6 bg-gradient-to-r from-primary-50 to-secondary-50 border-b border-gray-200">
<div class="flex items-center mb-2">
<div class="bg-primary-500 text-white p-2 rounded-lg mr-3">
<i class="fas fa-align-left"></i>
</div>
<h2 class="text-xl font-semibold text-gray-800">Input Text</h2>
</div>
<p class="text-sm text-gray-500 ml-12">Paste your document content below (max 1000 words)</p>
</div>
<div class="p-6">
<div class="text-area-container">
<textarea id="inputText" rows="8" class="w-full p-4 border border-gray-200 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500 transition-all placeholder-gray-400" placeholder="Example: Retrieval-Augmented Generation (RAG) combines pre-trained language models with information retrieval systems to produce more accurate and contextually relevant responses..."></textarea>
<div class="word-counter">
<span id="wordCount">0</span>/1000 words
</div>
</div>
<div class="mt-4 flex items-center text-sm text-gray-500">
<i class="fas fa-info-circle mr-2 text-primary-500"></i>
<span>For best results, use well-structured text with complete sentences.</span>
</div>
</div>
</div>
<!-- Controls Section -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
<!-- Chunk Size Card -->
<div class="bg-white rounded-xl shadow-md overflow-hidden border border-gray-100 stat-card">
<div class="p-6">
<div class="flex items-center mb-4">
<div class="bg-primary-100 text-primary-600 p-2 rounded-lg mr-3">
<i class="fas fa-ruler"></i>
</div>
<div>
<h2 class="text-lg font-semibold text-gray-800">Chunk Size</h2>
<p class="text-sm text-gray-500">Words per chunk</p>
</div>
</div>
<div class="mb-2">
<input type="range" id="chunkSize" min="50" max="500" value="200" step="10" class="w-full slider-thumb">
<div class="flex justify-between text-sm text-gray-600 mt-1">
<span>50</span>
<span class="font-medium text-primary-600" id="chunkSizeValue">200</span>
<span>500</span>
</div>
</div>
<div class="flex items-center text-sm text-gray-500">
<i class="fas fa-info-circle mr-2 text-primary-500"></i>
<span>Larger chunks provide more context but may be less precise.</span>
</div>
</div>
</div>
<!-- Overlap Card -->
<div class="bg-white rounded-xl shadow-md overflow-hidden border border-gray-100 stat-card">
<div class="p-6">
<div class="flex items-center mb-4">
<div class="bg-secondary-100 text-secondary-600 p-2 rounded-lg mr-3">
<i class="fas fa-layer-group"></i>
</div>
<div>
<h2 class="text-lg font-semibold text-gray-800">Overlap</h2>
<p class="text-sm text-gray-500">Words between chunks</p>
</div>
</div>
<div class="mb-2">
<input type="range" id="overlapSize" min="0" max="100" value="20" step="5" class="w-full slider-thumb">
<div class="flex justify-between text-sm text-gray-600 mt-1">
<span>0</span>
<span class="font-medium text-secondary-600" id="overlapSizeValue">20</span>
<span>100</span>
</div>
</div>
<div class="flex items-center text-sm text-gray-500">
<i class="fas fa-info-circle mr-2 text-secondary-500"></i>
<span>Higher overlap reduces context loss but increases redundancy.</span>
</div>
</div>
</div>
<!-- Statistics Card -->
<div class="bg-white rounded-xl shadow-md overflow-hidden border border-gray-100 stat-card">
<div class="p-6">
<div class="flex items-center mb-4">
<div class="bg-purple-100 text-purple-600 p-2 rounded-lg mr-3">
<i class="fas fa-chart-pie"></i>
</div>
<div>
<h2 class="text-lg font-semibold text-gray-800">Statistics</h2>
<p class="text-sm text-gray-500">Current configuration</p>
</div>
</div>
<div class="space-y-3">
<div class="flex justify-between items-center">
<div class="flex items-center">
<span class="text-gray-600">Total Chunks:</span>
<div class="tooltip ml-1">
<i class="fas fa-question-circle text-gray-400 text-xs"></i>
<span class="tooltip-text">Total number of chunks generated from your text</span>
</div>
</div>
<span id="totalChunks" class="font-medium text-gray-800 bg-primary-50 px-3 py-1 rounded-full">0</span>
</div>
<div class="flex justify-between items-center">
<div class="flex items-center">
<span class="text-gray-600">Avg Chunk Size:</span>
<div class="tooltip ml-1">
<i class="fas fa-question-circle text-gray-400 text-xs"></i>
<span class="tooltip-text">Average word count per chunk</span>
</div>
</div>
<span id="avgChunkSize" class="font-medium text-gray-800 bg-primary-50 px-3 py-1 rounded-full">0</span>
</div>
<div class="flex justify-between items-center">
<div class="flex items-center">
<span class="text-gray-600">Redundancy:</span>
<div class="tooltip ml-1">
<i class="fas fa-question-circle text-gray-400 text-xs"></i>
<span class="tooltip-text">Percentage of repeated words due to overlap</span>
</div>
</div>
<span id="redundancy" class="font-medium text-gray-800 bg-primary-50 px-3 py-1 rounded-full">0%</span>
</div>
</div>
</div>
</div>
</div>
<!-- Results Section -->
<div class="bg-white rounded-xl shadow-lg overflow-hidden border border-gray-100 mb-8">
<div class="p-6 border-b border-gray-200 bg-gradient-to-r from-primary-50 to-secondary-50">
<div class="flex flex-col md:flex-row md:items-center md:justify-between mb-2">
<div class="flex items-center mb-3 md:mb-0">
<div class="bg-primary-500 text-white p-2 rounded-lg mr-3">
<i class="fas fa-cubes"></i>
</div>
<h2 class="text-xl font-semibold text-gray-800">Generated Chunks</h2>
</div>
<div class="flex items-center space-x-4">
<div class="flex items-center">
<span class="w-4 h-4 rounded-full bg-primary-300 mr-2"></span>
<span class="text-sm">Chunk</span>
</div>
<div class="flex items-center">
<span class="w-4 h-4 rounded-full bg-secondary-300 mr-2"></span>
<span class="text-sm">Overlap</span>
</div>
<button id="copyAllBtn" class="text-sm bg-gray-100 hover:bg-gray-200 text-gray-700 px-3 py-1 rounded-lg transition-all flex items-center">
<i class="fas fa-copy mr-1"></i> Copy All
</button>
</div>
</div>
<p class="text-sm text-gray-500 ml-12">Preview how your document will be split based on current settings</p>
</div>
<div id="chunksContainer" class="border-b border-gray-200 p-6 bg-gray-50 max-h-[500px] overflow-y-auto scrollbar-custom">
<div class="text-center text-gray-500 py-10">
<i class="fas fa-cubes text-4xl mb-3 text-gray-300"></i>
<h3 class="text-lg font-medium text-gray-400 mb-1">No chunks generated yet</h3>
<p class="max-w-md mx-auto">Paste your text above and adjust the sliders to see how it will be divided into chunks</p>
</div>
</div>
<div class="p-4 bg-gray-50 border-t border-gray-200 flex justify-between items-center">
<div class="text-sm text-gray-500">
<span id="visibleChunks">0</span> of <span id="totalVisibleChunks">0</span> chunks displayed
</div>
<div class="flex space-x-2">
<button id="prevChunkBtn" class="px-3 py-1 bg-gray-200 rounded-lg text-gray-700 disabled:opacity-50" disabled>
<i class="fas fa-chevron-left"></i>
</button>
<button id="nextChunkBtn" class="px-3 py-1 bg-gray-200 rounded-lg text-gray-700 disabled:opacity-50" disabled>
<i class="fas fa-chevron-right"></i>
</button>
</div>
</div>
</div>
<!-- Tips Section -->
<div class="bg-gradient-to-r from-primary-50 to-secondary-50 rounded-xl p-6 shadow-sm border border-gray-200">
<div class="flex items-center mb-4">
<div class="bg-gradient-to-r from-primary-500 to-secondary-500 text-white p-2 rounded-lg mr-3">
<i class="fas fa-lightbulb"></i>
</div>
<h3 class="text-xl font-semibold text-gray-800">Chunking Strategy Recommendations</h3>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-white p-5 rounded-lg shadow-sm border border-gray-100 hover:shadow-md transition-all">
<div class="flex items-start mb-2">
<div class="bg-primary-100 text-primary-600 p-2 rounded-lg mr-3">
<i class="fas fa-bars"></i>
</div>
<div>
<div class="font-medium text-primary-700 mb-1">Small Chunks (50-150 words)</div>
<p class="text-sm text-gray-600">Best for precise retrieval of facts or when working with short documents like FAQs or product descriptions. Use overlap of 10-20 words.</p>
</div>
</div>
</div>
<div class="bg-white p-5 rounded-lg shadow-sm border border-gray-100 hover:shadow-md transition-all">
<div class="flex items-start mb-2">
<div class="bg-primary-100 text-primary-600 p-2 rounded-lg mr-3">
<i class="fas fa-th-large"></i>
</div>
<div>
<div class="font-medium text-primary-700 mb-1">Medium Chunks (150-300 words)</div>
<p class="text-sm text-gray-600">Good balance for most documents, providing enough context while maintaining retrieval precision. Use overlap of 20-40 words.</p>
</div>
</div>
</div>
<div class="bg-white p-5 rounded-lg shadow-sm border border-gray-100 hover:shadow-md transition-all">
<div class="flex items-start mb-2">
<div class="bg-primary-100 text-primary-600 p-2 rounded-lg mr-3">
<i class="fas fa-th"></i>
</div>
<div>
<div class="font-medium text-primary-700 mb-1">Large Chunks (300-500 words)</div>
<p class="text-sm text-gray-600">Useful for complex topics requiring more context, like research papers or technical documentation. Use overlap of 40-60 words.</p>
</div>
</div>
</div>
<div class="bg-white p-5 rounded-lg shadow-sm border border-gray-100 hover:shadow-md transition-all">
<div class="flex items-start mb-2">
<div class="bg-secondary-100 text-secondary-600 p-2 rounded-lg mr-3">
<i class="fas fa-random"></i>
</div>
<div>
<div class="font-medium text-secondary-700 mb-1">Advanced Strategies</div>
<p class="text-sm text-gray-600">Consider semantic chunking for complex documents, or hybrid approaches combining fixed-size chunks with paragraph boundaries.</p>
</div>
</div>
</div>
</div>
</div>
<!-- Footer -->
<div class="mt-10 text-center text-gray-500 text-sm">
<p>RAG Chunking Calculator v1.0 | Designed for AI pipeline optimization</p>
<p class="mt-1">Use this tool to experiment with different chunking strategies for your Retrieval-Augmented Generation systems</p>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const inputText = document.getElementById('inputText');
const chunkSizeSlider = document.getElementById('chunkSize');
const overlapSizeSlider = document.getElementById('overlapSize');
const chunkSizeValue = document.getElementById('chunkSizeValue');
const overlapSizeValue = document.getElementById('overlapSizeValue');
const chunksContainer = document.getElementById('chunksContainer');
const wordCount = document.getElementById('wordCount');
const totalChunks = document.getElementById('totalChunks');
const avgChunkSize = document.getElementById('avgChunkSize');
const redundancy = document.getElementById('redundancy');
const copyAllBtn = document.getElementById('copyAllBtn');
const prevChunkBtn = document.getElementById('prevChunkBtn');
const nextChunkBtn = document.getElementById('nextChunkBtn');
const visibleChunks = document.getElementById('visibleChunks');
const totalVisibleChunks = document.getElementById('totalVisibleChunks');
// State variables
let currentChunks = [];
let currentVisibleIndex = 0;
const chunksPerPage = 3;
// Initialize
updateSliderValues();
// Event Listeners
chunkSizeSlider.addEventListener('input', updateChunking);
overlapSizeSlider.addEventListener('input', updateChunking);
inputText.addEventListener('input', updateChunking);
copyAllBtn.addEventListener('click', copyAllChunks);
prevChunkBtn.addEventListener('click', showPreviousChunks);
nextChunkBtn.addEventListener('click', showNextChunks);
// Functions
function updateSliderValues() {
chunkSizeValue.textContent = chunkSizeSlider.value;
overlapSizeValue.textContent = overlapSizeSlider.value;
}
function updateWordCount() {
const text = inputText.value.trim();
const words = text ? text.split(/\s+/).filter(word => word.length > 0).length : 0;
wordCount.textContent = words;
// Limit to 1000 words
if (words > 1000) {
wordCount.classList.add('text-red-500');
// Truncate the text to 1000 words
const truncatedText = text.split(/\s+/).slice(0, 1000).join(' ');
inputText.value = truncatedText;
setTimeout(() => {
wordCount.textContent = '1000';
}, 0);
} else {
wordCount.classList.remove('text-red-500');
}
}
function updateChunking() {
updateSliderValues();
updateWordCount();
const text = inputText.value.trim();
if (!text) {
chunksContainer.innerHTML = `
<div class="text-center text-gray-500 py-10">
<i class="fas fa-cubes text-4xl mb-3 text-gray-300"></i>
<h3 class="text-lg font-medium text-gray-400 mb-1">No chunks generated yet</h3>
<p class="max-w-md mx-auto">Paste your text above and adjust the sliders to see how it will be divided into chunks</p>
</div>
`;
totalChunks.textContent = '0';
avgChunkSize.textContent = '0';
redundancy.textContent = '0%';
visibleChunks.textContent = '0';
totalVisibleChunks.textContent = '0';
prevChunkBtn.disabled = true;
nextChunkBtn.disabled = true;
currentChunks = [];
return;
}
const chunkSize = parseInt(chunkSizeSlider.value);
const overlap = parseInt(overlapSizeSlider.value);
// Split text into words
const words = text.split(/\s+/).filter(word => word.length > 0);
// Generate chunks
const chunks = [];
let start = 0;
while (start < words.length) {
const end = Math.min(start + chunkSize, words.length);
chunks.push({
start,
end,
text: words.slice(start, end).join(' ')
});
// Move forward by chunk size minus overlap
start += (chunkSize - overlap);
}
// Update statistics
totalChunks.textContent = chunks.length;
const avgSize = chunks.reduce((sum, chunk) => sum + (chunk.end - chunk.start), 0) / chunks.length;
avgChunkSize.textContent = Math.round(avgSize);
const totalWords = words.length;
const uniqueWords = new Set(words).size;
const redundancyPercent = Math.round(((totalWords - uniqueWords) / totalWords) * 100);
redundancy.textContent = `${redundancyPercent}%`;
// Store chunks and display
currentChunks = chunks;
currentVisibleIndex = 0;
displayVisibleChunks();
}
function displayVisibleChunks() {
if (currentChunks.length === 0) {
chunksContainer.innerHTML = '<p class="text-gray-500">No chunks generated.</p>';
return;
}
const startIdx = currentVisibleIndex;
const endIdx = Math.min(currentVisibleIndex + chunksPerPage, currentChunks.length);
const visibleChunksArray = currentChunks.slice(startIdx, endIdx);
chunksContainer.innerHTML = '';
visibleChunksArray.forEach((chunk, index) => {
const chunkElement = document.createElement('div');
chunkElement.className = 'mb-8 fade-in';
// Chunk header
const header = document.createElement('div');
header.className = 'flex justify-between items-center mb-3 px-2';
const title = document.createElement('span');
title.className = 'font-medium text-primary-700 flex items-center';
const chunkNumber = document.createElement('span');
chunkNumber.className = 'bg-primary-500 text-white text-sm px-2 py-1 rounded mr-2';
chunkNumber.textContent = `#${startIdx + index + 1}`;
title.appendChild(chunkNumber);
title.appendChild(document.createTextNode(` Words ${chunk.start + 1}-${chunk.end}`));
const wordCount = document.createElement('span');
wordCount.className = 'text-sm bg-primary-100 text-primary-800 px-3 py-1 rounded-full';
wordCount.textContent = `${chunk.end - chunk.start} words`;
header.appendChild(title);
header.appendChild(wordCount);
chunkElement.appendChild(header);
// Chunk content
const content = document.createElement('div');
content.className = 'bg-white p-5 rounded-lg border border-gray-200 shadow-sm hover:shadow-md transition-all';
// Highlight the current chunk
const chunkText = document.createElement('div');
chunkText.className = 'chunk-highlight';
chunkText.textContent = chunk.text;
content.appendChild(chunkText);
// If there's overlap with the next chunk, show it
const globalIndex = startIdx + index;
if (globalIndex < currentChunks.length - 1 && overlapSizeSlider.value > 0) {
const nextChunk = currentChunks[globalIndex + 1];
const overlapStart = nextChunk.start;
const overlapEnd = Math.min(chunk.end, nextChunk.end);
if (overlapStart < overlapEnd) {
const overlapText = currentChunks[0].text.split(/\s+/).slice(overlapStart, overlapEnd).join(' ');
const overlapLabel = document.createElement('div');
overlapLabel.className = 'text-xs text-secondary-700 mt-4 mb-2 font-medium flex items-center';
overlapLabel.innerHTML = `<i class="fas fa-link mr-1"></i> Overlap with Chunk #${globalIndex + 2}:`;
content.appendChild(overlapLabel);
const overlapElement = document.createElement('div');
overlapElement.className = 'overlap-highlight';
overlapElement.textContent = overlapText;
content.appendChild(overlapElement);
}
}
chunkElement.appendChild(content);
chunksContainer.appendChild(chunkElement);
});
// Update pagination controls
visibleChunks.textContent = `${startIdx + 1}-${endIdx}`;
totalVisibleChunks.textContent = currentChunks.length;
prevChunkBtn.disabled = currentVisibleIndex === 0;
nextChunkBtn.disabled = endIdx >= currentChunks.length;
}
function showPreviousChunks() {
if (currentVisibleIndex > 0) {
currentVisibleIndex = Math.max(0, currentVisibleIndex - chunksPerPage);
displayVisibleChunks();
}
}
function showNextChunks() {
if (currentVisibleIndex + chunksPerPage < currentChunks.length) {
currentVisibleIndex += chunksPerPage;
displayVisibleChunks();
}
}
function copyAllChunks() {
if (currentChunks.length === 0) return;
const chunksText = currentChunks.map((chunk, index) => {
return `=== Chunk ${index + 1} (Words ${chunk.start + 1}-${chunk.end}) ===\n${chunk.text}\n`;
}).join('\n');
navigator.clipboard.writeText(chunksText).then(() => {
// Show feedback
const originalText = copyAllBtn.innerHTML;
copyAllBtn.innerHTML = '<i class="fas fa-check mr-1"></i> Copied!';
copyAllBtn.classList.remove('bg-gray-100', 'hover:bg-gray-200');
copyAllBtn.classList.add('bg-green-100', 'text-green-700');
setTimeout(() => {
copyAllBtn.innerHTML = originalText;
copyAllBtn.classList.remove('bg-green-100', 'text-green-700');
copyAllBtn.classList.add('bg-gray-100', 'hover:bg-gray-200');
}, 2000);
});
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Kobish44/jackspace" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>