wait, why are you talking about location. The issue is that Gradio 4.44 doesn’t recognise demo route. Have i made a mistake?
import gradio as gr
from gradio.themes import Base
from dotenv import load_dotenv
import os
import base64
import yaml
from llm_article import ChainManager
from llm_chat import ChatManager
import regex as re
import datetime
import requests
from requests_futures.sessions import FuturesSession
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
import uvicorn
app = FastAPI()
#chain_manager = ChainManager()
#chat_manager = ChatManager()
load_dotenv()
HUGGINGFACE_TOKEN = os.getenv(“HUGGINGFACE_TOKEN”)
PORT = int(os.environ.get(“PORT”, 7860))
GOOGLE_API_KEY = os.getenv(“GOOGLE_API_KEY”)
GOOGLE_URL = os.getenv(“GOOGLE_URL”)
USERNAME = os.getenv(“APP_USERNAME”)
PASSWORD = os.getenv(“APP_PASSWORD”)
if not USERNAME or not PASSWORD:
raise ValueError(“APP_USERNAME and/or APP_PASSWORD are not set in the environment.”)
if not HUGGINGFACE_TOKEN:
raise ValueError(“HUGGINGFACE_TOKEN is not set! Make sure to define it in .env.”)
with open(“config_cannes.yaml”, “r”, encoding=“utf-8”) as file:
config = yaml.safe_load(file)
api_info = config[“API”]
prompts = config[“prompts”]
rag_queries = config[“rag”]
parameters = config[“parameters”]
instruction = config[“user_instruction”]
custom_head = config[“custom_head”]
def authenticate(user, pwd):
if user == USERNAME and pwd == PASSWORD:
return “Login Successful”, True
return “Invalid credentials. Please try again.”, False
def check_login(user, pwd):
msg, success = authenticate(user, pwd)
if success:
# Hide the login page, show the main app UI.
return gr.update(visible=False), gr.update(visible=True), msg
else:
# Keep the login page visible (and hide the main app UI).
return gr.update(visible=True), gr.update(visible=False), msg
def show_chat_ui(state, region):
r = region
#print(f”region is {region}”)
if region is None:
return gr.update(visible=False), gr.update(visible=True), gr.update(visible=True), state, r
else:
chat_manager = state or ChatManager()
chat_manager._initialize_config()
return gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), chat_manager, r
def show_chat_ui_random(state):
chat_manager = state or ChatManager()
chat_manager._initialize_config()
region = chat_manager.select_random_region()
tree = select_tree(region)
return gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), gr.update(value=f”{region} — {tree}”), chat_manager
def record_user_info(name, email, organization):
base_url = GOOGLE_URL
url = f”{base_url}?apiKey={GOOGLE_API_KEY}”
"organization": organization,
"time": str(datetime.datetime.now()),
# Create a FuturesSession which wraps around the standard requests.Session
session = FuturesSession()
# Send the request asynchronously.
future = session.post(url, json=payload)
def callback(sess, response):
print("Status code:", response.status_code)
print("Response:", response.text)
future.add_done_callback(lambda f: callback(session, f.result()))
# response = requests.post(url, json=payload)
# # print("Status code:", response.status_code)
# print("Raw response text:", response.text)
def start_app(name, email, organization):
if not (name and email and organization):
return “Unfilled”
if not is_valid_email(email):
return “NonEmail”
return ""
def is_valid_email(email):
# This regular expression is a common pattern for basic email validation.
email_regex = r”(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$)”
return re.match(email_regex, email) is not None
def handle_click(name, email, organization):
msg = start_app(name, email, organization)
print(msg)
if msg == “Unfilled”:
return gr.update(visible=True), gr.update(visible=False), gr.update(visible=True), gr.update(visible=False)
elif msg == “NonEmail”:
return gr.update(visible=False), gr.update(visible=True), gr.update(visible=True), gr.update(visible=False)
else:
record_user_info(name, email, organization)
return gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=True)
def custom_css():
return gr.HTML('')
def select_tree(location):
#“Czechia/Travný”, “Brazil/Viçosa”, “Korea/Hongcheon”
if location == “Czechia/Travný”:
return “Silver Fir #907,439”
if location == “Brazil/Viçosa”:
return “Juçara Palm #907,438”
if location == “Korea/Hongcheon”:
return “Tulip Tree #907,437”
def select_location(tree):
if tree == “Tulip Tree/Liriodendron Tulipifera”:
return “Korea/Hongcheon”
if tree == “Juçara Palm/Euterpe Edulis”:
return “Brazil/Viçosa”
if tree == “Silver Fir/Abies Alba”:
return “Czechia/Travný”
def handle_region_selection(choice, state, region):
#instruction = chat_manager.select_regional_instruction(choice)
chat_manager = state or ChatManager()
s_region = region or choice
location = select_location(choice)
chat_manager.update_region(location)
tree = select_tree(location)
return gr.update(value=f”
{location} — {tree}
”), chat_manager, s_region
def handle_send(_input, history, state):
chat_manager = state or ChatManager()
print(f”🧩 Session {id(chat_manager)} — Region: {chat_manager.region} — Step: {chat_manager.process_step}”)
response, cleared_input = chat_manager.generate_tree_response(_input, history)
return response, cleared_input, gr.update(visible=True), chat_manager
class CustomTheme(Base):
def init(self):
super().init()
self.primary_hue = gr.themes.colors.orange # Adjusts the primary color
self.secondary_hue = 340 # Adjusts the secondary color
self.neutral_hue = “#c7c7c7”
self.body_text_color = “#c7c7c7”
#self.font = “IBM Plex Mono” # Change the default font
self.font = “Courier”
self.background_fill_primary = “#0c0f18”
# chatbot
self.background_fill_secondary = “#121826”
self.color_accent_soft = “#394150”
self.border_color_accent = “#495469”
self.block_background_fill = "#0c0f18"
self.input_background_fill = "#394050"
self.block_border_color = "#394050"
self.border_color_primary = "#394050"
#self.input_border_width = 0
#self.input_border_color = "#394050"
self.button_primary_background_fill = "#394050"
self.button_secondary_background_fill = "#394050"
self.button_secondary_text_color = "#c7c7c7"
self.checkbox_background_color_selected = "#121726"
self.checkbox_background_color_hover = "#121726"
self.checkbox_background_color_focus = "#121726"
self.checkbox_label_background_fill_selected = "#121726"
js_func = """
function refresh() {
const url = new URL(window.location);
if (url.searchParams.get(‘__theme’) !== ‘dark’) {
url.searchParams.set(‘__theme’, ‘dark’);
window.location.href = url.href;
}
}
refresh();
"""
#def launch_gradio():
with gr.Blocks(theme=CustomTheme(), title=“Tree Correspondents - In Conversation”, head=custom_head) as demo:
# !!!!!!=====IMPORTANT DECLARE CHATMANAGER STATE========
region_state = gr.State(None)
reply_state = gr.State(None)
# Custom CSS for centering elements
custom_css() # Load the custom styles
with demo.route(“Login”, “/login”):
# Define a login page column
with gr.Column(visible=False, elem_id=“login_page”) as login_page:
gr.Markdown("", elem_id=“login-spacer”)
gr.Markdown(”
Please Log In with the credentials you received
”, elem_id=“login_title”)
log_input = gr.Textbox(label=“Username”, placeholder=“Enter your username”, container=False)
pwd_input = gr.Textbox(label=“Password”, placeholder=“Enter your password”, type=“password”, container=False)
login_message = gr.Markdown("") # This area will show success or error messages.
login_button = gr.Button(“Log In”)
with demo.route(“Landing”, ”/”):
with gr.Column(visible=True) as landing_page:
gr.Markdown("", elem_id=“land-spacer”)
# Centered Title
gr.Markdown(“
---Welcome to Tree Correspondents
”, elem_id=“land-title”)
gr.Markdown(“
Where the wisdom of the forests meets the power of journalism.
”
"
", elem_id=“description_text”)
gr.Markdown(“
---This is a tool built for journalists.
”, elem_id=“land-intro”)
gr.Markdown(“
Use it to uncover stories rooted in truth — about deforestation,
”
“climate change, ecosystem health, and nature’s resilience.
”
"
"
“
Every insight you receive is backed by real-time, ground-level data
”
“and verified scientific models, giving you a credible foundation to build your reporting on.
”
"
"
“
We believe that when trees speak, the world should listen.
”
“And when journalists listen, change can happen.”
"
"
"
", elem_id=“description_text”)
gr.Markdown(“
To gain access, please tell us a little about yourself:
”, elem_id=“info-prompt”)
name_input = gr.Textbox(
show_label=False,
container=False,
type=“text”,
placeholder=“Name”,
elem_id=“my-textbox”
)
email_input = gr.Textbox(
show_label=False,
container=False,
type=“email”,
placeholder=“Email”,
elem_id=“my-textbox”
)
org_input = gr.Textbox(
show_label=False,
container=False,
type=“text”,
placeholder=“Organization”,
elem_id=“my-textbox”,
)
with gr.Row(visible=False) as error_message:
floating_message = gr.Markdown(value=“
Please fill in all fields to proceed.
”, elem_id=“floating-message”)
with gr.Row(visible=False) as bad_email:
floating_message_2 = gr.Markdown(value=“
This is not a valid email format.
”, elem_id=“floating-message-2”)
# gr.Markdown("
"
# “Let’s write stories the world needs to read.”)
gr.Markdown("", elem_id=“one-line-spacer”)
begin_button = gr.Button(“enter”, elem_id=“start-button”)
#floating_message = gr.HTML(value="", elem_id="floating-message")
with gr.Column(visible=False) as base_ui:
# Add a flexible top spacer for centering effect
gr.Markdown("", elem_id="top-spacer")
gr.Markdown("<h1 style='text-align:left;'>--- Tree Correspondents</h1>", elem_id="title")
gr.Markdown("<h3>You’ve arrived at a newsroom unlike any other — one where trees speak through science and stories.</h3>",
# Empty space for vertical adjustment
gr.Markdown("", height=30)
gr.Markdown("<p>Across the world, sensors placed in the soil, trunks, and canopies of trees are collecting "
"real-time environmental data. That data is then processed through an advanced bespoke and secure AI "
"language model trained to turn complex signals into clear, credible, and compelling narratives. "
"Listen for yourself by chatting with one of our tree correspondents here. </p>")
gr.Markdown("", elem_id="mid-spacer")
# Button container for selection
#gr.Markdown("Select a Correspondent")
#site_radio = gr.Radio(["Czechia/Travný", "Brazil/Viçosa", "Korea/Hongcheon"])
# site_selection = gr.Dropdown(["Tulip Tree/Liriodendron Tulipifera", "Juçara Palm/Euterpe Edulis", "Silver Fir/Abies Alba"],
# value=None, interactive=True, allow_custom_value=False,
# filterable=False, container=False, elem_id="country_dropdown", scale=1)
# chain_button = gr.Button("📝 Article Generation", scale=1)
chat_button = gr.Button("Connect to the wisdom of trees", scale=2)
with gr.Column(visible=False) as no_region:
no_region_message = gr.Markdown("Please select a Correspondent to continue.")
# Add a flexible bottom spacer to push elements to the center
gr.Markdown("", elem_id="bottom-spacer")
# ===========================================
# ===========================================
# 🔹 CHAT UI (Initially Hidden)
# ===========================================
# ===========================================
with gr.Column(visible=False) as chat_ui:
gr.Markdown("## Tree Correspondents / **In Conversation**"
selected_region = gr.Markdown(" ### Select Region", elem_id="region_text")
# back_button = gr.Button("Back", size="sm", elem_id="back_button")
# site_selection = gr.Dropdown(["Czechia/Travný", "Brazil/Viçosa", "Korea/Hongcheon"], label="Select Region",
# value="Brazil/Viçosa", interactive=True, allow_custom_value=False,
# filterable=False, container=False, elem_id="country_dropdown")
# general_instruction = gr.Textbox(label="Journalist Role", interactive=True, visible=False, value=parameters['general_instruction'], lines=3)
# refine_state = gr.State(True)
# gr.Markdown("<p>Welcome to the only place in the world where you can ask a tree anything and get a response. So whatever kind of information you are looking for, just type it below. You can ask all kinds of questions, including things like, “who are you?” or “how does this work?” or “what’s the temperature where you are?” or even more granular questions like, “is your soil dryer than usual?” or “tell me more about pollution in your part of the world.”</p>",
# elem_id="user_instruction")
gr.Markdown(instruction,elem_id="user_instruction")
with gr.Column(visible=False) as chat_box:
conversation_box = gr.Chatbot(label="Tree Chat", elem_id="tree_chatbox")
user_input = gr.Textbox(label="Enter your message", interactive=True, lines=1, elem_id="message_box")
send_button = gr.Button("Send")
# with gr.Column(scale=1):
# reset_button = gr.Button("Reset Chat")
reset_button = gr.Button("Reset Chat", size="sm")
back_button = gr.Button("Go Back", size="sm")
# Empty space for vertical adjustment
# gr.Markdown("", elem_id="spacer")
# chat_download_btn = gr.Button("📥 Download History", variant="secondary")
# chat_file_output = gr.File(label="Download your history here")
# ===========================================
# ===========================================
# ===========================================
# ===========================================
# 🔹 Button Click Actions to Show UI
outputs=[chat_ui, base_ui, no_region, selected_region, chat_state]
# Wire up the login button: when clicked, check the credentials.
inputs=[log_input, pwd_input],
outputs=[login_page, base_ui, login_message]
inputs=[name_input, email_input, org_input],
outputs=[error_message, bad_email, landing_page, login_page],
// 2) This JS runs after handle_click returns.
// If all fields were valid (i.e. landing_page was hidden),
// move the browser to /login in the history API.
if (document.getElementById('landing_page').style.display === 'none') {
history.pushState({}, '', '/login');
# Button action: Process user input and update chatbox
# get_chat_manager().generate_tree_response,
# inputs=[general_instruction, user_input, conversation_box],
# outputs=[conversation_box, user_input],
# lambda instruction, u_input, history, state:
# ((state or ChatManager()).generate_tree_response(instruction, u_input, history) + (state or ChatManager(),)),
inputs=[user_input, conversation_box, chat_state],
outputs=[conversation_box, user_input, chat_box, chat_state],
((state or ChatManager()).reset_chat(), state or ChatManager()),
#get_chat_manager().reset_chat,
outputs=[conversation_box, chat_state],
((state or ChatManager()).reset_chat(), state or ChatManager(),
gr.update(visible=False), gr.update(visible=True)),
outputs=[conversation_box, chat_state, chat_ui, base_ui]
# handle_region_selection,
# inputs=[site_selection, chat_state, region_state],
# outputs=[selected_region, chat_state, region_state]
#chat_download_btn.click(chat_manager.save_history, inputs=[conversation_box], outputs=[chat_file_output])
# Allow enter key submission
# lambda instruction, u_input, history, state:
# ((state or ChatManager()).generate_tree_response(instruction, u_input, history) + (state or ChatManager(),)),
inputs=[user_input, conversation_box, chat_state],
outputs=[conversation_box, user_input, chat_box, chat_state]
demo.launch(
server_name=“0.0.0.0”,
server_port=PORT,
favicon_path=“tree.png”
)