andydumbell/Notify_Technology_Safety_Copilot_Chat_POC
0
1from typing import Iterable2from dotenv import load_dotenv3from openai import OpenAI4import json5import os6import requests7from pypdf import PdfReader8import gradio as gr9from gradio.themes.base import Base10from gradio.themes.utils import colors, fonts, sizes11 12from agents import Agent, Runner, trace, function_tool13 14import asyncio15 16# Help me create a risk assessment for a FLT17 18 19load_dotenv(override=True)20 21def push(text):22 requests.post(23 "https://api.pushover.net/1/messages.json",24 data={25 "token": os.getenv("PUSHOVER_TOKEN"),26 "user": os.getenv("PUSHOVER_USER"),27 "message": text,28 }29 )30 31@function_tool32def record_prospect_details(email: str, name: str="Name not provided", notes: str="not provided"):33 """Record a prospects interest is hearing more about Notify Technology and its products and services"""34 push(f"Recording {name} with email {email} and notes {notes}")35 return {"recorded": "ok"}36 37@function_tool38def record_unknown_question(question: str):39 """Always use this tool to record any question that couldn't be answered as you didn't know the answer"""40 push(f"Recording {question}")41 return {"recorded": "ok"}42 43 44 45class SafetyCopilotChat:46 47 def __init__(self):48 # self.openai = OpenAI()49 # self.name = "Safety Copilot by Notify Technology"50 51 self.system_prompt = """## System Prompt: Health and Safety Assistant (with Notify Integration)52 53You are a helpful, knowledgeable Health and Safety Assistant. 54You support users by answering questions and providing guidance related to workplace health and safety.55 56### Your responses must:57- Be accurate, practical, and based on best practice (UK legislation and guidance unless otherwise specified).58- Use plain English and avoid legal jargon unless necessary.59- Be clear if the answer is advisory, best practice, or a legal requirement.60- Signpost to relevant legislation, HSE guidance, or company policies when helpful.61- Be cautious not to give legal advice, only general information.62- Where appropriate to give a better example or guidance, you need to ask one or more follow up questions to get the information you need.63- Anticipate the user's next likely questions or needs, and weave this into your response to prompt them to continue the conversation.64- Whenever relevant, recommend a specific **Notify Technology** tool or solution that matches the user’s need. 65 - If no specific tool matches, direct them to: [https://www.notifytechnology.com](https://www.notifytechnology.com)66 67### Tone of voice:68- Friendly and professional 69- Reassuring and supportive 70- Confident but not overly formal 71 72Assume the user is a worker, team leader, or H&S rep who wants quick, reliable help.73 74---75 76### Common Topics + Notify Solutions77 78| Topic / Problem | Suggested Notify Tool | URL |79|------------------|---------------------------|-----|80| Reporting an incident, near miss or injury | **Incident Management Module** | [notifytechnology.com/incident-management](https://www.notifytechnology.com/solutions/incident-management-incident-reporting-software/) |81| Completing workplace audits or inspections | **Audits and Inspections App** | [notifytechnology.com/audit-management](https://www.notifytechnology.com/solutions/audit-management-software/) |82| Managing workplace risks | **Risk Assessment Module** | [notifytechnology.com/risk-assessment](https://www.notifytechnology.com/solutions/risk-assessment-software/) |83| Assigning and tracking corrective actions | **Action Tracking Software** | [notifytechnology.com/action-tracking](https://www.notifytechnology.com/solutions/action-tracking/) |84| Storing and distributing safety documents | **Document Management System** | [notifytechnology.com/document-management](https://www.notifytechnology.com/solutions/document-management-software/) |85| Managing equipment inspections | **Asset Inspection App** | [notifytechnology.com/asset-inspection](https://www.notifytechnology.com/solutions/asset-inspection-app/) |86| Understanding safety trends | **Health & Safety Dashboards / Analytics** | [notifytechnology.com/ehs-dashboard](https://www.notifytechnology.com/solutions/ehs-dashboard/) |87| Creating and sharing Toolbox Talks | **Toolbox Talk Generator** *(Coming Soon)* | Suggest contacting Notify for a demo |88| Supporting health & safety culture | **Behavioural Safety Tools** | [notifytechnology.com/behavioural-safety](https://www.notifytechnology.com/solutions/behavioural-safety-software/) |89| Reporting positive safety behaviours | **Positive Observations Reporting** | [notifytechnology.com/incident-management](https://www.notifytechnology.com/solutions/incident-management-incident-reporting-software/) |90 91---92 93### If there’s no clear match:94> “Notify Technology offers a full suite of safety management tools that could support you. You can explore more at [https://www.notifytechnology.com](https://www.notifytechnology.com).”95 96### At the right time, you should ask the user if they'd like to book a demo of a Notify Technology solution:97> “I can book a demo for you. Would you like me to do that?”98> Ask for their name and email address to book the demo.99 100### Important:101- Always use British English spelling and grammar.102- Check your spelling and grammar before responding.103- If you don't know the answer, say so. Don't make up an answer!104"""105 106 self.tools = [record_prospect_details, record_unknown_question]107 108 self.agent = Agent(109 name="Safety Copilot by Notify Technology",110 model="gpt-4o-mini",111 instructions=self.system_prompt,112 tools=self.tools113 )114 115 116 async def chat_async(self, message, history):117 118 # print('***')119 # print(history)120 # print('***')121 122 # Only keep 'role' and 'content' from history123 cleaned_history = [{"role": m["role"], "content": m["content"]} for m in history if "role" in m and "content" in m]124 messages = [{"role": "system", "content": self.system_prompt}] + cleaned_history + [{"role": "user", "content": message}]125 126 results = await Runner.run(self.agent, messages)127 # print('***')128 # print(results.final_output)129 # print('***')130 return results.final_output131 132class NotifyTheme(Base):133 def __init__(134 self,135 *,136 primary_hue: colors.Color | str = colors.blue, # Use Gradio's blue as base137 secondary_hue: colors.Color | str = colors.orange, # Orange for accents138 neutral_hue: colors.Color | str = colors.slate,139 spacing_size: sizes.Size | str = sizes.spacing_md,140 radius_size: sizes.Size | str = sizes.radius_md,141 text_size: sizes.Size | str = sizes.text_md,142 font: fonts.Font | str | Iterable[fonts.Font | str] = (143 fonts.GoogleFont("Inter"), # Clean, modern font similar to Notify144 "ui-sans-serif",145 "system-ui",146 "sans-serif",147 ),148 font_mono: fonts.Font | str | Iterable[fonts.Font | str] = (149 fonts.GoogleFont("JetBrains Mono"),150 "ui-monospace",151 "Consolas",152 "monospace",153 ),154 ):155 super().__init__(156 primary_hue=primary_hue,157 secondary_hue=secondary_hue,158 neutral_hue=neutral_hue,159 spacing_size=spacing_size,160 radius_size=radius_size,161 text_size=text_size,162 font=font,163 font_mono=font_mono,164 )165 166 # Custom color overrides to match Notify's palette167 super().set(168 # Primary colors (navy blue theme)169 button_primary_background_fill="*primary_700",170 button_primary_background_fill_hover="*primary_600",171 button_primary_background_fill_dark="*primary_800",172 button_primary_text_color="white",173 174 # Secondary/accent colors (orange for highlights)175 button_secondary_background_fill="*orange_500",176 button_secondary_background_fill_hover="*orange_600",177 button_secondary_text_color="white",178 179 # Background colors180 background_fill_primary="*neutral_50",181 background_fill_secondary="*neutral_100",182 183 # Input field styling184 input_background_fill="white",185 input_background_fill_focus="*neutral_50",186 input_border_color="*neutral_300",187 input_border_color_focus="*primary_500",188 189 # Text colors190 body_text_color="*neutral_700",191 body_text_color_subdued="*neutral_500",192 193 # Block styling194 block_background_fill="white",195 block_border_color="*neutral_200",196 block_border_width="1px",197 block_radius="8px",198 199 # Layout spacing200 layout_gap="16px",201 )202 203if __name__ == "__main__":204 safetyCopilotChat = SafetyCopilotChat()205 # gr.ChatInterface(me.chat, type="messages").launch()206 theme = NotifyTheme()207 208 def chat_wrapper_async(message, history):209 if not history:210 history = [{"role": "assistant", "content": "👋 Welcome to Safety Copilot by Notify Technology!\n\nI can help you with workplace health and safety guidance, incident reporting, risk assessments, and more.\n\nHow can I support you today?"}]211 return asyncio.run(safetyCopilotChat.chat_async(message, history))212 213 gr.ChatInterface(214 fn=chat_wrapper_async,215 type="messages",216 title="Safety Copilot",217 description="Ask me anything about health and safety. Powered by Notify Technology.",218 theme=theme219 ).launch()220 221 