Skip to content

Commit 79c2acb

Browse files
authored
[fix] trajectory agent step (#359)
fix trajectory agent step
1 parent 5f17dc9 commit 79c2acb

2 files changed

Lines changed: 72 additions & 42 deletions

File tree

backend/modules/observability/domain/trace/entity/loop_span/trajectory.go

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -251,14 +251,10 @@ func buildAgentSteps(agentSpan *Span, spanMap map[string]*Span) []*Step {
251251
childSpans := getDirectChildren(agentSpan, spanMap)
252252

253253
for _, childSpan := range childSpans {
254-
// 深度遍历每个分支收集所有普通子节点,每个分支直到遇到agent节点为止
255-
branchSteps := collectOtherSteps(childSpan, spanMap)
256-
steps = append(steps, branchSteps...)
257-
258-
// 对每个直接子节点,向下深度遍历找到每个分支的第一个agent/model/tool节点
259-
agentModelToolSteps := findAgentModelToolNode(childSpan, spanMap)
260-
if len(agentModelToolSteps) > 0 {
261-
steps = append(steps, agentModelToolSteps...)
254+
// 深度遍历每个分支收集所有子节点,每个分支直到遇到agent节点为止
255+
branchSteps := collectSubSteps(childSpan, spanMap)
256+
if len(branchSteps) > 0 {
257+
steps = append(steps, branchSteps...)
262258
}
263259
}
264260

@@ -315,34 +311,8 @@ func buildStep(span *Span) *Step {
315311
return step
316312
}
317313

318-
// findAgentModelToolNode 向下深度遍历,找到每个分支的第一个agent/model/tool节点
319-
func findAgentModelToolNode(startSpan *Span, spanMap map[string]*Span) []*Step {
320-
if startSpan == nil {
321-
return nil
322-
}
323-
324-
steps := make([]*Step, 0)
325-
stepType := getStepType(startSpan)
326-
327-
// 如果当前节点就是agent/model/tool,直接返回
328-
if stepType == StepTypeAgent || stepType == StepTypeModel || stepType == StepTypeTool {
329-
steps = append(steps, buildStep(startSpan))
330-
return steps
331-
}
332-
333-
// 如果是other节点,继续向下遍历
334-
children := getDirectChildren(startSpan, spanMap)
335-
for _, child := range children {
336-
if result := findAgentModelToolNode(child, spanMap); len(result) > 0 {
337-
steps = append(steps, result...)
338-
}
339-
}
340-
341-
return steps
342-
}
343-
344-
// collectOtherSteps 深度遍历分支,收集任意层级的普通子节点,直到遇到agent节点为止
345-
func collectOtherSteps(startSpan *Span, spanMap map[string]*Span) []*Step {
314+
// collectSubSteps 深度遍历分支,收集任意层级的普通子节点,直到遇到agent节点为止
315+
func collectSubSteps(startSpan *Span, spanMap map[string]*Span) []*Step {
346316
if startSpan == nil {
347317
return nil
348318
}
@@ -351,19 +321,15 @@ func collectOtherSteps(startSpan *Span, spanMap map[string]*Span) []*Step {
351321
stepType := getStepType(startSpan)
352322

353323
// 如果当前节点是agent节点,停止遍历
324+
steps = append(steps, buildStep(startSpan))
354325
if stepType == StepTypeAgent {
355326
return steps
356327
}
357328

358-
// 如果是普通节点,添加到结果中,然后继续向下遍历
359-
if stepType != StepTypeModel && stepType != StepTypeTool {
360-
steps = append(steps, buildStep(startSpan))
361-
}
362-
363329
// 获取当前节点的子节点,继续深度遍历
364330
children := getDirectChildren(startSpan, spanMap)
365331
for _, child := range children {
366-
childSteps := collectOtherSteps(child, spanMap)
332+
childSteps := collectSubSteps(child, spanMap)
367333
if len(childSteps) > 0 {
368334
steps = append(steps, childSteps...)
369335
}

backend/modules/observability/domain/trace/entity/loop_span/trajectory_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,70 @@ func TestBuildTrajectoryFromSpans_ComplexTree(t *testing.T) {
220220
assert.NotEmpty(t, s)
221221
}
222222

223+
func TestBuildTrajectoryFromSpans_ModelIsParentOfTool(t *testing.T) {
224+
t.Parallel()
225+
traceID := "trace1"
226+
227+
// 根 agent
228+
root := &Span{
229+
SpanID: "r",
230+
ParentID: "", // 作为root
231+
TraceID: traceID,
232+
SpanName: "root-agent",
233+
SpanType: "agent",
234+
StartTime: 0, // us
235+
DurationMicros: 3000000, // 3s
236+
Input: "root-in",
237+
Output: "root-out",
238+
TagsString: map[string]string{},
239+
TagsLong: map[string]int64{},
240+
}
241+
242+
// 分支1:model->tool
243+
m1 := &Span{
244+
SpanID: "m1",
245+
ParentID: "r",
246+
TraceID: traceID,
247+
SpanName: "parser-1",
248+
SpanType: "model",
249+
StartTime: 100, // us
250+
}
251+
t1 := &Span{
252+
SpanID: "t1",
253+
ParentID: "m1",
254+
TraceID: traceID,
255+
SpanName: "tool-1",
256+
SpanType: "tool",
257+
}
258+
259+
spans := SpanList{root, m1, t1}
260+
traj := BuildTrajectoryFromSpans(spans)
261+
assert.NotNil(t, traj)
262+
assert.NotNil(t, traj.RootStep)
263+
assert.NotNil(t, traj.ID)
264+
assert.Equal(t, traceID, *traj.ID)
265+
266+
assert.Equal(t, 1, len(traj.AgentSteps))
267+
268+
// AgentSteps 包含 root 和 a1
269+
// 找到 root 对应的 AgentStep
270+
var m1Step, t1Step *Step
271+
for _, s := range traj.AgentSteps[0].Steps {
272+
if s != nil && s.ID != nil {
273+
switch *s.ID {
274+
case "m1":
275+
m1Step = s
276+
case "t1":
277+
t1Step = s
278+
default:
279+
}
280+
}
281+
}
282+
assert.NotNil(t, m1Step)
283+
assert.NotNil(t, t1Step)
284+
assert.Equal(t, *t1Step.ParentID, "m1")
285+
}
286+
223287
func TestGetDirectChildren_Sorting(t *testing.T) {
224288
t.Parallel()
225289
parent := &Span{SpanID: "p"}

0 commit comments

Comments
 (0)