Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import requests | |
| import os | |
| from fastapi import FastAPI | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from ping import add_ping_route | |
| # ===== THEME COLOR VARIABLES ===== | |
| PRIMARY_COLOR = "#13406B" # CPA Dark Corporate Blue | |
| SECONDARY_COLOR = "#CD9D5B" # CPA Muted Bronze/Tan | |
| BACKGROUND_COLOR = "#f8fafc" # Light gray - page background | |
| TEXT_COLOR = "#1e293b" # Dark slate - text color | |
| # Configuration | |
| LANGFLOW_API_URL = os.environ.get("LANGFLOW_API_URL", "") | |
| LANGFLOW_API_KEY = os.environ.get("LANGFLOW_API_KEY", "") | |
| HF_API_KEY = os.environ.get("HF_API_KEY", "") | |
| if not LANGFLOW_API_URL: | |
| print("FATAL: LANGFLOW_API_URL secret not found or is empty.") | |
| else: | |
| print("SUCCESS: LANGFLOW_API_URL loaded securely.") | |
| if not LANGFLOW_API_KEY: | |
| print("FATAL: LANGFLOW_API_KEY secret not found or is empty.") | |
| else: | |
| print("SUCCESS: LANGFLOW_API_KEY loaded securely.") | |
| if not HF_API_KEY: | |
| print("FATAL: HF_API_KEY secret not found or is empty.") | |
| else: | |
| print("SUCCESS: HF_API_KEY loaded securely.") | |
| # Function that calls the LangFlow chat | |
| def call_langflow_api(message): | |
| """ | |
| Call Langflow API and return the response | |
| """ | |
| headers = { | |
| "Content-Type": "application/json", | |
| } | |
| # Add API keys | |
| if HF_API_KEY: | |
| headers["Authorization"] = f"Bearer {HF_API_KEY}" | |
| if LANGFLOW_API_KEY: | |
| headers["x-api-key"] = f"{LANGFLOW_API_KEY}" | |
| # Adjust this payload based on your Langflow API structure | |
| payload = { | |
| "input_value": message, | |
| "output_type": "chat", | |
| "input_type": "chat", | |
| "tweaks": {} | |
| } | |
| try: | |
| response = requests.post( | |
| LANGFLOW_API_URL, | |
| json=payload, | |
| headers=headers, | |
| timeout=30 | |
| ) | |
| response.raise_for_status() | |
| # Parse response - adjust based on your API response structure | |
| data = response.json() | |
| bot_message = data["outputs"][0]["outputs"][0]["results"]["message"]["text"] | |
| return bot_message | |
| except requests.exceptions.RequestException as e: | |
| return f"Error connecting to Langflow: {str(e)}" | |
| except (KeyError, IndexError) as e: | |
| return f"Error parsing response: {str(e)}\nResponse: {data}" | |
| #Create FastAPI App for health check. | |
| fastapi_app = FastAPI(title="Chatbot with Ping API") | |
| # Optional CORS setup | |
| fastapi_app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Add /ping route from ping.py | |
| add_ping_route(fastapi_app, call_langflow_api) | |
| # Custom CSS using theme variables | |
| custom_css = f""" | |
| /* Hide footer */ | |
| footer {{display: none !important;}} | |
| .footer {{display: none !important;}} | |
| #footer {{display: none !important;}} | |
| .svelte-1p1dq6v {{display: none !important;}} | |
| /* Main container background */ | |
| .gradio-container {{ | |
| background-color: {BACKGROUND_COLOR} !important; | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| }} | |
| /* Chatbot container styling */ | |
| #chatbot-window {{ | |
| background-color: {BACKGROUND_COLOR} !important; | |
| border-radius: 12px !important; | |
| box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; | |
| border: 2px solid {PRIMARY_COLOR} !important; | |
| }} | |
| #chatbot-window .placeholder-content {{ | |
| background-color: {BACKGROUND_COLOR} !important; | |
| }} | |
| #chatbot-window .bubble-wrap {{ | |
| background-color: {BACKGROUND_COLOR} !important; | |
| }} | |
| /* Description text */ | |
| #descr p{{ | |
| color: black !important; | |
| font-size: 16px !important; | |
| margin-bottom: 20px !important; | |
| }} | |
| #disclaimer {{ | |
| background-color: {PRIMARY_COLOR} !important; | |
| color: white !important; | |
| font-size: 16px !important; | |
| border: 2px solid {SECONDARY_COLOR} !important; | |
| border-radius: 8px !important; | |
| }} | |
| #disclaimer p {{ | |
| color: white !important; | |
| }} | |
| /* User messages */ | |
| #chatbot-window .message.user {{ | |
| background-color: {SECONDARY_COLOR} !important; | |
| color: white !important; | |
| border: none !important; | |
| }} | |
| #chatbot-window .flex-wrap {{ | |
| border: none !important; | |
| }} | |
| #chatbot-window .message.user p{{ | |
| color: white !important; | |
| }} | |
| /* Bot messages */ | |
| #chatbot-window .message.bot {{ | |
| background-color: {PRIMARY_COLOR} !important; | |
| color: white !important; | |
| border: none !important; | |
| }} | |
| #chatbot-window .message.bot p{{ | |
| color: white !important; | |
| }} | |
| /* All text inside bot messages, avoids changes from browser theme */ | |
| #chatbot-window .message.bot *, | |
| #chatbot-window .message.bot li {{ | |
| color: white !important; | |
| }} | |
| /* Input textbox */ | |
| #input-textbox {{ | |
| background-color: {BACKGROUND_COLOR} !important; | |
| }} | |
| /* this gets the text box and send button to align */ | |
| #component-4 {{ | |
| display: flex; /* ensure it's a flex container */ | |
| align-items: center; /* vertically centers children */ | |
| gap: 10px; /* optional spacing between textbox & button */ | |
| }} | |
| /* this removes the text box border that was unnecessary */ | |
| div.form {{ | |
| --block-border-width: 0px !important; | |
| --block-shadow: none !important; | |
| --block-radius: 0px !important; | |
| padding: 0 !important; | |
| }} | |
| #input-textbox textarea{{ | |
| border: 2px solid {SECONDARY_COLOR} !important; | |
| border-radius: 8px !important; | |
| font-size: 16px !important; | |
| color: {TEXT_COLOR} !important; | |
| background-color: {BACKGROUND_COLOR} !important; | |
| }} | |
| #input-textbox textarea:focus {{ | |
| border-color: {PRIMARY_COLOR} !important; | |
| box-shadow: 0 0 0 3px rgba(19, 64, 107, 0.1) !important; | |
| }} | |
| /* Buttons */ | |
| button {{ | |
| border-radius: 8px !important; | |
| font-weight: 600 !important; | |
| }} | |
| /* Primary buttons (Send) */ | |
| #send-button {{ | |
| background-color: {PRIMARY_COLOR} !important; | |
| color: white !important; | |
| border: none !important; | |
| }} | |
| #send-button:hover {{ | |
| background-color: {SECONDARY_COLOR} !important; | |
| }} | |
| /* Secondary buttons (Clear) */ | |
| button.secondary {{ | |
| background-color: white !important; | |
| color: {PRIMARY_COLOR} !important; | |
| border: 2px solid {SECONDARY_COLOR} !important; | |
| }} | |
| button.secondary:hover {{ | |
| background-color: {BACKGROUND_COLOR} !important; | |
| }} | |
| /* Example buttons */ | |
| #example-buttons button {{ | |
| background-color: {PRIMARY_COLOR} !important; | |
| color: white !important; | |
| border: 2px solid {SECONDARY_COLOR} !important; | |
| border-radius: 8px !important; | |
| font-weight: 500 !important; | |
| }} | |
| #example-buttons button:hover {{ | |
| background-color: {SECONDARY_COLOR} !important; | |
| }} | |
| /* Example label text */ | |
| #example-buttons .label {{ | |
| color: {TEXT_COLOR} !important; | |
| font-size: 16px !important; | |
| }} | |
| """ | |
| # Create custom Gradio interface with Blocks | |
| with gr.Blocks(css=custom_css, analytics_enabled=False) as chatui: | |
| # Description | |
| gr.Markdown( | |
| "Ask Cosmo the cougar questions related to Crown Pointe Academy policies.", | |
| elem_classes="description", | |
| elem_id="descr" | |
| ) | |
| #Diclaimer | |
| gr.HTML("<p> I am an AI guide on school policies, not the official source. I may " \ | |
| "generate misinformation. Verify all results with official school documents. </p>", elem_id="disclaimer") | |
| # Chatbot component - MUST use type='messages' | |
| chatbot = gr.Chatbot( | |
| type='messages', | |
| height=500, | |
| elem_classes="chatbot", | |
| elem_id="chatbot-window" | |
| ) | |
| # Input row | |
| with gr.Row(): | |
| msg = gr.Textbox( | |
| label="", | |
| placeholder="Type your question here...", | |
| scale=4, | |
| show_label=False, | |
| elem_id="input-textbox" | |
| ) | |
| submit = gr.Button( | |
| "Send", | |
| scale=1, | |
| variant="primary", | |
| elem_id="send-button" | |
| ) | |
| # Example buttons | |
| gr.Examples( | |
| examples=[ | |
| "What is the dress code for students?", | |
| "How do I report an absence?", | |
| "What is the policy on cell phones?" | |
| ], | |
| inputs=msg, | |
| label="Try these examples:", | |
| elem_id="example-buttons" | |
| ) | |
| # Clear button | |
| clear = gr.Button("Clear Chat", variant="secondary") | |
| # Chat logic for messages format | |
| def respond(message, chat_history): | |
| if not message.strip(): | |
| return "", chat_history | |
| # Get bot response | |
| bot_message = call_langflow_api(message) | |
| # Append messages in the new format | |
| chat_history.append({"role": "user", "content": message}) | |
| chat_history.append({"role": "assistant", "content": bot_message}) | |
| return "", chat_history | |
| # Event handlers - mark as non-API to avoid schema issues | |
| msg.submit(respond, [msg, chatbot], [msg, chatbot], api_name=False) | |
| submit.click(respond, [msg, chatbot], [msg, chatbot], api_name=False) | |
| clear.click(lambda: [], None, chatbot, queue=False, api_name=False) | |
| # Mount Gradio app to FastAPI at root path | |
| app = gr.mount_gradio_app(fastapi_app, chatui, path="/") |