Docs/Skills and code/src/
src/analysis/embeddings.js
const DEFAULT_BASE_URL = "http://localhost:11434";
export function embeddingConfig() {
return {
baseUrl: (process.env.OLLAMA_BASE_URL || DEFAULT_BASE_URL).replace(/\/$/, ""),
model: process.env.OLLAMA_EMBEDDING_MODEL || "nomic-embed-text"
};
}
export async function embedTexts(texts, { baseUrl, model } = embeddingConfig()) {
if (!texts.length) return [];
const response = await fetch(`${baseUrl}/api/embed`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ model, input: texts }),
signal: AbortSignal.timeout(120000)
});
if (!response.ok) {
const body = await response.text().catch(() => "");
throw new Error(`Ollama embedding request failed (${response.status}): ${body.slice(0, 400)}`);
}
const payload = await response.json();
const vectors = payload.embeddings;
if (!Array.isArray(vectors) || vectors.length !== texts.length) {
throw new Error(`Embedding response mismatch: expected ${texts.length}, received ${vectors?.length ?? 0}`);
}
for (const vector of vectors) {
if (!Array.isArray(vector) || !vector.length || vector.some(n => !Number.isFinite(n))) {
throw new Error("Ollama returned an invalid embedding vector.");
}
}
return vectors;
}
export function cosineSimilarity(a, b) {
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length || !a.length) return null;
let dot = 0;
let normA = 0;
let normB = 0;
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i];
normA += a[i] * a[i];
normB += b[i] * b[i];
}
if (!normA || !normB) return null;
return dot / (Math.sqrt(normA) * Math.sqrt(normB));
}
Shown as it is in the repository at build time (2026-11-03); the home directory appears as <home>. If this page and the file differ, the file is right. Back to the catalogue.