Download app.py from Denysyk/Lab6: direct link, hf CLI and curl.
- Browser
- Download file 7.27 kB
-
https://huggingface.co/spaces/Denysyk/Lab6/resolve/main/app.py
- Command line
-
hf download hf://spaces/Denysyk/Lab6/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Denysyk/Lab6/resolve/main/app.py
7.27 kB
| """ | |
| Gradio web interface for AI Examiner Agent. | |
| Run: python app.py | |
| """ | |
| import gradio as gr | |
| from agent import ExaminerAgent | |
| _agent: ExaminerAgent | None = None | |
| def init_exam(api_key: str): | |
| """Called when the user clicks 'Start Exam'. Resets chat completely.""" | |
| global _agent | |
| if not api_key.strip(): | |
| return [{ | |
| "role": "assistant", | |
| "content": "Please enter your Groq API key first." | |
| }], gr.update(interactive=False) | |
| try: | |
| _agent = ExaminerAgent(api_key.strip()) | |
| opening = _agent.start() | |
| return [{"role": "assistant", "content": opening}], gr.update(interactive=True) | |
| except Exception as e: | |
| _agent = None | |
| err = str(e) | |
| if "401" in err or "invalid_api_key" in err or "Invalid API Key" in err: | |
| msg = "Invalid API key. Please check your Groq API key at console.groq.com and try again." | |
| elif "429" in err or "rate_limit" in err: | |
| msg = "Rate limit reached. Your daily token quota is exhausted. Please wait until tomorrow or upgrade your Groq plan." | |
| elif "403" in err: | |
| msg = "Access denied. Your API key does not have permission to use this model." | |
| elif "404" in err: | |
| msg = "Model not found. Please contact support." | |
| elif "connection" in err.lower() or "timeout" in err.lower(): | |
| msg = "Connection error. Please check your internet connection and try again." | |
| else: | |
| msg = f"Error: {e}" | |
| return [{"role": "assistant", "content": msg}], gr.update(interactive=False) | |
| def user_message(message: str, history: list): | |
| """Called when the student sends a message.""" | |
| global _agent | |
| if not message.strip(): | |
| return history, "" | |
| if _agent is None: | |
| return history + [ | |
| {"role": "user", "content": message}, | |
| {"role": "assistant", "content": "Please click Start Exam first."}, | |
| ], "" | |
| # Block messages after exam is finished | |
| if _agent.exam_finished: | |
| return history + [ | |
| {"role": "user", "content": message}, | |
| {"role": "assistant", "content": "The exam is already finished. Click Start Exam to begin a new session."}, | |
| ], "" | |
| history = history + [{"role": "user", "content": message}] | |
| try: | |
| reply = _agent.chat(message) | |
| except Exception as e: | |
| err = str(e) | |
| if "429" in err or "rate_limit" in err: | |
| reply = "Rate limit reached. Daily quota exhausted β please try again tomorrow." | |
| elif "401" in err or "invalid_api_key" in err: | |
| reply = "Invalid API key. Please restart and enter a valid Groq key." | |
| elif "connection" in err.lower() or "timeout" in err.lower(): | |
| reply = "Connection error. Please check your internet and try again." | |
| elif "tool_use_failed" in err or "Failed to call a function" in err: | |
| # Leaked function call that wasn't caught β restart agent turn | |
| try: | |
| reply = _agent.chat("Please continue.") | |
| except Exception: | |
| reply = "Model error. Please try sending your message again." | |
| else: | |
| reply = f"Error: {e}" | |
| history = history + [{"role": "assistant", "content": reply}] | |
| return history, "" | |
| # βββ UI ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| CSS = """ | |
| @import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Syne:wght@400;600;800&display=swap'); | |
| body, .gradio-container { | |
| background: #0d0f14 !important; | |
| font-family: 'Syne', sans-serif !important; | |
| } | |
| .title-block { | |
| text-align: center; | |
| padding: 2rem 1rem 1rem; | |
| } | |
| .title-block h1 { | |
| font-family: 'Syne', sans-serif; | |
| font-weight: 800; | |
| font-size: 2.6rem; | |
| letter-spacing: -1px; | |
| background: linear-gradient(135deg, #e2ff5d 0%, #00ffc2 100%); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| margin: 0; | |
| } | |
| .title-block p { | |
| color: #8b95a8; | |
| font-family: 'Space Mono', monospace; | |
| font-size: 0.82rem; | |
| margin-top: 0.4rem; | |
| } | |
| .gr-button-primary { | |
| background: linear-gradient(135deg, #e2ff5d, #00ffc2) !important; | |
| color: #0d0f14 !important; | |
| font-family: 'Space Mono', monospace !important; | |
| font-weight: 700 !important; | |
| border: none !important; | |
| border-radius: 6px !important; | |
| } | |
| .gr-button-primary:hover { filter: brightness(1.1) !important; } | |
| label { color: #8b95a8 !important; font-family: 'Space Mono', monospace !important; font-size: 0.78rem !important; } | |
| input, textarea { background: #141820 !important; border: 1px solid #2a3040 !important; color: #e8ecf4 !important; border-radius: 6px !important; } | |
| .info-box { | |
| background: #141820; | |
| border: 1px solid #2a3040; | |
| border-radius: 8px; | |
| padding: 1rem 1.2rem; | |
| font-family: 'Space Mono', monospace; | |
| font-size: 0.75rem; | |
| color: #5a6478; | |
| line-height: 1.7; | |
| } | |
| .info-box strong { color: #e2ff5d; } | |
| """ | |
| with gr.Blocks(title="AI Examiner Agent") as demo: | |
| gr.HTML(""" | |
| <div class="title-block"> | |
| <h1>⬑ AI Examiner Agent</h1> | |
| <p>NLP course Β· oral exam simulation Β· powered by AI</p> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1, min_width=260): | |
| gr.HTML(""" | |
| <div class="info-box"> | |
| <strong>How it works</strong><br> | |
| 1. Paste your Groq API key<br> | |
| 2. Click <em>Start Exam</em><br> | |
| 3. Tell the bot your name & email<br> | |
| 4. Answer NLP questions<br> | |
| 5. Get your score & feedback | |
| <br><br> | |
| <strong>Demo students</strong><br> | |
| test@test.com / test | |
| </div> | |
| """) | |
| api_key = gr.Textbox( | |
| label="Groq API Key", | |
| placeholder="gsk_...", | |
| type="password", | |
| lines=1, | |
| ) | |
| start_btn = gr.Button("βΆ Start Exam", variant="primary") | |
| with gr.Column(scale=3): | |
| chatbot = gr.Chatbot( | |
| label="Exam Chat", | |
| height=520, | |
| show_label=False, | |
| layout="bubble", | |
| ) | |
| with gr.Row(): | |
| msg_input = gr.Textbox( | |
| placeholder="Type your answer hereβ¦", | |
| show_label=False, | |
| lines=1, | |
| scale=5, | |
| interactive=False, | |
| ) | |
| send_btn = gr.Button("Send β", scale=1, variant="primary") | |
| # Start Exam β clears chat history completely, creates new agent | |
| start_btn.click( | |
| fn=init_exam, | |
| inputs=[api_key], | |
| outputs=[chatbot, msg_input], | |
| ) | |
| send_btn.click( | |
| fn=user_message, | |
| inputs=[msg_input, chatbot], | |
| outputs=[chatbot, msg_input], | |
| ) | |
| msg_input.submit( | |
| fn=user_message, | |
| inputs=[msg_input, chatbot], | |
| outputs=[chatbot, msg_input], | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(share=False, css=CSS) |