e08c484838
Six-step weekly workflow (research → sources → storyline → draft → quality → publication) supporting Claude, ChatGPT, Gemini, and Mistral in parallel for creative steps. Web search via Anthropic tool for news research. Episode index built from 34 existing KNIEPUNKT episodes for redundancy checks. Sessions persisted as JSON for mid-workflow resume. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
115 lines
3.8 KiB
Python
115 lines
3.8 KiB
Python
"""Draft generation across all configured providers and author selection."""
|
||
from rich.console import Console
|
||
from rich.panel import Panel
|
||
from rich.prompt import Prompt
|
||
|
||
console = Console()
|
||
|
||
_DRAFT_SYSTEM = """Du bist ein erfahrener Ghostwriter für die LinkedIn-Kolumne KNIEPUNKT von Dr. André Knie.
|
||
|
||
Tonvorgaben:
|
||
- Kolumnenhaft und glossenhaft: pointiert, amüsant, Widersprüche und Anekdoten nutzen
|
||
- Kulturell gebildet: griechische/römische Mythologie, Kanonliteratur und klassische deutsche Literatur willkommen
|
||
- Meinungsstark: die Meinung des Autors muss deutlich erkennbar sein
|
||
- Nicht zu technisch: Entscheider-Zielgruppe, kein Tech-Deep-Dive
|
||
- Lesernahe Interpretation: nicht nur Nachrichten referieren, sondern einordnen und bewerten
|
||
|
||
Format: LinkedIn Newsletter-Artikel, 600–900 Wörter. Sprache: Deutsch.
|
||
Füge am Ende an: ## Quellen (nummeriert mit URL/Fundort)."""
|
||
|
||
_ENRICHMENT_SYSTEM = _DRAFT_SYSTEM + (
|
||
"\n\nDu erhältst einen bestehenden Entwurf und Überarbeitungshinweise. "
|
||
"Ändere nur, was explizit verlangt wird. Behalte Ton, Meinung und Aufhänger bei."
|
||
)
|
||
|
||
|
||
def _build_prompt(
|
||
storyline_text: str,
|
||
storyline_choice: int,
|
||
adjustments: str,
|
||
news_digest: str,
|
||
source_assessment: str,
|
||
author_input: dict,
|
||
) -> str:
|
||
adj = f"\nAnpassungen des Autors: {adjustments}" if adjustments else ""
|
||
return f"""Schreibe einen vollständigen KNIEPUNKT-Artikel.
|
||
|
||
Ausgewählte Storyline (Option {storyline_choice}):
|
||
{storyline_text}
|
||
{adj}
|
||
|
||
Verfügbare Nachrichten:
|
||
{news_digest}
|
||
|
||
Quellenbewertung (für Quellenauswahl beachten):
|
||
{source_assessment[:800]}
|
||
|
||
Persönliche Notizen des Autors:
|
||
{author_input['author_news'][:500]}
|
||
|
||
Schreibe jetzt den vollständigen Artikel im KNIEPUNKT-Stil.
|
||
Anhang: ## Quellen (nummeriert mit URL/Fundort)."""
|
||
|
||
|
||
def generate_drafts(
|
||
providers: list,
|
||
storyline_text: str,
|
||
storyline_choice: int,
|
||
adjustments: str,
|
||
news_digest: str,
|
||
source_assessment: str,
|
||
author_input: dict,
|
||
) -> dict[str, str]:
|
||
"""Run draft generation on all providers. Returns {provider_name: draft}."""
|
||
prompt = _build_prompt(storyline_text, storyline_choice, adjustments, news_digest, source_assessment, author_input)
|
||
messages = [{"role": "user", "content": prompt}]
|
||
results = {}
|
||
|
||
for provider in providers:
|
||
console.print(f"\n[yellow]Schreibe Entwurf mit {provider.name}...[/yellow]")
|
||
try:
|
||
results[provider.name] = provider.chat(messages, _DRAFT_SYSTEM, max_tokens=4096)
|
||
except Exception as e:
|
||
console.print(f"[red]{provider.name} übersprungen: {e}[/red]")
|
||
|
||
return results
|
||
|
||
|
||
def select_draft(results: dict[str, str]) -> tuple[str, str]:
|
||
"""Show all drafts, return (provider_name, selected_draft_text)."""
|
||
if not results:
|
||
raise RuntimeError("Kein Modell hat einen Entwurf geliefert. API-Keys und Verbindung prüfen.")
|
||
provider_names = list(results.keys())
|
||
|
||
for name, draft in results.items():
|
||
console.print(Panel(draft, title=f"Entwurf – {name}", border_style="green"))
|
||
console.print()
|
||
|
||
if len(provider_names) > 1:
|
||
choice = Prompt.ask(
|
||
"Welchen Entwurf als Basis verwenden?",
|
||
choices=provider_names,
|
||
default=provider_names[0],
|
||
)
|
||
else:
|
||
choice = provider_names[0]
|
||
|
||
return choice, results[choice]
|
||
|
||
|
||
def enrich_draft(client, draft: str, author_feedback: str) -> str:
|
||
"""Refine the selected draft based on author feedback (Claude only)."""
|
||
from kniepunkt.llm import chat
|
||
|
||
console.print("\n[yellow]Überarbeite Entwurf...[/yellow]")
|
||
|
||
prompt = f"""Überarbeite diesen KNIEPUNKT-Entwurf basierend auf den folgenden Autorenhinweisen.
|
||
|
||
Aktueller Entwurf:
|
||
{draft}
|
||
|
||
Hinweise des Autors:
|
||
{author_feedback}"""
|
||
|
||
return chat(client, [{"role": "user", "content": prompt}], _ENRICHMENT_SYSTEM, max_tokens=4096)
|