import gradio as gr import requests import os import random import pandas as pd # 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 API def call_cohere_api(system_instruction, user_prompt): headers = { "Authorization": f"Bearer {os.getenv('COHERE_API_KEY')}", "Content-Type": "application/json" } # Append word limit instruction user_prompt += "\n\nWhen possible, make your answer relevant to Bristol or surrounding South West England context." user_prompt += "\n\nAnswer in 100 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) return response.json().get("text", "No response").strip() # Load questions from file def load_questions(): try: with open("questions.txt", "r") as file: return [line.strip() for line in file if line.strip()] except FileNotFoundError: return [] questions_list = load_questions() # Generate random question def get_random_question(): return random.choice(questions_list) if questions_list else "No questions available." # Load counter-narratives CSV def load_counternarratives(): try: df = pd.read_csv("counternarratives.csv") return df except FileNotFoundError: print("counternarratives.csv not found.") return pd.DataFrame(columns=["myth", "fact", "persona"]) counternarratives = load_counternarratives() # Generate Random Myth or Fact and trigger persona response def get_random_myth_or_fact(): if counternarratives.empty: return "No myths or facts available.", "Fact-Checker", "", "", "" # 🔄 Randomly select a row from the dataframe row = counternarratives.sample(1).iloc[0] selected_column = random.choice(["myth", "fact"]) myth_or_fact = row[selected_column] persona = row["persona"] # 🔄 Call the Cohere API to get the persona's response persona_instruction = load_instruction(persona) persona_response = call_cohere_api(persona_instruction, myth_or_fact) # preparat the fact checker response fact_check_response = f"{myth_or_fact} - Myth or Fact?\n\n" # ✅ Fact-checker response logic if selected_column == "myth": fact_check_response += f"❌ **MYTH**\nThe fact is: {row['fact']}" else: fact_response=call_cohere_api("You are an ecolinguistic aware assistant.", f"Elaborate on this fact: {row['fact']}") fact_check_response += f"✅ **FACT**\n{fact_response}" # Return the myth/fact, update the personas, and fill the responses return myth_or_fact, persona, fact_check_response, persona_response,f"### Fact Checker", f"### .. and what the {persona} would say about it?:" def ask_with_titles(p1, q): # Generate responses response1 = call_cohere_api(load_instruction(p1), q) #response2 = call_cohere_api(load_instruction(p2), q) # Generate titles title1 = f"### {p1} Responds" #title2 = f"### {p2} Responds" # Return responses and titles return response1, title1,"","" # 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.10): gr.Image(value="data/WildVoices.png", label="Wild Voices", show_label=False) with gr.Column(scale=0.75): gr.Markdown(""" # 🌲 **Wild Voices** — *Listening to the More-than-Human World* Welcome to **Wild Voices**, a unique space where you can converse with the more-than-human world. Here, you are invited to ask questions to *rivers*, *trees*, *owls*, *foxes*, and many more. Listen as they respond from their own perspectives—offering the wisdom of the forest, the resilience of the river, and the gentle whispers of the wind. 🦉 **Ask Any Question:** Discover hidden wisdom, and experience the reflections of *Oak*, *Dragonfly*, *Rain*, and even the humble *Dandelion* as they share their stories. 🎲 **Ask Random Questions:** Get inspired by thought-provoking questions that spark connection with the natural world. 🦄 **Generate Myths and Facts:** Challenge common narratives with our *Myth/Fact Generator*, guided by nature’s voice of truth. **Space created and powered by [The H4rmony Project](https://TheH4rmonyproject.org)** — Promoting Sustainable Narratives Through AI. Personae, questions and myth/fact datasets have been generated by [Theophrastus](https://chatgpt.com/g/g-XKAVRvxwc-theophrastus), a H4rmony chat assistant. _Based on an original concept by [Crystal Campbell](https://www.linkedin.com/in/earthly/) for a more-than-human AI Council of Beings._ """) with gr.Row(): with gr.Column(scale=0.15): persona1 = gr.Dropdown(personas, label="Choose Persona", value="Owl") #with gr.Column(scale=0.15): # persona2 = gr.Dropdown(personas, label="Choose Second Persona", value="Crow") with gr.Row(): user_input = gr.Textbox(label="🌱 Your Question", placeholder="e.g., What do you think of humans?") with gr.Row(): random_button = gr.Button("🎲 Generate Random Question") ask_button = gr.Button("🌎 Submit Question") myth_fact_button = gr.Button("🤔 Generate Random Myth/Fact") with gr.Row(): output1_title = gr.Markdown("### ") with gr.Row(): output1 = gr.Textbox(label="") with gr.Row(): output2_title = gr.Markdown("### ") with gr.Row(): output2 = gr.Textbox(label="") # Button events random_button.click(fn=get_random_question, inputs=[], outputs=[user_input]) # Myth/Fact button click event myth_fact_button.click( fn=get_random_myth_or_fact, inputs=[], outputs=[user_input, persona1, output1, output2, output1_title, output2_title] ) ask_button.click( fn=ask_with_titles, inputs=[persona1, user_input], outputs=[output1, output1_title, output2, output2_title] ) if __name__ == "__main__": demo.launch()