import gradio as gr import requests import os import random # Load instructions from local files def load_instruction(persona): try: with open(f"instructions/{persona.lower()}.txt", "r") as file: return file.read() except FileNotFoundError: return "" # Call Cohere R+ model via API def call_cohere_api(system_instruction, user_prompt): headers = { "Authorization": f"Bearer {os.getenv('COHERE_API_KEY')}", "Content-Type": "application/json" } # Append the word limit instruction user_prompt += "\n\nAnswer in 200 words or fewer." payload = { "model": "command-r-plus", "message": user_prompt, "preamble": system_instruction, "max_tokens": 300 } response = requests.post("https://api.cohere.ai/v1/chat", headers=headers, json=payload) if response.status_code == 200: return response.json().get("text", "No response").strip() else: return f"Error: {response.status_code} - {response.text}" # Wrapper for dual assistant responses def ask_forest_oracle(persona1, persona2, prompt): instruction1 = load_instruction(persona1) instruction2 = load_instruction(persona2) response1 = call_cohere_api(instruction1, prompt) response2 = call_cohere_api(instruction2, prompt) return response1, response2 # Load questions from a text file def load_questions(): try: with open("questions.txt", "r") as file: questions = [line.strip() for line in file if line.strip()] return questions except FileNotFoundError: return [] questions_list = load_questions() # Function to get a random question def get_random_question(): if questions_list: return random.choice(questions_list) else: return "No questions found. Please add questions to questions.txt." # Dynamically load persona names from instructions folder personas = [ os.path.splitext(f)[0].capitalize() for f in os.listdir("instructions") if f.endswith(".txt") ] # Gradio Interface with gr.Blocks() as demo: with gr.Row(): with gr.Column(scale=0.15): gr.Image(value="data/MoreThanHumanVoices.png", label="More Than Human Voices", show_label=False) with gr.Column(): gr.Markdown("""# More Than Human Voices 🌳🪶 *Conversations with the more-than-human world.* This interactive experience allows you to ask questions to non-human personas—trees, crows, fungi, rivers—each responding from their own unique ecological viewpoint. Rooted in poetic imagination but grounded in truth, these voices offer insight into the living Earth and our entanglement with it. """) with gr.Row(): persona1 = gr.Dropdown(personas, label="Choose First Persona", value="Western human") persona2 = gr.Dropdown(personas, label="Choose Second Persona", value="Fungal network") # Question box with random question generator with gr.Row(): user_input = gr.Textbox(label="Your Question to them", placeholder="e.g., What do you think of humans?", lines=2) random_button = gr.Button("🎲 Generate Random Question") with gr.Row(): ask_button = gr.Button("🌱 Submit Question") # Textboxes that dynamically display the persona names with gr.Row(): output1 = gr.Textbox(label="Persona 1 Responds") output2 = gr.Textbox(label="Persona 2 Responds") # Update the labels when personas are selected def update_labels(p1, p2): return f"{p1} Responds", f"{p2} Responds" persona1.change(fn=update_labels, inputs=[persona1, persona2], outputs=[output1, output2]) persona2.change(fn=update_labels, inputs=[persona1, persona2], outputs=[output1, output2]) # Button events random_button.click(fn=get_random_question, inputs=[], outputs=[user_input]) ask_button.click(fn=ask_forest_oracle, inputs=[persona1, persona2, user_input], outputs=[output1, output2]) if __name__ == "__main__": demo.launch()