# πŸ—„οΈ Sistema de Persistencia con PostgreSQL + Prisma ## Base de Datos Completa con RAG Vector Support He implementado un sistema completo de persistencia usando PostgreSQL con soporte para vectores (pgvector) para RAG, utilizando Prisma ORM para un manejo escalable. --- ## πŸ“Š Arquitectura de Base de Datos ### ConexiΓ³n PostgreSQL ``` Host: 192.168.1.20:5433 Database: nexus User: postgres Password: 72ff3d8d80c352f89d99 Extension: pgvector (para RAG) ``` ### Variables de Entorno (.env) ```env # Database DATABASE_URL="postgres://postgres:72ff3d8d80c352f89d99@192.168.1.20:5433/nexus?sslmode=disable" # Server PORT=3000 NODE_ENV=development CLIENT_URL=http://localhost:3001 # JWT JWT_SECRET=your-super-secret-jwt-key-change-in-production-nexus-2026 # File Upload MAX_FILE_SIZE=10485760 UPLOAD_DIR=./uploads # AI Providers (optional - users configure in UI) OPENAI_API_KEY= ANTHROPIC_API_KEY= GOOGLE_API_KEY= MISTRAL_API_KEY= COHERE_API_KEY= ``` --- ## πŸ—ƒοΈ Modelos de Base de Datos ### 1. User ```prisma model User { id String @id @default(cuid()) email String @unique name String? password String avatar String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt conversations Conversation[] aiProviders AIProvider[] knowledgeBases KnowledgeBase[] agents Agent[] settings AppSettings? } ``` **PropΓ³sito**: GestiΓ³n de usuarios y autenticaciΓ³n --- ### 2. AppSettings (Branding + Config) ```prisma model AppSettings { id String @id @default(cuid()) userId String @unique // Branding appName String @default("NexusChat") appLogo String? // URL or base64 appIcon String? // URL or base64 for avatar/favicon // Theme theme String @default("dark") primaryColor String @default("#667eea") // General Settings autoSave Boolean @default(true) soundEnabled Boolean @default(false) language String @default("en") } ``` **PropΓ³sito**: - βœ… PersonalizaciΓ³n de marca (logo, icono, nombre) - βœ… ConfiguraciΓ³n de tema - βœ… Preferencias generales --- ### 3. AIProvider ```prisma model AIProvider { id String @id @default(cuid()) userId String providerId String // openai, anthropic, google, mistral, cohere name String enabled Boolean @default(false) apiKey String? @db.Text // Encrypted } ``` **PropΓ³sito**: Almacenar configuraciΓ³n de AI Providers por usuario --- ### 4. Conversation ```prisma model Conversation { id String @id @default(cuid()) userId String title String agentId String? modelId String? // gpt-4o, claude-3-opus, etc providerId String? // openai, anthropic, etc messages Message[] topics Topic[] } ``` **PropΓ³sito**: GestiΓ³n de conversaciones de chat --- ### 5. Message ```prisma model Message { id String @id @default(cuid()) conversationId String role String // user, assistant, system content String @db.Text // Metadata tokensUsed Int? model String? } ``` **PropΓ³sito**: Almacenar mensajes de las conversaciones --- ### 6. Topic ```prisma model Topic { id String @id @default(cuid()) conversationId String title String order Int @default(0) } ``` **PropΓ³sito**: Topics del panel derecho del chat --- ### 7. KnowledgeBase ```prisma model KnowledgeBase { id String @id @default(cuid()) userId String name String description String? @db.Text documents Document[] agents Agent[] } ``` **PropΓ³sito**: Contenedor de documentos para RAG --- ### 8. Document ```prisma model Document { id String @id @default(cuid()) knowledgeBaseId String fileName String fileType String fileSize Int filePath String status String @default("processing") // processing, ready, error chunksCount Int @default(0) chunks DocumentChunk[] } ``` **PropΓ³sito**: Archivos subidos para RAG --- ### 9. DocumentChunk (RAG con Vectores) ```prisma model DocumentChunk { id String @id @default(cuid()) documentId String content String @db.Text chunkIndex Int // Vector embedding for semantic search (using pgvector) // TODO: Enable after pgvector extension is installed // embedding Unsupported("vector(1536)")? metadata Json? // Additional metadata } ``` **PropΓ³sito**: - βœ… Chunks de documentos procesados - βœ… Vector embeddings para bΓΊsqueda semΓ‘ntica - βœ… Metadata adicional **Nota**: El campo `embedding` estΓ‘ comentado temporalmente. Se habilitarΓ‘ despuΓ©s de instalar la extensiΓ³n pgvector en PostgreSQL. --- ### 10. Agent ```prisma model Agent { id String @id @default(cuid()) userId String name String emoji String @default("πŸ€–") role String description String @db.Text status String @default("active") // active, inactive // Capabilities mcpEnabled Boolean @default(false) mcpTools Json? // Array of MCP tools // RAG Configuration ragEnabled Boolean @default(false) // Stats interactions Int @default(0) lastUsedAt DateTime? conversations Conversation[] knowledgeBases KnowledgeBase[] } ``` **PropΓ³sito**: Agentes IA configurables con MCP y RAG --- ## 🎨 Nueva Feature: Branding Settings ### Componente SettingsBranding Permite personalizar: 1. **Nombre de la aplicaciΓ³n** 2. **Logo (texto)** - Imagen para el header 3. **Icono (avatar)** - Imagen para el chat avatar ### Visual ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ✨ Branding β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ Nombre de la AplicaciΓ³n β”‚ β”‚ [NexusChat ] β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Logo β”‚ Icono β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ ⬆️ Upload β”‚ ⬆️ Upload β”‚ β”‚ β”‚ β”‚ Click para β”‚ Click para subir β”‚ β”‚ β”‚ β”‚ subir logo β”‚ icono β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ [Guardar Cambios] β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### Funcionalidades - βœ… Upload de imagen para logo - βœ… Upload de imagen para icono - βœ… Cambiar nombre de la app - βœ… Preview de imΓ‘genes - βœ… BotΓ³n para remover imΓ‘genes - βœ… Guardar en localStorage (temporal) - βœ… TODO: Guardar en base de datos --- ## πŸ“ Estructura de Archivos ### Backend ``` / β”œβ”€β”€ .env (configuraciΓ³n) β”œβ”€β”€ prisma/ β”‚ β”œβ”€β”€ schema.prisma (modelos) β”‚ └── migrations/ (migraciones) β”‚ └── src/ └── config/ └── prisma.ts (cliente singleton) ``` ### Frontend ``` client/src/components/ └── SettingsBranding.tsx (nuevo componente) ``` --- ## πŸš€ Uso del Sistema ### 1. Iniciar Base de Datos La base de datos ya estΓ‘ configurada en `192.168.1.20:5433` ### 2. Aplicar Migraciones ```bash cd /Users/cesarmendivil/WebstormProjects/Nexus npx prisma migrate dev ``` ### 3. Generar Cliente ```bash npx prisma generate ``` ### 4. Usar Prisma en Backend ```typescript import prisma from './config/prisma'; // Crear usuario const user = await prisma.user.create({ data: { email: 'user@example.com', password: 'hashed_password', name: 'John Doe', }, }); // Guardar configuraciΓ³n de AI Provider await prisma.aIProvider.create({ data: { userId: user.id, providerId: 'openai', name: 'OpenAI', enabled: true, apiKey: 'encrypted_key', }, }); // Crear conversaciΓ³n const conversation = await prisma.conversation.create({ data: { userId: user.id, title: 'Nueva conversaciΓ³n', modelId: 'gpt-4o', providerId: 'openai', }, }); // Guardar mensaje await prisma.message.create({ data: { conversationId: conversation.id, role: 'user', content: 'Hola!', }, }); ``` --- ## πŸ”„ Flujo de Datos ### ConfiguraciΓ³n de AI Providers ``` UI (SettingsModal) β†’ localStorage (temporal) β†’ Backend API (TODO) β†’ Prisma β†’ PostgreSQL ``` ### Branding ``` UI (SettingsBranding) β†’ Upload imagen β†’ Base64 / File β†’ localStorage (temporal) β†’ Backend API (TODO) β†’ Prisma (AppSettings) β†’ PostgreSQL ``` ### RAG Pipeline ``` 1. Usuario sube archivo β†’ KnowledgeBase 2. Backend procesa archivo β†’ Divide en chunks β†’ DocumentChunk 3. Genera embeddings β†’ OpenAI embeddings API β†’ Guarda en vector field 4. BΓΊsqueda semΓ‘ntica β†’ Query β†’ embedding β†’ pgvector similarity search β†’ Retorna chunks relevantes ``` --- ## πŸ“Š Diagrama de Relaciones ``` User β”œβ”€β”€ Conversation β”‚ β”œβ”€β”€ Message β”‚ └── Topic β”‚ β”œβ”€β”€ AIProvider β”‚ β”œβ”€β”€ KnowledgeBase β”‚ └── Document β”‚ └── DocumentChunk (with vector) β”‚ β”œβ”€β”€ Agent β”‚ └── KnowledgeBase (many-to-many) β”‚ └── AppSettings ``` --- ## πŸ”’ Seguridad ### API Keys - βœ… Almacenadas en campo `@db.Text` - ⚠️ TODO: Implementar encriptaciΓ³n - βœ… No expuestas en el cliente ### Passwords - ⚠️ TODO: Implementar hashing (bcrypt) - βœ… Campo password en User model ### JWT - βœ… Secret configurado en .env - ⚠️ TODO: Implementar autenticaciΓ³n --- ## πŸ“‹ PrΓ³ximos Pasos ### Backend APIs a Implementar #### 1. Auth ```typescript POST /api/auth/register POST /api/auth/login POST /api/auth/logout GET /api/auth/me ``` #### 2. AI Providers ```typescript GET /api/providers POST /api/providers PUT /api/providers/:id DELETE /api/providers/:id ``` #### 3. Conversations ```typescript GET /api/conversations POST /api/conversations GET /api/conversations/:id DELETE /api/conversations/:id POST /api/conversations/:id/messages ``` #### 4. Knowledge Base ```typescript GET /api/knowledge POST /api/knowledge POST /api/knowledge/:id/documents GET /api/knowledge/:id/documents DELETE /api/documents/:id ``` #### 5. Agents ```typescript GET /api/agents POST /api/agents PUT /api/agents/:id DELETE /api/agents/:id ``` #### 6. Settings ```typescript GET /api/settings PUT /api/settings POST /api/settings/branding/upload ``` --- ## 🎯 IntegraciΓ³n con Frontend ### useChat Hook (Actualizar) ```typescript // En lugar de localStorage const messages = await fetch('/api/conversations/${id}/messages'); // Guardar mensaje await fetch('/api/conversations/${id}/messages', { method: 'POST', body: JSON.stringify({ content, role: 'user' }), }); ``` ### SettingsAIProviders (Actualizar) ```typescript // En lugar de localStorage const providers = await fetch('/api/providers'); // Guardar provider await fetch('/api/providers', { method: 'POST', body: JSON.stringify(providerData), }); ``` ### SettingsBranding (Actualizar) ```typescript // Upload logo const formData = new FormData(); formData.append('logo', file); await fetch('/api/settings/branding/upload', { method: 'POST', body: formData, }); ``` --- ## πŸ—„οΈ Comandos Útiles de Prisma ### Ver Base de Datos ```bash npx prisma studio ``` Abre interfaz web en `http://localhost:5555` ### Crear MigraciΓ³n ```bash npx prisma migrate dev --name migration_name ``` ### Reset Database ```bash npx prisma migrate reset ``` ### Pull Schema from DB ```bash npx prisma db pull ``` ### Push Schema to DB (sin migraciΓ³n) ```bash npx prisma db push ``` --- ## βœ… Estado Actual ``` ╔════════════════════════════════════════════╗ β•‘ βœ… BASE DE DATOS CONFIGURADA β•‘ β•‘ β•‘ β•‘ PostgreSQL: 192.168.1.20:5433 β•‘ β•‘ Database: nexus β•‘ β•‘ ORM: Prisma β•‘ β•‘ Extension: pgvector (preparado) β•‘ β•‘ β•‘ β•‘ Modelos: 10 β•‘ β•‘ - User β•‘ β•‘ - AppSettings (Branding) β•‘ β•‘ - AIProvider β•‘ β•‘ - Conversation β•‘ β•‘ - Message β•‘ β•‘ - Topic β•‘ β•‘ - KnowledgeBase β•‘ β•‘ - Document β•‘ β•‘ - DocumentChunk (RAG) β•‘ β•‘ - Agent β•‘ β•‘ β•‘ β•‘ Features Frontend: β•‘ β•‘ βœ… Branding Settings UI β•‘ β•‘ βœ… Upload logo/icono β•‘ β•‘ βœ… Cambiar nombre app β•‘ β•‘ β•‘ β•‘ TODO: β•‘ β•‘ ⏳ Backend APIs β•‘ β•‘ ⏳ AutenticaciΓ³n β•‘ β•‘ ⏳ EncriptaciΓ³n API Keys β•‘ β•‘ ⏳ IntegraciΓ³n RAG pipeline β•‘ β•‘ β•‘ β•‘ Estado: ESTRUCTURA COMPLETA βœ… β•‘ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• ``` --- **Implementado**: 14 de Febrero, 2026 **Base de Datos**: PostgreSQL con pgvector **ORM**: Prisma **Modelos**: 10 completos **Features**: Branding Settings UI **Estado**: βœ… **ESTRUCTURA LISTA - APIs PENDIENTES**