{
"event": "PreToolUse",
"tool_name": "mcp__mcp-docs__docs_update",
"tool_input": {
"id": 76,
"content": "<nav class=\"breadcrumb\">\n <a href=\"\/docs\">Dokumentation<\/a> » <a href=\"\/docs\/content-studio\">Content Studio<\/a> » Kritiker\n<\/nav>\n\n<h1>Kritiker<\/h1>\n<p class=\"doc-meta\"><strong>Erstellt:<\/strong> 2025-12-20 | <strong>Aktualisiert:<\/strong> 2025-12-31<\/p>\n\n<p>Qualitätsprüfungs-System mit LLM-basierten und deterministischen Kritikern.<\/p>\n\n<table>\n <tr><th>Modul<\/th><td>generators\/critic.py, generators\/format_checker.py<\/td><\/tr>\n <tr><th>Tabelle<\/th><td>content_config (type='critic')<\/td><\/tr>\n <tr><th>Ergebnisse<\/th><td>content_critiques<\/td><\/tr>\n<\/table>\n\n<h2>Kritiker-Typen<\/h2>\n\n<table>\n <tr><th>Typ<\/th><th>Kritiker<\/th><th>Methode<\/th><th>Zuverlässigkeit<\/th><\/tr>\n <tr><td>Inhalt<\/td><td>Faktenprüfer, Stilist, Strukturanalyst<\/td><td>LLM<\/td><td>Gut für semantische Prüfung<\/td><\/tr>\n <tr><td>Format<\/td><td>Formatierungsprüfer<\/td><td>Deterministisch<\/td><td>100% zuverlässig<\/td><\/tr>\n<\/table>\n\n<div class=\"alert alert-warning\">\n<strong>Wichtig:<\/strong> LLMs halluzinieren bei Zeichenprüfungen (Gedankenstriche, Emojis, Anführungszeichen). Der Formatierungsprüfer verwendet daher deterministischen Code statt LLM.\n<\/div>\n\n<h2>Architektur<\/h2>\n<pre><code>Content Version\n ↓\n┌─────────────────────────────────────┐\n│ Faktenprüfer (LLM) → 8\/10 │\n│ Stilist (LLM) → 8\/10 │\n│ Strukturanalyst (LLM) → 8\/10 │\n│ Formatierungsprüfer (Code) → 10\/10 │\n└─────────────────────────────────────┘\n ↓\nall_passed? → validate : revision<\/code><\/pre>\n\n<h2>Deterministischer Format-Checker<\/h2>\n\n<p>Datei: <code>\/var\/www\/scripts\/pipeline\/generators\/format_checker.py<\/code><\/p>\n\n<h3>Geprüfte Regeln<\/h3>\n<table>\n <tr><th>Regel<\/th><th>Quelle<\/th><th>Prüfung<\/th><\/tr>\n <tr><td>emojis_verboten<\/td><td>structure.formatierung.emojis<\/td><td>Unicode-Ranges + Bullet-Emojis<\/td><\/tr>\n <tr><td>markdown_verboten<\/td><td>structure.ausgabe.format = \"reiner Text\"<\/td><td>**bold**, *italic*, # headers<\/td><\/tr>\n <tr><td>fettschrift_verboten<\/td><td>structure.formatierung.fettschrift<\/td><td>**text**, __text__<\/td><\/tr>\n <tr><td>gedankenstriche_verboten<\/td><td>profile.grammatik_und_satzbau.gedankenstriche<\/td><td>– (U+2013), — (U+2014)<\/td><\/tr>\n <tr><td>hashtags_verboten<\/td><td>structure.formatierung.hashtags = \"keine\"<\/td><td>#Hashtag Pattern<\/td><\/tr>\n <tr><td>ausrufezeichen_sparsam<\/td><td>profile.formatierung.ausrufezeichen<\/td><td>Max. 2 Ausrufezeichen<\/td><\/tr>\n<\/table>\n\n<h3>Post-Processing<\/h3>\n<p>Datei: <code>generators\/persistence.py<\/code> - <code>strip_markdown()<\/code><\/p>\n<p>Für <code>output_format == \"reiner Text\"<\/code> werden automatisch ersetzt:<\/p>\n<ul>\n <li>Gedankenstriche: <code>–<\/code> → <code>-<\/code>, <code>—<\/code> → <code>-<\/code><\/li>\n <li>Anführungszeichen: <code>„\"<\/code> → <code>\"\"<\/code>, <code>‚'<\/code> → <code>''<\/code><\/li>\n <li>Markdown: **bold** → bold, *italic* → italic<\/li>\n<\/ul>\n\n<h2>Aktuelle Kritiker<\/h2>\n<table>\n <tr><th>ID<\/th><th>Name<\/th><th>Typ<\/th><th>Fokus<\/th><\/tr>\n <tr><td>30<\/td><td>Faktenprüfer<\/td><td>LLM<\/td><td>Quellen, Aktualität, Genauigkeit<\/td><\/tr>\n <tr><td>31<\/td><td>Stilist<\/td><td>LLM<\/td><td>Stil, Tonalität, Fluss<\/td><\/tr>\n <tr><td>32<\/td><td>Strukturanalyst<\/td><td>LLM<\/td><td>Gliederung, Absätze, Aufbau<\/td><\/tr>\n <tr><td>33<\/td><td>Formatierungsprüfer<\/td><td>Code<\/td><td>Emojis, Markdown, Gedankenstriche<\/td><\/tr>\n<\/table>\n\n<h2>Feedback-Format<\/h2>\n<pre><code>{\n \"rating\": 8,\n \"score\": 8,\n \"passed\": true,\n \"issues\": [\"Issue 1\", \"Issue 2\"],\n \"suggestions\": [\"Suggestion 1\"],\n \"summary\": \"Kurze Zusammenfassung\",\n \"deterministic\": false \/\/ true bei Formatierungsprüfer\n}<\/code><\/pre>\n\n<h2>API-Verwendung<\/h2>\n<pre><code># Einzelnen Kritiker ausführen\nfrom generators.critic import run_critic\nresult = run_critic(content, critic_id=33, model=\"ollama:gemma3:27b-it-qat\")\n\n# Deterministisch prüfen (ohne DB)\nfrom generators.format_checker import check_formatting\nresult = check_formatting(text, structure_config, profile_config)<\/code><\/pre>\n\n<h2>Kritik-Ablauf<\/h2>\n\n<h3>run_critic()<\/h3>\n<pre><code>def run_critic(content, critic_id, model, structure_config=None, profile_config=None):\n critic = get_critic(critic_id)\n \n # Formatierungsprüfer: Deterministisch\n if critic[\"name\"] == \"Formatierungsprüfer\":\n return check_formatting(content, structure_config, profile_config)\n \n # Andere Kritiker: LLM\n prompt = prompt_template.format(fokus=fokus_str, content=content)\n response = call_llm(prompt, model)\n return parse_json(response)<\/code><\/pre>\n\n<h3>run_critique_round()<\/h3>\n<ol>\n <li>Version-Content laden<\/li>\n <li>Alle aktiven Kritiker aus content_config laden<\/li>\n <li>Kritik-Runde inkrementieren<\/li>\n <li>Jeden Kritiker ausführen (LLM oder deterministisch)<\/li>\n <li>Feedback in content_critiques speichern<\/li>\n <li>Status basierend auf Ergebnis setzen<\/li>\n<\/ol>\n\n<h2>Warum deterministisch?<\/h2>\n<p>LLMs halluzinieren bei Zeichenprüfung. Beispiel:<\/p>\n<pre><code># Text ohne Gedankenstriche\ntext = \"Vertrauen ist keine Eigenschaft, sondern eine Beziehung.\"\n\n# LLM-Formatierungsprüfer: 6\/10 - \"2 Gedankenstriche gefunden\" (FALSCH!)\n# Deterministischer Checker: 10\/10 - \"Keine Fehler\" (KORREKT)<\/code><\/pre>\n\n<p>Der Code sucht exakt nach Unicode-Zeichen:<\/p>\n<pre><code>def check_gedankenstriche(text: str) -> list[dict]:\n for i, char in enumerate(text):\n if char == \"–\": # U+2013\n issues.append({\"type\": \"en_dash\", \"position\": i})\n if char == \"—\": # U+2014\n issues.append({\"type\": \"em_dash\", \"position\": i})<\/code><\/pre>"
}
}
{
"tool_response": [
{
"type": "text",
"text": "{\n \"success\": true,\n \"doc\": {\n \"id\": 76,\n \"parent_id\": 34,\n \"slug\": \"kritiker\",\n \"path\": \"\/content-studio\/kritiker\",\n \"title\": \"Kritiker\",\n \"description\": \"Kritiker-System und KI-gestützte Qualitätsprüfung\",\n \"content\": \"<nav class=\\\"breadcrumb\\\">\\n <a href=\\\"\/docs\\\">Dokumentation<\/a> » <a href=\\\"\/docs\/content-studio\\\">Content Studio<\/a> » Kritiker\\n<\/nav>\\n\\n<h1>Kritiker<\/h1>\\n<p class=\\\"doc-meta\\\"><strong>Erstellt:<\/strong> 2025-12-20 | <strong>Aktualisiert:<\/strong> 2025-12-31<\/p>\\n\\n<p>Qualitätsprüfungs-System mit LLM-basierten und deterministischen Kritikern.<\/p>\\n\\n<table>\\n <tr><th>Modul<\/th><td>generators\/critic.py, generators\/format_checker.py<\/td><\/tr>\\n <tr><th>Tabelle<\/th><td>content_config (type='critic')<\/td><\/tr>\\n <tr><th>Ergebnisse<\/th><td>content_critiques<\/td><\/tr>\\n<\/table>\\n\\n<h2>Kritiker-Typen<\/h2>\\n\\n<table>\\n <tr><th>Typ<\/th><th>Kritiker<\/th><th>Methode<\/th><th>Zuverlässigkeit<\/th><\/tr>\\n <tr><td>Inhalt<\/td><td>Faktenprüfer, Stilist, Strukturanalyst<\/td><td>LLM<\/td><td>Gut für semantische Prüfung<\/td><\/tr>\\n <tr><td>Format<\/td><td>Formatierungsprüfer<\/td><td>Deterministisch<\/td><td>100% zuverlässig<\/td><\/tr>\\n<\/table>\\n\\n<div class=\\\"alert alert-warning\\\">\\n<strong>Wichtig:<\/strong> LLMs halluzinieren bei Zeichenprüfungen (Gedankenstriche, Emojis, Anführungszeichen). Der Formatierungsprüfer verwendet daher deterministischen Code statt LLM.\\n<\/div>\\n\\n<h2>Architektur<\/h2>\\n<pre><code>Content Version\\n ↓\\n┌─────────────────────────────────────┐\\n│ Faktenprüfer (LLM) → 8\/10 │\\n│ Stilist (LLM) → 8\/10 │\\n│ Strukturanalyst (LLM) → 8\/10 │\\n│ Formatierungsprüfer (Code) → 10\/10 │\\n└─────────────────────────────────────┘\\n ↓\\nall_passed? → validate : revision<\/code><\/pre>\\n\\n<h2>Deterministischer Format-Checker<\/h2>\\n\\n<p>Datei: <code>\/var\/www\/scripts\/pipeline\/generators\/format_checker.py<\/code><\/p>\\n\\n<h3>Geprüfte Regeln<\/h3>\\n<table>\\n <tr><th>Regel<\/th><th>Quelle<\/th><th>Prüfung<\/th><\/tr>\\n <tr><td>emojis_verboten<\/td><td>structure.formatierung.emojis<\/td><td>Unicode-Ranges + Bullet-Emojis<\/td><\/tr>\\n <tr><td>markdown_verboten<\/td><td>structure.ausgabe.format = \\\"reiner Text\\\"<\/td><td>**bold**, *italic*, # headers<\/td><\/tr>\\n <tr><td>fettschrift_verboten<\/td><td>structure.formatierung.fettschrift<\/td><td>**text**, __text__<\/td><\/tr>\\n <tr><td>gedankenstriche_verboten<\/td><td>profile.grammatik_und_satzbau.gedankenstriche<\/td><td>– (U+2013), — (U+2014)<\/td><\/tr>\\n <tr><td>hashtags_verboten<\/td><td>structure.formatierung.hashtags = \\\"keine\\\"<\/td><td>#Hashtag Pattern<\/td><\/tr>\\n <tr><td>ausrufezeichen_sparsam<\/td><td>profile.formatierung.ausrufezeichen<\/td><td>Max. 2 Ausrufezeichen<\/td><\/tr>\\n<\/table>\\n\\n<h3>Post-Processing<\/h3>\\n<p>Datei: <code>generators\/persistence.py<\/code> - <code>strip_markdown()<\/code><\/p>\\n<p>Für <code>output_format == \\\"reiner Text\\\"<\/code> werden automatisch ersetzt:<\/p>\\n<ul>\\n <li>Gedankenstriche: <code>–<\/code> → <code>-<\/code>, <code>—<\/code> → <code>-<\/code><\/li>\\n <li>Anführungszeichen: <code>„\\\"<\/code> → <code>\\\"\\\"<\/code>, <code>‚'<\/code> → <code>''<\/code><\/li>\\n <li>Markdown: **bold** → bold, *italic* → italic<\/li>\\n<\/ul>\\n\\n<h2>Aktuelle Kritiker<\/h2>\\n<table>\\n <tr><th>ID<\/th><th>Name<\/th><th>Typ<\/th><th>Fokus<\/th><\/tr>\\n <tr><td>30<\/td><td>Faktenprüfer<\/td><td>LLM<\/td><td>Quellen, Aktualität, Genauigkeit<\/td><\/tr>\\n <tr><td>31<\/td><td>Stilist<\/td><td>LLM<\/td><td>Stil, Tonalität, Fluss<\/td><\/tr>\\n <tr><td>32<\/td><td>Strukturanalyst<\/td><td>LLM<\/td><td>Gliederung, Absätze, Aufbau<\/td><\/tr>\\n <tr><td>33<\/td><td>Formatierungsprüfer<\/td><td>Code<\/td><td>Emojis, Markdown, Gedankenstriche<\/td><\/tr>\\n<\/table>\\n\\n<h2>Feedback-Format<\/h2>\\n<pre><code>{\\n \\\"rating\\\": 8,\\n \\\"score\\\": 8,\\n \\\"passed\\\": true,\\n \\\"issues\\\": [\\\"Issue 1\\\", \\\"Issue 2\\\"],\\n \\\"suggestions\\\": [\\\"Suggestion 1\\\"],\\n \\\"summary\\\": \\\"Kurze Zusammenfassung\\\",\\n \\\"deterministic\\\": false \/\/ true bei Formatierungsprüfer\\n}<\/code><\/pre>\\n\\n<h2>API-Verwendung<\/h2>\\n<pre><code># Einzelnen Kritiker ausführen\\nfrom generators.critic import run_critic\\nresult = run_critic(content, critic_id=33, model=\\\"ollama:gemma3:27b-it-qat\\\")\\n\\n# Deterministisch prüfen (ohne DB)\\nfrom generators.format_checker import check_formatting\\nresult = check_formatting(text, structure_config, profile_config)<\/code><\/pre>\\n\\n<h2>Kritik-Ablauf<\/h2>\\n\\n<h3>run_critic()<\/h3>\\n<pre><code>def run_critic(content, critic_id, model, structure_config=None, profile_config=None):\\n critic = get_critic(critic_id)\\n \\n # Formatierungsprüfer: Deterministisch\\n if critic[\\\"name\\\"] == \\\"Formatierungsprüfer\\\":\\n return check_formatting(content, structure_config, profile_config)\\n \\n # Andere Kritiker: LLM\\n prompt = prompt_template.format(fokus=fokus_str, content=content)\\n response = call_llm(prompt, model)\\n return parse_json(response)<\/code><\/pre>\\n\\n<h3>run_critique_round()<\/h3>\\n<ol>\\n <li>Version-Content laden<\/li>\\n <li>Alle aktiven Kritiker aus content_config laden<\/li>\\n <li>Kritik-Runde inkrementieren<\/li>\\n <li>Jeden Kritiker ausführen (LLM oder deterministisch)<\/li>\\n <li>Feedback in content_critiques speichern<\/li>\\n <li>Status basierend auf Ergebnis setzen<\/li>\\n<\/ol>\\n\\n<h2>Warum deterministisch?<\/h2>\\n<p>LLMs halluzinieren bei Zeichenprüfung. Beispiel:<\/p>\\n<pre><code># Text ohne Gedankenstriche\\ntext = \\\"Vertrauen ist keine Eigenschaft, sondern eine Beziehung.\\\"\\n\\n# LLM-Formatierungsprüfer: 6\/10 - \\\"2 Gedankenstriche gefunden\\\" (FALSCH!)\\n# Deterministischer Checker: 10\/10 - \\\"Keine Fehler\\\" (KORREKT)<\/code><\/pre>\\n\\n<p>Der Code sucht exakt nach Unicode-Zeichen:<\/p>\\n<pre><code>def check_gedankenstriche(text: str) -> list[dict]:\\n for i, char in enumerate(text):\\n if char == \\\"–\\\": # U+2013\\n issues.append({\\\"type\\\": \\\"en_dash\\\", \\\"position\\\": i})\\n if char == \\\"—\\\": # U+2014\\n issues.append({\\\"type\\\": \\\"em_dash\\\", \\\"position\\\": i})<\/code><\/pre>\",\n \"status\": \"published\",\n \"sort_order\": 3,\n \"depth\": 1,\n \"created_at\": \"2025-12-20T13:37:24\",\n \"updated_at\": \"2025-12-31T02:51:41\"\n },\n \"message\": \"Document #76 updated\"\n}"
}
]
}