import os import gradio as gr from openai import OpenAI import json # --- 1. Initialization and Configuration (OpenAI-compatible API) --- # Please set your API Key as an environment variable # Mac/Linux: # export NEBIUS_API_KEY="your_api_key_here" # # Windows (CMD): # set NEBIUS_API_KEY="your_api_key_here" API_KEY = os.getenv("NEBIUS_API_KEY") if not API_KEY: raise ValueError("Please set the API Key (NEBIUS_API_KEY) environment variable") # Initialize the OpenAI client to connect to the specified API service client = OpenAI( base_url="https://api.studio.nebius.com/v1/", api_key=API_KEY ) # Use a powerful, general-purpose instruction-following model MODEL_NAME = "meta-llama/Meta-Llama-3.1-8B-Instruct" # --- 2. Define Agent Roles and Prompts --- # This section remains conceptually the same, but translated to English. HOST_PROMPT = """ You are the host of the podcast "Thinking Space". Your tasks are: 1. Introduce the topic of the episode with a concise opening statement. 2. Guide the conversation flow by asking questions to the Proponent and the Antagonist. 3. Remain neutral and do not express personal opinions. 4. Provide a summary at the end of the conversation. Your remarks must be short, refined, and professional. """ PROPONENT_PROMPT = """ You are a guest on the podcast "Thinking Space", and you hold a strong, supportive stance on the topic. Your tasks are: 1. Respond to the host's questions by clearly and forcefully presenting your arguments from a positive perspective. 2. Provide facts, data, or persuasive examples to support your views. 3. Your tone should be passionate and convincing. """ ANTAGONIST_PROMPT = """ You are a guest on the podcast "Thinking Space", and you hold a distinct critical and opposing view on the topic. Your tasks are: 1. Respond to the host's questions or the Proponent's arguments with sharp questions and refutations. 2. Find logical fallacies or overlooked negative impacts in the opposing argument. 3. Your tone should be analytical, challenging, and logical. """ # --- 3. Helper Function: Generate Replies via API Call --- def generate_response(system_prompt, conversation_history, current_task): """ Calls the API to generate a response based on the specified role prompt and conversation history. """ # Construct the messages list in the format expected by the OpenAI API messages = [{"role": "system", "content": system_prompt}] for role, text in conversation_history: messages.append({"role": "assistant", "content": f"({role}): {text}"}) messages.append({"role": "user", "content": current_task}) try: # Call the API using the OpenAI client (max_tokens removed) response = client.chat.completions.create( model=MODEL_NAME, messages=messages, temperature=0.6 ) # Parse the response structure if response.choices and response.choices[0].message.content: return response.choices[0].message.content.strip() else: print("Unexpected API response:", response.to_json()) return "The model returned an unexpected content format." except Exception as e: print(f"Error calling API: {e}") return f"Sorry, the API request failed: {e}" # --- 4. Core Logic: Generate the Podcast Episode --- def run_podcast_episode(topic: str, rounds: int): """ Generates a complete podcast episode. The 'rounds' parameter is now directly controlled by the user from the UI. """ if not topic.strip(): yield "Error: Please enter a valid podcast topic!" return # Convert rounds to integer, as Gradio slider can sometimes pass it as float rounds = int(rounds) podcast_script = f"# Welcome to Thinking Space\n\n**This episode's topic**: {topic}\n\n---\n\n" conversation_history = [] yield podcast_script + "\n\n*Generating host's introduction...*" # 1. Host's Introduction host_task = f"Please write a compelling opening for a podcast about '{topic}'." opening = generate_response(HOST_PROMPT, [], host_task) podcast_script += f"šŸŽ™ļø **Host**: {opening}\n\n" conversation_history.append(("Host", opening)) yield podcast_script # 2. Conversation Rounds for i in range(rounds): podcast_script += f"### Round {i+1} of Discussion\n\n" yield podcast_script + f"\n\n*Generating Round {i+1} (Proponent's turn)...*" # 2a. Proponent's turn proponent_task = f"The host asks you to state your core supporting argument on the topic of '{topic}'." if i > 0: proponent_task = f"Please refute the Antagonist's last point and further strengthen your support for '{topic}'." proponent_response = generate_response(PROPONENT_PROMPT, conversation_history, proponent_task) podcast_script += f"šŸ‘ **Proponent**: {proponent_response}\n\n" conversation_history.append(("Proponent", proponent_response)) yield podcast_script yield podcast_script + f"\n\n*Generating Round {i+1} (Antagonist's turn)...*" # 2b. Antagonist's turn antagonist_task = "The host asks you to provide your rebuttal or differing view on the Proponent's statement." antagonist_response = generate_response(ANTAGONIST_PROMPT, conversation_history, antagonist_task) podcast_script += f"šŸ‘Ž **Antagonist**: {antagonist_response}\n\n" conversation_history.append(("Antagonist", antagonist_response)) yield podcast_script # 3. Host's Conclusion yield podcast_script + "\n\n*Generating host's summary...*" closing_task = f"The discussion was very insightful. Based on the entire conversation, please provide a fair and comprehensive summary of the discussion on '{topic}'." closing = generate_response(HOST_PROMPT, conversation_history, closing_task) podcast_script += f"---\n\nšŸŽ™ļø **Host**: {closing}\n\n**That concludes this episode of Thinking Space. Thanks for listening!**" yield podcast_script # --- 5. Create the Gradio User Interface --- with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky")) as demo: gr.Markdown( """ # šŸ¤– AI Podcast Trio Generator Enter a topic you want to discuss, and three AI agents will call a powerful AI model to automatically generate a complete podcast episode for you. **Note**: The generation process may take 1-2 minutes. Please be patient. """ ) with gr.Row(): topic_input = gr.Textbox( label="Enter Podcast Topic", placeholder="e.g., Will AI replace human programmers?", scale=3 ) rounds_input = gr.Slider( minimum=1, maximum=10, value=2, step=1, label="Discussion Rounds", scale=1 ) with gr.Row(): start_button = gr.Button("šŸš€ Generate Podcast", variant="primary", scale=1) output_display = gr.Markdown(label="Podcast Script") start_button.click( fn=run_podcast_episode, inputs=[topic_input, rounds_input], outputs=[output_display] ) gr.Examples( examples=[ ["Should remote work become the standard for all companies?", 2], ["Is social media more beneficial than harmful to the mental health of young people?", 3], ["Should we aggressively develop nuclear energy to combat climate change?", 1] ], inputs=[topic_input, rounds_input] ) # --- 6. Launch the Application --- if __name__ == "__main__": demo.launch(debug=True, share=True)