Files
nexusAI/packages/embedding-service/src/index.js
2026-04-26 21:59:16 -07:00

82 lines
2.4 KiB
JavaScript

require ('dotenv').config();
const express = require('express');
const {getEnv, OLLAMA, PORTS, logger} = require('@nexusai/shared');
const app = express();
app.use(express.json());
const PORT = getEnv('PORT', PORTS.EMBEDDING);
const OLLAMA_URL = getEnv('OLLAMA_URL', OLLAMA.DEFAULT_URL);
const EMBED_MODEL = getEnv('EMBEDDING_MODEL', OLLAMA.EMBED_MODEL);
//OLLAMA embedding helper function
async function embedText(text) {
const res = await fetch(`${OLLAMA_URL}/api/embed`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ model: EMBED_MODEL, input: text })
});
if (!res.ok) {
throw new Error(`Ollama error: ${res.status} ${res.statusText}`);
}
const data = await res.json();
return data.embeddings[0];
}
/**** ROUTES ***** */
// Health check endpoint
app.get('/health', (req,res) => {
res.json({ service: 'Embedding Service', status: 'healthy' });
})
// Single text embedding
app.post('/embed', async (req, res) => {
const { text } = req.body;
if (!text || typeof text !== 'string' || text.trim() === '') {
return res.status(400).json({ error: 'text is required and must be empty' });
}
try {
const embedding = await embedText(text.trim());
res.json({
embedding,
model: EMBED_MODEL,
dimensions: embedding.length
});
} catch (err) {
res.status(502).json({ error: 'Embedding failed', detail: err.message });
}
});
// Batch embedding endpoint
app.post('/embed/batch', async (req, res) => {
const { texts } = req.body;
if (!Array.isArray(texts) || texts.length ===0 ) {
return res.status(400).json({ error: 'texts array must not be empty' });
}
try {
//sequential embedding for now, Ollama doesn't natively parallize embeddings
const embeddings = [];
for (const text of texts) {
embeddings.push(await embedText(text.trim()));
}
res.json ({
embeddings,
model: EMBED_MODEL,
dimensions: embeddings[0].length,
count: embeddings.length
})
} catch (err) {
res.status(502).json({ error: 'Batch embedding failed', detail: err.message });
}
})
/******* Start Server ********/
app.listen(PORT, () => {
logger.info(`Embedding Service listening on port ${PORT}`);
});