User-Feedback nach Live-Test:
**1. Idempotenz** — Pressemitteilungen wurden ungespeichert generiert,
doppelter Klick erzeugte doppelten Draft + LLM-Kosten.
- Neuer Helper `_find_existing_draft(drucksache, news_url)` der den
neuesten Draft fuer das Paar zurueckgibt
- `generate_draft()` prueft per Default zuerst den Lookup, liefert
existing zurueck mit `_was_existing=True` (kein LLM-Call)
- `force=True` Parameter fuer bewusste Neu-Generierung
- Endpoint nimmt `?force=true` Query-Param entgegen
- UI: Modal zeigt klar "Bestehender Entwurf vs Neu generiert" Banner,
mit "Neu generieren"-Button im existing-Banner
**2. Premium-Modell statt Default** — User wollte hoehere Sprachqualitaet
("Opus oder sowas"). Da das Projekt Qwen via DashScope nutzt (kein
Anthropic), Wechsel auf `settings.llm_model_premium` (qwen-max).
- Tradeoff: ~3× teurer (~6 Cent statt 2 Cent) und ~2× langsamer
(~30 s statt 15 s) — aber spuerbare Qualitaetsverbesserung in
Pressemitteilungs-Diktion
- confirm-Dialog im Frontend nennt jetzt 6 Cent + 30 s
**3. Wrapper-Verbesserungen** — `auto-fetch-news.sh` aufgeraeumt:
- Container-Check (skip wenn down) analog zu run-digest.sh
- START/END-Timestamps
- Ausfuehrliche cron-install-Doku im Header
- Auto-Backfill: wenn erster Run >= 100 Embeddings (Limit gehit),
wird embed_pending_articles bis zu 500 weitere nachgeholt
Tests: 5 neue (idempotency, force, _find_existing_draft × 3). Suite
1053 gruen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
53 lines
1.9 KiB
Bash
Executable File
53 lines
1.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# Aktuelle-Themen-Dashboard: News-Aggregator-Cron (#170 Phase 1).
|
|
#
|
|
# Holt taeglich Headlines aus AI-erlaubenden, oeffentlich-rechtlichen
|
|
# bzw. parlamentarischen Quellen (Tagesschau-API + Bundestag-RSS),
|
|
# persistiert sie in ``news_articles`` und embeddet die neuen via
|
|
# Qwen-Embeddings-API. Idempotent (URL-PK), wiederhol-bar bei Fehlern.
|
|
#
|
|
# Bewusst NICHT verwendet: RND.de und andere Quellen, die in robots.txt
|
|
# explizit ClaudeBot/GPTBot/CCBot bannen.
|
|
#
|
|
# Erwartete Laufzeit: ~30 s leer (kein neuer Artikel) bis ~3 Min mit
|
|
# 100 Embeddings (Erst-Fetch / Backfill).
|
|
#
|
|
# Install als Host-Cron (taeglich 05:00 Uhr morgens, vor
|
|
# auto-ingest-protocols um 06:30):
|
|
#
|
|
# crontab -e
|
|
# 0 5 * * * /opt/gwoe-antragspruefer-dev/scripts/auto-fetch-news.sh \
|
|
# gwoe-antragspruefer-dev >> /var/log/gwoe-fetch-news.log 2>&1
|
|
#
|
|
# Manueller Aufruf (lokaler Smoketest):
|
|
# ./scripts/auto-fetch-news.sh gwoe-antragspruefer-dev
|
|
|
|
set -euo pipefail
|
|
|
|
CONTAINER="${1:-gwoe-antragspruefer}"
|
|
|
|
# Skip wenn Container nicht laeuft (analog zu run-digest.sh).
|
|
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then
|
|
echo "$(date -Iseconds) SKIP — ${CONTAINER} is not running"
|
|
exit 0
|
|
fi
|
|
|
|
echo "$(date -Iseconds) START auto-fetch-news (container=${CONTAINER})"
|
|
|
|
docker exec -i "$CONTAINER" python <<'EOF'
|
|
from app.news_aggregator import run_aggregator
|
|
stats = run_aggregator()
|
|
print(f" inserted={stats['inserted']} updated={stats['updated']} embedded={stats['embedded']}")
|
|
|
|
# Embeddings-Backfill: wenn der erste Run das Limit (100) gehittet hat,
|
|
# weiter embedden, bis alle pending durch sind. Pro Tag ein paar hundert
|
|
# moeglich, kein Risiko Timing-explosion.
|
|
if stats['embedded'] >= 100:
|
|
from app.news_aggregator import embed_pending_articles
|
|
backfill = embed_pending_articles(limit=500)
|
|
if backfill > 0:
|
|
print(f" embeddings_backfill={backfill}")
|
|
EOF
|
|
|
|
echo "$(date -Iseconds) END auto-fetch-news"
|