unique_toolkit 0.7.7__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 (166) hide show
  1. unique_toolkit/__init__.py +28 -1
  2. unique_toolkit/_common/api_calling/human_verification_manager.py +343 -0
  3. unique_toolkit/_common/base_model_type_attribute.py +303 -0
  4. unique_toolkit/_common/chunk_relevancy_sorter/config.py +49 -0
  5. unique_toolkit/_common/chunk_relevancy_sorter/exception.py +5 -0
  6. unique_toolkit/_common/chunk_relevancy_sorter/schemas.py +46 -0
  7. unique_toolkit/_common/chunk_relevancy_sorter/service.py +374 -0
  8. unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +275 -0
  9. unique_toolkit/_common/default_language_model.py +12 -0
  10. unique_toolkit/_common/docx_generator/__init__.py +7 -0
  11. unique_toolkit/_common/docx_generator/config.py +12 -0
  12. unique_toolkit/_common/docx_generator/schemas.py +80 -0
  13. unique_toolkit/_common/docx_generator/service.py +252 -0
  14. unique_toolkit/_common/docx_generator/template/Doc Template.docx +0 -0
  15. unique_toolkit/_common/endpoint_builder.py +305 -0
  16. unique_toolkit/_common/endpoint_requestor.py +430 -0
  17. unique_toolkit/_common/exception.py +24 -0
  18. unique_toolkit/_common/feature_flags/schema.py +9 -0
  19. unique_toolkit/_common/pydantic/rjsf_tags.py +936 -0
  20. unique_toolkit/_common/pydantic_helpers.py +154 -0
  21. unique_toolkit/_common/referencing.py +53 -0
  22. unique_toolkit/_common/string_utilities.py +140 -0
  23. unique_toolkit/_common/tests/test_referencing.py +521 -0
  24. unique_toolkit/_common/tests/test_string_utilities.py +506 -0
  25. unique_toolkit/_common/token/image_token_counting.py +67 -0
  26. unique_toolkit/_common/token/token_counting.py +204 -0
  27. unique_toolkit/_common/utils/__init__.py +1 -0
  28. unique_toolkit/_common/utils/files.py +43 -0
  29. unique_toolkit/_common/utils/structured_output/__init__.py +1 -0
  30. unique_toolkit/_common/utils/structured_output/schema.py +5 -0
  31. unique_toolkit/_common/utils/write_configuration.py +51 -0
  32. unique_toolkit/_common/validators.py +101 -4
  33. unique_toolkit/agentic/__init__.py +1 -0
  34. unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +28 -0
  35. unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +278 -0
  36. unique_toolkit/agentic/evaluation/config.py +36 -0
  37. unique_toolkit/{evaluators → agentic/evaluation}/context_relevancy/prompts.py +25 -0
  38. unique_toolkit/agentic/evaluation/context_relevancy/schema.py +80 -0
  39. unique_toolkit/agentic/evaluation/context_relevancy/service.py +273 -0
  40. unique_toolkit/agentic/evaluation/evaluation_manager.py +218 -0
  41. unique_toolkit/agentic/evaluation/hallucination/constants.py +61 -0
  42. unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +111 -0
  43. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/prompts.py +1 -1
  44. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/service.py +16 -15
  45. unique_toolkit/{evaluators → agentic/evaluation}/hallucination/utils.py +30 -20
  46. unique_toolkit/{evaluators → agentic/evaluation}/output_parser.py +20 -2
  47. unique_toolkit/{evaluators → agentic/evaluation}/schemas.py +27 -7
  48. unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +253 -0
  49. unique_toolkit/agentic/evaluation/tests/test_output_parser.py +87 -0
  50. unique_toolkit/agentic/history_manager/history_construction_with_contents.py +297 -0
  51. unique_toolkit/agentic/history_manager/history_manager.py +242 -0
  52. unique_toolkit/agentic/history_manager/loop_token_reducer.py +484 -0
  53. unique_toolkit/agentic/history_manager/utils.py +96 -0
  54. unique_toolkit/agentic/postprocessor/postprocessor_manager.py +212 -0
  55. unique_toolkit/agentic/reference_manager/reference_manager.py +103 -0
  56. unique_toolkit/agentic/responses_api/__init__.py +19 -0
  57. unique_toolkit/agentic/responses_api/postprocessors/code_display.py +63 -0
  58. unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +145 -0
  59. unique_toolkit/agentic/responses_api/stream_handler.py +15 -0
  60. unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +141 -0
  61. unique_toolkit/agentic/thinking_manager/thinking_manager.py +103 -0
  62. unique_toolkit/agentic/tools/__init__.py +1 -0
  63. unique_toolkit/agentic/tools/a2a/__init__.py +36 -0
  64. unique_toolkit/agentic/tools/a2a/config.py +17 -0
  65. unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +15 -0
  66. unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +66 -0
  67. unique_toolkit/agentic/tools/a2a/evaluation/config.py +55 -0
  68. unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +260 -0
  69. unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +9 -0
  70. unique_toolkit/agentic/tools/a2a/manager.py +55 -0
  71. unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +21 -0
  72. unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py +185 -0
  73. unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py +73 -0
  74. unique_toolkit/agentic/tools/a2a/postprocessing/config.py +45 -0
  75. unique_toolkit/agentic/tools/a2a/postprocessing/display.py +180 -0
  76. unique_toolkit/agentic/tools/a2a/postprocessing/references.py +101 -0
  77. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py +1335 -0
  78. unique_toolkit/agentic/tools/a2a/postprocessing/test/test_ref_utils.py +603 -0
  79. unique_toolkit/agentic/tools/a2a/prompts.py +46 -0
  80. unique_toolkit/agentic/tools/a2a/response_watcher/__init__.py +6 -0
  81. unique_toolkit/agentic/tools/a2a/response_watcher/service.py +91 -0
  82. unique_toolkit/agentic/tools/a2a/tool/__init__.py +4 -0
  83. unique_toolkit/agentic/tools/a2a/tool/_memory.py +26 -0
  84. unique_toolkit/agentic/tools/a2a/tool/_schema.py +9 -0
  85. unique_toolkit/agentic/tools/a2a/tool/config.py +73 -0
  86. unique_toolkit/agentic/tools/a2a/tool/service.py +306 -0
  87. unique_toolkit/agentic/tools/agent_chunks_hanlder.py +65 -0
  88. unique_toolkit/agentic/tools/config.py +167 -0
  89. unique_toolkit/agentic/tools/factory.py +44 -0
  90. unique_toolkit/agentic/tools/mcp/__init__.py +4 -0
  91. unique_toolkit/agentic/tools/mcp/manager.py +71 -0
  92. unique_toolkit/agentic/tools/mcp/models.py +28 -0
  93. unique_toolkit/agentic/tools/mcp/tool_wrapper.py +234 -0
  94. unique_toolkit/agentic/tools/openai_builtin/__init__.py +11 -0
  95. unique_toolkit/agentic/tools/openai_builtin/base.py +30 -0
  96. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +8 -0
  97. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +57 -0
  98. unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +230 -0
  99. unique_toolkit/agentic/tools/openai_builtin/manager.py +62 -0
  100. unique_toolkit/agentic/tools/schemas.py +141 -0
  101. unique_toolkit/agentic/tools/test/test_mcp_manager.py +536 -0
  102. unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +445 -0
  103. unique_toolkit/agentic/tools/tool.py +183 -0
  104. unique_toolkit/agentic/tools/tool_manager.py +523 -0
  105. unique_toolkit/agentic/tools/tool_progress_reporter.py +285 -0
  106. unique_toolkit/agentic/tools/utils/__init__.py +19 -0
  107. unique_toolkit/agentic/tools/utils/execution/__init__.py +1 -0
  108. unique_toolkit/agentic/tools/utils/execution/execution.py +286 -0
  109. unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
  110. unique_toolkit/agentic/tools/utils/source_handling/schema.py +21 -0
  111. unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +207 -0
  112. unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +216 -0
  113. unique_toolkit/app/__init__.py +6 -0
  114. unique_toolkit/app/dev_util.py +180 -0
  115. unique_toolkit/app/init_sdk.py +32 -1
  116. unique_toolkit/app/schemas.py +198 -31
  117. unique_toolkit/app/unique_settings.py +367 -0
  118. unique_toolkit/chat/__init__.py +8 -1
  119. unique_toolkit/chat/deprecated/service.py +232 -0
  120. unique_toolkit/chat/functions.py +642 -77
  121. unique_toolkit/chat/rendering.py +34 -0
  122. unique_toolkit/chat/responses_api.py +461 -0
  123. unique_toolkit/chat/schemas.py +133 -2
  124. unique_toolkit/chat/service.py +115 -767
  125. unique_toolkit/content/functions.py +153 -4
  126. unique_toolkit/content/schemas.py +122 -15
  127. unique_toolkit/content/service.py +278 -44
  128. unique_toolkit/content/smart_rules.py +301 -0
  129. unique_toolkit/content/utils.py +8 -3
  130. unique_toolkit/embedding/service.py +102 -11
  131. unique_toolkit/framework_utilities/__init__.py +1 -0
  132. unique_toolkit/framework_utilities/langchain/client.py +71 -0
  133. unique_toolkit/framework_utilities/langchain/history.py +19 -0
  134. unique_toolkit/framework_utilities/openai/__init__.py +6 -0
  135. unique_toolkit/framework_utilities/openai/client.py +83 -0
  136. unique_toolkit/framework_utilities/openai/message_builder.py +229 -0
  137. unique_toolkit/framework_utilities/utils.py +23 -0
  138. unique_toolkit/language_model/__init__.py +3 -0
  139. unique_toolkit/language_model/builder.py +27 -11
  140. unique_toolkit/language_model/default_language_model.py +3 -0
  141. unique_toolkit/language_model/functions.py +327 -43
  142. unique_toolkit/language_model/infos.py +992 -50
  143. unique_toolkit/language_model/reference.py +242 -0
  144. unique_toolkit/language_model/schemas.py +475 -48
  145. unique_toolkit/language_model/service.py +228 -27
  146. unique_toolkit/protocols/support.py +145 -0
  147. unique_toolkit/services/__init__.py +7 -0
  148. unique_toolkit/services/chat_service.py +1630 -0
  149. unique_toolkit/services/knowledge_base.py +861 -0
  150. unique_toolkit/short_term_memory/service.py +178 -41
  151. unique_toolkit/smart_rules/__init__.py +0 -0
  152. unique_toolkit/smart_rules/compile.py +56 -0
  153. unique_toolkit/test_utilities/events.py +197 -0
  154. {unique_toolkit-0.7.7.dist-info → unique_toolkit-1.23.0.dist-info}/METADATA +606 -7
  155. unique_toolkit-1.23.0.dist-info/RECORD +182 -0
  156. unique_toolkit/evaluators/__init__.py +0 -1
  157. unique_toolkit/evaluators/config.py +0 -35
  158. unique_toolkit/evaluators/constants.py +0 -1
  159. unique_toolkit/evaluators/context_relevancy/constants.py +0 -32
  160. unique_toolkit/evaluators/context_relevancy/service.py +0 -53
  161. unique_toolkit/evaluators/context_relevancy/utils.py +0 -142
  162. unique_toolkit/evaluators/hallucination/constants.py +0 -41
  163. unique_toolkit-0.7.7.dist-info/RECORD +0 -64
  164. /unique_toolkit/{evaluators → agentic/evaluation}/exception.py +0 -0
  165. {unique_toolkit-0.7.7.dist-info → unique_toolkit-1.23.0.dist-info}/LICENSE +0 -0
  166. {unique_toolkit-0.7.7.dist-info → unique_toolkit-1.23.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,180 @@
1
+ import asyncio
2
+ import logging
3
+ from collections import defaultdict
4
+ from typing import NamedTuple, override
5
+
6
+ import unique_sdk
7
+ from pydantic import BaseModel, Field
8
+
9
+ from unique_toolkit._common.pydantic_helpers import get_configuration_dict
10
+ from unique_toolkit.agentic.postprocessor.postprocessor_manager import Postprocessor
11
+ from unique_toolkit.agentic.tools.a2a.postprocessing._display_utils import (
12
+ get_sub_agent_answer_display,
13
+ remove_sub_agent_answer_from_text,
14
+ )
15
+ from unique_toolkit.agentic.tools.a2a.postprocessing._ref_utils import (
16
+ add_content_refs_and_replace_in_text,
17
+ )
18
+ from unique_toolkit.agentic.tools.a2a.postprocessing.config import (
19
+ SubAgentDisplayConfig,
20
+ SubAgentResponseDisplayMode,
21
+ )
22
+ from unique_toolkit.agentic.tools.a2a.response_watcher import (
23
+ SubAgentResponse,
24
+ SubAgentResponseWatcher,
25
+ )
26
+ from unique_toolkit.content import ContentReference
27
+ from unique_toolkit.language_model.schemas import LanguageModelStreamResponse
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+ SpaceMessage = unique_sdk.Space.Message
32
+
33
+
34
+ class SubAgentDisplaySpec(NamedTuple):
35
+ assistant_id: str
36
+ display_name: str
37
+ display_config: SubAgentDisplayConfig
38
+
39
+
40
+ class SubAgentResponsesPostprocessorConfig(BaseModel):
41
+ model_config = get_configuration_dict()
42
+
43
+ sleep_time_before_update: float = Field(
44
+ default=1, description="Time to sleep before updating the main agent message."
45
+ )
46
+
47
+
48
+ class SubAgentResponsesDisplayPostprocessor(Postprocessor):
49
+ def __init__(
50
+ self,
51
+ config: SubAgentResponsesPostprocessorConfig,
52
+ response_watcher: SubAgentResponseWatcher,
53
+ display_specs: list[SubAgentDisplaySpec],
54
+ ) -> None:
55
+ super().__init__(name=self.__class__.__name__)
56
+
57
+ self._config = config
58
+ self._response_watcher = response_watcher
59
+ self._display_specs: dict[str, SubAgentDisplaySpec] = {
60
+ display_spec.assistant_id: display_spec
61
+ for display_spec in display_specs
62
+ if display_spec.display_config.mode != SubAgentResponseDisplayMode.HIDDEN
63
+ }
64
+
65
+ @override
66
+ async def run(self, loop_response: LanguageModelStreamResponse) -> None:
67
+ await asyncio.sleep(
68
+ self._config.sleep_time_before_update
69
+ ) # Frontend rendering issues
70
+
71
+ def _get_displayed_sub_agent_responses(
72
+ self,
73
+ ) -> dict[str, list[SubAgentResponse]]:
74
+ responses = defaultdict(list)
75
+ all_responses = self._response_watcher.get_all_responses()
76
+ for response in all_responses:
77
+ assistant_id = response.assistant_id
78
+ if assistant_id in self._display_specs:
79
+ responses[assistant_id].append(response)
80
+ return responses
81
+
82
+ @override
83
+ def apply_postprocessing_to_response(
84
+ self, loop_response: LanguageModelStreamResponse
85
+ ) -> bool:
86
+ displayed_sub_agent_responses = self._get_displayed_sub_agent_responses()
87
+
88
+ if len(displayed_sub_agent_responses) == 0:
89
+ logger.info("No sub agent responses to prepend")
90
+ return False
91
+
92
+ logger.info("Prepending sub agent responses to the main agent response")
93
+
94
+ answers_displayed_before = []
95
+ answers_displayed_after = []
96
+
97
+ for assistant_id, responses in displayed_sub_agent_responses.items():
98
+ for response in responses:
99
+ message = response.message
100
+ tool_info = self._display_specs[assistant_id]
101
+
102
+ _add_response_references_to_message_in_place(
103
+ loop_response=loop_response, response=message
104
+ )
105
+
106
+ display_name = tool_info.display_name
107
+ if len(responses) > 1:
108
+ display_name += f" {response.sequence_number}"
109
+
110
+ if message["text"] is None:
111
+ logger.warning(
112
+ "Sub agent response for assistant %s with sequence number %s does not contain any text",
113
+ assistant_id,
114
+ response.sequence_number,
115
+ )
116
+
117
+ answer = get_sub_agent_answer_display(
118
+ display_name=display_name,
119
+ display_config=tool_info.display_config,
120
+ answer=message["text"] or "",
121
+ assistant_id=assistant_id,
122
+ )
123
+
124
+ if tool_info.display_config.position == "before":
125
+ answers_displayed_before.append(answer)
126
+ else:
127
+ answers_displayed_after.append(answer)
128
+
129
+ loop_response.message.text = _get_final_answer_display(
130
+ text=loop_response.message.text,
131
+ answers_before=answers_displayed_before,
132
+ answers_after=answers_displayed_after,
133
+ )
134
+
135
+ return True
136
+
137
+ @override
138
+ async def remove_from_text(self, text) -> str:
139
+ for display_info in self._display_specs.values():
140
+ text = remove_sub_agent_answer_from_text(
141
+ display_config=display_info.display_config,
142
+ text=text,
143
+ assistant_id=display_info.assistant_id,
144
+ )
145
+ return text
146
+
147
+
148
+ def _add_response_references_to_message_in_place(
149
+ loop_response: LanguageModelStreamResponse, response: unique_sdk.Space.Message
150
+ ) -> None:
151
+ references = response["references"]
152
+ text = response["text"]
153
+
154
+ if references is None or len(references) == 0 or text is None:
155
+ return
156
+
157
+ content_refs = [ContentReference.from_sdk_reference(ref) for ref in references]
158
+
159
+ text, refs = add_content_refs_and_replace_in_text(
160
+ message_text=text,
161
+ message_refs=loop_response.message.references,
162
+ new_refs=content_refs,
163
+ )
164
+
165
+ response["text"] = text # Diplayed at a later stage
166
+ loop_response.message.references = refs
167
+
168
+
169
+ def _get_final_answer_display(
170
+ text: str,
171
+ answers_before: list[str],
172
+ answers_after: list[str],
173
+ sep: str = "<br>\n\n",
174
+ ) -> str:
175
+ if len(answers_before) > 0:
176
+ text = sep.join(answers_before) + sep + text
177
+
178
+ if len(answers_after) > 0:
179
+ text = text + sep + sep.join(answers_after)
180
+ return text
@@ -0,0 +1,101 @@
1
+ import logging
2
+ import re
3
+ from typing import override
4
+
5
+ from unique_toolkit._common.referencing import (
6
+ get_reference_pattern,
7
+ remove_consecutive_ref_space,
8
+ )
9
+ from unique_toolkit.agentic.postprocessor.postprocessor_manager import Postprocessor
10
+ from unique_toolkit.agentic.tools.a2a.postprocessing._ref_utils import (
11
+ add_content_refs_and_replace_in_text,
12
+ )
13
+ from unique_toolkit.agentic.tools.a2a.response_watcher import (
14
+ SubAgentResponse,
15
+ SubAgentResponseWatcher,
16
+ )
17
+ from unique_toolkit.agentic.tools.a2a.tool import SubAgentTool
18
+ from unique_toolkit.content import ContentReference
19
+ from unique_toolkit.language_model.schemas import LanguageModelStreamResponse
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class SubAgentReferencesPostprocessor(Postprocessor):
25
+ def __init__(self, response_watcher: SubAgentResponseWatcher) -> None:
26
+ super().__init__(name=self.__class__.__name__)
27
+ self._response_watcher = response_watcher
28
+
29
+ @override
30
+ async def run(self, loop_response: LanguageModelStreamResponse) -> None:
31
+ return
32
+
33
+ @override
34
+ def apply_postprocessing_to_response(
35
+ self, loop_response: LanguageModelStreamResponse
36
+ ) -> bool:
37
+ logger.info("Adding sub agent references to the main agent response")
38
+
39
+ num_sources = len(loop_response.message.references)
40
+
41
+ # At the moment, the `PostprocessorManager` expects modifications to happen in place
42
+ _add_sub_agent_references_in_place(
43
+ loop_response=loop_response,
44
+ responses=self._response_watcher.get_all_responses(),
45
+ )
46
+
47
+ return num_sources != len(
48
+ loop_response.message.references
49
+ ) # We only add references
50
+
51
+ @override
52
+ async def remove_from_text(self, text: str) -> str:
53
+ """
54
+ It is not possible to **only** remove sub agent references from the text,
55
+ as they are identical to normal references.
56
+ """
57
+ return text
58
+
59
+
60
+ def _add_sub_agent_references_in_place(
61
+ loop_response: LanguageModelStreamResponse,
62
+ responses: list[SubAgentResponse],
63
+ ) -> None:
64
+ text = loop_response.message.text
65
+ refs = []
66
+
67
+ for response in responses:
68
+ sub_agent_refs = []
69
+ references = response.message["references"]
70
+
71
+ if references is None or len(references) == 0:
72
+ continue
73
+
74
+ for reference in sorted(references, key=lambda r: r["sequenceNumber"]):
75
+ reference_re = SubAgentTool.get_sub_agent_reference_re(
76
+ name=response.name,
77
+ sequence_number=response.sequence_number,
78
+ reference_number=reference["sequenceNumber"],
79
+ )
80
+
81
+ if re.search(reference_re, text) is None:
82
+ # Reference not used
83
+ continue
84
+
85
+ sub_agent_refs.append(ContentReference.from_sdk_reference(reference))
86
+
87
+ text, refs = add_content_refs_and_replace_in_text(
88
+ message_text=text,
89
+ message_refs=refs,
90
+ new_refs=sub_agent_refs,
91
+ ref_pattern_f=lambda x: r"\s*" # Normalize spaces
92
+ + SubAgentTool.get_sub_agent_reference_re(
93
+ name=response.name,
94
+ sequence_number=response.sequence_number,
95
+ reference_number=x,
96
+ ),
97
+ ref_replacement_f=lambda x: " " + get_reference_pattern(x),
98
+ )
99
+
100
+ loop_response.message.references = refs
101
+ loop_response.message.text = remove_consecutive_ref_space(text)