import { createHash } from "node:crypto"; import type { EmbeddingProvider } from "@rakazo/adapter-kit"; export const EMULATED_EMBEDDING_DIMENSIONS = 256; /** * Deterministic bag-of-words vector: every word adds ±1 to a hashed dimension, so texts that * share words point in similar directions and unrelated texts are close to orthogonal. */ export function emulatedEmbedding(text: string): number[] { const vector = new Array(EMULATED_EMBEDDING_DIMENSIONS).fill(0); for (const word of text .normalize("NFKC") .toLowerCase() .match(/[\p{L}\p{N}]+/gu) ?? []) { const digest = createHash("sha256").update(word).digest(); const index = digest.readUInt32BE(0) % EMULATED_EMBEDDING_DIMENSIONS; vector[index] = vector[index]! + (digest[4]! & 1 ? 1 : -1); } const norm = Math.hypot(...vector); if (norm === 0) return vector.map((_, index) => (index === 0 ? 1 : 0)); return vector.map((value) => value / norm); } /** Offline embedding provider for tests and conformance; no model server involved. */ export class EmulatorEmbeddingProvider implements EmbeddingProvider { constructor(private readonly model = "emulator") {} describe() { return { id: "emulator", contractVersion: "1", adapterVersion: "0.1.0", capabilities: { model: this.model }, }; } async embed(texts: string[], signal?: AbortSignal): Promise { signal?.throwIfAborted(); return texts.map(emulatedEmbedding); } } interface EmulatedEmbeddingRequest { url: string; authorization: string | null; model: unknown; input: unknown; } /** * In-process substitute for an OpenAI-compatible `POST /v1/embeddings` server (llama.cpp, * vLLM, Ollama, OpenAI), so the real HTTP adapter runs in offline tests. */ export class OpenAiCompatibleEmbeddingServerEmulator { readonly requests: EmulatedEmbeddingRequest[] = []; /** Answer the next request with this HTTP status instead of vectors. */ failNextStatus: number | undefined; constructor(private readonly options: { apiKey?: string } = {}) {} readonly fetch: typeof fetch = async (input, init) => { init?.signal?.throwIfAborted(); const url = new URL(input instanceof Request ? input.url : String(input)); if (init?.method !== "POST" || !url.pathname.endsWith("/embeddings")) { return Response.json({ error: { message: "Not found" } }, { status: 404 }); } const authorization = new Headers(init.headers).get("authorization"); const body = JSON.parse(String(init.body)) as { model?: unknown; input?: unknown }; this.requests.push({ url: url.href, authorization, model: body.model, input: body.input }); if (this.failNextStatus) { const status = this.failNextStatus; this.failNextStatus = undefined; return new Response("Upstream failure", { status }); } if (this.options.apiKey && authorization !== `Bearer ${this.options.apiKey}`) { return Response.json({ error: { message: "Invalid API key" } }, { status: 401 }); } const texts = typeof body.input === "string" ? [body.input] : body.input; if (!Array.isArray(texts) || !texts.every((text) => typeof text === "string")) { return Response.json({ error: { message: "input must be text" } }, { status: 400 }); } return Response.json({ object: "list", model: body.model, data: texts.map((text, index) => ({ object: "embedding", index, embedding: emulatedEmbedding(text), })), usage: { prompt_tokens: 0, total_tokens: 0 }, }); }; }