UNPKG

llmverify

Version:

AI Output Verification Toolkit — Local-first LLM safety, hallucination detection, PII redaction, prompt injection defense, and runtime monitoring. Zero telemetry. OWASP LLM Top 10 aligned.

109 lines 10.2 kB
"use strict"; /** * Local Adapter * * Adapter for local LLM inference (llama.cpp, vLLM, Ollama, etc.) * * @module adapters/providers/local * @author Haiec * @license MIT */ Object.defineProperty(exports, "__esModule", { value: true }); exports.buildLocalAdapter = buildLocalAdapter; const types_1 = require("../types"); /** * Builds a local adapter. * * @param config - Adapter configuration * @returns LLM client for local inference * * @example * // Simple function * const llm = buildLocalAdapter({ * provider: 'local', * client: async (prompt) => await myLocalModel(prompt) * }); * * @example * // With Ollama * import ollama from 'ollama'; * const llm = buildLocalAdapter({ * provider: 'local', * client: async (prompt, opts) => { * const response = await ollama.generate({ * model: opts?.model ?? 'llama3', * prompt * }); * return response.response; * }, * defaultModel: 'llama3' * }); * * @example * // With llama.cpp server * const llm = buildLocalAdapter({ * provider: 'local', * client: async (prompt) => { * const res = await fetch('http://localhost:8080/completion', { * method: 'POST', * body: JSON.stringify({ prompt }) * }); * const data = await res.json(); * return data.content; * } * }); */ function buildLocalAdapter(config) { if (typeof config.client !== 'function') { throw new types_1.AdapterConfigError('local', 'Local adapter requires client as a function: (prompt: string, options?) => Promise<string | { text, tokens }>'); } const fn = config.client; const defaultModel = config.defaultModel ?? 'local'; return { provider: 'local', providerName: config.providerName ?? 'Local Model', async generate(request) { // Build prompt with system instruction if provided let prompt = request.prompt; if (request.system) { prompt = `${request.system}\n\n${request.prompt}`; } const result = await fn(prompt, { model: request.model || defaultModel, temperature: request.temperature, maxTokens: request.maxTokens }); // Handle both string and object responses let text; let tokens; if (typeof result === 'string') { text = result; tokens = estimateTokens(text); } else { text = result.text; tokens = result.tokens ?? estimateTokens(text); } return { text, tokens, model: request.model || defaultModel, finishReason: 'stop', raw: null }; }, async healthCheck() { try { const result = await fn('test', { maxTokens: 1 }); return typeof result === 'string' ? result.length > 0 : result.text.length > 0; } catch { return false; } } }; } function estimateTokens(text) { return Math.ceil(text.split(/\s+/).length * 1.3); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9jYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYWRhcHRlcnMvcHJvdmlkZXJzL2xvY2FsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7R0FRRzs7QUF1REgsOENBMERDO0FBL0dELG9DQUFpRztBQVdqRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Q0c7QUFDSCxTQUFnQixpQkFBaUIsQ0FBQyxNQUFxQjtJQUNyRCxJQUFJLE9BQU8sTUFBTSxDQUFDLE1BQU0sS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUN4QyxNQUFNLElBQUksMEJBQWtCLENBQzFCLE9BQU8sRUFDUCwrR0FBK0csQ0FDaEgsQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsTUFBMEIsQ0FBQztJQUM3QyxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxJQUFJLE9BQU8sQ0FBQztJQUVwRCxPQUFPO1FBQ0wsUUFBUSxFQUFFLE9BQU87UUFDakIsWUFBWSxFQUFFLE1BQU0sQ0FBQyxZQUFZLElBQUksYUFBYTtRQUVsRCxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQW1CO1lBQ2hDLG1EQUFtRDtZQUNuRCxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO1lBQzVCLElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNuQixNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsTUFBTSxPQUFPLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNwRCxDQUFDO1lBRUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxFQUFFLENBQUMsTUFBTSxFQUFFO2dCQUM5QixLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUssSUFBSSxZQUFZO2dCQUNwQyxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVc7Z0JBQ2hDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUzthQUM3QixDQUFDLENBQUM7WUFFSCwwQ0FBMEM7WUFDMUMsSUFBSSxJQUFZLENBQUM7WUFDakIsSUFBSSxNQUFjLENBQUM7WUFFbkIsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDL0IsSUFBSSxHQUFHLE1BQU0sQ0FBQztnQkFDZCxNQUFNLEdBQUcsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hDLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQztnQkFDbkIsTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLElBQUksY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2pELENBQUM7WUFFRCxPQUFPO2dCQUNMLElBQUk7Z0JBQ0osTUFBTTtnQkFDTixLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUssSUFBSSxZQUFZO2dCQUNwQyxZQUFZLEVBQUUsTUFBTTtnQkFDcEIsR0FBRyxFQUFFLElBQUk7YUFDVixDQUFDO1FBQ0osQ0FBQztRQUVELEtBQUssQ0FBQyxXQUFXO1lBQ2YsSUFBSSxDQUFDO2dCQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNsRCxPQUFPLE9BQU8sTUFBTSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNqRixDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLE9BQU8sS0FBSyxDQUFDO1lBQ2YsQ0FBQztRQUNILENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsY0FBYyxDQUFDLElBQVk7SUFDbEMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDO0FBQ25ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIExvY2FsIEFkYXB0ZXJcbiAqIFxuICogQWRhcHRlciBmb3IgbG9jYWwgTExNIGluZmVyZW5jZSAobGxhbWEuY3BwLCB2TExNLCBPbGxhbWEsIGV0Yy4pXG4gKiBcbiAqIEBtb2R1bGUgYWRhcHRlcnMvcHJvdmlkZXJzL2xvY2FsXG4gKiBAYXV0aG9yIEhhaWVjXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuXG5pbXBvcnQgeyBMbG1DbGllbnQsIExsbVJlcXVlc3QsIExsbVJlc3BvbnNlLCBBZGFwdGVyQ29uZmlnLCBBZGFwdGVyQ29uZmlnRXJyb3IgfSBmcm9tICcuLi90eXBlcyc7XG5cbi8qKlxuICogTG9jYWwgaW5mZXJlbmNlIGZ1bmN0aW9uIHR5cGUuXG4gKi9cbnR5cGUgTG9jYWxJbmZlcmVuY2VGbiA9IChwcm9tcHQ6IHN0cmluZywgb3B0aW9ucz86IHtcbiAgbW9kZWw/OiBzdHJpbmc7XG4gIHRlbXBlcmF0dXJlPzogbnVtYmVyO1xuICBtYXhUb2tlbnM/OiBudW1iZXI7XG59KSA9PiBQcm9taXNlPHN0cmluZyB8IHsgdGV4dDogc3RyaW5nOyB0b2tlbnM/OiBudW1iZXIgfT47XG5cbi8qKlxuICogQnVpbGRzIGEgbG9jYWwgYWRhcHRlci5cbiAqIFxuICogQHBhcmFtIGNvbmZpZyAtIEFkYXB0ZXIgY29uZmlndXJhdGlvblxuICogQHJldHVybnMgTExNIGNsaWVudCBmb3IgbG9jYWwgaW5mZXJlbmNlXG4gKiBcbiAqIEBleGFtcGxlXG4gKiAvLyBTaW1wbGUgZnVuY3Rpb25cbiAqIGNvbnN0IGxsbSA9IGJ1aWxkTG9jYWxBZGFwdGVyKHtcbiAqICAgcHJvdmlkZXI6ICdsb2NhbCcsXG4gKiAgIGNsaWVudDogYXN5bmMgKHByb21wdCkgPT4gYXdhaXQgbXlMb2NhbE1vZGVsKHByb21wdClcbiAqIH0pO1xuICogXG4gKiBAZXhhbXBsZVxuICogLy8gV2l0aCBPbGxhbWFcbiAqIGltcG9ydCBvbGxhbWEgZnJvbSAnb2xsYW1hJztcbiAqIGNvbnN0IGxsbSA9IGJ1aWxkTG9jYWxBZGFwdGVyKHtcbiAqICAgcHJvdmlkZXI6ICdsb2NhbCcsXG4gKiAgIGNsaWVudDogYXN5bmMgKHByb21wdCwgb3B0cykgPT4ge1xuICogICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgb2xsYW1hLmdlbmVyYXRlKHtcbiAqICAgICAgIG1vZGVsOiBvcHRzPy5tb2RlbCA/PyAnbGxhbWEzJyxcbiAqICAgICAgIHByb21wdFxuICogICAgIH0pO1xuICogICAgIHJldHVybiByZXNwb25zZS5yZXNwb25zZTtcbiAqICAgfSxcbiAqICAgZGVmYXVsdE1vZGVsOiAnbGxhbWEzJ1xuICogfSk7XG4gKiBcbiAqIEBleGFtcGxlXG4gKiAvLyBXaXRoIGxsYW1hLmNwcCBzZXJ2ZXJcbiAqIGNvbnN0IGxsbSA9IGJ1aWxkTG9jYWxBZGFwdGVyKHtcbiAqICAgcHJvdmlkZXI6ICdsb2NhbCcsXG4gKiAgIGNsaWVudDogYXN5bmMgKHByb21wdCkgPT4ge1xuICogICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKCdodHRwOi8vbG9jYWxob3N0OjgwODAvY29tcGxldGlvbicsIHtcbiAqICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICogICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBwcm9tcHQgfSlcbiAqICAgICB9KTtcbiAqICAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzLmpzb24oKTtcbiAqICAgICByZXR1cm4gZGF0YS5jb250ZW50O1xuICogICB9XG4gKiB9KTtcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkTG9jYWxBZGFwdGVyKGNvbmZpZzogQWRhcHRlckNvbmZpZyk6IExsbUNsaWVudCB7XG4gIGlmICh0eXBlb2YgY29uZmlnLmNsaWVudCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBBZGFwdGVyQ29uZmlnRXJyb3IoXG4gICAgICAnbG9jYWwnLFxuICAgICAgJ0xvY2FsIGFkYXB0ZXIgcmVxdWlyZXMgY2xpZW50IGFzIGEgZnVuY3Rpb246IChwcm9tcHQ6IHN0cmluZywgb3B0aW9ucz8pID0+IFByb21pc2U8c3RyaW5nIHwgeyB0ZXh0LCB0b2tlbnMgfT4nXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IGZuID0gY29uZmlnLmNsaWVudCBhcyBMb2NhbEluZmVyZW5jZUZuO1xuICBjb25zdCBkZWZhdWx0TW9kZWwgPSBjb25maWcuZGVmYXVsdE1vZGVsID8/ICdsb2NhbCc7XG5cbiAgcmV0dXJuIHtcbiAgICBwcm92aWRlcjogJ2xvY2FsJyxcbiAgICBwcm92aWRlck5hbWU6IGNvbmZpZy5wcm92aWRlck5hbWUgPz8gJ0xvY2FsIE1vZGVsJyxcblxuICAgIGFzeW5jIGdlbmVyYXRlKHJlcXVlc3Q6IExsbVJlcXVlc3QpOiBQcm9taXNlPExsbVJlc3BvbnNlPiB7XG4gICAgICAvLyBCdWlsZCBwcm9tcHQgd2l0aCBzeXN0ZW0gaW5zdHJ1Y3Rpb24gaWYgcHJvdmlkZWRcbiAgICAgIGxldCBwcm9tcHQgPSByZXF1ZXN0LnByb21wdDtcbiAgICAgIGlmIChyZXF1ZXN0LnN5c3RlbSkge1xuICAgICAgICBwcm9tcHQgPSBgJHtyZXF1ZXN0LnN5c3RlbX1cXG5cXG4ke3JlcXVlc3QucHJvbXB0fWA7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZuKHByb21wdCwge1xuICAgICAgICBtb2RlbDogcmVxdWVzdC5tb2RlbCB8fCBkZWZhdWx0TW9kZWwsXG4gICAgICAgIHRlbXBlcmF0dXJlOiByZXF1ZXN0LnRlbXBlcmF0dXJlLFxuICAgICAgICBtYXhUb2tlbnM6IHJlcXVlc3QubWF4VG9rZW5zXG4gICAgICB9KTtcblxuICAgICAgLy8gSGFuZGxlIGJvdGggc3RyaW5nIGFuZCBvYmplY3QgcmVzcG9uc2VzXG4gICAgICBsZXQgdGV4dDogc3RyaW5nO1xuICAgICAgbGV0IHRva2VuczogbnVtYmVyO1xuXG4gICAgICBpZiAodHlwZW9mIHJlc3VsdCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGV4dCA9IHJlc3VsdDtcbiAgICAgICAgdG9rZW5zID0gZXN0aW1hdGVUb2tlbnModGV4dCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0ZXh0ID0gcmVzdWx0LnRleHQ7XG4gICAgICAgIHRva2VucyA9IHJlc3VsdC50b2tlbnMgPz8gZXN0aW1hdGVUb2tlbnModGV4dCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRleHQsXG4gICAgICAgIHRva2VucyxcbiAgICAgICAgbW9kZWw6IHJlcXVlc3QubW9kZWwgfHwgZGVmYXVsdE1vZGVsLFxuICAgICAgICBmaW5pc2hSZWFzb246ICdzdG9wJyxcbiAgICAgICAgcmF3OiBudWxsXG4gICAgICB9O1xuICAgIH0sXG5cbiAgICBhc3luYyBoZWFsdGhDaGVjaygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZuKCd0ZXN0JywgeyBtYXhUb2tlbnM6IDEgfSk7XG4gICAgICAgIHJldHVybiB0eXBlb2YgcmVzdWx0ID09PSAnc3RyaW5nJyA/IHJlc3VsdC5sZW5ndGggPiAwIDogcmVzdWx0LnRleHQubGVuZ3RoID4gMDtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBlc3RpbWF0ZVRva2Vucyh0ZXh0OiBzdHJpbmcpOiBudW1iZXIge1xuICByZXR1cm4gTWF0aC5jZWlsKHRleHQuc3BsaXQoL1xccysvKS5sZW5ndGggKiAxLjMpO1xufVxuIl19