import React, { useState } from 'react'; import { Search, Zap, Database, Loader2, ArrowRight } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Badge } from '@/components/ui/badge'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Separator } from '@/components/ui/separator'; interface VectorSearchResult { id: string; title: string; content: string; source: string; relevanceScore: number; rank: number; snippet: string; } interface SearchResults { success: boolean; query: string; indexName: string; results: VectorSearchResult[]; totalFound: number; searchTime?: number; error?: string; } export default function VectorSearch() { const [query, setQuery] = useState(''); const [indexName, setIndexName] = useState('research_papers_clean_v2'); const [maxResults, setMaxResults] = useState(10); const [isSearching, setIsSearching] = useState(false); const [searchResults, setSearchResults] = useState(null); const [comparisonMode, setComparisonMode] = useState(false); const [traditionalResults, setTraditionalResults] = useState(null); const handleVectorSearch = async () => { if (!query.trim()) return; setIsSearching(true); try { const response = await fetch('/api/documents/search/vector', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: query.trim(), indexName, maxResults }) }); const result = await response.json(); setSearchResults(result); // If comparison mode is enabled, also run traditional search if (comparisonMode) { await runTraditionalSearch(); } } catch (error) { console.error('Vector search error:', error); setSearchResults({ success: false, query: query.trim(), indexName, results: [], totalFound: 0, error: error instanceof Error ? error.message : 'Search failed' }); } finally { setIsSearching(false); } }; const runTraditionalSearch = async () => { try { const response = await fetch('/api/search', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: query.trim(), searchType: 'keyword', limit: maxResults, offset: 0 }) }); const result = await response.json(); setTraditionalResults(result); } catch (error) { console.error('Traditional search error:', error); setTraditionalResults(null); } }; const handleKeyPress = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !isSearching) { handleVectorSearch(); } }; const formatRelevanceScore = (score: number): string => { return (score * 100).toFixed(1) + '%'; }; const getScoreColor = (score: number): string => { if (score >= 0.8) return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'; if (score >= 0.6) return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200'; if (score >= 0.4) return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200'; return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'; }; return (
{/* Search Interface */} Vector Search (Modal + FAISS) {/* Search Input */}
setQuery(e.target.value)} onKeyPress={handleKeyPress} className="flex-1" />
{/* Search Options */}
{/* Search Info */} Vector search uses Modal.com's distributed FAISS implementation for high-performance semantic similarity matching. Enable comparison mode to see differences between vector and traditional keyword search.
{/* Search Results */} {searchResults && (
{/* Vector Search Results */}
Vector Search Results
{searchResults.searchTime && ( Search time: {(searchResults.searchTime * 1000).toFixed(0)}ms )} {searchResults.totalFound} results found
{searchResults.success ? (
{searchResults.results.length === 0 ? (

No results found in vector index.

Try uploading and processing some documents first.

) : ( searchResults.results.map((result, index) => (
#{result.rank} {formatRelevanceScore(result.relevanceScore)}
ID: {result.id}

{result.title}

{result.snippet}

{result.source}
)) )}
) : ( {searchResults.error || 'Vector search failed'} )}
{/* Traditional Search Results (if comparison mode) */} {comparisonMode && traditionalResults && ( Traditional Search Results (for comparison) {traditionalResults.results && traditionalResults.results.length > 0 ? (
{traditionalResults.results.slice(0, maxResults).map((result: any, index: number) => (
#{index + 1} {formatRelevanceScore(result.relevanceScore || 0)}

{result.title}

{result.snippet}

{result.source}
))}
) : (

No traditional search results found.

)}
)}
)} {/* Help Text */} {!searchResults && (

Advanced Vector Search

Search through your documents using semantic similarity powered by Modal.com's distributed FAISS implementation. Upload documents first to build your vector index.

)}
); }