optimize gui
add help text sections
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
|
||||
<nav class="navbar navbar-dark bg-black border-bottom border-secondary px-3">
|
||||
<span class="navbar-brand fw-semibold text-info">
|
||||
mitho Admin
|
||||
mitho® RAG-System
|
||||
</span>
|
||||
|
||||
<div class="ms-auto d-flex align-items-center gap-3">
|
||||
@@ -79,12 +79,12 @@
|
||||
|
||||
<a class="nav-link text-light {% if route starts with 'admin_job' %}active fw-bold{% endif %}"
|
||||
href="{{ path('admin_jobs') }}">
|
||||
Ingest Jobs
|
||||
Indexierungs-Log (Ingest Jobs)
|
||||
</a>
|
||||
|
||||
<a class="nav-link text-light {% if route starts with 'admin_system_agent' %}active fw-bold{% endif %}"
|
||||
href="{{ path('admin_system_agent') }}">
|
||||
Chunk-Index
|
||||
Retrieval Wissensbasis (Chunk-Index)
|
||||
</a>
|
||||
|
||||
<hr class="border-secondary">
|
||||
@@ -100,7 +100,7 @@
|
||||
|
||||
<a class="nav-link text-light {% if route starts with 'admin_ingest_profile' %}active fw-bold{% endif %}"
|
||||
href="{{ path('admin_ingest_profile_list') }}">
|
||||
Ingest Profiles
|
||||
Indexierungsprofile (Ingest Profiles)
|
||||
</a>
|
||||
|
||||
<hr class="border-secondary">
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
<a class="nav-link text-light {% if route starts with 'admin_model_config' %}active fw-bold{% endif %}"
|
||||
href="{{ path('admin_model_config_list') }}">
|
||||
Modell-Generierung
|
||||
Modell-Generierung (Matrix Parameter)
|
||||
</a>
|
||||
<hr class="border-secondary">
|
||||
<div class="text-info text-uppercase small mb-2">
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<br>
|
||||
<strong>Größere Werte:</strong> Weniger Chunks, mehr Kontext pro Treffer.
|
||||
<br><br>
|
||||
Empfehlung für Produkt- und Wissensdaten: 600–1000.
|
||||
Empfehlung für Produkt- und Wissensbasis: 600–1000.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,6 +12,48 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{# ========================================================= #}
|
||||
{# PROFIL SYSTEM DESCRIPTION #}
|
||||
{# ========================================================= #}
|
||||
<div class="card bg-black border-secondary mb-4 shadow-sm">
|
||||
<div class="card-body text-light">
|
||||
|
||||
<h5 class="text-info mb-3">Was sind Indexierungsprofile?</h5>
|
||||
|
||||
<p class="small text-light mb-3">
|
||||
Indexierungsprofile definieren die strukturellen Regeln des RAG-Systems.
|
||||
Sie bestimmen, wie Dokumente in Chunks zerlegt, eingebettet
|
||||
und später bewertet werden.
|
||||
</p>
|
||||
|
||||
<ul class="small text-light mb-3">
|
||||
<li>Chunk-Größe und Overlap (Textsegmentierung)</li>
|
||||
<li>Embedding-Modell und Dimension</li>
|
||||
<li>Scoring-Version (Retrieval-Logik)</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="text-info mt-3">Warum sind Profile versioniert?</h6>
|
||||
|
||||
<p class="small text-light mb-3">
|
||||
Jede strukturelle Änderung beeinflusst die gesamte Indexarchitektur.
|
||||
Deshalb ist ein Profil immer versioniert und unveränderlich.
|
||||
Bei Aktivierung eines neuen Profils kann eine vollständige
|
||||
Neuindizierung erforderlich werden.
|
||||
</p>
|
||||
|
||||
<h6 class="text-info mt-3">Wie prüft das System Konsistenz?</h6>
|
||||
|
||||
<p class="small text-light mb-0">
|
||||
Das System vergleicht das aktive Profil mit der aktuellen
|
||||
<code>index_meta.json</code>. Weichen Parameter wie
|
||||
Embedding-Dimension, Chunking oder Scoring ab,
|
||||
wird eine Strukturabweichung erkannt und ein Global Reindex
|
||||
empfohlen oder erzwungen.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# ============================= #}
|
||||
{# Strukturstatus Alert #}
|
||||
{# ============================= #}
|
||||
@@ -70,20 +112,20 @@
|
||||
<span class="badge bg-success">Aktiv</span>
|
||||
{% else %}
|
||||
<span class="badge bg-dark border border-secondary">
|
||||
Inaktiv
|
||||
</span>
|
||||
Inaktiv
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{% if p.reindexRequired %}
|
||||
<span class="badge bg-warning text-dark">
|
||||
Erforderlich
|
||||
</span>
|
||||
Erforderlich
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">
|
||||
Nein
|
||||
</span>
|
||||
Nein
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
@@ -91,7 +133,6 @@
|
||||
|
||||
{% if not p.active and is_granted('ROLE_SUPER_ADMIN') %}
|
||||
|
||||
{# Aktivieren via POST #}
|
||||
<form method="post"
|
||||
action="{{ path('admin_ingest_profile_activate', {id: p.id}) }}"
|
||||
class="d-inline"
|
||||
@@ -106,7 +147,6 @@
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{# Löschen via POST #}
|
||||
<form method="post"
|
||||
action="{{ path('admin_ingest_profile_remove', {id: p.id}) }}"
|
||||
class="d-inline"
|
||||
@@ -143,12 +183,12 @@
|
||||
{# ============================= #}
|
||||
|
||||
<div class="card bg-black border-secondary">
|
||||
<div class="card-body">
|
||||
<div class="card-body text-light">
|
||||
|
||||
<h5 class="text-info mb-3">Index-Struktur Vergleich</h5>
|
||||
|
||||
{% if indexMeta %}
|
||||
<div class="mb-3 small text-secondary">
|
||||
<div class="mb-3 small text-light">
|
||||
Aktuelle Index-Version:
|
||||
<strong>{{ indexMeta.index_version }}</strong>
|
||||
</div>
|
||||
@@ -194,9 +234,10 @@
|
||||
</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 class="mt-4 small text-light">
|
||||
Hinweis: Strukturänderungen (Chunking, Embedding, Scoring)
|
||||
führen zu inkonsistentem Retrieval, bis eine vollständige
|
||||
Neuindizierung durchgeführt wird.
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -15,17 +15,67 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{# ========================================================= #}
|
||||
{# MODEL CONFIG DESCRIPTION #}
|
||||
{# ========================================================= #}
|
||||
<div class="card bg-black border-secondary text-light mb-4 shadow-sm">
|
||||
<div class="card-body">
|
||||
|
||||
<h5 class="text-info mb-3">Was steuert die Modell-Konfiguration?</h5>
|
||||
|
||||
<p class="small text-light mb-3">
|
||||
Die Modell-Konfiguration definiert die vollständige
|
||||
Generierungsumgebung des Agents. Sie trennt strikt zwischen:
|
||||
</p>
|
||||
|
||||
<ul class="small text-light mb-3">
|
||||
<li>LLM-Verhalten (Sampling & Kontext)</li>
|
||||
<li>Retrieval-Parameter (Vektor-Wissen)</li>
|
||||
<li>Streaming-Modus</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="text-info mt-3">LLM Sampling</h6>
|
||||
|
||||
<p class="small text-light mb-3">
|
||||
Parameter wie Temperature, TopK und TopP beeinflussen die
|
||||
kreative Varianz der Antwort. Repeat Penalty steuert Wiederholungen,
|
||||
während <code>numCtx</code> die maximale Kontextgröße des Modells festlegt.
|
||||
</p>
|
||||
|
||||
<h6 class="text-info mt-3">Retrieval Vector Wissen</h6>
|
||||
|
||||
<p class="small text-light mb-3">
|
||||
Retrieval-Parameter bestimmen, wie viele Chunks aus dem
|
||||
NDJSON-Vektorindex geladen werden und wie viele
|
||||
Top-K Kandidaten aus der FAISS-Suche berücksichtigt werden.
|
||||
Diese Werte beeinflussen die Wissensbreite der Antwort,
|
||||
nicht deren Kreativität.
|
||||
</p>
|
||||
|
||||
<h6 class="text-info mt-3">Architektur-Prinzip</h6>
|
||||
|
||||
<p class="small text-light mb-0">
|
||||
Das Retrieval ist deterministisch und vom LLM getrennt.
|
||||
Das Modell erhält ausschließlich die vorselektierten
|
||||
Chunks als Kontext. Änderungen hier verändern die
|
||||
Wissensbasis der Antwort — nicht den gespeicherten Index.
|
||||
Pro Modell kann genau eine Konfiguration aktiv sein.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-black border-secondary">
|
||||
<div class="card-body p-0">
|
||||
|
||||
<table class="table table-dark table-striped table-hover align-middle mb-0">
|
||||
<thead class="table-secondary text-dark">
|
||||
<tr>
|
||||
<th>Modell</th>
|
||||
<th>Version</th>
|
||||
<th>Stream</th>
|
||||
<th>Sampling</th>
|
||||
<th class="text-warning">Retrieval</th>
|
||||
<th>LLM Modell</th>
|
||||
<th>Profil-Version</th>
|
||||
<th>Streaming</th>
|
||||
<th>LLM Sampling</th>
|
||||
<th class="text-warning">Retrieval Vector Wissen</th>
|
||||
<th>Status</th>
|
||||
<th class="text-end">Aktionen</th>
|
||||
</tr>
|
||||
@@ -49,22 +99,16 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
{# ========================= #}
|
||||
{# Sampling Group #}
|
||||
{# ========================= #}
|
||||
<td>
|
||||
<div class="small">
|
||||
<div><strong>T:</strong> {{ config.temperature }}</div>
|
||||
<div><strong>K:</strong> {{ config.topK }}</div>
|
||||
<div><strong>P:</strong> {{ config.topP }}</div>
|
||||
<div><strong>R:</strong> {{ config.repeatPenalty }}</div>
|
||||
<div><strong>Ctx:</strong> {{ config.numCtx }}</div>
|
||||
<div><strong>Temperature:</strong> {{ config.temperature }}</div>
|
||||
<div><strong>TopK:</strong> {{ config.topK }}</div>
|
||||
<div><strong>TopP:</strong> {{ config.topP }}</div>
|
||||
<div><strong>Repeat Penalty:</strong> {{ config.repeatPenalty }}</div>
|
||||
<div><strong>NumCtx:</strong> {{ config.numCtx }}</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
{# ========================= #}
|
||||
{# Retrieval Group #}
|
||||
{# ========================= #}
|
||||
<td class="text-warning">
|
||||
<div class="small">
|
||||
<div><strong>Chunks:</strong> {{ config.retrievalMaxChunks }}</div>
|
||||
@@ -119,14 +163,14 @@
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
<span class="text-secondary small">—</span>
|
||||
<span class="text-light small">—</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7" class="text-center text-secondary py-4">
|
||||
<td colspan="7" class="text-center py-4">
|
||||
Keine Konfiguration vorhanden.
|
||||
</td>
|
||||
</tr>
|
||||
@@ -138,8 +182,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 mb-4 small text-secondary">
|
||||
Hinweis: Änderungen wirken sich unmittelbar auf die Generierungsparameter
|
||||
<div class="mt-4 mb-4 small text-light">
|
||||
Hinweis: Änderungen wirken sich unmittelbar auf Sampling- und Retrieval-Parameter
|
||||
des aktiven Modells aus. Pro Modell kann nur eine Version aktiv sein.
|
||||
</div>
|
||||
|
||||
@@ -155,7 +199,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 small text-secondary">
|
||||
<div class="mt-3 small text-light">
|
||||
Der Agent läuft im isolierten Admin-Test-Modus.
|
||||
Keine Persistenz. Keine produktive Session.
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{% extends 'admin/base.html.twig' %}
|
||||
|
||||
{% block title %}Wissensdaten (Chunk-Index){% endblock %}
|
||||
{% block title %}Retrieval Wissensbasis (Chunk-Index){% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3">Wissensdaten (Chunk-Index)</h1>
|
||||
<h1 class="h3">Retrieval Wissensbasis (Chunk-Index)</h1>
|
||||
|
||||
<a href="{{ path('admin_dashboard') }}"
|
||||
class="btn btn-sm btn-outline-secondary">
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="card bg-black border-secondary mb-5">
|
||||
<div class="card-body">
|
||||
|
||||
<h5 class="text-info mb-3">Index Meta (index_meta.json)</h5>
|
||||
<h5 class="text-info mb-3">Wissensdaten Generierungsmatrix Index Meta (index_meta.json)</h5>
|
||||
|
||||
{% if meta.error is defined %}
|
||||
<div class="alert alert-danger">
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h5 class="text-info mb-0">
|
||||
NDJSON-Index Übersicht (index.ndjson)
|
||||
Chunks Index | NDJSON-Index Übersicht (index.ndjson)
|
||||
</h5>
|
||||
|
||||
<div class="btn-group">
|
||||
|
||||
@@ -11,6 +11,45 @@
|
||||
<h1 class="h3">System Prompt Verwaltung</h1>
|
||||
</div>
|
||||
|
||||
{# ========================================================= #}
|
||||
{# SYSTEM PROMPT DESCRIPTION #}
|
||||
{# ========================================================= #}
|
||||
<div class="card bg-black border-secondary text-light mb-4 shadow-sm">
|
||||
<div class="card-body">
|
||||
|
||||
<h5 class="text-info mb-3">Was steuert der System Prompt?</h5>
|
||||
|
||||
<p class="small text-light mb-3">
|
||||
Der System Prompt definiert das globale Antwortverhalten des LLM.
|
||||
Er ist die oberste Steuerungsebene des Systems und beeinflusst:
|
||||
</p>
|
||||
|
||||
<ul class="small text-light mb-3">
|
||||
<li>Ton und Stil der Antworten</li>
|
||||
<li>Struktur der Ausgaben</li>
|
||||
<li>Umgang mit Unsicherheiten</li>
|
||||
<li>Bezug auf Wissensquellen</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="text-info mt-3">Architektur-Prinzip</h6>
|
||||
|
||||
<p class="small text-light mb-3">
|
||||
Der System Prompt ist strikt von der Wissensebene getrennt.
|
||||
Er verändert keine Dokumente, Chunks oder Vektoren,
|
||||
sondern nur die Interpretation und Darstellung der Retrieval-Ergebnisse.
|
||||
</p>
|
||||
|
||||
<h6 class="text-info mt-3">Warum Versionierung?</h6>
|
||||
|
||||
<p class="small text-light mb-0">
|
||||
Jede Änderung kann das Antwortverhalten signifikant verändern.
|
||||
Daher ist der Prompt versioniert, rollbackfähig und nur eine Version kann aktiv sein.
|
||||
Aktivierungen wirken unmittelbar auf alle nachfolgenden Anfragen.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Flash Messages -->
|
||||
{% for message in app.flashes('success') %}
|
||||
<div class="alert alert-success">{{ message }}</div>
|
||||
@@ -21,10 +60,7 @@
|
||||
|
||||
<div class="row g-4">
|
||||
|
||||
<!-- ===================================================== -->
|
||||
<!-- LEFT SIDE – Versionen (50%) -->
|
||||
<!-- ===================================================== -->
|
||||
|
||||
<!-- LEFT SIDE – Versionen -->
|
||||
<div class="col-lg-6">
|
||||
|
||||
<div class="card bg-black border-secondary text-light h-100">
|
||||
@@ -54,8 +90,8 @@
|
||||
<span class="badge bg-success">Aktiv</span>
|
||||
{% else %}
|
||||
<span class="badge bg-dark border border-secondary">
|
||||
Inaktiv
|
||||
</span>
|
||||
Inaktiv
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
@@ -96,14 +132,14 @@
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
<span class="text-secondary">—</span>
|
||||
<span class="text-light">—</span>
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="5" class="text-center text-secondary py-4">
|
||||
<td colspan="5" class="text-center py-4">
|
||||
Keine Versionen vorhanden.
|
||||
</td>
|
||||
</tr>
|
||||
@@ -115,10 +151,10 @@
|
||||
|
||||
<hr class="border-secondary mt-4">
|
||||
|
||||
<div class="small text-secondary">
|
||||
<div class="small text-light">
|
||||
<strong>Governance-Hinweis:</strong><br>
|
||||
Der aktive System Prompt beeinflusst das globale Antwortverhalten des LLM unmittelbar.
|
||||
Änderungen sollten dokumentiert, versioniert und nachvollziehbar erfolgen.
|
||||
Der aktive System Prompt beeinflusst das globale Antwortverhalten unmittelbar.
|
||||
Änderungen sollten dokumentiert, versioniert und bewusst aktiviert werden.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -126,10 +162,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ===================================================== -->
|
||||
<!-- RIGHT SIDE – Neue Version (50%) -->
|
||||
<!-- ===================================================== -->
|
||||
|
||||
<!-- RIGHT SIDE – Neue Version -->
|
||||
<div class="col-lg-6">
|
||||
|
||||
<div class="card bg-black border-secondary text-light h-100">
|
||||
@@ -148,7 +181,7 @@
|
||||
name="comment"
|
||||
class="form-control bg-dark text-light border-secondary"
|
||||
placeholder="Warum wurde der Prompt geändert?">
|
||||
<div class="form-text text-secondary">
|
||||
<div class="form-text text-light">
|
||||
Dokumentation der Änderung für spätere Nachvollziehbarkeit.
|
||||
</div>
|
||||
</div>
|
||||
@@ -156,7 +189,7 @@
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Prompt-Inhalt</label>
|
||||
|
||||
<div class="form-text text-secondary mb-2">
|
||||
<div class="form-text text-light mb-2">
|
||||
Verfügbare Variable:
|
||||
<code>{% verbatim %}{% now %}{% endverbatim %}</code>
|
||||
(aktuelles Datum / Zeit)
|
||||
|
||||
@@ -9,22 +9,61 @@
|
||||
</div>
|
||||
|
||||
{# ========================================================= #}
|
||||
{# Flash Messages #}
|
||||
{# TAG SYSTEM DESCRIPTION #}
|
||||
{# ========================================================= #}
|
||||
{#{% if app.flashes('success') %}
|
||||
<ul class="alert alert-success shadow-sm">
|
||||
{% for message in app.flashes('success') %}
|
||||
<li>{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% if app.flashes('danger') %}
|
||||
<ul class="alert alert-danger shadow-sm">
|
||||
{% for message in app.flashes('danger') %}
|
||||
<li>{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}#}
|
||||
<div class="card bg-black border-secondary text-light mb-4 shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5 class="text-info mb-3">Was machen Tags im System?</h5>
|
||||
|
||||
<p class="small text-light mb-2">
|
||||
Tags dienen als semantische Routing-Ebene innerhalb des RAG-Systems.
|
||||
Sie strukturieren Dokumente thematisch und beeinflussen,
|
||||
welche Inhalte bei einer Nutzeranfrage priorisiert werden.
|
||||
</p>
|
||||
|
||||
<ul class="small text-light mb-3">
|
||||
<li>
|
||||
Tags werden Dokumenten manuell zugewiesen.
|
||||
</li>
|
||||
<li>
|
||||
Beim Rebuild wird aus allen Tags eine eigene
|
||||
<code>tags.ndjson</code> erzeugt.
|
||||
</li>
|
||||
<li>
|
||||
Zusätzlich wird ein separater Vektorindex
|
||||
(<code>vector_tags.index</code>) aufgebaut.
|
||||
</li>
|
||||
<li>
|
||||
Bei einer Anfrage erfolgt zunächst ein Tag-Matching,
|
||||
danach wird das Chunk-Retrieval entsprechend gewichtet.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="text-info mt-3">Wie werden Tags bewertet?</h6>
|
||||
|
||||
<p class="small text-light mb-2">
|
||||
Die Bewertung erfolgt über einen eigenen Vektor-Similarity-Score
|
||||
im Tag-Index. Das System berechnet:
|
||||
</p>
|
||||
|
||||
<ul class="small text-light">
|
||||
<li>
|
||||
Ähnlichkeit zwischen Nutzeranfrage und Tag-Embedding
|
||||
</li>
|
||||
<li>
|
||||
Top-K Treffer im Tag-Index
|
||||
</li>
|
||||
<li>
|
||||
Gewichtete Übergabe an das Chunk-Retrieval
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p class="small text-light mt-2 mb-0">
|
||||
Tags wirken somit als semantischer Verstärker.
|
||||
Sie ersetzen kein Chunk-Retrieval, sondern steuern dessen Priorisierung.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# ========================================================= #}
|
||||
{# LIVE REBUILD STATUS (SSE) #}
|
||||
@@ -40,12 +79,10 @@
|
||||
|
||||
<script>
|
||||
const statusBox = document.getElementById('rebuild-status');
|
||||
|
||||
const source = new EventSource("{{ path('admin_tags_rebuild_stream') }}");
|
||||
|
||||
source.onmessage = function (event) {
|
||||
const data = JSON.parse(event.data);
|
||||
|
||||
let html = '';
|
||||
|
||||
if (data.status === '{{ statusRunning }}') {
|
||||
|
||||
Reference in New Issue
Block a user