feat(secretaria): RAG sem pgvector no conhecimento (embeddings + cosseno)
Adiciona busca semântica na Base de Conhecimento da secretária: - embeddings.ts: chunking, embed (OpenAI text-embedding-3-small ou Gemini text-embedding-004) e similaridade cosseno — tudo na aplicação, sem pgvector. - tabela sec_knowledge_chunks (vetor em JSON/text) com índices. - brain.ts: no nó 'knowledge', injeta só os top-4 trechos relevantes à pergunta do usuário; indexação lazy por hash do conteúdo. Fallback para o conteúdo inteiro se não houver chave de embedding ou em qualquer falha (não regride). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,23 @@ async function runMigrations(db) {
|
||||
t.timestamps(true, true);
|
||||
});
|
||||
}
|
||||
// ── sec_knowledge_chunks (RAG sem pgvector) ───────────────────────────────
|
||||
// Chunks de conhecimento + embedding (JSON em text). Busca por similaridade
|
||||
// roda na aplicação (cosseno), então não exige a extensão pgvector.
|
||||
if (!(await db.schema.hasTable('sec_knowledge_chunks'))) {
|
||||
await db.schema.createTable('sec_knowledge_chunks', (t) => {
|
||||
t.uuid('id').primary().defaultTo(db.raw('gen_random_uuid()'));
|
||||
t.uuid('agent_id').notNullable().references('id').inTable('sec_agents').onDelete('CASCADE');
|
||||
t.uuid('node_id').notNullable();
|
||||
t.string('content_hash', 40).notNullable(); // detecta quando reindexar
|
||||
t.integer('chunk_index').notNullable().defaultTo(0);
|
||||
t.text('content').notNullable();
|
||||
t.text('embedding').notNullable(); // vetor serializado em JSON
|
||||
t.timestamps(true, true);
|
||||
});
|
||||
await db.raw('CREATE INDEX IF NOT EXISTS idx_sec_chunks_agent ON sec_knowledge_chunks (agent_id)');
|
||||
await db.raw('CREATE INDEX IF NOT EXISTS idx_sec_chunks_node ON sec_knowledge_chunks (node_id)');
|
||||
}
|
||||
// ── Seeds: agente padrão + nós + calendário ───────────────────────────────
|
||||
const agentCount = await db('sec_agents').count('id as c').first();
|
||||
if (Number(agentCount?.c ?? 0) === 0) {
|
||||
|
||||
Reference in New Issue
Block a user