Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 86 additions & 74 deletions src/sections/TokenViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ function encodeWhitespace(str: string) {
return result;
}

const firstOccurrences: Record<number, number> = {};

export function TokenViewer(props: {
isFetching: boolean;
model: string | undefined;
Expand All @@ -63,6 +65,16 @@ export function TokenViewer(props: {

const [showWhitespace, setShowWhitespace] = useState(false);

// Keep track of the first occurrence of each token
props.data?.forEach(({ tokens }) => {
tokens.forEach(({ id, idx }) => {
if (firstOccurrences[id] == null) {
console.log("firstOccurrences", id, idx);
firstOccurrences[id] = idx;
}
});
});

return (
<>
<div className="flex gap-4">
Expand All @@ -75,83 +87,83 @@ export function TokenViewer(props: {
<div className="flex-grow rounded-md border bg-slate-50 p-4 shadow-sm">
<p className="text-sm ">Price per prompt</p>
<p className="text-lg">
${pricing?.multipliedBy(tokenCount)?.toFixed()}
</p>
</div>
)}
${pricing?.multipliedBy(tokenCount)?. toFixed()}
</p>
</div>
)}
</div>

<pre className="min-h-[256px] max-w-[100vw] overflow-auto whitespace-pre-wrap break-all rounded-md border bg-slate-50 p-4 shadow-sm">
{props.data?.map(({ text }, idx) => (
<span
key={idx}
onMouseEnter={() => setIndexHover(idx)}
onMouseLeave={() => setIndexHover(null)}
className={cn(
"transition-all",
(indexHover == null || indexHover === idx) &&
COLORS[idx % COLORS.length],
props.isFetching && "opacity-50"
)}
>
{showWhitespace || indexHover === idx
? encodeWhitespace(text)
: text}
</span>
))}
</pre>
<pre className="min-h-[256px] max-w-[100vw] overflow-auto whitespace-pre-wrap break-word rounded-md border bg-slate-50 p-4 shadow-sm">
{props.data?.map(({ text, tokens }, idx) => (
<span
key={idx}
onMouseEnter={() => setIndexHover(idx)}
onMouseLeave={() => setIndexHover(null)}
className={cn(
"transition-all",
(indexHover == null || indexHover === idx) &&
COLORS[firstOccurrences[tokens[0]!.id]! % COLORS.length],
props.isFetching && "opacity-50"
)}
>
{showWhitespace || indexHover === idx
? encodeWhitespace(text)
: text}
</span>
))}
</pre>

<pre
className={
"min-h-[256px] max-w-[100vw] overflow-auto whitespace-pre-wrap break-all rounded-md border bg-slate-50 p-4 shadow-sm"
}
<pre
className={
"min-h-[256px] max-w-[100vw] overflow-auto whitespace-pre-wrap break-word rounded-md border bg-slate-50 p-4 shadow-sm"
}
>
{props.data && tokenCount > 0 && (
<span
className={cn(
"transition-opacity",
props.isFetching && "opacity-50"
)}
>
{props.data && tokenCount > 0 && (
<span
className={cn(
"transition-opacity",
props.isFetching && "opacity-50"
)}
>
[
{props.data.map((segment, segmentIdx) => (
<Fragment key={segmentIdx}>
{segment.tokens.map((token) => (
<Fragment key={token.idx}>
<span
onMouseEnter={() => setIndexHover(segmentIdx)}
onMouseLeave={() => setIndexHover(null)}
className={cn(
"transition-colors",
indexHover === segmentIdx &&
COLORS[segmentIdx % COLORS.length]
)}
>
{token.id}
</span>
<span className="last-of-type:hidden">{", "}</span>
</Fragment>
))}
[
{props.data.map(({ tokens }, segmentIdx) => (
<Fragment key={segmentIdx}>
{tokens.map(({ id, idx }) => (
<Fragment key={idx}>
<span
onMouseEnter={() => setIndexHover(segmentIdx)}
onMouseLeave={() => setIndexHover(null)}
className={cn(
"transition-colors",
indexHover === segmentIdx &&
COLORS[firstOccurrences[id]! % COLORS.length]
)}
>
{id}
</span>
<span className="last-of-type:hidden">{", "}</span>
</Fragment>
))}
]
</span>
)}
</pre>

<div className="flex items-center space-x-2">
<Checkbox
id="terms"
checked={showWhitespace}
onClick={() => setShowWhitespace((v) => !v)}
/>
<label
htmlFor="terms"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Show whitespace
</label>
</div>
</>
);
}
</Fragment>
))}
]
</span>
)}
</pre>

<div className="flex items-center space-x-2">
<Checkbox
id="terms"
checked={showWhitespace}
onClick={() => setShowWhitespace((v) => !v)}
/>
<label
htmlFor="terms"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Show whitespace
</label>
</div>
</>
);
}