Funktioniert
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
dc-backend/target
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user