Base de Datos Vectorial (Qdrant)
¿Por qué Qdrant?
Section titled “¿Por qué Qdrant?”Qdrant es la base de datos vectorial que permite al AI Backend realizar búsqueda semántica de alta calidad. Almacena representaciones vectoriales del contenido para recuperar los chunks más relevantes dado un query.
Colecciones
Section titled “Colecciones”| Colección | Propósito | Dimensiones | Modelo de embedding |
|---|---|---|---|
lesson_content | Embeddings de lecciones para búsqueda semántica | 1536 | text-embedding-3-small |
tutor_context | Contexto conversacional del tutor por usuario | 1536 | text-embedding-3-small |
user_profiles | Vectores de perfil de aprendizaje por usuario | 1536 | text-embedding-3-small |
quiz_questions | Banco de preguntas para deduplicación | 1536 | text-embedding-3-small |
QdrantService
Section titled “QdrantService”Archivo: apps/ai-backend/src/modules/vector-db/qdrant.service.ts
// Operaciones principalessearch(collection: string, vector: number[], limit: number, filter?: object): Promise<SearchResult[]>upsert(collection: string, points: VectorPoint[]): Promise<void>healthCheck(): Promise<{ status: 'ok' | 'error'; collections: string[]; vectorCount: number }>getCollectionInfo(collection: string): Promise<CollectionInfo>El servicio usa lazy initialization: las colecciones se crean si no existen al primer upsert.
EmbeddingService
Section titled “EmbeddingService”Archivo: apps/ai-backend/src/modules/vector-db/embedding.service.ts
- Genera embeddings con
OpenAIAdapterusandotext-embedding-3-small - Caché en memoria (por
text-hash → vector) para no regenerar embeddings idénticos - Los embeddings cacheados tienen TTL de 1 hora
async embed(text: string): Promise<number[]> { const hash = sha256(text); if (this.cache.has(hash)) return this.cache.get(hash)!;
const vector = await this.openai.createEmbedding(text, 'text-embedding-3-small'); this.cache.set(hash, { vector, cachedAt: Date.now() }); return vector;}IndexingService (Listener de eventos)
Section titled “IndexingService (Listener de eventos)”Archivo: apps/ai-backend/src/modules/vector-db/indexing.service.ts
Escucha el evento lesson.published desde apps/api y automáticamente indexa la lección en Qdrant:
sequenceDiagram participant API as apps/api participant AI as apps/ai-backend participant Q as Qdrant
API->>AI: POST /usecases/indexing/index-lesson {lessonId} AI->>API: GET /internal/lessons/:id (contenido completo) API-->>AI: { title, markdownContent, videoTranscript } AI->>AI: EmbeddingService.embed(content) AI->>Q: upsert('lesson_content', [{ id: lessonId, vector, payload }]) AI-->>API: { indexed: true, vectorId: lessonId }Job de reindexación completa
Section titled “Job de reindexación completa”Accesible desde el panel admin (/admin/ai/vector-db):
POST /admin/vector-db/reindex-allReindexará todas las lecciones publicadas. El proceso corre en background y devuelve un job ID para polling del estado.