uipath-langchain 0.0.132__py3-none-any.whl → 0.0.134__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.
- uipath_langchain/_cli/cli_eval.py +20 -6
- uipath_langchain/tools/__init__.py +0 -0
- uipath_langchain/tools/preconfigured.py +191 -0
- {uipath_langchain-0.0.132.dist-info → uipath_langchain-0.0.134.dist-info}/METADATA +3 -2
- {uipath_langchain-0.0.132.dist-info → uipath_langchain-0.0.134.dist-info}/RECORD +8 -6
- {uipath_langchain-0.0.132.dist-info → uipath_langchain-0.0.134.dist-info}/WHEEL +0 -0
- {uipath_langchain-0.0.132.dist-info → uipath_langchain-0.0.134.dist-info}/entry_points.txt +0 -0
- {uipath_langchain-0.0.132.dist-info → uipath_langchain-0.0.134.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import uuid
|
|
2
3
|
from typing import List, Optional
|
|
3
4
|
|
|
4
5
|
from openinference.instrumentation.langchain import (
|
|
5
6
|
LangChainInstrumentor,
|
|
6
7
|
get_current_span,
|
|
7
8
|
)
|
|
9
|
+
from uipath._cli._evals._progress_reporter import StudioWebProgressReporter
|
|
8
10
|
from uipath._cli._evals._runtime import UiPathEvalContext, UiPathEvalRuntime
|
|
9
11
|
from uipath._cli._runtime._contracts import (
|
|
10
12
|
UiPathRuntimeFactory,
|
|
11
13
|
)
|
|
12
14
|
from uipath._cli._utils._eval_set import EvalHelpers
|
|
13
15
|
from uipath._cli.middlewares import MiddlewareResult
|
|
16
|
+
from uipath._events._event_bus import EventBus
|
|
14
17
|
from uipath.eval._helpers import auto_discover_entrypoint
|
|
15
18
|
|
|
16
19
|
from uipath_langchain._cli._runtime._context import LangGraphRuntimeContext
|
|
@@ -31,14 +34,16 @@ def langgraph_eval_middleware(
|
|
|
31
34
|
should_continue=True
|
|
32
35
|
) # Continue with normal flow if no langgraph.json
|
|
33
36
|
|
|
34
|
-
eval_context = UiPathEvalContext.with_defaults(**kwargs)
|
|
35
|
-
eval_context.eval_set = eval_set or EvalHelpers.auto_discover_eval_set()
|
|
36
|
-
eval_context.eval_ids = eval_ids
|
|
37
|
-
|
|
38
37
|
try:
|
|
39
38
|
_instrument_traceable_attributes()
|
|
40
39
|
|
|
41
|
-
|
|
40
|
+
event_bus = EventBus()
|
|
41
|
+
|
|
42
|
+
if not kwargs.get("no_report", False):
|
|
43
|
+
progress_reporter = StudioWebProgressReporter(
|
|
44
|
+
spans_exporter=LangChainExporter()
|
|
45
|
+
)
|
|
46
|
+
asyncio.run(progress_reporter.subscribe_to_eval_runtime_events(event_bus))
|
|
42
47
|
|
|
43
48
|
def generate_runtime_context(
|
|
44
49
|
context_entrypoint: str, langgraph_config: LangGraphConfig, **context_kwargs
|
|
@@ -48,6 +53,14 @@ def langgraph_eval_middleware(
|
|
|
48
53
|
context.entrypoint = context_entrypoint
|
|
49
54
|
return context
|
|
50
55
|
|
|
56
|
+
runtime_entrypoint = entrypoint or auto_discover_entrypoint()
|
|
57
|
+
|
|
58
|
+
eval_context = UiPathEvalContext.with_defaults(
|
|
59
|
+
entrypoint=runtime_entrypoint, execution_id=str(uuid.uuid4()), **kwargs
|
|
60
|
+
)
|
|
61
|
+
eval_context.eval_set = eval_set or EvalHelpers.auto_discover_eval_set()
|
|
62
|
+
eval_context.eval_ids = eval_ids
|
|
63
|
+
|
|
51
64
|
runtime_factory = UiPathRuntimeFactory(
|
|
52
65
|
LangGraphRuntime,
|
|
53
66
|
LangGraphRuntimeContext,
|
|
@@ -65,9 +78,10 @@ def langgraph_eval_middleware(
|
|
|
65
78
|
|
|
66
79
|
async def execute():
|
|
67
80
|
async with UiPathEvalRuntime.from_eval_context(
|
|
68
|
-
factory=runtime_factory, context=eval_context
|
|
81
|
+
factory=runtime_factory, context=eval_context, event_bus=event_bus
|
|
69
82
|
) as eval_runtime:
|
|
70
83
|
await eval_runtime.execute()
|
|
84
|
+
await event_bus.wait_for_all()
|
|
71
85
|
|
|
72
86
|
asyncio.run(execute())
|
|
73
87
|
return MiddlewareResult(should_continue=False)
|
|
File without changes
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Iterable, Optional, Type
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
from jsonschema_pydantic import jsonschema_to_pydantic as create_model # type: ignore
|
|
7
|
+
from langchain_core.caches import BaseCache
|
|
8
|
+
from langchain_core.runnables.utils import Output
|
|
9
|
+
from langchain_core.tools import BaseTool, StructuredTool
|
|
10
|
+
from langgraph.types import interrupt
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
from uipath import UiPath
|
|
13
|
+
from uipath.agent.models.agent import (
|
|
14
|
+
AgentDefinition,
|
|
15
|
+
AgentEscalationChannel,
|
|
16
|
+
AgentEscalationResourceConfig,
|
|
17
|
+
AgentIntegrationToolResourceConfig,
|
|
18
|
+
AgentProcessToolResourceConfig,
|
|
19
|
+
AgentResourceConfig,
|
|
20
|
+
)
|
|
21
|
+
from uipath.models import CreateAction, InvokeProcess
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def create_process_tool(resource: AgentProcessToolResourceConfig) -> Iterable[BaseTool]:
|
|
27
|
+
async def process(**kwargs) -> BaseModel:
|
|
28
|
+
return interrupt(
|
|
29
|
+
InvokeProcess(
|
|
30
|
+
name=resource.name,
|
|
31
|
+
input_arguments=kwargs,
|
|
32
|
+
process_folder_path=resource.properties.folder_path,
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
input_schema = create_model(resource.input_schema)
|
|
37
|
+
|
|
38
|
+
class ProcessTool(StructuredTool):
|
|
39
|
+
@property
|
|
40
|
+
def OutputType(self) -> type[Output]:
|
|
41
|
+
return create_model(resource.output_schema)
|
|
42
|
+
|
|
43
|
+
yield ProcessTool(
|
|
44
|
+
name=resource.name,
|
|
45
|
+
args_schema=input_schema,
|
|
46
|
+
description=resource.description,
|
|
47
|
+
coroutine=process,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def create_escalation_tool_from_channel(channel: AgentEscalationChannel) -> BaseTool:
|
|
52
|
+
async def escalate(**kwargs) -> BaseModel:
|
|
53
|
+
recipients = channel.recipients
|
|
54
|
+
if len(recipients) > 1:
|
|
55
|
+
logger.warning(
|
|
56
|
+
"Received more than one recipient. Defaulting to first recipient."
|
|
57
|
+
)
|
|
58
|
+
assignee = recipients[0].value if recipients else None
|
|
59
|
+
return interrupt(
|
|
60
|
+
CreateAction(
|
|
61
|
+
title=channel.description,
|
|
62
|
+
data=kwargs,
|
|
63
|
+
assignee=assignee,
|
|
64
|
+
app_name=channel.properties.app_name,
|
|
65
|
+
app_folder_path=None, # Channels specify folder name but not folder path.
|
|
66
|
+
app_folder_key=channel.properties.resource_key,
|
|
67
|
+
app_key=channel.properties.resource_key,
|
|
68
|
+
app_version=channel.properties.app_version,
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
input_schema = create_model(channel.input_schema)
|
|
73
|
+
|
|
74
|
+
class EscalationTool(StructuredTool):
|
|
75
|
+
@property
|
|
76
|
+
def OutputType(self) -> type[Output]:
|
|
77
|
+
return create_model(channel.output_schema)
|
|
78
|
+
|
|
79
|
+
return EscalationTool(
|
|
80
|
+
name=channel.name,
|
|
81
|
+
args_schema=input_schema,
|
|
82
|
+
description=channel.description,
|
|
83
|
+
coroutine=escalate,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def create_escalation_tool(
|
|
88
|
+
resource: AgentEscalationResourceConfig,
|
|
89
|
+
) -> Iterable[BaseTool]:
|
|
90
|
+
for channel in resource.channels:
|
|
91
|
+
yield create_escalation_tool_from_channel(channel)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def create_integration_tool(
|
|
95
|
+
resource: AgentIntegrationToolResourceConfig,
|
|
96
|
+
) -> Iterable[BaseTool]:
|
|
97
|
+
async def integration(**kwargs) -> BaseModel:
|
|
98
|
+
uipath = UiPath()
|
|
99
|
+
remote_connection = await uipath.connections.retrieve_async(
|
|
100
|
+
resource.properties.connection.id
|
|
101
|
+
)
|
|
102
|
+
token = await uipath.connections.retrieve_token_async(
|
|
103
|
+
resource.properties.connection.id
|
|
104
|
+
)
|
|
105
|
+
tool_url = f"{remote_connection.api_base_uri}/v3/element/instances/{remote_connection.element_instance_id}{resource.properties.tool_path}"
|
|
106
|
+
|
|
107
|
+
response = await httpx.AsyncClient().request(
|
|
108
|
+
resource.properties.method,
|
|
109
|
+
tool_url,
|
|
110
|
+
headers={"Authorization": f"Bearer {token.access_token}"},
|
|
111
|
+
content=json.dumps(kwargs),
|
|
112
|
+
)
|
|
113
|
+
return response.json()
|
|
114
|
+
|
|
115
|
+
input_schema = create_model(resource.input_schema)
|
|
116
|
+
|
|
117
|
+
class IntegrationTool(StructuredTool):
|
|
118
|
+
@property
|
|
119
|
+
def OutputType(self) -> type[Output]:
|
|
120
|
+
return create_model({})
|
|
121
|
+
|
|
122
|
+
yield IntegrationTool(
|
|
123
|
+
name=resource.name,
|
|
124
|
+
args_schema=input_schema,
|
|
125
|
+
description=resource.description,
|
|
126
|
+
coroutine=integration,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def create_cached_wrapper_from_tool(
|
|
131
|
+
wrapped: BaseTool, cache: Optional[BaseCache]
|
|
132
|
+
) -> BaseTool:
|
|
133
|
+
if cache is None:
|
|
134
|
+
return wrapped
|
|
135
|
+
else:
|
|
136
|
+
|
|
137
|
+
async def cached_invocation(**kwargs) -> BaseModel:
|
|
138
|
+
namespace = f"{wrapped.name}.tool_invoke"
|
|
139
|
+
key = str(kwargs)
|
|
140
|
+
cached = cache.lookup(namespace, key)
|
|
141
|
+
if cached:
|
|
142
|
+
return cached[0]
|
|
143
|
+
response = await wrapped.ainvoke(input=kwargs)
|
|
144
|
+
cache.update(namespace, key, [response])
|
|
145
|
+
return response
|
|
146
|
+
|
|
147
|
+
input_schema = wrapped.args_schema
|
|
148
|
+
|
|
149
|
+
class CachedTool(StructuredTool):
|
|
150
|
+
OutputType: Type[BaseModel] = wrapped.OutputType
|
|
151
|
+
|
|
152
|
+
return CachedTool(
|
|
153
|
+
name=wrapped.name,
|
|
154
|
+
args_schema=input_schema,
|
|
155
|
+
description=wrapped.description,
|
|
156
|
+
coroutine=cached_invocation,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def create_cached_wrapper(
|
|
161
|
+
tools: Iterable[BaseTool], cache: Optional[BaseCache]
|
|
162
|
+
) -> Iterable[BaseTool]:
|
|
163
|
+
for wrapped in tools:
|
|
164
|
+
yield create_cached_wrapper_from_tool(wrapped, cache)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def create_resource_tool(
|
|
168
|
+
resource: AgentResourceConfig, cache: Optional[BaseCache] = None
|
|
169
|
+
) -> Iterable[BaseTool]:
|
|
170
|
+
match resource:
|
|
171
|
+
case AgentProcessToolResourceConfig():
|
|
172
|
+
return create_cached_wrapper(create_process_tool(resource), cache)
|
|
173
|
+
case AgentIntegrationToolResourceConfig():
|
|
174
|
+
return create_cached_wrapper(create_integration_tool(resource), cache)
|
|
175
|
+
case AgentEscalationResourceConfig():
|
|
176
|
+
return create_cached_wrapper(create_escalation_tool(resource), cache)
|
|
177
|
+
case _:
|
|
178
|
+
raise NotImplementedError()
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def safe_extract_tools(
|
|
182
|
+
agent_definition: AgentDefinition, cache: Optional[BaseCache] = None
|
|
183
|
+
) -> list[BaseTool]:
|
|
184
|
+
tools = []
|
|
185
|
+
for resource in agent_definition.resources:
|
|
186
|
+
try:
|
|
187
|
+
for structured_tool in create_resource_tool(resource, cache):
|
|
188
|
+
tools.append(structured_tool)
|
|
189
|
+
except NotImplementedError:
|
|
190
|
+
logger.warning(f"Unable to convert {resource.name} into a tool.")
|
|
191
|
+
return tools
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uipath-langchain
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.134
|
|
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
|
|
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
15
15
|
Classifier: Topic :: Software Development :: Build Tools
|
|
16
16
|
Requires-Python: >=3.10
|
|
17
17
|
Requires-Dist: httpx>=0.27.0
|
|
18
|
+
Requires-Dist: jsonschema-pydantic>=0.6
|
|
18
19
|
Requires-Dist: langchain-community>=0.3.21
|
|
19
20
|
Requires-Dist: langchain-core>=0.3.34
|
|
20
21
|
Requires-Dist: langchain-openai>=0.3.3
|
|
@@ -25,7 +26,7 @@ Requires-Dist: openai>=1.65.5
|
|
|
25
26
|
Requires-Dist: openinference-instrumentation-langchain>=0.1.50
|
|
26
27
|
Requires-Dist: pydantic-settings>=2.6.0
|
|
27
28
|
Requires-Dist: python-dotenv>=1.0.1
|
|
28
|
-
Requires-Dist: uipath<2.2.0,>=2.1.
|
|
29
|
+
Requires-Dist: uipath<2.2.0,>=2.1.64
|
|
29
30
|
Provides-Extra: langchain
|
|
30
31
|
Description-Content-Type: text/markdown
|
|
31
32
|
|
|
@@ -2,7 +2,7 @@ uipath_langchain/__init__.py,sha256=VBrvQn7d3nuOdN7zEnV2_S-uhmkjgEIlXiFVeZxZakQ,
|
|
|
2
2
|
uipath_langchain/middlewares.py,sha256=6ljfbtWekrYc5G9KWDLSaViJ1DVIaNM-4qeB1BfHywE,731
|
|
3
3
|
uipath_langchain/_cli/__init__.py,sha256=juqd9PbXs4yg45zMJ7BHAOPQjb7sgEbWE9InBtGZhfo,24
|
|
4
4
|
uipath_langchain/_cli/cli_dev.py,sha256=3e9RldNGirIk9184NdLK6kDuGeeqZjekTxbSZRtXjBE,1505
|
|
5
|
-
uipath_langchain/_cli/cli_eval.py,sha256=
|
|
5
|
+
uipath_langchain/_cli/cli_eval.py,sha256=OBU8ADax8eF6KKOC8vxqdDR8YbuXiIe_r632p7SzveA,3386
|
|
6
6
|
uipath_langchain/_cli/cli_init.py,sha256=xhxJ8tuMSrVUNHvltgyPpOrvgMA-wq9shHeYYwvHILs,8199
|
|
7
7
|
uipath_langchain/_cli/cli_new.py,sha256=KKLxCzz7cDQ__rRr_a496IHWlSQXhmrBNgmKHnXAnTY,2336
|
|
8
8
|
uipath_langchain/_cli/cli_run.py,sha256=hRcoXJgOIFceCswzTfZKyzqVee3j-oSh-13EfuQmmE8,2614
|
|
@@ -30,10 +30,12 @@ uipath_langchain/embeddings/__init__.py,sha256=QICtYB58ZyqFfDQrEaO8lTEgAU5NuEKlR
|
|
|
30
30
|
uipath_langchain/embeddings/embeddings.py,sha256=45gKyb6HVKigwE-0CXeZcAk33c0mteaEdPGa8hviqcw,4339
|
|
31
31
|
uipath_langchain/retrievers/__init__.py,sha256=rOn7PyyHgZ4pMnXWPkGqmuBmx8eGuo-Oyndo7Wm9IUU,108
|
|
32
32
|
uipath_langchain/retrievers/context_grounding_retriever.py,sha256=YLCIwy89LhLnNqcM0YJ5mZoeNyCs5UiKD3Wly8gnW1E,2239
|
|
33
|
+
uipath_langchain/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
|
+
uipath_langchain/tools/preconfigured.py,sha256=Ucl9mta_su66j-5uOC-vZzyc3V2-Em6q9WO1qsmQv48,6291
|
|
33
35
|
uipath_langchain/vectorstores/__init__.py,sha256=w8qs1P548ud1aIcVA_QhBgf_jZDrRMK5Lono78yA8cs,114
|
|
34
36
|
uipath_langchain/vectorstores/context_grounding_vectorstore.py,sha256=TncIXG-YsUlO0R5ZYzWsM-Dj1SVCZbzmo2LraVxXelc,9559
|
|
35
|
-
uipath_langchain-0.0.
|
|
36
|
-
uipath_langchain-0.0.
|
|
37
|
-
uipath_langchain-0.0.
|
|
38
|
-
uipath_langchain-0.0.
|
|
39
|
-
uipath_langchain-0.0.
|
|
37
|
+
uipath_langchain-0.0.134.dist-info/METADATA,sha256=jqUMjAKUcTSiZQNCXpW2OF5jhoSzvkziuuG2nE7Vtu4,4275
|
|
38
|
+
uipath_langchain-0.0.134.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
39
|
+
uipath_langchain-0.0.134.dist-info/entry_points.txt,sha256=FUtzqGOEntlJKMJIXhQUfT7ZTbQmGhke1iCmDWZaQZI,81
|
|
40
|
+
uipath_langchain-0.0.134.dist-info/licenses/LICENSE,sha256=JDpt-uotAkHFmxpwxi6gwx6HQ25e-lG4U_Gzcvgp7JY,1063
|
|
41
|
+
uipath_langchain-0.0.134.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|