@nataliapc/mcp-openmsx
Version:
Model context protocol server for openMSX automation and control
62 lines (61 loc) • 1.98 kB
JavaScript
/**
* Vector Database wrapper class
*
* @author Natalia Pujol Cremades (@nataliapc)
* @license GPL2
*/
import path from 'path';
import { LocalIndex } from 'vectra';
import embeddings from '@themaximalist/embeddings.js';
export class VectorDB {
static instance;
static vectorDbDir = path.join('..', 'vector-db');
index;
static getInstance() {
if (!VectorDB.instance) {
VectorDB.instance = new VectorDB();
}
return VectorDB.instance;
}
static setIndexDirectory(dbDir) {
VectorDB.vectorDbDir = dbDir;
}
constructor(dbDir = VectorDB.vectorDbDir) {
this.index = new LocalIndex(dbDir);
if (!this.initDatabase()) {
throw new Error('Failed to initialize VectorDB: Index does not exist');
}
}
async initDatabase() {
return await this.index.isIndexCreated();
}
async getVector(text) {
const response = await embeddings(text);
if (!response || !Array.isArray(response) || response.length === 0) {
throw new Error('Failed to generate embedding vector');
}
return response;
}
async query(text) {
const vector = await this.getVector(text);
let results = [];
try {
results = await this.index.queryItems(vector, text, 10);
if (results.length > 0) {
return results.map(result => {
return {
score: result.score.toFixed(4),
uri: result.item.metadata?.uri || 'unknown',
title: result.item.metadata?.title || 'unknown',
document: String(result.item.metadata?.document || ''),
id: result.item.metadata?.id || 'unknown',
};
});
}
}
catch (error) {
throw new Error(`Query failed: ${error}`);
}
return results;
}
}