zrald
Version:
Advanced Graph RAG MCP Server with sophisticated graph structures, operators, and agentic capabilities for AI agents
151 lines • 5.21 kB
JavaScript
export class VectorStore {
dimension;
maxElements;
nodeMap = new Map();
chunkMap = new Map();
embeddings = new Map();
currentIndex = 0;
constructor(dimension = 384, maxElements = 10000) {
this.dimension = dimension;
this.maxElements = maxElements;
}
async initialize() {
console.log(`Vector store initialized with dimension ${this.dimension}`);
}
async addNode(node) {
if (!node.embedding || node.embedding.length !== this.dimension) {
console.warn(`Node ${node.id} has invalid embedding, skipping`);
return;
}
this.nodeMap.set(node.id, node);
this.embeddings.set(node.id, node.embedding);
}
async addChunk(chunk) {
if (!chunk.embedding || chunk.embedding.length !== this.dimension) {
console.warn(`Chunk ${chunk.id} has invalid embedding, skipping`);
return;
}
this.chunkMap.set(chunk.id, chunk);
this.embeddings.set(chunk.id, chunk.embedding);
}
async searchNodes(queryEmbedding, topK = 10, threshold = 0.7) {
if (queryEmbedding.length !== this.dimension) {
throw new Error(`Query embedding dimension ${queryEmbedding.length} does not match store dimension ${this.dimension}`);
}
const searchResults = [];
// Simple brute force search for demonstration
for (const [id, embedding] of this.embeddings) {
const similarity = VectorStore.cosineSimilarity(queryEmbedding, embedding);
if (similarity >= threshold) {
const node = this.nodeMap.get(id);
const chunk = this.chunkMap.get(id);
searchResults.push({
id,
score: similarity,
node,
chunk
});
}
}
return searchResults
.sort((a, b) => b.score - a.score)
.slice(0, topK);
}
async searchByNodeTypes(queryEmbedding, nodeTypes, topK = 10, threshold = 0.7) {
const allResults = await this.searchNodes(queryEmbedding, topK * 2, threshold);
return allResults
.filter(result => result.node && nodeTypes.includes(result.node.type))
.slice(0, topK);
}
async searchChunks(queryEmbedding, topK = 10, threshold = 0.7) {
const allResults = await this.searchNodes(queryEmbedding, topK * 2, threshold);
return allResults
.filter(result => result.chunk)
.slice(0, topK);
}
async getNodeById(id) {
return this.nodeMap.get(id);
}
async getChunkById(id) {
return this.chunkMap.get(id);
}
async updateNode(node) {
// Remove old entry if exists
if (this.nodeMap.has(node.id)) {
this.nodeMap.delete(node.id);
this.embeddings.delete(node.id);
}
// Add updated node
await this.addNode(node);
}
async removeNode(id) {
this.nodeMap.delete(id);
this.chunkMap.delete(id);
this.embeddings.delete(id);
}
async batchAddNodes(nodes) {
for (const node of nodes) {
await this.addNode(node);
}
}
async batchAddChunks(chunks) {
for (const chunk of chunks) {
await this.addChunk(chunk);
}
}
getStats() {
return {
totalNodes: this.nodeMap.size,
totalChunks: this.chunkMap.size,
dimension: this.dimension,
maxElements: this.maxElements
};
}
async saveIndex(filePath) {
// Simple JSON serialization for demonstration
const data = {
nodes: Array.from(this.nodeMap.entries()),
chunks: Array.from(this.chunkMap.entries()),
embeddings: Array.from(this.embeddings.entries())
};
// In a real implementation, you'd write this to a file
console.log(`Would save index to ${filePath}`);
}
async loadIndex(filePath) {
// In a real implementation, you'd load from a file
console.log(`Would load index from ${filePath}`);
}
async clear() {
this.nodeMap.clear();
this.chunkMap.clear();
this.embeddings.clear();
this.currentIndex = 0;
}
// Similarity computation utilities
static cosineSimilarity(a, b) {
if (a.length !== b.length) {
throw new Error('Vectors must have the same dimension');
}
let dotProduct = 0;
let normA = 0;
let normB = 0;
for (let i = 0; i < a.length; i++) {
dotProduct += a[i] * b[i];
normA += a[i] * a[i];
normB += b[i] * b[i];
}
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}
static euclideanDistance(a, b) {
if (a.length !== b.length) {
throw new Error('Vectors must have the same dimension');
}
let sum = 0;
for (let i = 0; i < a.length; i++) {
const diff = a[i] - b[i];
sum += diff * diff;
}
return Math.sqrt(sum);
}
}
//# sourceMappingURL=vector-store.js.map