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 jakarta.ws.rs.core.Response;
|
||||||
import org.eclipse.microprofile.openapi.annotations.Operation;
|
import org.eclipse.microprofile.openapi.annotations.Operation;
|
||||||
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
|
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import java.util.Map;
|
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.
|
* REST-Endpunkte des Dokumenten-Check-Backend.
|
||||||
*
|
*
|
||||||
* POST /check/{projectId}
|
* POST /check/{projectId}
|
||||||
* → Startet die asynchrone Verarbeitung eines Projekts.
|
* → Reiht das Projekt in eine sequentielle Warteschlange ein (202 sofort).
|
||||||
* → Gibt sofort 202 Accepted zurück; Fortschritt über ORDS-Endpunkte ablesbar.
|
* → Projekte werden strikt nacheinander verarbeitet (kein paralleler Betrieb).
|
||||||
*
|
*
|
||||||
* GET /check/health
|
* GET /check/health
|
||||||
* → Einfacher Health-Check.
|
* → Einfacher Health-Check inkl. Warteschlangenlänge.
|
||||||
*/
|
*/
|
||||||
@Path("/check")
|
@Path("/check")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Tag(name = "Dokumenten-Check", description = "KI-gestützte Dokumentenprüfung")
|
@Tag(name = "Dokumenten-Check", description = "KI-gestützte Dokumentenprüfung")
|
||||||
public class CheckResource {
|
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
|
@Inject
|
||||||
CheckOrchestrationService orchestrationService;
|
CheckOrchestrationService orchestrationService;
|
||||||
|
|
||||||
@@ -36,34 +53,33 @@ public class CheckResource {
|
|||||||
@POST
|
@POST
|
||||||
@Path("/{projectId}")
|
@Path("/{projectId}")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Startet die Dokumentenprüfung für ein Projekt",
|
summary = "Reiht ein Projekt in die Verarbeitungswarteschlange ein",
|
||||||
description = """
|
description = """
|
||||||
Triggert den vollständigen Prüfablauf asynchron:
|
Projekte werden strikt nacheinander verarbeitet.
|
||||||
1. OCR / Konvertierung der Dokumente (KI)
|
Der Aufruf kehrt sofort mit 202 zurück; die eigentliche Verarbeitung
|
||||||
2. Übersetzung ins Deutsche (KI)
|
startet sobald alle vorher eingereihten Projekte abgeschlossen sind.
|
||||||
3. Auswertung des Fragenkatalogs (KI)
|
|
||||||
4. Ergebnisse werden in ORDS gespeichert
|
|
||||||
|
|
||||||
Das Projekt muss im Status PENDING sein.
|
Das Projekt muss im Status PENDING sein.
|
||||||
Fortschritt: GET {ords}/api/dc/projects/{id}
|
Fortschritt: GET {ords}/api/dc/projects/{id}
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
public Response startCheck(@PathParam("projectId") long projectId) {
|
public Response startCheck(@PathParam("projectId") long projectId) {
|
||||||
// Asynchron starten – Fire & Forget.
|
int position = QUEUED.incrementAndGet();
|
||||||
// Der aufrufende Thread (z.B. APEX-Button) bekommt sofort 202.
|
|
||||||
// Der Verarbeitungs-Thread läuft im ForkJoin-CommonPool.
|
QUEUE.submit(() -> {
|
||||||
CompletableFuture
|
try {
|
||||||
.runAsync(() -> orchestrationService.process(projectId))
|
LOG.infof("Starte Projekt %d (Warteschlange: %d)", projectId, QUEUED.get());
|
||||||
.exceptionally(ex -> {
|
orchestrationService.process(projectId);
|
||||||
// Der Orchestrator fängt intern; dies ist eine letzte Absicherung.
|
} finally {
|
||||||
// Logging ist dort bereits vorhanden.
|
QUEUED.decrementAndGet();
|
||||||
return null;
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return Response
|
return Response
|
||||||
.accepted(Map.of(
|
.accepted(Map.of(
|
||||||
"message", "Verarbeitung gestartet",
|
"message", "Projekt in Warteschlange eingereiht",
|
||||||
"project_id", projectId,
|
"project_id", projectId,
|
||||||
|
"queue_position", position,
|
||||||
"hint", "Fortschritt: GET /api/dc/projects/" + projectId
|
"hint", "Fortschritt: GET /api/dc/projects/" + projectId
|
||||||
))
|
))
|
||||||
.build();
|
.build();
|
||||||
@@ -75,8 +91,12 @@ public class CheckResource {
|
|||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/health")
|
@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() {
|
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
|
dc.ai.api-key=324GF44-50AA-4B57-9386-K435DLJ764DFR
|
||||||
|
|
||||||
# Hauptmodell: Auswertung + Übersetzung
|
# 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.timeout=300s
|
||||||
dc.ai.main.max-retries=2
|
dc.ai.main.max-retries=2
|
||||||
dc.ai.main.temperature=0.1
|
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
|
# 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.timeout=120s
|
||||||
dc.ai.ocr.max-retries=2
|
dc.ai.ocr.max-retries=2
|
||||||
|
|
||||||
@@ -32,7 +38,7 @@ dc.ai.ocr.max-retries=2
|
|||||||
# ORDS REST Client
|
# ORDS REST Client
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Basis-URL des ORDS-Servers (Schema-Pfad anpassen)
|
# 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.scope=jakarta.inject.Singleton
|
||||||
quarkus.rest-client.ords-api.connect-timeout=10000
|
quarkus.rest-client.ords-api.connect-timeout=10000
|
||||||
quarkus.rest-client.ords-api.read-timeout=60000
|
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)
|
# KI-Kommunikation mitloggen (nur in Dev)
|
||||||
%dev.dc.ai.log-requests=true
|
%dev.dc.ai.log-requests=true
|
||||||
%dev.dc.ai.log-responses=true
|
%dev.dc.ai.log-responses=true
|
||||||
%prod.dc.ai.log-requests=false
|
%prod.dc.ai.log-requests=true
|
||||||
%prod.dc.ai.log-responses=false
|
%prod.dc.ai.log-responses=true
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Jackson: snake_case für ORDS-Responses
|
# 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/EvaluationService.class
|
||||||
|
de/frigosped/dc/service/MarkdownExportService.class
|
||||||
de/frigosped/dc/service/DocumentProcessingService.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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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