Skip to content

Commit de83b58

Browse files
committed
Merge branch 'release/14.7'
2 parents 137e766 + 5c15614 commit de83b58

7 files changed

Lines changed: 406 additions & 17 deletions

File tree

HISTORY.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ Changelog
22
==========
33

44

5+
14.7.3 (2026-08-03)
6+
-------------------
7+
8+
* Initial release for DSS 14.7.3
9+
510
14.7.2 (2026-07-13)
611
-------------------
712

dataikuapi/dss/agent_tool.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def id(self):
6464
"""
6565
return self.tool_id
6666

67-
def get_descriptor(self):
67+
def get_descriptor(self, context=None):
6868
"""
6969
Get the descriptor of the tool
7070
@@ -73,7 +73,10 @@ def get_descriptor(self):
7373
"""
7474

7575
if self._descriptor is None:
76-
self._descriptor = self.client._perform_json("GET", "/projects/%s/agents/tools/%s/descriptor" % (self.project_key, self.tool_id))
76+
if context is None:
77+
self._descriptor = self.client._perform_json("GET", "/projects/%s/agents/tools/%s/descriptor" % (self.project_key, self.tool_id))
78+
else:
79+
self._descriptor = self.client._perform_json("POST", "/projects/%s/agents/tools/%s/descriptor" % (self.project_key, self.tool_id), body={"context": context})
7780
return self._descriptor
7881

7982
def get_settings(self):

dataikuapi/dss/langchain/embeddings.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,25 @@
22
import asyncio
33
import concurrent
44
import logging
5-
import threading
5+
import threading
6+
import itertools
67

78
from typing import Callable, List, Any, Union
89

910
import pydantic
11+
12+
_thread_pool_executor_counter = itertools.count().__next__
13+
14+
def next_thread_pool_executor_prefix(prefix):
15+
return "{}-{}".format(prefix, _thread_pool_executor_counter())
16+
1017
try:
1118
from langchain_core.embeddings.embeddings import Embeddings
1219
except ModuleNotFoundError:
1320
from langchain.embeddings.base import Embeddings
1421
from langchain_core.callbacks import BaseCallbackHandler, LLMManagerMixin
22+
23+
1524
from dataikuapi.dss.llm_tracing import new_trace, SpanBuilder
1625

1726
from dataikuapi.dss.langchain.utils import must_use_deprecated_pydantic_config
@@ -121,7 +130,7 @@ def embed_documents(self, texts: List[str]) -> List[List[float]]:
121130

122131
async def aembed_documents(self, texts: List[str]) -> List[List[float]]:
123132
loop = asyncio.get_event_loop()
124-
with concurrent.futures.ThreadPoolExecutor() as executor:
133+
with concurrent.futures.ThreadPoolExecutor(thread_name_prefix=next_thread_pool_executor_prefix("DKUEmbeddingsAsyncExecutor")) as executor:
125134
result = await loop.run_in_executor(executor, self.embed_documents, texts)
126135
return result
127136

dataikuapi/dss/llm.py

Lines changed: 146 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ def add_image(self, image, text = None):
199199
def new_guardrail(self, type):
200200
"""
201201
Start adding a guardrail to the request. You need to configure the returned object, and call add() to actually add it
202+
203+
:rtype: :class:`DSSLLMRequestGuardrailBuilder`
202204
"""
203205
return DSSLLMRequestGuardrailBuilder(self, type)
204206

@@ -420,15 +422,27 @@ def with_structured_output(self, model_type, strict=None, compatible=None):
420422

421423

422424
class DSSLLMRequestGuardrailBuilder(object):
425+
"""
426+
.. important::
427+
Do not create this class directly, use :meth:`dataikuapi.dss.llm.DSSLLMCompletionQuery.new_guardrail`,
428+
:meth:`dataikuapi.dss.llm.DSSLLMCompletionsQuery.new_guardrail`, :meth:`dataikuapi.dss.llm.DSSLLMEmbeddingsQuery.new_guardrail` or
429+
:meth:`dataikuapi.dss.llm.DSSLLMImageGenerationQuery.new_guardrail`.
430+
"""
431+
423432
def __init__(self, request, type):
424433
self.request = request
425-
self.guardrail = { "type" : type, "enabled": True, "params" : {}}
434+
self.guardrail = {"type" : type, "enabled": True, "params" : {}}
426435

427436
@property
428437
def params(self):
438+
"""
439+
:return: The parameters of this guardrail
440+
:rtype: dict
441+
"""
429442
return self.guardrail["params"]
430443

431444
def add(self):
445+
"""Add this guardrail to the completion query"""
432446
if self.request._guardrails is None:
433447
self.request._guardrails = {"guardrails" : []}
434448
self.request._guardrails["guardrails"].append(self.guardrail)
@@ -537,6 +551,8 @@ def settings(self):
537551
def new_guardrail(self, type):
538552
"""
539553
Start adding a guardrail to the request. You need to configure the returned object, and call add() to actually add it
554+
555+
:rtype: :class:`DSSLLMRequestGuardrailBuilder`
540556
"""
541557
return DSSLLMRequestGuardrailBuilder(self, type)
542558

@@ -638,6 +654,8 @@ def new_completion(self):
638654
def new_guardrail(self, type):
639655
"""
640656
Start adding a guardrail to the request. You need to configure the returned object, and call add() to actually add it
657+
658+
:rtype: :class:`DSSLLMRequestGuardrailBuilder`
641659
"""
642660
return DSSLLMRequestGuardrailBuilder(self, type)
643661

@@ -664,7 +682,7 @@ def execute(self):
664682
return DSSLLMCompletionsResponse(ret["responses"], response_parser=self._response_parser)
665683

666684

667-
class DSSLLMCompletionQueryMultipartBuilder(object):
685+
class _DSSLLMCompletionQueryMultipartBuilder(object):
668686
def __init__(self):
669687
self.parts = []
670688

@@ -681,6 +699,8 @@ def _encode_image(image):
681699
def with_text(self, text):
682700
"""
683701
Add a text part to the multipart message
702+
703+
:param str text: The text to add
684704
"""
685705
self.parts.append({"type": "TEXT", "text": text})
686706
return self
@@ -692,7 +712,7 @@ def with_inline_image(self, image, mime_type=None):
692712
:param Union[str, bytes] image: The image
693713
:param str mime_type: None for default
694714
"""
695-
img_b64 = DSSLLMCompletionQueryMultipartMessage._encode_image(image)
715+
img_b64 = _DSSLLMCompletionQueryMultipartBuilder._encode_image(image)
696716

697717
part = {
698718
"type": "IMAGE_INLINE",
@@ -713,7 +733,7 @@ def with_captioned_image_inline(self, caption, image, mime_type=None):
713733
:param Union[str, bytes] image: The image
714734
:param str mime_type: None for default
715735
"""
716-
img_b64 = DSSLLMCompletionQueryMultipartMessage._encode_image(image)
736+
img_b64 = _DSSLLMCompletionQueryMultipartBuilder._encode_image(image)
717737

718738
image_part = {
719739
"type": "IMAGE_INLINE",
@@ -736,14 +756,13 @@ def with_image_url(self, image):
736756
"""
737757
Add an image url part to the multipart message
738758
739-
:param image: str the image url
759+
:param str image: the image url
740760
"""
741-
742761
self.parts.append({"type": "IMAGE_URI", "imageUrl": image})
743762
return self
744763

745764

746-
class DSSLLMCompletionQueryMultipartMessage(DSSLLMCompletionQueryMultipartBuilder):
765+
class DSSLLMCompletionQueryMultipartMessage(_DSSLLMCompletionQueryMultipartBuilder):
747766
"""
748767
.. important::
749768
Do not create this class directly, use :meth:`dataikuapi.dss.llm.DSSLLMCompletionQuery.new_multipart_message` or
@@ -761,8 +780,43 @@ def add(self):
761780
self.q.cq["messages"].append(self.msg)
762781
return self.q
763782

783+
def with_text(self, text):
784+
"""
785+
Add a text part to the multipart message
786+
787+
:param str text: The text to add
788+
"""
789+
return super().with_text(text)
790+
791+
def with_inline_image(self, image, mime_type=None):
792+
"""
793+
Add an image part to the multipart message
794+
795+
:param Union[str, bytes] image: The image
796+
:param str mime_type: None for default
797+
"""
798+
return super().with_inline_image(image, mime_type)
764799

765-
class DSSLLMCompletionQueryMultipartToolOutput(DSSLLMCompletionQueryMultipartBuilder):
800+
def with_captioned_image_inline(self, caption, image, mime_type=None):
801+
"""
802+
Add a captioned image part to the multipart message
803+
804+
:param str caption: Image caption
805+
:param Union[str, bytes] image: The image
806+
:param str mime_type: None for default
807+
"""
808+
return super().with_captioned_image_inline(caption, image, mime_type)
809+
810+
def with_image_url(self, image):
811+
"""
812+
Add an image url part to the multipart message
813+
814+
:param str image: The image url
815+
"""
816+
return super().with_image_url(image)
817+
818+
819+
class DSSLLMCompletionQueryMultipartToolOutput(_DSSLLMCompletionQueryMultipartBuilder):
766820
"""
767821
.. important::
768822
Do not create this class directly, use :meth:`dataikuapi.dss.llm.DSSLLMCompletionQuery.new_multipart_tool_output` or
@@ -787,41 +841,107 @@ def add(self):
787841
self.q.cq["messages"].append(self.msg)
788842
return self.q
789843

844+
def with_text(self, text):
845+
"""
846+
Add a text part to the multipart tool output
847+
848+
:param str text: The text to add
849+
"""
850+
return super().with_text(text)
851+
852+
def with_inline_image(self, image, mime_type=None):
853+
"""
854+
Add an image part to the multipart tool output
855+
856+
:param Union[str, bytes] image: The image
857+
:param str mime_type: None for default
858+
"""
859+
return super().with_inline_image(image, mime_type)
860+
861+
def with_captioned_image_inline(self, caption, image, mime_type=None):
862+
"""
863+
Add a captioned image part to the multipart tool output
864+
865+
:param str caption: Image caption
866+
:param Union[str, bytes] image: The image
867+
:param str mime_type: None for default
868+
"""
869+
return super().with_captioned_image_inline(caption, image, mime_type)
870+
871+
def with_image_url(self, image):
872+
"""
873+
Add an image url part to the multipart tool output
874+
875+
:param str image: The image url
876+
"""
877+
return super().with_image_url(image)
878+
790879

791880
class DSSLLMStreamedCompletionChunk(object):
881+
"""
882+
A handle to interact with a streamed completion query chunk.
883+
884+
.. important::
885+
Do not create this class directly, iterate over a :class:`dataikuapi.dss.llm.DSSLLMStreamedCompletionChunks` iterator instead to generate the chunks instead.
886+
"""
887+
792888
def __init__(self, data):
793889
self.data = data
794890

795891
@property
796892
def type(self):
797-
"""Type of this chunk, either "content" or "event" """
893+
"""
894+
:return: Type of this chunk, either "content" or "event"
895+
:rtype: Literal["content", "event"]
896+
"""
798897
return self.data.get("type", "content")
799898

800899
@property
801900
def text(self):
802-
"""If this chunk is content and has text, the (partial) text"""
901+
"""
902+
:return: If this chunk is content and has text, the (partial) text
903+
:rtype: bool
904+
"""
803905
return self.data.get("text", None)
804906

805907
@property
806908
def event_kind(self):
807-
"""If this chunk is an event, its kind"""
909+
"""
910+
:return: If this chunk is an event, its kind
911+
:rtype: str
912+
"""
808913
return self.data.get("eventKind", None)
809914

810915
def __repr__(self):
811916
return "<completion-chunk: %s>" % self.data
812917

813918

814919
class DSSLLMStreamedCompletionFooter(object):
920+
"""
921+
A handle to interact with a streamed completion query footer.
922+
923+
.. important::
924+
Do not create this class directly, iterate over a :class:`dataikuapi.dss.llm.DSSLLMStreamedCompletionChunks` iterator instead to generate the chunks instead.
925+
"""
926+
815927
def __init__(self, data):
816928
self.data = data
817929

818930
# Compatibility for code that just checks for "type""
819931
@property
820932
def type(self):
933+
"""
934+
:return: Type of this chunk, to distinguish it from :class:`dataikuapi.dss.llm.DSSLLMStreamedCompletionChunk` chunks. Can only be "footer"
935+
:rtype: Literal["footer"]
936+
"""
821937
return "footer"
822938

823939
@property
824940
def trace(self):
941+
"""
942+
:return: The trace of the completion query if available, None otherwise.
943+
:rtype: Union[dict, None]
944+
"""
825945
return self.data.get("trace", None)
826946

827947
@property
@@ -890,7 +1010,11 @@ def iterevents(self):
8901010

8911011
class DSSLLMCompletionResponse(object):
8921012
"""
893-
Response to a completion
1013+
A handle to interact with a completion query result.
1014+
1015+
.. important::
1016+
Do not create this class directly, use :meth:`dataikuapi.dss.llm.DSSLLMCompletionQuery.execute` or
1017+
:attr:`dataikuapi.dss.llm.DSSLLMCompletionsResponse.responses` or :attr:`dataikuapi.dss.llm.DSSLLMStreamedCompletionChunks.response` instead.
8941018
"""
8951019
def __init__(self, raw_resp=None, text=None, finish_reason=None, response_parser=None, trace=None, query=None):
8961020
if raw_resp is not None:
@@ -990,6 +1114,10 @@ def context_upsert(self):
9901114

9911115
@property
9921116
def trace(self):
1117+
"""
1118+
:return: The trace of the completion query if available, None otherwise.
1119+
:rtype: Union[dict, None]
1120+
"""
9931121
return self._raw.get("trace", None)
9941122

9951123
@property
@@ -1157,6 +1285,8 @@ def with_mask(self, mode, image=None):
11571285
def new_guardrail(self, type):
11581286
"""
11591287
Start adding a guardrail to the request. You need to configure the returned object, and call add() to actually add it
1288+
1289+
:rtype: :class:`DSSLLMRequestGuardrailBuilder`
11601290
"""
11611291
return DSSLLMRequestGuardrailBuilder(self, type)
11621292

@@ -1381,6 +1511,10 @@ def images(self):
13811511

13821512
@property
13831513
def trace(self):
1514+
"""
1515+
:return: The trace of the image generation query if available, None otherwise.
1516+
:rtype: Union[dict, None]
1517+
"""
13841518
return self._raw.get("trace", None)
13851519

13861520
@property

0 commit comments

Comments
 (0)