zrald1
Version:
Advanced Graph RAG MCP Server with file location identification, graph processing, and result summarization capabilities
181 lines • 6.18 kB
JavaScript
export class VectorStore {
dimension;
maxElements;
nodeMap = new Map();
chunkMap = new Map();
fileMap = 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 addFile(file, embedding) {
this.fileMap.set(file.id, file);
if (embedding && embedding.length === this.dimension) {
this.embeddings.set(file.id, 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);
const file = this.fileMap.get(id);
searchResults.push({
id,
score: similarity,
node,
chunk,
file
});
}
}
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 searchFiles(queryEmbedding, topK = 10, threshold = 0.7) {
const allResults = await this.searchNodes(queryEmbedding, topK * 2, threshold);
return allResults
.filter(result => result.file)
.slice(0, topK);
}
getStats() {
return {
totalNodes: this.nodeMap.size,
totalChunks: this.chunkMap.size,
totalFiles: this.fileMap.size,
totalEmbeddings: this.embeddings.size,
dimension: this.dimension,
maxElements: this.maxElements
};
}
// Utility methods
static cosineSimilarity(a, b) {
if (a.length !== b.length) {
throw new Error('Vectors must have the same length');
}
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];
}
normA = Math.sqrt(normA);
normB = Math.sqrt(normB);
if (normA === 0 || normB === 0) {
return 0;
}
return dotProduct / (normA * normB);
}
static euclideanDistance(a, b) {
if (a.length !== b.length) {
throw new Error('Vectors must have the same length');
}
let sum = 0;
for (let i = 0; i < a.length; i++) {
const diff = a[i] - b[i];
sum += diff * diff;
}
return Math.sqrt(sum);
}
static dotProduct(a, b) {
if (a.length !== b.length) {
throw new Error('Vectors must have the same length');
}
let product = 0;
for (let i = 0; i < a.length; i++) {
product += a[i] * b[i];
}
return product;
}
// Generate random embedding for testing
static generateRandomEmbedding(dimension) {
const embedding = new Array(dimension);
for (let i = 0; i < dimension; i++) {
embedding[i] = Math.random() * 2 - 1; // Random values between -1 and 1
}
// Normalize the embedding
const norm = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));
return embedding.map(val => val / norm);
}
// Clear all data
clear() {
this.nodeMap.clear();
this.chunkMap.clear();
this.fileMap.clear();
this.embeddings.clear();
this.currentIndex = 0;
}
// Get all nodes
getAllNodes() {
return Array.from(this.nodeMap.values());
}
// Get all chunks
getAllChunks() {
return Array.from(this.chunkMap.values());
}
// Get all files
getAllFiles() {
return Array.from(this.fileMap.values());
}
// Remove node
removeNode(nodeId) {
const removed = this.nodeMap.delete(nodeId);
this.embeddings.delete(nodeId);
return removed;
}
// Remove chunk
removeChunk(chunkId) {
const removed = this.chunkMap.delete(chunkId);
this.embeddings.delete(chunkId);
return removed;
}
// Remove file
removeFile(fileId) {
const removed = this.fileMap.delete(fileId);
this.embeddings.delete(fileId);
return removed;
}
}
//# sourceMappingURL=vector-store.js.map