forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfeedback.py
More file actions
124 lines (107 loc) · 4.08 KB
/
Copy pathfeedback.py
File metadata and controls
124 lines (107 loc) · 4.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""Shared write path into the feedback ledger.
Three separate endpoints rate a chat message (mobile legacy, mobile v2,
desktop) and each already had its own persistence. Rather than teach each one
how to build a ledger row, they all call ``record_chat_message_feedback``,
which looks the message up once and captures the coordinates the daily report
needs: which session the turn belonged to, when it happened, and which prompt
revision produced it.
Capturing coordinates at write time is the point. Without them the report job
would have to scan a user's whole message history to locate a rated turn, which
is both slow and — on a collection this size — expensive enough to matter.
"""
import logging
from typing import Optional
import database.chat as chat_db
import database.feedback as feedback_db
from models.feedback import FeedbackSurface, FeedbackTargetKind
logger = logging.getLogger(__name__)
def _attr(message, key: str):
"""Read a field off a Message model or the raw dict, whichever we got."""
value = getattr(message, key, None)
if value is None and isinstance(message, dict):
value = message.get(key)
return value
def record_chat_message_feedback(
uid: str,
message_id: str,
value: int,
*,
surface: FeedbackSurface = FeedbackSurface.chat_text,
reason: Optional[str] = None,
comment: Optional[str] = None,
platform: Optional[str] = None,
app_version: Optional[str] = None,
) -> Optional[str]:
"""Append a chat-message rating to the ledger. Returns the event id or None.
Best-effort by design: the caller has already persisted the rating itself,
so this never raises and never fails the user's request.
"""
chat_session_id = None
target_created_at = None
app_id = None
langsmith_run_id = None
prompt_name = None
prompt_commit = None
try:
found = chat_db.get_message(uid, message_id)
if found:
message, _ = found
chat_session_id = _attr(message, 'chat_session_id')
target_created_at = _attr(message, 'created_at')
app_id = _attr(message, 'app_id')
langsmith_run_id = _attr(message, 'langsmith_run_id')
prompt_name = _attr(message, 'prompt_name')
prompt_commit = _attr(message, 'prompt_commit')
except Exception as e:
# Coordinates are an optimization; a rating with none is still worth
# recording, and the report resolves the window from the id alone.
logger.error(f'Could not read coordinates for rated message {message_id}: {e}')
return feedback_db.record_feedback_event(
uid,
surface,
FeedbackTargetKind.chat_message,
message_id,
value,
reason=reason,
comment=comment,
platform=platform,
app_version=app_version,
app_id=app_id,
chat_session_id=chat_session_id,
target_created_at=target_created_at,
langsmith_run_id=langsmith_run_id,
prompt_name=prompt_name,
prompt_commit=prompt_commit,
)
def record_conversation_summary_feedback(
uid: str,
conversation_id: str,
value: int,
*,
reason: Optional[str] = None,
comment: Optional[str] = None,
) -> Optional[str]:
return feedback_db.record_feedback_event(
uid,
FeedbackSurface.conversation_summary,
FeedbackTargetKind.conversation,
conversation_id,
value,
reason=reason,
comment=comment,
)
def record_memory_feedback(uid: str, memory_id: str, keep: bool) -> Optional[str]:
"""Record a memory keep/discard verdict.
Discarding a memory is the memories list's thumbs-down. Until now it only
set ``user_review: False`` on the memory document — a mutable flag with no
timestamp, so "which memories were rejected yesterday" had no answer. The
ledger row gives that verdict a time and puts it in the same report as
every other negative signal.
"""
return feedback_db.record_feedback_event(
uid,
FeedbackSurface.memory,
FeedbackTargetKind.memory,
memory_id,
1 if keep else -1,
)