optimize ui
add new ki endpoint params
This commit is contained in:
@@ -1,76 +1,145 @@
|
||||
{% extends 'admin/base.html.twig' %}
|
||||
|
||||
{% block title %}System Prompt{% endblock %}
|
||||
{% block title %}Neues Indexierungsprofil{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Create Ingest Profile</h1>
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3">Neues Indexierungsprofil</h1>
|
||||
|
||||
<form method="post">
|
||||
<table class="table table-sm table-dark align-middle">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row" class="w-25">Chunk Size (500-2500)</th>
|
||||
<td>
|
||||
<label>
|
||||
<select name="chunk_size" class="form-select">
|
||||
<a href="{{ path('admin_ingest_profile_list') }}"
|
||||
class="btn btn-sm btn-outline-secondary">
|
||||
Zurück
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card bg-black border-secondary text-light">
|
||||
<div class="card-body">
|
||||
|
||||
<form method="post">
|
||||
<input type="hidden"
|
||||
name="_token"
|
||||
value="{{ csrf_token('create_ingest_profile') }}">
|
||||
|
||||
<div class="row g-4">
|
||||
|
||||
<!-- ===================== -->
|
||||
<!-- Chunking Section -->
|
||||
<!-- ===================== -->
|
||||
<div class="col-12">
|
||||
<h5 class="text-info">Chunking</h5>
|
||||
<hr class="border-secondary">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">
|
||||
Chunk Size
|
||||
</label>
|
||||
<select name="chunk_size"
|
||||
class="form-select bg-dark text-light border-secondary"
|
||||
required>
|
||||
{% for i in range(250, 2500, 50) %}
|
||||
<option value="{{ i }}" {{ selectedValue is defined and selectedValue == i ? 'selected' : '' }}>
|
||||
<option value="{{ i }}">
|
||||
{{ i }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Chunk Overlap (50-150)</th>
|
||||
<td>
|
||||
<label>
|
||||
<select name="chunk_overlap" class="form-select">
|
||||
{% for i in range(50, 150, 25) %}
|
||||
<option value="{{ i }}" {{ selectedValue is defined and selectedValue == i ? 'selected' : '' }}>
|
||||
{{ i }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Embedding Model (default)</th>
|
||||
<td>
|
||||
<label>
|
||||
<select name="embedding_model" class="form-control" required>
|
||||
<option value="all-MiniLM-L6-v2">all-MiniLM-L6-v2</option>
|
||||
</select>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Embedding Dimension (default)</th>
|
||||
<td>
|
||||
<label>
|
||||
<select name="embedding_dimension" class="form-control" required>
|
||||
<option value="768">768</option>
|
||||
</select>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Scoring Version (default)</th>
|
||||
<td>
|
||||
<label>
|
||||
<input type="number" name="scoring_version" class="form-control" value="1" placeholder="1" readonly required>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="text-start">
|
||||
<button type="submit" class="btn btn-primary">Create</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
<div class="form-text text-secondary">
|
||||
Größere Werte = weniger Chunks, mehr Kontext pro Chunk.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">
|
||||
Chunk Overlap
|
||||
</label>
|
||||
<select name="chunk_overlap"
|
||||
class="form-select bg-dark text-light border-secondary"
|
||||
required>
|
||||
{% for i in range(50, 200, 25) %}
|
||||
<option value="{{ i }}">
|
||||
{{ i }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class="form-text text-secondary">
|
||||
Überlappung zwischen Chunks zur Kontextstabilisierung.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===================== -->
|
||||
<!-- Embedding Section -->
|
||||
<!-- ===================== -->
|
||||
<div class="col-12 mt-4">
|
||||
<h5 class="text-info">Embedding</h5>
|
||||
<hr class="border-secondary">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">
|
||||
Embedding Model
|
||||
</label>
|
||||
<select name="embedding_model"
|
||||
class="form-select bg-dark text-light border-secondary"
|
||||
required>
|
||||
<option value="all-MiniLM-L6-v2">
|
||||
all-MiniLM-L6-v2 (768d)
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">
|
||||
Embedding Dimension
|
||||
</label>
|
||||
<input type="number"
|
||||
name="embedding_dimension"
|
||||
value="768"
|
||||
class="form-control bg-dark text-light border-secondary"
|
||||
readonly>
|
||||
<div class="form-text text-secondary">
|
||||
Muss mit dem Embedding-Modell übereinstimmen.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===================== -->
|
||||
<!-- Scoring Section -->
|
||||
<!-- ===================== -->
|
||||
<div class="col-12 mt-4">
|
||||
<h5 class="text-info">Scoring</h5>
|
||||
<hr class="border-secondary">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">
|
||||
Scoring Version
|
||||
</label>
|
||||
<input type="number"
|
||||
name="scoring_version"
|
||||
value="1"
|
||||
class="form-control bg-dark text-light border-secondary"
|
||||
readonly>
|
||||
<div class="form-text text-secondary">
|
||||
Erhöhung erzwingt Global Reindex.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="border-secondary my-4">
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
<button type="submit"
|
||||
class="btn btn-outline-info">
|
||||
Profil erstellen
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 small text-secondary">
|
||||
Hinweis: Änderungen am Indexierungsprofil wirken sich auf die Struktur des
|
||||
Vektor-Indexes aus. Nach Aktivierung ist ein vollständiger Reindex erforderlich.
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,94 +1,202 @@
|
||||
{% extends 'admin/base.html.twig' %}
|
||||
|
||||
{% block title %}Ingest Profiles{% endblock %}
|
||||
{% block title %}Indexierungsprofile{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Ingest Profiles</h1>
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3">Indexierungsprofile</h1>
|
||||
|
||||
<a class="btn btn-sm btn-outline-info"
|
||||
href="{{ path('admin_ingest_profile_create') }}">
|
||||
Neues Profil anlegen
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{# ============================= #}
|
||||
{# Strukturstatus Alert #}
|
||||
{# ============================= #}
|
||||
|
||||
{% if structureMismatch %}
|
||||
<div class="alert alert-danger">
|
||||
⚠ Strukturabweichung festgestellt – Globale Neuindizierung erforderlich | <a href="{{ path('admin_jobs') }}">Global Reindex aufrufen</a>
|
||||
<div class="alert alert-danger d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<strong>Strukturabweichung erkannt.</strong>
|
||||
Die aktuelle Indexstruktur entspricht nicht dem aktiven Profil.
|
||||
Eine globale Neuindizierung ist erforderlich.
|
||||
</div>
|
||||
<a href="{{ path('admin_jobs') }}"
|
||||
class="btn btn-sm btn-outline-light">
|
||||
Global Reindex starten
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-success">
|
||||
✅ Die Indexstruktur entspricht dem aktiven Profil
|
||||
Die Indexstruktur entspricht dem aktiven Profil.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<p><a class="btn btn-outline-light" href="{{ path('admin_ingest_profile_create') }}">+ Neues Profil anlegen</a></p>
|
||||
{# ============================= #}
|
||||
{# Profile Tabelle #}
|
||||
{# ============================= #}
|
||||
|
||||
<h2>Profiles</h2>
|
||||
<div class="card bg-black border-secondary mb-5">
|
||||
<div class="card-body p-0">
|
||||
|
||||
<table border="1" cellpadding="6" class="table table-sm table-dark align-middle">
|
||||
<tr>
|
||||
<th>Version</th>
|
||||
<th>Chunk Size</th>
|
||||
<th>Overlap</th>
|
||||
<th>Model</th>
|
||||
<th>Dimension</th>
|
||||
<th>Scoring</th>
|
||||
<th>Active</th>
|
||||
<th>Reindex Required</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
<table class="table table-dark table-striped table-hover align-middle mb-0">
|
||||
<thead class="table-secondary text-dark">
|
||||
<tr>
|
||||
<th>Version</th>
|
||||
<th>Chunk Size</th>
|
||||
<th>Overlap</th>
|
||||
<th>Embedding</th>
|
||||
<th>Dim</th>
|
||||
<th>Scoring</th>
|
||||
<th>Status</th>
|
||||
<th>Reindex</th>
|
||||
<th class="text-end">Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for p in profiles %}
|
||||
<tr>
|
||||
<td>v{{ p.version }}</td>
|
||||
<td>{{ p.chunkSize }}</td>
|
||||
<td>{{ p.chunkOverlap }}</td>
|
||||
<td>{{ p.embeddingModel }}</td>
|
||||
<td>{{ p.embeddingDimension }}</td>
|
||||
<td>{{ p.scoringVersion }}</td>
|
||||
|
||||
{% for p in profiles %}
|
||||
<tr>
|
||||
<td {% if p.active %}class="text-success"{% endif %}>{{ p.version }}</td>
|
||||
<td>{{ p.chunkSize }}</td>
|
||||
<td>{{ p.chunkOverlap }}</td>
|
||||
<td>{{ p.embeddingModel }}</td>
|
||||
<td>{{ p.embeddingDimension }}</td>
|
||||
<td>{{ p.scoringVersion }}</td>
|
||||
<td {% if p.active %}class="text-success"{% endif %}>{{ p.active ? 'Yes' : 'No' }}</td>
|
||||
<td>{{ p.reindexRequired ? 'Yes' : 'No' }}</td>
|
||||
<td>
|
||||
{% if not p.active %}
|
||||
<a class="btn btn-outline-success btn-sm" href="{{ path('admin_ingest_profile_activate', {id: p.id}) }}">
|
||||
Aktivieren
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if not p.active %}
|
||||
<a class="btn btn-outline-danger btn-sm" href="{{ path('admin_ingest_profile_remove', {id: p.id}) }}">
|
||||
Löschen
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<td>
|
||||
{% if p.active %}
|
||||
<span class="badge bg-success">Aktiv</span>
|
||||
{% else %}
|
||||
<span class="badge bg-dark border border-secondary">
|
||||
Inaktiv
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<hr>
|
||||
<h2>Index-Struktur-Profil Diff</h2>
|
||||
<td>
|
||||
{% if p.reindexRequired %}
|
||||
<span class="badge bg-warning text-dark">
|
||||
Erforderlich
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">
|
||||
Nein
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
{% if indexMeta %}
|
||||
<p><strong>Index Version:</strong> {{ indexMeta.index_version }}</p>
|
||||
{% else %}
|
||||
<p>No index_meta.json found.</p>
|
||||
{% endif %}
|
||||
<td class="text-end">
|
||||
|
||||
<table border="1" cellpadding="6" class="table table-sm table-dark align-middle">
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Index Meta</th>
|
||||
<th>Active Profile</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
{% if not p.active and is_granted('ROLE_SUPER_ADMIN') %}
|
||||
|
||||
{% for key, row in diff %}
|
||||
<tr>
|
||||
<td>{{ key }}</td>
|
||||
<td>{{ row.meta }}</td>
|
||||
<td>{{ row.profile }}</td>
|
||||
<td>
|
||||
{% if row.equal %}
|
||||
<span style="color:green;">✓</span>
|
||||
{% else %}
|
||||
<span style="color:red;">✗</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{# Aktivieren via POST #}
|
||||
<form method="post"
|
||||
action="{{ path('admin_ingest_profile_activate', {id: p.id}) }}"
|
||||
class="d-inline"
|
||||
onsubmit="return confirm('Profil aktivieren? Global Reindex kann erforderlich sein.');">
|
||||
|
||||
<input type="hidden"
|
||||
name="_token"
|
||||
value="{{ csrf_token('activate_ingest_profile_' ~ p.id) }}">
|
||||
|
||||
<button class="btn btn-sm btn-outline-success me-2">
|
||||
Aktivieren
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{# Löschen via POST #}
|
||||
<form method="post"
|
||||
action="{{ path('admin_ingest_profile_remove', {id: p.id}) }}"
|
||||
class="d-inline"
|
||||
onsubmit="return confirm('Profil wirklich löschen?');">
|
||||
|
||||
<input type="hidden"
|
||||
name="_token"
|
||||
value="{{ csrf_token('delete_ingest_profile_' ~ p.id) }}">
|
||||
|
||||
<button class="btn btn-sm btn-outline-danger">
|
||||
Löschen
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="9" class="text-center text-secondary py-4">
|
||||
Keine Profile vorhanden.
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# ============================= #}
|
||||
{# Struktur-Diff #}
|
||||
{# ============================= #}
|
||||
|
||||
<div class="card bg-black border-secondary">
|
||||
<div class="card-body">
|
||||
|
||||
<h5 class="text-info mb-3">Index-Struktur Vergleich</h5>
|
||||
|
||||
{% if indexMeta %}
|
||||
<div class="mb-3 small text-secondary">
|
||||
Aktuelle Index-Version:
|
||||
<strong>{{ indexMeta.index_version }}</strong>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning">
|
||||
index_meta.json nicht gefunden.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<table class="table table-dark table-striped table-hover align-middle">
|
||||
<thead class="table-secondary text-dark">
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Index Meta</th>
|
||||
<th>Aktives Profil</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for key, row in diff %}
|
||||
<tr>
|
||||
<td>{{ key }}</td>
|
||||
<td>{{ row.meta }}</td>
|
||||
<td>{{ row.profile }}</td>
|
||||
<td>
|
||||
{% if row.equal %}
|
||||
<span class="badge bg-success">Identisch</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">Abweichung</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="4" class="text-center text-secondary py-4">
|
||||
Keine Vergleichsdaten verfügbar.
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 small text-secondary">
|
||||
Hinweis: Strukturänderungen (Chunking, Embedding, Scoring) führen zu
|
||||
inkonsistentem Retrieval, bis eine vollständige Neuindizierung durchgeführt wird.
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user