Skip to content

Commit 0c41eb8

Browse files
authored
Fireworks Client (#6)
1 parent 4cf4548 commit 0c41eb8

15 files changed

Lines changed: 628 additions & 314 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes to `uipath_llm_client` (core package) will be documented in this file.
44

5+
## [1.1.0] - 2026-02-11
6+
7+
### Stable release
8+
- Adeed BYOM validation for settings
9+
- Stable release
10+
511
## [1.0.13] - 2026-02-05
612

713
### Fix

packages/uipath_langchain_client/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
All notable changes to `uipath_langchain_client` will be documented in this file.
44

5+
## [1.1.0] - 2026-02-11
6+
7+
### Features
8+
- Added langchain fireworks client and tested with GLM
9+
10+
### Stable release
11+
- Fixed BYO on passthrough
12+
- Stable release
13+
514
## [1.0.13] - 2026-02-05
615

716
### Fix

packages/uipath_langchain_client/pyproject.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ readme = "README.md"
66
requires-python = ">=3.11"
77
dependencies = [
88
"langchain>=1.2.7",
9-
"uipath-llm-client>=1.0.13",
9+
"uipath-llm-client>=1.1.0",
1010
]
1111

1212
[project.optional-dependencies]
@@ -29,8 +29,11 @@ azure = [
2929
vertexai = [
3030
"langchain-google-vertexai>=3.2.1",
3131
]
32+
fireworks = [
33+
"langchain-fireworks>=1.1.0",
34+
]
3235
all = [
33-
"uipath-langchain-client[openai,aws,google,anthropic,azure,vertexai]"
36+
"uipath-langchain-client[openai,aws,google,anthropic,azure,vertexai,fireworks]"
3437
]
3538

3639
[build-system]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
__title__ = "UiPath LangChain Client"
22
__description__ = "A Python client for interacting with UiPath's LLM services via LangChain."
3-
__version__ = "1.0.13"
3+
__version__ = "1.1.0"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from uipath_langchain_client.clients.fireworks.chat_models import UiPathChatFireworks
2+
from uipath_langchain_client.clients.fireworks.embeddings import UiPathFireworksEmbeddings
3+
4+
__all__ = ["UiPathChatFireworks", "UiPathFireworksEmbeddings"]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from typing import Self
2+
3+
from pydantic import Field, SecretStr, model_validator
4+
from uipath_langchain_client.base_client import UiPathBaseLLMClient
5+
from uipath_langchain_client.settings import UiPathAPIConfig
6+
7+
try:
8+
from langchain_fireworks.chat_models import ChatFireworks
9+
10+
from fireworks.client.api_client import FireworksClient as FireworksClientV1
11+
except ImportError as e:
12+
raise ImportError(
13+
"The 'fireworks' extra is required to use UiPathChatFireworks. "
14+
'Install it with: uv add "uipath-langchain-client[fireworks]"'
15+
) from e
16+
17+
18+
class UiPathChatFireworks(UiPathBaseLLMClient, ChatFireworks): # type: ignore[override]
19+
api_config: UiPathAPIConfig = UiPathAPIConfig(
20+
api_type="completions",
21+
client_type="passthrough",
22+
vendor_type="openai",
23+
api_flavor="chat-completions",
24+
api_version="2025-03-01-preview",
25+
freeze_base_url=True,
26+
)
27+
28+
# Override fields to avoid errors when instantiating the class
29+
fireworks_api_base: str | None = Field(alias="base_url", default="PLACEHOLDER")
30+
fireworks_api_key: SecretStr = Field(default=SecretStr("PLACEHOLDER"), alias="api_key")
31+
32+
@model_validator(mode="after")
33+
def setup_uipath_client(self) -> Self:
34+
fireworks_client_v1 = FireworksClientV1(
35+
api_key=self.fireworks_api_key.get_secret_value(),
36+
base_url=self.fireworks_api_base,
37+
)
38+
fireworks_client_v1._client = self.uipath_sync_client
39+
fireworks_client_v1._async_client = self.uipath_async_client
40+
self.client._client = fireworks_client_v1
41+
return self
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from typing import Self
2+
3+
from pydantic import model_validator
4+
from uipath_langchain_client.base_client import UiPathBaseLLMClient
5+
from uipath_langchain_client.settings import UiPathAPIConfig
6+
7+
try:
8+
from langchain_fireworks.embeddings import FireworksEmbeddings
9+
from openai import AsyncOpenAI, OpenAI
10+
except ImportError as e:
11+
raise ImportError(
12+
"The 'fireworks' extra is required to use UiPathFireworksEmbeddings. "
13+
'Install it with: uv add "uipath-langchain-client[fireworks]"'
14+
) from e
15+
16+
17+
class UiPathFireworksEmbeddings(UiPathBaseLLMClient, FireworksEmbeddings):
18+
api_config: UiPathAPIConfig = UiPathAPIConfig(
19+
api_type="embeddings",
20+
client_type="passthrough",
21+
vendor_type="openai",
22+
api_flavor="chat-completions",
23+
api_version="2025-03-01-preview",
24+
freeze_base_url=True,
25+
)
26+
27+
@model_validator(mode="after")
28+
def setup_uipath_client(self) -> Self:
29+
self.client = OpenAI(
30+
api_key="PLACEHOLDER",
31+
timeout=None, # handled by the UiPath client
32+
max_retries=0, # handled by the UiPath client
33+
http_client=self.uipath_sync_client,
34+
)
35+
self.async_client = AsyncOpenAI(
36+
api_key="PLACEHOLDER",
37+
timeout=None, # handled by the UiPath client
38+
max_retries=0, # handled by the UiPath client
39+
http_client=self.uipath_async_client,
40+
)
41+
return self
42+
43+
def embed_documents(self, texts: list[str]) -> list[list[float]]:
44+
"""Embed search docs."""
45+
return [
46+
i.embedding for i in self.client.embeddings.create(input=texts, model=self.model).data
47+
]
48+
49+
def embed_query(self, text: str) -> list[float]:
50+
"""Embed query text."""
51+
return self.embed_documents([text])[0]
52+
53+
async def aembed_documents(self, texts: list[str]) -> list[list[float]]:
54+
"""Embed search docs asynchronously."""
55+
return [
56+
i.embedding
57+
for i in (await self.async_client.embeddings.create(input=texts, model=self.model)).data
58+
]
59+
60+
async def aembed_query(self, text: str) -> list[float]:
61+
"""Embed query text asynchronously."""
62+
return (await self.aembed_documents([text]))[0]

packages/uipath_langchain_client/src/uipath_langchain_client/factory.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,13 @@ def get_chat_model(
8787
ValueError: If the model is not found in available models or vendor is not supported
8888
"""
8989
client_settings = client_settings or get_default_client_settings()
90+
9091
model_info = _get_model_info(model_name, client_settings, byo_connection_id)
9192

93+
is_uipath_owned = model_info.get("modelSubscriptionType") == "UiPathOwned"
94+
if not is_uipath_owned:
95+
client_settings.validate_byo_model(model_info)
96+
9297
if client_type == "normalized":
9398
from uipath_langchain_client.clients.normalized.chat_models import (
9499
UiPathNormalizedChatModel,
@@ -102,7 +107,6 @@ def get_chat_model(
102107
)
103108

104109
vendor_type = model_info["vendor"].lower()
105-
is_uipath_owned = model_info.get("modelSubscriptionType") == "UiPathOwned"
106110
match vendor_type:
107111
case "openai":
108112
if is_uipath_owned:
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
__titile__ = "UiPath LLM Client"
22
__description__ = "A Python client for interacting with UiPath's LLM services."
3-
__version__ = "1.0.13"
3+
__version__ = "1.1.0"

src/uipath_llm_client/httpx_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def build_routing_headers(
7575
if api_config.api_version is not None:
7676
headers["X-UiPath-LlmGateway-ApiVersion"] = api_config.api_version
7777
if byo_connection_id is not None:
78-
headers["X-UiPath-LlmGateway-ByoConnectionId"] = byo_connection_id
78+
headers["X-UiPath-LlmGateway-ByoIsConnectionId"] = byo_connection_id
7979
return headers
8080

8181

@@ -141,7 +141,7 @@ def __init__(
141141
merged_headers = Headers(self._default_headers)
142142
merged_headers.update(
143143
build_routing_headers(
144-
api_config=api_config, model_name=model_name, byo_connection_id=byo_connection_id
144+
model_name=model_name, byo_connection_id=byo_connection_id, api_config=api_config
145145
)
146146
)
147147
if headers is not None:
@@ -261,7 +261,7 @@ def __init__(
261261
merged_headers = Headers(self._default_headers)
262262
merged_headers.update(
263263
build_routing_headers(
264-
api_config=api_config, model_name=model_name, byo_connection_id=byo_connection_id
264+
model_name=model_name, byo_connection_id=byo_connection_id, api_config=api_config
265265
)
266266
)
267267
if headers is not None:

0 commit comments

Comments
 (0)