Skip to content

Commit 5fab762

Browse files
committed
dashboard/app: add support for AI workflows
Support for: - polling for AI jobs - handling completion of AI jobs - submitting job trajectory logs - basic visualization for AI jobs
1 parent e9f4dc8 commit 5fab762

File tree

20 files changed

+1324
-5
lines changed

20 files changed

+1324
-5
lines changed

dashboard/app/ai.go

Lines changed: 456 additions & 0 deletions
Large diffs are not rendered by default.

dashboard/app/ai_test.go

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ package main
55

66
import (
77
"testing"
8+
"time"
89

10+
"github.com/google/syzkaller/dashboard/dashapi"
11+
"github.com/google/syzkaller/pkg/aflow/trajectory"
12+
"github.com/google/syzkaller/prog"
913
"github.com/stretchr/testify/require"
1014
)
1115

@@ -23,4 +27,173 @@ func TestAIMigrations(t *testing.T) {
2327
require.NoError(t, executeSpannerDDL(c.ctx, down))
2428
require.NoError(t, executeSpannerDDL(c.ctx, up))
2529
require.NoError(t, executeSpannerDDL(c.ctx, down))
30+
require.NoError(t, executeSpannerDDL(c.ctx, up))
31+
}
32+
33+
func TestAIBugWorkflows(t *testing.T) {
34+
c := NewSpannerCtx(t)
35+
defer c.Close()
36+
37+
build := testBuild(1)
38+
c.aiClient.UploadBuild(build)
39+
40+
// KCSAN bug w/o repro.
41+
crash1 := testCrash(build, 1)
42+
crash1.Title = "KCSAN: data-race in foo / bar"
43+
c.aiClient.ReportCrash(crash1)
44+
bugExtID1 := c.aiClient.pollEmailExtID()
45+
kcsanBug, _, _ := c.loadBug(bugExtID1)
46+
47+
// Bug2: KASAN bug with repro.
48+
crash2 := testCrashWithRepro(build, 2)
49+
crash2.Title = "KASAN: head-use-after-free in foo"
50+
c.aiClient.ReportCrash(crash2)
51+
bugExtID2 := c.aiClient.pollEmailExtID()
52+
kasanBug, _, _ := c.loadBug(bugExtID2)
53+
54+
requireWorkflows := func(bug *Bug, want []string) {
55+
got, err := aiBugWorkflows(c.ctx, bug)
56+
require.NoError(t, err)
57+
require.Equal(t, got, want)
58+
}
59+
requireWorkflows(kcsanBug, nil)
60+
requireWorkflows(kasanBug, nil)
61+
62+
_, err := c.aiClient.AIJobPoll(&dashapi.AIJobPollReq{
63+
CodeRevision: prog.GitRevision,
64+
LLMModel: "smarty",
65+
Workflows: []dashapi.AIWorkflow{
66+
{Type: "patching", Name: "patching"},
67+
{Type: "patching", Name: "patching-foo"},
68+
{Type: "patching", Name: "patching-bar"},
69+
},
70+
})
71+
require.NoError(t, err)
72+
73+
// This should make patching-foo inactive.
74+
c.advanceTime(2 * 24 * time.Hour)
75+
76+
_, err = c.aiClient.AIJobPoll(&dashapi.AIJobPollReq{
77+
CodeRevision: prog.GitRevision,
78+
LLMModel: "smarty",
79+
Workflows: []dashapi.AIWorkflow{
80+
{Type: "patching", Name: "patching"},
81+
{Type: "patching", Name: "patching-bar"},
82+
{Type: "patching", Name: "patching-baz"},
83+
{Type: "assessment-kcsan", Name: "assessment-kcsan"},
84+
},
85+
})
86+
require.NoError(t, err)
87+
88+
_, err = c.aiClient.AIJobPoll(&dashapi.AIJobPollReq{
89+
CodeRevision: prog.GitRevision,
90+
LLMModel: "smarty",
91+
Workflows: []dashapi.AIWorkflow{
92+
{Type: "patching", Name: "patching"},
93+
{Type: "patching", Name: "patching-bar"},
94+
{Type: "patching", Name: "patching-qux"},
95+
{Type: "assessment-kcsan", Name: "assessment-kcsan"},
96+
{Type: "assessment-kcsan", Name: "assessment-kcsan-foo"},
97+
},
98+
})
99+
require.NoError(t, err)
100+
101+
requireWorkflows(kcsanBug, []string{"assessment-kcsan", "assessment-kcsan-foo"})
102+
requireWorkflows(kasanBug, []string{"patching", "patching-bar", "patching-baz", "patching-qux"})
103+
}
104+
105+
func TestAIJob(t *testing.T) {
106+
c := NewSpannerCtx(t)
107+
defer c.Close()
108+
109+
build := testBuild(1)
110+
c.aiClient.UploadBuild(build)
111+
crash := testCrash(build, 1)
112+
crash.Title = "KCSAN: data-race in foo / bar"
113+
c.aiClient.ReportCrash(crash)
114+
c.aiClient.pollEmailBug()
115+
116+
resp, err := c.aiClient.AIJobPoll(&dashapi.AIJobPollReq{
117+
CodeRevision: prog.GitRevision,
118+
LLMModel: "smarty",
119+
Workflows: []dashapi.AIWorkflow{
120+
{Type: "assessment-kcsan", Name: "assessment-kcsan"},
121+
},
122+
})
123+
require.NoError(t, err)
124+
require.NotEqual(t, resp.ID, "")
125+
require.Equal(t, resp.Workflow, "assessment-kcsan")
126+
require.Equal(t, resp.Args, map[string]any{
127+
"CrashReport": "report1",
128+
"KernelRepo": "repo1",
129+
"KernelCommit": "1111111111111111111111111111111111111111",
130+
"KernelConfig": "config1",
131+
"SyzkallerCommit": "syzkaller_commit1",
132+
"ReproOpts": "",
133+
})
134+
135+
resp2, err2 := c.aiClient.AIJobPoll(&dashapi.AIJobPollReq{
136+
CodeRevision: prog.GitRevision,
137+
LLMModel: "smarty",
138+
Workflows: []dashapi.AIWorkflow{
139+
{Type: "assessment-kcsan", Name: "assessment-kcsan"},
140+
},
141+
})
142+
require.NoError(t, err2)
143+
require.Equal(t, resp2.ID, "")
144+
145+
require.NoError(t, c.aiClient.AITrajectoryLog(&dashapi.AITrajectoryReq{
146+
JobID: resp.ID,
147+
Span: &trajectory.Span{
148+
Seq: 0,
149+
Type: trajectory.SpanFlow,
150+
Name: "assessment-kcsan",
151+
Started: c.mockedTime,
152+
},
153+
}))
154+
155+
require.NoError(t, c.aiClient.AITrajectoryLog(&dashapi.AITrajectoryReq{
156+
JobID: resp.ID,
157+
Span: &trajectory.Span{
158+
Seq: 1,
159+
Type: trajectory.SpanAgent,
160+
Name: "agent",
161+
Prompt: "do something",
162+
Started: c.mockedTime,
163+
},
164+
}))
165+
166+
require.NoError(t, c.aiClient.AITrajectoryLog(&dashapi.AITrajectoryReq{
167+
JobID: resp.ID,
168+
Span: &trajectory.Span{
169+
Seq: 1,
170+
Type: trajectory.SpanAgent,
171+
Name: "agent",
172+
Prompt: "do something",
173+
Started: c.mockedTime,
174+
Finished: c.mockedTime.Add(time.Second),
175+
Reply: "something",
176+
},
177+
}))
178+
179+
require.NoError(t, c.aiClient.AITrajectoryLog(&dashapi.AITrajectoryReq{
180+
JobID: resp.ID,
181+
Span: &trajectory.Span{
182+
Seq: 0,
183+
Type: trajectory.SpanFlow,
184+
Name: "assessment-kcsan",
185+
Started: c.mockedTime,
186+
Finished: c.mockedTime.Add(time.Second),
187+
},
188+
}))
189+
190+
require.NoError(t, c.aiClient.AIJobDone(&dashapi.AIJobDoneReq{
191+
ID: resp.ID,
192+
Results: map[string]any{
193+
"Patch": "patch",
194+
"Explanation": "foo",
195+
"Number": 1,
196+
"Bool": true,
197+
},
198+
}))
26199
}

0 commit comments

Comments
 (0)