diff --git a/src/Agent/PromptBuilder.php b/src/Agent/PromptBuilder.php index 3704a34..134b78e 100644 --- a/src/Agent/PromptBuilder.php +++ b/src/Agent/PromptBuilder.php @@ -40,35 +40,6 @@ final readonly class PromptBuilder // ------------------------------------------------------------ // 1) SYSTEM INSTRUCTIONS // ------------------------------------------------------------ - //ToDO: remove old systemLines - /*$systemLines = [ - 'You are a conversational AI assistant.', - 'Respond clearly, precisely, and in context of the ongoing conversation.', - 'The conversation context is authoritative and must be respected.', - 'External knowledge is supporting information only.', - 'If the user asks for contact details such as phone number, email address, postal address or contact person, and the provided context contains such information, answer explicitly with the concrete data.', - 'Do not omit contact details.', - 'It is allowed and desired to quote contact data verbatim if it appears in the context.', - "Current date and time: {$now}", - '', - 'IMPORTANT FORMATTING RULES:', - '- Always answer in valid Markdown.', - '- Use headings, lists, and paragraphs where appropriate.', - '- Insert line breaks early and often.', - '- Never write long paragraphs without newlines.', - '- Each list item must start on a new line.', - '- Prefer short paragraphs over dense text blocks.', - '', - 'IMPORTANT LANGUAGE RULES:', - '- If the user input contains misspellings, silently use the correct canonical terms in your answer.', - '- Never mention, explain, or point out spelling mistakes.', - '- Do not ask clarifying questions about possible misspellings.', - '- Do not repeat or quote misspelled terms from the user input.', - '- Always use the correct technical spelling found in the provided context.', - '- Answer directly and confidently using always correct canonical terminology.' - ]; - - $systemBlock = "SYSTEM:\n" . implode("\n", $systemLines);*/ $activePrompt = $this->systemPromptRepository->findActive(); diff --git a/src/Controller/Admin/DocumentController.php b/src/Controller/Admin/DocumentController.php index 46435ac..c1b8775 100644 --- a/src/Controller/Admin/DocumentController.php +++ b/src/Controller/Admin/DocumentController.php @@ -187,7 +187,12 @@ class DocumentController extends AbstractController throw $this->createNotFoundException(); } - $documentService->activateVersion($version); + try { + $documentService->activateVersion($version); + $this->addFlash('success', 'Version aktiviert und Index aktualisiert.'); + } catch (\Throwable $e) { + $this->addFlash('danger', 'Aktivierung/Re-Ingest fehlgeschlagen: ' . $e->getMessage()); + } return $this->redirectToRoute('admin_document_show', [ 'id' => $version->getDocument()->getId() @@ -305,4 +310,4 @@ class DocumentController extends AbstractController $this->addFlash('success', 'Das System wurde erfolgreich zurückgesetzt.'); return $this->redirectToRoute('admin_dashboard'); } -} +} \ No newline at end of file diff --git a/src/Service/DocumentService.php b/src/Service/DocumentService.php index 1cbb750..cf12874 100644 --- a/src/Service/DocumentService.php +++ b/src/Service/DocumentService.php @@ -5,12 +5,15 @@ namespace App\Service; use App\Entity\Document; use App\Entity\DocumentVersion; use App\Entity\User; +use App\Ingest\IngestFlow; use Doctrine\ORM\EntityManagerInterface; class DocumentService { public function __construct( - private EntityManagerInterface $em + private EntityManagerInterface $em, + private LockService $lockService, + private IngestFlow $ingestFlow, ) {} /** @@ -70,20 +73,49 @@ class DocumentService } /** - * Aktiviert eine Version (setzt andere inaktiv) + * Aktiviert eine Version (setzt andere inaktiv) und aktualisiert den Index. + * + * Beim Aktivieren wird deterministisch sichergestellt, dass nur diese + * Version im Index vorhanden ist: + * - alle Chunks des Dokuments werden aus index.ndjson entfernt (streaming compaction) + * - die aktive Version wird neu ge-chunkt und appended + * - FAISS wird vollständig aus index.ndjson neu gebaut */ public function activateVersion(DocumentVersion $version): void { - $document = $version->getDocument(); - - foreach ($document->getVersions() as $existingVersion) { - $existingVersion->setActive(false); + if (!$this->lockService->acquire()) { + throw new \RuntimeException('Another ingest job is already running.'); } - $version->setActive(true); - $document->setCurrentVersion($version); + try { + $document = $version->getDocument(); - $this->em->flush(); + // 1) Aktiv-Status in DB konsistent setzen (genau 1 aktive Version) + foreach ($document->getVersions() as $existingVersion) { + $existingVersion->setActive(false); + } + + $version->setActive(true); + $document->setCurrentVersion($version); + + // 2) Ingest-Status (UI) – wird im Fehlerfall auf FAILED gesetzt + $version->setIngestStatus(DocumentVersion::INGEST_RUNNING); + $this->em->flush(); + + // 3) Deterministischer Re-Ingest: alte Chunks raus, neue rein, FAISS rebuild + $this->ingestFlow->ingestDocumentVersion($version); + + $version->setIngestStatus(DocumentVersion::INGEST_INDEXED); + $this->em->flush(); + + } catch (\Throwable $e) { + // Aktivierung bleibt in DB bestehen, aber Index ist ggf. nicht aktuell → Status markieren + $version->setIngestStatus(DocumentVersion::INGEST_FAILED); + $this->em->flush(); + throw $e; + } finally { + $this->lockService->release(); + } } /** @@ -120,4 +152,4 @@ class DocumentService return $max + 1; } -} +} \ No newline at end of file diff --git a/templates/admin/document/show.html.twig b/templates/admin/document/show.html.twig index 7d916fb..d6fffa9 100644 --- a/templates/admin/document/show.html.twig +++ b/templates/admin/document/show.html.twig @@ -107,6 +107,7 @@