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 | |
| from src.config.theme_config import CUSTOM_CSS, GRADIO_THEME, EXAMPLE_QUESTIONS | |
| load_dotenv() | |
| _FILE_PATH = Path(__file__).parents[1] | |
| FOMC_MEETINGS = load_processed_meetings() | |
| PROMPT_LIBRARY = load_prompt_library() | |
| 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 | |
| def generate_meetings_html(meetings_list): | |
| """Generate HTML for meetings list with Fireworks AI purple palette""" | |
| if not meetings_list: | |
| return '<p style="color: #64748B; text-align: center; padding: 20px;">No meetings available</p>' | |
| html_content = '<div style="max-height: 600px; overflow-y: auto;">' | |
| for meeting in meetings_list: | |
| date = meeting.get('date', 'Unknown Date') | |
| rate_decision = meeting.get('rate', 'N/A') | |
| title = meeting.get('title', 'FOMC Meeting') | |
| action = meeting.get('action', 'N/A') | |
| magnitude = meeting.get('magnitude', 'N/A') | |
| forward_guidance = meeting.get('forward_guidance') | |
| economic_outlook = meeting.get('economic_outlook') | |
| 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 style='margin: 10px 0 6px 0; font-size: 0.9em; color: #0F172A; font-weight: 600;'>Key Factors:</p><ul style='margin: 4px 0; padding-left: 20px; font-size: 0.88em; color: #64748B;'>" | |
| for factor in key_factors: | |
| factors_html += f"<li style='margin: 4px 0;'>{factor}</li>" | |
| factors_html += "</ul>" | |
| html_content += f""" | |
| <details class="meeting-details" style="border: 1px solid #E6EAF4; border-radius: 10px; margin: 10px 0; background: white; overflow: hidden; transition: all 0.25s ease;"> | |
| <summary class="meeting-summary" style="font-weight: 600; cursor: pointer; color: #0F172A; padding: 14px 18px; font-size: 0.95em; background: linear-gradient(90deg, transparent 0%, #F3F0FF 100%);"> | |
| {date} - {rate_decision} | |
| </summary> | |
| <div class="meeting-content" style="padding: 16px 18px; border-top: 1px solid #E6EAF4; background: #FAFBFC; font-size: 0.88em;"> | |
| <p style="margin: 6px 0; color: #0F172A;"><strong style="color: #6720FF;">Action:</strong> {action}</p> | |
| <p style="margin: 6px 0; color: #0F172A;"><strong style="color: #6720FF;">Magnitude:</strong> {magnitude}</p> | |
| <p style="margin: 10px 0 6px 0; color: #0F172A;"><strong style="color: #6720FF;">Forward Guidance:</strong></p> | |
| <p style="margin: 0 0 10px 0; color: #64748B; line-height: 1.5;">{forward_guidance}</p> | |
| {factors_html} | |
| <p style="margin: 10px 0 6px 0; color: #0F172A;"><strong style="color: #6720FF;">Economic Outlook:</strong></p> | |
| <p style="margin: 0 0 10px 0; color: #64748B; line-height: 1.5;">{economic_outlook}</p> | |
| <p style="margin: 10px 0 6px 0; color: #0F172A;"><strong style="color: #6720FF;">Market Impact:</strong></p> | |
| <p style="margin: 0 0 10px 0; color: #64748B; line-height: 1.5;">{market_impact}</p> | |
| {f'<p style="margin: 10px 0 0 0;"><strong style="color: #6720FF;">Source:</strong> <a href="{url}" target="_blank" style="color: #6720FF; text-decoration: none; transition: color 0.2s ease;">Fed Minutes PDF</a></p>' if url else ''} | |
| </div> | |
| </details> | |
| """ | |
| html_content += '</div>' | |
| return html_content | |
| 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.Blocks(css=CUSTOM_CSS, title="Fed AI Savant", theme=GRADIO_THEME) as demo: | |
| gr.Markdown(""" | |
| <h1 class="header-title" style="font-size: 2.5em; margin-bottom: 0.5em;">Fed AI Savant</h1> | |
| <p style="color: #64748B; font-size: 1.1em; margin-top: 0;">Intelligent Analysis of Federal Reserve Policy and FOMC Meetings with <a href="https://huggingface.co/openai/gpt-oss-120b" target="_blank" style="color: #6720FF;">gpt-oss 120B</a></p> | |
| """) | |
| with gr.Row(): | |
| # Sidebar for FOMC Meetings | |
| with gr.Column(scale=1, min_width=300, elem_classes="meetings-container"): | |
| gr.Markdown("### FOMC Meetings") | |
| # Date search | |
| date_search = gr.Textbox( | |
| placeholder="Search by date...", | |
| label="Search", | |
| lines=1, | |
| container=False, | |
| elem_classes="search-box" | |
| ) | |
| meetings_accordion = gr.HTML(generate_meetings_html(FOMC_MEETINGS)) | |
| # Main content area | |
| with gr.Column(scale=2): | |
| # Compact header with Fireworks AI logo and API key | |
| with gr.Row(elem_classes="compact-header"): | |
| with gr.Column(scale=1, min_width=150): | |
| gr.Markdown("<p style='margin: 0; padding: 0; font-size: 0.85em; color: #64748B;'>Powered by</p>") | |
| gr.Image( | |
| value=str(_FILE_PATH / "assets" / "fireworks_logo.png"), | |
| height=35, | |
| width=140, | |
| show_label=False, | |
| show_download_button=False, | |
| container=False, | |
| show_fullscreen_button=False, | |
| show_share_button=False, | |
| ) | |
| with gr.Column(scale=2): | |
| val = os.getenv("FIREWORKS_API_KEY", "") | |
| api_key_value = gr.Textbox( | |
| label="API Key", | |
| type="password", | |
| placeholder="Enter your Fireworks AI API key", | |
| value=val, | |
| container=True, | |
| elem_classes="compact-input" | |
| ) | |
| # Example Questions - compact version | |
| with gr.Row(elem_classes="compact-examples"): | |
| example_1 = gr.Button(EXAMPLE_QUESTIONS[0], size="sm", scale=1) | |
| example_2 = gr.Button(EXAMPLE_QUESTIONS[1], size="sm", scale=1) | |
| example_3 = gr.Button(EXAMPLE_QUESTIONS[2], size="sm", scale=1) | |
| example_4 = gr.Button(EXAMPLE_QUESTIONS[3], size="sm", scale=1) | |
| # Chat interface with more space | |
| chat_interface = gr.ChatInterface( | |
| fn=respond_for_chat_interface, | |
| type="messages", | |
| chatbot=gr.Chatbot(height=450, show_label=False, type="messages", elem_classes="chat-window"), | |
| 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" | |
| ) | |
| date_search.change( | |
| search_and_format_meetings, | |
| inputs=date_search, | |
| outputs=meetings_accordion | |
| ) | |
| def set_example_text(text): | |
| return text | |
| example_1.click( | |
| lambda: EXAMPLE_QUESTIONS[0], | |
| outputs=chat_interface.textbox | |
| ) | |
| example_2.click( | |
| lambda: EXAMPLE_QUESTIONS[1], | |
| outputs=chat_interface.textbox | |
| ) | |
| example_3.click( | |
| lambda: EXAMPLE_QUESTIONS[2], | |
| outputs=chat_interface.textbox | |
| ) | |
| example_4.click( | |
| lambda: EXAMPLE_QUESTIONS[3], | |
| outputs=chat_interface.textbox | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |