Skip to content

Commit b0c8695

Browse files
authored
fix notifications and improve cooldown logic (#2922)
1 parent 1a6060e commit b0c8695

File tree

1 file changed

+70
-16
lines changed

1 file changed

+70
-16
lines changed

plugins/example/notifications/hey_omi.py

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import logging
44
import time
55
import os
6+
import requests
67
from collections import defaultdict
78
from openai import OpenAI
89
from tenacity import retry, stop_after_attempt, wait_exponential
@@ -21,6 +22,15 @@
2122

2223
client = OpenAI(api_key=api_key)
2324

25+
# OMI App credentials for notifications
26+
omi_app_id = os.getenv('HEY_OMI_APP_ID')
27+
omi_app_secret = os.getenv('HEY_OMI_APP_SECRET')
28+
29+
if not omi_app_id or not omi_app_secret:
30+
raise ValueError("HEY_OMI_APP_ID and HEY_OMI_APP_SECRET environment variables are required")
31+
32+
print(f"OMI App ID loaded: {omi_app_id}")
33+
2434
router = APIRouter(prefix="/notifications", tags=["notifications"])
2535

2636
# Set up logging
@@ -31,7 +41,7 @@
3141
TRIGGER_PHRASES = ["hey omi", "hey, omi"] # Base triggers
3242
PARTIAL_FIRST = ["hey", "hey,"] # First part of trigger
3343
PARTIAL_SECOND = ["omi"] # Second part of trigger
34-
QUESTION_AGGREGATION_TIME = 5 # seconds to wait for collecting the question
44+
QUESTION_AGGREGATION_TIME = 10 # seconds to wait for collecting the question
3545

3646
# Replace the message buffer with a class to better manage state
3747
class MessageBuffer:
@@ -81,7 +91,7 @@ def cleanup_old_sessions(self):
8191

8292
# Add cooldown tracking
8393
notification_cooldowns = defaultdict(float)
84-
NOTIFICATION_COOLDOWN = 10 # 10 seconds cooldown between notifications for each session
94+
NOTIFICATION_COOLDOWN = 15 # 15 seconds cooldown between notifications for each session
8595

8696
# Add these near the top of the file, after the imports
8797
if os.getenv('HTTPS_PROXY'):
@@ -101,7 +111,7 @@ def get_openai_response(text):
101111
"""Get response from OpenAI for the user's question"""
102112
try:
103113
logger.info(f"Sending question to OpenAI: {text}")
104-
114+
105115
response = client.chat.completions.create(
106116
model="gpt-4",
107117
messages=[
@@ -112,21 +122,46 @@ def get_openai_response(text):
112122
max_tokens=150,
113123
timeout=30
114124
)
115-
125+
116126
answer = response.choices[0].message.content.strip()
117127
logger.info(f"Received response from OpenAI: {answer}")
118128
return answer
119129
except Exception as e:
120130
logger.error(f"Error getting OpenAI response: {str(e)}")
121131
return "I'm sorry, I encountered an error processing your request."
122132

133+
134+
def send_omi_notification(uid: str, message: str):
135+
"""Send notification using OMI's notifications endpoint"""
136+
try:
137+
url = f"https://api.omi.me/v2/integrations/{omi_app_id}/notification"
138+
headers = {
139+
"Authorization": f"Bearer {omi_app_secret}",
140+
"Content-Type": "application/json"
141+
}
142+
params = {
143+
"uid": uid,
144+
"message": message
145+
}
146+
147+
logger.info(f"Sending notification to OMI for uid {uid}: {message}")
148+
149+
response = requests.post(url, headers=headers, params=params, timeout=30)
150+
response.raise_for_status()
151+
152+
logger.info(f"Successfully sent notification to OMI for uid {uid}")
153+
return True
154+
except Exception as e:
155+
logger.error(f"Error sending notification to OMI: {str(e)}")
156+
return False
157+
123158
@router.post('/webhook')
124159
async def webhook(request: WebhookRequest):
125160
logger.info("Received webhook POST request")
126161
logger.info(f"Received data: {request.dict()}")
127162

128163
session_id = request.session_id
129-
uid = request.uid
164+
uid = request.uid or session_id # Use session_id as uid if uid is not provided
130165
logger.info(f"Processing request for session_id: {session_id}, uid: {uid}")
131166

132167
if not session_id:
@@ -141,12 +176,18 @@ async def webhook(request: WebhookRequest):
141176
# Add debug logging
142177
logger.debug(f"Current buffer state for session {session_id}: {buffer_data}")
143178

179+
# Check and handle cooldown
180+
last_notification_time = notification_cooldowns.get(session_id, 0)
181+
time_since_last_notification = current_time - last_notification_time
182+
183+
# If cooldown has expired, reset it
184+
if time_since_last_notification >= NOTIFICATION_COOLDOWN:
185+
notification_cooldowns[session_id] = 0
186+
144187
# Only check cooldown if we have a trigger and are about to process
145-
if buffer_data['trigger_detected'] and not buffer_data['response_sent']:
146-
time_since_last_notification = current_time - notification_cooldowns[session_id]
147-
if time_since_last_notification < NOTIFICATION_COOLDOWN:
148-
logger.info(f"Cooldown active. {NOTIFICATION_COOLDOWN - time_since_last_notification:.0f}s remaining")
149-
return WebhookResponse(status="success")
188+
if buffer_data['trigger_detected'] and not buffer_data['response_sent'] and time_since_last_notification < NOTIFICATION_COOLDOWN:
189+
logger.info(f"Cooldown active. {NOTIFICATION_COOLDOWN - time_since_last_notification:.0f}s remaining")
190+
return WebhookResponse(status="success")
150191

151192
# Process each segment
152193
for segment in segments:
@@ -164,7 +205,7 @@ async def webhook(request: WebhookRequest):
164205
buffer_data['collected_question'] = []
165206
buffer_data['response_sent'] = False
166207
buffer_data['partial_trigger'] = False
167-
notification_cooldowns[session_id] = current_time # Set cooldown when trigger is detected
208+
# Note: cooldown is now set when notification is actually sent, not when trigger is detected
168209

169210
# Extract any question part that comes after the trigger
170211
question_part = text.split('omi,')[-1].strip() if 'omi,' in text.lower() else ''
@@ -222,24 +263,37 @@ async def webhook(request: WebhookRequest):
222263
)
223264

224265
if should_process and buffer_data['collected_question']:
225-
# Process question and send response
266+
# Process question and send notification
226267
full_question = ' '.join(buffer_data['collected_question']).strip()
227268
if not full_question.endswith('?'):
228269
full_question += '?'
229-
270+
230271
logger.info(f"Processing complete question: {full_question}")
231272
response = get_openai_response(full_question)
232273
logger.info(f"Got response from OpenAI: {response}")
233-
274+
275+
# Send notification using OMI endpoint
276+
if uid:
277+
notification_success = send_omi_notification(uid, response)
278+
if notification_success:
279+
logger.info(f"Successfully sent notification for session {session_id}")
280+
# Set cooldown timestamp when notification is successfully sent
281+
notification_cooldowns[session_id] = current_time
282+
else:
283+
logger.error(f"Failed to send notification for session {session_id}")
284+
else:
285+
logger.error(f"No uid provided for session {session_id}, cannot send notification")
286+
234287
# Reset all states
235288
buffer_data['trigger_detected'] = False
236289
buffer_data['trigger_time'] = 0
237290
buffer_data['collected_question'] = []
238291
buffer_data['response_sent'] = True
239292
buffer_data['partial_trigger'] = False
240293
has_processed = True
241-
242-
return WebhookResponse(status="success", message=response)
294+
295+
# Return success without message (notification sent separately)
296+
return WebhookResponse(status="success")
243297

244298
# Return success if no response needed
245299
return WebhookResponse(status="success")

0 commit comments

Comments
 (0)