feat(Phase 18): PM-Prompt verschaerft + Auto-Re-Generate bei zu kurzem Output
- SYSTEM_PROMPT mit explizitem 'Mindestens 320 Worte, < 280 ist Verstoss' + Hinweis 'wenn Substanz ausgeht: Lebenslage vertiefen statt abbrechen'. - Output-Format-Beispiel mit MINDESTENS-Hinweis. - generate_draft prüft nach LLM-Call die Wortzahl. Bei <280 Worten: ein einzelner Re-Prompt mit höherer Temperatur (0.5) und Hint zur ersten zu-kurzen Wortzahl. Wenn der zweite Versuch laenger ist, wird er übernommen — sonst bleibt der erste. - max_retries=1 fuer den zweiten Call (nicht endlos). Audit-Hauptbefund war 15/19 PMs unter Soll 320–380 Worten. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
727d7d2976
commit
bdbfc1ff7d
@ -95,7 +95,10 @@ Drücke das aus über:
|
|||||||
|
|
||||||
## Stil
|
## Stil
|
||||||
|
|
||||||
- 320–380 Worte (länger als bisher — konkrete Beispiele brauchen Platz)
|
- **Mindestens 320 Worte, höchstens 400.** Outputs unter 280 Worten
|
||||||
|
sind Verstoß gegen die Vorgabe — wenn dir die Substanz ausgeht,
|
||||||
|
vertiefe eine der drei Lebenslagen mit konkreten Zahlen statt
|
||||||
|
einfach abzubrechen.
|
||||||
- Aktive Verben, kurze Sätze (max 22 Worte)
|
- Aktive Verben, kurze Sätze (max 22 Worte)
|
||||||
- Drucksachen-Nummer einmal im Lead nennen ("Drucksache 21/4757")
|
- Drucksachen-Nummer einmal im Lead nennen ("Drucksache 21/4757")
|
||||||
- Bezug zur News-Lage in 1 Satz, ohne den Medienanbieter zu nennen
|
- Bezug zur News-Lage in 1 Satz, ohne den Medienanbieter zu nennen
|
||||||
@ -159,7 +162,7 @@ Niemals ganze Sätze fett, niemals Zwischenüberschriften.
|
|||||||
Antworte NUR mit gültigem JSON:
|
Antworte NUR mit gültigem JSON:
|
||||||
{
|
{
|
||||||
"titel": "<thesenstark, max 100 Zeichen, NENNT die Bürger:innengruppe oder den konkreten Effekt — nicht den GWÖ-Score>",
|
"titel": "<thesenstark, max 100 Zeichen, NENNT die Bürger:innengruppe oder den konkreten Effekt — nicht den GWÖ-Score>",
|
||||||
"body": "<320–380 Worte. Mindestens 3 Lebenslagen mit konkretem Effekt. Keine GWÖ-Werte-Aufzählung. Kein Score.>"
|
"body": "<MINDESTENS 320 Worte (≥ 280 Worte hartes Minimum), höchstens 400. Mindestens 3 Lebenslagen mit konkretem Effekt. Pro Lebenslage: konkrete Zahlen / Personen / Beträge. Keine GWÖ-Werte-Aufzählung. Kein Score.>"
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
|
|
||||||
@ -444,6 +447,41 @@ async def generate_draft(
|
|||||||
if needs_split:
|
if needs_split:
|
||||||
body = _split_into_thread_posts(body)
|
body = _split_into_thread_posts(body)
|
||||||
|
|
||||||
|
# PM-Wortzahl-Re-Generate: wenn deutlich unter Mindestwortzahl,
|
||||||
|
# ein Re-Prompt mit höherer Temperatur. Nur ein Versuch — sonst
|
||||||
|
# endlose LLM-Calls bei zähen Anträgen.
|
||||||
|
if style == "pm":
|
||||||
|
word_count = len(body.split())
|
||||||
|
if word_count < 280:
|
||||||
|
logger.info(
|
||||||
|
"PM-Wortzahl %s zu niedrig (Soll ≥320), re-generate mit Hint",
|
||||||
|
word_count,
|
||||||
|
)
|
||||||
|
req2 = LlmRequest(
|
||||||
|
system_prompt=system_prompt_active,
|
||||||
|
user_prompt=user_prompt + (
|
||||||
|
f"\n\nWICHTIG: Der erste Versuch hatte nur {word_count} Worte "
|
||||||
|
"und ist zu kurz. Liefere jetzt mindestens 320 Worte mit "
|
||||||
|
"konkreten Zahlen/Personen/Beträgen pro Lebenslage."
|
||||||
|
),
|
||||||
|
model=model,
|
||||||
|
base_temperature=0.5,
|
||||||
|
max_tokens=1800,
|
||||||
|
max_retries=1,
|
||||||
|
json_object_mode=True,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
result2 = await bewerter.bewerte(req2)
|
||||||
|
titel2 = (result2.get("titel") or "").strip()[:200]
|
||||||
|
body2 = (result2.get("body") or "").strip()
|
||||||
|
body2 = body2.replace("\\n", "\n").replace("\\r", "\r").replace("\\t", "\t")
|
||||||
|
body2 = _re.sub(r'([.!?])"([A-ZÄÖÜ])', r'\1\n\n\2', body2)
|
||||||
|
if len(body2.split()) > word_count and titel2 and body2:
|
||||||
|
titel = titel2
|
||||||
|
body = body2
|
||||||
|
except Exception:
|
||||||
|
logger.exception("PM-Wortzahl-Re-Generate fehlgeschlagen")
|
||||||
|
|
||||||
if not titel or not body:
|
if not titel or not body:
|
||||||
raise ValueError("LLM-Response unvollständig (titel oder body leer)")
|
raise ValueError("LLM-Response unvollständig (titel oder body leer)")
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user