Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
This commit is contained in:
304
crates/rvlite/examples/dashboard/vector-inspector-changes.md
Normal file
304
crates/rvlite/examples/dashboard/vector-inspector-changes.md
Normal file
@@ -0,0 +1,304 @@
|
||||
# Vector Inspector Implementation Guide
|
||||
|
||||
## Changes to /workspaces/ruvector/crates/rvlite/examples/dashboard/src/App.tsx
|
||||
|
||||
### 1. Add VectorEntry import (Line 90)
|
||||
**FIND:**
|
||||
```typescript
|
||||
import useRvLite, { type SearchResult, type CypherResult, type SparqlResult, type SqlResult } from './hooks/useRvLite';
|
||||
```
|
||||
|
||||
**REPLACE WITH:**
|
||||
```typescript
|
||||
import useRvLite, { type SearchResult, type CypherResult, type SparqlResult, type SqlResult, type VectorEntry } from './hooks/useRvLite';
|
||||
```
|
||||
|
||||
### 2. Add Eye icon import (Line 31-74)
|
||||
**FIND the lucide-react imports ending with:**
|
||||
```typescript
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
} from 'lucide-react';
|
||||
```
|
||||
|
||||
**REPLACE WITH:**
|
||||
```typescript
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
Eye,
|
||||
} from 'lucide-react';
|
||||
```
|
||||
|
||||
### 3. Add getVector to useRvLite destructuring (Line ~460)
|
||||
**FIND:**
|
||||
```typescript
|
||||
const {
|
||||
isReady,
|
||||
isLoading,
|
||||
error: rvliteError,
|
||||
stats,
|
||||
insertVector,
|
||||
insertVectorWithId,
|
||||
searchVectors,
|
||||
searchVectorsWithFilter,
|
||||
deleteVector,
|
||||
getAllVectors,
|
||||
```
|
||||
|
||||
**REPLACE WITH:**
|
||||
```typescript
|
||||
const {
|
||||
isReady,
|
||||
isLoading,
|
||||
error: rvliteError,
|
||||
stats,
|
||||
insertVector,
|
||||
insertVectorWithId,
|
||||
searchVectors,
|
||||
searchVectorsWithFilter,
|
||||
getVector,
|
||||
deleteVector,
|
||||
getAllVectors,
|
||||
```
|
||||
|
||||
### 4. Add modal disclosure (after line ~507)
|
||||
**FIND:**
|
||||
```typescript
|
||||
const { isOpen: isScenariosOpen, onOpen: onScenariosOpen, onClose: onScenariosClose } = useDisclosure();
|
||||
```
|
||||
|
||||
**ADD AFTER:**
|
||||
```typescript
|
||||
const { isOpen: isVectorDetailOpen, onOpen: onVectorDetailOpen, onClose: onVectorDetailClose } = useDisclosure();
|
||||
```
|
||||
|
||||
### 5. Add state variables (after line ~519)
|
||||
**FIND:**
|
||||
```typescript
|
||||
const [importJson, setImportJson] = useState('');
|
||||
```
|
||||
|
||||
**ADD AFTER:**
|
||||
```typescript
|
||||
const [selectedVectorId, setSelectedVectorId] = useState<string | null>(null);
|
||||
const [selectedVectorData, setSelectedVectorData] = useState<VectorEntry | null>(null);
|
||||
```
|
||||
|
||||
### 6. Add handler function (after refreshVectors function, around line ~650)
|
||||
**ADD NEW FUNCTION:**
|
||||
```typescript
|
||||
const handleViewVector = useCallback(async (id: string) => {
|
||||
try {
|
||||
const vectorData = getVector(id);
|
||||
if (vectorData) {
|
||||
setSelectedVectorId(id);
|
||||
setSelectedVectorData(vectorData);
|
||||
onVectorDetailOpen();
|
||||
addLog('info', `Viewing vector: ${id}`);
|
||||
} else {
|
||||
addLog('error', `Vector not found: ${id}`);
|
||||
}
|
||||
} catch (err) {
|
||||
addLog('error', `Failed to get vector: ${formatError(err)}`);
|
||||
}
|
||||
}, [getVector, onVectorDetailOpen, addLog]);
|
||||
```
|
||||
|
||||
### 7. Update Vector Table Cell to make ID clickable (around line 1218-1222)
|
||||
**FIND:**
|
||||
```typescript
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-2">
|
||||
<FileJson className="w-4 h-4 text-primary" />
|
||||
<span className="font-mono text-sm">{vector.id}</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
```
|
||||
|
||||
**REPLACE WITH:**
|
||||
```typescript
|
||||
<TableCell>
|
||||
<div
|
||||
className="flex items-center gap-2 cursor-pointer hover:text-primary transition-colors"
|
||||
onClick={() => handleViewVector(vector.id)}
|
||||
>
|
||||
<FileJson className="w-4 h-4 text-primary" />
|
||||
<span className="font-mono text-sm">{vector.id}</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
```
|
||||
|
||||
### 8. Update View Details button (around line 1236-1240)
|
||||
**FIND:**
|
||||
```typescript
|
||||
<Tooltip content="View Details">
|
||||
<Button isIconOnly size="sm" variant="light">
|
||||
<Code className="w-4 h-4" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
```
|
||||
|
||||
**REPLACE WITH:**
|
||||
```typescript
|
||||
<Tooltip content="View Details">
|
||||
<Button
|
||||
isIconOnly
|
||||
size="sm"
|
||||
variant="light"
|
||||
onPress={() => handleViewVector(vector.id)}
|
||||
>
|
||||
<Eye className="w-4 h-4" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
```
|
||||
|
||||
### 9. Add Vector Detail Modal (after Sample Scenarios Modal, around line 2350+)
|
||||
**ADD NEW MODAL:**
|
||||
```typescript
|
||||
{/* Vector Detail Modal */}
|
||||
<Modal isOpen={isVectorDetailOpen} onClose={onVectorDetailClose} size="3xl" scrollBehavior="inside">
|
||||
<ModalContent className="bg-gray-900 border border-gray-700">
|
||||
<ModalHeader className="flex items-center gap-2 border-b border-gray-700">
|
||||
<Eye className="w-5 h-5 text-primary" />
|
||||
<span>Vector Inspector</span>
|
||||
{selectedVectorId && (
|
||||
<Chip size="sm" variant="flat" color="primary" className="ml-2">
|
||||
{selectedVectorId}
|
||||
</Chip>
|
||||
)}
|
||||
</ModalHeader>
|
||||
<ModalBody className="py-6 space-y-6">
|
||||
{selectedVectorData ? (
|
||||
<>
|
||||
{/* Vector ID Section */}
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2 text-sm font-semibold text-gray-300">
|
||||
<Hash className="w-4 h-4" />
|
||||
<span>Vector ID</span>
|
||||
</div>
|
||||
<Snippet
|
||||
symbol=""
|
||||
className="bg-gray-800/50 border border-gray-700"
|
||||
classNames={{
|
||||
pre: "font-mono text-sm text-gray-200"
|
||||
}}
|
||||
>
|
||||
{selectedVectorData.id}
|
||||
</Snippet>
|
||||
</div>
|
||||
|
||||
{/* Dimensions */}
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2 text-sm font-semibold text-gray-300">
|
||||
<Layers className="w-4 h-4" />
|
||||
<span>Dimensions</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Chip size="lg" variant="flat" color="primary">
|
||||
{selectedVectorData.vector.length}D
|
||||
</Chip>
|
||||
<span className="text-xs text-gray-400">
|
||||
({selectedVectorData.vector.length} values)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Embedding Values */}
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2 text-sm font-semibold text-gray-300">
|
||||
<Code className="w-4 h-4" />
|
||||
<span>Embedding Values</span>
|
||||
</div>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="flat"
|
||||
onPress={() => {
|
||||
navigator.clipboard.writeText(JSON.stringify(selectedVectorData.vector));
|
||||
addLog('success', 'Embedding copied to clipboard');
|
||||
}}
|
||||
>
|
||||
<Copy className="w-3 h-3 mr-1" />
|
||||
Copy Array
|
||||
</Button>
|
||||
</div>
|
||||
<div className="bg-gray-800/50 border border-gray-700 rounded-lg p-4 max-h-60 overflow-auto">
|
||||
<pre className="text-xs font-mono text-gray-300">
|
||||
{selectedVectorData.vector.length <= 20
|
||||
? `[${selectedVectorData.vector.map(v => v.toFixed(6)).join(', ')}]`
|
||||
: `[${selectedVectorData.vector.slice(0, 20).map(v => v.toFixed(6)).join(', ')}\n ... ${selectedVectorData.vector.length - 20} more values]`
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
{selectedVectorData.vector.length > 20 && (
|
||||
<p className="text-xs text-gray-400 italic">
|
||||
Showing first 20 of {selectedVectorData.vector.length} values
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Metadata */}
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2 text-sm font-semibold text-gray-300">
|
||||
<FileJson className="w-4 h-4" />
|
||||
<span>Metadata</span>
|
||||
</div>
|
||||
{selectedVectorData.metadata && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="flat"
|
||||
onPress={() => {
|
||||
navigator.clipboard.writeText(JSON.stringify(selectedVectorData.metadata, null, 2));
|
||||
addLog('success', 'Metadata copied to clipboard');
|
||||
}}
|
||||
>
|
||||
<Copy className="w-3 h-3 mr-1" />
|
||||
Copy JSON
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{selectedVectorData.metadata ? (
|
||||
<div className="bg-gray-800/50 border border-gray-700 rounded-lg p-4 max-h-60 overflow-auto">
|
||||
<pre className="text-xs font-mono text-gray-300">
|
||||
{JSON.stringify(selectedVectorData.metadata, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-gray-800/50 border border-gray-700 rounded-lg p-4 text-center">
|
||||
<p className="text-sm text-gray-500 italic">No metadata</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="text-center py-8">
|
||||
<AlertCircle className="w-12 h-12 text-gray-600 mx-auto mb-3" />
|
||||
<p className="text-gray-400">Vector data not available</p>
|
||||
</div>
|
||||
)}
|
||||
</ModalBody>
|
||||
<ModalFooter className="border-t border-gray-700">
|
||||
<Button variant="flat" className="bg-gray-800 text-white hover:bg-gray-700" onPress={onVectorDetailClose}>
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
```
|
||||
|
||||
## Summary of Changes
|
||||
|
||||
1. **Imports**: Added `VectorEntry` type and `Eye` icon
|
||||
2. **Hook**: Added `getVector` function from useRvLite
|
||||
3. **State**: Added `selectedVectorId` and `selectedVectorData` state variables
|
||||
4. **Modal**: Added `isVectorDetailOpen` disclosure
|
||||
5. **Handler**: Created `handleViewVector` function
|
||||
6. **Table**: Made vector IDs clickable and updated View Details button
|
||||
7. **Modal Component**: Added complete Vector Inspector modal with:
|
||||
- Vector ID display with copy button
|
||||
- Dimensions display
|
||||
- Embedding values (first 20 + count if more)
|
||||
- Metadata as formatted JSON
|
||||
- Copy buttons for embedding and metadata
|
||||
- Dark theme styling matching existing UI
|
||||
Reference in New Issue
Block a user