uipath-langchain 0.0.130__py3-none-any.whl → 0.0.132__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.

Potentially problematic release.


This version of uipath-langchain might be problematic. Click here for more details.

@@ -1,4 +1,3 @@
1
- from ..tracers._instrument_traceable import _instrument_traceable_attributes
2
1
  from ._request_mixin import UiPathRequestMixin
3
2
 
4
- __all__ = ["UiPathRequestMixin", "_instrument_traceable_attributes"]
3
+ __all__ = ["UiPathRequestMixin"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath-langchain
3
- Version: 0.0.130
3
+ Version: 0.0.132
4
4
  Summary: UiPath Langchain
5
5
  Project-URL: Homepage, https://uipath.com
6
6
  Project-URL: Repository, https://github.com/UiPath/uipath-langchain-python
@@ -25,7 +25,7 @@ Requires-Dist: openai>=1.65.5
25
25
  Requires-Dist: openinference-instrumentation-langchain>=0.1.50
26
26
  Requires-Dist: pydantic-settings>=2.6.0
27
27
  Requires-Dist: python-dotenv>=1.0.1
28
- Requires-Dist: uipath<2.2.0,>=2.1.49
28
+ Requires-Dist: uipath<2.2.0,>=2.1.56
29
29
  Provides-Extra: langchain
30
30
  Description-Content-Type: text/markdown
31
31
 
@@ -1,21 +1,25 @@
1
1
  uipath_langchain/__init__.py,sha256=VBrvQn7d3nuOdN7zEnV2_S-uhmkjgEIlXiFVeZxZakQ,80
2
2
  uipath_langchain/middlewares.py,sha256=6ljfbtWekrYc5G9KWDLSaViJ1DVIaNM-4qeB1BfHywE,731
3
3
  uipath_langchain/_cli/__init__.py,sha256=juqd9PbXs4yg45zMJ7BHAOPQjb7sgEbWE9InBtGZhfo,24
4
- uipath_langchain/_cli/cli_dev.py,sha256=VlI8qgCw-63I97tp_9lbXs-CVcNSjpd2sC13YNZAIuU,1401
5
- uipath_langchain/_cli/cli_eval.py,sha256=eGhvenAKJDdt9zIYWO7k01zJ7T1tGte7a6zz06iO6cw,2539
4
+ uipath_langchain/_cli/cli_dev.py,sha256=3e9RldNGirIk9184NdLK6kDuGeeqZjekTxbSZRtXjBE,1505
5
+ uipath_langchain/_cli/cli_eval.py,sha256=mvaKRF-pvxdNa2mk_ude9SYSd_kmMBo-hChlXokXOcw,2795
6
6
  uipath_langchain/_cli/cli_init.py,sha256=xhxJ8tuMSrVUNHvltgyPpOrvgMA-wq9shHeYYwvHILs,8199
7
- uipath_langchain/_cli/cli_new.py,sha256=dL8-Rri6u67ZZdbb4nT38A5xD_Q3fVnG0UK9VSeKaqg,2563
8
- uipath_langchain/_cli/cli_run.py,sha256=FT4ilVCBNSYllB-wS6__0E0fWKlrQEhO9N74wNHPffs,2056
7
+ uipath_langchain/_cli/cli_new.py,sha256=KKLxCzz7cDQ__rRr_a496IHWlSQXhmrBNgmKHnXAnTY,2336
8
+ uipath_langchain/_cli/cli_run.py,sha256=hRcoXJgOIFceCswzTfZKyzqVee3j-oSh-13EfuQmmE8,2614
9
9
  uipath_langchain/_cli/_runtime/_context.py,sha256=yyzYJDmk2fkH4T5gm4cLGRyXtjLESrpzHBT9euqluTA,817
10
10
  uipath_langchain/_cli/_runtime/_conversation.py,sha256=S1KTx_q-La7ikPRT3nBcIp8t-J9CF0QB0DCduQIIB28,11149
11
11
  uipath_langchain/_cli/_runtime/_exception.py,sha256=USKkLYkG-dzjX3fEiMMOHnVUpiXJs_xF0OQXCCOvbYM,546
12
- uipath_langchain/_cli/_runtime/_input.py,sha256=3IKrZR9xmxYg6l_1TbFpaLOWPDvK8d3nSKIHPGEEGzE,5715
12
+ uipath_langchain/_cli/_runtime/_input.py,sha256=Zx-8ZEr5Z796gdd3NnrlNObMIuXJobAV9mZwOql67Lo,5658
13
13
  uipath_langchain/_cli/_runtime/_output.py,sha256=yJOZPWv2FRUJWv1NRs9JmpB4QMTDXu8jrxoaKrfJvzw,9078
14
- uipath_langchain/_cli/_runtime/_runtime.py,sha256=ai-r6cYp4YbJqGhxWGvL68BHtJGhYhAZF-MEhKT7ceY,14955
14
+ uipath_langchain/_cli/_runtime/_runtime.py,sha256=cVt0TlsEBmKv6EcFTtCOT9ITsguzLDqFGMdhPOiBPRc,14318
15
15
  uipath_langchain/_cli/_templates/langgraph.json.template,sha256=eeh391Gta_hoRgaNaZ58nW1LNvCVXA7hlAH6l7Veous,107
16
- uipath_langchain/_cli/_templates/main.py.template,sha256=nMJQIYPlRk90iANfNVpkJ2EQX20Dxsyq92-BucEz_UM,1189
17
- uipath_langchain/_cli/_utils/_graph.py,sha256=JPShHNl0UQvl4AdjLIqLpNt_JAjpWH9WWF22Gs47Xew,7445
18
- uipath_langchain/_utils/__init__.py,sha256=WoY66enCygRXTh6v5B1UrRcFCnQYuPJ8oqDkwomXzLc,194
16
+ uipath_langchain/_cli/_templates/main.py.template,sha256=GpSblGH2hwS9ibqQmX2iB2nsmOA5zDfEEF4ChLiMxbQ,875
17
+ uipath_langchain/_cli/_utils/_graph.py,sha256=nMJWy8FmaD9rqPUY2lHc5uVpUzbXD1RO12uJnhe0kdo,6803
18
+ uipath_langchain/_tracing/__init__.py,sha256=UqrLc_WimpzKY82M0LJsgJ-HFQUQFjOmOlD1XQ8V-R4,181
19
+ uipath_langchain/_tracing/_instrument_traceable.py,sha256=8f9FyAKWE6kH1N8ErbpwqZHAzNjGwbLjQn7jdX5yAgA,4343
20
+ uipath_langchain/_tracing/_oteladapter.py,sha256=bhbLLTBwZ1rLDL-BgbvB8oR11y1Tp8jEw2mrAuVJ5go,8433
21
+ uipath_langchain/_tracing/_utils.py,sha256=r_fiSk3HDDAcePY_UbbEYiSbNqzn5gFeMPYBDvGrFx0,902
22
+ uipath_langchain/_utils/__init__.py,sha256=-w-4TD9ZnJDCpj4VIPXhJciukrmDJJbmnOFnhAkAaEU,81
19
23
  uipath_langchain/_utils/_request_mixin.py,sha256=ddKFs_0mjoFCmvPTiOTPJh1IIqYUo5CUka-B7zAZphE,19695
20
24
  uipath_langchain/_utils/_settings.py,sha256=2fExMQJ88YptfldmzMfZIpsx-m1gfMkeYGf5t6KIe0A,3084
21
25
  uipath_langchain/_utils/_sleep_policy.py,sha256=e9pHdjmcCj4CVoFM1jMyZFelH11YatsgWfpyrfXzKBQ,1251
@@ -26,15 +30,10 @@ uipath_langchain/embeddings/__init__.py,sha256=QICtYB58ZyqFfDQrEaO8lTEgAU5NuEKlR
26
30
  uipath_langchain/embeddings/embeddings.py,sha256=45gKyb6HVKigwE-0CXeZcAk33c0mteaEdPGa8hviqcw,4339
27
31
  uipath_langchain/retrievers/__init__.py,sha256=rOn7PyyHgZ4pMnXWPkGqmuBmx8eGuo-Oyndo7Wm9IUU,108
28
32
  uipath_langchain/retrievers/context_grounding_retriever.py,sha256=YLCIwy89LhLnNqcM0YJ5mZoeNyCs5UiKD3Wly8gnW1E,2239
29
- uipath_langchain/tracers/AsyncUiPathTracer.py,sha256=SgFLVU8ZtRaUjIiiM5jjYqlKc-4ec3tAXwZVceDM2ng,9147
30
- uipath_langchain/tracers/__init__.py,sha256=bMmqGCC4DsuLUdDVM4zvmVbRLPeULZ8K9ity0GAfy_4,197
31
- uipath_langchain/tracers/_events.py,sha256=CJri76SSdu7rGJIkXurJ2C5sQahfSK4E5UWwWYdEAtE,922
32
- uipath_langchain/tracers/_instrument_traceable.py,sha256=0e841zVzcPWjOGtmBx0GeHbq3JoqsmWv6gVPzDOKNTM,13496
33
- uipath_langchain/tracers/_utils.py,sha256=JOT1tKMdvqjMDtj2WbmbOWMeMlTXBWavxWpogX7KlRA,1543
34
33
  uipath_langchain/vectorstores/__init__.py,sha256=w8qs1P548ud1aIcVA_QhBgf_jZDrRMK5Lono78yA8cs,114
35
34
  uipath_langchain/vectorstores/context_grounding_vectorstore.py,sha256=TncIXG-YsUlO0R5ZYzWsM-Dj1SVCZbzmo2LraVxXelc,9559
36
- uipath_langchain-0.0.130.dist-info/METADATA,sha256=scZv_AxHBJjIMWBIWNcTU---140Ml8Tgy8TzNGSOkTU,4235
37
- uipath_langchain-0.0.130.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
38
- uipath_langchain-0.0.130.dist-info/entry_points.txt,sha256=FUtzqGOEntlJKMJIXhQUfT7ZTbQmGhke1iCmDWZaQZI,81
39
- uipath_langchain-0.0.130.dist-info/licenses/LICENSE,sha256=JDpt-uotAkHFmxpwxi6gwx6HQ25e-lG4U_Gzcvgp7JY,1063
40
- uipath_langchain-0.0.130.dist-info/RECORD,,
35
+ uipath_langchain-0.0.132.dist-info/METADATA,sha256=ta5yg3ODDXTdagrZVgeevO7wzwjwDeIIR3dAC_wmctM,4235
36
+ uipath_langchain-0.0.132.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
37
+ uipath_langchain-0.0.132.dist-info/entry_points.txt,sha256=FUtzqGOEntlJKMJIXhQUfT7ZTbQmGhke1iCmDWZaQZI,81
38
+ uipath_langchain-0.0.132.dist-info/licenses/LICENSE,sha256=JDpt-uotAkHFmxpwxi6gwx6HQ25e-lG4U_Gzcvgp7JY,1063
39
+ uipath_langchain-0.0.132.dist-info/RECORD,,
@@ -1,274 +0,0 @@
1
- import asyncio
2
- import json
3
- import logging
4
- import queue
5
- import uuid
6
- import warnings
7
- from os import environ as env
8
- from typing import Any, Dict, Optional
9
-
10
- import httpx
11
- from langchain_core.tracers.base import AsyncBaseTracer
12
- from langchain_core.tracers.schemas import Run
13
- from pydantic import PydanticDeprecationWarning
14
- from uipath._cli._runtime._contracts import UiPathTraceContext
15
-
16
- from ._events import CustomTraceEvents, FunctionCallEventData
17
- from ._utils import _setup_tracer_httpx_logging, _simple_serialize_defaults
18
-
19
- logger = logging.getLogger(__name__)
20
-
21
- _setup_tracer_httpx_logging("/llmops_/api/Agent/trace/")
22
-
23
-
24
- class Status:
25
- SUCCESS = 1
26
- ERROR = 2
27
- INTERRUPTED = 3
28
-
29
-
30
- class AsyncUiPathTracer(AsyncBaseTracer):
31
- def __init__(
32
- self,
33
- context: Optional[UiPathTraceContext] = None,
34
- client: Optional[httpx.AsyncClient] = None,
35
- **kwargs,
36
- ):
37
- super().__init__(**kwargs)
38
-
39
- self.client = client or httpx.AsyncClient()
40
- self.retries = 3
41
- self.log_queue: queue.Queue[dict[str, Any]] = queue.Queue()
42
-
43
- self.context = context or UiPathTraceContext()
44
-
45
- self.base_url = self._get_base_url()
46
-
47
- auth_token = env.get("UNATTENDED_USER_ACCESS_TOKEN") or env.get(
48
- "UIPATH_ACCESS_TOKEN"
49
- )
50
-
51
- self.headers = {"Authorization": f"Bearer {auth_token}"}
52
-
53
- self.running = True
54
- self.worker_task = asyncio.create_task(self._worker())
55
- self.function_call_run_map: Dict[str, Run] = {}
56
-
57
- async def on_custom_event(
58
- self,
59
- name: str,
60
- data: Any,
61
- *,
62
- run_id: uuid.UUID,
63
- tags=None,
64
- metadata=None,
65
- **kwargs: Any,
66
- ) -> None:
67
- if name == CustomTraceEvents.UIPATH_TRACE_FUNCTION_CALL:
68
- # only handle the function call event
69
-
70
- if not isinstance(data, FunctionCallEventData):
71
- logger.warning(
72
- f"Received unexpected data type for function call event: {type(data)}"
73
- )
74
- return
75
-
76
- if data.event_type == "call":
77
- run = self.run_map[str(run_id)]
78
- child_run = run.create_child(
79
- name=data.function_name,
80
- run_type=data.run_type,
81
- tags=data.tags,
82
- inputs=data.inputs,
83
- )
84
-
85
- if data.metadata is not None:
86
- run.add_metadata(data.metadata)
87
-
88
- call_uuid = data.call_uuid
89
- self.function_call_run_map[call_uuid] = child_run
90
-
91
- self._send_span(run)
92
-
93
- if data.event_type == "completion":
94
- call_uuid = data.call_uuid
95
- previous_run = self.function_call_run_map.pop(call_uuid, None)
96
-
97
- if previous_run:
98
- previous_run.end(
99
- outputs=self._safe_dict_dump(data.output), error=data.error
100
- )
101
- self._send_span(previous_run)
102
-
103
- async def wait_for_all_tracers(self) -> None:
104
- """
105
- Wait for all pending log requests to complete
106
- """
107
- self.running = False
108
- if self.worker_task:
109
- await self.worker_task
110
-
111
- async def _worker(self):
112
- """Worker loop that processes logs from the queue."""
113
- while self.running:
114
- try:
115
- if self.log_queue.empty():
116
- await asyncio.sleep(1)
117
- continue
118
-
119
- span_data = self.log_queue.get_nowait()
120
-
121
- url = self._build_url(self.context.trace_id)
122
-
123
- for attempt in range(self.retries):
124
- response = await self.client.post(
125
- url,
126
- headers=self.headers,
127
- json=[span_data], # api expects a list of spans
128
- timeout=10,
129
- )
130
-
131
- if response.is_success:
132
- break
133
-
134
- await asyncio.sleep(0.5 * (2**attempt)) # Exponential backoff
135
-
136
- if 400 <= response.status_code < 600:
137
- logger.warning(
138
- f"Error when sending trace: {response}. Body is: {response.text}"
139
- )
140
- except Exception as e:
141
- logger.warning(f"Exception when sending trace: {e}", exc_info=e)
142
-
143
- # wait for a bit to ensure all logs are sent
144
- await asyncio.sleep(1)
145
-
146
- # try to send any remaining logs in the queue
147
- while True:
148
- try:
149
- if self.log_queue.empty():
150
- break
151
-
152
- span_data = self.log_queue.get_nowait()
153
- url = self._build_url(self.context.trace_id)
154
-
155
- response = await self.client.post(
156
- url,
157
- headers=self.headers,
158
- json=[span_data], # api expects a list of spans
159
- timeout=10,
160
- )
161
- except Exception as e:
162
- logger.warning(f"Exception when sending trace: {e}", exc_info=e)
163
-
164
- async def _persist_run(self, run: Run) -> None:
165
- # Determine if this is a start or end trace based on whether end_time is set
166
- self._send_span(run)
167
-
168
- def _send_span(self, run: Run) -> None:
169
- """Send span data for a run to the API"""
170
- run_id = str(run.id)
171
-
172
- try:
173
- start_time = (
174
- run.start_time.isoformat() if run.start_time is not None else None
175
- )
176
- end_time = (
177
- run.end_time.isoformat() if run.end_time is not None else start_time
178
- )
179
-
180
- parent_id = (
181
- str(run.parent_run_id)
182
- if run.parent_run_id is not None
183
- else self.context.parent_span_id
184
- )
185
- attributes = self._safe_jsons_dump(self._run_to_dict(run))
186
- status = self._determine_status(run.error)
187
-
188
- span_data = {
189
- "id": run_id,
190
- "parentId": parent_id,
191
- "traceId": self.context.trace_id,
192
- "name": run.name,
193
- "startTime": start_time,
194
- "endTime": end_time,
195
- "referenceId": self.context.reference_id,
196
- "attributes": attributes,
197
- "organizationId": self.context.org_id,
198
- "tenantId": self.context.tenant_id,
199
- "spanType": "LangGraphRun",
200
- "status": status,
201
- "jobKey": self.context.job_id,
202
- "folderKey": self.context.folder_key,
203
- "processKey": self.context.folder_key,
204
- "expiryTimeUtc": None,
205
- }
206
-
207
- self.log_queue.put(span_data)
208
- except Exception as e:
209
- logger.warning(f"Exception when adding trace to queue: {e}.")
210
-
211
- async def _start_trace(self, run: Run) -> None:
212
- await super()._start_trace(run)
213
- await self._persist_run(run)
214
-
215
- async def _end_trace(self, run: Run) -> None:
216
- await super()._end_trace(run)
217
- await self._persist_run(run)
218
-
219
- def _determine_status(self, error: Optional[str]):
220
- if error:
221
- if error.startswith("GraphInterrupt("):
222
- return Status.INTERRUPTED
223
-
224
- return Status.ERROR
225
-
226
- return Status.SUCCESS
227
-
228
- def _safe_jsons_dump(self, obj) -> str:
229
- try:
230
- json_str = json.dumps(obj, default=_simple_serialize_defaults)
231
- return json_str
232
- except Exception as e:
233
- logger.warning(f"Error serializing object to JSON: {e}")
234
- return "{ }"
235
-
236
- def _safe_dict_dump(self, obj) -> Dict[str, Any]:
237
- try:
238
- serialized = json.loads(json.dumps(obj, default=_simple_serialize_defaults))
239
- return serialized
240
- except Exception as e:
241
- # Last resort - string representation
242
- logger.warning(f"Error serializing object to JSON: {e}")
243
- return {"raw": str(obj)}
244
-
245
- def _run_to_dict(self, run: Run):
246
- with warnings.catch_warnings():
247
- warnings.simplefilter("ignore", category=PydanticDeprecationWarning)
248
-
249
- # Helper function to safely copy values
250
- def safe_copy(value):
251
- if value is None:
252
- return None
253
- if hasattr(value, "copy") and callable(value.copy):
254
- return value.copy()
255
- return value
256
-
257
- return {
258
- **run.dict(exclude={"child_runs", "inputs", "outputs", "serialized"}),
259
- "inputs": safe_copy(run.inputs),
260
- "outputs": safe_copy(run.outputs),
261
- }
262
-
263
- def _get_base_url(self) -> str:
264
- uipath_url = (
265
- env.get("UIPATH_URL") or "https://cloud.uipath.com/dummyOrg/dummyTennant/"
266
- )
267
-
268
- uipath_url = uipath_url.rstrip("/")
269
-
270
- return uipath_url
271
-
272
- def _build_url(self, trace_id: Optional[str]) -> str:
273
- """Construct the URL for the API request."""
274
- return f"{self.base_url}/llmopstenant_/api/Traces/spans?traceId={trace_id}&source=Robots"
@@ -1,7 +0,0 @@
1
- from ._instrument_traceable import _instrument_traceable_attributes
2
- from .AsyncUiPathTracer import AsyncUiPathTracer
3
-
4
- __all__ = [
5
- "AsyncUiPathTracer",
6
- "_instrument_traceable_attributes",
7
- ]
@@ -1,33 +0,0 @@
1
- from typing import Any, Dict, List, Literal, Optional
2
-
3
- RUN_TYPE_T = Literal[
4
- "tool", "chain", "llm", "retriever", "embedding", "prompt", "parser"
5
- ]
6
-
7
-
8
- class CustomTraceEvents:
9
- UIPATH_TRACE_FUNCTION_CALL = "__uipath_trace_function_call"
10
-
11
-
12
- class FunctionCallEventData:
13
- def __init__(
14
- self,
15
- function_name: str,
16
- event_type: str,
17
- inputs: Dict[str, Any],
18
- call_uuid: str,
19
- output: Any,
20
- error: Optional[str] = None,
21
- run_type: Optional[RUN_TYPE_T] = None,
22
- tags: Optional[List[str]] = None,
23
- metadata: Optional[Dict[str, Any]] = None,
24
- ):
25
- self.function_name = function_name
26
- self.event_type = event_type
27
- self.inputs = inputs
28
- self.call_uuid = call_uuid
29
- self.output = output
30
- self.error = error
31
- self.run_type = run_type or "chain"
32
- self.tags = tags
33
- self.metadata = metadata