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.

107 lines 12.2 kB
"use strict"; /** * Text Similarity Utilities * * Simple similarity measures for consistency checking. * * @module utils/similarity * @author Haiec * @license MIT */ Object.defineProperty(exports, "__esModule", { value: true }); exports.jaccardSimilarity = jaccardSimilarity; exports.cosineSimilarity = cosineSimilarity; exports.levenshteinDistance = levenshteinDistance; exports.levenshteinSimilarity = levenshteinSimilarity; exports.combinedSimilarity = combinedSimilarity; /** * Calculate Jaccard similarity between two texts */ function jaccardSimilarity(text1, text2) { const words1 = new Set(text1.toLowerCase().split(/\s+/)); const words2 = new Set(text2.toLowerCase().split(/\s+/)); const intersection = new Set([...words1].filter(x => words2.has(x))); const union = new Set([...words1, ...words2]); if (union.size === 0) return 1; return intersection.size / union.size; } /** * Calculate cosine similarity using word frequency vectors */ function cosineSimilarity(text1, text2) { const freq1 = getWordFrequency(text1); const freq2 = getWordFrequency(text2); const allWords = new Set([...Object.keys(freq1), ...Object.keys(freq2)]); let dotProduct = 0; let norm1 = 0; let norm2 = 0; for (const word of allWords) { const v1 = freq1[word] || 0; const v2 = freq2[word] || 0; dotProduct += v1 * v2; norm1 += v1 * v1; norm2 += v2 * v2; } if (norm1 === 0 || norm2 === 0) return 0; return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2)); } /** * Get word frequency map */ function getWordFrequency(text) { const words = text.toLowerCase().split(/\s+/); const freq = {}; for (const word of words) { if (word.length > 0) { freq[word] = (freq[word] || 0) + 1; } } return freq; } /** * Calculate Levenshtein distance between two strings */ function levenshteinDistance(str1, str2) { const m = str1.length; const n = str2.length; const dp = Array(m + 1) .fill(null) .map(() => Array(n + 1).fill(0)); for (let i = 0; i <= m; i++) dp[i][0] = i; for (let j = 0; j <= n; j++) dp[0][j] = j; for (let i = 1; i <= m; i++) { for (let j = 1; j <= n; j++) { if (str1[i - 1] === str2[j - 1]) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]); } } } return dp[m][n]; } /** * Calculate normalized Levenshtein similarity (0-1) */ function levenshteinSimilarity(str1, str2) { const maxLen = Math.max(str1.length, str2.length); if (maxLen === 0) return 1; const distance = levenshteinDistance(str1, str2); return 1 - distance / maxLen; } /** * Combined similarity score using multiple methods */ function combinedSimilarity(text1, text2) { const jaccard = jaccardSimilarity(text1, text2); const cosine = cosineSimilarity(text1, text2); // Weighted average return jaccard * 0.4 + cosine * 0.6; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltaWxhcml0eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9zaW1pbGFyaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7R0FRRzs7QUFLSCw4Q0FVQztBQUtELDRDQXNCQztBQXFCRCxrREEwQkM7QUFLRCxzREFNQztBQUtELGdEQU1DO0FBN0dEOztHQUVHO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsS0FBYSxFQUFFLEtBQWE7SUFDNUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3pELE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUV6RCxNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckUsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFFOUMsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUM7UUFBRSxPQUFPLENBQUMsQ0FBQztJQUUvQixPQUFPLFlBQVksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQztBQUN4QyxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxLQUFhLEVBQUUsS0FBYTtJQUMzRCxNQUFNLEtBQUssR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN0QyxNQUFNLEtBQUssR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUV0QyxNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRXpFLElBQUksVUFBVSxHQUFHLENBQUMsQ0FBQztJQUNuQixJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDZCxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7SUFFZCxLQUFLLE1BQU0sSUFBSSxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQzVCLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUIsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUU1QixVQUFVLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUN0QixLQUFLLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUNqQixLQUFLLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUNuQixDQUFDO0lBRUQsSUFBSSxLQUFLLEtBQUssQ0FBQyxJQUFJLEtBQUssS0FBSyxDQUFDO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFFekMsT0FBTyxVQUFVLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUM1RCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGdCQUFnQixDQUFDLElBQVk7SUFDcEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM5QyxNQUFNLElBQUksR0FBMkIsRUFBRSxDQUFDO0lBRXhDLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDekIsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDckMsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLG1CQUFtQixDQUFDLElBQVksRUFBRSxJQUFZO0lBQzVELE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDdEIsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUV0QixNQUFNLEVBQUUsR0FBZSxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUNoQyxJQUFJLENBQUMsSUFBSSxDQUFDO1NBQ1YsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFbkMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUU7UUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzFDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFO1FBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUUxQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDNUIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzVCLElBQUksSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUM5QixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUNyQixFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUNaLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQ1osRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQ2pCLENBQUM7WUFDSixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNsQixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixxQkFBcUIsQ0FBQyxJQUFZLEVBQUUsSUFBWTtJQUM5RCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2xELElBQUksTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLENBQUMsQ0FBQztJQUUzQixNQUFNLFFBQVEsR0FBRyxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDakQsT0FBTyxDQUFDLEdBQUcsUUFBUSxHQUFHLE1BQU0sQ0FBQztBQUMvQixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixrQkFBa0IsQ0FBQyxLQUFhLEVBQUUsS0FBYTtJQUM3RCxNQUFNLE9BQU8sR0FBRyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDaEQsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRTlDLG1CQUFtQjtJQUNuQixPQUFPLE9BQU8sR0FBRyxHQUFHLEdBQUcsTUFBTSxHQUFHLEdBQUcsQ0FBQztBQUN0QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUZXh0IFNpbWlsYXJpdHkgVXRpbGl0aWVzXG4gKiBcbiAqIFNpbXBsZSBzaW1pbGFyaXR5IG1lYXN1cmVzIGZvciBjb25zaXN0ZW5jeSBjaGVja2luZy5cbiAqIFxuICogQG1vZHVsZSB1dGlscy9zaW1pbGFyaXR5XG4gKiBAYXV0aG9yIEhhaWVjXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuXG4vKipcbiAqIENhbGN1bGF0ZSBKYWNjYXJkIHNpbWlsYXJpdHkgYmV0d2VlbiB0d28gdGV4dHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGphY2NhcmRTaW1pbGFyaXR5KHRleHQxOiBzdHJpbmcsIHRleHQyOiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCB3b3JkczEgPSBuZXcgU2V0KHRleHQxLnRvTG93ZXJDYXNlKCkuc3BsaXQoL1xccysvKSk7XG4gIGNvbnN0IHdvcmRzMiA9IG5ldyBTZXQodGV4dDIudG9Mb3dlckNhc2UoKS5zcGxpdCgvXFxzKy8pKTtcbiAgXG4gIGNvbnN0IGludGVyc2VjdGlvbiA9IG5ldyBTZXQoWy4uLndvcmRzMV0uZmlsdGVyKHggPT4gd29yZHMyLmhhcyh4KSkpO1xuICBjb25zdCB1bmlvbiA9IG5ldyBTZXQoWy4uLndvcmRzMSwgLi4ud29yZHMyXSk7XG4gIFxuICBpZiAodW5pb24uc2l6ZSA9PT0gMCkgcmV0dXJuIDE7XG4gIFxuICByZXR1cm4gaW50ZXJzZWN0aW9uLnNpemUgLyB1bmlvbi5zaXplO1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZSBjb3NpbmUgc2ltaWxhcml0eSB1c2luZyB3b3JkIGZyZXF1ZW5jeSB2ZWN0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3NpbmVTaW1pbGFyaXR5KHRleHQxOiBzdHJpbmcsIHRleHQyOiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCBmcmVxMSA9IGdldFdvcmRGcmVxdWVuY3kodGV4dDEpO1xuICBjb25zdCBmcmVxMiA9IGdldFdvcmRGcmVxdWVuY3kodGV4dDIpO1xuICBcbiAgY29uc3QgYWxsV29yZHMgPSBuZXcgU2V0KFsuLi5PYmplY3Qua2V5cyhmcmVxMSksIC4uLk9iamVjdC5rZXlzKGZyZXEyKV0pO1xuICBcbiAgbGV0IGRvdFByb2R1Y3QgPSAwO1xuICBsZXQgbm9ybTEgPSAwO1xuICBsZXQgbm9ybTIgPSAwO1xuICBcbiAgZm9yIChjb25zdCB3b3JkIG9mIGFsbFdvcmRzKSB7XG4gICAgY29uc3QgdjEgPSBmcmVxMVt3b3JkXSB8fCAwO1xuICAgIGNvbnN0IHYyID0gZnJlcTJbd29yZF0gfHwgMDtcbiAgICBcbiAgICBkb3RQcm9kdWN0ICs9IHYxICogdjI7XG4gICAgbm9ybTEgKz0gdjEgKiB2MTtcbiAgICBub3JtMiArPSB2MiAqIHYyO1xuICB9XG4gIFxuICBpZiAobm9ybTEgPT09IDAgfHwgbm9ybTIgPT09IDApIHJldHVybiAwO1xuICBcbiAgcmV0dXJuIGRvdFByb2R1Y3QgLyAoTWF0aC5zcXJ0KG5vcm0xKSAqIE1hdGguc3FydChub3JtMikpO1xufVxuXG4vKipcbiAqIEdldCB3b3JkIGZyZXF1ZW5jeSBtYXBcbiAqL1xuZnVuY3Rpb24gZ2V0V29yZEZyZXF1ZW5jeSh0ZXh0OiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+IHtcbiAgY29uc3Qgd29yZHMgPSB0ZXh0LnRvTG93ZXJDYXNlKCkuc3BsaXQoL1xccysvKTtcbiAgY29uc3QgZnJlcTogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICBcbiAgZm9yIChjb25zdCB3b3JkIG9mIHdvcmRzKSB7XG4gICAgaWYgKHdvcmQubGVuZ3RoID4gMCkge1xuICAgICAgZnJlcVt3b3JkXSA9IChmcmVxW3dvcmRdIHx8IDApICsgMTtcbiAgICB9XG4gIH1cbiAgXG4gIHJldHVybiBmcmVxO1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZSBMZXZlbnNodGVpbiBkaXN0YW5jZSBiZXR3ZWVuIHR3byBzdHJpbmdzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsZXZlbnNodGVpbkRpc3RhbmNlKHN0cjE6IHN0cmluZywgc3RyMjogc3RyaW5nKTogbnVtYmVyIHtcbiAgY29uc3QgbSA9IHN0cjEubGVuZ3RoO1xuICBjb25zdCBuID0gc3RyMi5sZW5ndGg7XG4gIFxuICBjb25zdCBkcDogbnVtYmVyW11bXSA9IEFycmF5KG0gKyAxKVxuICAgIC5maWxsKG51bGwpXG4gICAgLm1hcCgoKSA9PiBBcnJheShuICsgMSkuZmlsbCgwKSk7XG4gIFxuICBmb3IgKGxldCBpID0gMDsgaSA8PSBtOyBpKyspIGRwW2ldWzBdID0gaTtcbiAgZm9yIChsZXQgaiA9IDA7IGogPD0gbjsgaisrKSBkcFswXVtqXSA9IGo7XG4gIFxuICBmb3IgKGxldCBpID0gMTsgaSA8PSBtOyBpKyspIHtcbiAgICBmb3IgKGxldCBqID0gMTsgaiA8PSBuOyBqKyspIHtcbiAgICAgIGlmIChzdHIxW2kgLSAxXSA9PT0gc3RyMltqIC0gMV0pIHtcbiAgICAgICAgZHBbaV1bal0gPSBkcFtpIC0gMV1baiAtIDFdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZHBbaV1bal0gPSAxICsgTWF0aC5taW4oXG4gICAgICAgICAgZHBbaSAtIDFdW2pdLFxuICAgICAgICAgIGRwW2ldW2ogLSAxXSxcbiAgICAgICAgICBkcFtpIC0gMV1baiAtIDFdXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIFxuICByZXR1cm4gZHBbbV1bbl07XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIG5vcm1hbGl6ZWQgTGV2ZW5zaHRlaW4gc2ltaWxhcml0eSAoMC0xKVxuICovXG5leHBvcnQgZnVuY3Rpb24gbGV2ZW5zaHRlaW5TaW1pbGFyaXR5KHN0cjE6IHN0cmluZywgc3RyMjogc3RyaW5nKTogbnVtYmVyIHtcbiAgY29uc3QgbWF4TGVuID0gTWF0aC5tYXgoc3RyMS5sZW5ndGgsIHN0cjIubGVuZ3RoKTtcbiAgaWYgKG1heExlbiA9PT0gMCkgcmV0dXJuIDE7XG4gIFxuICBjb25zdCBkaXN0YW5jZSA9IGxldmVuc2h0ZWluRGlzdGFuY2Uoc3RyMSwgc3RyMik7XG4gIHJldHVybiAxIC0gZGlzdGFuY2UgLyBtYXhMZW47XG59XG5cbi8qKlxuICogQ29tYmluZWQgc2ltaWxhcml0eSBzY29yZSB1c2luZyBtdWx0aXBsZSBtZXRob2RzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21iaW5lZFNpbWlsYXJpdHkodGV4dDE6IHN0cmluZywgdGV4dDI6IHN0cmluZyk6IG51bWJlciB7XG4gIGNvbnN0IGphY2NhcmQgPSBqYWNjYXJkU2ltaWxhcml0eSh0ZXh0MSwgdGV4dDIpO1xuICBjb25zdCBjb3NpbmUgPSBjb3NpbmVTaW1pbGFyaXR5KHRleHQxLCB0ZXh0Mik7XG4gIFxuICAvLyBXZWlnaHRlZCBhdmVyYWdlXG4gIHJldHVybiBqYWNjYXJkICogMC40ICsgY29zaW5lICogMC42O1xufVxuIl19