inspect-ai 0.3.96__py3-none-any.whl → 0.3.97__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- inspect_ai/_eval/eval.py +10 -2
- inspect_ai/_eval/task/util.py +32 -3
- inspect_ai/_util/registry.py +7 -0
- inspect_ai/_util/timer.py +13 -0
- inspect_ai/_view/www/dist/assets/index.css +275 -195
- inspect_ai/_view/www/dist/assets/index.js +8568 -7376
- inspect_ai/_view/www/src/app/App.css +1 -0
- inspect_ai/_view/www/src/app/App.tsx +27 -10
- inspect_ai/_view/www/src/app/appearance/icons.ts +5 -0
- inspect_ai/_view/www/src/app/content/RecordTree.module.css +22 -0
- inspect_ai/_view/www/src/app/content/RecordTree.tsx +370 -0
- inspect_ai/_view/www/src/app/content/RenderedContent.module.css +5 -0
- inspect_ai/_view/www/src/app/content/RenderedContent.tsx +32 -19
- inspect_ai/_view/www/src/app/content/record_processors/store.ts +101 -0
- inspect_ai/_view/www/src/app/content/record_processors/types.ts +3 -0
- inspect_ai/_view/www/src/app/content/types.ts +5 -0
- inspect_ai/_view/www/src/app/log-view/LogView.tsx +1 -0
- inspect_ai/_view/www/src/app/log-view/LogViewContainer.tsx +35 -28
- inspect_ai/_view/www/src/app/log-view/LogViewLayout.tsx +1 -8
- inspect_ai/_view/www/src/app/log-view/navbar/PrimaryBar.tsx +2 -4
- inspect_ai/_view/www/src/app/log-view/navbar/ResultsPanel.tsx +13 -3
- inspect_ai/_view/www/src/app/log-view/navbar/ScoreGrid.module.css +15 -0
- inspect_ai/_view/www/src/app/log-view/navbar/ScoreGrid.tsx +14 -10
- inspect_ai/_view/www/src/app/log-view/tabs/InfoTab.tsx +9 -3
- inspect_ai/_view/www/src/app/log-view/tabs/JsonTab.tsx +1 -3
- inspect_ai/_view/www/src/app/log-view/tabs/SamplesTab.tsx +8 -2
- inspect_ai/_view/www/src/app/log-view/types.ts +1 -0
- inspect_ai/_view/www/src/app/plan/ModelCard.module.css +7 -0
- inspect_ai/_view/www/src/app/plan/ModelCard.tsx +5 -2
- inspect_ai/_view/www/src/app/plan/PlanCard.tsx +13 -8
- inspect_ai/_view/www/src/app/routing/navigationHooks.ts +63 -8
- inspect_ai/_view/www/src/app/routing/url.ts +45 -0
- inspect_ai/_view/www/src/app/samples/InlineSampleDisplay.module.css +2 -1
- inspect_ai/_view/www/src/app/samples/InlineSampleDisplay.tsx +15 -8
- inspect_ai/_view/www/src/app/samples/SampleDialog.module.css +3 -0
- inspect_ai/_view/www/src/app/samples/SampleDialog.tsx +16 -5
- inspect_ai/_view/www/src/app/samples/SampleDisplay.module.css +9 -1
- inspect_ai/_view/www/src/app/samples/SampleDisplay.tsx +68 -31
- inspect_ai/_view/www/src/app/samples/chat/ChatMessage.module.css +12 -7
- inspect_ai/_view/www/src/app/samples/chat/ChatMessage.tsx +17 -5
- inspect_ai/_view/www/src/app/samples/chat/ChatMessageRow.module.css +9 -0
- inspect_ai/_view/www/src/app/samples/chat/ChatMessageRow.tsx +48 -18
- inspect_ai/_view/www/src/app/samples/chat/ChatView.tsx +0 -1
- inspect_ai/_view/www/src/app/samples/chat/ChatViewVirtualList.module.css +4 -0
- inspect_ai/_view/www/src/app/samples/chat/ChatViewVirtualList.tsx +41 -1
- inspect_ai/_view/www/src/app/samples/chat/messages.ts +7 -0
- inspect_ai/_view/www/src/app/samples/chat/tools/ToolCallView.module.css +0 -3
- inspect_ai/_view/www/src/app/samples/chat/tools/ToolCallView.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/chat/tools/ToolInput.module.css +1 -1
- inspect_ai/_view/www/src/app/samples/chat/tools/ToolOutput.module.css +1 -1
- inspect_ai/_view/www/src/app/samples/descriptor/score/NumericScoreDescriptor.tsx +5 -1
- inspect_ai/_view/www/src/app/samples/descriptor/score/PassFailScoreDescriptor.tsx +11 -6
- inspect_ai/_view/www/src/app/samples/list/SampleList.tsx +7 -0
- inspect_ai/_view/www/src/app/samples/list/SampleRow.tsx +5 -18
- inspect_ai/_view/www/src/app/samples/sample-tools/SortFilter.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/scores/SampleScoresGrid.tsx +18 -5
- inspect_ai/_view/www/src/app/samples/scores/SampleScoresView.module.css +0 -6
- inspect_ai/_view/www/src/app/samples/scores/SampleScoresView.tsx +4 -1
- inspect_ai/_view/www/src/app/samples/transcript/ApprovalEventView.tsx +4 -2
- inspect_ai/_view/www/src/app/samples/transcript/ErrorEventView.tsx +6 -4
- inspect_ai/_view/www/src/app/samples/transcript/InfoEventView.module.css +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/InfoEventView.tsx +13 -6
- inspect_ai/_view/www/src/app/samples/transcript/InputEventView.tsx +6 -4
- inspect_ai/_view/www/src/app/samples/transcript/LoggerEventView.tsx +4 -2
- inspect_ai/_view/www/src/app/samples/transcript/ModelEventView.tsx +11 -8
- inspect_ai/_view/www/src/app/samples/transcript/SampleInitEventView.tsx +14 -8
- inspect_ai/_view/www/src/app/samples/transcript/SampleLimitEventView.tsx +13 -8
- inspect_ai/_view/www/src/app/samples/transcript/SandboxEventView.tsx +25 -16
- inspect_ai/_view/www/src/app/samples/transcript/ScoreEventView.tsx +7 -5
- inspect_ai/_view/www/src/app/samples/transcript/SpanEventView.tsx +11 -28
- inspect_ai/_view/www/src/app/samples/transcript/StepEventView.tsx +12 -20
- inspect_ai/_view/www/src/app/samples/transcript/SubtaskEventView.tsx +12 -31
- inspect_ai/_view/www/src/app/samples/transcript/ToolEventView.tsx +25 -29
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualList.tsx +297 -0
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualListComponent.module.css +0 -8
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualListComponent.tsx +43 -25
- inspect_ai/_view/www/src/app/samples/transcript/event/EventPanel.module.css +43 -0
- inspect_ai/_view/www/src/app/samples/transcript/event/EventPanel.tsx +109 -43
- inspect_ai/_view/www/src/app/samples/transcript/state/StateEventView.tsx +19 -8
- inspect_ai/_view/www/src/app/samples/transcript/transform/treeify.ts +128 -60
- inspect_ai/_view/www/src/app/samples/transcript/transform/utils.ts +14 -4
- inspect_ai/_view/www/src/app/samples/transcript/types.ts +6 -4
- inspect_ai/_view/www/src/app/types.ts +12 -1
- inspect_ai/_view/www/src/components/Card.css +6 -3
- inspect_ai/_view/www/src/components/Card.tsx +15 -2
- inspect_ai/_view/www/src/components/CopyButton.tsx +4 -6
- inspect_ai/_view/www/src/components/ExpandablePanel.module.css +20 -14
- inspect_ai/_view/www/src/components/ExpandablePanel.tsx +17 -22
- inspect_ai/_view/www/src/components/LargeModal.tsx +5 -1
- inspect_ai/_view/www/src/components/LiveVirtualList.tsx +25 -1
- inspect_ai/_view/www/src/components/MarkdownDiv.css +4 -0
- inspect_ai/_view/www/src/components/MarkdownDiv.tsx +2 -2
- inspect_ai/_view/www/src/components/TabSet.module.css +6 -1
- inspect_ai/_view/www/src/components/TabSet.tsx +8 -2
- inspect_ai/_view/www/src/state/hooks.ts +83 -13
- inspect_ai/_view/www/src/state/logPolling.ts +2 -2
- inspect_ai/_view/www/src/state/logSlice.ts +1 -2
- inspect_ai/_view/www/src/state/logsSlice.ts +9 -9
- inspect_ai/_view/www/src/state/samplePolling.ts +1 -1
- inspect_ai/_view/www/src/state/sampleSlice.ts +134 -7
- inspect_ai/_view/www/src/state/scoring.ts +1 -1
- inspect_ai/_view/www/src/state/scrolling.ts +39 -6
- inspect_ai/_view/www/src/state/store.ts +5 -0
- inspect_ai/_view/www/src/state/store_filter.ts +47 -44
- inspect_ai/_view/www/src/utils/debugging.ts +95 -0
- inspect_ai/_view/www/src/utils/format.ts +2 -2
- inspect_ai/_view/www/src/utils/json.ts +29 -0
- inspect_ai/agent/__init__.py +2 -1
- inspect_ai/agent/_agent.py +12 -0
- inspect_ai/agent/_react.py +184 -48
- inspect_ai/agent/_types.py +14 -1
- inspect_ai/analysis/beta/__init__.py +0 -2
- inspect_ai/analysis/beta/_dataframe/columns.py +11 -16
- inspect_ai/analysis/beta/_dataframe/evals/table.py +65 -40
- inspect_ai/analysis/beta/_dataframe/events/table.py +24 -36
- inspect_ai/analysis/beta/_dataframe/messages/table.py +24 -15
- inspect_ai/analysis/beta/_dataframe/progress.py +35 -5
- inspect_ai/analysis/beta/_dataframe/record.py +13 -9
- inspect_ai/analysis/beta/_dataframe/samples/columns.py +1 -1
- inspect_ai/analysis/beta/_dataframe/samples/table.py +156 -46
- inspect_ai/analysis/beta/_dataframe/util.py +14 -12
- inspect_ai/model/_call_tools.py +1 -1
- inspect_ai/model/_providers/anthropic.py +18 -5
- inspect_ai/model/_providers/azureai.py +7 -2
- inspect_ai/model/_providers/util/llama31.py +3 -3
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/METADATA +1 -1
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/RECORD +131 -126
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/WHEEL +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptView.module.css +0 -48
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptView.tsx +0 -276
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/licenses/LICENSE +0 -0
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
import { RecordProcessor } from "./types";
|
2
|
+
|
3
|
+
const kStoreInstanceKey = /^(.+)?:([a-zA-Z0-9]{22}):instance$/;
|
4
|
+
const kStoreKey = /^(.+)?:([a-zA-Z0-9]{22}):(.+)$/;
|
5
|
+
|
6
|
+
// Expands store keys in the record. When an instance key is found, this will create a new node, and subsequent store
|
7
|
+
// keys will be added as children to that node. Since instance keys always appear first, we can do this in a single pass.
|
8
|
+
export const resolveStoreKeys: RecordProcessor = (
|
9
|
+
record: Record<string, unknown>,
|
10
|
+
): Record<string, unknown> => {
|
11
|
+
const result: Record<string, unknown> = {};
|
12
|
+
const storeInstances: Record<string, Record<string, unknown>> = {};
|
13
|
+
const instanceKeys: Set<string> = new Set();
|
14
|
+
|
15
|
+
const entries = Object.entries(record);
|
16
|
+
for (let i = 0; i < entries.length; i++) {
|
17
|
+
const [key, value] = entries[i];
|
18
|
+
|
19
|
+
// First check if it's an instance key
|
20
|
+
const instanceInfo = parseStoreInstanceKey(key, value);
|
21
|
+
if (instanceInfo) {
|
22
|
+
const { storeName, instanceId } = instanceInfo;
|
23
|
+
const instanceKey = storeKey(storeName, instanceId);
|
24
|
+
|
25
|
+
// Create a container for this instance if it doesn't exist
|
26
|
+
if (!storeInstances[instanceKey]) {
|
27
|
+
storeInstances[instanceKey] = {};
|
28
|
+
}
|
29
|
+
|
30
|
+
instanceKeys.add(key);
|
31
|
+
continue;
|
32
|
+
} else {
|
33
|
+
// Then check if it's a store key that belongs to an instance
|
34
|
+
const storeKeyInfo = parseStoreKey(key);
|
35
|
+
if (storeKeyInfo) {
|
36
|
+
const { storeName, instanceId, keyName } = storeKeyInfo;
|
37
|
+
const instanceKey = storeKey(storeName, instanceId);
|
38
|
+
|
39
|
+
// If we have a container for this instance, add this key as a child
|
40
|
+
if (storeInstances[instanceKey]) {
|
41
|
+
storeInstances[instanceKey][keyName] = value;
|
42
|
+
continue;
|
43
|
+
}
|
44
|
+
} else {
|
45
|
+
// If it's not a store key or instance key, add it directly to the result
|
46
|
+
result[key] = value;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
// Add all store instances to the result
|
52
|
+
for (const [instanceKey, children] of Object.entries(storeInstances)) {
|
53
|
+
// Recursively process the children to handle nested store keys
|
54
|
+
result[instanceKey] = resolveStoreKeys(children);
|
55
|
+
}
|
56
|
+
|
57
|
+
// Process any nested objects recursively
|
58
|
+
for (const [key, value] of Object.entries(result)) {
|
59
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
60
|
+
result[key] = resolveStoreKeys(value as Record<string, unknown>);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
return result;
|
65
|
+
};
|
66
|
+
|
67
|
+
// Parses the store instance key
|
68
|
+
const parseStoreInstanceKey = (key: string, value: unknown) => {
|
69
|
+
const match = key.match(kStoreInstanceKey);
|
70
|
+
if (match) {
|
71
|
+
const [, storeName, instanceId] = match;
|
72
|
+
if (typeof value === "string" && instanceId === value) {
|
73
|
+
return {
|
74
|
+
storeName,
|
75
|
+
instanceId,
|
76
|
+
};
|
77
|
+
}
|
78
|
+
}
|
79
|
+
return null;
|
80
|
+
};
|
81
|
+
|
82
|
+
// Parses a store key
|
83
|
+
const parseStoreKey = (key: string) => {
|
84
|
+
const match = key.match(kStoreKey);
|
85
|
+
if (match) {
|
86
|
+
const [, storeName, instanceId, keyName] = match;
|
87
|
+
if (keyName !== "instance") {
|
88
|
+
return {
|
89
|
+
storeName,
|
90
|
+
instanceId,
|
91
|
+
keyName,
|
92
|
+
};
|
93
|
+
}
|
94
|
+
}
|
95
|
+
return null;
|
96
|
+
};
|
97
|
+
|
98
|
+
// Create a unique key for the store instance
|
99
|
+
const storeKey = (storeName: string, instanceId: string) => {
|
100
|
+
return `${storeName || ""} (${instanceId})`;
|
101
|
+
};
|
@@ -6,12 +6,17 @@ export const Buckets = {
|
|
6
6
|
final: 1000,
|
7
7
|
};
|
8
8
|
|
9
|
+
export interface RenderOptions {
|
10
|
+
renderString: "pre" | "markdown";
|
11
|
+
}
|
12
|
+
|
9
13
|
export interface ContentRenderer {
|
10
14
|
bucket: number;
|
11
15
|
canRender: (content: any) => boolean;
|
12
16
|
render: (
|
13
17
|
id: string,
|
14
18
|
content: any,
|
19
|
+
options: RenderOptions,
|
15
20
|
) => {
|
16
21
|
rendered: string | number | bigint | boolean | object | ReactNode | null;
|
17
22
|
};
|
@@ -141,6 +141,7 @@ export const LogView: FC = () => {
|
|
141
141
|
selected={selectedTab === tab.id}
|
142
142
|
scrollable={!!tab.scrollable}
|
143
143
|
scrollRef={tab.scrollRef}
|
144
|
+
className={clsx(tab.className)}
|
144
145
|
style={{ height: tab.scrollable ? "100%" : undefined }}
|
145
146
|
>
|
146
147
|
{createElement(tab.component, tab.componentProps)}
|
@@ -1,7 +1,11 @@
|
|
1
1
|
import { FC, useEffect } from "react";
|
2
2
|
import { useNavigate, useParams } from "react-router-dom";
|
3
3
|
import { kLogViewSamplesTabId } from "../../constants";
|
4
|
-
import {
|
4
|
+
import {
|
5
|
+
useFilteredSamples,
|
6
|
+
usePrevious,
|
7
|
+
useTotalSampleCount,
|
8
|
+
} from "../../state/hooks";
|
5
9
|
import { useStore } from "../../state/store";
|
6
10
|
import { baseUrl } from "../routing/url";
|
7
11
|
import { LogViewLayout } from "./LogViewLayout";
|
@@ -17,26 +21,34 @@ export const LogViewContainer: FC = () => {
|
|
17
21
|
epoch?: string;
|
18
22
|
sampleTabId?: string;
|
19
23
|
}>();
|
20
|
-
const
|
21
|
-
const
|
22
|
-
|
24
|
+
const initialState = useStore((state) => state.app.initialState);
|
25
|
+
const clearInitialState = useStore(
|
26
|
+
(state) => state.appActions.clearInitialState,
|
27
|
+
);
|
28
|
+
const setSampleTab = useStore((state) => state.appActions.setSampleTab);
|
23
29
|
const setShowingSampleDialog = useStore(
|
24
30
|
(state) => state.appActions.setShowingSampleDialog,
|
25
31
|
);
|
26
|
-
const selectSample = useStore((state) => state.logActions.selectSample);
|
27
|
-
const setSampleTab = useStore((state) => state.appActions.setSampleTab);
|
28
|
-
const filteredSamples = useFilteredSamples();
|
29
|
-
const totalSampleCount = useTotalSampleCount();
|
30
32
|
const setStatus = useStore((state) => state.appActions.setStatus);
|
33
|
+
const setWorkspaceTab = useStore((state) => state.appActions.setWorkspaceTab);
|
34
|
+
|
35
|
+
const refreshLogs = useStore((state) => state.logsActions.refreshLogs);
|
36
|
+
const selectLogFile = useStore((state) => state.logsActions.selectLogFile);
|
37
|
+
const selectSample = useStore((state) => state.logActions.selectSample);
|
31
38
|
const setSelectedLogIndex = useStore(
|
32
39
|
(state) => state.logsActions.setSelectedLogIndex,
|
33
40
|
);
|
34
41
|
|
35
|
-
const
|
36
|
-
|
37
|
-
const clearInitialState = useStore(
|
38
|
-
(state) => state.appActions.clearInitialState,
|
42
|
+
const clearSelectedLogSummary = useStore(
|
43
|
+
(state) => state.logActions.clearSelectedLogSummary,
|
39
44
|
);
|
45
|
+
|
46
|
+
const clearSelectedSample = useStore(
|
47
|
+
(state) => state.sampleActions.clearSelectedSample,
|
48
|
+
);
|
49
|
+
|
50
|
+
const filteredSamples = useFilteredSamples();
|
51
|
+
const totalSampleCount = useTotalSampleCount();
|
40
52
|
const navigate = useNavigate();
|
41
53
|
|
42
54
|
useEffect(() => {
|
@@ -51,6 +63,8 @@ export const LogViewContainer: FC = () => {
|
|
51
63
|
}
|
52
64
|
}, [initialState]);
|
53
65
|
|
66
|
+
const prevLogPath = usePrevious<string | undefined>(logPath);
|
67
|
+
|
54
68
|
useEffect(() => {
|
55
69
|
const loadLogFromPath = async () => {
|
56
70
|
if (logPath) {
|
@@ -64,6 +78,13 @@ export const LogViewContainer: FC = () => {
|
|
64
78
|
} else {
|
65
79
|
setWorkspaceTab(kLogViewSamplesTabId);
|
66
80
|
}
|
81
|
+
|
82
|
+
// Reset the sample
|
83
|
+
if (logPath !== prevLogPath) {
|
84
|
+
clearSelectedSample();
|
85
|
+
|
86
|
+
clearSelectedLogSummary();
|
87
|
+
}
|
67
88
|
} else {
|
68
89
|
setStatus({
|
69
90
|
loading: true,
|
@@ -80,10 +101,6 @@ export const LogViewContainer: FC = () => {
|
|
80
101
|
// Select the first log in the list
|
81
102
|
setSelectedLogIndex(0);
|
82
103
|
|
83
|
-
if (!sampleId) {
|
84
|
-
selectSample(0);
|
85
|
-
}
|
86
|
-
|
87
104
|
setStatus({
|
88
105
|
loading: false,
|
89
106
|
error: undefined,
|
@@ -102,16 +119,6 @@ export const LogViewContainer: FC = () => {
|
|
102
119
|
setStatus,
|
103
120
|
]);
|
104
121
|
|
105
|
-
const clearSample = useStore(
|
106
|
-
(state) => state.sampleActions.clearSelectedSample,
|
107
|
-
);
|
108
|
-
|
109
|
-
useEffect(() => {
|
110
|
-
if (selectedLogIndex > -1) {
|
111
|
-
selectSample(0);
|
112
|
-
}
|
113
|
-
}, [selectedLogIndex]);
|
114
|
-
|
115
122
|
// Handle sample selection from URL params
|
116
123
|
useEffect(() => {
|
117
124
|
if (sampleId && filteredSamples) {
|
@@ -140,7 +147,7 @@ export const LogViewContainer: FC = () => {
|
|
140
147
|
// This handles the case when user navigates back from a sample
|
141
148
|
setShowingSampleDialog(false);
|
142
149
|
if (totalSampleCount > 1) {
|
143
|
-
|
150
|
+
clearSelectedSample();
|
144
151
|
}
|
145
152
|
}
|
146
153
|
}, [
|
@@ -152,7 +159,7 @@ export const LogViewContainer: FC = () => {
|
|
152
159
|
selectSample,
|
153
160
|
setSampleTab,
|
154
161
|
setShowingSampleDialog,
|
155
|
-
|
162
|
+
clearSelectedSample,
|
156
163
|
]);
|
157
164
|
|
158
165
|
return <LogViewLayout />;
|
@@ -35,7 +35,6 @@ export const LogViewLayout: FC = () => {
|
|
35
35
|
// Log Data
|
36
36
|
const selectedLogSummary = useStore((state) => state.log.selectedLogSummary);
|
37
37
|
const resetFiltering = useStore((state) => state.logActions.resetFiltering);
|
38
|
-
const selectSample = useStore((state) => state.logActions.selectSample);
|
39
38
|
|
40
39
|
// The main application reference
|
41
40
|
const mainAppRef = useRef<HTMLDivElement>(null);
|
@@ -49,13 +48,7 @@ export const LogViewLayout: FC = () => {
|
|
49
48
|
resetFiltering();
|
50
49
|
clearSampleTab();
|
51
50
|
clearWorkspaceTab();
|
52
|
-
}, [
|
53
|
-
setOffCanvas,
|
54
|
-
resetFiltering,
|
55
|
-
clearSampleTab,
|
56
|
-
clearWorkspaceTab,
|
57
|
-
selectSample,
|
58
|
-
]);
|
51
|
+
}, [setOffCanvas, resetFiltering, clearSampleTab, clearWorkspaceTab]);
|
59
52
|
|
60
53
|
const handleKeyboard = useCallback(
|
61
54
|
(e: KeyboardEvent) => {
|
@@ -7,6 +7,7 @@ import { kModelNone } from "../../../constants";
|
|
7
7
|
import { useStore } from "../../../state/store";
|
8
8
|
import { filename } from "../../../utils/path";
|
9
9
|
import { ApplicationIcons } from "../../appearance/icons";
|
10
|
+
import { ModelRolesView } from "./ModelRolesView";
|
10
11
|
import styles from "./PrimaryBar.module.css";
|
11
12
|
import {
|
12
13
|
displayScorersFromRunningMetrics,
|
@@ -15,7 +16,6 @@ import {
|
|
15
16
|
} from "./ResultsPanel";
|
16
17
|
import { RunningStatusPanel } from "./RunningStatusPanel";
|
17
18
|
import { CancelledPanel, ErroredPanel } from "./StatusPanel";
|
18
|
-
import { ModelRolesView } from "./ModelRolesView";
|
19
19
|
|
20
20
|
interface PrimaryBarProps {
|
21
21
|
showToggle: boolean;
|
@@ -37,9 +37,7 @@ export const PrimaryBar: FC<PrimaryBarProps> = ({
|
|
37
37
|
const offCanvas = useStore((state) => state.app.offcanvas);
|
38
38
|
const setOffCanvas = useStore((state) => state.appActions.setOffcanvas);
|
39
39
|
const streamSamples = useStore((state) => state.capabilities.streamSamples);
|
40
|
-
const selectedLogFile = useStore((state) =>
|
41
|
-
state.logsActions.getSelectedLogFile(),
|
42
|
-
);
|
40
|
+
const selectedLogFile = useStore((state) => state.logs.selectedLogFile);
|
43
41
|
|
44
42
|
const logFileName = selectedLogFile ? filename(selectedLogFile) : "";
|
45
43
|
|
@@ -22,6 +22,8 @@ export interface ResultsScorer {
|
|
22
22
|
metrics: ResultsMetric[];
|
23
23
|
}
|
24
24
|
|
25
|
+
const kMaxPrimaryScoreRows = 4;
|
26
|
+
|
25
27
|
export const displayScorersFromRunningMetrics = (metrics?: RunningMetric[]) => {
|
26
28
|
if (!metrics) {
|
27
29
|
return [];
|
@@ -123,19 +125,27 @@ export const ResultsPanel: FC<ResultsPanelProps> = ({ scorers }) => {
|
|
123
125
|
|
124
126
|
// Try to select metrics with a group size 5 or less, if possible
|
125
127
|
let primaryResults = grouped[0];
|
126
|
-
|
128
|
+
let showMore = grouped.length > 1;
|
129
|
+
if (primaryResults.length > kMaxPrimaryScoreRows) {
|
127
130
|
const shorterResults = grouped.find((g) => {
|
128
|
-
return g.length <=
|
131
|
+
return g.length <= kMaxPrimaryScoreRows;
|
129
132
|
});
|
130
133
|
if (shorterResults) {
|
131
134
|
primaryResults = shorterResults;
|
132
135
|
}
|
136
|
+
|
137
|
+
// If the primary metrics are still too long, truncate them and
|
138
|
+
// show the rest in the modal
|
139
|
+
if (primaryResults.length > kMaxPrimaryScoreRows) {
|
140
|
+
primaryResults = primaryResults.slice(0, kMaxPrimaryScoreRows);
|
141
|
+
showMore = true;
|
142
|
+
}
|
133
143
|
}
|
134
144
|
|
135
145
|
return (
|
136
146
|
<div className={clsx(styles.metricsSummary)}>
|
137
147
|
<ScoreGrid scoreGroups={[primaryResults]} showReducer={showReducer} />
|
138
|
-
{
|
148
|
+
{showMore ? (
|
139
149
|
<>
|
140
150
|
<Modal
|
141
151
|
id="results-metrics"
|
@@ -33,3 +33,18 @@
|
|
33
33
|
.tableBody {
|
34
34
|
border-top-color: var(--bs-light-border-subtle);
|
35
35
|
}
|
36
|
+
|
37
|
+
thead,
|
38
|
+
thead tr,
|
39
|
+
thead td,
|
40
|
+
thead th {
|
41
|
+
border: none !important;
|
42
|
+
padding: 0 !important;
|
43
|
+
}
|
44
|
+
|
45
|
+
.tableSeparator,
|
46
|
+
.tableSeparator tr,
|
47
|
+
.tableSeparator td,
|
48
|
+
.tableSeparator th {
|
49
|
+
border: none !important;
|
50
|
+
}
|
@@ -51,10 +51,12 @@ export const ScoreGrid: FC<ScoreGridProps> = ({
|
|
51
51
|
}
|
52
52
|
|
53
53
|
const headerRow = (
|
54
|
-
<
|
55
|
-
<
|
56
|
-
|
57
|
-
|
54
|
+
<thead>
|
55
|
+
<tr className={clsx(styles.headerRow)}>
|
56
|
+
<td></td>
|
57
|
+
{cells}
|
58
|
+
</tr>
|
59
|
+
</thead>
|
58
60
|
);
|
59
61
|
const rows: ReactNode[] = [];
|
60
62
|
scoreGroup.forEach((g) => {
|
@@ -84,12 +86,14 @@ export const ScoreGrid: FC<ScoreGridProps> = ({
|
|
84
86
|
subTables.push(
|
85
87
|
<>
|
86
88
|
{index > 0 ? (
|
87
|
-
<
|
88
|
-
<
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
89
|
+
<tbody className={clsx(styles.tableSeparator)}>
|
90
|
+
<tr>
|
91
|
+
<td
|
92
|
+
colSpan={columnCount + 1}
|
93
|
+
className={clsx(styles.groupSeparator)}
|
94
|
+
></td>
|
95
|
+
</tr>
|
96
|
+
</tbody>
|
93
97
|
) : undefined}
|
94
98
|
{headerRow}
|
95
99
|
<tbody className={clsx("table-group-divider", styles.tableBody)}>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { FC, useMemo } from "react";
|
1
|
+
import { FC, RefObject, useMemo, useRef } from "react";
|
2
2
|
import {
|
3
3
|
EvalError,
|
4
4
|
EvalPlan,
|
@@ -20,6 +20,7 @@ export const useInfoTabConfig = (
|
|
20
20
|
evalError: EvalError | undefined | null,
|
21
21
|
evalResults: EvalResults | undefined | null,
|
22
22
|
) => {
|
23
|
+
const scrollRef = useRef<HTMLDivElement | null>(null);
|
23
24
|
const totalSampleCount = useTotalSampleCount();
|
24
25
|
return useMemo(() => {
|
25
26
|
return {
|
@@ -33,12 +34,14 @@ export const useInfoTabConfig = (
|
|
33
34
|
evalError,
|
34
35
|
evalResults,
|
35
36
|
sampleCount: totalSampleCount,
|
37
|
+
scrollRef,
|
36
38
|
},
|
39
|
+
scrollRef,
|
37
40
|
};
|
38
41
|
}, [evalSpec, evalPlan, evalError, evalResults, totalSampleCount]);
|
39
42
|
};
|
40
43
|
|
41
|
-
interface
|
44
|
+
interface InfoTabProps {
|
42
45
|
evalSpec?: EvalSpec;
|
43
46
|
evalPlan?: EvalPlan;
|
44
47
|
evalStats?: EvalStats;
|
@@ -47,15 +50,17 @@ interface PlanTabProps {
|
|
47
50
|
evalStatus?: "started" | "error" | "cancelled" | "success";
|
48
51
|
evalError?: EvalError;
|
49
52
|
sampleCount?: number;
|
53
|
+
scrollRef: RefObject<HTMLDivElement | null>;
|
50
54
|
}
|
51
55
|
|
52
|
-
export const InfoTab: FC<
|
56
|
+
export const InfoTab: FC<InfoTabProps> = ({
|
53
57
|
evalSpec,
|
54
58
|
evalPlan,
|
55
59
|
evalResults,
|
56
60
|
evalStatus,
|
57
61
|
evalError,
|
58
62
|
sampleCount,
|
63
|
+
scrollRef,
|
59
64
|
}) => {
|
60
65
|
const showWarning =
|
61
66
|
sampleCount === 0 &&
|
@@ -79,6 +84,7 @@ export const InfoTab: FC<PlanTabProps> = ({
|
|
79
84
|
evalSpec={evalSpec}
|
80
85
|
evalPlan={evalPlan}
|
81
86
|
scores={evalResults?.scores}
|
87
|
+
scrollRef={scrollRef}
|
82
88
|
/>
|
83
89
|
{evalStatus === "error" && evalError ? (
|
84
90
|
<TaskErrorCard error={evalError} />
|
@@ -30,9 +30,7 @@ export const useJsonTabConfig = (
|
|
30
30
|
evalResults: EvalResults | undefined | null,
|
31
31
|
evalStats: EvalStats | undefined,
|
32
32
|
) => {
|
33
|
-
const selectedLogFile = useStore((state) =>
|
34
|
-
state.logsActions.getSelectedLogFile(),
|
35
|
-
);
|
33
|
+
const selectedLogFile = useStore((state) => state.logs.selectedLogFile);
|
36
34
|
const selectedTab = useStore((state) => state.app.tabs.workspace);
|
37
35
|
|
38
36
|
return useMemo(() => {
|
@@ -106,7 +106,9 @@ export const SamplesTab: FC<SamplesTabProps> = ({ running }) => {
|
|
106
106
|
const groupByOrder = useGroupByOrder();
|
107
107
|
const currentScore = useScore();
|
108
108
|
|
109
|
-
const
|
109
|
+
const selectedSampleIdentifier = useStore(
|
110
|
+
(state) => state.sample.sample_identifier,
|
111
|
+
);
|
110
112
|
|
111
113
|
const [items, setItems] = useState<ListItem[]>([]);
|
112
114
|
const [sampleItems, setSampleItems] = useState<ListItem[]>([]);
|
@@ -213,7 +215,11 @@ export const SamplesTab: FC<SamplesTabProps> = ({ running }) => {
|
|
213
215
|
) : undefined}
|
214
216
|
{showingSampleDialog && (
|
215
217
|
<SampleDialog
|
216
|
-
id={
|
218
|
+
id={
|
219
|
+
selectedSampleIdentifier
|
220
|
+
? `${selectedSampleIdentifier.id}_${selectedSampleIdentifier.epoch}`
|
221
|
+
: ""
|
222
|
+
}
|
217
223
|
title={title}
|
218
224
|
showingSampleDialog={showingSampleDialog}
|
219
225
|
/>
|
@@ -9,8 +9,15 @@
|
|
9
9
|
display: grid;
|
10
10
|
grid-template-columns: max-content auto;
|
11
11
|
column-gap: 1em;
|
12
|
+
row-gap: 0.1em;
|
12
13
|
}
|
13
14
|
|
14
15
|
.role {
|
15
16
|
grid-column: -1/1;
|
16
17
|
}
|
18
|
+
|
19
|
+
.sep {
|
20
|
+
grid-column: -1/1;
|
21
|
+
height: 1px;
|
22
|
+
background-color: var(--bs-light-border-subtle);
|
23
|
+
}
|
@@ -51,14 +51,15 @@ export const ModelCard: FC<ModelCardProps> = ({ evalSpec }) => {
|
|
51
51
|
>
|
52
52
|
{modelKey}
|
53
53
|
</div>
|
54
|
-
|
54
|
+
<div className={clsx(styles.sep)} />
|
55
55
|
<div className={clsx("text-style-label")}>Model</div>
|
56
56
|
<div>{modelInfo.model}</div>
|
57
|
-
|
57
|
+
<div className={clsx(styles.sep)} />
|
58
58
|
<div className={clsx("text-style-label")}>Base Url</div>
|
59
59
|
<div className="text-size-small">
|
60
60
|
{modelInfo.base_url || noneEl}
|
61
61
|
</div>
|
62
|
+
<div className={clsx(styles.sep)} />
|
62
63
|
<div className={clsx("text-style-label")}>Configuration</div>
|
63
64
|
<div className="text-size-small">
|
64
65
|
{modelInfo.config &&
|
@@ -72,6 +73,7 @@ export const ModelCard: FC<ModelCardProps> = ({ evalSpec }) => {
|
|
72
73
|
noneEl
|
73
74
|
)}
|
74
75
|
</div>
|
76
|
+
<div className={clsx(styles.sep)} />
|
75
77
|
<div className={clsx("text-style-label")}>Args</div>
|
76
78
|
<div className="text-size-small">
|
77
79
|
{Object.keys(modelInfo.args).length > 0 ? (
|
@@ -82,6 +84,7 @@ export const ModelCard: FC<ModelCardProps> = ({ evalSpec }) => {
|
|
82
84
|
noneEl
|
83
85
|
)}
|
84
86
|
</div>
|
87
|
+
<div className={clsx(styles.sep)} />
|
85
88
|
</div>
|
86
89
|
);
|
87
90
|
})}
|
@@ -1,19 +1,25 @@
|
|
1
|
-
import { FC } from "react";
|
1
|
+
import { FC, RefObject } from "react";
|
2
2
|
import { EvalPlan, EvalScore, EvalSpec } from "../../@types/log";
|
3
3
|
import { Card, CardBody, CardHeader } from "../../components/Card";
|
4
|
-
import {
|
4
|
+
import { RecordTree } from "../content/RecordTree";
|
5
5
|
import { PlanDetailView } from "./PlanDetailView";
|
6
6
|
|
7
7
|
interface PlanCardProps {
|
8
8
|
evalSpec?: EvalSpec;
|
9
9
|
evalPlan?: EvalPlan;
|
10
10
|
scores?: EvalScore[];
|
11
|
+
scrollRef: RefObject<HTMLDivElement | null>;
|
11
12
|
}
|
12
13
|
|
13
14
|
/**
|
14
15
|
* Renders the plan card
|
15
16
|
*/
|
16
|
-
export const PlanCard: FC<PlanCardProps> = ({
|
17
|
+
export const PlanCard: FC<PlanCardProps> = ({
|
18
|
+
evalSpec,
|
19
|
+
evalPlan,
|
20
|
+
scores,
|
21
|
+
scrollRef,
|
22
|
+
}) => {
|
17
23
|
const metadata = evalSpec?.metadata || {};
|
18
24
|
|
19
25
|
return (
|
@@ -33,11 +39,10 @@ export const PlanCard: FC<PlanCardProps> = ({ evalSpec, evalPlan, scores }) => {
|
|
33
39
|
<Card>
|
34
40
|
<CardHeader label="Metadata" />
|
35
41
|
<CardBody id={"task-metadata`"}>
|
36
|
-
<
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
tableOptions="sm"
|
42
|
+
<RecordTree
|
43
|
+
id={"plan-md-metadata"}
|
44
|
+
record={metadata}
|
45
|
+
scrollRef={scrollRef}
|
41
46
|
/>
|
42
47
|
</CardBody>
|
43
48
|
</Card>
|