fcas / app.py
lsempe's picture
Update app and remove old files
48c2af7
# =============================================================================
# app.py (main entry point)
# =============================================================================
import logging
import os
# Ensure logs folder exists
os.makedirs("logs", exist_ok=True)
# Configure logging
logging.basicConfig(
level=logging.DEBUG, # or INFO if you want less noise
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
handlers=[
logging.FileHandler("logs/app.log", mode="a"), # Log to file
logging.StreamHandler() # Still show in Spaces Logs tab
]
)
logger = logging.getLogger(__name__)
# Example usage
logger.info("App started")
logger.debug("This is debug info")
import gradio as gr
from data_handler import DataHandler
from gradio_callbacks import GradioCallbacks
from gradio_components import (
create_qa_tab, create_filters_tab, create_about_tab
)
def main():
# Initialize data
data_handler = DataHandler()
callbacks = GradioCallbacks(data_handler)
data = data_handler.get_data()
# Create Gradio app
with gr.Blocks(
theme=gr.themes.Monochrome(),
title="FCAS Research Methods Evidence Mapping",
css="""
@import url('https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@400;700&display=swap');
:root {
--primary: #012069;
--secondary: #5E548E;
--accent: #231942;
--text: #686868;
--background: #F9F9F9;
--heading-font: 'Libre Franklin', Sans-serif;
--body-font: 'Helvetica Neue', Arial, Helvetica, sans-serif;
}
.gradio-container {
max-width: 1200px !important;
font-family: var(--body-font);
background-color: var(--background);
color: var(--text);
}
/* Make Gradio primary buttons navy blue with white text */
.gr-button,
.gr-button-primary,
button[class*="primary"] {
background: #012069 !important;
color: #fff !important;
border: none !important;
font-family: var(--body-font);
}
h1, h2, h3, .main-header {
font-family: var(--heading-font);
color: var(--primary);
}
.main-header {
background: var(--secondary);
color: var(--background);
padding: 2rem;
border-radius: 10px;
margin-bottom: 2rem;
}
.gr-button {
background: var(--accent);
color: var(--background);
font-family: var(--body-font);
}
/* Synthesis and references styling */
#synthesis_md, #references_md {
background: linear-gradient(90deg, #ffffff 0%, #fbfdff 100%);
border: 1px solid rgba(1,32,105,0.06);
padding: 16px;
border-radius: 8px;
box-shadow: 0 1px 4px rgba(2,6,23,0.02);
margin-bottom: 0.75rem;
}
#synthesis_md h1, #synthesis_md h2, #synthesis_md h3 {
color: var(--primary);
margin-top: 0;
}
"""
) as app:
# Shared state for Q&A synthesis
qa_synthesis_state = gr.State("")
with gr.Tabs():
create_qa_tab(callbacks, qa_synthesis_state)
create_filters_tab(callbacks, data['countries_list'], data['sectors_list'])
create_about_tab()
return app
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description='FCAS app launcher and utilities')
parser.add_argument('--gemini-multi', action='store_true', help='Run a one-off Gemini multi-speaker TTS generation (CLI mode)')
parser.add_argument('--text', type=str, default=None, help='Text to synthesize (use with --gemini-multi)')
parser.add_argument('--file', type=str, default=None, help='Path to a text file to synthesize (use with --gemini-multi)')
parser.add_argument('--use-stub', action='store_true', help='Set USE_TTS_STUB=1 for offline testing')
args = parser.parse_args()
if args.gemini_multi:
# CLI-only path: run simplified Gemini multi-speaker generation and exit
if args.use_stub:
os.environ['USE_TTS_STUB'] = '1'
# Load data handler and callbacks like the app would
dh = DataHandler()
cb = GradioCallbacks(dh)
# Obtain text to synthesize
synth_text = None
if args.text:
synth_text = args.text
elif args.file:
try:
with open(args.file, 'r', encoding='utf-8') as f:
synth_text = f.read()
except Exception as e:
logger.error('Failed to read input file: %s', e)
raise
else:
logger.error('No --text or --file provided for --gemini-multi. Use --text "..." or --file path.')
raise SystemExit(2)
logger.info('Running Gemini multi-speaker generation (CLI)')
out_path, err, provider, tts_used = cb.generate_podcast_episode(synth_text)
print('Result:', (out_path, err, provider, tts_used))
raise SystemExit(0)
else:
# Auto-run mode: if AUTO_RUN_GEMINI=1 is set in the environment, run a single
# Gemini multi-speaker generation (useful for CI or scripting) and exit.
if os.environ.get('AUTO_RUN_GEMINI', '0') in ('1', 'true', 'True'):
# Load text from PODCAST_TEXT env or from podcast_input.txt if present
synth_text = os.environ.get('PODCAST_TEXT')
if not synth_text and os.path.exists('podcast_input.txt'):
try:
with open('podcast_input.txt', 'r', encoding='utf-8') as f:
synth_text = f.read()
except Exception as e:
logger.error('Failed to read podcast_input.txt: %s', e)
if not synth_text:
logger.error('AUTO_RUN_GEMINI set but no PODCAST_TEXT or podcast_input.txt found.')
raise SystemExit(2)
dh = DataHandler()
cb = GradioCallbacks(dh)
logger.info('AUTO_RUN_GEMINI: running Gemini multi-speaker generation')
out_path, err, provider, tts_used = cb.generate_podcast_episode(synth_text)
print('Result:', (out_path, err, provider, tts_used))
raise SystemExit(0)
app = main()
app.launch(
share=True,
server_name="0.0.0.0",
server_port=7860,
show_error=True
)