unique_toolkit 0.8.15__py3-none-any.whl → 0.8.17__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 (28) hide show
  1. unique_toolkit/_common/token/token_counting.py +2 -3
  2. unique_toolkit/_common/validators.py +7 -0
  3. unique_toolkit/debug_info_manager/debug_info_manager.py +19 -0
  4. unique_toolkit/evals/config.py +36 -0
  5. unique_toolkit/evals/context_relevancy/prompts.py +56 -0
  6. unique_toolkit/evals/context_relevancy/schema.py +88 -0
  7. unique_toolkit/evals/context_relevancy/service.py +241 -0
  8. unique_toolkit/evals/hallucination/constants.py +61 -0
  9. unique_toolkit/evals/hallucination/hallucination_evaluation.py +91 -0
  10. unique_toolkit/evals/hallucination/prompts.py +79 -0
  11. unique_toolkit/evals/hallucination/service.py +57 -0
  12. unique_toolkit/evals/hallucination/utils.py +213 -0
  13. unique_toolkit/evals/output_parser.py +48 -0
  14. unique_toolkit/evals/tests/test_context_relevancy_service.py +252 -0
  15. unique_toolkit/evals/tests/test_output_parser.py +80 -0
  16. unique_toolkit/history_manager/history_construction_with_contents.py +4 -4
  17. unique_toolkit/history_manager/history_manager.py +51 -66
  18. unique_toolkit/history_manager/loop_token_reducer.py +17 -17
  19. unique_toolkit/language_model/schemas.py +8 -0
  20. unique_toolkit/postprocessor/postprocessor_manager.py +1 -2
  21. unique_toolkit/tools/factory.py +7 -2
  22. unique_toolkit/tools/tool.py +0 -2
  23. unique_toolkit/tools/tool_manager.py +0 -3
  24. {unique_toolkit-0.8.15.dist-info → unique_toolkit-0.8.17.dist-info}/METADATA +7 -1
  25. {unique_toolkit-0.8.15.dist-info → unique_toolkit-0.8.17.dist-info}/RECORD +27 -15
  26. unique_toolkit/tools/agent_chunks_handler.py +0 -62
  27. {unique_toolkit-0.8.15.dist-info → unique_toolkit-0.8.17.dist-info}/LICENSE +0 -0
  28. {unique_toolkit-0.8.15.dist-info → unique_toolkit-0.8.17.dist-info}/WHEEL +0 -0
@@ -0,0 +1,80 @@
1
+ import pytest
2
+
3
+ from unique_toolkit.evals.context_relevancy.schema import EvaluationSchemaStructuredOutput, Fact
4
+ from unique_toolkit.evals.exception import EvaluatorException
5
+ from unique_toolkit.evals.output_parser import parse_eval_metric_result, parse_eval_metric_result_structured_output
6
+ from unique_toolkit.evals.schemas import EvaluationMetricName, EvaluationMetricResult
7
+
8
+
9
+
10
+
11
+ def test_parse_eval_metric_result_success():
12
+ # Test successful parsing with all fields
13
+ result = '{"value": "high", "reason": "Test reason"}'
14
+ parsed = parse_eval_metric_result(result, EvaluationMetricName.CONTEXT_RELEVANCY)
15
+
16
+ assert isinstance(parsed, EvaluationMetricResult)
17
+ assert parsed.name == EvaluationMetricName.CONTEXT_RELEVANCY
18
+ assert parsed.value == "high"
19
+ assert parsed.reason == "Test reason"
20
+ assert parsed.fact_list == []
21
+
22
+
23
+ def test_parse_eval_metric_result_missing_fields():
24
+ # Test parsing with missing fields (should use default "None")
25
+ result = '{"value": "high"}'
26
+ parsed = parse_eval_metric_result(result, EvaluationMetricName.CONTEXT_RELEVANCY)
27
+
28
+ assert isinstance(parsed, EvaluationMetricResult)
29
+ assert parsed.name == EvaluationMetricName.CONTEXT_RELEVANCY
30
+ assert parsed.value == "high"
31
+ assert parsed.reason == "None"
32
+ assert parsed.fact_list == []
33
+
34
+
35
+ def test_parse_eval_metric_result_invalid_json():
36
+ # Test parsing with invalid JSON
37
+ result = "invalid json"
38
+ with pytest.raises(EvaluatorException) as exc_info:
39
+ parse_eval_metric_result(result, EvaluationMetricName.CONTEXT_RELEVANCY)
40
+
41
+ assert "Error occurred during parsing the evaluation metric result" in str(
42
+ exc_info.value
43
+ )
44
+
45
+
46
+ def test_parse_eval_metric_result_structured_output_basic():
47
+ # Test basic structured output without fact list
48
+ result = EvaluationSchemaStructuredOutput(value="high", reason="Test reason")
49
+ parsed = parse_eval_metric_result_structured_output(
50
+ result, EvaluationMetricName.CONTEXT_RELEVANCY
51
+ )
52
+
53
+ assert isinstance(parsed, EvaluationMetricResult)
54
+ assert parsed.name == EvaluationMetricName.CONTEXT_RELEVANCY
55
+ assert parsed.value == "high"
56
+ assert parsed.reason == "Test reason"
57
+ assert parsed.fact_list == []
58
+
59
+
60
+ def test_parse_eval_metric_result_structured_output_with_facts():
61
+ # Test structured output with fact list
62
+ result = EvaluationSchemaStructuredOutput(
63
+ value="high",
64
+ reason="Test reason",
65
+ fact_list=[
66
+ Fact(fact="Fact 1"),
67
+ Fact(fact="Fact 2"),
68
+ ],
69
+ )
70
+ parsed = parse_eval_metric_result_structured_output(
71
+ result, EvaluationMetricName.CONTEXT_RELEVANCY
72
+ )
73
+
74
+ assert isinstance(parsed, EvaluationMetricResult)
75
+ assert parsed.name == EvaluationMetricName.CONTEXT_RELEVANCY
76
+ assert parsed.value == "high"
77
+ assert parsed.reason == "Test reason"
78
+ assert parsed.fact_list == ["Fact 1", "Fact 2"]
79
+ assert isinstance(parsed.fact_list, list)
80
+ assert len(parsed.fact_list) == 2 # None fact should be filtered out
@@ -9,10 +9,10 @@ import tiktoken
9
9
 
10
10
  from pydantic import RootModel
11
11
 
12
- from _common.token.token_counting import num_tokens_per_language_model_message
13
- from chat.service import ChatService
14
- from content.service import ContentService
15
- from language_model.schemas import LanguageModelMessages
12
+ from unique_toolkit._common.token.token_counting import num_tokens_per_language_model_message
13
+ from unique_toolkit.chat.service import ChatService
14
+ from unique_toolkit.content.service import ContentService
15
+ from unique_toolkit.language_model.schemas import LanguageModelMessages
16
16
  from unique_toolkit.app import ChatEventUserMessage
17
17
  from unique_toolkit.chat.schemas import ChatMessage
18
18
  from unique_toolkit.chat.schemas import ChatMessageRole as ChatRole
@@ -1,91 +1,84 @@
1
- from datetime import datetime
2
1
  from logging import Logger
3
2
  from typing import Annotated, Awaitable, Callable
4
3
 
5
4
  from pydantic import BaseModel, Field
6
5
 
7
- import tiktoken
8
6
  from unique_toolkit.app.schemas import ChatEvent
9
7
 
10
8
 
11
- from unique_toolkit.chat.schemas import ChatMessage
12
- from unique_toolkit.chat.service import ChatService
13
- from unique_toolkit.content.schemas import Content
14
- from unique_toolkit.content.service import ContentService
15
- from unique_toolkit.language_model.builder import MessagesBuilder
9
+
16
10
  from unique_toolkit.language_model.schemas import (
17
11
  LanguageModelAssistantMessage,
18
12
  LanguageModelFunction,
19
- LanguageModelMessage,
20
- LanguageModelMessageRole,
21
- LanguageModelSystemMessage,
22
- LanguageModelToolMessage,
23
- LanguageModelUserMessage,
13
+ LanguageModelMessage,
14
+ LanguageModelMessages,
15
+ LanguageModelToolMessage
24
16
  )
25
17
 
26
18
  from unique_toolkit.tools.schemas import ToolCallResponse
27
19
  from unique_toolkit.history_manager.utils import transform_chunks_to_string
28
20
 
29
- from _common.validators import LMI
30
- from history_manager.loop_token_reducer import LoopTokenReducer
31
- from reference_manager.reference_manager import ReferenceManager
32
- from tools.config import get_configuration_dict
21
+ from unique_toolkit._common.validators import LMI
22
+ from unique_toolkit.history_manager.loop_token_reducer import LoopTokenReducer
23
+ from unique_toolkit.language_model.infos import LanguageModelInfo, LanguageModelName
24
+ from unique_toolkit.reference_manager.reference_manager import ReferenceManager
25
+ from unique_toolkit.tools.config import get_configuration_dict
33
26
 
34
27
  DeactivatedNone = Annotated[
35
28
  None,
36
29
  Field(title="Deactivated", description="None"),
37
30
  ]
38
31
 
39
- class HistoryManagerConfig(BaseModel):
32
+ class UploadedContentConfig(BaseModel):
33
+ model_config = get_configuration_dict()
40
34
 
41
- class InputTokenDistributionConfig(BaseModel):
42
- model_config = get_configuration_dict(frozen=True)
35
+ user_context_window_limit_warning: str = Field(
36
+ default="The uploaded content is too large to fit into the ai model. "
37
+ "Unique AI will search for relevant sections in the material and if needed combine the data with knowledge base content",
38
+ description="Message to show when using the Internal Search instead of upload and chat tool due to context window limit. Jinja template.",
39
+ )
40
+ percent_for_uploaded_content: float = Field(
41
+ default=0.6,
42
+ ge=0.0,
43
+ lt=1.0,
44
+ description="The fraction of the max input tokens that will be reserved for the uploaded content.",
45
+ )
43
46
 
44
- percent_for_history: float = Field(
45
- default=0.6,
46
- ge=0.0,
47
- lt=1.0,
48
- description="The fraction of the max input tokens that will be reserved for the history.",
49
- )
47
+ class ExperimentalFeatures(BaseModel):
50
48
 
51
- def max_history_tokens(self, max_input_token: int) -> int:
52
- return int(self.percent_for_history * max_input_token)
53
-
54
- class UploadedContentConfig(BaseModel):
55
- model_config = get_configuration_dict()
49
+ full_sources_serialize_dump: bool = Field(
50
+ default=False,
51
+ description="If True, the sources will be serialized in full, otherwise only the content will be serialized.",
52
+ )
56
53
 
57
- user_context_window_limit_warning: str = Field(
58
- default="The uploaded content is too large to fit into the ai model. "
59
- "Unique AI will search for relevant sections in the material and if needed combine the data with knowledge base content",
60
- description="Message to show when using the Internal Search instead of upload and chat tool due to context window limit. Jinja template.",
61
- )
62
- percent_for_uploaded_content: float = Field(
63
- default=0.6,
64
- ge=0.0,
65
- lt=1.0,
66
- description="The fraction of the max input tokens that will be reserved for the uploaded content.",
67
- )
68
54
 
69
- class ExperimentalFeatures(BaseModel):
70
- def __init__(self, full_sources_serialize_dump: bool = False):
71
- self.full_sources_serialize_dump = full_sources_serialize_dump
55
+ class HistoryManagerConfig(BaseModel):
72
56
 
73
- full_sources_serialize_dump: bool = Field(
74
- default=False,
75
- description="If True, the sources will be serialized in full, otherwise only the content will be serialized.",
76
- )
77
57
 
78
58
  experimental_features: ExperimentalFeatures = Field(
79
59
  default=ExperimentalFeatures(),
80
60
  description="Experimental features for the history manager.",
81
61
  )
82
62
 
83
- max_history_tokens: int = Field(
84
- default=8000,
85
- ge=0,
86
- description="The maximum number of tokens to keep in the history.",
63
+
64
+ percent_of_max_tokens_for_history: float = Field(
65
+ default=0.2,
66
+ ge=0.0,
67
+ lt=1.0,
68
+ description="The fraction of the max input tokens that will be reserved for the history.",
87
69
  )
88
70
 
71
+ language_model: LMI = LanguageModelInfo.from_name(
72
+ LanguageModelName.AZURE_GPT_4o_2024_1120
73
+ )
74
+
75
+ @property
76
+ def max_history_tokens(self) -> int:
77
+ return int(
78
+ self.language_model.token_limits.token_limit_input
79
+ * self.percent_of_max_tokens_for_history,
80
+ )
81
+
89
82
  uploaded_content_config: (
90
83
  Annotated[
91
84
  UploadedContentConfig,
@@ -95,11 +88,6 @@ class HistoryManagerConfig(BaseModel):
95
88
  ) = UploadedContentConfig()
96
89
 
97
90
 
98
- input_token_distribution: InputTokenDistributionConfig = Field(
99
- default=InputTokenDistributionConfig(),
100
- description="Configuration for the input token distribution.",
101
- )
102
-
103
91
 
104
92
  class HistoryManager:
105
93
  """
@@ -139,7 +127,8 @@ class HistoryManager:
139
127
  self._token_reducer = LoopTokenReducer(
140
128
  logger=self._logger,
141
129
  event=event,
142
- config=self._config,
130
+ max_history_tokens=self._config.max_history_tokens,
131
+ has_uploaded_content_config=bool(self._config.uploaded_content_config),
143
132
  language_model=self._language_model,
144
133
  reference_manager=reference_manager,
145
134
  )
@@ -218,13 +207,9 @@ class HistoryManager:
218
207
  rendered_user_message_string: str,
219
208
  rendered_system_message_string: str,
220
209
  remove_from_text: Callable[[str], Awaitable[str]]
221
- ) -> list[
222
- LanguageModelMessage
223
- | LanguageModelToolMessage
224
- | LanguageModelAssistantMessage
225
- | LanguageModelSystemMessage
226
- | LanguageModelUserMessage
227
- ]:
210
+ ) -> LanguageModelMessages:
211
+ self._logger.info("Getting history for model call -> ")
212
+
228
213
  messages = await self._token_reducer.get_history_for_model_call(
229
214
  original_user_message=original_user_message,
230
215
  rendered_user_message_string=rendered_user_message_string,
@@ -232,4 +217,4 @@ class HistoryManager:
232
217
  loop_history=self._loop_history,
233
218
  remove_from_text=remove_from_text,
234
219
  )
235
- return messages.root
220
+ return messages
@@ -5,16 +5,15 @@ from typing import Awaitable, Callable
5
5
 
6
6
  from pydantic import BaseModel
7
7
  import tiktoken
8
- from _common.token.token_counting import num_token_for_language_model_messages
9
- from _common.validators import LMI
10
- from app.schemas import ChatEvent
11
- from chat.service import ChatService
12
- from content.schemas import ContentChunk
13
- from content.service import ContentService
14
- from history_manager.history_construction_with_contents import FileContentSerialization, get_full_history_with_contents
15
- from history_manager.history_manager import HistoryManagerConfig
16
- from language_model.schemas import LanguageModelAssistantMessage, LanguageModelMessage, LanguageModelMessageRole, LanguageModelMessages, LanguageModelSystemMessage, LanguageModelToolMessage, LanguageModelUserMessage
17
- from reference_manager.reference_manager import ReferenceManager
8
+ from unique_toolkit._common.token.token_counting import num_token_for_language_model_messages
9
+ from unique_toolkit._common.validators import LMI
10
+ from unique_toolkit.app.schemas import ChatEvent
11
+ from unique_toolkit.chat.service import ChatService
12
+ from unique_toolkit.content.schemas import ContentChunk
13
+ from unique_toolkit.content.service import ContentService
14
+ from unique_toolkit.history_manager.history_construction_with_contents import FileContentSerialization, get_full_history_with_contents
15
+ from unique_toolkit.language_model.schemas import LanguageModelAssistantMessage, LanguageModelMessage, LanguageModelMessageRole, LanguageModelMessages, LanguageModelSystemMessage, LanguageModelToolMessage, LanguageModelUserMessage
16
+ from unique_toolkit.reference_manager.reference_manager import ReferenceManager
18
17
 
19
18
 
20
19
  class SourceReductionResult(BaseModel):
@@ -33,11 +32,14 @@ class LoopTokenReducer():
33
32
  self,
34
33
  logger: Logger,
35
34
  event: ChatEvent,
36
- config: HistoryManagerConfig,
35
+ max_history_tokens:int,
36
+ has_uploaded_content_config: bool,
37
37
  reference_manager: ReferenceManager,
38
38
  language_model: LMI
39
39
  ):
40
- self._config = config
40
+
41
+ self._max_history_tokens = max_history_tokens
42
+ self._has_uploaded_content_config = has_uploaded_content_config
41
43
  self._logger = logger
42
44
  self._reference_manager = reference_manager
43
45
  self._language_model = language_model
@@ -49,7 +51,7 @@ class LoopTokenReducer():
49
51
 
50
52
 
51
53
  def _get_encoder(self, language_model: LMI) -> tiktoken.Encoding:
52
- name = language_model.name or "cl100k_base"
54
+ name = language_model.encoder_name or "cl100k_base"
53
55
  return tiktoken.get_encoding(name)
54
56
 
55
57
  async def get_history_for_model_call( self,
@@ -203,7 +205,7 @@ class LoopTokenReducer():
203
205
  content_service=self._content_service,
204
206
  file_content_serialization_type=(
205
207
  FileContentSerialization.NONE
206
- if self._config.uploaded_content_config
208
+ if self._has_uploaded_content_config
207
209
  else FileContentSerialization.FILE_NAME
208
210
  ),
209
211
  )
@@ -212,9 +214,7 @@ class LoopTokenReducer():
212
214
 
213
215
  limited_history_messages = self._limit_to_token_window(
214
216
  full_history.root,
215
- self._config.input_token_distribution.max_history_tokens(
216
- self._language_model.token_limits.token_limit_input,
217
- )
217
+ self._max_history_tokens
218
218
  )
219
219
 
220
220
 
@@ -129,6 +129,14 @@ class LanguageModelStreamResponse(BaseModel):
129
129
  message: LanguageModelStreamResponseMessage
130
130
  tool_calls: list[LanguageModelFunction] | None = None
131
131
 
132
+ def is_empty(self) -> bool:
133
+ """
134
+ Check if the stream response is empty.
135
+ An empty stream response has no text and no tool calls.
136
+ """
137
+ return not self.message.original_text and not self.tool_calls
138
+
139
+
132
140
  def to_openai_param(self) -> ChatCompletionAssistantMessageParam:
133
141
  return ChatCompletionAssistantMessageParam(
134
142
  role="assistant",
@@ -4,10 +4,9 @@ from logging import Logger
4
4
 
5
5
  from unique_toolkit.chat.service import ChatService
6
6
  from unique_toolkit.language_model.schemas import (
7
- LanguageModelMessage,
8
7
  LanguageModelStreamResponse,
9
8
  )
10
- from unique_toolkit.tools.utils.execution.execution import Result, SafeTaskExecutor
9
+ from unique_toolkit.tools.utils.execution.execution import SafeTaskExecutor
11
10
 
12
11
 
13
12
  class Postprocessor(ABC):
@@ -1,13 +1,18 @@
1
1
  from typing import Callable
2
2
 
3
- from typing import TYPE_CHECKING
4
- from unique_toolkit.tools.schemas import BaseToolConfig
3
+
5
4
  from unique_toolkit.tools.tool import Tool
6
5
 
6
+ from unique_toolkit.tools.schemas import BaseToolConfig
7
+
8
+
9
+ from typing import TYPE_CHECKING
7
10
  if TYPE_CHECKING:
8
11
  from unique_toolkit.tools.config import ToolBuildConfig
9
12
 
10
13
 
14
+
15
+
11
16
  class ToolFactory:
12
17
  tool_map: dict[str, type[Tool]] = {}
13
18
  tool_config_map: dict[str, Callable] = {}
@@ -19,7 +19,6 @@ from unique_toolkit.language_model.service import LanguageModelService
19
19
 
20
20
 
21
21
  from unique_toolkit.evals.schemas import EvaluationMetricName
22
- from unique_toolkit.tools.agent_chunks_handler import AgentChunksHandler
23
22
  from unique_toolkit.tools.config import ToolBuildConfig, ToolSelectionPolicy
24
23
  from unique_toolkit.tools.schemas import BaseToolConfig, ToolCallResponse, ToolPrompts
25
24
  from unique_toolkit.tools.tool_progress_reporter import ToolProgressReporter
@@ -81,7 +80,6 @@ class Tool(ABC, Generic[ConfigType]):
81
80
  def get_tool_call_result_for_loop_history(
82
81
  self,
83
82
  tool_response: ToolCallResponse,
84
- agent_chunks_handler: AgentChunksHandler,
85
83
  ) -> LanguageModelMessage:
86
84
  raise NotImplementedError
87
85
 
@@ -35,9 +35,6 @@ class ToolManagerConfig(BaseModel):
35
35
  description="Maximum number of tool calls that can be executed in one iteration.",
36
36
  )
37
37
 
38
- def __init__(self, tools: list[ToolBuildConfig], max_tool_calls: int = 10):
39
- self.tools = tools
40
- self.max_tool_calls = max_tool_calls
41
38
 
42
39
 
43
40
  class ToolManager:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 0.8.15
3
+ Version: 0.8.17
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Martin Fadler
@@ -114,6 +114,12 @@ All notable changes to this project will be documented in this file.
114
114
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
115
115
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
116
116
 
117
+ ## [0.8.17] - 2025-08-22
118
+ - fixed circular dependencies in tools
119
+
120
+ ## [0.8.16] - 2025-08-19
121
+ - moved Hallucination evaluator into toolkit
122
+
117
123
  ## [0.8.15] - 2025-08-19
118
124
  - Added history loading from database for History Manager
119
125
 
@@ -4,9 +4,9 @@ unique_toolkit/_common/_time_utils.py,sha256=ztmTovTvr-3w71Ns2VwXC65OKUUh-sQlzbH
4
4
  unique_toolkit/_common/default_language_model.py,sha256=M6OiVfpi21CixfgYFigOcJGqG8r987f2rxHnn0NZ2dc,333
5
5
  unique_toolkit/_common/exception.py,sha256=caQIE1btsQnpKCHqL2cgWUSbHup06enQu_Pt7uGUTTE,727
6
6
  unique_toolkit/_common/token/image_token_counting.py,sha256=VpFfZyY0GIH27q_Wy4YNjk2algqvbCtJyzuuROoFQPw,2189
7
- unique_toolkit/_common/token/token_counting.py,sha256=l8tDo5EaD5FIlKz7Zd6CTNYwMhF-UZ2S3Hb-pU5z2UY,6281
7
+ unique_toolkit/_common/token/token_counting.py,sha256=PE_SGqWr6sXwEYJcap85SQA_xX2RP1E7yvvYYOju-DE,6282
8
8
  unique_toolkit/_common/validate_required_values.py,sha256=Y_M1ub9gIKP9qZ45F6Zq3ZHtuIqhmOjl8Z2Vd3avg8w,588
9
- unique_toolkit/_common/validators.py,sha256=uPGPkeygNi3KimWZxKOKYFxwpCxTkhhYBAn-b_5TS_M,2584
9
+ unique_toolkit/_common/validators.py,sha256=BPDy-Bm4W_Sq-ICJ6p2OwzsvjvRZlRX5W1ws0ZJjwl0,2804
10
10
  unique_toolkit/app/__init__.py,sha256=ETxYDpEizg_PKmi4JPX_P76ySq-us-xypfAIdKQ1QZU,1284
11
11
  unique_toolkit/app/dev_util.py,sha256=rN-xSg4OGfmwjaToy8m_hQroehcLYyk9-GCmQJ-f6uY,4302
12
12
  unique_toolkit/app/init_logging.py,sha256=Sh26SRxOj8i8dzobKhYha2lLrkrMTHfB1V4jR3h23gQ,678
@@ -29,15 +29,28 @@ unique_toolkit/content/functions.py,sha256=HZtDIAH3ZxWleq5Si_v30n_7vTnNRu6BCxpTH
29
29
  unique_toolkit/content/schemas.py,sha256=KJ604BOx0vBh2AwlTCZkOo55aHsI6yj8vxDAARKKqEo,2995
30
30
  unique_toolkit/content/service.py,sha256=3zUu3vUcPV8Mb_v1TCyi2hicGVMLNBamKB3Q6-z1trY,21455
31
31
  unique_toolkit/content/utils.py,sha256=qNVmHTuETaPNGqheg7TbgPr1_1jbNHDc09N5RrmUIyo,7901
32
+ unique_toolkit/debug_info_manager/debug_info_manager.py,sha256=-IiArCVjazVxbJY884cLfKSnLEOKDfqt5i3SVPAAvFo,650
32
33
  unique_toolkit/embedding/__init__.py,sha256=uUyzjonPvuDCYsvXCIt7ErQXopLggpzX-MEQd3_e2kE,250
33
34
  unique_toolkit/embedding/constants.py,sha256=Lj8-Lcy1FvuC31PM9Exq7vaFuxQV4pEI1huUMFX-J2M,52
34
35
  unique_toolkit/embedding/functions.py,sha256=3qp-BfuMAbnp8YB04rh3xH8vsJuCBPizoy-JeaBFtoQ,1944
35
36
  unique_toolkit/embedding/schemas.py,sha256=1GvKCaSk4jixzVQ2PKq8yDqwGEVY_hWclYtoAr6CC2g,96
36
37
  unique_toolkit/embedding/service.py,sha256=2KjYlUKxeh-Je8S1mOPiQ735pqAmdbeztycVNJxcUXA,5039
37
38
  unique_toolkit/embedding/utils.py,sha256=v86lo__bCJbxZBQ3OcLu5SuwT6NbFfWlcq8iyk6BuzQ,279
39
+ unique_toolkit/evals/config.py,sha256=LtBcPVCNpyZ2fFAKjiT9dPGauDSH5f0d_Jt4KpuS5OM,954
40
+ unique_toolkit/evals/context_relevancy/prompts.py,sha256=EdHFUOB581yVxcOL8482KUv_LzaRjuiem71EF8udYMc,1331
41
+ unique_toolkit/evals/context_relevancy/schema.py,sha256=xJeAHUwTTc-a090HhRYiK8Mob5Vt350lNfItz6w6Cq8,2958
42
+ unique_toolkit/evals/context_relevancy/service.py,sha256=j7crX64kMEGTcbQoUwCeGCCVaGfoLvYHclXLVt-x3zA,8384
38
43
  unique_toolkit/evals/evaluation_manager.py,sha256=_4XF2JY8EZd8kRmaZzF1S5R0kNATKTzgpE0ZIQDqQLE,7711
39
44
  unique_toolkit/evals/exception.py,sha256=7lcVbCyoN4Md1chNJDFxpUYyWbVrcr9dcc3TxWykJTc,115
45
+ unique_toolkit/evals/hallucination/constants.py,sha256=-eA0e3QntllNJ1wLOx-zAnCUrvDT4pS5IRwmACoMICc,1998
46
+ unique_toolkit/evals/hallucination/hallucination_evaluation.py,sha256=2zroBydl90xxB6Lcf2v6Wsg9PsQHZ6uHrHoSUUFo6VQ,3088
47
+ unique_toolkit/evals/hallucination/prompts.py,sha256=O3Hi_rOzZlujvnO2wn2jhoPmrYLjzVtRWwxn5Q81m9Y,3405
48
+ unique_toolkit/evals/hallucination/service.py,sha256=VH0jhoIf5_8lwy3f7ODhgVU08LfsXs5uk8GOjCpPVkc,2409
49
+ unique_toolkit/evals/hallucination/utils.py,sha256=CytY60CBdhq7777YljO38ngK3RSMqA-5Xh5YfpJbsE8,8127
50
+ unique_toolkit/evals/output_parser.py,sha256=vYjnlm8upIH1eiqGlwGx8K-KSf6IALgFeGMn6eW_HFE,1379
40
51
  unique_toolkit/evals/schemas.py,sha256=VwxT_L_1Fima1RwGWajp1DIPy36-4n23_eCFkK3MjTM,3114
52
+ unique_toolkit/evals/tests/test_context_relevancy_service.py,sha256=1kpNw4eeGXGX9eBr6IGEp605M6BrnBHFWs4j1_s3_Mc,7898
53
+ unique_toolkit/evals/tests/test_output_parser.py,sha256=HwSqptYI_8BeQtwyrQwPLwX11ugC5tjxL1BrM0LdMVc,3018
41
54
  unique_toolkit/evaluators/__init__.py,sha256=3Rfpnowm7MUXHWmeU4UV4s_3Hk-sw3V20oBwQCYlejQ,50
42
55
  unique_toolkit/evaluators/config.py,sha256=_DIXToJ-hGNpDAdWa7Q6GMjAsxiC_DquLF-SS5s9rTE,717
43
56
  unique_toolkit/evaluators/constants.py,sha256=1oI93jsh0R_TjX_8OenliiiywVe3vTooSnaMqtq6R18,27
@@ -57,9 +70,9 @@ unique_toolkit/framework_utilities/langchain/history.py,sha256=R9RuCeSFNaUO3OZ0G
57
70
  unique_toolkit/framework_utilities/openai/client.py,sha256=IasxPXlVJHIsZdXHin7yq-5tO4RNLUu9cEuhrgb4ghE,1205
58
71
  unique_toolkit/framework_utilities/openai/message_builder.py,sha256=VU6mJm_upLcarJQKFft_t1RlLRncWDxDuLC5LIJ5lQQ,4339
59
72
  unique_toolkit/framework_utilities/utils.py,sha256=JK7g2yMfEx3eMprug26769xqNpS5WJcizf8n2zWMBng,789
60
- unique_toolkit/history_manager/history_construction_with_contents.py,sha256=xKUVnJ4ZJq4-nnO2_35dbDh9d-zfCJfRzuj7v9hXUdM,9049
61
- unique_toolkit/history_manager/history_manager.py,sha256=ULtsC7cGl92G2fXKIkEajH3tIy_qqWKIK8FudpNKhu4,8834
62
- unique_toolkit/history_manager/loop_token_reducer.py,sha256=-7Ezk3OLUsrU0Jd9Qc73_PBJZIayz7bVE3awc-q6Se0,17624
73
+ unique_toolkit/history_manager/history_construction_with_contents.py,sha256=0-xq8CPlqG_nAjmPu_sAXMbzau2TsG9j-6PSMo6tO6k,9109
74
+ unique_toolkit/history_manager/history_manager.py,sha256=DL2RCTYAerqVy1V2z29WSNHfn3lH_z_4wc1sJS2oQ8I,8090
75
+ unique_toolkit/history_manager/loop_token_reducer.py,sha256=F5iFPS-m1qaYyi5xysky3nxCV4zyM8s21muyOxSquaQ,17725
63
76
  unique_toolkit/history_manager/utils.py,sha256=3GT53SfOQ7g-dN3PHFIPaAab74sUfV28hbUtGMdX-bY,5607
64
77
  unique_toolkit/language_model/__init__.py,sha256=lRQyLlbwHbNFf4-0foBU13UGb09lwEeodbVsfsSgaCk,1971
65
78
  unique_toolkit/language_model/builder.py,sha256=4OKfwJfj3TrgO1ezc_ewIue6W7BCQ2ZYQXUckWVPPTA,3369
@@ -68,10 +81,10 @@ unique_toolkit/language_model/functions.py,sha256=-nWgcscaZvEfuf2ftCQj8hyFY2RynP
68
81
  unique_toolkit/language_model/infos.py,sha256=MbuXYtyTLik-7KTKlyQCjW3uNRTT5ddTvbpSarFxzPk,45715
69
82
  unique_toolkit/language_model/prompt.py,sha256=JSawaLjQg3VR-E2fK8engFyJnNdk21zaO8pPIodzN4Q,3991
70
83
  unique_toolkit/language_model/reference.py,sha256=nkX2VFz-IrUz8yqyc3G5jUMNwrNpxITBrMEKkbqqYoI,8583
71
- unique_toolkit/language_model/schemas.py,sha256=p95cAwrYmEBupI8f7JZY17aJTKEHvtqF88hMIzS5r_k,16259
84
+ unique_toolkit/language_model/schemas.py,sha256=ix5tCLUnlpAgc-WzV_54O_QpVI-shXOIUJVYVBRagpo,16498
72
85
  unique_toolkit/language_model/service.py,sha256=N_I3VtK5B0G8s5c6TcBVWM7CcLGqakDhEdHQ_z-Hcok,11676
73
86
  unique_toolkit/language_model/utils.py,sha256=bPQ4l6_YO71w-zaIPanUUmtbXC1_hCvLK0tAFc3VCRc,1902
74
- unique_toolkit/postprocessor/postprocessor_manager.py,sha256=68TAcXMU_ohWOtzo91LntY950HV9I9gGU92-V0Mxmr8,4239
87
+ unique_toolkit/postprocessor/postprocessor_manager.py,sha256=fhTFto_t0FL5bacraGNMAky-AVVYJFJbIpXGRwSNpEE,4205
75
88
  unique_toolkit/protocols/support.py,sha256=V15WEIFKVMyF1QCnR8vIi4GrJy4dfTCB6d6JlqPZ58o,2341
76
89
  unique_toolkit/reference_manager/reference_manager.py,sha256=WIvZkRgQztkY0zNTM_KIPSqJFT22HIGNexJ4yG3aj5E,3993
77
90
  unique_toolkit/short_term_memory/__init__.py,sha256=2mI3AUrffgH7Yt-xS57EGqnHf7jnn6xquoKEhJqk3Wg,185
@@ -83,19 +96,18 @@ unique_toolkit/short_term_memory/service.py,sha256=5PeVBu1ZCAfyDb2HLVvlmqSbyzBBu
83
96
  unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
97
  unique_toolkit/smart_rules/compile.py,sha256=cxWjb2dxEI2HGsakKdVCkSNi7VK9mr08w5sDcFCQyWI,9553
85
98
  unique_toolkit/thinking_manager/thinking_manager.py,sha256=_7G4RJM4Or66myx2AJ2UNk1vhQXV7_uLXlIxmumgmKk,4208
86
- unique_toolkit/tools/agent_chunks_handler.py,sha256=ORjC22ulfHTfPxUHmU7QU0H53j3AdLmt1a0opeI91V8,1809
87
99
  unique_toolkit/tools/config.py,sha256=9bYxdDuUPmAxhYyIdLbmXLzX1X2AUw--_WISQxQ4G2U,3003
88
- unique_toolkit/tools/factory.py,sha256=vxxchbPTrk2lVjSMdpcFN-6FRcMLiy-NgHHS3w0wYCA,1271
100
+ unique_toolkit/tools/factory.py,sha256=wA30xdUxpahzrtO_uau8-VokpGRttxG1P7SuH95EQ2E,1276
89
101
  unique_toolkit/tools/schemas.py,sha256=IngcnYCqaAVl3ADbW-j_-ZXlPK1oVKeXqHDyXJH8Bso,4692
90
102
  unique_toolkit/tools/test/test_tool_progress_reporter.py,sha256=YCR7uJ4_sn-z3CJskzSNWNDYYcThr9m2Q6gRBxbLVfg,6298
91
- unique_toolkit/tools/tool.py,sha256=UZ-WdScj_VBdBNMz56SwvdpIKGNZLKNy3lRsgJAr6EY,5746
92
- unique_toolkit/tools/tool_manager.py,sha256=eXzx4608noza2At7yjqC2B44h4a7gv7lZMo1-xoLY98,9046
103
+ unique_toolkit/tools/tool.py,sha256=RZ8JelfueEr5v-6JedOf7WRVnYEB4euaPXk_LIjSkN8,5623
104
+ unique_toolkit/tools/tool_manager.py,sha256=Bbfuh-9DB0iBG6FWyLxEBwD8fh8Ias4zsaD6kXQTQ0w,8894
93
105
  unique_toolkit/tools/tool_progress_reporter.py,sha256=j6iVTpoLU_PjLwoK6fpIy9vmX_MLWF_-_v-nTDUcwas,7954
94
106
  unique_toolkit/tools/utils/execution/execution.py,sha256=vjG2Y6awsGNtlvyQAGCTthQ5thWHYnn-vzZXaYLb3QE,7922
95
107
  unique_toolkit/tools/utils/source_handling/schema.py,sha256=pvNhtL2daDLpCVIQpfdn6R35GvKmITVLXjZNLAwpgUE,871
96
108
  unique_toolkit/tools/utils/source_handling/source_formatting.py,sha256=C7uayNbdkNVJdEARA5CENnHtNY1SU6etlaqbgHNyxaQ,9152
97
109
  unique_toolkit/tools/utils/source_handling/tests/test_source_formatting.py,sha256=zu3AJnYH9CMqZPrxKEH3IgI-fM3nlvIBuspJG6W6B18,6978
98
- unique_toolkit-0.8.15.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
99
- unique_toolkit-0.8.15.dist-info/METADATA,sha256=HC0kUwceqxR_BLx4SUd7-mFMLZ4roX2mIxpTRy19xnE,27726
100
- unique_toolkit-0.8.15.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
101
- unique_toolkit-0.8.15.dist-info/RECORD,,
110
+ unique_toolkit-0.8.17.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
111
+ unique_toolkit-0.8.17.dist-info/METADATA,sha256=iFqwENwo_SlhPt0d_Dc6MnqAQgw3qPYmbP1ppLMkCvY,27862
112
+ unique_toolkit-0.8.17.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
113
+ unique_toolkit-0.8.17.dist-info/RECORD,,
@@ -1,62 +0,0 @@
1
- from unique_toolkit.content.schemas import ContentChunk, ContentReference
2
-
3
-
4
- class AgentChunksHandler:
5
- def __init__(self):
6
- self._tool_chunks = {}
7
- self._chunks: list[ContentChunk] = []
8
- self._references: list[list[ContentReference]] = []
9
-
10
- @property
11
- def chunks(self) -> list[ContentChunk]:
12
- return self._chunks
13
-
14
- @property
15
- def tool_chunks(self) -> dict:
16
- return self._tool_chunks
17
-
18
- def extend(self, chunks: list[ContentChunk]):
19
- self._chunks.extend(chunks)
20
-
21
- def replace(self, chunks: list[ContentChunk]):
22
- self._chunks = chunks
23
-
24
- def add_references(
25
- self,
26
- references: list[ContentReference],
27
- ):
28
- self._references.append(references)
29
-
30
- @property
31
- def all_references(
32
- self,
33
- ) -> list[list[ContentReference]]:
34
- return self._references
35
-
36
- @property
37
- def latest_references(
38
- self,
39
- ) -> list[ContentReference]:
40
- if not self._references:
41
- return []
42
- return self._references[-1]
43
-
44
- @property
45
- def latest_referenced_chunks(self) -> list[ContentChunk]:
46
- if not self._references:
47
- return []
48
- return self._get_referenced_chunks_from_references(self._references[-1])
49
-
50
- def _get_referenced_chunks_from_references(
51
- self,
52
- references: list[ContentReference],
53
- ) -> list[ContentChunk]:
54
- """
55
- Get _referenced_chunks by matching sourceId from _references with merged id and chunk_id from _chunks.
56
- """
57
- referenced_chunks: list[ContentChunk] = []
58
- for ref in references:
59
- for chunk in self._chunks:
60
- if ref.source_id == str(chunk.id) + "_" + str(chunk.chunk_id):
61
- referenced_chunks.append(chunk)
62
- return referenced_chunks