unique_toolkit 1.8.1__py3-none-any.whl → 1.23.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.

Potentially problematic release.


This version of unique_toolkit might be problematic. Click here for more details.

Files changed (105) hide show
  1. unique_toolkit/__init__.py +20 -0
  2. unique_toolkit/_common/api_calling/human_verification_manager.py +121 -28
  3. unique_toolkit/_common/chunk_relevancy_sorter/config.py +3 -3
  4. unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +2 -5
  5. unique_toolkit/_common/default_language_model.py +9 -3
  6. unique_toolkit/_common/docx_generator/__init__.py +7 -0
  7. unique_toolkit/_common/docx_generator/config.py +12 -0
  8. unique_toolkit/_common/docx_generator/schemas.py +80 -0
  9. unique_toolkit/_common/docx_generator/service.py +252 -0
  10. unique_toolkit/_common/docx_generator/template/Doc Template.docx +0 -0
  11. unique_toolkit/_common/endpoint_builder.py +138 -117
  12. unique_toolkit/_common/endpoint_requestor.py +240 -14
  13. unique_toolkit/_common/exception.py +20 -0
  14. unique_toolkit/_common/feature_flags/schema.py +1 -5
  15. unique_toolkit/_common/referencing.py +53 -0
  16. unique_toolkit/_common/string_utilities.py +52 -1
  17. unique_toolkit/_common/tests/test_referencing.py +521 -0
  18. unique_toolkit/_common/tests/test_string_utilities.py +506 -0
  19. unique_toolkit/_common/utils/files.py +43 -0
  20. unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +16 -6
  21. unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +278 -0
  22. unique_toolkit/agentic/evaluation/config.py +3 -2
  23. unique_toolkit/agentic/evaluation/context_relevancy/service.py +2 -2
  24. unique_toolkit/agentic/evaluation/evaluation_manager.py +9 -5
  25. unique_toolkit/agentic/evaluation/hallucination/constants.py +1 -1
  26. unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +26 -3
  27. unique_toolkit/agentic/history_manager/history_manager.py +14 -11
  28. unique_toolkit/agentic/history_manager/loop_token_reducer.py +3 -4
  29. unique_toolkit/agentic/history_manager/utils.py +10 -87
  30. unique_toolkit/agentic/postprocessor/postprocessor_manager.py +107 -16
  31. unique_toolkit/agentic/reference_manager/reference_manager.py +1 -1
  32. unique_toolkit/agentic/responses_api/__init__.py +19 -0
  33. unique_toolkit/agentic/responses_api/postprocessors/code_display.py +63 -0
  34. unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +145 -0
  35. unique_toolkit/agentic/responses_api/stream_handler.py +15 -0
  36. unique_toolkit/agentic/tools/a2a/__init__.py +18 -2
  37. unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +2 -0
  38. unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +3 -3
  39. unique_toolkit/agentic/tools/a2a/evaluation/config.py +1 -1
  40. unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +143 -91
  41. unique_toolkit/agentic/tools/a2a/manager.py +7 -1
  42. unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +11 -3
  43. unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py +185 -0
  44. unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py +73 -0
  45. unique_toolkit/agentic/tools/a2a/postprocessing/config.py +21 -0
  46. unique_toolkit/agentic/tools/a2a/postprocessing/display.py +180 -0
  47. unique_toolkit/agentic/tools/a2a/postprocessing/references.py +101 -0
  48. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py +1335 -0
  49. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_ref_utils.py +603 -0
  50. unique_toolkit/agentic/tools/a2a/prompts.py +46 -0
  51. unique_toolkit/agentic/tools/a2a/response_watcher/__init__.py +6 -0
  52. unique_toolkit/agentic/tools/a2a/response_watcher/service.py +91 -0
  53. unique_toolkit/agentic/tools/a2a/tool/config.py +15 -5
  54. unique_toolkit/agentic/tools/a2a/tool/service.py +69 -36
  55. unique_toolkit/agentic/tools/config.py +16 -2
  56. unique_toolkit/agentic/tools/factory.py +4 -0
  57. unique_toolkit/agentic/tools/mcp/tool_wrapper.py +7 -35
  58. unique_toolkit/agentic/tools/openai_builtin/__init__.py +11 -0
  59. unique_toolkit/agentic/tools/openai_builtin/base.py +30 -0
  60. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +8 -0
  61. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +57 -0
  62. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +230 -0
  63. unique_toolkit/agentic/tools/openai_builtin/manager.py +62 -0
  64. unique_toolkit/agentic/tools/test/test_mcp_manager.py +95 -7
  65. unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +240 -0
  66. unique_toolkit/agentic/tools/tool.py +0 -11
  67. unique_toolkit/agentic/tools/tool_manager.py +337 -122
  68. unique_toolkit/agentic/tools/tool_progress_reporter.py +81 -15
  69. unique_toolkit/agentic/tools/utils/__init__.py +18 -0
  70. unique_toolkit/agentic/tools/utils/execution/execution.py +8 -4
  71. unique_toolkit/agentic/tools/utils/source_handling/schema.py +1 -1
  72. unique_toolkit/chat/__init__.py +8 -1
  73. unique_toolkit/chat/deprecated/service.py +232 -0
  74. unique_toolkit/chat/functions.py +54 -40
  75. unique_toolkit/chat/rendering.py +34 -0
  76. unique_toolkit/chat/responses_api.py +461 -0
  77. unique_toolkit/chat/schemas.py +1 -1
  78. unique_toolkit/chat/service.py +96 -1569
  79. unique_toolkit/content/functions.py +116 -1
  80. unique_toolkit/content/schemas.py +59 -0
  81. unique_toolkit/content/service.py +5 -37
  82. unique_toolkit/content/smart_rules.py +301 -0
  83. unique_toolkit/framework_utilities/langchain/client.py +27 -3
  84. unique_toolkit/framework_utilities/openai/client.py +12 -1
  85. unique_toolkit/framework_utilities/openai/message_builder.py +85 -1
  86. unique_toolkit/language_model/default_language_model.py +3 -0
  87. unique_toolkit/language_model/functions.py +25 -9
  88. unique_toolkit/language_model/infos.py +72 -4
  89. unique_toolkit/language_model/schemas.py +246 -40
  90. unique_toolkit/protocols/support.py +91 -9
  91. unique_toolkit/services/__init__.py +7 -0
  92. unique_toolkit/services/chat_service.py +1630 -0
  93. unique_toolkit/services/knowledge_base.py +861 -0
  94. unique_toolkit/smart_rules/compile.py +56 -301
  95. unique_toolkit/test_utilities/events.py +197 -0
  96. {unique_toolkit-1.8.1.dist-info → unique_toolkit-1.23.0.dist-info}/METADATA +173 -3
  97. {unique_toolkit-1.8.1.dist-info → unique_toolkit-1.23.0.dist-info}/RECORD +99 -67
  98. unique_toolkit/agentic/tools/a2a/postprocessing/_display.py +0 -122
  99. unique_toolkit/agentic/tools/a2a/postprocessing/_utils.py +0 -19
  100. unique_toolkit/agentic/tools/a2a/postprocessing/postprocessor.py +0 -230
  101. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_consolidate_references.py +0 -665
  102. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +0 -391
  103. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_postprocessor_reference_functions.py +0 -256
  104. {unique_toolkit-1.8.1.dist-info → unique_toolkit-1.23.0.dist-info}/LICENSE +0 -0
  105. {unique_toolkit-1.8.1.dist-info → unique_toolkit-1.23.0.dist-info}/WHEEL +0 -0
@@ -1,230 +0,0 @@
1
- import logging
2
- from typing import TypedDict, override
3
-
4
- import unique_sdk
5
-
6
- from unique_toolkit.agentic.postprocessor.postprocessor_manager import Postprocessor
7
- from unique_toolkit.agentic.tools.a2a.postprocessing._display import (
8
- _build_sub_agent_answer_display,
9
- _remove_sub_agent_answer_from_text,
10
- )
11
- from unique_toolkit.agentic.tools.a2a.postprocessing._utils import (
12
- _replace_references_in_text,
13
- )
14
- from unique_toolkit.agentic.tools.a2a.postprocessing.config import (
15
- SubAgentDisplayConfig,
16
- SubAgentResponseDisplayMode,
17
- )
18
- from unique_toolkit.agentic.tools.a2a.tool import SubAgentTool
19
- from unique_toolkit.content.schemas import ContentReference
20
- from unique_toolkit.language_model.schemas import LanguageModelStreamResponse
21
-
22
- logger = logging.getLogger(__name__)
23
-
24
- SpaceMessage = unique_sdk.Space.Message
25
-
26
-
27
- class _SubAgentMessageInfo(TypedDict):
28
- text: str
29
- references: list[unique_sdk.Space.Reference]
30
-
31
-
32
- class _SubAgentToolInfo(TypedDict):
33
- display_name: str
34
- display_config: SubAgentDisplayConfig
35
- responses: dict[int, _SubAgentMessageInfo]
36
-
37
-
38
- class SubAgentResponsesPostprocessor(Postprocessor):
39
- def __init__(
40
- self,
41
- user_id: str,
42
- company_id: str,
43
- main_agent_chat_id: str,
44
- ) -> None:
45
- super().__init__(name=self.__class__.__name__)
46
-
47
- self._user_id = user_id
48
- self._company_id = company_id
49
- self._main_agent_chat_id = main_agent_chat_id
50
-
51
- self._assistant_id_to_tool_info: dict[str, _SubAgentToolInfo] = {}
52
- self._main_agent_message: SpaceMessage | None = None
53
-
54
- @override
55
- async def run(self, loop_response: LanguageModelStreamResponse) -> None:
56
- self._main_agent_message = await unique_sdk.Space.get_latest_message_async(
57
- user_id=self._user_id,
58
- company_id=self._company_id,
59
- chat_id=self._main_agent_chat_id,
60
- )
61
-
62
- @override
63
- def apply_postprocessing_to_response(
64
- self, loop_response: LanguageModelStreamResponse
65
- ) -> bool:
66
- logger.info("Prepending sub agent responses to the main agent response")
67
-
68
- if len(self._assistant_id_to_tool_info) == 0 or all(
69
- len(tool_info["responses"]) == 0
70
- for tool_info in self._assistant_id_to_tool_info.values()
71
- ):
72
- logger.info("No sub agent responses to prepend")
73
- return False
74
-
75
- if self._main_agent_message is None:
76
- raise ValueError(
77
- "Main agent message is not set, the `run` method must be called first"
78
- )
79
-
80
- existing_refs = {
81
- ref.source_id: ref.sequence_number
82
- for ref in loop_response.message.references
83
- }
84
-
85
- _consolidate_references_in_place(
86
- list(self._assistant_id_to_tool_info.values()), existing_refs
87
- )
88
-
89
- answers = []
90
- for assistant_id in self._assistant_id_to_tool_info.keys():
91
- messages = self._assistant_id_to_tool_info[assistant_id]["responses"]
92
-
93
- for sequence_number in sorted(messages):
94
- message = messages[sequence_number]
95
- tool_info = self._assistant_id_to_tool_info[assistant_id]
96
-
97
- display_mode = tool_info["display_config"].mode
98
- display_name = tool_info["display_name"]
99
- if len(messages) > 1:
100
- display_name += f" {sequence_number}"
101
-
102
- answers.append(
103
- _build_sub_agent_answer_display(
104
- display_name=display_name,
105
- assistant_id=assistant_id,
106
- display_mode=display_mode,
107
- answer=message["text"],
108
- )
109
- )
110
-
111
- loop_response.message.references.extend(
112
- ContentReference(
113
- message_id=self._main_agent_message["id"],
114
- source_id=ref["sourceId"],
115
- url=ref["url"] or "",
116
- source=ref["source"],
117
- name=ref["name"],
118
- sequence_number=ref["sequenceNumber"],
119
- )
120
- for ref in message["references"]
121
- )
122
-
123
- loop_response.message.text = "\n".join(answers) + loop_response.message.text
124
-
125
- return True
126
-
127
- @override
128
- async def remove_from_text(self, text) -> str:
129
- for assistant_id, tool_info in self._assistant_id_to_tool_info.items():
130
- display_config = tool_info["display_config"]
131
- if display_config.remove_from_history:
132
- text = _remove_sub_agent_answer_from_text(
133
- display_mode=display_config.mode,
134
- text=text,
135
- assistant_id=assistant_id,
136
- )
137
- return text
138
-
139
- def register_sub_agent_tool(
140
- self, tool: SubAgentTool, display_config: SubAgentDisplayConfig
141
- ) -> None:
142
- if display_config.mode == SubAgentResponseDisplayMode.HIDDEN:
143
- logger.info(
144
- "Sub agent tool %s has display mode `hidden`, responses will be ignored.",
145
- tool.config.assistant_id,
146
- )
147
- return
148
-
149
- if tool.config.assistant_id not in self._assistant_id_to_tool_info:
150
- tool.subscribe(self)
151
- self._assistant_id_to_tool_info[tool.config.assistant_id] = (
152
- _SubAgentToolInfo(
153
- display_config=display_config,
154
- display_name=tool.display_name(),
155
- responses={},
156
- )
157
- )
158
-
159
- def notify_sub_agent_response(
160
- self, response: SpaceMessage, sub_agent_assistant_id: str, sequence_number: int
161
- ) -> None:
162
- if sub_agent_assistant_id not in self._assistant_id_to_tool_info:
163
- logger.warning(
164
- "Unknown assistant id %s received, message will be ignored.",
165
- sub_agent_assistant_id,
166
- )
167
- return
168
-
169
- if response["text"] is None:
170
- logger.warning(
171
- "Sub agent response %s has no text, message will be ignored.",
172
- sequence_number,
173
- )
174
- return
175
-
176
- self._assistant_id_to_tool_info[sub_agent_assistant_id]["responses"][
177
- sequence_number
178
- ] = {
179
- "text": response["text"],
180
- "references": [
181
- {
182
- "name": ref["name"],
183
- "url": ref["url"],
184
- "sequenceNumber": ref["sequenceNumber"],
185
- "originalIndex": [],
186
- "sourceId": ref["sourceId"],
187
- "source": ref["source"],
188
- }
189
- for ref in response["references"] or []
190
- ],
191
- }
192
-
193
-
194
- def _consolidate_references_in_place(
195
- messages: list[_SubAgentToolInfo], existing_refs: dict[str, int]
196
- ) -> None:
197
- start_index = max(existing_refs.values(), default=0) + 1
198
-
199
- for assistant_tool_info in messages:
200
- assistant_messages = assistant_tool_info["responses"]
201
-
202
- for sequence_number in sorted(assistant_messages):
203
- message = assistant_messages[sequence_number]
204
-
205
- references = message["references"]
206
- if len(references) == 0:
207
- logger.debug(
208
- "Message from assistant %s with sequence number %s does not contain any references",
209
- assistant_tool_info["display_name"],
210
- sequence_number,
211
- )
212
- continue
213
-
214
- references = list(sorted(references, key=lambda ref: ref["sequenceNumber"]))
215
- ref_map = {}
216
- message_new_refs = []
217
-
218
- for reference in references:
219
- source_id = reference["sourceId"]
220
- if source_id not in existing_refs:
221
- message_new_refs.append(reference)
222
- existing_refs[source_id] = start_index
223
- start_index += 1
224
-
225
- reference_num = existing_refs[source_id]
226
- ref_map[reference["sequenceNumber"]] = reference_num
227
- reference["sequenceNumber"] = reference_num
228
-
229
- message["text"] = _replace_references_in_text(message["text"], ref_map)
230
- message["references"] = message_new_refs