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
|
||||
|
||||
- 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)
|
||||
- Drucksachen-Nummer einmal im Lead nennen ("Drucksache 21/4757")
|
||||
- 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:
|
||||
{
|
||||
"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:
|
||||
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:
|
||||
raise ValueError("LLM-Response unvollständig (titel oder body leer)")
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user