1. Recherche: fetchChunkSnippets() — après le classement RRF existant, récupère les passages précis qui matchent depuis NoteEmbeddingChunk. Pur affichage, AUCUN changement de classement. 2. Script migration: scripts/migrate-chunk-embeddings.ts Indexe toutes les notes existantes en fragments. Batch de 10, barre de progression. Usage: npx tsx scripts/migrate-chunk-embeddings.ts 3. Memory Echo chunk-level: à faire (US restante)
52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
/**
|
|
* Script de migration : indexe toutes les notes existantes en fragments.
|
|
* Usage: npx tsx scripts/migrate-chunk-embeddings.ts
|
|
*/
|
|
import prisma from '@/lib/prisma'
|
|
import { chunkIndexingService } from '@/lib/ai/services/chunk-indexing.service'
|
|
|
|
async function main() {
|
|
console.log('=== Migration des chunks d\'embeddings ===\n')
|
|
|
|
const notes = await prisma.note.findMany({
|
|
where: {
|
|
trashedAt: null,
|
|
noteEmbedding: { isNot: null },
|
|
},
|
|
select: { id: true, title: true, content: true },
|
|
orderBy: { createdAt: 'asc' },
|
|
})
|
|
|
|
console.log(`${notes.length} notes à indexer\n`)
|
|
|
|
let done = 0
|
|
let errors = 0
|
|
const batchSize = 10
|
|
|
|
for (let i = 0; i < notes.length; i += batchSize) {
|
|
const batch = notes.slice(i, i + batchSize)
|
|
|
|
await Promise.all(batch.map(async (note) => {
|
|
try {
|
|
const result = await chunkIndexingService.indexNote(note.id, note.title, note.content)
|
|
if (result.newFragments > 0) {
|
|
done++
|
|
}
|
|
} catch (e: any) {
|
|
errors++
|
|
console.error(` ✗ ${note.title?.slice(0, 40)}: ${e.message}`)
|
|
}
|
|
}))
|
|
|
|
process.stdout.write(`\r${Math.min(i + batchSize, notes.length)}/${notes.length} traitées`)
|
|
}
|
|
|
|
console.log(`\n\n=== Terminé ===`)
|
|
console.log(`Notes indexées: ${done}`)
|
|
console.log(`Erreurs: ${errors}`)
|
|
|
|
await prisma.$disconnect()
|
|
}
|
|
|
|
main().catch(console.error)
|