unique_toolkit 0.8.19__py3-none-any.whl → 0.8.21__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.
@@ -1,4 +1,6 @@
1
1
  import logging
2
+ import mimetypes
3
+ from enum import StrEnum
2
4
  from pathlib import Path
3
5
  from typing import Any, overload
4
6
 
@@ -33,6 +35,29 @@ from unique_toolkit.content.schemas import (
33
35
  logger = logging.getLogger(f"toolkit.{DOMAIN_NAME}.{__name__}")
34
36
 
35
37
 
38
+ class FileMimeType(StrEnum):
39
+ PDF = "application/pdf"
40
+ DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
41
+ DOC = "application/msword"
42
+ XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
43
+ XLS = "application/vnd.ms-excel"
44
+ PPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation"
45
+ CSV = "text/csv"
46
+ HTML = "text/html"
47
+ MD = "text/markdown"
48
+ TXT = "text/plain"
49
+
50
+
51
+ class ImageMimeType(StrEnum):
52
+ JPEG = "image/jpeg"
53
+ PNG = "image/png"
54
+ GIF = "image/gif"
55
+ BMP = "image/bmp"
56
+ WEBP = "image/webp"
57
+ TIFF = "image/tiff"
58
+ SVG = "image/svg+xml"
59
+
60
+
36
61
  class ContentService:
37
62
  """
38
63
  Provides methods for searching, downloading and uploading content in the knowledge base.
@@ -622,3 +647,51 @@ class ContentService:
622
647
  content_id=content_id,
623
648
  chat_id=chat_id,
624
649
  )
650
+
651
+ def get_documents_uploaded_to_chat(self) -> list[Content]:
652
+ chat_contents = self.search_contents(
653
+ where={
654
+ "ownerId": {
655
+ "equals": self._chat_id,
656
+ },
657
+ },
658
+ )
659
+
660
+ content: list[Content] = []
661
+ for c in chat_contents:
662
+ if self.is_file_content(c.key):
663
+ content.append(c)
664
+
665
+ return content
666
+
667
+ def get_images_uploaded_to_chat(self) -> list[Content]:
668
+ chat_contents = self.search_contents(
669
+ where={
670
+ "ownerId": {
671
+ "equals": self._chat_id,
672
+ },
673
+ },
674
+ )
675
+
676
+ content: list[Content] = []
677
+ for c in chat_contents:
678
+ if self.is_image_content(c.key):
679
+ content.append(c)
680
+
681
+ return content
682
+
683
+ def is_file_content(self, filename: str) -> bool:
684
+ mimetype, _ = mimetypes.guess_type(filename)
685
+
686
+ if not mimetype:
687
+ return False
688
+
689
+ return mimetype in FileMimeType.__members__.values()
690
+
691
+ def is_image_content(self, filename: str) -> bool:
692
+ mimetype, _ = mimetypes.guess_type(filename)
693
+
694
+ if not mimetype:
695
+ return False
696
+
697
+ return mimetype in ImageMimeType.__members__.values()
@@ -94,6 +94,7 @@ def complete(
94
94
 
95
95
  async def complete_async(
96
96
  company_id: str,
97
+ user_id: str,
97
98
  messages: LanguageModelMessages | list[ChatCompletionMessageParam],
98
99
  model_name: LanguageModelName | str,
99
100
  temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
@@ -142,6 +143,7 @@ async def complete_async(
142
143
  try:
143
144
  response = await unique_sdk.ChatCompletion.create_async(
144
145
  company_id=company_id,
146
+ user_id=user_id,
145
147
  model=model,
146
148
  messages=cast(
147
149
  "list[unique_sdk.Integrated.ChatCompletionRequestMessage]",
@@ -419,6 +421,7 @@ def complete_with_references(
419
421
 
420
422
  async def complete_with_references_async(
421
423
  company_id: str,
424
+ user_id: str,
422
425
  messages: LanguageModelMessages,
423
426
  model_name: LanguageModelName | str,
424
427
  content_chunks: list[ContentChunk] | None = None,
@@ -432,6 +435,7 @@ async def complete_with_references_async(
432
435
  # Use toolkit language model functions for chat completion
433
436
  response = await complete_async(
434
437
  company_id=company_id,
438
+ user_id=user_id,
435
439
  model_name=model_name,
436
440
  messages=messages,
437
441
  temperature=temperature,
@@ -261,6 +261,7 @@ class LanguageModelService:
261
261
 
262
262
  return await complete_async(
263
263
  company_id=self._company_id,
264
+ user_id=self._user_id,
264
265
  messages=messages,
265
266
  model_name=model_name,
266
267
  temperature=temperature,
@@ -276,6 +277,7 @@ class LanguageModelService:
276
277
  async def complete_async_util(
277
278
  cls,
278
279
  company_id: str,
280
+ user_id: str,
279
281
  messages: LanguageModelMessages,
280
282
  model_name: LanguageModelName | str,
281
283
  temperature: float = DEFAULT_COMPLETE_TEMPERATURE,
@@ -291,6 +293,7 @@ class LanguageModelService:
291
293
 
292
294
  return await complete_async(
293
295
  company_id=company_id,
296
+ user_id=user_id,
294
297
  messages=messages,
295
298
  model_name=model_name,
296
299
  temperature=temperature,
@@ -132,6 +132,7 @@ class Source(BaseModel):
132
132
  class ToolPrompts(BaseModel):
133
133
  name: str
134
134
  display_name: str
135
+ tool_system_prompt: str
135
136
  tool_description: str
136
137
  tool_format_information_for_system_prompt: str
137
138
  input_model: dict[str, Any]
@@ -109,6 +109,7 @@ class Tool(ABC, Generic[ConfigType]):
109
109
  name=self.name,
110
110
  display_name=self.display_name(),
111
111
  tool_description=self.tool_description().description,
112
+ tool_system_prompt=self.tool_description_for_system_prompt(),
112
113
  tool_format_information_for_system_prompt=self.tool_format_information_for_system_prompt(),
113
114
  input_model=self.tool_description_as_json(),
114
115
  )
@@ -1,5 +1,6 @@
1
1
  import asyncio
2
2
  from logging import Logger, getLogger
3
+ from typing import Any
3
4
 
4
5
  from pydantic import BaseModel, Field
5
6
 
@@ -18,13 +19,6 @@ from unique_toolkit.tools.tool_progress_reporter import ToolProgressReporter
18
19
  from unique_toolkit.tools.utils.execution.execution import Result, SafeTaskExecutor
19
20
 
20
21
 
21
- class ForcedToolOption:
22
- type: str = "function"
23
-
24
- def __init__(self, name: str):
25
- self.name = name
26
-
27
-
28
22
  class ToolManagerConfig(BaseModel):
29
23
  tools: list[ToolBuildConfig] = Field(
30
24
  default=[],
@@ -122,13 +116,20 @@ class ToolManager:
122
116
  return tool
123
117
  return None
124
118
 
125
- def get_forced_tools(self) -> list[ForcedToolOption]:
119
+ def get_forced_tools(self) -> list[dict[str, Any]]:
126
120
  return [
127
- ForcedToolOption(t.name)
121
+ self._convert_to_forced_tool(t.name)
128
122
  for t in self._tools
129
123
  if t.name in self._tool_choices
130
124
  ]
131
125
 
126
+ def add_forced_tool(self, name):
127
+ tool = self.get_tool_by_name(name)
128
+ if not tool:
129
+ raise ValueError(f"Tool {name} not found")
130
+ self._tools.append(tool)
131
+ self._tool_choices.append(tool.name)
132
+
132
133
  def get_tool_definitions(
133
134
  self,
134
135
  ) -> list[LanguageModelTool | LanguageModelToolDescription]:
@@ -198,7 +199,9 @@ class ToolManager:
198
199
  ) -> ToolCallResponse:
199
200
  self._logger.info(f"Processing tool call: {tool_call.name}")
200
201
 
201
- tool_instance = self.get_tool_by_name(tool_call.name)
202
+ tool_instance = self.get_tool_by_name(
203
+ tool_call.name
204
+ ) # we need to copy this as it will have problematic interference on multi calls.
202
205
 
203
206
  if tool_instance:
204
207
  # Execute the tool
@@ -254,3 +257,11 @@ class ToolManager:
254
257
  f"Filtered out {len(tool_calls) - len(unique_tool_calls)} duplicate tool calls."
255
258
  )
256
259
  return unique_tool_calls
260
+
261
+ from typing import Any
262
+
263
+ def _convert_to_forced_tool(self, tool_name: str) -> dict[str, Any]:
264
+ return {
265
+ "type": "function",
266
+ "function": {"name": tool_name},
267
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 0.8.19
3
+ Version: 0.8.21
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Martin Fadler
@@ -114,6 +114,14 @@ 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.21] - 2025-08-26
118
+ - Fixed old (not used) function "create_async" in language_model.functions : The function always returns "Unauthorized" --> Added "user_id" argument to fix this.
119
+
120
+ ## [0.8.20] - 2025-08-24
121
+ - Fixed forced-tool-calls
122
+
123
+ ## [0.8.20] - 2025-08-05
124
+ - Bump SDK version to support the latest features.
117
125
 
118
126
  ## [0.8.19] - 2025-08-24
119
127
  - Enforce usage of ruff using pipeline
@@ -27,7 +27,7 @@ unique_toolkit/content/__init__.py,sha256=EdJg_A_7loEtCQf4cah3QARQreJx6pdz89Rm96
27
27
  unique_toolkit/content/constants.py,sha256=1iy4Y67xobl5VTnJB6SxSyuoBWbdLl9244xfVMUZi5o,60
28
28
  unique_toolkit/content/functions.py,sha256=HZtDIAH3ZxWleq5Si_v30n_7vTnNRu6BCxpTHb9TxdA,18635
29
29
  unique_toolkit/content/schemas.py,sha256=KJ604BOx0vBh2AwlTCZkOo55aHsI6yj8vxDAARKKqEo,2995
30
- unique_toolkit/content/service.py,sha256=3zUu3vUcPV8Mb_v1TCyi2hicGVMLNBamKB3Q6-z1trY,21455
30
+ unique_toolkit/content/service.py,sha256=u4-9hXxali4eSpRtnjK93TunsV0YmB6EDqPY1rpnKQ4,23443
31
31
  unique_toolkit/content/utils.py,sha256=qNVmHTuETaPNGqheg7TbgPr1_1jbNHDc09N5RrmUIyo,7901
32
32
  unique_toolkit/debug_info_manager/debug_info_manager.py,sha256=7c2yb3ES0yu-SJy3o7EwpuCBGaq_8IOMEAvD-BQ-eLI,576
33
33
  unique_toolkit/embedding/__init__.py,sha256=uUyzjonPvuDCYsvXCIt7ErQXopLggpzX-MEQd3_e2kE,250
@@ -77,12 +77,12 @@ unique_toolkit/history_manager/utils.py,sha256=iu4LsYOElx8HlZjcx3ZC75I-TmEYBiEP9
77
77
  unique_toolkit/language_model/__init__.py,sha256=lRQyLlbwHbNFf4-0foBU13UGb09lwEeodbVsfsSgaCk,1971
78
78
  unique_toolkit/language_model/builder.py,sha256=4OKfwJfj3TrgO1ezc_ewIue6W7BCQ2ZYQXUckWVPPTA,3369
79
79
  unique_toolkit/language_model/constants.py,sha256=B-topqW0r83dkC_25DeQfnPk3n53qzIHUCBS7YJ0-1U,119
80
- unique_toolkit/language_model/functions.py,sha256=-nWgcscaZvEfuf2ftCQj8hyFY2RynPFO8XgX2gsN924,16665
80
+ unique_toolkit/language_model/functions.py,sha256=ByKA9AZVMxuGP0P52bEDk5Z6N7R45cXaCuBiHb7NZWc,16755
81
81
  unique_toolkit/language_model/infos.py,sha256=2WvhsgLDuiAuZ_gtV-aiRg1LafwXbHpiEMYYXWqdxWc,45703
82
82
  unique_toolkit/language_model/prompt.py,sha256=JSawaLjQg3VR-E2fK8engFyJnNdk21zaO8pPIodzN4Q,3991
83
83
  unique_toolkit/language_model/reference.py,sha256=nkX2VFz-IrUz8yqyc3G5jUMNwrNpxITBrMEKkbqqYoI,8583
84
84
  unique_toolkit/language_model/schemas.py,sha256=EOgy-p1GRcS46Sq0qEsN8MfOMl-KCcvEd9aCmqm9d08,16497
85
- unique_toolkit/language_model/service.py,sha256=N_I3VtK5B0G8s5c6TcBVWM7CcLGqakDhEdHQ_z-Hcok,11676
85
+ unique_toolkit/language_model/service.py,sha256=UOYYYO2xaN35mSc6d_lmkCrn9Iyj_ypm6rqvsONLAXY,11762
86
86
  unique_toolkit/language_model/utils.py,sha256=bPQ4l6_YO71w-zaIPanUUmtbXC1_hCvLK0tAFc3VCRc,1902
87
87
  unique_toolkit/postprocessor/postprocessor_manager.py,sha256=yf34VMwZfwGjmDbVeMJ5JN3ET4N68V39EF9kiWVUa_Y,4213
88
88
  unique_toolkit/protocols/support.py,sha256=V15WEIFKVMyF1QCnR8vIi4GrJy4dfTCB6d6JlqPZ58o,2341
@@ -98,16 +98,16 @@ unique_toolkit/smart_rules/compile.py,sha256=cxWjb2dxEI2HGsakKdVCkSNi7VK9mr08w5s
98
98
  unique_toolkit/thinking_manager/thinking_manager.py,sha256=AJfmrTXTr-DxBnJ2_zYYpYo57kr5deqT0LiZb8UdaDQ,4175
99
99
  unique_toolkit/tools/config.py,sha256=CHelTOEd2uqktK-bSYIyaqb9M1hKz8fy_DAR2mVzXpc,2985
100
100
  unique_toolkit/tools/factory.py,sha256=w3uNHuYBIJ330Xi8PTdAkr8G3OMbQH2cBgvk5UT16oE,1253
101
- unique_toolkit/tools/schemas.py,sha256=Zsrkh9RXY6n2GLrW-afzhsWRrU9uIMuZhfAs-s_4_Lo,4692
101
+ unique_toolkit/tools/schemas.py,sha256=PJBWN9NcEBSUmhrAMznbnw06ordrf4lfbhcxYZFmAOc,4720
102
102
  unique_toolkit/tools/test/test_tool_progress_reporter.py,sha256=GTtmBqOUo0-4fh_q0lRgxDhwKeankc3FHFD5ULZAm4Y,6299
103
- unique_toolkit/tools/tool.py,sha256=oMhGR_XdCP36L08LKHELpNwus4_UnC1klb_josM2-vM,5552
104
- unique_toolkit/tools/tool_manager.py,sha256=_kbB6dA1nyMM9D2YLARn8Ims25SOclOy1944Z0NVGcE,8895
103
+ unique_toolkit/tools/tool.py,sha256=zreY6fGBAfOIPNujWkl4cV5fBojjzGzVyvYuNLDrbzQ,5626
104
+ unique_toolkit/tools/tool_manager.py,sha256=vYGmNF9IvQoAG3N20TIbCpzmsJfoTFn_SVaENTJIk1w,9358
105
105
  unique_toolkit/tools/tool_progress_reporter.py,sha256=ixud9VoHey1vlU1t86cW0-WTvyTwMxNSWBon8I11SUk,7955
106
106
  unique_toolkit/tools/utils/execution/execution.py,sha256=vjG2Y6awsGNtlvyQAGCTthQ5thWHYnn-vzZXaYLb3QE,7922
107
107
  unique_toolkit/tools/utils/source_handling/schema.py,sha256=vzAyf6ZWNexjMO0OrnB8y2glGkvAilmGGQXd6zcDaKw,870
108
108
  unique_toolkit/tools/utils/source_handling/source_formatting.py,sha256=C7uayNbdkNVJdEARA5CENnHtNY1SU6etlaqbgHNyxaQ,9152
109
109
  unique_toolkit/tools/utils/source_handling/tests/test_source_formatting.py,sha256=oM5ZxEgzROrnX1229KViCAFjRxl9wCTzWZoinYSHleM,6979
110
- unique_toolkit-0.8.19.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
111
- unique_toolkit-0.8.19.dist-info/METADATA,sha256=AQgIWpBO6zd4H4cWtY8ML4t2Wdhq5AxdmbjUakFiRFs,28002
112
- unique_toolkit-0.8.19.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
113
- unique_toolkit-0.8.19.dist-info/RECORD,,
110
+ unique_toolkit-0.8.21.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
111
+ unique_toolkit-0.8.21.dist-info/METADATA,sha256=h58IrH1nT5r5bOi2fDSTXBFl8itzZo2Uq1foVlskhBI,28318
112
+ unique_toolkit-0.8.21.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
113
+ unique_toolkit-0.8.21.dist-info/RECORD,,