unique_toolkit 0.5.55__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. unique_toolkit/_common/validate_required_values.py +21 -0
  2. unique_toolkit/app/__init__.py +20 -0
  3. unique_toolkit/app/schemas.py +73 -7
  4. unique_toolkit/chat/__init__.py +5 -4
  5. unique_toolkit/chat/constants.py +3 -0
  6. unique_toolkit/chat/functions.py +661 -0
  7. unique_toolkit/chat/schemas.py +11 -11
  8. unique_toolkit/chat/service.py +273 -430
  9. unique_toolkit/content/__init__.py +1 -0
  10. unique_toolkit/content/constants.py +2 -0
  11. unique_toolkit/content/functions.py +475 -0
  12. unique_toolkit/content/service.py +163 -315
  13. unique_toolkit/content/utils.py +32 -0
  14. unique_toolkit/embedding/__init__.py +3 -0
  15. unique_toolkit/embedding/constants.py +2 -0
  16. unique_toolkit/embedding/functions.py +79 -0
  17. unique_toolkit/embedding/service.py +47 -34
  18. unique_toolkit/evaluators/__init__.py +1 -0
  19. unique_toolkit/evaluators/constants.py +1 -0
  20. unique_toolkit/evaluators/context_relevancy/constants.py +3 -3
  21. unique_toolkit/evaluators/context_relevancy/utils.py +5 -2
  22. unique_toolkit/evaluators/hallucination/utils.py +2 -1
  23. unique_toolkit/language_model/__init__.py +1 -0
  24. unique_toolkit/language_model/constants.py +4 -0
  25. unique_toolkit/language_model/functions.py +362 -0
  26. unique_toolkit/language_model/service.py +246 -293
  27. unique_toolkit/short_term_memory/__init__.py +5 -0
  28. unique_toolkit/short_term_memory/constants.py +1 -0
  29. unique_toolkit/short_term_memory/functions.py +175 -0
  30. unique_toolkit/short_term_memory/service.py +153 -27
  31. {unique_toolkit-0.5.55.dist-info → unique_toolkit-0.6.0.dist-info}/METADATA +33 -7
  32. unique_toolkit-0.6.0.dist-info/RECORD +64 -0
  33. unique_toolkit-0.5.55.dist-info/RECORD +0 -50
  34. {unique_toolkit-0.5.55.dist-info → unique_toolkit-0.6.0.dist-info}/LICENSE +0 -0
  35. {unique_toolkit-0.5.55.dist-info → unique_toolkit-0.6.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,661 @@
1
+ import logging
2
+ import re
3
+ from typing import Any, Dict, List
4
+
5
+ import unique_sdk
6
+ from unique_sdk._list_object import ListObject
7
+
8
+ from unique_toolkit._common import _time_utils
9
+ from unique_toolkit.chat.constants import DEFAULT_MAX_MESSAGES
10
+ from unique_toolkit.chat.schemas import (
11
+ ChatMessage,
12
+ ChatMessageAssessment,
13
+ ChatMessageAssessmentLabel,
14
+ ChatMessageAssessmentStatus,
15
+ ChatMessageAssessmentType,
16
+ ChatMessageRole,
17
+ )
18
+ from unique_toolkit.content.schemas import ContentReference
19
+ from unique_toolkit.content.utils import count_tokens
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ def modify_message(
25
+ user_id: str,
26
+ company_id: str,
27
+ assistant_message_id: str,
28
+ chat_id: str,
29
+ user_message_id: str,
30
+ user_message_text: str,
31
+ assistant: bool,
32
+ content: str | None = None,
33
+ original_content: str | None = None,
34
+ references: list[ContentReference] | None = None,
35
+ debug_info: dict | None = None,
36
+ message_id: str | None = None,
37
+ set_completed_at: bool = False,
38
+ ) -> ChatMessage:
39
+ """
40
+ Modifies a chat message synchronously.
41
+
42
+ Args:
43
+ user_id (str): The user ID.
44
+ company_id (str): The company ID.
45
+ assistant_message_id (str): The assistant message ID.
46
+ chat_id (str): The chat ID.
47
+ user_message_id (str): The user message ID.
48
+ user_message_text (str): The user message text.
49
+ assistant (bool): Whether the message is an assistant message.
50
+ content (str, optional): The new content for the message.
51
+ original_content (str, optional): The original content for the message.
52
+ message_id (str, optional): The message ID. Defaults to None, then the ChatState assistant message id is used.
53
+ references (list[ContentReference]): list of ContentReference objects. Defaults to None.
54
+ debug_info (dict[str, Any]], optional): Debug information. Defaults to None.
55
+ set_completed_at (bool, optional): Whether to set the completedAt field with the current date time. Defaults to False.
56
+
57
+ Returns:
58
+ ChatMessage: The modified message.
59
+
60
+ Raises:
61
+ Exception: If the modification fails.
62
+ """
63
+ try:
64
+ params = _construct_message_modify_params(
65
+ user_id=user_id,
66
+ company_id=company_id,
67
+ assistant_message_id=assistant_message_id,
68
+ chat_id=chat_id,
69
+ user_message_id=user_message_id,
70
+ user_message_text=user_message_text,
71
+ assistant=assistant,
72
+ content=content,
73
+ original_content=original_content,
74
+ references=references,
75
+ debug_info=debug_info,
76
+ message_id=message_id,
77
+ set_completed_at=set_completed_at,
78
+ )
79
+ message = unique_sdk.Message.modify(**params)
80
+ return ChatMessage(**message)
81
+ except Exception as e:
82
+ logger.error(f"Failed to modify user message: {e}")
83
+ raise e
84
+
85
+
86
+ async def modify_message_async(
87
+ user_id: str,
88
+ company_id: str,
89
+ assistant_message_id: str,
90
+ chat_id: str,
91
+ user_message_id: str,
92
+ user_message_text: str,
93
+ assistant: bool,
94
+ content: str | None = None,
95
+ original_content: str | None = None,
96
+ references: list[ContentReference] | None = None,
97
+ debug_info: dict | None = None,
98
+ message_id: str | None = None,
99
+ set_completed_at: bool = False,
100
+ ) -> ChatMessage:
101
+ """
102
+ Modifies a chat message asynchronously.
103
+
104
+ Args:
105
+ user_id (str): The user ID.
106
+ company_id (str): The company ID.
107
+ assistant_message_id (str): The assistant message ID.
108
+ chat_id (str): The chat ID.
109
+ user_message_id (str): The user message ID.
110
+ user_message_text (str): The user message text.
111
+ assistant (bool): Whether the message is an assistant message.
112
+ content (str, optional): The new content for the message.
113
+ original_content (str, optional): The original content for the message.
114
+ message_id (str, optional): The message ID. Defaults to None, then the ChatState assistant message id is used.
115
+ references (list[ContentReference]): list of ContentReference objects. Defaults to None.
116
+ debug_info (dict[str, Any]], optional): Debug information. Defaults to None.
117
+ set_completed_at (bool, optional): Whether to set the completedAt field with the current date time. Defaults to False.
118
+
119
+ Returns:
120
+ ChatMessage: The modified message.
121
+
122
+ Raises:
123
+ Exception: If the modification fails.
124
+ """
125
+ try:
126
+ params = _construct_message_modify_params(
127
+ user_id=user_id,
128
+ company_id=company_id,
129
+ assistant_message_id=assistant_message_id,
130
+ chat_id=chat_id,
131
+ user_message_id=user_message_id,
132
+ user_message_text=user_message_text,
133
+ assistant=assistant,
134
+ content=content,
135
+ original_content=original_content,
136
+ references=references,
137
+ debug_info=debug_info,
138
+ message_id=message_id,
139
+ set_completed_at=set_completed_at,
140
+ )
141
+ message = await unique_sdk.Message.modify_async(**params)
142
+ return ChatMessage(**message)
143
+ except Exception as e:
144
+ logger.error(f"Failed to modify user message: {e}")
145
+ raise e
146
+
147
+
148
+ def map_references(references: List[ContentReference]) -> List[Dict[str, Any]]:
149
+ return [
150
+ {
151
+ "name": ref.name,
152
+ "url": ref.url,
153
+ "sequenceNumber": ref.sequence_number,
154
+ "sourceId": ref.source_id,
155
+ "source": ref.source,
156
+ }
157
+ for ref in references
158
+ ]
159
+
160
+
161
+ def _construct_message_modify_params(
162
+ user_id: str,
163
+ company_id: str,
164
+ assistant_message_id: str,
165
+ chat_id: str,
166
+ user_message_id: str,
167
+ user_message_text: str,
168
+ assistant: bool = True,
169
+ content: str | None = None,
170
+ original_content: str | None = None,
171
+ references: list[ContentReference] | None = None,
172
+ debug_info: dict | None = None,
173
+ message_id: str | None = None,
174
+ set_completed_at: bool = False,
175
+ ) -> Dict[str, Any]:
176
+ completed_at_datetime = None
177
+
178
+ if message_id:
179
+ # Message ID specified. No need to guess
180
+ message_id = message_id
181
+ elif assistant:
182
+ # Assistant message ID
183
+ message_id = assistant_message_id
184
+ else:
185
+ message_id = user_message_id
186
+ if content is None:
187
+ content = user_message_text
188
+
189
+ if set_completed_at:
190
+ completed_at_datetime = _time_utils.get_datetime_now()
191
+
192
+ params = {
193
+ "user_id": user_id,
194
+ "company_id": company_id,
195
+ "id": message_id,
196
+ "chatId": chat_id,
197
+ "text": content,
198
+ "originalText": original_content,
199
+ "references": map_references(references) if references else [],
200
+ "debugInfo": debug_info,
201
+ "completedAt": completed_at_datetime,
202
+ }
203
+ return params
204
+
205
+
206
+ def create_message(
207
+ user_id: str,
208
+ company_id: str,
209
+ chat_id: str,
210
+ assistant_id: str,
211
+ role: ChatMessageRole,
212
+ content: str | None = None,
213
+ original_content: str | None = None,
214
+ references: list[ContentReference] | None = None,
215
+ debug_info: dict | None = None,
216
+ set_completed_at: bool | None = False,
217
+ ):
218
+ """
219
+ Creates a message in the chat session synchronously.
220
+
221
+ Args:
222
+ user_id (str): The user ID.
223
+ company_id (str): The company ID.
224
+ chat_id (str): The chat ID.
225
+ assistant_id (str): The assistant ID.
226
+ role (ChatMessageRole): The role of the message.
227
+ content (str, optional): The content for the message. Defaults to None.
228
+ original_content (str, optional): The original content for the message. Defaults to None.
229
+ references (list[ContentReference], optional): list of ContentReference objects. Defaults to None.
230
+ debug_info (dict[str, Any]], optional): Debug information. Defaults to None.
231
+ set_completed_at (Optional[bool]): Whether to set the completedAt field with the current date time. Defaults to False.
232
+
233
+ Returns:
234
+ ChatMessage: The created message.
235
+
236
+ Raises:
237
+ Exception: If the creation fails.
238
+ """
239
+ if original_content is None:
240
+ original_content = content
241
+
242
+ try:
243
+ params = _construct_message_create_params(
244
+ user_id=user_id,
245
+ company_id=company_id,
246
+ chat_id=chat_id,
247
+ assistant_id=assistant_id,
248
+ role=role,
249
+ content=content,
250
+ original_content=original_content,
251
+ references=references,
252
+ debug_info=debug_info,
253
+ set_completed_at=set_completed_at,
254
+ )
255
+
256
+ message = unique_sdk.Message.create(**params)
257
+ return ChatMessage(**message)
258
+ except Exception as e:
259
+ logger.error(f"Failed to create assistant message: {e}")
260
+ raise e
261
+
262
+
263
+ async def create_message_async(
264
+ user_id: str,
265
+ company_id: str,
266
+ chat_id: str,
267
+ assistant_id: str,
268
+ role: ChatMessageRole,
269
+ content: str | None = None,
270
+ original_content: str | None = None,
271
+ references: list[ContentReference] | None = None,
272
+ debug_info: dict | None = None,
273
+ set_completed_at: bool | None = False,
274
+ ):
275
+ """
276
+ Creates a message in the chat session synchronously.
277
+
278
+ Args:
279
+ user_id (str): The user ID.
280
+ company_id (str): The company ID.
281
+ chat_id (str): The chat ID.
282
+ assistant_id (str): The assistant ID.
283
+ role (ChatMessageRole): The role of the message.
284
+ content (str, optional): The content for the message. Defaults to None.
285
+ original_content (str, optional): The original content for the message. Defaults to None.
286
+ references (list[ContentReference], optional): list of ContentReference objects. Defaults to None.
287
+ debug_info (dict[str, Any]], optional): Debug information. Defaults to None.
288
+ set_completed_at (Optional[bool]): Whether to set the completedAt field with the current date time. Defaults to False.
289
+
290
+ Returns:
291
+ ChatMessage: The created message.
292
+
293
+ Raises:
294
+ Exception: If the creation fails.
295
+ """
296
+ if original_content is None:
297
+ original_content = content
298
+
299
+ try:
300
+ params = _construct_message_create_params(
301
+ user_id=user_id,
302
+ company_id=company_id,
303
+ chat_id=chat_id,
304
+ assistant_id=assistant_id,
305
+ role=role,
306
+ content=content,
307
+ original_content=original_content,
308
+ references=references,
309
+ debug_info=debug_info,
310
+ set_completed_at=set_completed_at,
311
+ )
312
+
313
+ message = await unique_sdk.Message.create_async(**params)
314
+ return ChatMessage(**message)
315
+ except Exception as e:
316
+ logger.error(f"Failed to create assistant message: {e}")
317
+ raise e
318
+
319
+
320
+ def _construct_message_create_params(
321
+ user_id: str,
322
+ company_id: str,
323
+ chat_id: str,
324
+ assistant_id: str,
325
+ role: ChatMessageRole,
326
+ content: str | None = None,
327
+ original_content: str | None = None,
328
+ references: list[ContentReference] | None = None,
329
+ debug_info: dict | None = None,
330
+ set_completed_at: bool | None = False,
331
+ ) -> Dict[str, Any]:
332
+ if original_content is None:
333
+ original_content = content
334
+
335
+ return {
336
+ "user_id": user_id,
337
+ "company_id": company_id,
338
+ "assistantId": assistant_id,
339
+ "role": role.value.upper(),
340
+ "chatId": chat_id,
341
+ "text": content,
342
+ "originalText": original_content,
343
+ "references": map_references(references) if references else [],
344
+ "debugInfo": debug_info,
345
+ "completedAt": _time_utils.get_datetime_now() if set_completed_at else None,
346
+ }
347
+
348
+
349
+ def get_selection_from_history(
350
+ full_history: list[ChatMessage],
351
+ max_tokens: int,
352
+ max_messages=DEFAULT_MAX_MESSAGES,
353
+ ) -> List[ChatMessage]:
354
+ messages = full_history[-max_messages:]
355
+ filtered_messages = [m for m in messages if m.content]
356
+ mapped_messages = []
357
+
358
+ for m in filtered_messages:
359
+ m.content = re.sub(r"<sup>\d+</sup>", "", m.content or "")
360
+ m.role = (
361
+ ChatMessageRole.ASSISTANT
362
+ if m.role == ChatMessageRole.ASSISTANT
363
+ else ChatMessageRole.USER
364
+ )
365
+ mapped_messages.append(m)
366
+
367
+ return pick_messages_in_reverse_for_token_window(
368
+ messages=mapped_messages,
369
+ limit=max_tokens,
370
+ )
371
+
372
+
373
+ def map_to_chat_messages(messages: list[dict]) -> List[ChatMessage]:
374
+ return [ChatMessage(**msg) for msg in messages]
375
+
376
+
377
+ def pick_messages_in_reverse_for_token_window(
378
+ messages: list[ChatMessage],
379
+ limit: int,
380
+ ) -> List[ChatMessage]:
381
+ if len(messages) < 1 or limit < 1:
382
+ return []
383
+
384
+ last_index = len(messages) - 1
385
+ token_count = count_tokens(messages[last_index].content or "")
386
+ while token_count > limit:
387
+ logger.debug(
388
+ f"Limit too low for the initial message. Last message TokenCount {token_count} available tokens {limit} - cutting message in half until it fits"
389
+ )
390
+ content = messages[last_index].content or ""
391
+ messages[last_index].content = content[: len(content) // 2] + "..."
392
+ token_count = count_tokens(messages[last_index].content or "")
393
+
394
+ while token_count <= limit and last_index > 0:
395
+ token_count = count_tokens(
396
+ "".join([msg.content or "" for msg in messages[:last_index]])
397
+ )
398
+ if token_count <= limit:
399
+ last_index -= 1
400
+
401
+ last_index = max(0, last_index)
402
+ return messages[last_index:]
403
+
404
+
405
+ def list_messages(
406
+ event_user_id, event_company_id, chat_id: str
407
+ ) -> ListObject[unique_sdk.Message]:
408
+ try:
409
+ messages = unique_sdk.Message.list(
410
+ user_id=event_user_id,
411
+ company_id=event_company_id,
412
+ chatId=chat_id,
413
+ )
414
+ return messages
415
+ except Exception as e:
416
+ logger.error(f"Failed to list chat history: {e}")
417
+ raise e
418
+
419
+
420
+ async def list_messages_async(
421
+ event_user_id: str, event_company_id: str, chat_id: str
422
+ ) -> ListObject[unique_sdk.Message]:
423
+ try:
424
+ messages = await unique_sdk.Message.list_async(
425
+ user_id=event_user_id,
426
+ company_id=event_company_id,
427
+ chatId=chat_id,
428
+ )
429
+ return messages
430
+ except Exception as e:
431
+ logger.error(f"Failed to list chat history: {e}")
432
+ raise e
433
+
434
+
435
+ def get_full_history(
436
+ event_user_id, event_company_id, event_payload_chat_id
437
+ ) -> List[ChatMessage]:
438
+ messages = list_messages(event_user_id, event_company_id, event_payload_chat_id)
439
+ messages = filter_valid_messages(messages)
440
+
441
+ return map_to_chat_messages(messages)
442
+
443
+
444
+ async def get_full_history_async(
445
+ event_user_id, event_company_id, event_payload_chat_id
446
+ ) -> List[ChatMessage]:
447
+ messages = await list_messages_async(
448
+ event_user_id, event_company_id, event_payload_chat_id
449
+ )
450
+ messages = filter_valid_messages(messages)
451
+
452
+ return map_to_chat_messages(messages)
453
+
454
+
455
+ def filter_valid_messages(
456
+ messages: ListObject[unique_sdk.Message],
457
+ ) -> List[Dict[str, Any]]:
458
+ SYSTEM_MESSAGE_PREFIX = "[SYSTEM] "
459
+
460
+ # Remove the last two messages
461
+ messages = messages["data"][:-2] # type: ignore
462
+ filtered_messages = []
463
+ for message in messages:
464
+ if message["text"] is None:
465
+ continue
466
+ elif SYSTEM_MESSAGE_PREFIX in message["text"]:
467
+ continue
468
+ else:
469
+ filtered_messages.append(message)
470
+
471
+ return filtered_messages
472
+
473
+
474
+ def create_message_assessment(
475
+ user_id: str,
476
+ company_id: str,
477
+ assistant_message_id: str,
478
+ status: ChatMessageAssessmentStatus,
479
+ type: ChatMessageAssessmentType,
480
+ title: str | None = None,
481
+ explanation: str | None = None,
482
+ label: ChatMessageAssessmentLabel | None = None,
483
+ is_visible: bool = True,
484
+ ) -> ChatMessageAssessment:
485
+ """
486
+ Creates a message assessment for an assistant message synchronously.
487
+
488
+ Args:
489
+ user_id (str): The user ID.
490
+ company_id (str): The company ID.
491
+ assistant_message_id (str): The ID of the assistant message to assess
492
+ status (ChatMessageAssessmentStatus): The status of the assessment (e.g. "DONE")
493
+ type (ChatMessageAssessmentType): The type of assessment (e.g. "HALLUCINATION")
494
+ title (str | None): The title of the assessment
495
+ explanation (str | None): Explanation of the assessment
496
+ label (ChatMessageAssessmentLabel | None): The assessment label (e.g. "NEGATIVE")
497
+ is_visible (bool): Whether the assessment is visible to users. Defaults to True.
498
+
499
+ Returns:
500
+ ChatMessageAssessment: The created message assessment
501
+
502
+ Raises:
503
+ Exception: If the creation fails
504
+ """
505
+ try:
506
+ assessment = unique_sdk.MessageAssessment.create(
507
+ user_id=user_id,
508
+ company_id=company_id,
509
+ messageId=assistant_message_id,
510
+ status=status.name,
511
+ explanation=explanation,
512
+ label=label.name if label else None,
513
+ title=title,
514
+ type=type.name,
515
+ isVisible=is_visible,
516
+ )
517
+ return ChatMessageAssessment(**assessment)
518
+ except Exception as e:
519
+ logger.error(f"Failed to create message assessment: {e}")
520
+ raise e
521
+
522
+
523
+ async def create_message_assessment_async(
524
+ user_id: str,
525
+ company_id: str,
526
+ assistant_message_id: str,
527
+ status: ChatMessageAssessmentStatus,
528
+ type: ChatMessageAssessmentType,
529
+ title: str | None = None,
530
+ explanation: str | None = None,
531
+ label: ChatMessageAssessmentLabel | None = None,
532
+ is_visible: bool = True,
533
+ ) -> ChatMessageAssessment:
534
+ """
535
+ Creates a message assessment for an assistant message asynchronously.
536
+
537
+ Args:
538
+ user_id (str): The user ID.
539
+ company_id (str): The company ID.
540
+ assistant_message_id (str): The ID of the assistant message to assess
541
+ status (ChatMessageAssessmentStatus): The status of the assessment (e.g. "DONE")
542
+ type (ChatMessageAssessmentType): The type of assessment (e.g. "HALLUCINATION")
543
+ title (str | None): The title of the assessment
544
+ explanation (str | None): Explanation of the assessment
545
+ label (ChatMessageAssessmentLabel | None): The assessment label (e.g. "NEGATIVE")
546
+ is_visible (bool): Whether the assessment is visible to users. Defaults to True.
547
+
548
+ Returns:
549
+ MessageAssessment: The created message assessment
550
+
551
+ Raises:
552
+ Exception: If the creation fails
553
+ """
554
+ try:
555
+ assessment = await unique_sdk.MessageAssessment.create_async(
556
+ user_id=user_id,
557
+ company_id=company_id,
558
+ messageId=assistant_message_id,
559
+ status=status.name,
560
+ explanation=explanation,
561
+ label=label.name if label else None,
562
+ title=title,
563
+ type=type.name,
564
+ isVisible=is_visible,
565
+ )
566
+ return ChatMessageAssessment(**assessment)
567
+ except Exception as e:
568
+ logger.error(f"Failed to create message assessment: {e}")
569
+ raise e
570
+
571
+
572
+ def modify_message_assessment(
573
+ user_id: str,
574
+ company_id: str,
575
+ assistant_message_id: str,
576
+ status: ChatMessageAssessmentStatus,
577
+ type: ChatMessageAssessmentType,
578
+ title: str | None = None,
579
+ explanation: str | None = None,
580
+ label: ChatMessageAssessmentLabel | None = None,
581
+ ) -> ChatMessageAssessment:
582
+ """
583
+ Modifies a message assessment for an assistant message synchronously.
584
+
585
+ Args:
586
+ user_id (str): The user ID.
587
+ company_id (str): The company ID.
588
+ assistant_message_id (str): The ID of the assistant message to assess
589
+ status (MessageAssessmentStatus): The status of the assessment (e.g. "DONE")
590
+ title (str | None): The title of the assessment
591
+ explanation (str | None): Explanation of the assessment
592
+ label (ChatMessageAssessmentLabel | None): The assessment label (e.g. "NEGATIVE")
593
+ type (ChatMessageAssessmentType): The type of assessment (e.g. "HALLUCINATION")
594
+
595
+ Returns:
596
+ dict: The modified message assessment
597
+
598
+ Raises:
599
+ Exception: If the modification fails
600
+ """
601
+ try:
602
+ assessment = unique_sdk.MessageAssessment.modify(
603
+ user_id=user_id,
604
+ company_id=company_id,
605
+ messageId=assistant_message_id,
606
+ status=status.name,
607
+ title=title,
608
+ explanation=explanation,
609
+ label=label.name if label else None,
610
+ type=type.name,
611
+ )
612
+ return ChatMessageAssessment(**assessment)
613
+ except Exception as e:
614
+ logger.error(f"Failed to modify message assessment: {e}")
615
+ raise e
616
+
617
+
618
+ async def modify_message_assessment_async(
619
+ user_id: str,
620
+ company_id: str,
621
+ assistant_message_id: str,
622
+ type: ChatMessageAssessmentType,
623
+ title: str | None = None,
624
+ status: ChatMessageAssessmentStatus | None = None,
625
+ explanation: str | None = None,
626
+ label: ChatMessageAssessmentLabel | None = None,
627
+ ) -> ChatMessageAssessment:
628
+ """
629
+ Modifies a message assessment for an assistant message asynchronously.
630
+
631
+ Args:
632
+ user_id (str): The user ID.
633
+ company_id (str): The company ID.
634
+ assistant_message_id (str): The ID of the assistant message to assess
635
+ type (MessageAssessmentType): The type of assessment (e.g. "HALLUCINATION")
636
+ title (str | None): The title of the assessment
637
+ status (MessageAssessmentStatus): The status of the assessment (e.g. "DONE")
638
+ explanation (str | None): Explanation of the assessment
639
+ label (MessageAssessmentLabel | None): The assessment label (e.g. "NEGATIVE")
640
+
641
+ Returns:
642
+ MessageAssessment: The modified message assessment
643
+
644
+ Raises:
645
+ Exception: If the modification fails
646
+ """
647
+ try:
648
+ assessment = await unique_sdk.MessageAssessment.modify_async(
649
+ user_id=user_id,
650
+ company_id=company_id,
651
+ messageId=assistant_message_id,
652
+ status=status.name if status else None,
653
+ title=title,
654
+ explanation=explanation,
655
+ label=label.name if label else None,
656
+ type=type.name,
657
+ )
658
+ return ChatMessageAssessment(**assessment)
659
+ except Exception as e:
660
+ logger.error(f"Failed to modify message assessment: {e}")
661
+ raise e
@@ -69,34 +69,34 @@ class ChatMessage(BaseModel):
69
69
  return self
70
70
 
71
71
 
72
- class MessageAssessmentStatus(StrEnum):
72
+ class ChatMessageAssessmentStatus(StrEnum):
73
73
  PENDING = "PENDING"
74
74
  DONE = "DONE"
75
75
  ERROR = "ERROR"
76
76
 
77
77
 
78
- class MessageAssessmentLabel(StrEnum):
79
- POSITIVE = "POSITIVE"
80
- NEGATIVE = "NEGATIVE"
81
- VERIFIED = "VERIFIED"
82
- UNVERIFIED = "UNVERIFIED"
78
+ class ChatMessageAssessmentLabel(StrEnum):
79
+ RED = "RED"
80
+ YELLOW = "YELLOW"
81
+ GREEN = "GREEN"
83
82
 
84
83
 
85
- class MessageAssessmentType(StrEnum):
84
+ class ChatMessageAssessmentType(StrEnum):
86
85
  HALLUCINATION = "HALLUCINATION"
87
86
  COMPLIANCE = "COMPLIANCE"
88
87
 
89
88
 
90
- class MessageAssessment(BaseModel):
89
+ class ChatMessageAssessment(BaseModel):
91
90
  model_config = model_config
92
91
 
93
92
  id: str
94
93
  object: str
95
94
  message_id: str
96
- status: MessageAssessmentStatus
97
- type: MessageAssessmentType
95
+ status: ChatMessageAssessmentStatus
96
+ type: ChatMessageAssessmentType
97
+ title: str | None = None
98
98
  explanation: str | None = None
99
- label: MessageAssessmentLabel | None = None
99
+ label: ChatMessageAssessmentLabel | None = None
100
100
  is_visible: bool
101
101
  created_at: datetime | None = None
102
102
  updated_at: datetime | None = None