import assert from "node:assert/strict"; import fs from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; import vm from "node:vm"; import { addNode, createEmptyGraph, createNode } from "../graph/graph.js"; async function loadEnhancer() { const __dirname = path.dirname(fileURLToPath(import.meta.url)); const enhancerPath = path.resolve(__dirname, "../retrieval/retrieval-enhancer.js"); const source = await fs.readFile(enhancerPath, "utf8"); const transformed = `${source .replace(/^import[\s\S]*?from\s+["'][^"']+["'];\r?\n/gm, "") .replace(/export function /g, "function ") .replace(/export async function /g, "async function ")} this.exports = { applyDiversitySampling, createCooccurrenceIndex, nmfQueryAnalysis, sparseCodeResidual, splitIntentSegments, }; `; const context = vm.createContext({ Math, Date, console, WeakMap, Map, Set, Array, Number, String, JSON, embedText: async () => null, searchSimilar: () => [], getNode(graph, nodeId) { return graph.nodes.find((node) => node.id === nodeId) || null; }, isDirectVectorConfig() { return true; }, }); new vm.Script(transformed).runInContext(context); return context.exports; } const { applyDiversitySampling, createCooccurrenceIndex, nmfQueryAnalysis, sparseCodeResidual, splitIntentSegments, } = await loadEnhancer(); const segments = splitIntentSegments("规则一,然后规则二。另外规则三", { maxSegments: 4, }); assert.deepEqual(Array.from(segments), ["规则一", "规则二", "规则三"]); const diversity = applyDiversitySampling( [ { nodeId: "a", finalScore: 0.95, node: { embedding: [1, 0, 0] }, }, { nodeId: "b", finalScore: 0.9, node: { embedding: [0.99, 0.01, 0] }, }, { nodeId: "c", finalScore: 0.85, node: { embedding: [0, 1, 0] }, }, ], { k: 2, qualityWeight: 1.0 }, ); assert.equal(diversity.applied, true); assert.equal(diversity.selected.length, 2); assert.ok(Array.from(diversity.selected).some((item) => item.nodeId === "a")); assert.ok(Array.from(diversity.selected).some((item) => item.nodeId === "c")); const graph = createEmptyGraph(); const ruleA = createNode({ type: "rule", seq: 1, seqRange: [1, 2], fields: { title: "规则A" }, }); const ruleB = createNode({ type: "rule", seq: 2, seqRange: [2, 3], fields: { title: "规则B" }, }); const location = createNode({ type: "location", seq: 2, seqRange: [2, 2], fields: { name: "酒馆" }, }); addNode(graph, ruleA); addNode(graph, ruleB); addNode(graph, location); graph.batchJournal = [{ processedRange: [2, 2] }]; const cooccurrence = createCooccurrenceIndex(graph, { eligibleNodes: graph.nodes, maxAnchorsPerBatch: 10, }); assert.equal(cooccurrence.source, "batchJournal"); assert.equal(cooccurrence.batchCount, 1); assert.ok( (cooccurrence.map.get(ruleA.id) || []).some((item) => item.nodeId === ruleB.id), ); graph.batchJournal = []; const fallbackCooccurrence = createCooccurrenceIndex(graph, { eligibleNodes: graph.nodes, maxAnchorsPerBatch: 10, }); assert.equal(fallbackCooccurrence.source, "seqRange"); assert.ok( (fallbackCooccurrence.map.get(ruleA.id) || []).some( (item) => item.nodeId === ruleB.id, ), ); const nmf = nmfQueryAnalysis( [0.8, 0.6, 0, 0], [ [1, 0, 0, 0], [0, 1, 0, 0], ], { nTopics: 2, maxIter: 50 }, ); assert.ok(nmf.semanticDepth >= 0); assert.ok(nmf.novelty >= 0); const sparse = sparseCodeResidual( [0.8, 0.6, 0, 0], [ [1, 0, 0, 0], [0, 1, 0, 0], ], { lambda: 0.01, maxIter: 100 }, ); assert.ok(sparse.residualNorm < 0.2); console.log("retrieval-enhancer tests passed");