uipath-langchain-client 1.0.0__tar.gz → 1.0.2__tar.gz
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.
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/CHANGELOG.md +14 -4
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/PKG-INFO +2 -2
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/pyproject.toml +1 -1
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/__version__.py +1 -1
- uipath_langchain_client-1.0.2/src/uipath_langchain_client/clients/google/chat_models.py +60 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/openai/embeddings.py +2 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/vertexai/chat_models.py +4 -0
- uipath_langchain_client-1.0.0/src/uipath_langchain_client/clients/google/chat_models.py +0 -203
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/.gitignore +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/README.md +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/demo.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/__init__.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/base_client.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/anthropic/__init__.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/anthropic/chat_models.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/azure/__init__.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/azure/chat_models.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/azure/embeddings.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/bedrock/__init__.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/bedrock/chat_models.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/bedrock/embeddings.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/bedrock/utils.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/google/__init__.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/google/embeddings.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/normalized/__init__.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/normalized/chat_models.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/normalized/embeddings.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/openai/__init__.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/openai/chat_models.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/clients/vertexai/__init__.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/factory.py +0 -0
- {uipath_langchain_client-1.0.0 → uipath_langchain_client-1.0.2}/src/uipath_langchain_client/settings.py +0 -0
|
@@ -2,7 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `uipath_langchain_client` will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## [1.0.
|
|
5
|
+
## [1.0.2] - 2026-02-02
|
|
6
|
+
|
|
7
|
+
### Buf Fix
|
|
8
|
+
- Removed old fix on Gemini streaming and updated with a new cleaner one
|
|
9
|
+
|
|
10
|
+
## [1.0.1] - 2026-02-02
|
|
11
|
+
|
|
12
|
+
### Bug Fix
|
|
13
|
+
- Fixed Api Version on OpenAI Embeddings
|
|
14
|
+
|
|
15
|
+
## [1.0.0] - 2026-01-30
|
|
6
16
|
|
|
7
17
|
### Official Release
|
|
8
18
|
- First stable release of the UiPath LangChain Client
|
|
@@ -15,7 +25,7 @@ All notable changes to `uipath_langchain_client` will be documented in this file
|
|
|
15
25
|
- Comprehensive support for chat completions, embeddings, and streaming
|
|
16
26
|
- Seamless integration with both AgentHub and LLMGateway backends
|
|
17
27
|
|
|
18
|
-
## [0.3.x] -
|
|
28
|
+
## [0.3.x] - 2026-01-29
|
|
19
29
|
|
|
20
30
|
### Release
|
|
21
31
|
- First public release of the UiPath LangChain Client
|
|
@@ -39,7 +49,7 @@ All notable changes to `uipath_langchain_client` will be documented in this file
|
|
|
39
49
|
- Vertex AI
|
|
40
50
|
- Azure AI
|
|
41
51
|
|
|
42
|
-
## [0.2.x] -
|
|
52
|
+
## [0.2.x] - 2026-01-15
|
|
43
53
|
|
|
44
54
|
### Architecture
|
|
45
55
|
- Extracted from monolithic package into dedicated LangChain integration package
|
|
@@ -72,7 +82,7 @@ All notable changes to `uipath_langchain_client` will be documented in this file
|
|
|
72
82
|
- Package renamed from internal module to `uipath_langchain_client`
|
|
73
83
|
- Import paths changed; update imports accordingly
|
|
74
84
|
|
|
75
|
-
## [0.1.x] -
|
|
85
|
+
## [0.1.x] - 2025-12-20
|
|
76
86
|
|
|
77
87
|
### Initial Development Release
|
|
78
88
|
- LangChain-compatible chat models wrapping UiPath LLM services
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uipath-langchain-client
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: LangChain-compatible chat models and embeddings for UiPath's LLM services
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Requires-Dist: langchain>=1.2.7
|
|
7
|
-
Requires-Dist: uipath-llm-client>=1.0.
|
|
7
|
+
Requires-Dist: uipath-llm-client>=1.0.2
|
|
8
8
|
Provides-Extra: all
|
|
9
9
|
Requires-Dist: langchain-anthropic>=1.3.1; extra == 'all'
|
|
10
10
|
Requires-Dist: langchain-aws>=1.2.1; extra == 'all'
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from typing import Self
|
|
2
|
+
|
|
3
|
+
from httpx import URL, Request
|
|
4
|
+
from pydantic import Field, model_validator
|
|
5
|
+
from uipath_langchain_client.base_client import UiPathBaseLLMClient
|
|
6
|
+
from uipath_langchain_client.settings import UiPathAPIConfig
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from langchain_google_genai.chat_models import ChatGoogleGenerativeAI
|
|
10
|
+
|
|
11
|
+
from google.genai.client import Client
|
|
12
|
+
from google.genai.types import HttpOptions
|
|
13
|
+
except ImportError as e:
|
|
14
|
+
raise ImportError(
|
|
15
|
+
"The 'google' extra is required to use UiPathChatGoogleGenerativeAI. "
|
|
16
|
+
"Install it with: uv add uipath-langchain-client[google]"
|
|
17
|
+
) from e
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class UiPathChatGoogleGenerativeAI(UiPathBaseLLMClient, ChatGoogleGenerativeAI):
|
|
21
|
+
api_config: UiPathAPIConfig = UiPathAPIConfig(
|
|
22
|
+
api_type="completions",
|
|
23
|
+
client_type="passthrough",
|
|
24
|
+
vendor_type="vertexai",
|
|
25
|
+
api_flavor="generate-content",
|
|
26
|
+
api_version="v1beta1",
|
|
27
|
+
freeze_base_url=True,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Override fields to avoid errors when instantiating the class
|
|
31
|
+
model: str = Field(default="", alias="model_name")
|
|
32
|
+
project: str | None = "PLACEHOLDER"
|
|
33
|
+
location: str | None = "PLACEHOLDER"
|
|
34
|
+
|
|
35
|
+
@model_validator(mode="after")
|
|
36
|
+
def setup_uipath_client(self) -> Self:
|
|
37
|
+
def fix_url_for_streaming(request: Request):
|
|
38
|
+
if request.headers.get("X-UiPath-Streaming-Enabled") == "true":
|
|
39
|
+
request.url = URL(request.url).copy_add_param("alt", "sse")
|
|
40
|
+
|
|
41
|
+
async def fix_url_for_streaming_async(request: Request):
|
|
42
|
+
if request.headers.get("X-UiPath-Streaming-Enabled") == "true":
|
|
43
|
+
request.url = URL(request.url).copy_add_param("alt", "sse")
|
|
44
|
+
|
|
45
|
+
self.uipath_sync_client.event_hooks["request"].append(fix_url_for_streaming)
|
|
46
|
+
self.uipath_async_client.event_hooks["request"].append(fix_url_for_streaming_async)
|
|
47
|
+
|
|
48
|
+
self.client = Client(
|
|
49
|
+
vertexai=True,
|
|
50
|
+
api_key="PLACEHOLDER",
|
|
51
|
+
http_options=HttpOptions(
|
|
52
|
+
base_url=str(self.uipath_sync_client.base_url),
|
|
53
|
+
headers=dict(self.uipath_sync_client.headers),
|
|
54
|
+
timeout=None, # handled by the UiPath client
|
|
55
|
+
retry_options=None, # handled by the UiPath client
|
|
56
|
+
httpx_client=self.uipath_sync_client,
|
|
57
|
+
httpx_async_client=self.uipath_async_client,
|
|
58
|
+
),
|
|
59
|
+
)
|
|
60
|
+
return self
|
|
@@ -22,6 +22,7 @@ class UiPathOpenAIEmbeddings(UiPathBaseLLMClient, OpenAIEmbeddings):
|
|
|
22
22
|
client_type="passthrough",
|
|
23
23
|
vendor_type="openai",
|
|
24
24
|
freeze_base_url=True,
|
|
25
|
+
api_version="2025-03-01-preview",
|
|
25
26
|
)
|
|
26
27
|
|
|
27
28
|
# Override fields to avoid errors when instantiating the class
|
|
@@ -53,6 +54,7 @@ class UiPathAzureOpenAIEmbeddings(UiPathBaseLLMClient, AzureOpenAIEmbeddings):
|
|
|
53
54
|
client_type="passthrough",
|
|
54
55
|
vendor_type="openai",
|
|
55
56
|
freeze_base_url=True,
|
|
57
|
+
api_version="2025-03-01-preview",
|
|
56
58
|
)
|
|
57
59
|
|
|
58
60
|
# Override fields to avoid errors when instantiating the class
|
|
@@ -23,6 +23,10 @@ class UiPathChatAnthropicVertex(UiPathBaseLLMClient, ChatAnthropicVertex): # ty
|
|
|
23
23
|
freeze_base_url=True,
|
|
24
24
|
)
|
|
25
25
|
|
|
26
|
+
# Override fields to avoid errors when instantiating the class
|
|
27
|
+
project: str | None = "PLACEHOLDER"
|
|
28
|
+
location: str = "PLACEHOLDER"
|
|
29
|
+
|
|
26
30
|
@model_validator(mode="after")
|
|
27
31
|
def setup_uipath_client(self) -> Self:
|
|
28
32
|
self.client = AnthropicVertex(
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
from collections.abc import AsyncIterator, Iterator
|
|
2
|
-
from typing import Self
|
|
3
|
-
|
|
4
|
-
from httpx import Response
|
|
5
|
-
from pydantic import Field, SecretStr, model_validator
|
|
6
|
-
from uipath_langchain_client.base_client import UiPathBaseLLMClient
|
|
7
|
-
from uipath_langchain_client.settings import UiPathAPIConfig
|
|
8
|
-
|
|
9
|
-
try:
|
|
10
|
-
from langchain_google_genai.chat_models import ChatGoogleGenerativeAI
|
|
11
|
-
|
|
12
|
-
from google.genai.client import Client
|
|
13
|
-
from google.genai.types import HttpOptions
|
|
14
|
-
except ImportError as e:
|
|
15
|
-
raise ImportError(
|
|
16
|
-
"The 'google' extra is required to use UiPathChatGoogleGenerativeAI. "
|
|
17
|
-
"Install it with: uv add uipath-langchain-client[google]"
|
|
18
|
-
) from e
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def _wrap_iter_lines(original: Iterator[str]) -> Iterator[str]:
|
|
22
|
-
"""Wrap iter_lines to extract individual JSON objects from streaming responses.
|
|
23
|
-
|
|
24
|
-
The LLM Gateway wraps streaming JSON responses in an array like [{...}, {...}].
|
|
25
|
-
This extracts each complete JSON object and yields them individually.
|
|
26
|
-
Handles multiple JSON objects on a single line (e.g., {...},{...}).
|
|
27
|
-
|
|
28
|
-
We prefix output with 'data: ' so the SDK's _iter_response_stream bypasses its
|
|
29
|
-
broken brace counting (which doesn't handle braces inside strings) and yields
|
|
30
|
-
our JSON objects directly.
|
|
31
|
-
|
|
32
|
-
Temporal Fix until it's fixed in the main package.
|
|
33
|
-
"""
|
|
34
|
-
buffer = ""
|
|
35
|
-
balance = 0
|
|
36
|
-
in_string = False
|
|
37
|
-
escape_next = False
|
|
38
|
-
|
|
39
|
-
for line in original:
|
|
40
|
-
# Handle data: prefix (SSE format)
|
|
41
|
-
if line.startswith("data:"):
|
|
42
|
-
line = line[5:].lstrip()
|
|
43
|
-
|
|
44
|
-
for char in line:
|
|
45
|
-
# Handle escape sequences in strings
|
|
46
|
-
if escape_next:
|
|
47
|
-
buffer += char
|
|
48
|
-
escape_next = False
|
|
49
|
-
continue
|
|
50
|
-
|
|
51
|
-
if char == "\\" and in_string:
|
|
52
|
-
buffer += char
|
|
53
|
-
escape_next = True
|
|
54
|
-
continue
|
|
55
|
-
|
|
56
|
-
if char == '"':
|
|
57
|
-
in_string = not in_string
|
|
58
|
-
buffer += char
|
|
59
|
-
continue
|
|
60
|
-
|
|
61
|
-
# Only track braces outside of strings
|
|
62
|
-
if not in_string:
|
|
63
|
-
if char == "{":
|
|
64
|
-
balance += 1
|
|
65
|
-
buffer += char
|
|
66
|
-
elif char == "}":
|
|
67
|
-
buffer += char
|
|
68
|
-
balance -= 1
|
|
69
|
-
if balance == 0 and buffer:
|
|
70
|
-
# Complete JSON object found - yield with 'data: ' prefix
|
|
71
|
-
# so SDK bypasses its broken brace counting
|
|
72
|
-
yield "data: " + buffer
|
|
73
|
-
buffer = ""
|
|
74
|
-
elif balance == 0:
|
|
75
|
-
# Skip characters outside JSON objects (array brackets, commas, whitespace)
|
|
76
|
-
continue
|
|
77
|
-
else:
|
|
78
|
-
buffer += char
|
|
79
|
-
else:
|
|
80
|
-
buffer += char
|
|
81
|
-
|
|
82
|
-
# Yield any remaining buffer (handles incomplete streams)
|
|
83
|
-
if buffer:
|
|
84
|
-
yield "data: " + buffer
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
async def _wrap_aiter_lines(original: AsyncIterator[str]) -> AsyncIterator[str]:
|
|
88
|
-
"""Async version of _wrap_iter_lines.
|
|
89
|
-
|
|
90
|
-
Extracts individual JSON objects from streaming responses.
|
|
91
|
-
Handles multiple JSON objects on a single line (e.g., {...},{...}).
|
|
92
|
-
|
|
93
|
-
We prefix output with 'data: ' so the SDK's _iter_response_stream bypasses its
|
|
94
|
-
broken brace counting (which doesn't handle braces inside strings) and yields
|
|
95
|
-
our JSON objects directly.
|
|
96
|
-
"""
|
|
97
|
-
buffer = ""
|
|
98
|
-
balance = 0
|
|
99
|
-
in_string = False
|
|
100
|
-
escape_next = False
|
|
101
|
-
|
|
102
|
-
async for line in original:
|
|
103
|
-
# Handle data: prefix (SSE format)
|
|
104
|
-
if line.startswith("data:"):
|
|
105
|
-
line = line[5:].lstrip()
|
|
106
|
-
|
|
107
|
-
for char in line:
|
|
108
|
-
# Handle escape sequences in strings
|
|
109
|
-
if escape_next:
|
|
110
|
-
buffer += char
|
|
111
|
-
escape_next = False
|
|
112
|
-
continue
|
|
113
|
-
|
|
114
|
-
if char == "\\" and in_string:
|
|
115
|
-
buffer += char
|
|
116
|
-
escape_next = True
|
|
117
|
-
continue
|
|
118
|
-
|
|
119
|
-
if char == '"':
|
|
120
|
-
in_string = not in_string
|
|
121
|
-
buffer += char
|
|
122
|
-
continue
|
|
123
|
-
|
|
124
|
-
# Only track braces outside of strings
|
|
125
|
-
if not in_string:
|
|
126
|
-
if char == "{":
|
|
127
|
-
balance += 1
|
|
128
|
-
buffer += char
|
|
129
|
-
elif char == "}":
|
|
130
|
-
buffer += char
|
|
131
|
-
balance -= 1
|
|
132
|
-
if balance == 0 and buffer:
|
|
133
|
-
# Complete JSON object found - yield with 'data: ' prefix
|
|
134
|
-
# so SDK bypasses its broken brace counting
|
|
135
|
-
yield "data: " + buffer
|
|
136
|
-
buffer = ""
|
|
137
|
-
elif balance == 0:
|
|
138
|
-
# Skip characters outside JSON objects (array brackets, commas, whitespace)
|
|
139
|
-
continue
|
|
140
|
-
else:
|
|
141
|
-
buffer += char
|
|
142
|
-
else:
|
|
143
|
-
buffer += char
|
|
144
|
-
|
|
145
|
-
# Yield any remaining buffer (handles incomplete streams)
|
|
146
|
-
if buffer:
|
|
147
|
-
yield "data: " + buffer
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
class UiPathChatGoogleGenerativeAI(UiPathBaseLLMClient, ChatGoogleGenerativeAI):
|
|
151
|
-
api_config: UiPathAPIConfig = UiPathAPIConfig(
|
|
152
|
-
api_type="completions",
|
|
153
|
-
client_type="passthrough",
|
|
154
|
-
vendor_type="vertexai",
|
|
155
|
-
api_flavor="generate-content",
|
|
156
|
-
api_version="v1beta1",
|
|
157
|
-
freeze_base_url=True,
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
# Override fields to avoid errors when instantiating the class
|
|
161
|
-
model: str = Field(default="", alias="model_name")
|
|
162
|
-
google_api_key: SecretStr | None = Field(default=SecretStr("PLACEHOLDER"))
|
|
163
|
-
|
|
164
|
-
@model_validator(mode="after")
|
|
165
|
-
def setup_uipath_client(self) -> Self:
|
|
166
|
-
def fix_streaming_response(response: Response):
|
|
167
|
-
"""Monkey-patch iter_lines to strip JSON array brackets."""
|
|
168
|
-
original_iter_lines = response.iter_lines
|
|
169
|
-
response.iter_lines = lambda: _wrap_iter_lines(original_iter_lines())
|
|
170
|
-
|
|
171
|
-
async def fix_streaming_response_async(response: Response):
|
|
172
|
-
"""Monkey-patch aiter_lines to strip JSON array brackets."""
|
|
173
|
-
original_aiter_lines = response.aiter_lines
|
|
174
|
-
response.aiter_lines = lambda: _wrap_aiter_lines(original_aiter_lines())
|
|
175
|
-
|
|
176
|
-
self.uipath_sync_client.event_hooks["response"].append(fix_streaming_response)
|
|
177
|
-
self.uipath_async_client.event_hooks["response"].append(fix_streaming_response_async)
|
|
178
|
-
|
|
179
|
-
# TODO: in exactly 2 weeks, we need to uncomment this part of the code because it will work, 5 february 2026 is the date.
|
|
180
|
-
# def fix_url_for_streaming(request: Request):
|
|
181
|
-
# if request.headers.get("X-UiPath-Streaming-Enabled") == "true":
|
|
182
|
-
# request.url = URL(request.url).copy_add_param("alt", "sse")
|
|
183
|
-
|
|
184
|
-
# async def fix_url_for_streaming_async(request: Request):
|
|
185
|
-
# if request.headers.get("X-UiPath-Streaming-Enabled") == "true":
|
|
186
|
-
# request.url = URL(request.url).copy_add_param("alt", "sse")
|
|
187
|
-
|
|
188
|
-
# self.uipath_sync_client.event_hooks["request"].append(fix_url_for_streaming)
|
|
189
|
-
# self.uipath_async_client.event_hooks["request"].append(fix_url_for_streaming_async)
|
|
190
|
-
|
|
191
|
-
self.client = Client(
|
|
192
|
-
vertexai=True,
|
|
193
|
-
api_key="PLACEHOLDER",
|
|
194
|
-
http_options=HttpOptions(
|
|
195
|
-
base_url=str(self.uipath_sync_client.base_url),
|
|
196
|
-
headers=dict(self.uipath_sync_client.headers),
|
|
197
|
-
timeout=None, # handled by the UiPath client
|
|
198
|
-
retry_options=None, # handled by the UiPath client
|
|
199
|
-
httpx_client=self.uipath_sync_client,
|
|
200
|
-
httpx_async_client=self.uipath_async_client,
|
|
201
|
-
),
|
|
202
|
-
)
|
|
203
|
-
return self
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|