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.

99 lines 11.9 kB
"use strict"; /** * OpenAI Adapter * * Adapter for OpenAI API (GPT-4, GPT-3.5, etc.) * * @module adapters/providers/openai * @author Haiec * @license MIT */ Object.defineProperty(exports, "__esModule", { value: true }); exports.buildOpenAIAdapter = buildOpenAIAdapter; const types_1 = require("../types"); /** * Builds an OpenAI adapter. * * @param config - Adapter configuration * @returns LLM client for OpenAI * * @example * import OpenAI from 'openai'; * const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); * const llm = buildOpenAIAdapter({ provider: 'openai', client: openai }); */ function buildOpenAIAdapter(config) { if (!config.client && !config.apiKey) { throw new types_1.AdapterConfigError('openai', 'OpenAI adapter requires either a client instance or apiKey. ' + 'Install openai package: npm install openai'); } const client = config.client; const defaultModel = config.defaultModel ?? 'gpt-4o-mini'; return { provider: 'openai', providerName: 'OpenAI', async generate(request) { if (!client) { throw new types_1.AdapterConfigError('openai', 'Client not initialized'); } const model = request.model || defaultModel; // Build messages array const messages = []; if (request.system) { messages.push({ role: 'system', content: request.system }); } messages.push({ role: 'user', content: request.prompt }); const response = await client.chat.completions.create({ model, messages, temperature: request.temperature, max_tokens: request.maxTokens, stop: request.stop }); const choice = response.choices[0]; const text = choice?.message?.content?.toString() ?? ''; const tokens = response.usage?.completion_tokens ?? estimateTokens(text); const totalTokens = response.usage?.total_tokens; return { text, tokens, totalTokens, model: response.model ?? model, finishReason: normalizeFinishReason(choice?.finish_reason), raw: response }; }, async embed(input) { if (!client?.embeddings) { throw new types_1.AdapterConfigError('openai', 'Embeddings not available'); } const response = await client.embeddings.create({ model: 'text-embedding-3-small', input }); return response.data.map(d => d.embedding); } }; } /** * Estimates token count from text (rough approximation). */ function estimateTokens(text) { return Math.ceil(text.split(/\s+/).length * 1.3); } /** * Normalizes finish reason to standard format. */ function normalizeFinishReason(reason) { if (!reason) return undefined; const map = { 'stop': 'stop', 'length': 'length', 'content_filter': 'content_filter', 'tool_calls': 'tool_calls', 'function_call': 'tool_calls' }; return map[reason] ?? reason; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FkYXB0ZXJzL3Byb3ZpZGVycy9vcGVuYWkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7OztHQVFHOztBQStDSCxnREFrRUM7QUEvR0Qsb0NBQWlHO0FBa0NqRzs7Ozs7Ozs7OztHQVVHO0FBQ0gsU0FBZ0Isa0JBQWtCLENBQUMsTUFBcUI7SUFDdEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDckMsTUFBTSxJQUFJLDBCQUFrQixDQUMxQixRQUFRLEVBQ1IsOERBQThEO1lBQzlELDRDQUE0QyxDQUM3QyxDQUFDO0lBQ0osQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFzQixDQUFDO0lBQzdDLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxZQUFZLElBQUksYUFBYSxDQUFDO0lBRTFELE9BQU87UUFDTCxRQUFRLEVBQUUsUUFBUTtRQUNsQixZQUFZLEVBQUUsUUFBUTtRQUV0QixLQUFLLENBQUMsUUFBUSxDQUFDLE9BQW1CO1lBQ2hDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDWixNQUFNLElBQUksMEJBQWtCLENBQUMsUUFBUSxFQUFFLHdCQUF3QixDQUFDLENBQUM7WUFDbkUsQ0FBQztZQUVELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLElBQUksWUFBWSxDQUFDO1lBRTVDLHVCQUF1QjtZQUN2QixNQUFNLFFBQVEsR0FBNkMsRUFBRSxDQUFDO1lBQzlELElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNuQixRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDN0QsQ0FBQztZQUNELFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUV6RCxNQUFNLFFBQVEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQztnQkFDcEQsS0FBSztnQkFDTCxRQUFRO2dCQUNSLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVztnQkFDaEMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxTQUFTO2dCQUM3QixJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7YUFDbkIsQ0FBQyxDQUFDO1lBRUgsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNuQyxNQUFNLElBQUksR0FBRyxNQUFNLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUM7WUFDeEQsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLEtBQUssRUFBRSxpQkFBaUIsSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDekUsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUM7WUFFakQsT0FBTztnQkFDTCxJQUFJO2dCQUNKLE1BQU07Z0JBQ04sV0FBVztnQkFDWCxLQUFLLEVBQUUsUUFBUSxDQUFDLEtBQUssSUFBSSxLQUFLO2dCQUM5QixZQUFZLEVBQUUscUJBQXFCLENBQUMsTUFBTSxFQUFFLGFBQWEsQ0FBQztnQkFDMUQsR0FBRyxFQUFFLFFBQVE7YUFDZCxDQUFDO1FBQ0osQ0FBQztRQUVELEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBd0I7WUFDbEMsSUFBSSxDQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsQ0FBQztnQkFDeEIsTUFBTSxJQUFJLDBCQUFrQixDQUFDLFFBQVEsRUFBRSwwQkFBMEIsQ0FBQyxDQUFDO1lBQ3JFLENBQUM7WUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDO2dCQUM5QyxLQUFLLEVBQUUsd0JBQXdCO2dCQUMvQixLQUFLO2FBQ04sQ0FBQyxDQUFDO1lBRUgsT0FBTyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM3QyxDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsY0FBYyxDQUFDLElBQVk7SUFDbEMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDO0FBQ25ELENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMscUJBQXFCLENBQUMsTUFBZTtJQUM1QyxJQUFJLENBQUMsTUFBTTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQzlCLE1BQU0sR0FBRyxHQUFnRDtRQUN2RCxNQUFNLEVBQUUsTUFBTTtRQUNkLFFBQVEsRUFBRSxRQUFRO1FBQ2xCLGdCQUFnQixFQUFFLGdCQUFnQjtRQUNsQyxZQUFZLEVBQUUsWUFBWTtRQUMxQixlQUFlLEVBQUUsWUFBWTtLQUM5QixDQUFDO0lBQ0YsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDO0FBQy9CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE9wZW5BSSBBZGFwdGVyXG4gKiBcbiAqIEFkYXB0ZXIgZm9yIE9wZW5BSSBBUEkgKEdQVC00LCBHUFQtMy41LCBldGMuKVxuICogXG4gKiBAbW9kdWxlIGFkYXB0ZXJzL3Byb3ZpZGVycy9vcGVuYWlcbiAqIEBhdXRob3IgSGFpZWNcbiAqIEBsaWNlbnNlIE1JVFxuICovXG5cbmltcG9ydCB7IExsbUNsaWVudCwgTGxtUmVxdWVzdCwgTGxtUmVzcG9uc2UsIEFkYXB0ZXJDb25maWcsIEFkYXB0ZXJDb25maWdFcnJvciB9IGZyb20gJy4uL3R5cGVzJztcblxuLyoqXG4gKiBPcGVuQUkgU0RLIGNsaWVudCBpbnRlcmZhY2UgKG1pbmltYWwgdHlwaW5nIGZvciBjb21wYXRpYmlsaXR5KS5cbiAqL1xuaW50ZXJmYWNlIE9wZW5BSUNsaWVudCB7XG4gIGNoYXQ6IHtcbiAgICBjb21wbGV0aW9uczoge1xuICAgICAgY3JlYXRlKHBhcmFtczoge1xuICAgICAgICBtb2RlbDogc3RyaW5nO1xuICAgICAgICBtZXNzYWdlczogQXJyYXk8eyByb2xlOiBzdHJpbmc7IGNvbnRlbnQ6IHN0cmluZyB9PjtcbiAgICAgICAgdGVtcGVyYXR1cmU/OiBudW1iZXI7XG4gICAgICAgIG1heF90b2tlbnM/OiBudW1iZXI7XG4gICAgICAgIHN0b3A/OiBzdHJpbmdbXTtcbiAgICAgIH0pOiBQcm9taXNlPHtcbiAgICAgICAgY2hvaWNlczogQXJyYXk8e1xuICAgICAgICAgIG1lc3NhZ2U/OiB7IGNvbnRlbnQ/OiBzdHJpbmcgfCBudWxsIH07XG4gICAgICAgICAgZmluaXNoX3JlYXNvbj86IHN0cmluZztcbiAgICAgICAgfT47XG4gICAgICAgIHVzYWdlPzoge1xuICAgICAgICAgIGNvbXBsZXRpb25fdG9rZW5zPzogbnVtYmVyO1xuICAgICAgICAgIHRvdGFsX3Rva2Vucz86IG51bWJlcjtcbiAgICAgICAgfTtcbiAgICAgICAgbW9kZWw/OiBzdHJpbmc7XG4gICAgICB9PjtcbiAgICB9O1xuICB9O1xuICBlbWJlZGRpbmdzPzoge1xuICAgIGNyZWF0ZShwYXJhbXM6IHsgbW9kZWw6IHN0cmluZzsgaW5wdXQ6IHN0cmluZyB8IHN0cmluZ1tdIH0pOiBQcm9taXNlPHtcbiAgICAgIGRhdGE6IEFycmF5PHsgZW1iZWRkaW5nOiBudW1iZXJbXSB9PjtcbiAgICB9PjtcbiAgfTtcbn1cblxuLyoqXG4gKiBCdWlsZHMgYW4gT3BlbkFJIGFkYXB0ZXIuXG4gKiBcbiAqIEBwYXJhbSBjb25maWcgLSBBZGFwdGVyIGNvbmZpZ3VyYXRpb25cbiAqIEByZXR1cm5zIExMTSBjbGllbnQgZm9yIE9wZW5BSVxuICogXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IE9wZW5BSSBmcm9tICdvcGVuYWknO1xuICogY29uc3Qgb3BlbmFpID0gbmV3IE9wZW5BSSh7IGFwaUtleTogcHJvY2Vzcy5lbnYuT1BFTkFJX0FQSV9LRVkgfSk7XG4gKiBjb25zdCBsbG0gPSBidWlsZE9wZW5BSUFkYXB0ZXIoeyBwcm92aWRlcjogJ29wZW5haScsIGNsaWVudDogb3BlbmFpIH0pO1xuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRPcGVuQUlBZGFwdGVyKGNvbmZpZzogQWRhcHRlckNvbmZpZyk6IExsbUNsaWVudCB7XG4gIGlmICghY29uZmlnLmNsaWVudCAmJiAhY29uZmlnLmFwaUtleSkge1xuICAgIHRocm93IG5ldyBBZGFwdGVyQ29uZmlnRXJyb3IoXG4gICAgICAnb3BlbmFpJyxcbiAgICAgICdPcGVuQUkgYWRhcHRlciByZXF1aXJlcyBlaXRoZXIgYSBjbGllbnQgaW5zdGFuY2Ugb3IgYXBpS2V5LiAnICtcbiAgICAgICdJbnN0YWxsIG9wZW5haSBwYWNrYWdlOiBucG0gaW5zdGFsbCBvcGVuYWknXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IGNsaWVudCA9IGNvbmZpZy5jbGllbnQgYXMgT3BlbkFJQ2xpZW50O1xuICBjb25zdCBkZWZhdWx0TW9kZWwgPSBjb25maWcuZGVmYXVsdE1vZGVsID8/ICdncHQtNG8tbWluaSc7XG5cbiAgcmV0dXJuIHtcbiAgICBwcm92aWRlcjogJ29wZW5haScsXG4gICAgcHJvdmlkZXJOYW1lOiAnT3BlbkFJJyxcblxuICAgIGFzeW5jIGdlbmVyYXRlKHJlcXVlc3Q6IExsbVJlcXVlc3QpOiBQcm9taXNlPExsbVJlc3BvbnNlPiB7XG4gICAgICBpZiAoIWNsaWVudCkge1xuICAgICAgICB0aHJvdyBuZXcgQWRhcHRlckNvbmZpZ0Vycm9yKCdvcGVuYWknLCAnQ2xpZW50IG5vdCBpbml0aWFsaXplZCcpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtb2RlbCA9IHJlcXVlc3QubW9kZWwgfHwgZGVmYXVsdE1vZGVsO1xuICAgICAgXG4gICAgICAvLyBCdWlsZCBtZXNzYWdlcyBhcnJheVxuICAgICAgY29uc3QgbWVzc2FnZXM6IEFycmF5PHsgcm9sZTogc3RyaW5nOyBjb250ZW50OiBzdHJpbmcgfT4gPSBbXTtcbiAgICAgIGlmIChyZXF1ZXN0LnN5c3RlbSkge1xuICAgICAgICBtZXNzYWdlcy5wdXNoKHsgcm9sZTogJ3N5c3RlbScsIGNvbnRlbnQ6IHJlcXVlc3Quc3lzdGVtIH0pO1xuICAgICAgfVxuICAgICAgbWVzc2FnZXMucHVzaCh7IHJvbGU6ICd1c2VyJywgY29udGVudDogcmVxdWVzdC5wcm9tcHQgfSk7XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmNoYXQuY29tcGxldGlvbnMuY3JlYXRlKHtcbiAgICAgICAgbW9kZWwsXG4gICAgICAgIG1lc3NhZ2VzLFxuICAgICAgICB0ZW1wZXJhdHVyZTogcmVxdWVzdC50ZW1wZXJhdHVyZSxcbiAgICAgICAgbWF4X3Rva2VuczogcmVxdWVzdC5tYXhUb2tlbnMsXG4gICAgICAgIHN0b3A6IHJlcXVlc3Quc3RvcFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGNob2ljZSA9IHJlc3BvbnNlLmNob2ljZXNbMF07XG4gICAgICBjb25zdCB0ZXh0ID0gY2hvaWNlPy5tZXNzYWdlPy5jb250ZW50Py50b1N0cmluZygpID8/ICcnO1xuICAgICAgY29uc3QgdG9rZW5zID0gcmVzcG9uc2UudXNhZ2U/LmNvbXBsZXRpb25fdG9rZW5zID8/IGVzdGltYXRlVG9rZW5zKHRleHQpO1xuICAgICAgY29uc3QgdG90YWxUb2tlbnMgPSByZXNwb25zZS51c2FnZT8udG90YWxfdG9rZW5zO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICB0ZXh0LFxuICAgICAgICB0b2tlbnMsXG4gICAgICAgIHRvdGFsVG9rZW5zLFxuICAgICAgICBtb2RlbDogcmVzcG9uc2UubW9kZWwgPz8gbW9kZWwsXG4gICAgICAgIGZpbmlzaFJlYXNvbjogbm9ybWFsaXplRmluaXNoUmVhc29uKGNob2ljZT8uZmluaXNoX3JlYXNvbiksXG4gICAgICAgIHJhdzogcmVzcG9uc2VcbiAgICAgIH07XG4gICAgfSxcblxuICAgIGFzeW5jIGVtYmVkKGlucHV0OiBzdHJpbmcgfCBzdHJpbmdbXSk6IFByb21pc2U8bnVtYmVyW11bXT4ge1xuICAgICAgaWYgKCFjbGllbnQ/LmVtYmVkZGluZ3MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEFkYXB0ZXJDb25maWdFcnJvcignb3BlbmFpJywgJ0VtYmVkZGluZ3Mgbm90IGF2YWlsYWJsZScpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC5lbWJlZGRpbmdzLmNyZWF0ZSh7XG4gICAgICAgIG1vZGVsOiAndGV4dC1lbWJlZGRpbmctMy1zbWFsbCcsXG4gICAgICAgIGlucHV0XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGEubWFwKGQgPT4gZC5lbWJlZGRpbmcpO1xuICAgIH1cbiAgfTtcbn1cblxuLyoqXG4gKiBFc3RpbWF0ZXMgdG9rZW4gY291bnQgZnJvbSB0ZXh0IChyb3VnaCBhcHByb3hpbWF0aW9uKS5cbiAqL1xuZnVuY3Rpb24gZXN0aW1hdGVUb2tlbnModGV4dDogc3RyaW5nKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGguY2VpbCh0ZXh0LnNwbGl0KC9cXHMrLykubGVuZ3RoICogMS4zKTtcbn1cblxuLyoqXG4gKiBOb3JtYWxpemVzIGZpbmlzaCByZWFzb24gdG8gc3RhbmRhcmQgZm9ybWF0LlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVGaW5pc2hSZWFzb24ocmVhc29uPzogc3RyaW5nKTogTGxtUmVzcG9uc2VbJ2ZpbmlzaFJlYXNvbiddIHtcbiAgaWYgKCFyZWFzb24pIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IG1hcDogUmVjb3JkPHN0cmluZywgTGxtUmVzcG9uc2VbJ2ZpbmlzaFJlYXNvbiddPiA9IHtcbiAgICAnc3RvcCc6ICdzdG9wJyxcbiAgICAnbGVuZ3RoJzogJ2xlbmd0aCcsXG4gICAgJ2NvbnRlbnRfZmlsdGVyJzogJ2NvbnRlbnRfZmlsdGVyJyxcbiAgICAndG9vbF9jYWxscyc6ICd0b29sX2NhbGxzJyxcbiAgICAnZnVuY3Rpb25fY2FsbCc6ICd0b29sX2NhbGxzJ1xuICB9O1xuICByZXR1cm4gbWFwW3JlYXNvbl0gPz8gcmVhc29uO1xufVxuIl19