Skip to content

Commit c80a523

Browse files
committed
fixes
1 parent fafac9c commit c80a523

34 files changed

Lines changed: 459 additions & 308 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ All notable changes to `uipath_llm_client` (core package) will be documented in
77
### New client
88
- Added UiPathChatAnthropicBedrock
99

10+
### Fixes
11+
- Added constants for VendorType and ApiFlavor
12+
1013
## [1.3.0] - 2026-03-10
1114

1215
### Version Bump

packages/uipath_langchain_client/demo.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
from uipath_langchain_client import get_chat_model, get_embedding_model
2020
from uipath_langchain_client.settings import get_default_client_settings
2121

22+
from uipath.llm_client.settings.constants import RoutingMode
23+
2224

2325
def demo_basic_chat():
2426
"""Demonstrate basic chat completion using the factory function."""
@@ -199,7 +201,7 @@ def demo_normalized_api():
199201
chat_model = get_chat_model(
200202
model_name="gpt-4o-2024-11-20",
201203
client_settings=settings,
202-
client_type="normalized", # Use normalized API
204+
routing_mode=RoutingMode.NORMALIZED, # Use normalized API
203205
)
204206

205207
response = chat_model.invoke("What is machine learning in one sentence?")

packages/uipath_langchain_client/src/uipath_langchain_client/base_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
>>> client = UiPathBaseLLMClient(
1515
... model="gpt-4o-2024-11-20",
1616
... api_config=UiPathAPIConfig(
17-
... api_type="completions",
18-
... client_type="passthrough",
17+
... api_type=ApiType.COMPLETIONS,
18+
... routing_mode=RoutingMode.PASSTHROUGH,
1919
... vendor_type="openai",
2020
... ),
2121
... client_settings=get_default_client_settings(),
@@ -67,7 +67,7 @@ class UiPathBaseLLMClient(BaseModel, ABC):
6767
model_name: Name of the LLM model to use (aliased as "model")
6868
byo_connection_id: Optional connection ID for Bring Your Own (BYO) models enrolled
6969
in LLMGateway. When provided, routes requests to your custom-enrolled model.
70-
api_config: API configuration (api_type, client_type, vendor_type, etc.)
70+
api_config: API configuration (api_type, routing_mode, vendor_type, etc.)
7171
client_settings: Client configuration (base URL, auth headers, etc.)
7272
default_headers: Additional headers to include in requests
7373
request_timeout: Client-side request timeout in seconds

packages/uipath_langchain_client/src/uipath_langchain_client/clients/anthropic/chat_models.py

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
from functools import cached_property
2-
from typing import Any, Literal, Self
2+
from typing import Any, Self
33

44
from pydantic import Field, model_validator
55
from typing_extensions import override
66

77
from uipath_langchain_client.base_client import UiPathBaseChatModel
8-
from uipath_langchain_client.settings import UiPathAPIConfig
8+
from uipath_langchain_client.settings import (
9+
ApiFlavor,
10+
ApiType,
11+
RoutingMode,
12+
UiPathAPIConfig,
13+
VendorType,
14+
)
915

1016
try:
1117
from anthropic import (
@@ -28,22 +34,22 @@
2834

2935
class UiPathChatAnthropic(UiPathBaseChatModel, ChatAnthropic):
3036
api_config: UiPathAPIConfig = UiPathAPIConfig(
31-
api_type="completions",
32-
client_type="passthrough",
33-
vendor_type="awsbedrock",
37+
api_type=ApiType.COMPLETIONS,
38+
routing_mode=RoutingMode.PASSTHROUGH,
39+
vendor_type=VendorType.ANTHROPIC,
3440
freeze_base_url=True,
3541
)
36-
vendor_type: Literal["anthropic", "azure", "vertexai", "awsbedrock"] = "awsbedrock"
42+
vendor_type: VendorType = VendorType.ANTHROPIC
3743

3844
@model_validator(mode="after")
3945
def setup_api_flavor_and_version(self) -> Self:
4046
self.api_config.vendor_type = self.vendor_type
4147
match self.vendor_type:
42-
case "vertexai":
43-
self.api_config.api_flavor = "anthropic-claude"
48+
case VendorType.VERTEXAI:
49+
self.api_config.api_flavor = ApiFlavor.ANTHROPIC_CLAUDE
4450
self.api_config.api_version = "v1beta1"
45-
case "awsbedrock":
46-
self.api_config.api_flavor = "invoke"
51+
case VendorType.AWSBEDROCK:
52+
self.api_config.api_flavor = ApiFlavor.INVOKE
4753
case _:
4854
raise ValueError(
4955
"anthropic and azure vendors are currently not supported by UiPath"
@@ -60,15 +66,23 @@ def _anthropic_client(
6066
self,
6167
) -> Anthropic | AnthropicVertex | AnthropicBedrock | AnthropicFoundry:
6268
match self.vendor_type:
63-
case "azure":
69+
case VendorType.ANTHROPIC:
70+
return Anthropic(
71+
api_key="PLACEHOLDER",
72+
base_url=str(self.uipath_sync_client.base_url),
73+
default_headers=dict(self.uipath_sync_client.headers),
74+
max_retries=0, # handled by the UiPathBaseChatModel
75+
http_client=self.uipath_sync_client,
76+
)
77+
case VendorType.AZURE:
6478
return AnthropicFoundry(
6579
api_key="PLACEHOLDER",
6680
base_url=str(self.uipath_sync_client.base_url),
6781
default_headers=dict(self.uipath_sync_client.headers),
6882
max_retries=0, # handled by the UiPathBaseChatModel
6983
http_client=self.uipath_sync_client,
7084
)
71-
case "vertexai":
85+
case VendorType.VERTEXAI:
7286
return AnthropicVertex(
7387
region="PLACEHOLDER",
7488
project_id="PLACEHOLDER",
@@ -78,7 +92,7 @@ def _anthropic_client(
7892
max_retries=0, # handled by the UiPathBaseChatModel
7993
http_client=self.uipath_sync_client,
8094
)
81-
case "awsbedrock":
95+
case VendorType.AWSBEDROCK:
8296
return AnthropicBedrock(
8397
aws_access_key="PLACEHOLDER",
8498
aws_secret_key="PLACEHOLDER",
@@ -88,29 +102,31 @@ def _anthropic_client(
88102
max_retries=0, # handled by the UiPathBaseChatModel
89103
http_client=self.uipath_sync_client,
90104
)
91-
case "anthropic":
92-
return Anthropic(
93-
api_key="PLACEHOLDER",
94-
base_url=str(self.uipath_sync_client.base_url),
95-
default_headers=dict(self.uipath_sync_client.headers),
96-
max_retries=0, # handled by the UiPathBaseChatModel
97-
http_client=self.uipath_sync_client,
98-
)
105+
case _:
106+
raise ValueError("Anthropic models are currently not hosted on any other provider")
99107

100108
@cached_property
101109
def _async_anthropic_client(
102110
self,
103111
) -> AsyncAnthropic | AsyncAnthropicVertex | AsyncAnthropicBedrock | AsyncAnthropicFoundry:
104112
match self.vendor_type:
105-
case "azure":
113+
case VendorType.ANTHROPIC:
114+
return AsyncAnthropic(
115+
api_key="PLACEHOLDER",
116+
base_url=str(self.uipath_async_client.base_url),
117+
default_headers=dict(self.uipath_async_client.headers),
118+
max_retries=0, # handled by the UiPathBaseChatModel
119+
http_client=self.uipath_async_client,
120+
)
121+
case VendorType.AZURE:
106122
return AsyncAnthropicFoundry(
107123
api_key="PLACEHOLDER",
108124
base_url=str(self.uipath_async_client.base_url),
109125
default_headers=dict(self.uipath_async_client.headers),
110126
max_retries=0, # handled by the UiPathBaseChatModel
111127
http_client=self.uipath_async_client,
112128
)
113-
case "vertexai":
129+
case VendorType.VERTEXAI:
114130
return AsyncAnthropicVertex(
115131
region="PLACEHOLDER",
116132
project_id="PLACEHOLDER",
@@ -120,7 +136,7 @@ def _async_anthropic_client(
120136
max_retries=0, # handled by the UiPathBaseChatModel
121137
http_client=self.uipath_async_client,
122138
)
123-
case "awsbedrock":
139+
case VendorType.AWSBEDROCK:
124140
return AsyncAnthropicBedrock(
125141
aws_access_key="PLACEHOLDER",
126142
aws_secret_key="PLACEHOLDER",
@@ -131,13 +147,7 @@ def _async_anthropic_client(
131147
http_client=self.uipath_async_client,
132148
)
133149
case _:
134-
return AsyncAnthropic(
135-
api_key="PLACEHOLDER",
136-
base_url=str(self.uipath_async_client.base_url),
137-
default_headers=dict(self.uipath_async_client.headers),
138-
max_retries=0, # handled by the UiPathBaseChatModel
139-
http_client=self.uipath_async_client,
140-
)
150+
raise ValueError("Anthropic models are currently not hosted on any other provider")
141151

142152
@override
143153
def _create(self, payload: dict) -> Any:

packages/uipath_langchain_client/src/uipath_langchain_client/clients/azure/chat_models.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
from pydantic import Field, model_validator
55

66
from uipath_langchain_client.base_client import UiPathBaseChatModel
7-
from uipath_langchain_client.settings import UiPathAPIConfig
7+
from uipath_langchain_client.settings import (
8+
ApiFlavor,
9+
ApiType,
10+
RoutingMode,
11+
UiPathAPIConfig,
12+
VendorType,
13+
)
814

915
try:
1016
from azure.core.credentials import AzureKeyCredential, TokenCredential
@@ -20,9 +26,9 @@
2026

2127
class UiPathAzureAIChatCompletionsModel(UiPathBaseChatModel, AzureAIOpenAIApiChatModel): # type: ignore[override]
2228
api_config: UiPathAPIConfig = UiPathAPIConfig(
23-
api_type="completions",
24-
client_type="passthrough",
25-
vendor_type="azure",
29+
api_type=ApiType.COMPLETIONS,
30+
routing_mode=RoutingMode.PASSTHROUGH,
31+
vendor_type=VendorType.AZURE,
2632
freeze_base_url=False,
2733
)
2834

@@ -39,17 +45,17 @@ def setup_uipath_client(self) -> Self:
3945
def fix_url_and_api_flavor_header(request: Request):
4046
url_suffix = str(request.url).split(base_url)[-1]
4147
if "responses" in url_suffix:
42-
request.headers["X-UiPath-LlmGateway-ApiFlavor"] = "responses"
48+
request.headers["X-UiPath-LlmGateway-ApiFlavor"] = ApiFlavor.RESPONSES.value
4349
else:
44-
request.headers["X-UiPath-LlmGateway-ApiFlavor"] = "chat-completions"
50+
request.headers["X-UiPath-LlmGateway-ApiFlavor"] = ApiFlavor.CHAT_COMPLETIONS.value
4551
request.url = URL(base_url)
4652

4753
async def fix_url_and_api_flavor_header_async(request: Request):
4854
url_suffix = str(request.url).split(base_url)[-1]
4955
if "responses" in url_suffix:
50-
request.headers["X-UiPath-LlmGateway-ApiFlavor"] = "responses"
56+
request.headers["X-UiPath-LlmGateway-ApiFlavor"] = ApiFlavor.RESPONSES.value
5157
else:
52-
request.headers["X-UiPath-LlmGateway-ApiFlavor"] = "chat-completions"
58+
request.headers["X-UiPath-LlmGateway-ApiFlavor"] = ApiFlavor.CHAT_COMPLETIONS.value
5359
request.url = URL(base_url)
5460

5561
self.uipath_sync_client.event_hooks["request"].append(fix_url_and_api_flavor_header)

packages/uipath_langchain_client/src/uipath_langchain_client/clients/azure/embeddings.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from pydantic import Field, model_validator
44

55
from uipath_langchain_client.base_client import UiPathBaseEmbeddings
6-
from uipath_langchain_client.settings import UiPathAPIConfig
6+
from uipath_langchain_client.settings import ApiType, RoutingMode, UiPathAPIConfig, VendorType
77

88
try:
99
from azure.core.credentials import AzureKeyCredential, TokenCredential
@@ -19,9 +19,9 @@
1919

2020
class UiPathAzureAIEmbeddingsModel(UiPathBaseEmbeddings, AzureAIOpenAIApiEmbeddingsModel): # type: ignore[override]
2121
api_config: UiPathAPIConfig = UiPathAPIConfig(
22-
api_type="embeddings",
23-
client_type="passthrough",
24-
vendor_type="azure",
22+
api_type=ApiType.EMBEDDINGS,
23+
routing_mode=RoutingMode.PASSTHROUGH,
24+
vendor_type=VendorType.AZURE,
2525
freeze_base_url=True,
2626
)
2727

packages/uipath_langchain_client/src/uipath_langchain_client/clients/bedrock/chat_models.py

Lines changed: 49 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
from pydantic import Field, model_validator
55

66
from uipath_langchain_client.base_client import UiPathBaseChatModel
7-
from uipath_langchain_client.settings import UiPathAPIConfig
7+
from uipath_langchain_client.settings import (
8+
ApiFlavor,
9+
ApiType,
10+
RoutingMode,
11+
UiPathAPIConfig,
12+
VendorType,
13+
)
814

915
try:
1016
from anthropic import AnthropicBedrock, AsyncAnthropicBedrock
@@ -21,10 +27,10 @@
2127

2228
class UiPathChatBedrockConverse(UiPathBaseChatModel, ChatBedrockConverse):
2329
api_config: UiPathAPIConfig = UiPathAPIConfig(
24-
api_type="completions",
25-
client_type="passthrough",
26-
vendor_type="awsbedrock",
27-
api_flavor="converse",
30+
api_type=ApiType.COMPLETIONS,
31+
routing_mode=RoutingMode.PASSTHROUGH,
32+
vendor_type=VendorType.AWSBEDROCK,
33+
api_flavor=ApiFlavor.CONVERSE,
2834
freeze_base_url=True,
2935
)
3036

@@ -50,10 +56,10 @@ def setup_uipath_client(self) -> Self:
5056

5157
class UiPathChatBedrock(UiPathBaseChatModel, ChatBedrock):
5258
api_config: UiPathAPIConfig = UiPathAPIConfig(
53-
api_type="completions",
54-
client_type="passthrough",
55-
vendor_type="awsbedrock",
56-
api_flavor="invoke",
59+
api_type=ApiType.COMPLETIONS,
60+
routing_mode=RoutingMode.PASSTHROUGH,
61+
vendor_type=VendorType.AWSBEDROCK,
62+
api_flavor=ApiFlavor.INVOKE,
5763
freeze_base_url=True,
5864
)
5965

@@ -81,42 +87,40 @@ def _as_converse(self) -> UiPathChatBedrockConverse:
8187
raise NotImplementedError("You must instantiate the converse client directly")
8288

8389

84-
if ChatAnthropicBedrock is not None:
90+
class UiPathChatAnthropicBedrock(UiPathBaseChatModel, ChatAnthropicBedrock):
91+
api_config: UiPathAPIConfig = UiPathAPIConfig(
92+
api_type=ApiType.COMPLETIONS,
93+
routing_mode=RoutingMode.PASSTHROUGH,
94+
vendor_type=VendorType.AWSBEDROCK,
95+
api_flavor=ApiFlavor.INVOKE,
96+
freeze_base_url=True,
97+
)
8598

86-
class UiPathChatAnthropicBedrock(UiPathBaseChatModel, ChatAnthropicBedrock):
87-
api_config: UiPathAPIConfig = UiPathAPIConfig(
88-
api_type="completions",
89-
client_type="passthrough",
90-
vendor_type="awsbedrock",
91-
api_flavor="invoke",
92-
freeze_base_url=True,
99+
# Override fields to avoid typing issues and fix stuff
100+
stop_sequences: list[str] | None = Field(default=None, alias="stop")
101+
model: str = Field(default="", alias="model_name")
102+
default_request_timeout: float | None = None
103+
104+
@cached_property
105+
def _client(self) -> AnthropicBedrock:
106+
return AnthropicBedrock(
107+
aws_access_key="PLACEHOLDER",
108+
aws_secret_key="PLACEHOLDER",
109+
aws_region="PLACEHOLDER",
110+
base_url=str(self.uipath_sync_client.base_url),
111+
default_headers=dict(self.uipath_sync_client.headers),
112+
max_retries=0, # handled by the UiPathBaseChatModel
113+
http_client=self.uipath_sync_client,
93114
)
94115

95-
# Override fields to avoid typing issues and fix stuff
96-
stop_sequences: list[str] | None = Field(default=None, alias="stop")
97-
model: str = Field(default="", alias="model_name")
98-
default_request_timeout: float | None = None
99-
100-
@cached_property
101-
def _client(self) -> AnthropicBedrock:
102-
return AnthropicBedrock(
103-
aws_access_key="PLACEHOLDER",
104-
aws_secret_key="PLACEHOLDER",
105-
aws_region="PLACEHOLDER",
106-
base_url=str(self.uipath_sync_client.base_url),
107-
default_headers=dict(self.uipath_sync_client.headers),
108-
max_retries=0, # handled by the UiPathBaseChatModel
109-
http_client=self.uipath_sync_client,
110-
)
111-
112-
@cached_property
113-
def _async_client(self) -> AsyncAnthropicBedrock:
114-
return AsyncAnthropicBedrock(
115-
aws_access_key="PLACEHOLDER",
116-
aws_secret_key="PLACEHOLDER",
117-
aws_region="PLACEHOLDER",
118-
base_url=str(self.uipath_async_client.base_url),
119-
default_headers=dict(self.uipath_async_client.headers),
120-
max_retries=0, # handled by the UiPathBaseChatModel
121-
http_client=self.uipath_async_client,
122-
)
116+
@cached_property
117+
def _async_client(self) -> AsyncAnthropicBedrock:
118+
return AsyncAnthropicBedrock(
119+
aws_access_key="PLACEHOLDER",
120+
aws_secret_key="PLACEHOLDER",
121+
aws_region="PLACEHOLDER",
122+
base_url=str(self.uipath_async_client.base_url),
123+
default_headers=dict(self.uipath_async_client.headers),
124+
max_retries=0, # handled by the UiPathBaseChatModel
125+
http_client=self.uipath_async_client,
126+
)

0 commit comments

Comments
 (0)