feat(#145): LLM-Prompts auf /methodik als Transparenz-Block
System- und User-Prompt-Template stehen jetzt collapsed unter dem neuen Abschnitt 'LLM-Prompts'. Der User-Prompt wird auf eine eigene Konstante USER_PROMPT_TEMPLATE umgestellt und via .format(...) gerendert, sodass das gleiche Template auf der Methodik-Seite gezeigt werden kann ohne den f-string-Code zu duplizieren. Closes #145
This commit is contained in:
parent
5f6bcac282
commit
0d26cad549
@ -71,6 +71,52 @@ def load_context_file(name: str) -> str:
|
||||
return ""
|
||||
|
||||
|
||||
USER_PROMPT_TEMPLATE = """Analysiere den folgenden Antrag:
|
||||
|
||||
<kontext>
|
||||
{bundesland_context}
|
||||
</kontext>
|
||||
|
||||
<wahlprogramm_zitate>
|
||||
{quotes_context}
|
||||
</wahlprogramm_zitate>
|
||||
|
||||
<antrag>
|
||||
{text}
|
||||
</antrag>
|
||||
|
||||
**PFLICHT-FRAKTIONEN:** Du MUSST ALLE folgenden Fraktionen der aktuellen Wahlperiode in `wahlprogrammScores` bewerten — keine auslassen:
|
||||
{pflicht_fraktionen}
|
||||
|
||||
Bewerte nach GWÖ-Matrix 2.0 für Gemeinden:
|
||||
1. GWÖ-Treue (0-10) mit Matrix-Zuordnung und Symbolen (++/+/○/−/−−)
|
||||
2. Wahlprogrammtreue JEDER der oben genannten Pflicht-Fraktionen (0-10)
|
||||
3. Parteiprogrammtreue JEDER der oben genannten Pflicht-Fraktionen (0-10)
|
||||
4. Bis zu 3 Verbesserungsvorschläge in Redline-Syntax
|
||||
5. Themen-Tags für Kategorisierung
|
||||
|
||||
**ZITATEREGEL — STRIKT:** In jedem ``wahlprogrammScores[].wahlprogramm.zitate[].quelle``
|
||||
und ``parteiprogrammScores[].parteiprogramm.zitate[].quelle`` musst du **wortgleich**
|
||||
einen der oben in ``<wahlprogramm_zitate>`` aufgelisteten Quellen-Labels (Programm-Name +
|
||||
Seite) übernehmen — z.B. ``"CDU Mecklenburg-Vorpommern Wahlprogramm 2021, S. 33"``.
|
||||
Erfinde keine Quellen aus deinem Trainingswissen. Nimm keine Quelle aus einem anderen
|
||||
Bundesland (z.B. NRW 2022) als die hier aufgelisteten — selbst wenn dir die dortigen
|
||||
Programme bekannter sind. Findest du oben für eine Partei keinen passenden Chunk, lass
|
||||
``zitate`` leer (``[]``) und vermerke das in der ``begruendung``.
|
||||
|
||||
Ausgabe als reines JSON ohne Markdown-Codeblöcke."""
|
||||
|
||||
|
||||
def get_user_prompt_template() -> str:
|
||||
"""Public Template-String fuer Transparenz-Seite (#145).
|
||||
|
||||
Enthaelt die Platzhalter ``{bundesland_context}``, ``{quotes_context}``,
|
||||
``{text}`` und ``{pflicht_fraktionen}`` — gerendert wird in
|
||||
``analyze_text`` direkt via ``.format(...)``.
|
||||
"""
|
||||
return USER_PROMPT_TEMPLATE
|
||||
|
||||
|
||||
def get_system_prompt() -> str:
|
||||
"""Build the system prompt with GWÖ matrix context."""
|
||||
return """Du bist ein Experte für Gemeinwohl-Ökonomie (GWÖ) und parlamentarische Analyse. Du bewertest Anträge aus Landesparlamenten systematisch nach drei Dimensionen:
|
||||
@ -316,40 +362,12 @@ async def analyze_antrag(
|
||||
quotes = find_relevant_quotes(text, fraktionen, bundesland=bundesland)
|
||||
quotes_context = format_quote_for_prompt(quotes)
|
||||
|
||||
user_prompt = f"""Analysiere den folgenden Antrag:
|
||||
|
||||
<kontext>
|
||||
{bundesland_context}
|
||||
</kontext>
|
||||
|
||||
<wahlprogramm_zitate>
|
||||
{quotes_context if quotes_context else "Keine relevanten Zitate gefunden."}
|
||||
</wahlprogramm_zitate>
|
||||
|
||||
<antrag>
|
||||
{text}
|
||||
</antrag>
|
||||
|
||||
**PFLICHT-FRAKTIONEN:** Du MUSST ALLE folgenden Fraktionen der aktuellen Wahlperiode in `wahlprogrammScores` bewerten — keine auslassen:
|
||||
{', '.join(BUNDESLAENDER[bundesland].landtagsfraktionen)}
|
||||
|
||||
Bewerte nach GWÖ-Matrix 2.0 für Gemeinden:
|
||||
1. GWÖ-Treue (0-10) mit Matrix-Zuordnung und Symbolen (++/+/○/−/−−)
|
||||
2. Wahlprogrammtreue JEDER der oben genannten Pflicht-Fraktionen (0-10)
|
||||
3. Parteiprogrammtreue JEDER der oben genannten Pflicht-Fraktionen (0-10)
|
||||
4. Bis zu 3 Verbesserungsvorschläge in Redline-Syntax
|
||||
5. Themen-Tags für Kategorisierung
|
||||
|
||||
**ZITATEREGEL — STRIKT:** In jedem ``wahlprogrammScores[].wahlprogramm.zitate[].quelle``
|
||||
und ``parteiprogrammScores[].parteiprogramm.zitate[].quelle`` musst du **wortgleich**
|
||||
einen der oben in ``<wahlprogramm_zitate>`` aufgelisteten Quellen-Labels (Programm-Name +
|
||||
Seite) übernehmen — z.B. ``"CDU Mecklenburg-Vorpommern Wahlprogramm 2021, S. 33"``.
|
||||
Erfinde keine Quellen aus deinem Trainingswissen. Nimm keine Quelle aus einem anderen
|
||||
Bundesland (z.B. NRW 2022) als die hier aufgelisteten — selbst wenn dir die dortigen
|
||||
Programme bekannter sind. Findest du oben für eine Partei keinen passenden Chunk, lass
|
||||
``zitate`` leer (``[]``) und vermerke das in der ``begruendung``.
|
||||
|
||||
Ausgabe als reines JSON ohne Markdown-Codeblöcke."""
|
||||
user_prompt = USER_PROMPT_TEMPLATE.format(
|
||||
bundesland_context=bundesland_context,
|
||||
quotes_context=quotes_context if quotes_context else "Keine relevanten Zitate gefunden.",
|
||||
text=text,
|
||||
pflicht_fraktionen=", ".join(BUNDESLAENDER[bundesland].landtagsfraktionen),
|
||||
)
|
||||
|
||||
# LLM-Call über den Port. Retry-Loop + Markdown-Stripping wohnen im
|
||||
# Adapter (``QwenBewerter``). Bei exhausted retries wirft er
|
||||
|
||||
@ -1735,6 +1735,7 @@ async def methodik_page(request: Request, current_user: Optional[dict] = Depends
|
||||
"""Transparenz-/Methodik-Seite (#96)."""
|
||||
from .bundeslaender import aktive_bundeslaender, BUNDESLAENDER
|
||||
from .embeddings import get_indexing_status
|
||||
from .analyzer import get_system_prompt, get_user_prompt_template
|
||||
|
||||
bl_list = []
|
||||
for bl in aktive_bundeslaender():
|
||||
@ -1755,6 +1756,8 @@ async def methodik_page(request: Request, current_user: Optional[dict] = Depends
|
||||
"programme_count": status.get("total", 0),
|
||||
"chunk_count": sum(p.get("chunks", 0) for p in status.get("programmes", [])),
|
||||
"bundeslaender": sorted(bl_list, key=lambda x: x["name"]),
|
||||
"system_prompt": get_system_prompt(),
|
||||
"user_prompt_template": get_user_prompt_template(),
|
||||
**_v2_template_context(current_user),
|
||||
})
|
||||
|
||||
|
||||
@ -138,6 +138,7 @@
|
||||
<a href="#was-macht">Was macht der Prüfer?</a>
|
||||
<a href="#matrix">Die Matrix 2.0</a>
|
||||
<a href="#pipeline">Analyse-Pipeline</a>
|
||||
<a href="#prompts">LLM-Prompts</a>
|
||||
<a href="#qualitaet">Qualitätssicherung</a>
|
||||
<a href="#einschraenkungen">Einschränkungen</a>
|
||||
<a href="#datenquellen">Datenquellen</a>
|
||||
@ -365,6 +366,42 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="prompts">
|
||||
<h2>LLM-Prompts</h2>
|
||||
<div class="v2-kasten outline-blue">
|
||||
<p>
|
||||
Volle Transparenz: hier liegen die exakten Anweisungen, mit denen das
|
||||
Sprachmodell ({{ model_name }}) jeden Antrag bewertet. Der
|
||||
<strong>System-Prompt</strong> ist statisch und enthält die GWÖ-Matrix
|
||||
plus Ausgabe-Schema. Der <strong>User-Prompt</strong> wird pro Antrag
|
||||
dynamisch gefüllt — die Platzhalter <code>{kontext}</code>,
|
||||
<code>{wahlprogramm_zitate}</code>, <code>{antrag}</code> und
|
||||
<code>{pflicht_fraktionen}</code> sind unten als
|
||||
<code>{...}</code> markiert.
|
||||
</p>
|
||||
<p style="font-size:11px;opacity:0.7;">
|
||||
Quelle: <a href="https://repo.toppyr.de/tobias/gwoe-antragspruefer/src/branch/main/app/analyzer.py" target="_blank"><code>app/analyzer.py</code></a>
|
||||
(<code>get_system_prompt()</code> und <code>get_user_prompt_template()</code>).
|
||||
</p>
|
||||
|
||||
<details style="margin-top:1rem;">
|
||||
<summary style="cursor:pointer;color:var(--ecg-teal);font-weight:700;padding:6px 0;font-family:var(--font-display);">
|
||||
System-Prompt anzeigen
|
||||
<span style="font-family:var(--font-mono);font-size:11px;opacity:0.6;font-weight:400;">({{ system_prompt|length }} Zeichen)</span>
|
||||
</summary>
|
||||
<pre style="background:var(--ecg-bg-subtle);border:1px solid var(--ecg-border);border-radius:4px;padding:14px 16px;margin-top:8px;font-family:var(--font-mono);font-size:11px;line-height:1.5;white-space:pre-wrap;word-break:break-word;color:var(--ecg-dark);overflow-x:auto;">{{ system_prompt }}</pre>
|
||||
</details>
|
||||
|
||||
<details style="margin-top:0.75rem;">
|
||||
<summary style="cursor:pointer;color:var(--ecg-teal);font-weight:700;padding:6px 0;font-family:var(--font-display);">
|
||||
User-Prompt-Template anzeigen
|
||||
<span style="font-family:var(--font-mono);font-size:11px;opacity:0.6;font-weight:400;">({{ user_prompt_template|length }} Zeichen)</span>
|
||||
</summary>
|
||||
<pre style="background:var(--ecg-bg-subtle);border:1px solid var(--ecg-border);border-radius:4px;padding:14px 16px;margin-top:8px;font-family:var(--font-mono);font-size:11px;line-height:1.5;white-space:pre-wrap;word-break:break-word;color:var(--ecg-dark);overflow-x:auto;">{{ user_prompt_template }}</pre>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="qualitaet">
|
||||
<h2>Qualitätssicherung</h2>
|
||||
<div class="v2-kasten outline-green">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user