"""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)