Agrega uMind: chat con IA embebible por tenant (F1 — widget web + RAG)
Multi-tenant dentro de soft_usite, reutilizando la infraestructura ya existente (AiConfig, motor de function-calling del agente de Telegram) en vez de un servicio nuevo aparte: - UmindTenant: sitio/cliente con dominios permitidos, config de IA para el chat y personalidad/tono. - Ingesta: crawler simple (mismo dominio, N páginas) + chunking + embeddings (config global con módulo "umind_embeddings", pensada para OpenAI ya que Claude no ofrece embeddings) guardados como JSON, con búsqueda por similitud coseno en memoria (sin pgvector todavía). - Agente acotado: única herramienta buscar_conocimiento, sin acceso a nada interno — si no encuentra la respuesta, lo dice en vez de inventar. - Widget público (/widget/umind.js + /widget/:site_key/*), autenticado por site_key + validación de dominio (Origin/Referer), no por secreto, ya que la key viaja en el HTML público del sitio instalado. - Panel /app/umind: tenants, estado de ingesta, historial de conversaciones por sesión.
This commit is contained in:
@@ -194,3 +194,26 @@ func GetWhisperConfig() (*AiConfig, error) {
|
||||
}
|
||||
return nil, fmt.Errorf("no hay ninguna configuración activa con el módulo 'whisper' en /app/ai-config")
|
||||
}
|
||||
|
||||
// GetUmindEmbeddingsConfig retorna la config activa etiquetada con el módulo
|
||||
// "umind_embeddings" (usada para generar los vectores de la base de
|
||||
// conocimiento de todos los tenants de uMind). Es global, no por tenant: los
|
||||
// embeddings de un tenant solo son comparables entre sí si se generaron con
|
||||
// el mismo modelo, así que cambiar de config invalida los chunks existentes
|
||||
// (habría que reingestar). Sin fallback, igual que GetWhisperConfig — Claude
|
||||
// no ofrece embeddings, así que aquí sí importa exigir una config explícita
|
||||
// en vez de caer a cualquier config activa.
|
||||
func GetUmindEmbeddingsConfig() (*AiConfig, error) {
|
||||
var items []AiConfig
|
||||
if err := app.Http.Database.DB.Where("is_active = ?", true).Find(&items).Error; err != nil {
|
||||
return nil, fmt.Errorf("error leyendo ai_configs: %w", err)
|
||||
}
|
||||
for i := range items {
|
||||
for _, m := range SplitModulos(items[i].Modulo) {
|
||||
if m == "umind_embeddings" {
|
||||
return &items[i], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no hay ninguna configuración activa con el módulo 'umind_embeddings' en /app/ai-config (necesaria para generar embeddings, ej. un proveedor OpenAI)")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user