Files
memind/scripts/embed-memory-v2-local-hash.mjs
T
2026-07-03 09:46:03 +08:00

50 lines
1.5 KiB
JavaScript

const DEFAULT_DIMENSIONS = 3;
function resolveDimensions(value) {
const dimensions = Number(value ?? process.env.MEMORY_V2_LOCAL_EMBEDDING_DIMENSIONS ?? DEFAULT_DIMENSIONS);
if (!Number.isInteger(dimensions) || dimensions < 1 || dimensions > 4096) {
throw new Error(`Invalid MEMORY_V2_LOCAL_EMBEDDING_DIMENSIONS: ${value}`);
}
return dimensions;
}
function hashToken(token) {
let hash = 2166136261;
for (const char of String(token)) {
hash ^= char.codePointAt(0);
hash = Math.imul(hash, 16777619);
}
return hash >>> 0;
}
function tokenize(text) {
return String(text ?? '')
.toLowerCase()
.replace(/[^a-z0-9\u4e00-\u9fa5]+/gu, ' ')
.trim()
.split(/\s+/)
.filter(Boolean);
}
export function embedText(text, { dimensions = undefined } = {}) {
const resolvedDimensions = resolveDimensions(dimensions);
const vector = Array.from({ length: resolvedDimensions }, () => 0);
const tokens = tokenize(text);
for (const token of tokens.length ? tokens : ['empty']) {
const hash = hashToken(token);
const index = hash % resolvedDimensions;
const sign = hash & 1 ? 1 : -1;
vector[index] += sign * (1 + (token.length % 7));
}
const norm = Math.sqrt(vector.reduce((sum, value) => sum + value * value, 0)) || 1;
return vector.map((value) => Number((value / norm).toFixed(8)));
}
export async function embedQuery(query, input = {}) {
return embedText(query, {
dimensions: input.dimensions ?? input.embeddingDimensions,
});
}
export default embedQuery;