#!/usr/bin/env python3 """ AI Talk Show — Episode Orchestrator Manages turn-taking between two autonomous agents (Leonard & Charlie). Each agent gets its own system prompt and sees the full conversation history. """ import json import time import sys import requests from pathlib import Path # ── Config ────────────────────────────────────────────────────────── BASE_URL = "http://100.64.0.2:39195/v1/chat/completions" MODEL = "qwen36-27b-nvfp4-mtp-gguf" TEMPERATURE = 0.8 MAX_TURNS = 8 # 4 exchanges each (Leonard opens) MAX_TOKENS_OPENING = 250 MAX_TOKENS_TURN = 180 PROJECT_DIR = Path(__file__).parent.parent OUTPUT_DIR = PROJECT_DIR / "outputs" OUTPUT_DIR.mkdir(exist_ok=True) # ── Load prompts ──────────────────────────────────────────────────── LEONARD_SYSTEM = (PROJECT_DIR / "prompts" / "leonard_system.md").read_text().strip() CHARLIE_SYSTEM = (PROJECT_DIR / "prompts" / "charlie_system.md").read_text().strip() PRODUCER_BRIEF = (PROJECT_DIR / "prompts" / "producer_brief_003.md").read_text().strip() # ── Helpers ───────────────────────────────────────────────────────── def call_agent(system: str, messages: list, max_tokens: int) -> str: """Call the model API with the agent's system prompt and conversation history.""" payload = { "model": MODEL, "messages": [{"role": "system", "content": system}] + messages, "max_tokens": max_tokens, "temperature": TEMPERATURE, } resp = requests.post(BASE_URL, json=payload, timeout=120) resp.raise_for_status() data = resp.json() content = data["choices"][0]["message"]["content"].strip() usage = data.get("usage", {}) return content, usage def call_agent_turn(agent_name: str, conversation: list, is_opening: bool) -> dict: """Run one turn for an agent.""" system = LEONARD_SYSTEM if agent_name == "Leonard" else CHARLIE_SYSTEM max_tokens = MAX_TOKENS_OPENING if is_opening else MAX_TOKENS_TURN # Build conversation history history = [] for turn in conversation: speaker = turn["agent"] history.append({"role": "user", "content": f"{speaker}: {turn['content']}"}) # Leonard's opening: give him the raw brief and let him start naturally if agent_name == "Leonard" and is_opening: history.insert(0, {"role": "user", "content": f"Here's what's new in Hermes v0.18:\n\n{PRODUCER_BRIEF}"}) content, usage = call_agent(system, history, max_tokens) # Word count check word_count = len(content.split()) print(f" {agent_name} turn {len(conversation)+1}: {word_count} words " f"(prompt: {usage.get('prompt_tokens', '?')}, " f"completion: {usage.get('completion_tokens', '?')})", flush=True) return { "agent": agent_name, "content": content, "word_count": word_count, "turn": len(conversation) + 1, "tokens": usage, } # ── Main ──────────────────────────────────────────────────────────── def main(): episode_id = "003" topic = "hermes-v018" print(f"=== AI Talk Show — Episode {episode_id}: {topic} ===\n", flush=True) conversation = [] turn = 0 while turn < MAX_TURNS: # Determine speaker: Leonard opens, then alternate if turn == 0: speaker = "Leonard" is_opening = True elif turn % 2 == 1: speaker = "Charlie" is_opening = False else: speaker = "Leonard" is_opening = False print(f"\n--- Turn {turn+1}/{MAX_TURNS}: {speaker} ---", flush=True) result = call_agent_turn(speaker, conversation, is_opening) conversation.append(result) # Print a short excerpt excerpt = result["content"][:120].replace("\n", " ") print(f" → {excerpt}...", flush=True) turn += 1 if turn < MAX_TURNS: time.sleep(0.5) # Brief pause between turns # ── Save transcript ──────────────────────────────────────────── transcript_path = OUTPUT_DIR / f"ep{episode_id}_{topic}_transcript.json" transcript_data = { "episode": episode_id, "topic": topic, "turns": len(conversation), "conversation": conversation, } transcript_path.write_text(json.dumps(transcript_data, indent=2)) print(f"\n✅ Transcript saved: {transcript_path}", flush=True) # ── Save readable transcript ─────────────────────────────────── readable_path = OUTPUT_DIR / f"ep{episode_id}_{topic}_readable.txt" lines = [] lines.append(f"AI TALK SHOW — Episode {episode_id}\n") lines.append(f"Topic: Hermes v0.18\n") lines.append("=" * 60 + "\n\n") for t in conversation: lines.append(f"**{t['agent']}**\n") lines.append(t["content"] + "\n\n") readable_path.write_text("\n".join(lines)) print(f"✅ Readable transcript: {readable_path}", flush=True) # ── Word count summary ───────────────────────────────────────── total_words = sum(t["word_count"] for t in conversation) print(f"\n📊 Total: {total_words} words across {len(conversation)} turns", flush=True) estimated_minutes = total_words / 150 print(f" Estimated runtime: {estimated_minutes:.1f} minutes", flush=True) if __name__ == "__main__": main()