Skip to content

Commit a1ad5e3

Browse files
fix: deeprag prefix fix (#674)
Co-authored-by: Gabriel Martin <91462031+gcuip@users.noreply.github.com>
1 parent 7be0c92 commit a1ad5e3

3 files changed

Lines changed: 100 additions & 18 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uipath-langchain"
3-
version = "0.8.8"
3+
version = "0.8.10"
44
description = "Python SDK that enables developers to build and deploy LangGraph agents to the UiPath Cloud Platform"
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"

src/uipath_langchain/agent/tools/context_tool.py

Lines changed: 98 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
"""Context tool creation for semantic index retrieval."""
22

33
import uuid
4-
from typing import Any, Optional
4+
from typing import Any, Dict, Optional
55

66
from langchain_core.documents import Document
77
from langchain_core.messages import ToolCall
88
from langchain_core.tools import BaseTool, StructuredTool
9-
from pydantic import BaseModel, Field, create_model
9+
from pydantic import BaseModel, Field, TypeAdapter, create_model
1010
from uipath.agent.models.agent import (
1111
AgentContextResourceConfig,
1212
AgentContextRetrievalMode,
13+
AgentToolArgumentProperties,
1314
)
1415
from uipath.eval.mocks import mockable
1516
from uipath.platform import UiPath
@@ -41,6 +42,44 @@
4142
from .tool_node import ToolWrapperReturnType
4243
from .utils import sanitize_tool_name
4344

45+
_ARG_PROPS_ADAPTER = TypeAdapter(Dict[str, AgentToolArgumentProperties])
46+
47+
48+
def _get_argument_properties(
49+
resource: AgentContextResourceConfig,
50+
) -> dict[str, AgentToolArgumentProperties]:
51+
"""Extract argumentProperties from the resource's extra fields.
52+
53+
AgentContextResourceConfig doesn't declare argument_properties yet,
54+
but BaseCfg(extra="allow") preserves the raw JSON value.
55+
"""
56+
raw = (
57+
resource.model_extra.get("argumentProperties") if resource.model_extra else None
58+
)
59+
if not raw:
60+
return {}
61+
return _ARG_PROPS_ADAPTER.validate_python(raw)
62+
63+
64+
def _build_folder_path_prefix_arg_props(
65+
resource: AgentContextResourceConfig,
66+
) -> dict[str, Any]:
67+
"""Build argument_properties for folder_path_prefix from settings.
68+
69+
Fallback for when settings bag doesn't include argumentProperties
70+
at the resource level but does set settings.folder_path_prefix
71+
with variant="argument".
72+
"""
73+
assert resource.settings.folder_path_prefix is not None
74+
argument_path = (resource.settings.folder_path_prefix.value or "").strip("{}")
75+
return {
76+
"folder_path_prefix": {
77+
"variant": "argument",
78+
"argumentPath": argument_path,
79+
"isSensitive": False,
80+
}
81+
}
82+
4483

4584
def is_static_query(resource: AgentContextResourceConfig) -> bool:
4685
"""Check if the resource configuration uses a static query variant."""
@@ -152,27 +191,31 @@ def handle_deep_rag(
152191
if static:
153192
assert prompt is not None
154193

155-
folder_path_prefix = None
194+
static_folder_path_prefix = None
156195
if (
157196
resource.settings.folder_path_prefix
158197
and resource.settings.folder_path_prefix.value
198+
and resource.settings.folder_path_prefix.variant == "static"
159199
):
160-
folder_path_prefix = resource.settings.folder_path_prefix.value
200+
static_folder_path_prefix = resource.settings.folder_path_prefix.value
161201

162202
file_extension = None
163203
if resource.settings.file_extension and resource.settings.file_extension.value:
164204
file_extension = resource.settings.file_extension.value
165205

166-
glob_pattern = build_glob_pattern(
167-
folder_path_prefix=folder_path_prefix, file_extension=file_extension
168-
)
169-
170206
output_model = create_model(
171207
"DeepRagOutputModel",
172208
__base__=DeepRagContent,
173209
deep_rag_id=(str, Field(alias="deepRagId")),
174210
)
175211

212+
arg_props = _get_argument_properties(resource)
213+
214+
has_folder_path_prefix_arg = "folder_path_prefix" in arg_props or (
215+
resource.settings.folder_path_prefix
216+
and resource.settings.folder_path_prefix.variant == "argument"
217+
)
218+
176219
schema_fields: dict[str, Any] = (
177220
{}
178221
if static
@@ -186,6 +229,18 @@ def handle_deep_rag(
186229
),
187230
}
188231
)
232+
233+
if has_folder_path_prefix_arg:
234+
schema_fields["folder_path_prefix"] = (
235+
str,
236+
Field(
237+
default=None,
238+
description="The folder path prefix within the index to filter on",
239+
),
240+
)
241+
if "folder_path_prefix" not in arg_props:
242+
arg_props = _build_folder_path_prefix_arg_props(resource)
243+
189244
input_model = create_model("DeepRagInput", **schema_fields)
190245

191246
@mockable(
@@ -195,8 +250,14 @@ def handle_deep_rag(
195250
output_schema=output_model.model_json_schema(),
196251
example_calls=[], # Examples cannot be provided for context.
197252
)
198-
async def context_tool_fn(query: Optional[str] = None) -> dict[str, Any]:
253+
async def context_tool_fn(
254+
query: Optional[str] = None, folder_path_prefix: Optional[str] = None
255+
) -> dict[str, Any]:
199256
actual_prompt = prompt or query
257+
glob_pattern = build_glob_pattern(
258+
folder_path_prefix=static_folder_path_prefix or folder_path_prefix,
259+
file_extension=file_extension,
260+
)
200261

201262
@durable_interrupt
202263
async def create_deep_rag():
@@ -211,12 +272,13 @@ async def create_deep_rag():
211272

212273
return await create_deep_rag()
213274

214-
return StructuredToolWithOutputType(
275+
return StructuredToolWithArgumentProperties(
215276
name=tool_name,
216277
description=resource.description,
217278
args_schema=input_model,
218279
coroutine=context_tool_fn,
219280
output_type=output_model,
281+
argument_properties=arg_props,
220282
metadata={
221283
"tool_type": "context",
222284
"display_name": resource.name,
@@ -271,15 +333,19 @@ def handle_batch_transform(
271333
if static:
272334
assert prompt is not None
273335

274-
folder_path_prefix = None
336+
static_folder_path_prefix = None
275337
if (
276338
resource.settings.folder_path_prefix
277339
and resource.settings.folder_path_prefix.value
340+
and resource.settings.folder_path_prefix.variant == "static"
278341
):
279-
folder_path_prefix = resource.settings.folder_path_prefix.value
342+
static_folder_path_prefix = resource.settings.folder_path_prefix.value
280343

281-
glob_pattern = build_glob_pattern(
282-
folder_path_prefix=folder_path_prefix, file_extension=None
344+
arg_props = _get_argument_properties(resource)
345+
346+
has_folder_path_prefix_arg = "folder_path_prefix" in arg_props or (
347+
resource.settings.folder_path_prefix
348+
and resource.settings.folder_path_prefix.variant == "argument"
283349
)
284350

285351
output_model = create_model_from_schema(BATCH_TRANSFORM_OUTPUT_SCHEMA)
@@ -300,6 +366,16 @@ def handle_batch_transform(
300366
description="The relative file path destination for the modified csv file",
301367
),
302368
)
369+
if has_folder_path_prefix_arg:
370+
schema_fields["folder_path_prefix"] = (
371+
str,
372+
Field(
373+
default=None,
374+
description="The folder path prefix within the index to filter on",
375+
),
376+
)
377+
if "folder_path_prefix" not in arg_props:
378+
arg_props = _build_folder_path_prefix_arg_props(resource)
303379
input_model = create_model("BatchTransformInput", **schema_fields)
304380

305381
@mockable(
@@ -310,9 +386,15 @@ def handle_batch_transform(
310386
example_calls=[], # Examples cannot be provided for context.
311387
)
312388
async def context_tool_fn(
313-
query: Optional[str] = None, destination_path: str = "output.csv"
389+
query: Optional[str] = None,
390+
destination_path: str = "output.csv",
391+
folder_path_prefix: Optional[str] = None,
314392
) -> dict[str, Any]:
315393
actual_prompt = prompt or query
394+
glob_pattern = build_glob_pattern(
395+
folder_path_prefix=static_folder_path_prefix or folder_path_prefix,
396+
file_extension=None,
397+
)
316398

317399
@durable_interrupt
318400
async def create_batch_transform():
@@ -362,7 +444,7 @@ async def context_batch_transform_wrapper(
362444
args_schema=input_model,
363445
coroutine=context_tool_fn,
364446
output_type=output_model,
365-
argument_properties={},
447+
argument_properties=arg_props,
366448
metadata={
367449
"tool_type": "context",
368450
"display_name": resource.name,

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)