Duibonduil commited on
Commit
fb49ac2
·
verified ·
1 Parent(s): 1e3a82d

Upload 9 files

Browse files
examples/trace/asyncio_test.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import aworld.trace as trace
3
+ from aworld.logs.util import logger
4
+ trace.configure()
5
+
6
+
7
+ async def async_handler(name):
8
+ async with trace.span("async_handler") as span:
9
+ logger.info(f"async_handler start {name}")
10
+ await asyncio.sleep(1)
11
+ logger.info(f"async_handler end {name}")
12
+
13
+
14
+ async def async_handler2(name):
15
+ span = trace.get_current_span()
16
+ logger.info(f"async_handler2 span: {span.get_trace_id()}")
17
+ logger.info(f"async_handler2 start {name}")
18
+ await asyncio.sleep(1)
19
+ logger.info(f"async_handler2 end {name}")
20
+
21
+
22
+ async def test1():
23
+ logger.info(f"hello test1")
24
+ task = asyncio.create_task(async_handler('test1'))
25
+ # await task
26
+ logger.info(f"hello test1 end")
27
+
28
+
29
+ async def test2():
30
+ async with trace.span("test2") as span:
31
+ logger.info(f"hello test2")
32
+ task = asyncio.create_task(async_handler2(
33
+ 'test2'))
34
+ # await task
35
+ logger.info(f"hello test2 end")
36
+
37
+ if __name__ == "__main__":
38
+ with trace.span("hello") as span:
39
+ logger.info(f"main execute")
40
+ asyncio.run(test2())
41
+ asyncio.run(test1())
examples/trace/autotrace_demo.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+
3
+ class TestClassA:
4
+
5
+ def classa_function_1(self):
6
+ print("classa_function_1")
7
+
8
+ def classa_function_2(self):
9
+ time.sleep(0.02)
10
+ print("classa_function_2")
11
+
12
+ def classa_function_3(self):
13
+ print("classa_function_3")
14
+
15
+ class TestClassB:
16
+ def classb_function_1(self):
17
+ time.sleep(0.02)
18
+ print("classb_function_1")
19
+ def classb_function_2(self):
20
+ a = TestClassA()
21
+ a.classa_function_1()
22
+ a.classa_function_2()
23
+ a.classa_function_3()
24
+ print("classb_function_2")
examples/trace/instrument_fastapi.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import threading
4
+ from aworld.trace.config import ObservabilityConfig
5
+ from aworld.trace.instrumentation.fastapi import instrument_fastapi
6
+ from aworld.trace.instrumentation.requests import instrument_requests
7
+ from aworld.logs.util import logger, trace_logger
8
+ import aworld.trace as trace
9
+ from aworld.utils.import_package import import_packages
10
+ import_packages(['fastapi', 'uvicorn']) # noqa
11
+ import fastapi # noqa
12
+ import uvicorn # noqa
13
+
14
+ os.environ["MONITOR_SERVICE_NAME"] = "otlp_example"
15
+ os.environ["ANT_OTEL_ENDPOINT"] = "https://antcollector.alipay.com/namespace/aworld/task/aworld/otlp/api/v1/metrics"
16
+
17
+ trace.configure(ObservabilityConfig(
18
+ metrics_provider="otlp",
19
+ metrics_backend="antmonitor"
20
+ ))
21
+
22
+ instrument_fastapi()
23
+ instrument_requests()
24
+
25
+ app = fastapi.FastAPI()
26
+
27
+
28
+ @app.get("/api/hello")
29
+ async def hello():
30
+ return {"message": "Hello World"}
31
+
32
+
33
+ def invoke_api():
34
+ import requests
35
+ response = requests.get('http://127.0.0.1:7071/api/hello')
36
+ logger.info(f"invoke_api response={response.text}")
37
+
38
+
39
+ def main():
40
+ logger.info("main running")
41
+ with trace.span("test_fastapi") as span:
42
+ trace_logger.info("start invoke_api")
43
+ invoke_api()
44
+
45
+
46
+ if __name__ == "__main__":
47
+ server_thread = threading.Thread(
48
+ target=lambda: uvicorn.run(app, host="0.0.0.0", port=7071),
49
+ daemon=True
50
+ )
51
+ server_thread.start()
52
+ time.sleep(1)
53
+ main()
54
+ server_thread.join()
examples/trace/instrument_flask.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import threading
2
+ import flask
3
+ from aworld.trace.instrumentation.flask import instrument_flask
4
+ from aworld.trace.instrumentation.requests import instrument_requests
5
+ from aworld.logs.util import logger, trace_logger
6
+ import aworld.trace as trace
7
+ import os
8
+ from aworld.trace.config import ObservabilityConfig
9
+
10
+ os.environ["MONITOR_SERVICE_NAME"] = "otlp_example"
11
+ os.environ["ANT_OTEL_ENDPOINT"] = "https://antcollector.alipay.com/namespace/aworld/task/aworld/otlp/api/v1/metrics"
12
+
13
+ trace.configure(ObservabilityConfig(
14
+ metrics_provider="otlp",
15
+ metrics_backend="antmonitor"
16
+ ))
17
+ instrument_flask()
18
+ instrument_requests()
19
+
20
+ app = flask.Flask(__name__)
21
+
22
+
23
+ @app.route('/api/test')
24
+ def test():
25
+ return 'Hello, World!'
26
+
27
+
28
+ thread = threading.Thread(target=lambda: app.run(port=7070), daemon=True)
29
+ thread.start()
30
+
31
+
32
+ def invoke_api():
33
+ import requests
34
+ response = requests.get('http://localhost:7070/api/test')
35
+ logger.info(f"invoke_api response={response.text}")
36
+
37
+
38
+ def main():
39
+ logger.info("main running")
40
+ with trace.span("test_flask") as span:
41
+ trace_logger.info("start invoke_api")
42
+ invoke_api()
43
+
44
+
45
+ if __name__ == "__main__":
46
+ main()
47
+ thread.join()
examples/trace/instrument_threading.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import threading
2
+ import aworld.trace as trace
3
+ import os
4
+ import time
5
+ from aworld.trace.instrumentation.threading import instrument_theading
6
+ from aworld.logs.util import logger, trace_logger
7
+
8
+ os.environ["MONITOR_SERVICE_NAME"] = "otlp_example"
9
+ trace.configure()
10
+ instrument_theading()
11
+
12
+
13
+ def child_thread_func():
14
+ logger.info("child thread running")
15
+ with trace.span("child_thread") as span:
16
+ trace_logger.info("child thread running")
17
+ time.sleep(1000)
18
+
19
+
20
+ def main():
21
+ logger.info("main running")
22
+ with trace.span("test_fastapi") as span:
23
+ trace_logger.info("start run child_thread_func")
24
+ threading.Thread(target=child_thread_func).start()
25
+ threading.Thread(target=child_thread_func).start()
26
+
27
+
28
+ if __name__ == "__main__":
29
+ main()
examples/trace/opentelemetry_trace.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os # noqa
2
+ # os.environ["START_TRACE_SERVER"] = "false" # noqa
3
+ os.environ["MONITOR_SERVICE_NAME"] = "otlp_example" # noqa
4
+ # os.environ["OTLP_TRACES_ENDPOINT"] = "http://localhost:4318/v1/traces"
5
+ # os.environ["METRICS_SYSTEM_ENABLED"] = "true"
6
+ # os.environ["LOGFIRE_WRITE_TOKEN"] = (
7
+ # "Your logfire write token, "
8
+ # "create guide refer to "
9
+ # "https://logfire.pydantic.dev/docs/how-to-guides/create-write-tokens/"
10
+ # )
11
+
12
+ import aworld.trace as trace # noqa
13
+ from aworld.logs.util import logger, trace_logger
14
+ from aworld.trace.server import get_trace_server
15
+
16
+
17
+ trace.configure()
18
+
19
+
20
+ @trace.func_span(span_name="test_func", attributes={"test_attr": "test_value"}, extract_args=["param1"], add_attr="add_attr_value")
21
+ def traced_func(param1: str = None, param2: int = None):
22
+ trace_logger.info("this is a traced func")
23
+ traced_func2(param1="func2_param1_value", param2=222)
24
+ traced_func3(param1="func3_param1_value", param2=333)
25
+
26
+
27
+ @trace.func_span(span_name="test_func_2", add_attr="add_attr_value")
28
+ def traced_func2(param1: str = None, param2: int = None):
29
+ name = 'func2'
30
+ trace_logger.info(f"this is a traced {name}")
31
+ raise Exception("this is a traced func2 exception")
32
+
33
+
34
+ @trace.func_span
35
+ def traced_func3(param1: str = None, param2: int = None):
36
+ trace_logger.info("this is a traced func3")
37
+
38
+
39
+ def main():
40
+
41
+ logger.info("this is a no trace log")
42
+
43
+ trace.auto_tracing("examples.trace.*", 0.01)
44
+
45
+ with trace.span("hello") as span:
46
+ span.set_attribute("parent_test_attr", "pppppp")
47
+ logger.info("hello aworld")
48
+ trace_logger.info("trace hello aworld")
49
+ with trace.span("child hello") as span2:
50
+ span2.set_attribute("child_test_attr", "cccccc")
51
+ logger.info("child hello aworld")
52
+ current_span = trace.get_current_span()
53
+ logger.info("trace_id=%s", current_span.get_trace_id())
54
+ try:
55
+ traced_func(param1="func1_param1_value", param2=111)
56
+ except Exception as e:
57
+ logger.error(f"exception: {e}")
58
+ # from examples.trace.autotrace_demo import TestClassB
59
+ # b = TestClassB()
60
+ # b.classb_function_1()
61
+ # b.classb_function_2()
62
+ # b.classb_function_1()
63
+ # b.classb_function_2()
64
+ if get_trace_server():
65
+ get_trace_server().join()
66
+
67
+
68
+ if __name__ == "__main__":
69
+ main()
examples/trace/sofa_tracer.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os # noqa: E402
2
+
3
+ os.environ["MONITOR_SERVICE_NAME"] = "otlp_example" # noqa
4
+ os.environ["ANT_OTEL_ENDPOINT"] = "https://antcollector.alipay.com/namespace/aworld/task/aworld/otlp/api/v1/metrics" # noqa
5
+ os.environ["OTLP_TRACES_ENDPOINT"] = "https://antcollector.alipay.com/namespace/aworld/task/aworld_trace/otlp/api/v1/traces" # noqa
6
+
7
+ from aworld.trace.config import ObservabilityConfig
8
+ from aworld.logs.util import logger
9
+ from aworld.trace.baggage import BaggageContext
10
+ from aworld.trace.base import get_tracer_provider
11
+ from aworld.trace.instrumentation.requests import instrument_requests
12
+ from aworld.trace.instrumentation.flask import instrument_flask
13
+ import flask
14
+ import threading
15
+ import aworld.trace as trace
16
+
17
+
18
+ trace.configure(ObservabilityConfig(
19
+ trace_provider="otlp",
20
+ trace_backends=["other_otlp"],
21
+ trace_base_url="https://antcollector.alipay.com/namespace/aworld/task/aworld_trace/otlp/api/v1/traces",
22
+ metrics_provider="otlp",
23
+ metrics_backend="antmonitor",
24
+ metrics_base_url="https://antcollector.alipay.com/namespace/aworld/task/aworld/otlp/api/v1/metrics"
25
+ ))
26
+ instrument_flask()
27
+ instrument_requests()
28
+
29
+ app = flask.Flask(__name__)
30
+
31
+
32
+ @app.route('/api/test')
33
+ def test():
34
+ sofa_trace_id = BaggageContext.get_baggage_value("attributes.sofa.traceid")
35
+ sofa_rpc_id = BaggageContext.get_baggage_value("attributes.sofa.rpcid")
36
+ sofa_pen_attrs = BaggageContext.get_baggage_value(
37
+ "attributes.sofa.penattrs")
38
+ sofa_sys_pen_attrs = BaggageContext.get_baggage_value(
39
+ "attributes.sofa.syspenattrs")
40
+ logger.info(
41
+ f"test sofa_trace_id={sofa_trace_id}, sofa_rpc_id={sofa_rpc_id}, sofa_pen_attrs={sofa_pen_attrs}, sofa_sys_pen_attrs={sofa_sys_pen_attrs}"
42
+ )
43
+ return 'Hello, World!'
44
+
45
+
46
+ thread = threading.Thread(target=lambda: app.run(port=7070), daemon=True)
47
+ thread.start()
48
+
49
+
50
+ def invoke_api():
51
+ import requests
52
+ session = requests.session()
53
+ session.headers.update({
54
+ "SOFA-TraceId": "12345678901234567890123456789012",
55
+ "SOFA-RpcId": "0.1.1",
56
+ "sofaPenAttrs": "key1=value1&key2=value2",
57
+ "sysPenAttrs": "key1=value1&key2=value2"
58
+ })
59
+ response = session.get('http://localhost:7070/api/test')
60
+ logger.info(f"invoke_api response={response.text}")
61
+
62
+
63
+ def main():
64
+ logger.info("main running")
65
+ invoke_api()
66
+
67
+
68
+ if __name__ == "__main__":
69
+ main()
70
+ get_tracer_provider().force_flush(1000)
71
+ thread.join()
examples/trace/span_cosumer.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ from aworld.logs.util import logger, trace_logger
4
+ from typing import Sequence
5
+ import aworld.trace as trace
6
+ from aworld.trace.base import Span
7
+ from aworld.trace.span_cosumer import register_span_consumer, SpanConsumer
8
+ from aworld.logs.util import logger, trace_logger
9
+
10
+ os.environ["MONITOR_SERVICE_NAME"] = "otlp_example"
11
+
12
+
13
+ @register_span_consumer({"test_param": "MockSpanConsumer111"})
14
+ class MockSpanConsumer(SpanConsumer):
15
+
16
+ def __init__(self, test_param=None):
17
+ self._test_param = test_param
18
+
19
+ def consume(self, spans: Sequence[Span]) -> None:
20
+ for span in spans:
21
+ logger.info(
22
+ f"_test_param={self._test_param}, trace_id={span.get_trace_id()}, span_id={span.get_span_id()}, attributes={span.attributes}")
23
+
24
+
25
+ def main():
26
+ with trace.span("hello") as span:
27
+ span.set_attribute("parent_test_attr", "pppppp")
28
+ logger.info("hello aworld")
29
+ trace_logger.info("trace hello aworld")
30
+
31
+
32
+ if __name__ == "__main__":
33
+ main()
examples/trace/trace_agent.py ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import traceback
2
+ from aworld.agents.llm_agent import Agent
3
+ from aworld.config.conf import AgentConfig, ConfigDict
4
+ from aworld.core.common import Observation, ActionModel
5
+ from typing import Dict, Any, List, Union, Callable
6
+ from aworld.core.tool.base import ToolFactory
7
+ from aworld.models.llm import call_llm_model, acall_llm_model
8
+ from aworld.utils.common import sync_exec
9
+ from aworld.logs.util import logger
10
+ from examples.tools.common import Tools
11
+ from examples.tools.tool_action import GetTraceAction
12
+ from aworld.core.agent.swarm import Swarm
13
+ from aworld.runner import Runners
14
+ from aworld.trace.server import get_trace_server
15
+ from aworld.runners.state_manager import RuntimeStateManager, RunNode
16
+ import aworld.trace as trace
17
+
18
+
19
+ trace.configure()
20
+
21
+
22
+ class TraceAgent(Agent):
23
+
24
+ def __init__(self,
25
+ conf: Union[Dict[str, Any], ConfigDict, AgentConfig],
26
+ resp_parse_func: Callable[..., Any] = None,
27
+ **kwargs):
28
+ super().__init__(conf, **kwargs)
29
+
30
+ def policy(self, observation: Observation, info: Dict[str, Any] = {}, **kwargs) -> List[ActionModel]:
31
+ """use trace tool to get trace data, and call llm to summary
32
+
33
+ Args:
34
+ observation: The state observed from tools in the environment.
35
+ info: Extended information is used to assist the agent to decide a policy.
36
+
37
+ Returns:
38
+ ActionModel sequence from agent policy
39
+ """
40
+
41
+ self._finished = False
42
+ self.desc_transform()
43
+
44
+ tool_name = "trace"
45
+ tool = ToolFactory(tool_name, asyn=False)
46
+ tool.reset()
47
+ tool_params = {}
48
+ action = ActionModel(tool_name=tool_name,
49
+ action_name=GetTraceAction.GET_TRACE.name,
50
+ agent_name=self.id(),
51
+ params=tool_params)
52
+ message = tool.step(action)
53
+
54
+ observation, _, _, _, _ = message.payload
55
+
56
+ llm_response = None
57
+
58
+ messages = self.messages_transform(content=observation.content,
59
+ sys_prompt=self.system_prompt,
60
+ agent_prompt=self.agent_prompt)
61
+ try:
62
+ llm_response = call_llm_model(
63
+ self.llm,
64
+ messages=messages,
65
+ model=self.model_name,
66
+ temperature=self.conf.llm_config.llm_temperature
67
+ )
68
+
69
+ logger.info(f"Execute response: {llm_response.message}")
70
+ except Exception as e:
71
+ logger.warn(traceback.format_exc())
72
+ raise e
73
+ finally:
74
+ if llm_response:
75
+ if llm_response.error:
76
+ logger.info(
77
+ f"{self.id()} llm result error: {llm_response.error}")
78
+ else:
79
+ logger.error(f"{self.id()} failed to get LLM response")
80
+ raise RuntimeError(
81
+ f"{self.id()} failed to get LLM response")
82
+
83
+ agent_result = sync_exec(self.resp_parse_func, llm_response)
84
+ if not agent_result.is_call_tool:
85
+ self._finished = True
86
+ return agent_result.actions
87
+
88
+ async def async_policy(self, observation: Observation, info: Dict[str, Any] = {}, **kwargs) -> List[ActionModel]:
89
+
90
+ self._finished = False
91
+ self.desc_transform()
92
+
93
+ tool_name = "trace"
94
+ tool = ToolFactory(tool_name, asyn=False)
95
+ tool.reset()
96
+ tool_params = {}
97
+ action = ActionModel(tool_name=tool_name,
98
+ action_name=GetTraceAction.GET_TRACE.name,
99
+ agent_name=self.id(),
100
+ params=tool_params)
101
+ message = tool.step([action])
102
+
103
+ observation, _, _, _, _ = message.payload
104
+
105
+ llm_response = None
106
+
107
+ messages = self.messages_transform(content=observation.content,
108
+ sys_prompt=self.system_prompt,
109
+ agent_prompt=self.agent_prompt)
110
+ try:
111
+ llm_response = await acall_llm_model(
112
+ self.llm,
113
+ messages=messages,
114
+ model=self.model_name,
115
+ temperature=self.conf.llm_config.llm_temperature
116
+ )
117
+
118
+ logger.info(f"Execute response: {llm_response.message}")
119
+ except Exception as e:
120
+ logger.warn(traceback.format_exc())
121
+ raise e
122
+ finally:
123
+ if llm_response:
124
+ if llm_response.error:
125
+ logger.info(
126
+ f"{self.id()} llm result error: {llm_response.error}")
127
+ else:
128
+ logger.error(f"{self.id()} failed to get LLM response")
129
+ raise RuntimeError(
130
+ f"{self.id()} failed to get LLM response")
131
+
132
+ agent_result = sync_exec(self.resp_parse_func, llm_response)
133
+ if not agent_result.is_call_tool:
134
+ self._finished = True
135
+ return agent_result.actions
136
+
137
+
138
+ search_sys_prompt = "You are a helpful search agent."
139
+ search_prompt = """
140
+ Please act as a search agent, constructing appropriate keywords and searach terms, using search toolkit to collect relevant information, including urls, webpage snapshots, etc.
141
+
142
+ Here are the question: {task}
143
+
144
+ pleas only use one action complete this task, at least results 6 pages.
145
+ """
146
+
147
+ summary_sys_prompt = "You are a helpful general summary agent."
148
+
149
+ summary_prompt = """
150
+ Summarize the following text in one clear and concise paragraph, capturing the key ideas without missing critical points.
151
+ Ensure the summary is easy to understand and avoids excessive detail.
152
+
153
+ Here are the content:
154
+ {task}
155
+ """
156
+
157
+ trace_sys_prompt = "You are a helpful trace agent."
158
+
159
+ trace_prompt = """
160
+ Please act as a trace agent, Using the provided trace data, summarize the token usage of each agent,
161
+ whether the runotype attribute of span is an agent or a large model call:
162
+ run_type=AGNET represents the agent,
163
+ run_type=LLM represents the large model call.
164
+ The LLM call of a certain agent is represented as LLM span, which is a child span of that agent span
165
+
166
+ Here are the content: {task}
167
+ """
168
+
169
+
170
+ def build_run_flow(nodes: List[RunNode]):
171
+ graph = {}
172
+ start_nodes = []
173
+
174
+ for node in nodes:
175
+ if hasattr(node, 'parent_node_id') and node.parent_node_id:
176
+ if node.parent_node_id not in graph:
177
+ graph[node.parent_node_id] = []
178
+ graph[node.parent_node_id].append(node.node_id)
179
+ else:
180
+ start_nodes.append(node.node_id)
181
+
182
+ for start in start_nodes:
183
+ print("-----------------------------------")
184
+ _print_tree(graph, start, "", True)
185
+ print("-----------------------------------")
186
+
187
+
188
+ def _print_tree(graph, node_id, prefix, is_last):
189
+ print(prefix + ("└── " if is_last else "├── ") + node_id)
190
+ if node_id in graph:
191
+ children = graph[node_id]
192
+ for i, child in enumerate(children):
193
+ _print_tree(graph, child, prefix +
194
+ (" " if is_last else "│ "), i == len(children)-1)
195
+
196
+
197
+ if __name__ == "__main__":
198
+ agent_config = AgentConfig(
199
+ llm_provider="openai",
200
+ llm_model_name="gpt-4o",
201
+ llm_temperature=0.3,
202
+
203
+ llm_base_url="http://localhost:34567",
204
+ llm_api_key="dummy-key",
205
+ )
206
+
207
+ search = Agent(
208
+ conf=agent_config,
209
+ name="search_agent",
210
+ system_prompt=search_sys_prompt,
211
+ agent_prompt=search_prompt,
212
+ tool_names=[Tools.SEARCH_API.value]
213
+ )
214
+
215
+ summary = Agent(
216
+ conf=agent_config,
217
+ name="summary_agent",
218
+ system_prompt=summary_sys_prompt,
219
+ agent_prompt=summary_prompt
220
+ )
221
+
222
+ trace = TraceAgent(
223
+ conf=agent_config,
224
+ name="trace_agent",
225
+ system_prompt=trace_sys_prompt,
226
+ agent_prompt=trace_prompt
227
+ )
228
+
229
+ # default is sequence swarm mode
230
+ swarm = Swarm(search, summary, trace, max_steps=1, event_driven=True)
231
+
232
+ prefix = "search baidu:"
233
+ # can special search google, wiki, duck go, or baidu. such as:
234
+ # prefix = "search wiki: "
235
+ try:
236
+ res = Runners.sync_run(
237
+ input=prefix + """What is an agent.""",
238
+ swarm=swarm,
239
+ session_id="123"
240
+ )
241
+ print(res.answer)
242
+ except Exception as e:
243
+ logger.error(traceback.format_exc())
244
+
245
+ state_manager = RuntimeStateManager.instance()
246
+ nodes = state_manager.get_nodes("123")
247
+ logger.info(f"session 123 nodes: {nodes}")
248
+ build_run_flow(nodes)
249
+ get_trace_server().join()