- API: /api/ai/chat, /conversations, /documents con embeddings qwen3-embedding, coseno en SQLite, dedup por hash, historial de conversaciones - Base de conocimiento semilla (6 docs, 36 chunks): catálogo DIAGONAL, propuestas del cotizador, créditos, proceso de venta, FAQ, privacidad - App agente-ia (Vite/React/Tailwind, StudioBlank) servida en /ai/ vía nginx - 21 tests nuevos (91/91 verdes)
42 lines
1.6 KiB
TypeScript
42 lines
1.6 KiB
TypeScript
/**
|
|
* Seed de la base de conocimiento del agente IA.
|
|
* Lee knowledge/*.md, usa el primer encabezado H1 como título y los indexa
|
|
* vía indexarDocumento (idempotente: solo re-embebe si cambió el hash).
|
|
*
|
|
* Uso: npm run seed:ai (requiere NAN_API_KEY en el .env del ecosistema)
|
|
*/
|
|
import { readdir, readFile } from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import { indexarDocumento } from '../src/services/ai.service.js'
|
|
|
|
const KNOWLEDGE_DIR = path.resolve(process.cwd(), 'knowledge')
|
|
|
|
function tituloDe(contenido: string, archivo: string): string {
|
|
const h1 = contenido.split('\n').find((l) => l.startsWith('# '))
|
|
return h1 ? h1.replace(/^#\s+/, '').trim() : archivo.replace(/\.md$/, '')
|
|
}
|
|
|
|
async function main(): Promise<void> {
|
|
const archivos = (await readdir(KNOWLEDGE_DIR)).filter((f) => f.endsWith('.md')).sort()
|
|
if (archivos.length === 0) {
|
|
console.error(`No hay archivos .md en ${KNOWLEDGE_DIR}`)
|
|
process.exit(1)
|
|
}
|
|
console.log(`Indexando ${archivos.length} documentos desde ${KNOWLEDGE_DIR}…`)
|
|
let totalChunks = 0
|
|
for (const archivo of archivos) {
|
|
const contenido = await readFile(path.join(KNOWLEDGE_DIR, archivo), 'utf8')
|
|
const titulo = tituloDe(contenido, archivo)
|
|
const r = await indexarDocumento(titulo, contenido)
|
|
totalChunks += r.chunks
|
|
console.log(` ${r.estado.padEnd(12)} ${titulo} (${r.chunks} chunks)`)
|
|
}
|
|
console.log(`Listo: ${archivos.length} documentos procesados.`)
|
|
process.exit(0)
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error('Falló el seed:', err instanceof Error ? err.message : err)
|
|
process.exit(1)
|
|
})
|