Skip to content

Commit 6ffcaa3

Browse files
committed
feat: add Usage tab to detail drawer for model blocks
Signed-off-by: Nick Mitchell <[email protected]>
1 parent ea8004d commit 6ffcaa3

File tree

6 files changed

+107
-14
lines changed

6 files changed

+107
-14
lines changed

pdl-live-react/src/helpers.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,19 @@ export function hasModelUsage(
187187
)
188188
}
189189

190+
export function completionRate(
191+
block: ModelBlockWithUsage & PdlBlockWithTiming,
192+
) {
193+
return (
194+
block.pdl__usage.completion_tokens /
195+
((block.pdl__timing.end_nanos - block.pdl__timing.start_nanos) / 1000000000)
196+
)
197+
}
198+
199+
export function ptcRatio(block: ModelBlockWithUsage) {
200+
return block.pdl__usage.prompt_tokens / block.pdl__usage.completion_tokens
201+
}
202+
190203
/** Does the given block have context/background information? */
191204
export function hasContextInformation(
192205
block: unknown | PdlBlock,

pdl-live-react/src/view/detail/DrawerContentBody.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { Tab, TabTitleText } from "@patternfly/react-core"
33

44
const BlockNotFound = lazy(() => import("./BlockNotFound"))
55
const DefContent = lazy(() => import("./DefContent"))
6+
const UsageTabContent = lazy(() => import("./UsageTabContent"))
67
const SourceTabContent = lazy(() => import("./SourceTabContent"))
78
const ContextTabContent = lazy(() => import("./ContextTabContent"))
89
const SummaryTabContent = lazy(() => import("./SummaryTabContent"))
910
const RawTraceTabContent = lazy(() => import("./RawTraceTabContent"))
1011

1112
import {
1213
hasContextInformation,
14+
hasModelUsage,
1315
hasResult,
1416
type NonScalarPdlBlock as Model,
1517
} from "../../helpers"
@@ -54,6 +56,18 @@ function blockBody(block: Model) {
5456
)
5557
}
5658

59+
if (hasModelUsage(block)) {
60+
tabs.splice(
61+
1,
62+
0,
63+
<Tab key={4} eventKey={4} title={<TabTitleText>Usage</TabTitleText>}>
64+
<Suspense>
65+
<UsageTabContent block={block} />
66+
</Suspense>
67+
</Tab>,
68+
)
69+
}
70+
5771
return tabs
5872
}
5973

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import {
2+
DescriptionList,
3+
DescriptionListGroup,
4+
DescriptionListDescription,
5+
DescriptionListTerm,
6+
} from "@patternfly/react-core"
7+
8+
import {
9+
completionRate,
10+
ptcRatio,
11+
type ModelBlockWithUsage,
12+
type PdlBlockWithTiming,
13+
} from "../../helpers"
14+
15+
export default function UsageTabContent({
16+
block,
17+
}: {
18+
block: ModelBlockWithUsage & PdlBlockWithTiming
19+
}) {
20+
return <DescriptionList>{descriptionItems(block)}</DescriptionList>
21+
}
22+
23+
function descriptionItems(block: ModelBlockWithUsage & PdlBlockWithTiming) {
24+
return (
25+
<>
26+
<DescriptionListGroup>
27+
<DescriptionListTerm>Completion Rate</DescriptionListTerm>
28+
<DescriptionListDescription>
29+
{completionRate(block).toFixed(0)} tokens/sec
30+
</DescriptionListDescription>
31+
</DescriptionListGroup>
32+
33+
<DescriptionListGroup>
34+
<DescriptionListTerm>Prompt/Completion Ratio</DescriptionListTerm>
35+
<DescriptionListDescription>
36+
{(ptcRatio(block) * 100).toFixed(2)}%
37+
</DescriptionListDescription>
38+
</DescriptionListGroup>
39+
40+
<DescriptionListGroup>
41+
<DescriptionListTerm>Prompt Tokens Consumed</DescriptionListTerm>
42+
<DescriptionListDescription>
43+
{block.pdl__usage.prompt_tokens}
44+
</DescriptionListDescription>
45+
</DescriptionListGroup>
46+
47+
<DescriptionListGroup>
48+
<DescriptionListTerm>Completion Tokens Consumed</DescriptionListTerm>
49+
<DescriptionListDescription>
50+
{block.pdl__usage.completion_tokens}
51+
</DescriptionListDescription>
52+
</DescriptionListGroup>
53+
</>
54+
)
55+
}

pdl-live-react/src/view/masonry/MasonryTile.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ export default function MasonryTile({
5353
footer1Value,
5454
footer2Key,
5555
footer2Value,
56+
footer3Key,
57+
footer3Value,
5658
stability,
5759
actions: tileActions = [],
5860
block,
@@ -119,6 +121,7 @@ export default function MasonryTile({
119121
const hasFooter =
120122
(footer1Key && footer1Value) ||
121123
(footer2Key && footer2Value) ||
124+
(footer3Key && footer3Value) ||
122125
(stability?.length ?? 0) > 0
123126
const footer = hasFooter && (
124127
<DescriptionList className="pdl-masonry-tile-footer-dl">
@@ -138,6 +141,14 @@ export default function MasonryTile({
138141
</DescriptionListDescription>
139142
</DescriptionListGroup>
140143
)}
144+
{footer3Key && (
145+
<DescriptionListGroup>
146+
<DescriptionListTerm>{footer3Key}</DescriptionListTerm>
147+
<DescriptionListDescription>
148+
{footer3Value}
149+
</DescriptionListDescription>
150+
</DescriptionListGroup>
151+
)}
141152
{stability &&
142153
stability.map((m) => (
143154
<DescriptionListGroup

pdl-live-react/src/view/masonry/Tile.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ type Tile = {
1515
footer1Value?: string | number | boolean
1616
footer2Key?: string
1717
footer2Value?: string | number | boolean
18+
footer3Key?: string
19+
footer3Value?: string | number | boolean
1820
stability?: import("./stability").StabilityMetric[]
1921

2022
block?: import("../../helpers").NonScalarPdlBlock

pdl-live-react/src/view/masonry/model.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111
hasTimingInformation,
1212
capitalizeAndUnSnakeCase,
1313
extractStructuredModelResponse,
14+
completionRate,
15+
ptcRatio,
1416
type NonScalarPdlBlock,
1517
} from "../../helpers"
1618

@@ -89,20 +91,16 @@ export default function computeModel(block: import("../../pdl_ast").PdlBlock) {
8991
: undefined,
9092
footer1Value: meta?.[0]?.[1] ? String(meta[0][1]) : undefined,
9193

92-
footer2Key:
93-
hasModelUsage(block) && block.pdl__usage
94-
? "Tokens/sec"
95-
: undefined,
96-
footer2Value:
97-
hasModelUsage(block) && block.pdl__usage
98-
? (
99-
(block.pdl__usage.completion_tokens +
100-
block.pdl__usage.prompt_tokens) /
101-
((block.pdl__timing.end_nanos -
102-
block.pdl__timing.start_nanos) /
103-
1000000000)
104-
).toFixed(0)
105-
: undefined,
94+
footer2Key: hasModelUsage(block) ? "Completion Rate" : undefined,
95+
footer2Value: hasModelUsage(block)
96+
? completionRate(block).toFixed(0) + " tokens/sec"
97+
: undefined,
98+
footer3Key: hasModelUsage(block)
99+
? "Prompt/Completion Ratio"
100+
: undefined,
101+
footer3Value: hasModelUsage(block)
102+
? (100 * ptcRatio(block)).toFixed(2) + "%"
103+
: undefined,
106104

107105
stability,
108106
//footer2Key: stability.map((m) => `T=${m.temperature} Stability`),

0 commit comments

Comments
 (0)