Funktioniert

This commit is contained in:
2026-06-01 10:33:30 +02:00
parent ac9ab7ab15
commit fb185c1a71
11 changed files with 92 additions and 31 deletions

View File

@@ -7,25 +7,42 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
/**
* REST-Endpunkte des Dokumenten-Check-Backend.
*
* POST /check/{projectId}
* → Startet die asynchrone Verarbeitung eines Projekts.
* → Gibt sofort 202 Accepted zurück; Fortschritt über ORDS-Endpunkte ablesbar.
* → Reiht das Projekt in eine sequentielle Warteschlange ein (202 sofort).
* → Projekte werden strikt nacheinander verarbeitet (kein paralleler Betrieb).
*
* GET /check/health
* → Einfacher Health-Check.
* → Einfacher Health-Check inkl. Warteschlangenlänge.
*/
@Path("/check")
@Produces(MediaType.APPLICATION_JSON)
@Tag(name = "Dokumenten-Check", description = "KI-gestützte Dokumentenprüfung")
public class CheckResource {
private static final Logger LOG = Logger.getLogger(CheckResource.class);
// Single-Thread-Executor: garantiert sequentielle Abarbeitung.
// Eingehende Aufrufe werden automatisch in die Warteschlange gelegt.
private static final ExecutorService QUEUE =
Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "dc-processing-thread");
t.setDaemon(true);
return t;
});
// Anzahl Projekte in der Warteschlange (inkl. laufendem)
private static final AtomicInteger QUEUED = new AtomicInteger(0);
@Inject
CheckOrchestrationService orchestrationService;
@@ -36,35 +53,34 @@ public class CheckResource {
@POST
@Path("/{projectId}")
@Operation(
summary = "Startet die Dokumentenprüfung für ein Projekt",
summary = "Reiht ein Projekt in die Verarbeitungswarteschlange ein",
description = """
Triggert den vollständigen Prüfablauf asynchron:
1. OCR / Konvertierung der Dokumente (KI)
2. Übersetzung ins Deutsche (KI)
3. Auswertung des Fragenkatalogs (KI)
4. Ergebnisse werden in ORDS gespeichert
Projekte werden strikt nacheinander verarbeitet.
Der Aufruf kehrt sofort mit 202 zurück; die eigentliche Verarbeitung
startet sobald alle vorher eingereihten Projekte abgeschlossen sind.
Das Projekt muss im Status PENDING sein.
Fortschritt: GET {ords}/api/dc/projects/{id}
"""
)
public Response startCheck(@PathParam("projectId") long projectId) {
// Asynchron starten Fire & Forget.
// Der aufrufende Thread (z.B. APEX-Button) bekommt sofort 202.
// Der Verarbeitungs-Thread läuft im ForkJoin-CommonPool.
CompletableFuture
.runAsync(() -> orchestrationService.process(projectId))
.exceptionally(ex -> {
// Der Orchestrator fängt intern; dies ist eine letzte Absicherung.
// Logging ist dort bereits vorhanden.
return null;
});
int position = QUEUED.incrementAndGet();
QUEUE.submit(() -> {
try {
LOG.infof("Starte Projekt %d (Warteschlange: %d)", projectId, QUEUED.get());
orchestrationService.process(projectId);
} finally {
QUEUED.decrementAndGet();
}
});
return Response
.accepted(Map.of(
"message", "Verarbeitung gestartet",
"project_id", projectId,
"hint", "Fortschritt: GET /api/dc/projects/" + projectId
"message", "Projekt in Warteschlange eingereiht",
"project_id", projectId,
"queue_position", position,
"hint", "Fortschritt: GET /api/dc/projects/" + projectId
))
.build();
}
@@ -75,8 +91,12 @@ public class CheckResource {
@GET
@Path("/health")
@Operation(summary = "Health-Check", description = "Gibt UP zurück wenn der Service läuft.")
@Operation(summary = "Health-Check", description = "Gibt UP zurück inkl. Warteschlangenlänge.")
public Response health() {
return Response.ok(Map.of("status", "UP", "service", "dc-backend")).build();
return Response.ok(Map.of(
"status", "UP",
"service", "dc-backend",
"queued", QUEUED.get()
)).build();
}
}

View File

@@ -18,13 +18,19 @@ dc.ai.base-url=https://ollama.aquantico.de
dc.ai.api-key=324GF44-50AA-4B57-9386-K435DLJ764DFR
# Hauptmodell: Auswertung + Übersetzung
dc.ai.main.model=gpt-oss:20b
dc.ai.main.model=qwen3.6:35b-a3b-q4_K_M
dc.ai.main.timeout=300s
dc.ai.main.max-retries=2
dc.ai.main.temperature=0.1
# Katalog-Generierungsmodell: längerer Timeout für vollständige Katalog-Analyse
dc.ai.catalog.model=qwen3.6:35b-a3b-q4_K_M
dc.ai.catalog.timeout=1200s
dc.ai.catalog.max-retries=1
dc.ai.catalog.temperature=0.1
# OCR-Modell: Bildtext-Extraktion aus PDF-Seiten
dc.ai.ocr.model=quen3.5:9b
dc.ai.ocr.model=qwen3.6:35b-a3b-q4_K_M
dc.ai.ocr.timeout=120s
dc.ai.ocr.max-retries=2
@@ -32,7 +38,7 @@ dc.ai.ocr.max-retries=2
# ORDS REST Client
# =============================================================================
# Basis-URL des ORDS-Servers (Schema-Pfad anpassen)
quarkus.rest-client.ords-api.url=http://localhost:8080/ords/FRIGOSPED_APP
quarkus.rest-client.ords-api.url=http://ords:8080/ords/ai_dev
quarkus.rest-client.ords-api.scope=jakarta.inject.Singleton
quarkus.rest-client.ords-api.connect-timeout=10000
quarkus.rest-client.ords-api.read-timeout=60000
@@ -49,8 +55,8 @@ quarkus.log.category."de.frigosped".level=DEBUG
# KI-Kommunikation mitloggen (nur in Dev)
%dev.dc.ai.log-requests=true
%dev.dc.ai.log-responses=true
%prod.dc.ai.log-requests=false
%prod.dc.ai.log-responses=false
%prod.dc.ai.log-requests=true
%prod.dc.ai.log-responses=true
# =============================================================================
# Jackson: snake_case für ORDS-Responses

View File

@@ -1,4 +1,23 @@
de/frigosped/dc/service/CheckOrchestrationService.class
de/frigosped/dc/model/GeneratedCatalogStructure$GeneratedCategory.class
de/frigosped/dc/resource/ExportResource.class
de/frigosped/dc/model/OrdsQuestionCreateRequest.class
de/frigosped/dc/model/OrdsCategoryCreateRequest.class
de/frigosped/dc/model/OrdsCatalogCreateRequest.class
de/frigosped/dc/model/OrdsCatalogStatusUpdateRequest.class
de/frigosped/dc/service/EvaluationService.class
de/frigosped/dc/service/MarkdownExportService.class
de/frigosped/dc/service/DocumentProcessingService.class
de/frigosped/dc/model/CatalogGenerateResponse.class
de/frigosped/dc/service/MarkdownExportService$Seg.class
de/frigosped/dc/model/OrdsCatalogStatusResponse.class
de/frigosped/dc/model/OrdsDocumentTexts.class
de/frigosped/dc/resource/CatalogResource.class
de/frigosped/dc/model/ExportRequest.class
de/frigosped/dc/service/CatalogGenerationService.class
de/frigosped/dc/service/CheckOrchestrationService.class
de/frigosped/dc/service/MarkdownExportService$SegType.class
de/frigosped/dc/model/GeneratedCatalogStructure.class
de/frigosped/dc/client/OrdsLoggingFilter.class
de/frigosped/dc/service/MarkdownExportService$PdfWriter.class
de/frigosped/dc/security/ApiKeyFilter.class
de/frigosped/dc/model/GeneratedCatalogStructure$GeneratedQuestion.class

View File

@@ -1,16 +1,30 @@
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/ai/AiModelProducer.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/client/OrdsClient.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/client/OrdsLoggingFilter.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/CatalogGenerateResponse.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/EvaluationResult.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/ExportRequest.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/GeneratedCatalogStructure.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsCatalogCreateRequest.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsCatalogStatusResponse.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsCatalogStatusUpdateRequest.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsCategoryCreateRequest.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsDocument.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsDocumentList.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsDocumentTexts.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsProject.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsQuestion.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsQuestionCreateRequest.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/OrdsQuestionList.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/ProgressRequest.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/ResultRequest.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/model/TextsRequest.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/resource/CatalogResource.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/resource/CheckResource.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/resource/ExportResource.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/security/ApiKeyFilter.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/service/CatalogGenerationService.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/service/CheckOrchestrationService.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/service/DocumentProcessingService.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/service/EvaluationService.java
/mnt/c/source/Frigosped/Dokumenten-Check/dc-backend/src/main/java/de/frigosped/dc/service/MarkdownExportService.java