Skip to content

Commit 5c6a0dc

Browse files
committed
example
1 parent 68e8d70 commit 5c6a0dc

2 files changed

Lines changed: 584 additions & 481 deletions

File tree

src/uipath/v_next.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import abc
2+
from contextvars import ContextVar
3+
from typing import Generic, TypeVar, ContextManager
4+
5+
import logging
6+
from opentelemetry import trace
7+
from opentelemetry.sdk.trace import TracerProvider, SpanProcessor, SynchronousMultiSpanProcessor, Span
8+
from pydantic import BaseModel
9+
from typing_extensions import override
10+
11+
I = TypeVar("I")
12+
O = TypeVar("O")
13+
14+
logger = logging.getLogger(__name__)
15+
16+
class UiPathRuntime(abc.ABC, Generic[I, O]):
17+
@abc.abstractmethod
18+
def execute(self, input: I) -> O:
19+
"""
20+
Execute the agent.
21+
"""
22+
raise NotImplementedError()
23+
24+
25+
class MyAgentInput(BaseModel):
26+
query: str
27+
28+
class MyAgentOutput(BaseModel):
29+
response: str
30+
31+
32+
class MyAgent(UiPathRuntime[MyAgentInput, MyAgentOutput]):
33+
@override
34+
def execute(self, input: MyAgentInput) -> MyAgentOutput:
35+
print("Running agent with input:", input)
36+
return MyAgentOutput(response="AgentExecuted!")
37+
38+
class MultiSpanProcessor(SynchronousMultiSpanProcessor):
39+
def remove_span_processor(self, span_processor: SpanProcessor) -> None:
40+
with self._lock:
41+
temp_list = list(self._span_processors)
42+
temp_list.remove(span_processor)
43+
self._span_processors = tuple(temp_list)
44+
45+
uipath_multi_span_processor_context = ContextVar("uipath_multi_span_processor")
46+
class SpanProcessorContext(ContextManager):
47+
def __init__(self, span_processor: SpanProcessor):
48+
self.span_processor = span_processor
49+
50+
def __enter__(self):
51+
uipath_multi_span_processor:MultiSpanProcessor = uipath_multi_span_processor_context.get()
52+
if uipath_multi_span_processor:
53+
uipath_multi_span_processor.add_span_processor(self.span_processor)
54+
else:
55+
print("WARNING: CALL INIT!")
56+
57+
def __exit__(self, exc_type, exc_val, exc_tb):
58+
uipath_multi_span_processor = uipath_multi_span_processor_context.get()
59+
if uipath_multi_span_processor:
60+
uipath_multi_span_processor.remove_span_processor(self.span_processor)
61+
self.span_processor.shutdown()
62+
63+
64+
def add_span_processor(span_processor: SpanProcessor) -> SpanProcessorContext:
65+
return SpanProcessorContext(span_processor)
66+
67+
68+
def init():
69+
# setup tracer
70+
tracer_provider = TracerProvider()
71+
span_processor = MultiSpanProcessor()
72+
tracer_provider.add_span_processor(span_processor)
73+
trace.set_tracer_provider(tracer_provider)
74+
uipath_multi_span_processor_context.set(span_processor)
75+
76+
77+
78+
if __name__ == '__main__':
79+
# in uipath base command (applicable to everything)
80+
# invoke uipath_init() which sets up tracers and what not.
81+
init()
82+
83+
# in CLI-run
84+
entrypoint = "v_next.py:MyAgent"
85+
input_json = {"query": "query!"}
86+
# Note: input needs to be converted into correct object type.
87+
input_object = MyAgentInput(**input_json)
88+
# agent = RuntimeFactory.load(entrypoint) # this initializes the agent using contructor.
89+
agent = MyAgent()
90+
91+
class ConsoleLoggerProcessor(SpanProcessor):
92+
def on_start(self, span: Span, parent_context=None):
93+
print("Started span input:", span)
94+
95+
# Note: eval can add UiPathRuntimeExecutionSpanExporter for evaluation purposes.
96+
with add_span_processor(ConsoleLoggerProcessor()) as span_exporter:
97+
tracer = trace.get_tracer("uipath-runtime")
98+
with tracer.start_as_current_span(
99+
name="root",
100+
attributes={},
101+
):
102+
result = agent.execute(input_object)
103+
print("Agent result:",result)

0 commit comments

Comments
 (0)