feat: leer comprobantes via OCR externo + Gemini solo-texto
Antes, si Gemini Vision fallaba (cuota/API), el 100% de los comprobantes del chat web quedaban sin poder leerse. Ahora el job intenta primero un servicio OCR externo configurable (imagen -> texto) y le pasa el texto a Gemini para que solo lo estructure en JSON, más barato y sin la cuota de visión. Si el OCR no está habilitado o falla, cae al método anterior (Gemini leyendo la imagen directamente) sin romper nada. Agrega configuración en el panel (URL/token/habilitado + probar conexión) y la spec del servicio OCR a desplegar en docs/ocr-service-spec.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
7f4053ea62
commit
7afd22d581
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\ChatConfig;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class OcrExtractionService
|
||||
{
|
||||
private string $url;
|
||||
private string $token;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->url = rtrim(ChatConfig::get('ocr_url', ''), '/');
|
||||
$this->token = ChatConfig::get('ocr_token', '');
|
||||
}
|
||||
|
||||
public function habilitado(): bool
|
||||
{
|
||||
return ChatConfig::get('ocr_habilitado', '0') === '1' && $this->url !== '';
|
||||
}
|
||||
|
||||
/** Envia la imagen al servicio OCR externo y devuelve el texto crudo, o null si falla. */
|
||||
public function extraerTexto(string $base64, string $mimeType): ?string
|
||||
{
|
||||
if (! $this->url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
$response = Http::withToken($this->token)
|
||||
->timeout(20)
|
||||
->post("{$this->url}/extract", [
|
||||
'image_base64' => $base64,
|
||||
'mime_type' => $mimeType,
|
||||
]);
|
||||
|
||||
if (! $response->successful()) {
|
||||
Log::warning('[OCR] HTTP ' . $response->status() . ': ' . substr($response->body(), 0, 300));
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = $response->json();
|
||||
|
||||
if (! ($data['success'] ?? false) || empty($data['text'])) {
|
||||
Log::warning('[OCR] respuesta sin texto util: ' . substr($response->body(), 0, 300));
|
||||
return null;
|
||||
}
|
||||
|
||||
return $data['text'];
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('[OCR] excepcion: ' . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user