unique_toolkit 0.7.9__py3-none-any.whl → 1.33.3__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.
- unique_toolkit/__init__.py +36 -3
- unique_toolkit/_common/api_calling/human_verification_manager.py +357 -0
- unique_toolkit/_common/base_model_type_attribute.py +303 -0
- unique_toolkit/_common/chunk_relevancy_sorter/config.py +49 -0
- unique_toolkit/_common/chunk_relevancy_sorter/exception.py +5 -0
- unique_toolkit/_common/chunk_relevancy_sorter/schemas.py +46 -0
- unique_toolkit/_common/chunk_relevancy_sorter/service.py +374 -0
- unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +275 -0
- unique_toolkit/_common/default_language_model.py +12 -0
- unique_toolkit/_common/docx_generator/__init__.py +7 -0
- unique_toolkit/_common/docx_generator/config.py +12 -0
- unique_toolkit/_common/docx_generator/schemas.py +80 -0
- unique_toolkit/_common/docx_generator/service.py +225 -0
- unique_toolkit/_common/docx_generator/template/Doc Template.docx +0 -0
- unique_toolkit/_common/endpoint_builder.py +368 -0
- unique_toolkit/_common/endpoint_requestor.py +480 -0
- unique_toolkit/_common/exception.py +24 -0
- unique_toolkit/_common/experimental/endpoint_builder.py +368 -0
- unique_toolkit/_common/experimental/endpoint_requestor.py +488 -0
- unique_toolkit/_common/feature_flags/schema.py +9 -0
- unique_toolkit/_common/pydantic/rjsf_tags.py +936 -0
- unique_toolkit/_common/pydantic_helpers.py +174 -0
- unique_toolkit/_common/referencing.py +53 -0
- unique_toolkit/_common/string_utilities.py +140 -0
- unique_toolkit/_common/tests/test_referencing.py +521 -0
- unique_toolkit/_common/tests/test_string_utilities.py +506 -0
- unique_toolkit/_common/token/image_token_counting.py +67 -0
- unique_toolkit/_common/token/token_counting.py +204 -0
- unique_toolkit/_common/utils/__init__.py +1 -0
- unique_toolkit/_common/utils/files.py +43 -0
- unique_toolkit/_common/utils/image/encode.py +25 -0
- unique_toolkit/_common/utils/jinja/helpers.py +10 -0
- unique_toolkit/_common/utils/jinja/render.py +18 -0
- unique_toolkit/_common/utils/jinja/schema.py +65 -0
- unique_toolkit/_common/utils/jinja/utils.py +80 -0
- unique_toolkit/_common/utils/structured_output/__init__.py +1 -0
- unique_toolkit/_common/utils/structured_output/schema.py +5 -0
- unique_toolkit/_common/utils/write_configuration.py +51 -0
- unique_toolkit/_common/validators.py +101 -4
- unique_toolkit/agentic/__init__.py +1 -0
- unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +28 -0
- unique_toolkit/agentic/debug_info_manager/test/test_debug_info_manager.py +278 -0
- unique_toolkit/agentic/evaluation/config.py +36 -0
- unique_toolkit/{evaluators → agentic/evaluation}/context_relevancy/prompts.py +25 -0
- unique_toolkit/agentic/evaluation/context_relevancy/schema.py +80 -0
- unique_toolkit/agentic/evaluation/context_relevancy/service.py +273 -0
- unique_toolkit/agentic/evaluation/evaluation_manager.py +218 -0
- unique_toolkit/agentic/evaluation/hallucination/constants.py +61 -0
- unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +112 -0
- unique_toolkit/{evaluators → agentic/evaluation}/hallucination/prompts.py +1 -1
- unique_toolkit/{evaluators → agentic/evaluation}/hallucination/service.py +20 -16
- unique_toolkit/{evaluators → agentic/evaluation}/hallucination/utils.py +32 -21
- unique_toolkit/{evaluators → agentic/evaluation}/output_parser.py +20 -2
- unique_toolkit/{evaluators → agentic/evaluation}/schemas.py +27 -7
- unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +253 -0
- unique_toolkit/agentic/evaluation/tests/test_output_parser.py +87 -0
- unique_toolkit/agentic/history_manager/history_construction_with_contents.py +298 -0
- unique_toolkit/agentic/history_manager/history_manager.py +241 -0
- unique_toolkit/agentic/history_manager/loop_token_reducer.py +484 -0
- unique_toolkit/agentic/history_manager/utils.py +96 -0
- unique_toolkit/agentic/message_log_manager/__init__.py +5 -0
- unique_toolkit/agentic/message_log_manager/service.py +93 -0
- unique_toolkit/agentic/postprocessor/postprocessor_manager.py +212 -0
- unique_toolkit/agentic/reference_manager/reference_manager.py +103 -0
- unique_toolkit/agentic/responses_api/__init__.py +19 -0
- unique_toolkit/agentic/responses_api/postprocessors/code_display.py +71 -0
- unique_toolkit/agentic/responses_api/postprocessors/generated_files.py +297 -0
- unique_toolkit/agentic/responses_api/stream_handler.py +15 -0
- unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +141 -0
- unique_toolkit/agentic/thinking_manager/thinking_manager.py +103 -0
- unique_toolkit/agentic/tools/__init__.py +1 -0
- unique_toolkit/agentic/tools/a2a/__init__.py +36 -0
- unique_toolkit/agentic/tools/a2a/config.py +17 -0
- unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +15 -0
- unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +66 -0
- unique_toolkit/agentic/tools/a2a/evaluation/config.py +55 -0
- unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +260 -0
- unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +9 -0
- unique_toolkit/agentic/tools/a2a/manager.py +55 -0
- unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +21 -0
- unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py +240 -0
- unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py +84 -0
- unique_toolkit/agentic/tools/a2a/postprocessing/config.py +78 -0
- unique_toolkit/agentic/tools/a2a/postprocessing/display.py +264 -0
- unique_toolkit/agentic/tools/a2a/postprocessing/references.py +101 -0
- unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +421 -0
- unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display_utils.py +2103 -0
- unique_toolkit/agentic/tools/a2a/postprocessing/test/test_ref_utils.py +603 -0
- unique_toolkit/agentic/tools/a2a/prompts.py +46 -0
- unique_toolkit/agentic/tools/a2a/response_watcher/__init__.py +6 -0
- unique_toolkit/agentic/tools/a2a/response_watcher/service.py +91 -0
- unique_toolkit/agentic/tools/a2a/tool/__init__.py +4 -0
- unique_toolkit/agentic/tools/a2a/tool/_memory.py +26 -0
- unique_toolkit/agentic/tools/a2a/tool/_schema.py +9 -0
- unique_toolkit/agentic/tools/a2a/tool/config.py +158 -0
- unique_toolkit/agentic/tools/a2a/tool/service.py +393 -0
- unique_toolkit/agentic/tools/agent_chunks_hanlder.py +65 -0
- unique_toolkit/agentic/tools/config.py +128 -0
- unique_toolkit/agentic/tools/factory.py +44 -0
- unique_toolkit/agentic/tools/mcp/__init__.py +4 -0
- unique_toolkit/agentic/tools/mcp/manager.py +71 -0
- unique_toolkit/agentic/tools/mcp/models.py +28 -0
- unique_toolkit/agentic/tools/mcp/tool_wrapper.py +234 -0
- unique_toolkit/agentic/tools/openai_builtin/__init__.py +11 -0
- unique_toolkit/agentic/tools/openai_builtin/base.py +46 -0
- unique_toolkit/agentic/tools/openai_builtin/code_interpreter/__init__.py +8 -0
- unique_toolkit/agentic/tools/openai_builtin/code_interpreter/config.py +88 -0
- unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py +250 -0
- unique_toolkit/agentic/tools/openai_builtin/manager.py +79 -0
- unique_toolkit/agentic/tools/schemas.py +145 -0
- unique_toolkit/agentic/tools/test/test_mcp_manager.py +536 -0
- unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +445 -0
- unique_toolkit/agentic/tools/tool.py +187 -0
- unique_toolkit/agentic/tools/tool_manager.py +492 -0
- unique_toolkit/agentic/tools/tool_progress_reporter.py +285 -0
- unique_toolkit/agentic/tools/utils/__init__.py +19 -0
- unique_toolkit/agentic/tools/utils/execution/__init__.py +1 -0
- unique_toolkit/agentic/tools/utils/execution/execution.py +286 -0
- unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
- unique_toolkit/agentic/tools/utils/source_handling/schema.py +21 -0
- unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +207 -0
- unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +216 -0
- unique_toolkit/app/__init__.py +9 -0
- unique_toolkit/app/dev_util.py +180 -0
- unique_toolkit/app/fast_api_factory.py +131 -0
- unique_toolkit/app/init_sdk.py +32 -1
- unique_toolkit/app/schemas.py +206 -31
- unique_toolkit/app/unique_settings.py +367 -0
- unique_toolkit/app/webhook.py +77 -0
- unique_toolkit/chat/__init__.py +8 -1
- unique_toolkit/chat/deprecated/service.py +232 -0
- unique_toolkit/chat/functions.py +648 -78
- unique_toolkit/chat/rendering.py +34 -0
- unique_toolkit/chat/responses_api.py +461 -0
- unique_toolkit/chat/schemas.py +134 -2
- unique_toolkit/chat/service.py +115 -767
- unique_toolkit/content/functions.py +353 -8
- unique_toolkit/content/schemas.py +128 -15
- unique_toolkit/content/service.py +321 -45
- unique_toolkit/content/smart_rules.py +301 -0
- unique_toolkit/content/utils.py +10 -3
- unique_toolkit/data_extraction/README.md +96 -0
- unique_toolkit/data_extraction/__init__.py +11 -0
- unique_toolkit/data_extraction/augmented/__init__.py +5 -0
- unique_toolkit/data_extraction/augmented/service.py +93 -0
- unique_toolkit/data_extraction/base.py +25 -0
- unique_toolkit/data_extraction/basic/__init__.py +11 -0
- unique_toolkit/data_extraction/basic/config.py +18 -0
- unique_toolkit/data_extraction/basic/prompt.py +13 -0
- unique_toolkit/data_extraction/basic/service.py +55 -0
- unique_toolkit/embedding/service.py +103 -12
- unique_toolkit/framework_utilities/__init__.py +1 -0
- unique_toolkit/framework_utilities/langchain/__init__.py +10 -0
- unique_toolkit/framework_utilities/langchain/client.py +71 -0
- unique_toolkit/framework_utilities/langchain/history.py +19 -0
- unique_toolkit/framework_utilities/openai/__init__.py +6 -0
- unique_toolkit/framework_utilities/openai/client.py +84 -0
- unique_toolkit/framework_utilities/openai/message_builder.py +229 -0
- unique_toolkit/framework_utilities/utils.py +23 -0
- unique_toolkit/language_model/__init__.py +3 -0
- unique_toolkit/language_model/_responses_api_utils.py +93 -0
- unique_toolkit/language_model/builder.py +27 -11
- unique_toolkit/language_model/default_language_model.py +3 -0
- unique_toolkit/language_model/functions.py +345 -43
- unique_toolkit/language_model/infos.py +1288 -46
- unique_toolkit/language_model/reference.py +242 -0
- unique_toolkit/language_model/schemas.py +481 -49
- unique_toolkit/language_model/service.py +229 -28
- unique_toolkit/protocols/support.py +145 -0
- unique_toolkit/services/__init__.py +7 -0
- unique_toolkit/services/chat_service.py +1631 -0
- unique_toolkit/services/knowledge_base.py +1094 -0
- unique_toolkit/short_term_memory/service.py +178 -41
- unique_toolkit/smart_rules/__init__.py +0 -0
- unique_toolkit/smart_rules/compile.py +56 -0
- unique_toolkit/test_utilities/events.py +197 -0
- unique_toolkit-1.33.3.dist-info/METADATA +1145 -0
- unique_toolkit-1.33.3.dist-info/RECORD +205 -0
- unique_toolkit/evaluators/__init__.py +0 -1
- unique_toolkit/evaluators/config.py +0 -35
- unique_toolkit/evaluators/constants.py +0 -1
- unique_toolkit/evaluators/context_relevancy/constants.py +0 -32
- unique_toolkit/evaluators/context_relevancy/service.py +0 -53
- unique_toolkit/evaluators/context_relevancy/utils.py +0 -142
- unique_toolkit/evaluators/hallucination/constants.py +0 -41
- unique_toolkit-0.7.9.dist-info/METADATA +0 -413
- unique_toolkit-0.7.9.dist-info/RECORD +0 -64
- /unique_toolkit/{evaluators → agentic/evaluation}/exception.py +0 -0
- {unique_toolkit-0.7.9.dist-info → unique_toolkit-1.33.3.dist-info}/LICENSE +0 -0
- {unique_toolkit-0.7.9.dist-info → unique_toolkit-1.33.3.dist-info}/WHEEL +0 -0
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
from typing import overload
|
|
2
|
+
|
|
1
3
|
from typing_extensions import deprecated
|
|
2
4
|
|
|
3
5
|
from unique_toolkit._common._base_service import BaseService
|
|
4
6
|
from unique_toolkit._common.validate_required_values import validate_required_values
|
|
5
7
|
from unique_toolkit.app.schemas import BaseEvent, Event
|
|
8
|
+
from unique_toolkit.app.unique_settings import UniqueSettings
|
|
6
9
|
from unique_toolkit.embedding.constants import DEFAULT_TIMEOUT
|
|
7
10
|
from unique_toolkit.embedding.functions import embed_texts, embed_texts_async
|
|
8
11
|
from unique_toolkit.embedding.schemas import Embeddings
|
|
@@ -11,10 +14,23 @@ from unique_toolkit.embedding.schemas import Embeddings
|
|
|
11
14
|
class EmbeddingService(BaseService):
|
|
12
15
|
"""
|
|
13
16
|
Provides methods to interact with the Embedding service.
|
|
17
|
+
"""
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
company_id
|
|
17
|
-
|
|
19
|
+
@deprecated(
|
|
20
|
+
"Use __init__ with company_id and user_id instead or use the classmethod `from_event`"
|
|
21
|
+
)
|
|
22
|
+
@overload
|
|
23
|
+
def __init__(self, event: Event | BaseEvent): ...
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
Initialize the EmbeddingService with an event (deprecated)
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
@overload
|
|
30
|
+
def __init__(self, *, company_id: str, user_id: str): ...
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
Initialize the EmbeddingService with a company_id and user_id.
|
|
18
34
|
"""
|
|
19
35
|
|
|
20
36
|
def __init__(
|
|
@@ -25,12 +41,35 @@ class EmbeddingService(BaseService):
|
|
|
25
41
|
):
|
|
26
42
|
self._event = event
|
|
27
43
|
if event:
|
|
28
|
-
self.
|
|
29
|
-
self.
|
|
44
|
+
self._company_id: str = event.company_id
|
|
45
|
+
self._user_id: str = event.user_id
|
|
30
46
|
else:
|
|
31
47
|
[company_id, user_id] = validate_required_values([company_id, user_id])
|
|
32
|
-
self.
|
|
33
|
-
self.
|
|
48
|
+
self._company_id: str = company_id
|
|
49
|
+
self._user_id: str = user_id
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def from_event(cls, event: Event | BaseEvent):
|
|
53
|
+
"""
|
|
54
|
+
Initialize the EmbeddingService with an event.
|
|
55
|
+
"""
|
|
56
|
+
return cls(company_id=event.company_id, user_id=event.user_id)
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def from_settings(cls, settings: UniqueSettings | str | None = None):
|
|
60
|
+
"""
|
|
61
|
+
Initialize the EmbeddingService with a settings object.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
if settings is None:
|
|
65
|
+
settings = UniqueSettings.from_env_auto_with_sdk_init()
|
|
66
|
+
elif isinstance(settings, str):
|
|
67
|
+
settings = UniqueSettings.from_env_auto_with_sdk_init(filename=settings)
|
|
68
|
+
|
|
69
|
+
return cls(
|
|
70
|
+
company_id=settings.auth.company_id.get_secret_value(),
|
|
71
|
+
user_id=settings.auth.user_id.get_secret_value(),
|
|
72
|
+
)
|
|
34
73
|
|
|
35
74
|
@property
|
|
36
75
|
@deprecated(
|
|
@@ -45,6 +84,58 @@ class EmbeddingService(BaseService):
|
|
|
45
84
|
"""
|
|
46
85
|
return self._event
|
|
47
86
|
|
|
87
|
+
@property
|
|
88
|
+
@deprecated(
|
|
89
|
+
"The company_id property is deprecated and will be removed in a future version."
|
|
90
|
+
)
|
|
91
|
+
def company_id(self) -> str | None:
|
|
92
|
+
"""
|
|
93
|
+
Get the company identifier (deprecated).
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
str | None: The company identifier.
|
|
97
|
+
"""
|
|
98
|
+
return self._company_id
|
|
99
|
+
|
|
100
|
+
@company_id.setter
|
|
101
|
+
@deprecated(
|
|
102
|
+
"The company_id setter is deprecated and will be removed in a future version."
|
|
103
|
+
)
|
|
104
|
+
def company_id(self, value: str) -> None:
|
|
105
|
+
"""
|
|
106
|
+
Set the company identifier (deprecated).
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
value (str | None): The company identifier.
|
|
110
|
+
"""
|
|
111
|
+
self._company_id = value
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
@deprecated(
|
|
115
|
+
"The user_id property is deprecated and will be removed in a future version."
|
|
116
|
+
)
|
|
117
|
+
def user_id(self) -> str | None:
|
|
118
|
+
"""
|
|
119
|
+
Get the user identifier (deprecated).
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
str | None: The user identifier.
|
|
123
|
+
"""
|
|
124
|
+
return self._user_id
|
|
125
|
+
|
|
126
|
+
@user_id.setter
|
|
127
|
+
@deprecated(
|
|
128
|
+
"The user_id setter is deprecated and will be removed in a future version."
|
|
129
|
+
)
|
|
130
|
+
def user_id(self, value: str) -> None:
|
|
131
|
+
"""
|
|
132
|
+
Set the user identifier (deprecated).
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
value (str | None): The user identifier.
|
|
136
|
+
"""
|
|
137
|
+
self._user_id = value
|
|
138
|
+
|
|
48
139
|
def embed_texts(
|
|
49
140
|
self,
|
|
50
141
|
texts: list[str],
|
|
@@ -54,7 +145,7 @@ class EmbeddingService(BaseService):
|
|
|
54
145
|
Embed text.
|
|
55
146
|
|
|
56
147
|
Args:
|
|
57
|
-
|
|
148
|
+
texts (list[str]): The texts to embed.
|
|
58
149
|
timeout (int): The timeout in milliseconds. Defaults to 600000.
|
|
59
150
|
|
|
60
151
|
Returns:
|
|
@@ -64,8 +155,8 @@ class EmbeddingService(BaseService):
|
|
|
64
155
|
Exception: If an error occurs.
|
|
65
156
|
"""
|
|
66
157
|
return embed_texts(
|
|
67
|
-
user_id=self.
|
|
68
|
-
company_id=self.
|
|
158
|
+
user_id=self._user_id,
|
|
159
|
+
company_id=self._company_id,
|
|
69
160
|
texts=texts,
|
|
70
161
|
timeout=timeout,
|
|
71
162
|
)
|
|
@@ -89,8 +180,8 @@ class EmbeddingService(BaseService):
|
|
|
89
180
|
Exception: If an error occurs.
|
|
90
181
|
"""
|
|
91
182
|
return await embed_texts_async(
|
|
92
|
-
user_id=self.
|
|
93
|
-
company_id=self.
|
|
183
|
+
user_id=self._user_id,
|
|
184
|
+
company_id=self._company_id,
|
|
94
185
|
texts=texts,
|
|
95
186
|
timeout=timeout,
|
|
96
187
|
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Framework utilities for integrating with external frameworks."""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Langchain framework utilities."""
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
from .client import LangchainNotInstalledError, get_langchain_client
|
|
5
|
+
|
|
6
|
+
__all__ = ["get_langchain_client", "LangchainNotInstalledError"]
|
|
7
|
+
except (ImportError, Exception):
|
|
8
|
+
# If langchain is not installed, don't export anything
|
|
9
|
+
# This handles both ImportError and LangchainNotInstalledError
|
|
10
|
+
__all__ = []
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import importlib.util
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from typing_extensions import deprecated
|
|
5
|
+
|
|
6
|
+
from unique_toolkit.app.unique_settings import UniqueSettings
|
|
7
|
+
from unique_toolkit.framework_utilities.utils import get_default_headers
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger("toolkit.framework_utilities.langchain")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LangchainNotInstalledError(ImportError):
|
|
13
|
+
"""Raised when langchain-openai package is not installed but functionality requiring it is accessed."""
|
|
14
|
+
|
|
15
|
+
def __init__(self):
|
|
16
|
+
super().__init__(
|
|
17
|
+
"langchain-openai package is not installed. Install it with 'poetry install --with langchain'."
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if importlib.util.find_spec("langchain_openai") is not None:
|
|
22
|
+
from langchain_openai import ChatOpenAI
|
|
23
|
+
else:
|
|
24
|
+
raise LangchainNotInstalledError()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_langchain_client(
|
|
28
|
+
*,
|
|
29
|
+
unique_settings: UniqueSettings | None = None,
|
|
30
|
+
model: str = "AZURE_GPT_4o_2024_0806",
|
|
31
|
+
additional_headers: dict[str, str] | None = None,
|
|
32
|
+
) -> ChatOpenAI:
|
|
33
|
+
"""Get a Langchain ChatOpenAI client instance.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
unique_settings: UniqueSettings instance
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
ChatOpenAI client instance
|
|
40
|
+
|
|
41
|
+
Raises:
|
|
42
|
+
LangchainNotInstalledError: If langchain-openai package is not installed
|
|
43
|
+
"""
|
|
44
|
+
if unique_settings is None:
|
|
45
|
+
unique_settings = UniqueSettings.from_env_auto()
|
|
46
|
+
|
|
47
|
+
default_headers = get_default_headers(unique_settings.app, unique_settings.auth)
|
|
48
|
+
if additional_headers is not None:
|
|
49
|
+
default_headers.update(additional_headers)
|
|
50
|
+
|
|
51
|
+
return ChatOpenAI(
|
|
52
|
+
base_url=unique_settings.api.openai_proxy_url(),
|
|
53
|
+
default_headers=default_headers,
|
|
54
|
+
model=model,
|
|
55
|
+
api_key=unique_settings.app.key,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@deprecated("Use get_langchain_client instead")
|
|
60
|
+
def get_client(
|
|
61
|
+
unique_settings: UniqueSettings | None = None, model: str = "AZURE_GPT_4o_2024_0806"
|
|
62
|
+
) -> ChatOpenAI:
|
|
63
|
+
"""Get a Langchain ChatOpenAI client instance.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
unique_settings: UniqueSettings instance
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
ChatOpenAI client instance
|
|
70
|
+
"""
|
|
71
|
+
return get_client(unique_settings, model)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
|
|
2
|
+
|
|
3
|
+
from unique_toolkit.chat import ChatMessage as UniqueMessage
|
|
4
|
+
from unique_toolkit.chat import ChatMessageRole as UniqueRole
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def unique_history_to_langchain_history(
|
|
8
|
+
unique_history: list[UniqueMessage],
|
|
9
|
+
) -> list[BaseMessage]:
|
|
10
|
+
history = []
|
|
11
|
+
for m in unique_history:
|
|
12
|
+
if m.role == UniqueRole.ASSISTANT:
|
|
13
|
+
history.append(AIMessage(content=m.content or ""))
|
|
14
|
+
elif m.role == UniqueRole.USER:
|
|
15
|
+
history.append(HumanMessage(content=m.content or ""))
|
|
16
|
+
else:
|
|
17
|
+
raise Exception("Unknown message role.")
|
|
18
|
+
|
|
19
|
+
return history
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import importlib.util
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from unique_toolkit.app.unique_settings import UniqueSettings
|
|
5
|
+
from unique_toolkit.framework_utilities.utils import get_default_headers
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger("toolkit.framework_utilities.openai")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class OpenAINotInstalledError(ImportError):
|
|
11
|
+
"""Raised when OpenAI package is not installed but functionality requiring it is accessed."""
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
super().__init__(
|
|
15
|
+
"OpenAI package is not installed. Install it with 'poetry install --with openai'."
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
if importlib.util.find_spec("openai") is not None:
|
|
20
|
+
from openai import AsyncOpenAI, OpenAI
|
|
21
|
+
else:
|
|
22
|
+
raise OpenAINotInstalledError()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_openai_client(
|
|
26
|
+
*,
|
|
27
|
+
unique_settings: UniqueSettings | None = None,
|
|
28
|
+
additional_headers: dict[str, str] | None = None,
|
|
29
|
+
) -> OpenAI:
|
|
30
|
+
"""Get an OpenAI client instance.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
unique_settings (UniqueSettings | None): Optional UniqueSettings instance
|
|
34
|
+
additional_headers (dict[str, str] | None): Optional additional headers to add to the request
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
OpenAI client instance
|
|
38
|
+
|
|
39
|
+
Raises:
|
|
40
|
+
OpenAINotInstalledError: If OpenAI package is not installed
|
|
41
|
+
"""
|
|
42
|
+
if unique_settings is None:
|
|
43
|
+
unique_settings = UniqueSettings.from_env_auto()
|
|
44
|
+
|
|
45
|
+
default_headers = get_default_headers(unique_settings.app, unique_settings.auth)
|
|
46
|
+
if additional_headers is not None:
|
|
47
|
+
default_headers.update(additional_headers)
|
|
48
|
+
|
|
49
|
+
return OpenAI(
|
|
50
|
+
api_key="dummy_key",
|
|
51
|
+
base_url=unique_settings.api.openai_proxy_url(),
|
|
52
|
+
default_headers=default_headers,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def get_async_openai_client(
|
|
57
|
+
*,
|
|
58
|
+
unique_settings: UniqueSettings | None = None,
|
|
59
|
+
additional_headers: dict[str, str] | None = None,
|
|
60
|
+
) -> AsyncOpenAI:
|
|
61
|
+
"""Get an async OpenAI client instance.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
unique_settings: Optional UniqueSettings instance
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
AsyncOpenAI client instance
|
|
68
|
+
|
|
69
|
+
Raises:
|
|
70
|
+
OpenAINotInstalledError: If OpenAI package is not installed
|
|
71
|
+
"""
|
|
72
|
+
if unique_settings is None:
|
|
73
|
+
unique_settings = UniqueSettings.from_env_auto()
|
|
74
|
+
|
|
75
|
+
default_headers = get_default_headers(unique_settings.app, unique_settings.auth)
|
|
76
|
+
|
|
77
|
+
if additional_headers is not None:
|
|
78
|
+
default_headers.update(additional_headers)
|
|
79
|
+
|
|
80
|
+
return AsyncOpenAI(
|
|
81
|
+
api_key="dummy_key",
|
|
82
|
+
base_url=unique_settings.api.openai_proxy_url(),
|
|
83
|
+
default_headers=default_headers,
|
|
84
|
+
)
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import mimetypes
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Self, overload
|
|
6
|
+
|
|
7
|
+
from openai.types.chat.chat_completion_assistant_message_param import (
|
|
8
|
+
Audio,
|
|
9
|
+
ChatCompletionAssistantMessageParam,
|
|
10
|
+
ContentArrayOfContentPart,
|
|
11
|
+
FunctionCall,
|
|
12
|
+
)
|
|
13
|
+
from openai.types.chat.chat_completion_content_part_image_param import (
|
|
14
|
+
ChatCompletionContentPartImageParam,
|
|
15
|
+
ImageURL,
|
|
16
|
+
)
|
|
17
|
+
from openai.types.chat.chat_completion_content_part_param import (
|
|
18
|
+
ChatCompletionContentPartParam,
|
|
19
|
+
)
|
|
20
|
+
from openai.types.chat.chat_completion_content_part_text_param import (
|
|
21
|
+
ChatCompletionContentPartTextParam,
|
|
22
|
+
)
|
|
23
|
+
from openai.types.chat.chat_completion_developer_message_param import (
|
|
24
|
+
ChatCompletionDeveloperMessageParam,
|
|
25
|
+
)
|
|
26
|
+
from openai.types.chat.chat_completion_function_message_param import (
|
|
27
|
+
ChatCompletionFunctionMessageParam,
|
|
28
|
+
)
|
|
29
|
+
from openai.types.chat.chat_completion_message_param import ChatCompletionMessageParam
|
|
30
|
+
from openai.types.chat.chat_completion_message_tool_call_param import (
|
|
31
|
+
ChatCompletionMessageToolCallParam,
|
|
32
|
+
)
|
|
33
|
+
from openai.types.chat.chat_completion_system_message_param import (
|
|
34
|
+
ChatCompletionSystemMessageParam,
|
|
35
|
+
)
|
|
36
|
+
from openai.types.chat.chat_completion_tool_message_param import (
|
|
37
|
+
ChatCompletionToolMessageParam,
|
|
38
|
+
)
|
|
39
|
+
from openai.types.chat.chat_completion_user_message_param import (
|
|
40
|
+
ChatCompletionUserMessageParam,
|
|
41
|
+
)
|
|
42
|
+
from typing_extensions import Literal
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class OpenAIUserMessageBuilder:
|
|
46
|
+
def __init__(
|
|
47
|
+
self,
|
|
48
|
+
) -> None:
|
|
49
|
+
self._messages: list[ChatCompletionContentPartParam] = []
|
|
50
|
+
|
|
51
|
+
def append_text(self, content: str) -> Self:
|
|
52
|
+
part = ChatCompletionContentPartTextParam(
|
|
53
|
+
type="text",
|
|
54
|
+
text=content,
|
|
55
|
+
)
|
|
56
|
+
self._messages.append(part)
|
|
57
|
+
return self
|
|
58
|
+
|
|
59
|
+
@overload
|
|
60
|
+
def append_image(
|
|
61
|
+
self, *, url: str, detail: Literal["auto", "low", "high"] = "auto"
|
|
62
|
+
) -> Self: ...
|
|
63
|
+
|
|
64
|
+
@overload
|
|
65
|
+
def append_image(
|
|
66
|
+
self, *, path: Path, detail: Literal["auto", "low", "high"] = "auto"
|
|
67
|
+
) -> Self: ...
|
|
68
|
+
|
|
69
|
+
@overload
|
|
70
|
+
def append_image(
|
|
71
|
+
self,
|
|
72
|
+
*,
|
|
73
|
+
content: bytes,
|
|
74
|
+
mime_type: str,
|
|
75
|
+
detail: Literal["auto", "low", "high"] = "auto",
|
|
76
|
+
) -> Self: ...
|
|
77
|
+
|
|
78
|
+
def append_image(
|
|
79
|
+
self,
|
|
80
|
+
*,
|
|
81
|
+
url: str | None = None,
|
|
82
|
+
path: Path | None = None,
|
|
83
|
+
content: bytes | None = None,
|
|
84
|
+
mime_type: str | None = None,
|
|
85
|
+
detail: Literal["auto", "low", "high"] = "auto",
|
|
86
|
+
) -> Self:
|
|
87
|
+
if url is None and path is None and (content is None or mime_type is None):
|
|
88
|
+
raise ValueError("Either url or path must be provided")
|
|
89
|
+
|
|
90
|
+
if path is not None:
|
|
91
|
+
# Read image file and encode as base64 data URI
|
|
92
|
+
image_data = path.read_bytes()
|
|
93
|
+
base64_image = base64.b64encode(image_data).decode("utf-8")
|
|
94
|
+
mime_type = mimetypes.guess_type(str(path))[0] or "image/jpeg"
|
|
95
|
+
url = f"data:{mime_type};base64,{base64_image}"
|
|
96
|
+
|
|
97
|
+
if content is not None and mime_type is not None:
|
|
98
|
+
base64_image = base64.b64encode(content).decode("utf-8")
|
|
99
|
+
url = f"data:{mime_type};base64,{base64_image}"
|
|
100
|
+
|
|
101
|
+
image_url = ImageURL(url=url or "", detail=detail)
|
|
102
|
+
part = ChatCompletionContentPartImageParam(
|
|
103
|
+
type="image_url",
|
|
104
|
+
image_url=image_url,
|
|
105
|
+
)
|
|
106
|
+
self._messages.append(part)
|
|
107
|
+
return self
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def user_message(self) -> ChatCompletionUserMessageParam:
|
|
111
|
+
return ChatCompletionUserMessageParam(
|
|
112
|
+
content=self._messages,
|
|
113
|
+
role="user",
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def iterable_content(self) -> Iterable[ChatCompletionContentPartParam]:
|
|
118
|
+
return self._messages
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class OpenAIMessageBuilder:
|
|
122
|
+
def __init__(
|
|
123
|
+
self,
|
|
124
|
+
messages: list[ChatCompletionMessageParam] | None = None,
|
|
125
|
+
) -> None:
|
|
126
|
+
self._messages: list[ChatCompletionMessageParam] = []
|
|
127
|
+
if messages:
|
|
128
|
+
self._messages = messages
|
|
129
|
+
|
|
130
|
+
@classmethod
|
|
131
|
+
def from_messages(cls, messages: list[ChatCompletionMessageParam]) -> Self:
|
|
132
|
+
builder = cls()
|
|
133
|
+
builder._messages = messages.copy()
|
|
134
|
+
return builder
|
|
135
|
+
|
|
136
|
+
def append(self, message: ChatCompletionMessageParam):
|
|
137
|
+
self._messages.append(message)
|
|
138
|
+
|
|
139
|
+
def system_message_append(
|
|
140
|
+
self,
|
|
141
|
+
content: str | Iterable[ChatCompletionContentPartTextParam],
|
|
142
|
+
name: str = "system",
|
|
143
|
+
) -> Self:
|
|
144
|
+
self._messages.append(
|
|
145
|
+
ChatCompletionSystemMessageParam(
|
|
146
|
+
content=content,
|
|
147
|
+
role="system",
|
|
148
|
+
),
|
|
149
|
+
)
|
|
150
|
+
return self
|
|
151
|
+
|
|
152
|
+
def user_message_append(
|
|
153
|
+
self,
|
|
154
|
+
content: str | Iterable[ChatCompletionContentPartParam],
|
|
155
|
+
name: str = "user",
|
|
156
|
+
) -> Self:
|
|
157
|
+
self._messages.append(
|
|
158
|
+
ChatCompletionUserMessageParam(
|
|
159
|
+
content=content,
|
|
160
|
+
role="user",
|
|
161
|
+
),
|
|
162
|
+
)
|
|
163
|
+
return self
|
|
164
|
+
|
|
165
|
+
def assistant_message_append(
|
|
166
|
+
self,
|
|
167
|
+
content: str | Iterable[ContentArrayOfContentPart] | None = None,
|
|
168
|
+
name: str = "assistant",
|
|
169
|
+
audio: Audio | None = None,
|
|
170
|
+
function_call: FunctionCall | None = None,
|
|
171
|
+
refusal: str | None = None,
|
|
172
|
+
tool_calls: Iterable[ChatCompletionMessageToolCallParam] | None = None,
|
|
173
|
+
) -> Self:
|
|
174
|
+
self._messages.append(
|
|
175
|
+
ChatCompletionAssistantMessageParam(
|
|
176
|
+
content=content,
|
|
177
|
+
role="assistant",
|
|
178
|
+
audio=audio,
|
|
179
|
+
function_call=function_call,
|
|
180
|
+
refusal=refusal,
|
|
181
|
+
tool_calls=tool_calls or [],
|
|
182
|
+
),
|
|
183
|
+
)
|
|
184
|
+
return self
|
|
185
|
+
|
|
186
|
+
def developper_message_append(
|
|
187
|
+
self,
|
|
188
|
+
content: str | Iterable[ChatCompletionContentPartTextParam],
|
|
189
|
+
name: str = "developer",
|
|
190
|
+
) -> Self:
|
|
191
|
+
self._messages.append(
|
|
192
|
+
ChatCompletionDeveloperMessageParam(
|
|
193
|
+
content=content,
|
|
194
|
+
role="developer",
|
|
195
|
+
),
|
|
196
|
+
)
|
|
197
|
+
return self
|
|
198
|
+
|
|
199
|
+
def function_message_append(
|
|
200
|
+
self,
|
|
201
|
+
content: str | None,
|
|
202
|
+
name: str = "function",
|
|
203
|
+
) -> Self:
|
|
204
|
+
self._messages.append(
|
|
205
|
+
ChatCompletionFunctionMessageParam(
|
|
206
|
+
content=content,
|
|
207
|
+
role="function",
|
|
208
|
+
name=name,
|
|
209
|
+
),
|
|
210
|
+
)
|
|
211
|
+
return self
|
|
212
|
+
|
|
213
|
+
def tool_message_append(
|
|
214
|
+
self,
|
|
215
|
+
content: str | Iterable[ChatCompletionContentPartTextParam],
|
|
216
|
+
tool_call_id: str,
|
|
217
|
+
) -> Self:
|
|
218
|
+
self._messages.append(
|
|
219
|
+
ChatCompletionToolMessageParam(
|
|
220
|
+
content=content,
|
|
221
|
+
role="tool",
|
|
222
|
+
tool_call_id=tool_call_id,
|
|
223
|
+
),
|
|
224
|
+
)
|
|
225
|
+
return self
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def messages(self) -> list[ChatCompletionMessageParam]:
|
|
229
|
+
return self._messages
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from unique_toolkit.app.unique_settings import UniqueApp, UniqueAuth
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def auth_headers(auth_settings: UniqueAuth) -> dict[str, str]:
|
|
5
|
+
return {
|
|
6
|
+
"x-user-id": auth_settings.user_id.get_secret_value(),
|
|
7
|
+
"x-company-id": auth_settings.company_id.get_secret_value(),
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def app_headers(app_settings: UniqueApp) -> dict[str, str]:
|
|
12
|
+
return {
|
|
13
|
+
"x-app-id": app_settings.id.get_secret_value(),
|
|
14
|
+
"Authorization": f"Bearer {app_settings.key.get_secret_value()}",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_default_headers(app_settings: UniqueApp, auth_settings: UniqueAuth):
|
|
19
|
+
default_headers = {}
|
|
20
|
+
default_headers.update(app_headers(app_settings))
|
|
21
|
+
default_headers.update(auth_headers(auth_settings))
|
|
22
|
+
default_headers["x-api-version"] = "2023-12-06"
|
|
23
|
+
return default_headers
|
|
@@ -43,6 +43,9 @@ from .schemas import (
|
|
|
43
43
|
from .schemas import (
|
|
44
44
|
LanguageModelTool as LanguageModelTool,
|
|
45
45
|
)
|
|
46
|
+
from .schemas import (
|
|
47
|
+
LanguageModelToolDescription as LanguageModelToolDescription,
|
|
48
|
+
)
|
|
46
49
|
from .schemas import (
|
|
47
50
|
LanguageModelToolMessage as LanguageModelToolMessage,
|
|
48
51
|
)
|