retrieve.html•14.5 kB
{% extends "base.html" %}
{% block title %}Retrieve Information - ContextMore{% endblock %}
{% block content %}
<div class="max-w-3xl mx-auto">
<div class="bg-white shadow-sm rounded-lg overflow-hidden">
<!-- Header -->
<div class="border-b border-gray-200 bg-gray-50 px-6 py-4">
<h1 class="text-xl font-semibold text-gray-900">Retrieve Information</h1>
<p class="mt-1 text-sm text-gray-500">Search through your knowledge base using natural language queries.</p>
</div>
<!-- Search Form -->
<div class="p-6">
<form id="retrieveForm" class="space-y-6">
<div class="space-y-1">
<label for="query" class="block text-sm font-medium text-gray-700">Search Query</label>
<div class="mt-1 relative rounded-md shadow-sm">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</div>
<input type="text" id="query" name="query" required
class="pl-10 block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
placeholder="What would you like to know?">
</div>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
<div class="space-y-1">
<label for="top_k" class="block text-sm font-medium text-gray-700">Number of Results</label>
<div class="mt-1 relative rounded-md shadow-sm">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
</div>
<input type="number" id="top_k" name="top_k" min="1" max="100" value="5"
class="pl-10 block w-full rounded-md border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
placeholder="Number of results">
</div>
</div>
<div class="flex items-center space-x-3 sm:pt-6">
<div class="relative flex items-start">
<div class="flex items-center h-5">
<input type="checkbox" id="group_by_doc" name="group_by_doc" checked
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
</div>
<div class="ml-3 text-sm">
<label for="group_by_doc" class="font-medium text-gray-700">Group by Document</label>
<p class="text-gray-500">Combine results from the same source</p>
</div>
</div>
</div>
</div>
<div>
<button type="submit"
class="w-full inline-flex justify-center items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
<svg class="h-4 w-4 mr-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
Search Knowledge Base
</button>
</div>
</form>
<!-- Results Section -->
<div id="results" class="mt-8">
{% if results %}
<div class="border-t border-gray-200 pt-8">
<h2 class="text-lg font-medium text-gray-900 mb-4">Search Results</h2>
<div class="space-y-6">
{% for result in results %}
<div class="bg-gray-50 rounded-lg shadow-sm border border-gray-200 overflow-hidden">
<div class="p-4">
<p class="text-gray-900">{{ result.text }}</p>
<p class="text-sm text-gray-500 mt-2">Relevance Score: {{ "%.4f"|format(result.score) }}</p>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<script>
document.getElementById('retrieveForm').addEventListener('submit', async (e) => {
e.preventDefault();
const query = document.getElementById('query').value;
const top_k = document.getElementById('top_k').value;
const group_by_doc = document.getElementById('group_by_doc').checked;
const resultsDiv = document.getElementById('results');
// Show loading state
resultsDiv.innerHTML = `
<div class="flex items-center justify-center py-12">
<svg class="animate-spin h-8 w-8 text-blue-600" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</div>
`;
try {
const response = await fetch('/retrieve', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query,
top_k: parseInt(top_k),
group_by_doc
}),
});
const data = await response.json();
if (response.ok) {
if (data.results && data.results.length > 0) {
resultsDiv.innerHTML = `
<div class="border-t border-gray-200 pt-8">
<div class="flex items-center justify-between mb-6">
<h2 class="text-lg font-medium text-gray-900">Search Results</h2>
<span class="text-sm text-gray-500">${data.results.length} results found</span>
</div>
<div class="space-y-6">
${data.results.map(result => {
if (result.chunks) {
// Grouped results (by document)
return `
<div class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
<div class="bg-gray-50 px-4 py-3 border-b border-gray-200">
<div class="flex items-center justify-between">
<div class="flex-1 min-w-0">
<h3 class="text-sm font-medium text-gray-900">${result.call_name}</h3>
<a href="${result.url}" class="mt-1 text-xs text-blue-600 hover:text-blue-500 truncate block" target="_blank">
${result.url}
</a>
</div>
<div class="ml-4">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
Score: ${result.avg_score.toFixed(4)}
</span>
</div>
</div>
</div>
<div class="divide-y divide-gray-200">
${result.chunks.map(chunk => `
<div class="p-4">
<p class="text-sm text-gray-900">${chunk.text}</p>
<p class="mt-1 text-xs text-gray-500">Relevance: ${chunk.score.toFixed(4)}</p>
</div>
`).join('')}
</div>
</div>
`;
} else {
// Individual chunks
return `
<div class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
<div class="bg-gray-50 px-4 py-3 border-b border-gray-200">
<div class="flex items-center justify-between">
<div class="flex-1 min-w-0">
<h3 class="text-sm font-medium text-gray-900">${result.call_name}</h3>
<a href="${result.url}" class="mt-1 text-xs text-blue-600 hover:text-blue-500 truncate block" target="_blank">
${result.url}
</a>
</div>
<div class="ml-4">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
Score: ${result.score.toFixed(4)}
</span>
</div>
</div>
</div>
<div class="p-4">
<p class="text-sm text-gray-900">${result.text}</p>
</div>
</div>
`;
}
}).join('')}
</div>
</div>
`;
} else {
resultsDiv.innerHTML = `
<div class="rounded-md bg-yellow-50 p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-yellow-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-yellow-800">No results found</h3>
<p class="mt-2 text-sm text-yellow-700">Try adjusting your search query or adding more documents to your knowledge base.</p>
</div>
</div>
</div>
`;
}
} else {
resultsDiv.innerHTML = `
<div class="rounded-md bg-red-50 p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-red-800">Error</h3>
<p class="mt-2 text-sm text-red-700">${data.detail}</p>
</div>
</div>
</div>
`;
}
} catch (error) {
resultsDiv.innerHTML = `
<div class="rounded-md bg-red-50 p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-red-800">Error</h3>
<p class="mt-2 text-sm text-red-700">${error.message}</p>
</div>
</div>
</div>
`;
}
});
</script>
{% endblock %}