diff --git a/pkg/services/ia.service.go b/pkg/services/ia.service.go deleted file mode 100644 index b7ea73f..0000000 --- a/pkg/services/ia.service.go +++ /dev/null @@ -1,68 +0,0 @@ -package services - -import ( - "bufio" - "bytes" - "encoding/json" - "net/http" -) - -// DataIa estructura para el request a Ollama -type DataIa struct { - Prompt string `json:"prompt"` - Model string `json:"model"` - Stream bool `json:"stream"` -} - -// respuestaOllama estructura para parsear la respuesta de Ollama -type respuestaOllama struct { - Response string `json:"response"` - Done bool `json:"done"` -} - -// GenerateTextoStream lee respuesta de Ollama en tiempo real y devuelve canal -func GenerateTextoStream(data DataIa) (<-chan string, error) { - out := make(chan string) - - // Convertir datos a JSON - jsonData, err := json.Marshal(data) - if err != nil { - return nil, err - } - - // Crear request con cabecera personalizada - req, err := http.NewRequest("POST", "http://72.60.24.97:8080/ollama/api/generate", bytes.NewBuffer(jsonData)) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", "Bearer sk-43804e00f5294200ad1e599550fbee4f") - - // Ejecutar request - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - return nil, err - } - - // Procesar en goroutine - go func() { - defer resp.Body.Close() - defer close(out) - - scanner := bufio.NewScanner(resp.Body) - for scanner.Scan() { - var msg respuestaOllama - if err := json.Unmarshal(scanner.Bytes(), &msg); err == nil { - if msg.Response != "" { - out <- msg.Response - } - if msg.Done { - break - } - } - } - }() - - return out, nil -} diff --git a/rest/controllers/api/ia_controller.go b/rest/controllers/api/ia_controller.go index f345ee8..7d1e3d8 100644 --- a/rest/controllers/api/ia_controller.go +++ b/rest/controllers/api/ia_controller.go @@ -33,11 +33,12 @@ func GeneraTextoStream(c *fiber.Ctx) error { config, err := models.GetAiConfigForService("ia") if err != nil { - return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{ - "error": "No hay configuración de IA activa. Configura una en /app/ai-config", - }) + config = &models.AiConfig{ + BaseURL: "http://72.60.24.97:8080/ollama", + ApiKey: "", + ModelName: "gemma3:1b", + } } - if data.Model == "" { data.Model = config.ModelName } @@ -45,7 +46,6 @@ func GeneraTextoStream(c *fiber.Ctx) error { data.Model = "gemma3:1b" } - // Usar endpoint nativo de Ollama (/api/generate), no OpenAI compat (/v1/...) baseURL := strings.TrimSuffix(strings.TrimRight(config.BaseURL, "/"), "/v1") endpoint := baseURL + "/api/generate" @@ -55,7 +55,6 @@ func GeneraTextoStream(c *fiber.Ctx) error { return err } req.Header.Set("Content-Type", "application/json") - // Sin auth para red interna; api_key como token para URL pública if config.ApiKey != "" && config.ApiKey != "ollama" { req.SetBasicAuth("ollama", config.ApiKey) } @@ -65,6 +64,12 @@ func GeneraTextoStream(c *fiber.Ctx) error { if err != nil { return c.Status(fiber.StatusBadGateway).JSON(fiber.Map{"error": err.Error()}) } + if resp.StatusCode != http.StatusOK { + resp.Body.Close() + return c.Status(fiber.StatusBadGateway).JSON(fiber.Map{ + "error": fmt.Sprintf("Ollama respondió con status %d", resp.StatusCode), + }) + } c.Set("Content-Type", "text/plain; charset=utf-8") c.Set("Cache-Control", "no-cache") @@ -73,6 +78,7 @@ func GeneraTextoStream(c *fiber.Ctx) error { c.Context().SetBodyStreamWriter(func(w *bufio.Writer) { defer resp.Body.Close() scanner := bufio.NewScanner(resp.Body) + scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024) for scanner.Scan() { line := scanner.Bytes() if len(line) == 0 {