add activate document versions
This commit is contained in:
@@ -40,35 +40,6 @@ final readonly class PromptBuilder
|
|||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
// 1) SYSTEM INSTRUCTIONS
|
// 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();
|
$activePrompt = $this->systemPromptRepository->findActive();
|
||||||
|
|
||||||
|
|||||||
@@ -187,7 +187,12 @@ class DocumentController extends AbstractController
|
|||||||
throw $this->createNotFoundException();
|
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', [
|
return $this->redirectToRoute('admin_document_show', [
|
||||||
'id' => $version->getDocument()->getId()
|
'id' => $version->getDocument()->getId()
|
||||||
@@ -305,4 +310,4 @@ class DocumentController extends AbstractController
|
|||||||
$this->addFlash('success', 'Das System wurde erfolgreich zurückgesetzt.');
|
$this->addFlash('success', 'Das System wurde erfolgreich zurückgesetzt.');
|
||||||
return $this->redirectToRoute('admin_dashboard');
|
return $this->redirectToRoute('admin_dashboard');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,12 +5,15 @@ namespace App\Service;
|
|||||||
use App\Entity\Document;
|
use App\Entity\Document;
|
||||||
use App\Entity\DocumentVersion;
|
use App\Entity\DocumentVersion;
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
|
use App\Ingest\IngestFlow;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
class DocumentService
|
class DocumentService
|
||||||
{
|
{
|
||||||
public function __construct(
|
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
|
public function activateVersion(DocumentVersion $version): void
|
||||||
{
|
{
|
||||||
$document = $version->getDocument();
|
if (!$this->lockService->acquire()) {
|
||||||
|
throw new \RuntimeException('Another ingest job is already running.');
|
||||||
foreach ($document->getVersions() as $existingVersion) {
|
|
||||||
$existingVersion->setActive(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$version->setActive(true);
|
try {
|
||||||
$document->setCurrentVersion($version);
|
$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;
|
return $max + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,6 +107,7 @@
|
|||||||
<td>
|
<td>
|
||||||
{% if version.isActive %}
|
{% if version.isActive %}
|
||||||
|
|
||||||
|
{# Optional: manuelles Re-Ingest nur bei PENDING/FAILED #}
|
||||||
{% if version.ingestStatus in ['PENDING', 'FAILED'] %}
|
{% if version.ingestStatus in ['PENDING', 'FAILED'] %}
|
||||||
|
|
||||||
<form method="post"
|
<form method="post"
|
||||||
@@ -123,7 +124,14 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="text-muted">Nicht aktiv</span>
|
<form method="post"
|
||||||
|
action="{{ path('admin_document_version_activate', {versionId: version.id}) }}"
|
||||||
|
style="display:inline;">
|
||||||
|
<input type="hidden" name="_token" value="{{ csrf_token('activate_version') }}">
|
||||||
|
<button class="btn btn-sm btn-outline-light">
|
||||||
|
Aktivieren
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
@@ -135,4 +143,4 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user