import gradio as gr import os from dotenv import load_dotenv from pathlib import Path from modules.utils import load_processed_meetings, load_prompt_library from src.modules.fed_tools import search_meetings_by_date, FED_TOOLS from src.modules.llm_completions import stream_fed_agent_response load_dotenv() _FILE_PATH = Path(__file__).parents[1] FOMC_MEETINGS = load_processed_meetings() PROMPT_LIBRARY = load_prompt_library() _CUSTOM_CSS = """ .gradio-container { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } .chat-message { border-radius: 10px; padding: 10px; margin: 5px 0; } .function-call { background-color: #f0f8ff; border-left: 4px solid #1e88e5; padding: 10px; margin: 10px 0; border-radius: 5px; } """ _EXAMPLES = [ "What was the rate decision in the last FOMC meeting?", "What is the most likely rate decision in the next FOMC meeting?", "What does the economic outlook look like today?", "Give me a table which summarized the last 5 FOMC meetings" ] def convert_history_to_string(history: list) -> str: previous_messages = "" for msg in history: previous_messages += f"{msg['role'].capitalize()}: {msg['content']}\n\n" return previous_messages def respond_for_chat_interface(message: str, history: list, api_key_input: str = ""): """Enhanced response function for gr.ChatInterface with Fed AI Savant capabilities""" api_key = api_key_input.strip() if api_key_input else os.getenv("FIREWORKS_API_KEY", "") if not api_key: yield "❌ Please enter your Fireworks AI API key in the configuration section above." return message_with_history = convert_history_to_string(history) try: for messages in stream_fed_agent_response( message=message, api_key=api_key, prompt_library=PROMPT_LIBRARY, fed_tools=FED_TOOLS, history=message_with_history ): if isinstance(messages, list) and len(messages) > 0: yield messages else: yield str(messages) except Exception as e: error_msg = f"❌ Error: {str(e)}" yield error_msg # Function to create searchable FOMC meetings accordion def create_fomc_meetings_accordion(): """Create searchable accordion for FOMC meetings""" accordions = [] for meeting in FOMC_MEETINGS: title = f"{meeting['date']} - Rate: {meeting['rate_decision']}" content = f""" **Meeting Title:** {meeting['title']} **Rate Decision:** {meeting['rate_decision']} **Summary:** {meeting['summary']} --- *Click to expand for full meeting details* """ accordions.append((title, content)) return accordions # Create the enhanced interface with gr.Blocks(css=_CUSTOM_CSS, title="Fed AI Savant", theme=gr.themes.Soft()) as demo: # Row 1: Title and Description with gr.Row(): with gr.Column(): gr.Markdown(""" # 🏛️ Fed AI Savant 🏛️ **Intelligent Analysis of Federal Reserve Policy and FOMC Meetings** Ask questions about interest rate decisions, monetary policy changes, and economic analysis based on Federal Reserve meeting minutes. """) # Row 2: API Key Configuration with gr.Row(): with gr.Column(scale=1): gr.Markdown("### Powered by") gr.Image( value=str(_FILE_PATH / "assets" / "fireworks_logo.png"), height=60, width=200, show_label=False, show_download_button=False, container=False, show_fullscreen_button=False, show_share_button=False, ) with gr.Column(scale=1): gr.Markdown("## ⚙️ Configuration") val = os.getenv("FIREWORKS_API_KEY", "") api_key_value = gr.Textbox( label="Fireworks AI API Key", type="password", placeholder="Enter your Fireworks AI API key", value=val, info="Required for AI processing", ) with gr.Column(scale=2): gr.Markdown("### 📋 How to Use") gr.Markdown(""" 1. **Enter your AI API key** 2. **Ask questions** about Fed policy, rate decisions, or FOMC meetings 3. **Review AI reasoning** with expandable explanations and sources """) # Row 3: FOMC Meetings Accordion (Searchable by Date) with gr.Row(): with gr.Column(): gr.Markdown("### 📊 Recent FOMC Meeting Minutes") # Date search date_search = gr.Textbox( placeholder="Search by date (e.g., 2025-07, 'June 2024', etc)...", label="🔍 Search Meetings by Date", lines=1 ) with gr.Accordion("FOMC Meetings", open=False): def generate_meetings_html(meetings_list): """Generate HTML for meetings list""" if not meetings_list: return '
No meetings available
' html_content = 'Key Factors:
Meeting: {title}
Action: {action}
Rate: {rate_decision}
Magnitude: {magnitude}
Forward Guidance: {summary}
{factors_html}Economic Outlook: {economic_outlook}
Market Impact: {market_impact}
{f'Source: Fed Minutes PDF
' if url else ''}No meetings found matching your search.
' with gr.Row(): with gr.Column(): gr.Markdown("### 💬 Fed AI Assistant") chat_interface = gr.ChatInterface( fn=respond_for_chat_interface, type="messages", chatbot=gr.Chatbot(height=600, show_label=False, type="messages"), textbox=gr.Textbox( placeholder="Ask about Fed policy, rate decisions, or FOMC meetings...", scale=10 ), additional_inputs=[api_key_value], cache_examples=False, submit_btn="Send", ) with gr.Row(): with gr.Column(scale=1): example_1 = gr.Button(_EXAMPLES[0], size="md") example_2= gr.Button( _EXAMPLES[1], size="md" ) with gr.Column(scale=1): example_3 = gr.Button(_EXAMPLES[2], size="md") example_4 = gr.Button(_EXAMPLES[3], size="md") date_search.change( search_and_format_meetings, inputs=date_search, outputs=meetings_accordion ) def set_example_text(text): return text example_1.click( lambda: _EXAMPLES[0], outputs=chat_interface.textbox ) example_2.click( lambda: _EXAMPLES[1], outputs=chat_interface.textbox ) example_3.click( lambda: _EXAMPLES[2], outputs=chat_interface.textbox ) example_4.click( lambda: _EXAMPLES[3], outputs=chat_interface.textbox ) if __name__ == "__main__": demo.launch()