inspect-ai 0.3.81__py3-none-any.whl → 0.3.82__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.
Files changed (179) hide show
  1. inspect_ai/_cli/eval.py +35 -2
  2. inspect_ai/_cli/util.py +44 -1
  3. inspect_ai/_display/core/config.py +1 -1
  4. inspect_ai/_display/core/display.py +13 -4
  5. inspect_ai/_display/core/results.py +1 -1
  6. inspect_ai/_display/textual/widgets/task_detail.py +5 -4
  7. inspect_ai/_eval/eval.py +38 -1
  8. inspect_ai/_eval/evalset.py +5 -0
  9. inspect_ai/_eval/run.py +5 -2
  10. inspect_ai/_eval/task/log.py +53 -6
  11. inspect_ai/_eval/task/run.py +51 -10
  12. inspect_ai/_util/constants.py +2 -0
  13. inspect_ai/_util/file.py +17 -1
  14. inspect_ai/_util/json.py +36 -1
  15. inspect_ai/_view/server.py +113 -1
  16. inspect_ai/_view/www/App.css +1 -1
  17. inspect_ai/_view/www/dist/assets/index.css +518 -296
  18. inspect_ai/_view/www/dist/assets/index.js +38803 -36307
  19. inspect_ai/_view/www/eslint.config.mjs +1 -1
  20. inspect_ai/_view/www/log-schema.json +13 -0
  21. inspect_ai/_view/www/node_modules/flatted/python/flatted.py +149 -0
  22. inspect_ai/_view/www/package.json +8 -2
  23. inspect_ai/_view/www/src/App.tsx +151 -855
  24. inspect_ai/_view/www/src/api/api-browser.ts +176 -5
  25. inspect_ai/_view/www/src/api/api-vscode.ts +75 -1
  26. inspect_ai/_view/www/src/api/client-api.ts +66 -10
  27. inspect_ai/_view/www/src/api/jsonrpc.ts +2 -0
  28. inspect_ai/_view/www/src/api/types.ts +107 -2
  29. inspect_ai/_view/www/src/appearance/icons.ts +1 -0
  30. inspect_ai/_view/www/src/components/AsciinemaPlayer.tsx +3 -3
  31. inspect_ai/_view/www/src/components/DownloadPanel.tsx +2 -2
  32. inspect_ai/_view/www/src/components/ExpandablePanel.tsx +56 -61
  33. inspect_ai/_view/www/src/components/FindBand.tsx +17 -9
  34. inspect_ai/_view/www/src/components/HumanBaselineView.tsx +1 -1
  35. inspect_ai/_view/www/src/components/JsonPanel.tsx +14 -24
  36. inspect_ai/_view/www/src/components/LargeModal.tsx +2 -35
  37. inspect_ai/_view/www/src/components/LightboxCarousel.tsx +27 -11
  38. inspect_ai/_view/www/src/components/LiveVirtualList.module.css +11 -0
  39. inspect_ai/_view/www/src/components/LiveVirtualList.tsx +177 -0
  40. inspect_ai/_view/www/src/components/MarkdownDiv.tsx +3 -3
  41. inspect_ai/_view/www/src/components/MessageBand.tsx +14 -9
  42. inspect_ai/_view/www/src/components/MorePopOver.tsx +3 -3
  43. inspect_ai/_view/www/src/components/NavPills.tsx +20 -8
  44. inspect_ai/_view/www/src/components/NoContentsPanel.module.css +12 -0
  45. inspect_ai/_view/www/src/components/NoContentsPanel.tsx +20 -0
  46. inspect_ai/_view/www/src/components/ProgressBar.module.css +5 -4
  47. inspect_ai/_view/www/src/components/ProgressBar.tsx +3 -2
  48. inspect_ai/_view/www/src/components/PulsingDots.module.css +81 -0
  49. inspect_ai/_view/www/src/components/PulsingDots.tsx +45 -0
  50. inspect_ai/_view/www/src/components/TabSet.tsx +4 -37
  51. inspect_ai/_view/www/src/components/ToolButton.tsx +3 -4
  52. inspect_ai/_view/www/src/index.tsx +26 -94
  53. inspect_ai/_view/www/src/logfile/remoteLogFile.ts +9 -1
  54. inspect_ai/_view/www/src/logfile/remoteZipFile.ts +30 -4
  55. inspect_ai/_view/www/src/metadata/RenderedContent.tsx +4 -6
  56. inspect_ai/_view/www/src/plan/ScorerDetailView.tsx +1 -1
  57. inspect_ai/_view/www/src/samples/InlineSampleDisplay.module.css +9 -1
  58. inspect_ai/_view/www/src/samples/InlineSampleDisplay.tsx +67 -28
  59. inspect_ai/_view/www/src/samples/SampleDialog.tsx +51 -22
  60. inspect_ai/_view/www/src/samples/SampleDisplay.module.css +4 -0
  61. inspect_ai/_view/www/src/samples/SampleDisplay.tsx +144 -90
  62. inspect_ai/_view/www/src/samples/SampleSummaryView.module.css +4 -0
  63. inspect_ai/_view/www/src/samples/SampleSummaryView.tsx +82 -35
  64. inspect_ai/_view/www/src/samples/SamplesTools.tsx +23 -30
  65. inspect_ai/_view/www/src/samples/chat/ChatMessage.tsx +2 -1
  66. inspect_ai/_view/www/src/samples/chat/ChatMessageRenderer.tsx +1 -1
  67. inspect_ai/_view/www/src/samples/chat/ChatViewVirtualList.tsx +45 -53
  68. inspect_ai/_view/www/src/samples/chat/MessageContent.tsx +4 -1
  69. inspect_ai/_view/www/src/samples/chat/MessageContents.tsx +3 -0
  70. inspect_ai/_view/www/src/samples/chat/messages.ts +34 -0
  71. inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.module.css +3 -0
  72. inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.tsx +10 -1
  73. inspect_ai/_view/www/src/samples/chat/tools/ToolInput.tsx +22 -46
  74. inspect_ai/_view/www/src/samples/descriptor/samplesDescriptor.tsx +25 -17
  75. inspect_ai/_view/www/src/samples/descriptor/score/ObjectScoreDescriptor.tsx +2 -1
  76. inspect_ai/_view/www/src/samples/descriptor/types.ts +6 -5
  77. inspect_ai/_view/www/src/samples/list/SampleFooter.module.css +21 -3
  78. inspect_ai/_view/www/src/samples/list/SampleFooter.tsx +20 -1
  79. inspect_ai/_view/www/src/samples/list/SampleList.tsx +105 -85
  80. inspect_ai/_view/www/src/samples/list/SampleRow.module.css +6 -0
  81. inspect_ai/_view/www/src/samples/list/SampleRow.tsx +27 -14
  82. inspect_ai/_view/www/src/samples/sample-tools/SelectScorer.tsx +29 -18
  83. inspect_ai/_view/www/src/samples/sample-tools/SortFilter.tsx +28 -28
  84. inspect_ai/_view/www/src/samples/sample-tools/sample-filter/SampleFilter.tsx +19 -9
  85. inspect_ai/_view/www/src/samples/sampleDataAdapter.ts +33 -0
  86. inspect_ai/_view/www/src/samples/sampleLimit.ts +2 -2
  87. inspect_ai/_view/www/src/samples/scores/SampleScoreView.tsx +7 -9
  88. inspect_ai/_view/www/src/samples/scores/SampleScores.tsx +7 -11
  89. inspect_ai/_view/www/src/samples/transcript/ErrorEventView.tsx +0 -13
  90. inspect_ai/_view/www/src/samples/transcript/InfoEventView.tsx +0 -13
  91. inspect_ai/_view/www/src/samples/transcript/InputEventView.tsx +0 -13
  92. inspect_ai/_view/www/src/samples/transcript/ModelEventView.module.css +4 -0
  93. inspect_ai/_view/www/src/samples/transcript/ModelEventView.tsx +10 -24
  94. inspect_ai/_view/www/src/samples/transcript/SampleInitEventView.tsx +0 -13
  95. inspect_ai/_view/www/src/samples/transcript/SampleLimitEventView.tsx +4 -22
  96. inspect_ai/_view/www/src/samples/transcript/SandboxEventView.tsx +15 -24
  97. inspect_ai/_view/www/src/samples/transcript/ScoreEventView.tsx +0 -13
  98. inspect_ai/_view/www/src/samples/transcript/StepEventView.tsx +6 -28
  99. inspect_ai/_view/www/src/samples/transcript/SubtaskEventView.tsx +24 -34
  100. inspect_ai/_view/www/src/samples/transcript/ToolEventView.module.css +4 -0
  101. inspect_ai/_view/www/src/samples/transcript/ToolEventView.tsx +8 -13
  102. inspect_ai/_view/www/src/samples/transcript/TranscriptView.tsx +197 -338
  103. inspect_ai/_view/www/src/samples/transcript/TranscriptVirtualListComponent.module.css +16 -0
  104. inspect_ai/_view/www/src/samples/transcript/TranscriptVirtualListComponent.tsx +44 -0
  105. inspect_ai/_view/www/src/samples/transcript/event/EventNav.tsx +7 -4
  106. inspect_ai/_view/www/src/samples/transcript/event/EventPanel.tsx +52 -58
  107. inspect_ai/_view/www/src/samples/transcript/event/EventProgressPanel.module.css +23 -0
  108. inspect_ai/_view/www/src/samples/transcript/event/EventProgressPanel.tsx +27 -0
  109. inspect_ai/_view/www/src/samples/transcript/state/StateEventRenderers.tsx +30 -1
  110. inspect_ai/_view/www/src/samples/transcript/state/StateEventView.tsx +102 -72
  111. inspect_ai/_view/www/src/scoring/utils.ts +87 -0
  112. inspect_ai/_view/www/src/state/appSlice.ts +244 -0
  113. inspect_ai/_view/www/src/state/hooks.ts +397 -0
  114. inspect_ai/_view/www/src/state/logPolling.ts +196 -0
  115. inspect_ai/_view/www/src/state/logSlice.ts +214 -0
  116. inspect_ai/_view/www/src/state/logsPolling.ts +118 -0
  117. inspect_ai/_view/www/src/state/logsSlice.ts +181 -0
  118. inspect_ai/_view/www/src/state/samplePolling.ts +311 -0
  119. inspect_ai/_view/www/src/state/sampleSlice.ts +127 -0
  120. inspect_ai/_view/www/src/state/sampleUtils.ts +21 -0
  121. inspect_ai/_view/www/src/state/scrolling.ts +206 -0
  122. inspect_ai/_view/www/src/state/store.ts +168 -0
  123. inspect_ai/_view/www/src/state/store_filter.ts +84 -0
  124. inspect_ai/_view/www/src/state/utils.ts +23 -0
  125. inspect_ai/_view/www/src/storage/index.ts +26 -0
  126. inspect_ai/_view/www/src/types/log.d.ts +2 -0
  127. inspect_ai/_view/www/src/types.ts +94 -32
  128. inspect_ai/_view/www/src/utils/attachments.ts +58 -23
  129. inspect_ai/_view/www/src/utils/logger.ts +52 -0
  130. inspect_ai/_view/www/src/utils/polling.ts +100 -0
  131. inspect_ai/_view/www/src/utils/react.ts +30 -0
  132. inspect_ai/_view/www/src/utils/vscode.ts +1 -1
  133. inspect_ai/_view/www/src/workspace/WorkSpace.tsx +181 -216
  134. inspect_ai/_view/www/src/workspace/WorkSpaceView.tsx +11 -53
  135. inspect_ai/_view/www/src/workspace/navbar/Navbar.tsx +8 -18
  136. inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.module.css +1 -0
  137. inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.tsx +40 -22
  138. inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.module.css +0 -1
  139. inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.tsx +98 -39
  140. inspect_ai/_view/www/src/workspace/navbar/RunningStatusPanel.module.css +32 -0
  141. inspect_ai/_view/www/src/workspace/navbar/RunningStatusPanel.tsx +32 -0
  142. inspect_ai/_view/www/src/workspace/navbar/SecondaryBar.tsx +11 -13
  143. inspect_ai/_view/www/src/workspace/navbar/StatusPanel.tsx +6 -2
  144. inspect_ai/_view/www/src/workspace/sidebar/LogDirectoryTitleView.tsx +4 -4
  145. inspect_ai/_view/www/src/workspace/sidebar/Sidebar.tsx +28 -13
  146. inspect_ai/_view/www/src/workspace/tabs/InfoTab.tsx +5 -10
  147. inspect_ai/_view/www/src/workspace/tabs/JsonTab.tsx +4 -4
  148. inspect_ai/_view/www/src/workspace/tabs/RunningNoSamples.module.css +22 -0
  149. inspect_ai/_view/www/src/workspace/tabs/RunningNoSamples.tsx +19 -0
  150. inspect_ai/_view/www/src/workspace/tabs/SamplesTab.tsx +110 -115
  151. inspect_ai/_view/www/src/workspace/tabs/grouping.ts +37 -5
  152. inspect_ai/_view/www/src/workspace/tabs/types.ts +4 -0
  153. inspect_ai/_view/www/src/workspace/types.ts +4 -3
  154. inspect_ai/_view/www/src/workspace/utils.ts +4 -4
  155. inspect_ai/_view/www/vite.config.js +6 -0
  156. inspect_ai/_view/www/yarn.lock +370 -354
  157. inspect_ai/log/_condense.py +26 -0
  158. inspect_ai/log/_log.py +6 -3
  159. inspect_ai/log/_recorders/buffer/__init__.py +14 -0
  160. inspect_ai/log/_recorders/buffer/buffer.py +30 -0
  161. inspect_ai/log/_recorders/buffer/database.py +685 -0
  162. inspect_ai/log/_recorders/buffer/filestore.py +259 -0
  163. inspect_ai/log/_recorders/buffer/types.py +84 -0
  164. inspect_ai/log/_recorders/eval.py +2 -11
  165. inspect_ai/log/_recorders/types.py +30 -0
  166. inspect_ai/log/_transcript.py +27 -1
  167. inspect_ai/model/_call_tools.py +1 -0
  168. inspect_ai/model/_generate_config.py +2 -2
  169. inspect_ai/model/_model.py +1 -0
  170. inspect_ai/tool/_tool_support_helpers.py +4 -4
  171. inspect_ai/tool/_tools/_web_browser/_web_browser.py +3 -1
  172. inspect_ai/util/_subtask.py +1 -0
  173. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.82.dist-info}/METADATA +1 -1
  174. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.82.dist-info}/RECORD +178 -138
  175. inspect_ai/_view/www/src/samples/transcript/SampleTranscript.tsx +0 -22
  176. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.82.dist-info}/WHEEL +0 -0
  177. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.82.dist-info}/entry_points.txt +0 -0
  178. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.82.dist-info}/licenses/LICENSE +0 -0
  179. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.82.dist-info}/top_level.txt +0 -0
@@ -1,16 +1,15 @@
1
1
  import clsx from "clsx";
2
2
  import {
3
+ createElement,
3
4
  FC,
4
5
  Fragment,
5
6
  MouseEvent,
6
7
  RefObject,
7
8
  useCallback,
8
- useMemo,
9
9
  } from "react";
10
- import { SampleSummary } from "../api/types";
10
+ import { RunningMetric } from "../api/types";
11
11
  import { EmptyPanel } from "../components/EmptyPanel";
12
12
  import { TabPanel, TabSet } from "../components/TabSet";
13
- import { EvalDescriptor } from "../samples/descriptor/types";
14
13
  import {
15
14
  EvalPlan,
16
15
  EvalResults,
@@ -18,63 +17,37 @@ import {
18
17
  EvalStats,
19
18
  Status,
20
19
  } from "../types/log";
21
- import { debounce } from "../utils/sync";
22
20
  import { Navbar } from "./navbar/Navbar";
23
21
  import { TabDescriptor } from "./types";
24
22
 
23
+ import { useStore } from "../state/store";
25
24
  import styles from "./WorkSpaceView.module.css";
26
25
 
27
26
  interface WorkSpaceViewProps {
28
- logFileName?: string;
29
27
  evalSpec: EvalSpec;
30
28
  evalPlan?: EvalPlan;
31
29
  evalResults?: EvalResults;
30
+ runningMetrics?: RunningMetric[];
32
31
  evalStats?: EvalStats;
33
- samples?: SampleSummary[];
34
- evalDescriptor?: EvalDescriptor;
35
32
  status?: Status;
36
33
  showToggle: boolean;
37
- tabs: Record<string, TabDescriptor>;
38
- selectedTab: string;
39
- setSelectedTab: (tab: string) => void;
34
+ tabs: Record<string, TabDescriptor<any>>;
40
35
  divRef: RefObject<HTMLDivElement | null>;
41
- offcanvas: boolean;
42
- setOffcanvas: (offcanvas: boolean) => void;
43
- workspaceTabScrollPositionRef: RefObject<Record<string, number>>;
44
- setWorkspaceTabScrollPosition: (tab: string, pos: number) => void;
45
36
  }
46
37
 
47
38
  export const WorkSpaceView: FC<WorkSpaceViewProps> = ({
48
- logFileName,
49
39
  evalSpec,
50
40
  evalPlan,
51
41
  evalResults,
42
+ runningMetrics,
52
43
  evalStats,
53
- samples,
54
- evalDescriptor,
55
44
  status,
56
45
  showToggle,
57
- selectedTab,
58
46
  tabs,
59
- setSelectedTab,
60
47
  divRef,
61
- offcanvas,
62
- setOffcanvas,
63
- workspaceTabScrollPositionRef,
64
- setWorkspaceTabScrollPosition,
65
48
  }) => {
66
- const debouncedScroll = useMemo(() => {
67
- return debounce((id, position) => {
68
- setWorkspaceTabScrollPosition(id, position);
69
- }, 100);
70
- }, [setWorkspaceTabScrollPosition]);
71
-
72
- const onScroll = useCallback(
73
- (id: string, position: number) => {
74
- debouncedScroll(id, position);
75
- },
76
- [debouncedScroll],
77
- );
49
+ const selectedTab = useStore((state) => state.app.tabs.workspace);
50
+ const setSelectedTab = useStore((state) => state.appActions.setWorkspaceTab);
78
51
 
79
52
  const onSelected = useCallback(
80
53
  (e: MouseEvent<HTMLElement>) => {
@@ -85,12 +58,6 @@ export const WorkSpaceView: FC<WorkSpaceViewProps> = ({
85
58
  },
86
59
  [setSelectedTab],
87
60
  );
88
- const handleScroll = useCallback(
89
- (tabid: string, position: number) => {
90
- onScroll(tabid, position);
91
- },
92
- [onScroll],
93
- );
94
61
 
95
62
  if (evalSpec === undefined) {
96
63
  return <EmptyPanel />;
@@ -118,14 +85,10 @@ export const WorkSpaceView: FC<WorkSpaceViewProps> = ({
118
85
  evalSpec={evalSpec}
119
86
  evalPlan={evalPlan}
120
87
  evalResults={evalResults}
88
+ runningMetrics={runningMetrics}
121
89
  evalStats={evalStats}
122
- samples={samples}
123
- evalDescriptor={evalDescriptor}
124
90
  status={status}
125
- file={logFileName}
126
91
  showToggle={showToggle}
127
- offcanvas={offcanvas}
128
- setOffcanvas={setOffcanvas}
129
92
  />
130
93
  <div ref={divRef} className={clsx("workspace", styles.workspace)}>
131
94
  <div className={clsx("log-detail", styles.tabContainer)}>
@@ -148,14 +111,9 @@ export const WorkSpaceView: FC<WorkSpaceViewProps> = ({
148
111
  selected={selectedTab === tab.id}
149
112
  scrollable={!!tab.scrollable}
150
113
  scrollRef={tab.scrollRef}
151
- scrollPosition={
152
- workspaceTabScrollPositionRef.current?.[tab.id]
153
- }
154
- setScrollPosition={(position: number) => {
155
- handleScroll(tab.id, position);
156
- }}
114
+ style={{ height: tab.scrollable ? "100%" : undefined }}
157
115
  >
158
- {tab.content()}
116
+ {createElement(tab.component, tab.componentProps)}
159
117
  </TabPanel>
160
118
  );
161
119
  })}
@@ -1,7 +1,7 @@
1
1
  import clsx from "clsx";
2
2
  import { FC } from "react";
3
- import { SampleSummary } from "../../api/types";
4
- import { EvalDescriptor } from "../../samples/descriptor/types";
3
+ import { RunningMetric } from "../../api/types";
4
+ import { useTotalSampleCount } from "../../state/hooks";
5
5
  import {
6
6
  EvalPlan,
7
7
  EvalResults,
@@ -14,16 +14,12 @@ import { PrimaryBar } from "./PrimaryBar";
14
14
  import { SecondaryBar } from "./SecondaryBar";
15
15
 
16
16
  interface NavBarProps {
17
- file?: string;
18
17
  evalSpec?: EvalSpec;
19
18
  evalResults?: EvalResults;
19
+ runningMetrics?: RunningMetric[];
20
20
  evalPlan?: EvalPlan;
21
21
  evalStats?: EvalStats;
22
- evalDescriptor?: EvalDescriptor;
23
- samples?: SampleSummary[];
24
22
  status?: Status;
25
- offcanvas: boolean;
26
- setOffcanvas: (offcanvas: boolean) => void;
27
23
  showToggle: boolean;
28
24
  }
29
25
 
@@ -31,38 +27,32 @@ interface NavBarProps {
31
27
  * Renders the Navbar
32
28
  */
33
29
  export const Navbar: FC<NavBarProps> = ({
34
- file,
35
30
  evalSpec,
36
31
  evalPlan,
37
32
  evalResults,
38
33
  evalStats,
39
- samples,
40
- evalDescriptor,
41
34
  showToggle,
42
- offcanvas,
43
- setOffcanvas,
44
35
  status,
36
+ runningMetrics,
45
37
  }) => {
38
+ const totalSampleCount = useTotalSampleCount();
46
39
  return (
47
40
  <nav className={clsx("navbar", "sticky-top", styles.navbarWrapper)}>
48
41
  <PrimaryBar
49
- file={file}
50
42
  evalSpec={evalSpec}
51
43
  evalResults={evalResults}
52
- samples={samples}
53
44
  showToggle={showToggle}
54
- offcanvas={offcanvas}
55
- setOffcanvas={setOffcanvas}
56
45
  status={status}
46
+ runningMetrics={runningMetrics}
47
+ sampleCount={totalSampleCount}
57
48
  />
58
49
  <SecondaryBar
59
50
  evalSpec={evalSpec}
60
51
  evalPlan={evalPlan}
61
52
  evalResults={evalResults}
62
53
  evalStats={evalStats}
63
- samples={samples}
64
- evalDescriptor={evalDescriptor}
65
54
  status={status}
55
+ sampleCount={totalSampleCount}
66
56
  />
67
57
  </nav>
68
58
  );
@@ -38,6 +38,7 @@
38
38
  }
39
39
 
40
40
  .taskStatus {
41
+ display: flex;
41
42
  justify-content: end;
42
43
  margin-right: 1em;
43
44
  margin-bottom: 0;
@@ -1,41 +1,52 @@
1
1
  import clsx from "clsx";
2
2
  import { FC, useCallback } from "react";
3
- import { SampleSummary } from "../../api/types";
3
+ import { RunningMetric } from "../../api/types";
4
4
  import { ApplicationIcons } from "../../appearance/icons";
5
5
  import { CopyButton } from "../../components/CopyButton";
6
6
  import { kModelNone } from "../../constants";
7
+ import { useStore } from "../../state/store";
7
8
  import { EvalResults, EvalSpec, Status } from "../../types/log";
8
9
  import { filename } from "../../utils/path";
9
10
  import styles from "./PrimaryBar.module.css";
10
- import { ResultsPanel } from "./ResultsPanel";
11
- import { CancelledPanel, ErroredPanel, RunningPanel } from "./StatusPanel";
11
+ import {
12
+ displayScorersFromRunningMetrics,
13
+ ResultsPanel,
14
+ toDisplayScorers,
15
+ } from "./ResultsPanel";
16
+ import { RunningStatusPanel } from "./RunningStatusPanel";
17
+ import { CancelledPanel, ErroredPanel } from "./StatusPanel";
12
18
 
13
19
  interface PrimaryBarProps {
14
20
  showToggle: boolean;
15
- offcanvas: boolean;
16
- setOffcanvas: (offcanvas: boolean) => void;
17
21
  status?: Status;
18
22
  evalResults?: EvalResults;
19
- samples?: SampleSummary[];
20
- file?: string;
23
+ runningMetrics?: RunningMetric[];
21
24
  evalSpec?: EvalSpec;
25
+ sampleCount?: number;
22
26
  }
23
27
 
24
28
  export const PrimaryBar: FC<PrimaryBarProps> = ({
25
29
  showToggle,
26
- offcanvas,
27
30
  status,
28
31
  evalResults,
29
- samples,
30
- file,
32
+ runningMetrics,
31
33
  evalSpec,
32
- setOffcanvas,
34
+ sampleCount,
33
35
  }) => {
34
- const logFileName = file ? filename(file) : "";
36
+ const offCanvas = useStore((state) => state.app.offcanvas);
37
+ const setOffCanvas = useStore((state) => state.appActions.setOffcanvas);
38
+ const streamSamples = useStore((state) => state.capabilities.streamSamples);
39
+ const selectedLogFile = useStore((state) =>
40
+ state.logsActions.getSelectedLogFile(),
41
+ );
42
+
43
+ const logFileName = selectedLogFile ? filename(selectedLogFile) : "";
35
44
 
36
45
  const handleToggle = useCallback(() => {
37
- setOffcanvas(!offcanvas);
38
- }, [setOffcanvas, offcanvas]);
46
+ setOffCanvas(!offCanvas);
47
+ }, [offCanvas, setOffCanvas]);
48
+
49
+ const hasRunningMetrics = runningMetrics && runningMetrics.length > 0;
39
50
 
40
51
  return (
41
52
  <div className={clsx(styles.wrapper)}>
@@ -53,7 +64,7 @@ export const PrimaryBar: FC<PrimaryBarProps> = ({
53
64
  onClick={handleToggle}
54
65
  className={clsx(
55
66
  "btn",
56
- offcanvas ? "d-md-none" : undefined,
67
+ offCanvas ? "d-md-none" : undefined,
57
68
  styles.toggle,
58
69
  )}
59
70
  type="button"
@@ -93,22 +104,29 @@ export const PrimaryBar: FC<PrimaryBarProps> = ({
93
104
  <div className={clsx("navbar-secondary-text", "text-truncate")}>
94
105
  {logFileName}
95
106
  </div>
96
- {file ? <CopyButton value={file} /> : ""}
107
+ {selectedLogFile ? <CopyButton value={selectedLogFile} /> : ""}
97
108
  </div>
98
109
  </div>
99
110
  </div>
100
111
  <div className={clsx(styles.taskStatus, "navbar-text")}>
101
- {status === "success" ? (
102
- <ResultsPanel results={evalResults} />
112
+ {status === "success" ||
113
+ (status === "started" && streamSamples && hasRunningMetrics) ? (
114
+ <ResultsPanel
115
+ scorers={
116
+ runningMetrics
117
+ ? displayScorersFromRunningMetrics(runningMetrics)
118
+ : toDisplayScorers(evalResults?.scores)
119
+ }
120
+ />
103
121
  ) : undefined}
104
122
  {status === "cancelled" ? (
105
- <CancelledPanel sampleCount={samples?.length || 0} />
123
+ <CancelledPanel sampleCount={sampleCount || 0} />
106
124
  ) : undefined}
107
- {status === "started" ? (
108
- <RunningPanel sampleCount={samples?.length || 0} />
125
+ {status === "started" && (!streamSamples || !hasRunningMetrics) ? (
126
+ <RunningStatusPanel sampleCount={sampleCount || 0} />
109
127
  ) : undefined}
110
128
  {status === "error" ? (
111
- <ErroredPanel sampleCount={samples?.length || 0} />
129
+ <ErroredPanel sampleCount={sampleCount || 0} />
112
130
  ) : undefined}
113
131
  </div>
114
132
  <div id="task-created" style={{ display: "none" }}>
@@ -45,7 +45,6 @@
45
45
 
46
46
  .multiScorer {
47
47
  padding-left: 0;
48
- height: 100%;
49
48
  display: flex;
50
49
  flex-direction: column;
51
50
  padding: 0.5em 1em;
@@ -1,46 +1,103 @@
1
1
  import clsx from "clsx";
2
2
  import { FC } from "react";
3
- import { EvalMetric, EvalResults, EvalScore, Reducer } from "../../types/log";
3
+ import { RunningMetric } from "../../api/types";
4
+ import { Scores } from "../../types/log";
4
5
  import { formatPrettyDecimal } from "../../utils/format";
5
6
  import { metricDisplayName } from "../utils";
6
7
  import styles from "./ResultsPanel.module.css";
7
8
 
8
- interface ResultsPanelProps {
9
- results?: EvalResults;
9
+ export interface ResultsMetric {
10
+ name: string;
11
+ params?: {};
12
+ value: number;
10
13
  }
11
14
 
12
- interface MetricSummary {
13
- reducer: Reducer;
14
- metric: EvalMetric;
15
+ export interface ResultsScorer {
16
+ scorer: string;
17
+ reducer?: string;
18
+ metrics: ResultsMetric[];
15
19
  }
16
20
 
17
- export const ResultsPanel: FC<ResultsPanelProps> = ({ results }) => {
18
- // Map the scores into a list of key/values
19
- if (results?.scores?.length === 1) {
20
- const scorers: Record<string, MetricSummary[]> = {};
21
- results.scores.map((score) => {
22
- scorers[score.name] = Object.keys(score.metrics).map((key) => {
21
+ export const displayScorersFromRunningMetrics = (metrics?: RunningMetric[]) => {
22
+ if (!metrics) {
23
+ return [];
24
+ }
25
+
26
+ const getKey = (metric: RunningMetric) => {
27
+ return metric.reducer
28
+ ? `${metric.scorer}-${metric.reducer}`
29
+ : metric.scorer;
30
+ };
31
+
32
+ const scorers: Record<string, ResultsScorer> = {};
33
+ metrics.forEach((metric) => {
34
+ if (metric.value !== undefined) {
35
+ const key = getKey(metric);
36
+ if (scorers[key]) {
37
+ scorers[key].metrics.push({
38
+ name: metric.name,
39
+ value: metric.value,
40
+ });
41
+ } else {
42
+ scorers[key] = {
43
+ scorer: metric.scorer,
44
+ reducer: metric.reducer,
45
+ metrics: [
46
+ {
47
+ name: metric.name,
48
+ value: metric.value,
49
+ },
50
+ ],
51
+ };
52
+ }
53
+ }
54
+ });
55
+
56
+ return Object.values(scorers);
57
+ };
58
+
59
+ export const toDisplayScorers = (scores?: Scores): ResultsScorer[] => {
60
+ if (!scores) {
61
+ return [];
62
+ }
63
+
64
+ return scores.map((score) => {
65
+ return {
66
+ scorer: score.name,
67
+ reducer: score.reducer === null ? undefined : score.reducer,
68
+ metrics: Object.keys(score.metrics).map((key) => {
69
+ const metric = score.metrics[key];
23
70
  return {
24
- reducer: score.reducer,
25
- metric: {
26
- name: key,
27
- value: score.metrics[key].value,
28
- params: score.metrics[key].params,
29
- metadata: {},
30
- },
71
+ name: metric.name,
72
+ value: metric.value,
73
+ params: metric.params,
31
74
  };
32
- });
33
- });
75
+ }),
76
+ };
77
+ });
78
+ };
79
+
80
+ interface ResultsPanelProps {
81
+ scorers?: ResultsScorer[];
82
+ }
83
+
84
+ export const ResultsPanel: FC<ResultsPanelProps> = ({ scorers }) => {
85
+ if (!scorers || scorers.length === 0) {
86
+ return undefined;
87
+ }
34
88
 
35
- const metrics = Object.values(scorers)[0];
36
- const showReducer = metrics && metrics.length > 0 && !!metrics[0].reducer;
89
+ // Get the display scorers
90
+ if (scorers.length === 1) {
91
+ const showReducer = !!scorers[0].reducer;
92
+ const metrics = scorers[0].metrics;
37
93
  return (
38
94
  <div className={styles.simpleMetricsRows}>
39
95
  {metrics.map((metric, i) => {
40
96
  return (
41
97
  <VerticalMetric
42
98
  key={`simple-metric-${i}`}
43
- metricSummary={metric}
99
+ reducer={scorers[0].reducer}
100
+ metric={metric}
44
101
  isFirst={i === 0}
45
102
  showReducer={showReducer}
46
103
  />
@@ -49,15 +106,14 @@ export const ResultsPanel: FC<ResultsPanelProps> = ({ results }) => {
49
106
  </div>
50
107
  );
51
108
  } else {
52
- const showReducer =
53
- results?.scores.findIndex((score) => !!score.reducer) !== -1;
109
+ const showReducer = scorers.findIndex((score) => !!score.reducer) !== -1;
54
110
  return (
55
111
  <div className={styles.multiMetricsRows}>
56
- {results?.scores?.map((score, index) => {
112
+ {scorers.map((scorer, index) => {
57
113
  return (
58
114
  <MultiScorerMetric
59
115
  key={`multi-metric-${index}`}
60
- scorer={score}
116
+ scorer={scorer}
61
117
  isFirst={index === 0}
62
118
  showReducer={showReducer}
63
119
  />
@@ -69,7 +125,8 @@ export const ResultsPanel: FC<ResultsPanelProps> = ({ results }) => {
69
125
  };
70
126
 
71
127
  interface VerticalMetricProps {
72
- metricSummary: MetricSummary;
128
+ metric: ResultsMetric;
129
+ reducer?: string;
73
130
  isFirst: boolean;
74
131
  showReducer: boolean;
75
132
  }
@@ -77,7 +134,8 @@ interface VerticalMetricProps {
77
134
  /** Renders a Vertical Metric
78
135
  */
79
136
  const VerticalMetric: FC<VerticalMetricProps> = ({
80
- metricSummary,
137
+ metric,
138
+ reducer,
81
139
  isFirst,
82
140
  showReducer,
83
141
  }) => {
@@ -91,7 +149,7 @@ const VerticalMetric: FC<VerticalMetricProps> = ({
91
149
  styles.verticalMetricName,
92
150
  )}
93
151
  >
94
- {metricDisplayName(metricSummary.metric)}
152
+ {metricDisplayName(metric)}
95
153
  </div>
96
154
  {showReducer ? (
97
155
  <div
@@ -101,7 +159,7 @@ const VerticalMetric: FC<VerticalMetricProps> = ({
101
159
  styles.verticalMetricReducer,
102
160
  )}
103
161
  >
104
- {metricSummary.reducer || "default"}
162
+ {reducer || "default"}
105
163
  </div>
106
164
  ) : undefined}
107
165
 
@@ -112,14 +170,16 @@ const VerticalMetric: FC<VerticalMetricProps> = ({
112
170
  styles.verticalMetricValue,
113
171
  )}
114
172
  >
115
- {formatPrettyDecimal(metricSummary.metric.value)}
173
+ {metric.value !== undefined && metric.value !== null
174
+ ? formatPrettyDecimal(metric.value)
175
+ : "n/a"}
116
176
  </div>
117
177
  </div>
118
178
  );
119
179
  };
120
180
 
121
181
  interface MultiScorerMetricProps {
122
- scorer: EvalScore;
182
+ scorer: ResultsScorer;
123
183
  isFirst: boolean;
124
184
  showReducer: boolean;
125
185
  }
@@ -149,7 +209,7 @@ const MultiScorerMetric: FC<MultiScorerMetricProps> = ({
149
209
  styles.multiScorerLabel,
150
210
  )}
151
211
  >
152
- {scorer.name}
212
+ {scorer.scorer}
153
213
  </div>
154
214
  {showReducer ? (
155
215
  <div
@@ -164,13 +224,12 @@ const MultiScorerMetric: FC<MultiScorerMetricProps> = ({
164
224
  </div>
165
225
  ) : undefined}
166
226
  <div className={clsx(valueFontClz, styles.multiScorerValue)}>
167
- {Object.keys(scorer.metrics).map((key) => {
168
- const metric = scorer.metrics[key];
227
+ {scorer.metrics.map((metric) => {
169
228
  return (
170
- <div className={styles.multiScoreMetricGrid} key={key}>
229
+ <div className={styles.multiScoreMetricGrid} key={metric.name}>
171
230
  <div>{metricDisplayName(metric)}</div>
172
231
  <div className={styles.multiScorerValueContent}>
173
- {formatPrettyDecimal(metric.value)}
232
+ {metric.value ? formatPrettyDecimal(metric.value) : undefined}
174
233
  </div>
175
234
  </div>
176
235
  );
@@ -0,0 +1,32 @@
1
+ .statusContainer {
2
+ display: inline-block;
3
+ margin-top: 0.3em;
4
+ }
5
+
6
+ .status {
7
+ display: grid;
8
+ grid-template-columns: auto auto;
9
+ }
10
+
11
+ .statusText {
12
+ margin-top: 0.2em;
13
+ }
14
+
15
+ .metricsRows {
16
+ margin-top: 0.3em;
17
+ margin-left: 1.25em;
18
+ display: grid;
19
+ grid-template-columns: auto auto;
20
+ grid-template-rows: auto;
21
+ column-gap: 0.5em;
22
+ }
23
+
24
+ .icon {
25
+ font-size: var(--inspect-font-size-large);
26
+ margin-right: 0.3em;
27
+ margin-top: -0.1em;
28
+ }
29
+
30
+ .value {
31
+ font-weight: 600;
32
+ }
@@ -0,0 +1,32 @@
1
+ import clsx from "clsx";
2
+ import { RunningMetric } from "../../api/types";
3
+ import { ApplicationIcons } from "../../appearance/icons";
4
+
5
+ import { FC } from "react";
6
+ import styles from "./RunningStatusPanel.module.css";
7
+
8
+ export interface RunningPanelProps {
9
+ sampleCount: number;
10
+ displayMetrics?: RunningMetric[];
11
+ }
12
+
13
+ export const RunningStatusPanel: FC<RunningPanelProps> = ({ sampleCount }) => {
14
+ return (
15
+ <div>
16
+ <div className={clsx(styles.statusContainer)}>
17
+ <div className={clsx(styles.status)}>
18
+ <i className={clsx(ApplicationIcons.running, styles.icon)} />
19
+ <div
20
+ className={clsx(
21
+ styles.statusText,
22
+ "text-style-label",
23
+ "text-size-smaller",
24
+ )}
25
+ >
26
+ Running ({sampleCount} samples)
27
+ </div>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ );
32
+ };