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

@@ -246,10 +246,18 @@ class AsyncUiPathTracer(AsyncBaseTracer):
246
246
  with warnings.catch_warnings():
247
247
  warnings.simplefilter("ignore", category=PydanticDeprecationWarning)
248
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
+
249
257
  return {
250
258
  **run.dict(exclude={"child_runs", "inputs", "outputs", "serialized"}),
251
- "inputs": run.inputs.copy() if run.inputs is not None else None,
252
- "outputs": run.outputs.copy() if run.outputs is not None else None,
259
+ "inputs": safe_copy(run.inputs),
260
+ "outputs": safe_copy(run.outputs),
253
261
  }
254
262
 
255
263
  def _get_base_url(self) -> str:
@@ -1,9 +1,7 @@
1
1
  from ._instrument_traceable import _instrument_traceable_attributes
2
2
  from .AsyncUiPathTracer import AsyncUiPathTracer
3
- from .UiPathTracer import UiPathTracer
4
3
 
5
4
  __all__ = [
6
5
  "AsyncUiPathTracer",
7
- "UiPathTracer",
8
6
  "_instrument_traceable_attributes",
9
7
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath-langchain
3
- Version: 0.0.108
3
+ Version: 0.0.110
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
@@ -24,7 +24,7 @@ Requires-Dist: langgraph>=0.2.70
24
24
  Requires-Dist: openai>=1.65.5
25
25
  Requires-Dist: pydantic-settings>=2.6.0
26
26
  Requires-Dist: python-dotenv>=1.0.1
27
- Requires-Dist: uipath<2.1.0,>=2.0.33
27
+ Requires-Dist: uipath<2.1.0,>=2.0.55
28
28
  Provides-Extra: langchain
29
29
  Description-Content-Type: text/markdown
30
30
 
@@ -23,16 +23,15 @@ uipath_langchain/embeddings/__init__.py,sha256=QICtYB58ZyqFfDQrEaO8lTEgAU5NuEKlR
23
23
  uipath_langchain/embeddings/embeddings.py,sha256=gntzTfwO1pHbgnXiPdfETJaaurvQWqxVUCH75VMah54,4274
24
24
  uipath_langchain/retrievers/__init__.py,sha256=rOn7PyyHgZ4pMnXWPkGqmuBmx8eGuo-Oyndo7Wm9IUU,108
25
25
  uipath_langchain/retrievers/context_grounding_retriever.py,sha256=YLCIwy89LhLnNqcM0YJ5mZoeNyCs5UiKD3Wly8gnW1E,2239
26
- uipath_langchain/tracers/AsyncUiPathTracer.py,sha256=Q-9ZkajC9HEb5lYasIrxFIFJJpNeH1iIlN3jan44GVg,8922
27
- uipath_langchain/tracers/UiPathTracer.py,sha256=V5g1nlB0TI1wYvUIkfCEcAdhy4thqeMBmjflWtxc-_M,5601
28
- uipath_langchain/tracers/__init__.py,sha256=MwrQh6iuPXMS72S5EX0JdCAX0TKe-l7fIPGV3EG0Ssk,256
26
+ uipath_langchain/tracers/AsyncUiPathTracer.py,sha256=SgFLVU8ZtRaUjIiiM5jjYqlKc-4ec3tAXwZVceDM2ng,9147
27
+ uipath_langchain/tracers/__init__.py,sha256=bMmqGCC4DsuLUdDVM4zvmVbRLPeULZ8K9ity0GAfy_4,197
29
28
  uipath_langchain/tracers/_events.py,sha256=CJri76SSdu7rGJIkXurJ2C5sQahfSK4E5UWwWYdEAtE,922
30
29
  uipath_langchain/tracers/_instrument_traceable.py,sha256=0e841zVzcPWjOGtmBx0GeHbq3JoqsmWv6gVPzDOKNTM,13496
31
30
  uipath_langchain/tracers/_utils.py,sha256=JOT1tKMdvqjMDtj2WbmbOWMeMlTXBWavxWpogX7KlRA,1543
32
31
  uipath_langchain/vectorstores/__init__.py,sha256=w8qs1P548ud1aIcVA_QhBgf_jZDrRMK5Lono78yA8cs,114
33
32
  uipath_langchain/vectorstores/context_grounding_vectorstore.py,sha256=eTa5sX43-ydB1pj9VNHUPbB-hC36fZK_CGrNe5U2Nrw,9393
34
- uipath_langchain-0.0.108.dist-info/METADATA,sha256=uaFfqlHxo67N-cJSKg2aJP6c28u_UTgXdH-eXNEHgsg,4166
35
- uipath_langchain-0.0.108.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
36
- uipath_langchain-0.0.108.dist-info/entry_points.txt,sha256=FUtzqGOEntlJKMJIXhQUfT7ZTbQmGhke1iCmDWZaQZI,81
37
- uipath_langchain-0.0.108.dist-info/licenses/LICENSE,sha256=JDpt-uotAkHFmxpwxi6gwx6HQ25e-lG4U_Gzcvgp7JY,1063
38
- uipath_langchain-0.0.108.dist-info/RECORD,,
33
+ uipath_langchain-0.0.110.dist-info/METADATA,sha256=hgEO7QrBVpVmOUglrPN6Gi0VCZcKXGvuNjjgiC9lIPA,4166
34
+ uipath_langchain-0.0.110.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
+ uipath_langchain-0.0.110.dist-info/entry_points.txt,sha256=FUtzqGOEntlJKMJIXhQUfT7ZTbQmGhke1iCmDWZaQZI,81
36
+ uipath_langchain-0.0.110.dist-info/licenses/LICENSE,sha256=JDpt-uotAkHFmxpwxi6gwx6HQ25e-lG4U_Gzcvgp7JY,1063
37
+ uipath_langchain-0.0.110.dist-info/RECORD,,
@@ -1,161 +0,0 @@
1
- import json
2
- import logging
3
- import re
4
- import uuid
5
- import warnings
6
- from os import environ as env
7
- from time import sleep
8
-
9
- import httpx
10
- from langchain_core.tracers.base import BaseTracer
11
- from langchain_core.tracers.schemas import Run
12
- from pydantic import PydanticDeprecationWarning
13
-
14
- from ._utils import _simple_serialize_defaults
15
-
16
- logger = logging.getLogger(__name__)
17
-
18
-
19
- class UiPathTracer(BaseTracer):
20
- def __init__(self, client, **kwargs):
21
- super().__init__(**kwargs)
22
-
23
- self.client = client or httpx.Client()
24
- self.retries = 3
25
-
26
- llm_ops_pattern = self._get_base_url() + "{orgId}/llmops_"
27
- self.orgId = env.get("UIPATH_ORGANIZATION_ID")
28
- self.tenantId = env.get("UIPATH_TENANT_ID")
29
- self.url = llm_ops_pattern.format(orgId=self.orgId).rstrip("/")
30
-
31
- self.auth_token = env.get("UNATTENDED_USER_ACCESS_TOKEN") or env.get(
32
- "UIPATH_ACCESS_TOKEN"
33
- )
34
-
35
- self.jobKey = env.get("UIPATH_JOB_KEY")
36
- self.folderKey = env.get("UIPATH_FOLDER_KEY")
37
- self.processKey = env.get("UIPATH_PROCESS_UUID")
38
-
39
- self.referenceId = self.jobKey or str(uuid.uuid4())
40
-
41
- self.headers = {
42
- "Authorization": f"Bearer {self.auth_token}",
43
- }
44
-
45
- def _get_base_url(self) -> str:
46
- uipath_url = (
47
- env.get("UIPATH_URL") or "https://cloud.uipath.com/dummyOrg/dummyTennant/"
48
- )
49
- uipath_url = uipath_url.rstrip("/")
50
-
51
- # split by "//" to get ['', 'https:', 'alpha.uipath.com/ada/byoa']
52
- parts = uipath_url.split("//")
53
-
54
- # after splitting by //, the base URL will be at index 1 along with the rest,
55
- # hence split it again using "/" to get ['https:', 'alpha.uipath.com', 'ada', 'byoa']
56
- base_url_parts = parts[1].split("/")
57
-
58
- # combine scheme and netloc to get the base URL
59
- base_url = parts[0] + "//" + base_url_parts[0] + "/"
60
-
61
- return base_url
62
-
63
- def init_trace(self, run_name, trace_id=None) -> None:
64
- trace_id_env = env.get("UIPATH_TRACE_ID")
65
-
66
- if trace_id_env:
67
- self.trace_parent = trace_id_env
68
- else:
69
- self.start_trace(run_name, trace_id)
70
-
71
- def start_trace(self, run_name, trace_id=None) -> None:
72
- self.trace_parent = trace_id or str(uuid.uuid4())
73
- run_name = run_name or f"Job Run: {self.trace_parent}"
74
- trace_data = {
75
- "id": self.trace_parent,
76
- "name": re.sub(
77
- r"[!@#$<>\.]", "", run_name
78
- ), # if we use these characters the Agents UI throws some error (but llmops backend seems fine)
79
- "referenceId": self.referenceId,
80
- "attributes": "{}",
81
- "organizationId": self.orgId,
82
- "tenantId": self.tenantId,
83
- }
84
-
85
- for attempt in range(self.retries):
86
- response = self.client.post(
87
- f"{self.url}/api/Agent/trace/", headers=self.headers, json=trace_data
88
- )
89
-
90
- if response.is_success:
91
- break
92
-
93
- sleep(0.5 * (2**attempt)) # Exponential backoff
94
-
95
- if 400 <= response.status_code < 600:
96
- logger.warning(
97
- f"Error when sending trace: {response}. Body is: {response.text}"
98
- )
99
-
100
- def _persist_run(self, run: Run) -> None:
101
- # when (run.id == run.parent_run_id) it's the start of a new trace
102
- # but we treat all as spans and parent to a single Trace with Id == Job.Key
103
- start_time = run.start_time.isoformat() if run.start_time is not None else None
104
- end_time = run.end_time.isoformat() if run.end_time is not None else start_time
105
-
106
- span_data = {
107
- "id": str(run.id),
108
- "parentId": str(run.parent_run_id)
109
- if run.parent_run_id is not None
110
- else None,
111
- "traceId": self.trace_parent,
112
- "name": run.name,
113
- "startTime": start_time,
114
- "endTime": end_time,
115
- "referenceId": self.referenceId,
116
- "attributes": self._safe_json_dump(self._run_to_dict(run)),
117
- "organizationId": self.orgId,
118
- "tenantId": self.tenantId,
119
- "spanType": "LangGraphRun",
120
- "status": 2 if run.error else 1,
121
- "jobKey": self.jobKey,
122
- "folderKey": self.folderKey,
123
- "processKey": self.processKey,
124
- }
125
-
126
- for attempt in range(self.retries):
127
- response = self.client.post(
128
- f"{self.url}/api/Agent/span/", headers=self.headers, json=span_data
129
- )
130
-
131
- if response.is_success:
132
- break
133
-
134
- 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
-
141
- def _end_trace(self, run: Run) -> None:
142
- super()._end_trace(run)
143
- self._persist_run(run)
144
-
145
- def _safe_json_dump(self, obj) -> str:
146
- try:
147
- json_str = json.dumps(obj, default=_simple_serialize_defaults)
148
- return json_str
149
- except Exception as e:
150
- logger.warning(e)
151
- return "{ }"
152
-
153
- def _run_to_dict(self, run: Run):
154
- with warnings.catch_warnings():
155
- warnings.simplefilter("ignore", category=PydanticDeprecationWarning)
156
-
157
- return {
158
- **run.dict(exclude={"child_runs", "inputs", "outputs"}),
159
- "inputs": run.inputs.copy() if run.inputs is not None else None,
160
- "outputs": run.outputs.copy() if run.outputs is not None else None,
161
- }