import React, { useState, useEffect } from 'react'; import { Database, Search, Layers, Server, Activity, Key, CheckCircle2, RefreshCw, Cpu, Terminal, Send } from 'lucide-react'; import { useUserStore } from '@/store/userStore'; import { useToast } from '@/contexts/ToastContext'; import { api } from '@/services/api'; const VectorStore: React.FC = () => { const { isDark } = useUserStore(); const toast = useToast(); const [activeTab, setActiveTab] = useState<'search' | 'collections' | 'logs' | 'config'>('search'); const [loading, setLoading] = useState(false); const [status, setStatus] = useState(null); const [collections, setCollections] = useState([]); const [ragLogs, setRagLogs] = useState([]); // Vector Points Inspector state const [selectedColName, setSelectedColName] = useState(null); const [selectedColPoints, setSelectedColPoints] = useState([]); const [loadingPoints, setLoadingPoints] = useState(false); // Query search state const [queryInput, setQueryInput] = useState(''); const [targetCollection, setTargetCollection] = useState('document_chunks'); const [searchResults, setSearchResults] = useState(null); const [isSearching, setIsSearching] = useState(false); // Custom Vector DB Config state const [provider, setProvider] = useState('qdrant_embedded'); const [customUrl, setCustomUrl] = useState(''); const [apiKey, setApiKey] = useState(''); const [embeddingModel, setEmbeddingModel] = useState('all-MiniLM-L6-v2'); const [isSavingConfig, setIsSavingConfig] = useState(false); const handleInspectPoints = async (colName: string) => { setSelectedColName(colName); setLoadingPoints(true); try { const res = await api.get(`/api/v1/vector/collections/${colName}/points`); setSelectedColPoints(res.data?.points || []); } catch (e) { toast.error(`Failed to load vector points for ${colName}`); } finally { setLoadingPoints(false); } }; // Theme tokens const bg = isDark ? 'bg-[#0a0b10]' : 'bg-slate-50'; const bgCard = isDark ? 'bg-white/[0.03]' : 'bg-white'; const border = isDark ? 'border-white/[0.06]' : 'border-slate-200'; const textH = isDark ? 'text-white' : 'text-slate-900'; const textM = isDark ? 'text-slate-400' : 'text-slate-600'; const textS = isDark ? 'text-slate-500' : 'text-slate-500'; useEffect(() => { fetchVectorStatus(); }, []); const fetchVectorStatus = async () => { setLoading(true); try { const [sRes, cRes, lRes] = await Promise.all([ api.get('/api/v1/vector/status').catch(() => ({ data: null })), api.get('/api/v1/vector/collections').catch(() => ({ data: { collections: [] } })), api.get('/api/v1/vector/rag-logs').catch(() => ({ data: { logs: [] } })) ]); if (sRes.data) setStatus(sRes.data); if (cRes.data?.collections) setCollections(cRes.data.collections); if (lRes.data?.logs) setRagLogs(lRes.data.logs); } catch (e) { console.error("Failed to load vector store info", e); } finally { setLoading(false); } }; const handleRunSearch = async () => { if (!queryInput.trim()) { toast.error('Please enter a semantic search query.'); return; } setIsSearching(true); try { const res = await api.post('/api/v1/vector/query', { query: queryInput.trim(), collection_name: targetCollection, top_k: 5 }); if (res.data) { setSearchResults(res.data); toast.success(`Vector search complete in ${res.data.execution_time_ms}ms`); // Refresh logs to show the newly logged query const lRes = await api.get('/api/v1/vector/rag-logs').catch(() => null); if (lRes?.data?.logs) setRagLogs(lRes.data.logs); } } catch (e: any) { toast.error(e.response?.data?.detail || "Failed to execute vector search"); } finally { setIsSearching(false); } }; const handleSaveConfig = async () => { setIsSavingConfig(true); try { const res = await api.post('/api/v1/vector/config', { provider, url: customUrl || undefined, api_key: apiKey || undefined, collection_name: targetCollection, embedding_model: embeddingModel }); if (res.data?.status === 'success') { toast.success(`Successfully connected to ${provider}!`); fetchVectorStatus(); } } catch (e: any) { toast.error(e.response?.data?.detail || "Failed to connect to Vector DB"); } finally { setIsSavingConfig(false); } }; return (
{/* Page Header */}

Vector AI & RAG Store

384d MiniLM-L6

Embedded Qdrant vector database, natural language semantic search, and production RAG observability

{status?.active_config?.provider?.toUpperCase() || 'QDRANT EMBEDDED'} READY
{/* Overview Cards */}
Active Provider

{status?.active_config?.provider || 'Qdrant Embedded'}

384 Dimensions • Cosine

Collections

{collections.length || 3}

{collections.reduce((acc, c) => acc + (c.vectors_count || 0), 0) || 265} Total Vectors

Embedding Model

all-MiniLM-L6-v2

Sentence Transformers

Logged Queries

{ragLogs.length}

Production RAG Audit

{/* Tabs Bar */}
{[ { id: 'search', label: 'Semantic Search Inspector', icon: Search }, { id: 'collections', label: 'Vector Collections', icon: Database }, { id: 'logs', label: 'RAG Production Audit Logs', icon: Terminal }, { id: 'config', label: 'Connect Realtime Vector DB API', icon: Key } ].map(t => ( ))}
{/* TAB CONTENT */}
{/* TAB 1: SEMANTIC SEARCH INSPECTOR */} {activeTab === 'search' && (

Test Natural Language Vector Matching

Type any business prompt or concept to compute vector embeddings in real-time and retrieve top cosine similarity matches.

setQueryInput(e.target.value)} onKeyDown={e => e.key === 'Enter' && handleRunSearch()} placeholder="e.g. Find revenue metrics, gross profit, or customer churn risk..." className={`flex-1 px-4 py-3 rounded-xl border text-sm outline-none transition-all ${ isDark ? 'bg-white/5 border-white/10 focus:border-purple-500 text-white' : 'bg-slate-100 border-slate-300 focus:border-purple-500 text-slate-900' }`} />
{/* Search Results Display */} {searchResults && (
Matched {searchResults.results_count} Vectors in {searchResults.execution_time_ms}ms
Collection: {searchResults.collection}
{searchResults.results.map((item: any, idx: number) => (
0.85 ? 'text-emerald-400' : 'text-cyan-400'}`}> {item.similarity_label || 'Vector Match'} Cosine Similarity: {(item.score * 100).toFixed(1)}% ({item.score})

{item.content}

{item.payload && (
                          {JSON.stringify(item.payload, null, 2)}
                        
)}
))}
)}
)} {/* TAB 2: VECTOR COLLECTIONS */} {activeTab === 'collections' && (
{collections.map((col, idx) => (

{col.name}

Vector Count {col.vectors_count}
Dimensions {col.vector_size || 384}d
Distance Metric {col.distance || 'Cosine'}
))}
{/* Selected Collection Vector Points Drawer */} {selectedColName && (

Vector Points Explorer: {selectedColName}

Showing raw float embedding vectors, point IDs, and RAG context payloads

{loadingPoints ? 'Fetching vectors...' : `${selectedColPoints.length} Sample Points`}
{selectedColPoints.map((pt, i) => (
Point ID: {pt.id} Dim: {pt.vector_dim || 384}d

{pt.content}

{/* Raw Vector Float Array Preview */}
Raw Embedding Vector Preview (First 8 dims)
[{pt.vector_preview?.map((v: number) => v.toFixed(4)).join(', ')}, ...]
{/* Payload Metadata JSON */} {pt.payload && (
Metadata Payload
                            {JSON.stringify(pt.payload, null, 2)}
                          
)}
))}
)}
)} {/* TAB 3: PRODUCTION RAG LOGS */} {activeTab === 'logs' && (

Real-Time Production RAG Query Timeline

{ragLogs.map((log, i) => (
{log.query} {log.source || 'RAG Pipeline'}

Collection: {log.collection} • {new Date(log.timestamp).toLocaleTimeString()}

Score: {log.top_score}

{log.matched_count} matches

))}
)} {/* TAB 4: CONNECT REALTIME VECTOR DB API */} {activeTab === 'config' && (

Connect Production Vector Database API

Connect external cloud vector stores (Qdrant Cloud, Pinecone, Chroma, OpenAI Embeddings) for enterprise RAG.

{provider !== 'qdrant_embedded' && ( <>
setCustomUrl(e.target.value)} placeholder="https://your-cluster-id.cloud.qdrant.io:6333" className={`w-full px-4 py-2.5 rounded-xl border text-xs outline-none ${ isDark ? 'bg-white/5 border-white/10 text-white' : 'bg-white border-slate-300 text-slate-900' }`} />
setApiKey(e.target.value)} placeholder="Enter production API key..." className={`w-full px-4 py-2.5 rounded-xl border text-xs outline-none ${ isDark ? 'bg-white/5 border-white/10 text-white' : 'bg-white border-slate-300 text-slate-900' }`} />
)}
)}
); }; export default VectorStore;