Spaces:
Running
Running
| 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 '<p style="color: #6b7280; text-align: center; padding: 20px;">No meetings available</p>' | |
| html_content = '<div style="space-y: 8px;">' | |
| for meeting in meetings_list: | |
| date = meeting.get('date', 'Unknown Date') | |
| rate_decision = meeting.get('rate_decision', 'N/A') | |
| title = meeting.get('title', 'FOMC Meeting') | |
| action = meeting.get('action', 'N/A') | |
| magnitude = meeting.get('magnitude', 'N/A') | |
| summary = meeting.get('summary', 'No summary available') | |
| economic_outlook = meeting.get('economic_outlook', 'N/A') | |
| market_impact = meeting.get('market_impact', 'N/A') | |
| url = meeting.get('url', '') | |
| factors_html = "" | |
| key_factors = meeting.get('key_economic_factors', []) | |
| if key_factors and len(key_factors) > 0: | |
| factors_html = "<p><strong>Key Factors:</strong></p><ul>" | |
| for factor in key_factors: | |
| factors_html += f"<li>{factor}</li>" | |
| factors_html += "</ul>" | |
| html_content += f""" | |
| <details style="border: 1px solid #e5e7eb; border-radius: 6px; padding: 12px; margin-bottom: 8px;"> | |
| <summary style="font-weight: 600; cursor: pointer; color: #1f2937;"> | |
| π {date} - Rate: {rate_decision} | |
| </summary> | |
| <div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid #e5e7eb;"> | |
| <p><strong>Meeting:</strong> {title}</p> | |
| <p><strong>Action:</strong> {action}</p> | |
| <p><strong>Rate:</strong> {rate_decision}</p> | |
| <p><strong>Magnitude:</strong> {magnitude}</p> | |
| <p><strong>Forward Guidance:</strong> {summary}</p> | |
| {factors_html} | |
| <p><strong>Economic Outlook:</strong> {economic_outlook}</p> | |
| <p><strong>Market Impact:</strong> {market_impact}</p> | |
| {f'<p><strong>Source:</strong> <a href="{url}" target="_blank">Fed Minutes PDF</a></p>' if url else ''} | |
| </div> | |
| </details> | |
| """ | |
| html_content += '</div>' | |
| return html_content | |
| meetings_accordion = gr.HTML(generate_meetings_html(FOMC_MEETINGS)) | |
| def search_and_format_meetings(query: str): | |
| """Search meetings and format them for HTML display""" | |
| if not query.strip(): | |
| return generate_meetings_html(FOMC_MEETINGS) | |
| search_result = search_meetings_by_date(query) | |
| if search_result.get("success") and search_result.get("results"): | |
| return generate_meetings_html(search_result["results"]) | |
| else: | |
| return '<p style="color: #ef4444; text-align: center; padding: 20px;">No meetings found matching your search.</p>' | |
| 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() | |