const express = require('express'); const bodyParser = require('body-parser'); const vptree = require('vptree'); const similarity = require('compute-cosine-similarity'); const fs = require('fs'); const path = require('path'); const app = express(); const port = 2000; app.use(bodyParser.json()); // Function to load JSON data function loadJSON(filePath, callback) { fs.readFile(filePath, 'utf8', (err, data) => { if (err) { return callback(err, null); } try { const jsonData = JSON.parse(data); callback(null, jsonData); } catch (parseError) { callback(parseError, null); } }); } function cosineDistanceMatching(vector1, vector2) { let cosineSimilarity = similarity(vector1, vector2); let distance = 2 * (1 - cosineSimilarity); return Math.sqrt(distance); } let tree, vectors, jsonEmbeddings buildVPTree() loadVPTree() // Load tree endpoint app.post('/search/', (req, res) => { const { vector } = req.body; if (!Array.isArray(vector) || vector.length !== 7 || !vector.every(num => typeof num === 'number')) { return res.status(400).send({ success: false, message: 'Invalid vector provided. It must be an array of 7 floating-point numbers.' }); } let idx = queryVPTree(vector) // Retrieve the filename from the stored JSON data let filename = idx !== undefined && idx < jsonEmbeddings.length ? jsonEmbeddings[idx].filename : null; res.send({filename}); }); function queryVPTree(value){ let nearest = tree.search(value) let index = nearest[0].i return index } function buildVPTree(){ // Load JSON data from embeddings.json const jsonFilePath = path.join(__dirname, 'embeddings.json'); loadJSON(jsonFilePath, (err, jsonData) => { if (err) { console.error('Error loading JSON:', err); return; } // Extract vectors from the JSON data jsonEmbeddings = jsonData vectors = jsonEmbeddings.map(item => item.vector); tree = vptree.build(vectors, cosineDistanceMatching) const treeString = tree.stringify(); const fileName = "tree" const filePath = path.join(__dirname, `${fileName}.txt`); fs.writeFile(filePath, treeString, 'utf8', (err) => { if (err) { console.log("Tree did not save to file.") return } console.log("Tree saved successfully.") }); }); } function saveVPTree(fileName){ const treeString = tree.stringify(); const filePath = path.join(__dirname, `${fileName}.txt`); fs.writeFile(filePath, treeString, 'utf8', (err) => { if (err) { console.log("Tree did not save to file.") return } console.log("Tree saved successfully.") }); } function loadVPTree(){ loadTreeFromDisk("tree", (err, treeData) => { if (err) { console.error('Failed to load tree from disk:', err); return; } // Rebuild the VP-tree using the saved structure try { tree = vptree.load(vectors, cosineDistanceMatching, treeData); console.log('Tree loaded successfully.'); } catch (loadError) { console.error('Error loading the VP-tree:', loadError); } }); } function loadTreeFromDisk(fileName, callback){ const filePath = path.join(__dirname, `${fileName}.txt`); fs.readFile(filePath, 'utf8', (err, data) => { if (err) { console.error('Error reading the file:', err); return callback(err, null); } // Parse the data as a JavaScript object try { const treeData = eval(`(${data})`); // Using eval to convert to object callback(null, treeData); } catch (parseError) { console.error('Error parsing the tree data:', parseError); callback(parseError, null); } }); } app.listen(port, () => { console.log(`Server listening at http://localhost:${port}`); });