Files
liqiang b119135836
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
2026-08-20 13:12:50 +00:00

145 lines
5.1 KiB
Python

from aworld.trace.server import get_trace_server
from aworld.trace.constants import RunType, SPAN_NAME_PREFIX_EVENT_AGENT
from aworld.trace.instrumentation import semconv
def _get_agent_show_name(span: dict):
agent_name_prefix = SPAN_NAME_PREFIX_EVENT_AGENT
name = span.get("name")
if name and name.startswith(agent_name_prefix):
name = name[len(agent_name_prefix):]
if name and '---' in name:
name = name.split('---', 1)[0]
return name
def _remove_span_detail(root_spans: list):
keys_to_keep = {'span_id', 'show_name', 'task_group_id', 'event_id'}
for span in root_spans:
keys_to_remove = [key for key in span.keys() if key not in keys_to_keep]
for key in keys_to_remove:
span.pop(key, None)
if 'children' in span:
_remove_span_detail(span['children'])
def _build_graph(root_spans: list):
nodes = []
edges = []
group_id_counter = 0
def __process_group_span(parent_spans, group_id, group_spans):
nonlocal group_id_counter
group_id_counter += 1
# add group node
group_node = {
'span_id': f'group_{group_id_counter}',
'group_id': group_id,
'show_name': 'Task Group'
}
nodes.append(group_node)
# add edges from parent_spans to group node
for parent_span in parent_spans:
edges.append({
'source': parent_span['span_id'],
'target': group_node['span_id']
})
# add edges from group node to children spans
last_spans = []
for child in group_spans:
edges.append({
'source': group_node['span_id'],
'target': child['span_id']
})
last_spans.extend(__process_span(child))
return last_spans
def __process_span(span):
nonlocal group_id_counter
nodes.append(span)
if 'children' in span:
groups = {}
for child in span['children']:
group_id = child.get('task_group_id', id(child))
if group_id not in groups:
groups[group_id] = []
groups[group_id].append(child)
last_spans = [span] # The leaf nodes of the current subtree
for group_id, group_spans in groups.items():
if len(group_spans) > 1:
parent_spans = last_spans
last_spans = __process_group_span(parent_spans, group_id, group_spans)
else:
child_span = group_spans[0]
# add edges from last_spans to child
for prev_node in last_spans:
edges.append({
'source': prev_node['span_id'],
'target': child_span['span_id']
})
last_spans = __process_span(child_span)
return last_spans
for span in root_spans:
__process_span(span)
return {
'nodes': nodes,
'edges': edges
}
def get_agent_flow(trace_id):
storage = get_trace_server().get_storage()
spans = storage.get_all_spans(trace_id)
spans_dict = {span.span_id: span.dict() for span in spans}
children_spans = []
filtered_spans = {}
for span_id, span in spans_dict.items():
if span.get('is_event', False) and span.get('run_type') == RunType.AGNET.value:
span['show_name'] = _get_agent_show_name(span)
span['event_id'] = span.get('attributes', {}).get('event.id')
filtered_spans[span_id] = span
sub_task_spans = []
for span in list(filtered_spans.values()):
skip_this_span = False
parent_id = span['parent_id'] if span['parent_id'] else None
while parent_id and parent_id not in filtered_spans:
parent_span = spans_dict.get(parent_id)
if parent_span and parent_span.get('run_type') == RunType.TASK.value:
if str(parent_span['attributes'].get(semconv.TASK_IS_SUB_TASK)).lower() == 'true':
sub_task_spans.append(span)
skip_this_span = True
break
else:
print(f"parent_span_name: {parent_span['name']}")
span['task_group_id'] = parent_span['attributes'].get(semconv.TASK_GROUP_ID)
parent_id = parent_span['parent_id'] if parent_span and parent_span['parent_id'] else None
if skip_this_span:
continue
if parent_id:
parent_span = filtered_spans.get(parent_id)
if not parent_span:
continue
if 'children' not in parent_span:
parent_span['children'] = []
parent_span['children'].append(span)
children_spans.append(span)
filtered_span_list = [span for span in filtered_spans.values() if span not in sub_task_spans]
root_spans = [span for span in filtered_span_list
if span not in children_spans]
data = _build_graph(root_spans)
_remove_span_detail(data["nodes"])
return data