Skip to content

Commit fe34fae

Browse files
feat: fix input schema for chat
1 parent 384ac13 commit fe34fae

1 file changed

Lines changed: 75 additions & 39 deletions

File tree

  • packages/uipath-llamaindex/src/uipath_llamaindex/runtime

packages/uipath-llamaindex/src/uipath_llamaindex/runtime/schema.py

Lines changed: 75 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
ToolCall,
99
ToolCallResult,
1010
)
11-
from pydantic import BaseModel
1211
from uipath.runtime.schema import (
1312
UiPathRuntimeEdge,
1413
UiPathRuntimeGraph,
@@ -25,67 +24,104 @@
2524
)
2625

2726

27+
def _conversation_message_item_schema() -> dict[str, Any]:
28+
"""Minimal message schema: only role and contentParts required, contentParts items only need data.inline."""
29+
return {
30+
"type": "object",
31+
"properties": {
32+
"role": {"type": "string"},
33+
"contentParts": {
34+
"type": "array",
35+
"items": {
36+
"type": "object",
37+
"properties": {
38+
"mimeType": {"type": "string"},
39+
"data": {
40+
"type": "object",
41+
"properties": {
42+
"inline": {},
43+
},
44+
"required": ["inline"],
45+
},
46+
"citations": {"type": "array", "items": {"type": "object"}},
47+
},
48+
"required": ["data"],
49+
},
50+
},
51+
"toolCalls": {"type": "array", "items": {"type": "object"}},
52+
"interrupts": {"type": "array", "items": {"type": "object"}},
53+
},
54+
"required": ["role", "contentParts"],
55+
}
56+
57+
58+
def _default_messages_schema() -> dict[str, Any]:
59+
"""Default messages schema using minimal UiPath conversation message format."""
60+
return {
61+
"type": "object",
62+
"properties": {
63+
"messages": {
64+
"type": "array",
65+
"items": _conversation_message_item_schema(),
66+
"title": "Messages",
67+
"description": "UiPath conversation messages",
68+
}
69+
},
70+
"required": ["messages"],
71+
}
72+
73+
74+
def _default_input_schema() -> dict[str, Any]:
75+
"""Default input schema using UiPath conversation message format."""
76+
return _default_messages_schema()
77+
78+
79+
def _default_output_schema() -> dict[str, Any]:
80+
"""Default output schema using UiPath conversation message format."""
81+
return _default_messages_schema()
82+
83+
2884
def get_entrypoints_schema(workflow: Workflow) -> dict[str, Any]:
2985
"""
3086
Extract input/output schema from a LlamaIndex workflow.
3187
88+
For chat agents (BaseWorkflowAgent), uses the default UiPath messages schema
89+
for both input and output (matching the google-adk integration convention).
90+
For regular workflows, extracts schema from StartEvent/StopEvent.
91+
3292
Args:
3393
workflow: A LlamaIndex Workflow instance
3494
3595
Returns:
3696
Dictionary with input and output schemas
3797
"""
3898
schema = {
39-
"input": {"type": "object", "properties": {}, "required": []},
40-
"output": {"type": "object", "properties": {}, "required": []},
99+
"input": _default_input_schema(),
100+
"output": _default_output_schema(),
41101
}
42102

103+
# Chat agents use the messages schema for input/output — do not override from events
104+
if isinstance(workflow, BaseWorkflowAgent):
105+
return schema
106+
43107
# Find the actual StartEvent and StopEvent classes used in this workflow
44108
start_event_class = workflow._start_event_class
45109
stop_event_class = workflow._stop_event_class
46110

47111
# Generate input schema from StartEvent
48112
try:
49-
if isinstance(workflow, BaseWorkflowAgent):
50-
# For workflow agents, define a simple schema with just user_msg
51-
schema["input"] = {
52-
"type": "object",
53-
"properties": {
54-
"user_msg": {
55-
"type": "string",
56-
"title": "User Message",
57-
"description": "The user's question or request",
58-
}
59-
},
60-
"required": ["user_msg"],
61-
}
62-
else:
63-
input_schema = start_event_class.model_json_schema()
64-
# Resolve references and handle nullable types
65-
unpacked_input, _ = transform_references(input_schema)
66-
schema["input"]["properties"] = transform_nullable_types(
67-
unpacked_input.get("properties", {})
68-
)
69-
schema["input"]["required"] = unpacked_input.get("required", [])
113+
input_schema = start_event_class.model_json_schema()
114+
# Resolve references and handle nullable types
115+
unpacked_input, _ = transform_references(input_schema)
116+
schema["input"]["properties"] = transform_nullable_types(
117+
unpacked_input.get("properties", {})
118+
)
119+
schema["input"]["required"] = unpacked_input.get("required", [])
70120
except (AttributeError, Exception):
71121
pass
72122

73-
# Handle output schema - check if it's a workflow agent with output_cls first
74-
if isinstance(workflow, BaseWorkflowAgent):
75-
output_cls: type[BaseModel] | None = getattr(workflow, "output_cls", None)
76-
if output_cls is not None:
77-
try:
78-
output_schema = output_cls.model_json_schema()
79-
# Resolve references and handle nullable types
80-
unpacked_output, _ = transform_references(output_schema)
81-
schema["output"]["properties"] = transform_nullable_types(
82-
unpacked_output.get("properties", {})
83-
)
84-
schema["output"]["required"] = unpacked_output.get("required", [])
85-
except (AttributeError, Exception):
86-
pass
87123
# Check if it's the base StopEvent or a custom subclass
88-
elif stop_event_class is StopEvent:
124+
if stop_event_class is StopEvent:
89125
# base StopEvent
90126
schema["output"] = {
91127
"type": "object",

0 commit comments

Comments
 (0)