()
| 93 | } |
| 94 | |
| 95 | function main() { |
| 96 | const [oldPath, newPath] = process.argv.slice(2); |
| 97 | if (!oldPath || !newPath) { |
| 98 | console.error( |
| 99 | "Usage: bun packages/plugin/scripts/embedding-baseline-diff.ts <old.json> <new.json>", |
| 100 | ); |
| 101 | process.exit(1); |
| 102 | } |
| 103 | |
| 104 | const oldSnap = loadSnapshot(oldPath); |
| 105 | const newSnap = loadSnapshot(newPath); |
| 106 | |
| 107 | console.log(""); |
| 108 | console.log("─── Snapshot meta ─────────────────────────────────────────"); |
| 109 | console.log(`OLD: ${oldSnap.modelId} (dim=${oldSnap.embeddingDim}) ${oldSnap.timestamp}`); |
| 110 | console.log(`NEW: ${newSnap.modelId} (dim=${newSnap.embeddingDim}) ${newSnap.timestamp}`); |
| 111 | console.log( |
| 112 | `memories considered: old=${oldSnap.stats.memoriesConsidered} new=${newSnap.stats.memoriesConsidered} topK=${oldSnap.stats.topK}`, |
| 113 | ); |
| 114 | console.log( |
| 115 | `avg query latency: old=${oldSnap.stats.queryEmbedLatencyMs.avg}ms new=${newSnap.stats.queryEmbedLatencyMs.avg}ms`, |
| 116 | ); |
| 117 | |
| 118 | // Build a map for quick lookup. |
| 119 | const newById = new Map(newSnap.queries.map((q) => [q.id, q])); |
| 120 | |
| 121 | // Per-query metrics. |
| 122 | interface Row { |
| 123 | id: string; |
| 124 | group: string; |
| 125 | text: string; |
| 126 | oldTop1: number; |
| 127 | newTop1: number; |
| 128 | oldTop10: number; |
| 129 | newTop10: number; |
| 130 | top1Changed: boolean; |
| 131 | tau: number | null; |
| 132 | overlapCount: number; |
| 133 | } |
| 134 | const rows: Row[] = []; |
| 135 | |
| 136 | for (const oldQ of oldSnap.queries) { |
| 137 | const newQ = newById.get(oldQ.id); |
| 138 | if (!newQ) continue; |
| 139 | const oldIds = oldQ.topK.map((t) => t.memoryId); |
| 140 | const newIds = newQ.topK.map((t) => t.memoryId); |
| 141 | const newSet = new Set(newIds); |
| 142 | const overlap = new Set(oldIds.filter((id) => newSet.has(id))); |
| 143 | rows.push({ |
| 144 | id: oldQ.id, |
| 145 | group: oldQ.group, |
| 146 | text: oldQ.text, |
| 147 | oldTop1: oldQ.topK[0]?.score ?? 0, |
| 148 | newTop1: newQ.topK[0]?.score ?? 0, |
| 149 | oldTop10: oldQ.topK[oldQ.topK.length - 1]?.score ?? 0, |
| 150 | newTop10: newQ.topK[newQ.topK.length - 1]?.score ?? 0, |
| 151 | top1Changed: oldIds[0] !== newIds[0], |
| 152 | tau: kendallTau(oldIds, newIds), |
no test coverage detected