Nursing Citizen Development commited on
Commit
197883c
Β·
1 Parent(s): 6131c9a

UI: Premium glassmorphic design with NHS-inspired gradient and modern typography

Browse files
Files changed (1) hide show
  1. app.py +226 -20
app.py CHANGED
@@ -11,34 +11,240 @@ kb = PNAKnowledgeBase(GUIDE_FILENAME)
11
  client = PNAAssistantClient()
12
 
13
  def chat_response(message, history):
14
- # 1. Search Knowledge Base
 
15
  context = kb.search(message)
16
 
17
- # 2. Generate Response using fine-tuned model
18
- # Note: history in Gradio is list of [user, bot] pairs
19
  response = client.generate_response(message, context=context, history=history)
20
 
21
  return response
22
 
23
- # --- UI Layout ---
24
- CSS = """
25
- .gradio-container { max-width: 800px !important; margin: auto !important; }
26
- .header { text-align: center; padding: 20px; border-bottom: 1px solid #eee; }
27
- .title { font-size: 1.5rem; font-weight: bold; color: #2c3e50; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  """
29
 
30
- with gr.Blocks(css=CSS, title="PNA Assistant") as demo:
31
- with gr.Row(elem_classes="header"):
32
- gr.HTML("""
33
- <div class="title">πŸ‘¨πŸΎβ€βš•οΈ Professional Nurse Advocate Assistant πŸ‘©πŸ½β€βš•οΈ</div>
34
- <p>Guiding you through the A-EQUIP model and Restorative Supervision</p>
35
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
- chat = gr.ChatInterface(
38
- fn=chat_response,
39
- examples=["What is the A-EQUIP model?", "Tell me about Restorative Supervision", "What does a PNA do?"],
40
- cache_examples=False
41
- )
42
 
43
  if __name__ == "__main__":
44
- demo.launch()
 
11
  client = PNAAssistantClient()
12
 
13
  def chat_response(message, history):
14
+ """Generate response using RAG + fine-tuned model."""
15
+ # Search Knowledge Base for relevant context
16
  context = kb.search(message)
17
 
18
+ # Generate Response using fine-tuned MedGemma
 
19
  response = client.generate_response(message, context=context, history=history)
20
 
21
  return response
22
 
23
+ # --- Premium CSS ---
24
+ CUSTOM_CSS = """
25
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@600;700&display=swap');
26
+
27
+ /* Root Variables */
28
+ :root {
29
+ --primary: #4f46e5;
30
+ --primary-light: #818cf8;
31
+ --secondary: #0d9488;
32
+ --bg-main: #f8fafc;
33
+ --bg-card: rgba(255, 255, 255, 0.85);
34
+ --text-primary: #1e293b;
35
+ --text-secondary: #64748b;
36
+ --border-color: rgba(148, 163, 184, 0.2);
37
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
38
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
39
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
40
+ }
41
+
42
+ /* Global Styles */
43
+ .gradio-container {
44
+ max-width: 900px !important;
45
+ margin: 0 auto !important;
46
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
47
+ background: var(--bg-main) !important;
48
+ }
49
+
50
+ /* Header */
51
+ .header-container {
52
+ text-align: center;
53
+ padding: 2rem 1rem 1.5rem;
54
+ background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
55
+ border-radius: 0 0 24px 24px;
56
+ margin: -1rem -1rem 1.5rem -1rem;
57
+ box-shadow: var(--shadow-lg);
58
+ }
59
+
60
+ .header-title {
61
+ font-family: 'Outfit', sans-serif;
62
+ font-size: 1.75rem;
63
+ font-weight: 700;
64
+ color: white;
65
+ margin: 0 0 0.5rem 0;
66
+ letter-spacing: -0.02em;
67
+ }
68
+
69
+ .header-subtitle {
70
+ font-size: 0.95rem;
71
+ color: rgba(255, 255, 255, 0.9);
72
+ margin: 0;
73
+ font-weight: 400;
74
+ }
75
+
76
+ .emoji-bar {
77
+ font-size: 1.5rem;
78
+ margin-top: 0.75rem;
79
+ letter-spacing: 0.25rem;
80
+ }
81
+
82
+ /* Chat Container */
83
+ .chat-container {
84
+ background: var(--bg-card) !important;
85
+ backdrop-filter: blur(12px);
86
+ border-radius: 16px !important;
87
+ border: 1px solid var(--border-color) !important;
88
+ box-shadow: var(--shadow-md) !important;
89
+ padding: 1rem !important;
90
+ }
91
+
92
+ /* Chatbot Messages */
93
+ .message-wrap {
94
+ padding: 0.75rem 1rem !important;
95
+ }
96
+
97
+ .user-message, .bot-message {
98
+ border-radius: 16px !important;
99
+ padding: 0.875rem 1rem !important;
100
+ font-size: 0.95rem !important;
101
+ line-height: 1.6 !important;
102
+ }
103
+
104
+ .user-message {
105
+ background: var(--primary) !important;
106
+ color: white !important;
107
+ border-bottom-right-radius: 4px !important;
108
+ }
109
+
110
+ .bot-message {
111
+ background: white !important;
112
+ color: var(--text-primary) !important;
113
+ border: 1px solid var(--border-color) !important;
114
+ border-bottom-left-radius: 4px !important;
115
+ }
116
+
117
+ /* Input Area */
118
+ .input-container textarea {
119
+ border-radius: 24px !important;
120
+ border: 2px solid var(--border-color) !important;
121
+ padding: 0.875rem 1.25rem !important;
122
+ font-size: 0.95rem !important;
123
+ transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
124
+ }
125
+
126
+ .input-container textarea:focus {
127
+ border-color: var(--primary) !important;
128
+ box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important;
129
+ outline: none !important;
130
+ }
131
+
132
+ /* Submit Button */
133
+ .submit-btn {
134
+ background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%) !important;
135
+ border: none !important;
136
+ border-radius: 24px !important;
137
+ padding: 0.75rem 1.5rem !important;
138
+ font-weight: 600 !important;
139
+ color: white !important;
140
+ cursor: pointer !important;
141
+ transition: transform 0.15s ease, box-shadow 0.15s ease !important;
142
+ }
143
+
144
+ .submit-btn:hover {
145
+ transform: translateY(-1px) !important;
146
+ box-shadow: var(--shadow-md) !important;
147
+ }
148
+
149
+ /* Examples */
150
+ .examples-container {
151
+ margin-top: 1rem !important;
152
+ }
153
+
154
+ .examples-container button {
155
+ background: white !important;
156
+ border: 1px solid var(--border-color) !important;
157
+ border-radius: 20px !important;
158
+ padding: 0.5rem 1rem !important;
159
+ font-size: 0.85rem !important;
160
+ color: var(--text-secondary) !important;
161
+ transition: all 0.2s ease !important;
162
+ }
163
+
164
+ .examples-container button:hover {
165
+ border-color: var(--primary) !important;
166
+ color: var(--primary) !important;
167
+ background: rgba(79, 70, 229, 0.05) !important;
168
+ }
169
+
170
+ /* Footer */
171
+ footer {
172
+ display: none !important;
173
+ }
174
+
175
+ /* Disclaimer */
176
+ .disclaimer {
177
+ text-align: center;
178
+ font-size: 0.75rem;
179
+ color: var(--text-secondary);
180
+ margin-top: 1rem;
181
+ padding: 0.75rem;
182
+ background: rgba(148, 163, 184, 0.1);
183
+ border-radius: 8px;
184
+ }
185
  """
186
 
187
+ # --- UI Layout ---
188
+ with gr.Blocks(css=CUSTOM_CSS, title="PNA Assistant", theme=gr.themes.Soft()) as demo:
189
+ # Header
190
+ gr.HTML("""
191
+ <div class="header-container">
192
+ <h1 class="header-title">Professional Nurse Advocate Assistant</h1>
193
+ <p class="header-subtitle">Guiding you through the A-EQUIP model and Restorative Supervision</p>
194
+ <div class="emoji-bar">πŸ‘¨πŸΎβ€βš•οΈ πŸ‘©πŸ½β€βš•οΈ πŸ‘¨πŸΏβ€βš•οΈ πŸ‘©πŸ»β€βš•οΈ πŸ‘©β€βš•οΈ</div>
195
+ </div>
196
+ """)
197
+
198
+ # Chat Interface
199
+ with gr.Column(elem_classes="chat-container"):
200
+ chatbot = gr.Chatbot(
201
+ label="",
202
+ height=400,
203
+ show_label=False,
204
+ avatar_images=(None, "https://em-content.zobj.net/source/apple/391/woman-health-worker-medium-skin-tone_1f469-1f3fd-200d-2695-fe0f.png"),
205
+ bubble_full_width=False,
206
+ )
207
+
208
+ with gr.Row():
209
+ msg = gr.Textbox(
210
+ placeholder="Ask about the A-EQUIP model, Restorative Supervision, or the PNA role...",
211
+ show_label=False,
212
+ container=False,
213
+ elem_classes="input-container",
214
+ scale=9
215
+ )
216
+ submit = gr.Button("Send", elem_classes="submit-btn", scale=1)
217
+
218
+ # Examples
219
+ gr.Examples(
220
+ examples=[
221
+ "What is the A-EQUIP model?",
222
+ "Explain the four functions of clinical supervision",
223
+ "How can I support a colleague through restorative supervision?",
224
+ "What does a Professional Nurse Advocate do?"
225
+ ],
226
+ inputs=msg,
227
+ elem_classes="examples-container"
228
+ )
229
+
230
+ # Disclaimer
231
+ gr.HTML("""
232
+ <div class="disclaimer">
233
+ ⚠️ This tool is for educational purposes only. It does not provide clinical advice.
234
+ </div>
235
+ """)
236
+
237
+ # Event Handlers
238
+ def respond(message, chat_history):
239
+ if not message.strip():
240
+ return "", chat_history
241
+
242
+ bot_response = chat_response(message, chat_history)
243
+ chat_history.append((message, bot_response))
244
+ return "", chat_history
245
 
246
+ msg.submit(respond, [msg, chatbot], [msg, chatbot])
247
+ submit.click(respond, [msg, chatbot], [msg, chatbot])
 
 
 
248
 
249
  if __name__ == "__main__":
250
+ demo.launch(ssr_mode=False)