mirror of
https://github.com/sortedcord/omnia.git
synced 2026-07-22 03:52:48 +05:30
feat(gui): Model Statistics now show Validators in the pipeline
This commit is contained in:
@@ -18,7 +18,7 @@ interface PromptModalProps {
|
||||
}
|
||||
|
||||
export function PromptModal({ entry, onClose }: PromptModalProps) {
|
||||
const [activeTab, setActiveTab] = useState<"actor" | "decoder">("actor");
|
||||
const [activeTab, setActiveTab] = useState<string>("actor");
|
||||
|
||||
useEffect(() => {
|
||||
if (!entry.rawPrompt && entry.decoderPrompt) {
|
||||
@@ -53,6 +53,17 @@ export function PromptModal({ entry, onClose }: PromptModalProps) {
|
||||
const actorComponents = getComponents(entry.rawPrompt, "world");
|
||||
const decoderComponents = getComponents(entry.decoderPrompt, "input");
|
||||
|
||||
const isValidatorTab = activeTab.startsWith("validator-");
|
||||
const validatorIndex = isValidatorTab
|
||||
? parseInt(activeTab.substring("validator-".length), 10)
|
||||
: -1;
|
||||
const validatorCall = isValidatorTab
|
||||
? entry.validatorCalls?.find((c) => c.intentIndex === validatorIndex)
|
||||
: null;
|
||||
const validatorComponents = validatorCall
|
||||
? getComponents(validatorCall.prompt, "world")
|
||||
: [];
|
||||
|
||||
return (
|
||||
<Dialog open onOpenChange={(open) => !open && onClose()}>
|
||||
<DialogContent className="max-w-[750px] sm:max-w-[750px] h-[90vh] overflow-hidden flex flex-col p-0 gap-0">
|
||||
@@ -67,6 +78,12 @@ export function PromptModal({ entry, onClose }: PromptModalProps) {
|
||||
onTabChange={setActiveTab}
|
||||
hasActor={!!entry.rawPrompt}
|
||||
hasDecoder={!!entry.decoderPrompt}
|
||||
validatorCalls={
|
||||
entry.validatorCalls?.map((c) => ({
|
||||
intentIndex: c.intentIndex,
|
||||
intentContent: c.intentContent,
|
||||
})) || []
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="overflow-y-auto flex-1 p-5">
|
||||
@@ -99,10 +116,42 @@ export function PromptModal({ entry, onClose }: PromptModalProps) {
|
||||
modelName={entry.decoderUsage?.modelName}
|
||||
providerInstanceName={entry.decoderUsage?.providerInstanceName}
|
||||
outputLabel="LLM Output (Decoded Intent Sequence)"
|
||||
outputText={JSON.stringify(entry.intents, null, 2)}
|
||||
outputText={JSON.stringify(
|
||||
entry.decodedIntents || entry.intents,
|
||||
null,
|
||||
2,
|
||||
)}
|
||||
outputTokens={entry.decoderUsage?.outputTokens}
|
||||
/>
|
||||
)}
|
||||
|
||||
{validatorCall && validatorCall.prompt && (
|
||||
<PromptAnalyzer
|
||||
components={validatorComponents}
|
||||
inputTokens={validatorCall.usage?.inputTokens || 0}
|
||||
maxContext={
|
||||
validatorCall.usage?.maxContext !== undefined
|
||||
? validatorCall.usage.maxContext
|
||||
: 32768
|
||||
}
|
||||
modelName={validatorCall.usage?.modelName}
|
||||
providerInstanceName={validatorCall.usage?.providerInstanceName}
|
||||
outputLabel={`LLM Output (Validation for: "${validatorCall.intentContent}")`}
|
||||
outputText={JSON.stringify(validatorCall.response, null, 2)}
|
||||
outputTokens={validatorCall.usage?.outputTokens}
|
||||
/>
|
||||
)}
|
||||
|
||||
{validatorCall && !validatorCall.prompt && (
|
||||
<div className="flex flex-col items-center justify-center border border-dashed rounded-lg bg-muted/20 text-muted-foreground p-8 my-6">
|
||||
<span className="text-sm font-semibold mb-2 text-foreground">
|
||||
Bypassed LLM Validation
|
||||
</span>
|
||||
<p className="text-xs text-center text-muted-foreground max-w-md">
|
||||
{validatorCall.response.reason}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
"use client";
|
||||
|
||||
interface PromptSwitcherProps {
|
||||
activeTab: "actor" | "decoder";
|
||||
onTabChange: (tab: "actor" | "decoder") => void;
|
||||
activeTab: string;
|
||||
onTabChange: (tab: any) => void;
|
||||
hasActor: boolean;
|
||||
hasDecoder: boolean;
|
||||
validatorCalls?: { intentIndex: number; intentContent: string }[];
|
||||
}
|
||||
|
||||
export function PromptSwitcher({
|
||||
@@ -12,32 +13,67 @@ export function PromptSwitcher({
|
||||
onTabChange,
|
||||
hasActor,
|
||||
hasDecoder,
|
||||
validatorCalls = [],
|
||||
}: PromptSwitcherProps) {
|
||||
return (
|
||||
<div className="flex items-center justify-center gap-4 border-b bg-muted/50 px-5 py-4">
|
||||
<button
|
||||
onClick={() => onTabChange("actor")}
|
||||
disabled={!hasActor}
|
||||
className={`flex h-14 w-40 items-center justify-center border-2 text-sm font-medium transition-all ${
|
||||
activeTab === "actor"
|
||||
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
||||
: "border-border/30 bg-card text-foreground hover:border-primary/50"
|
||||
} disabled:cursor-not-allowed disabled:opacity-40`}
|
||||
>
|
||||
Actor Prompt
|
||||
</button>
|
||||
<span className="text-xl text-muted-foreground">→</span>
|
||||
<button
|
||||
onClick={() => onTabChange("decoder")}
|
||||
disabled={!hasDecoder}
|
||||
className={`flex h-14 w-44 items-center justify-center border-2 text-sm font-medium transition-all ${
|
||||
activeTab === "decoder"
|
||||
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
||||
: "border-border/30 bg-card text-foreground hover:border-primary/50"
|
||||
} disabled:cursor-not-allowed disabled:opacity-40`}
|
||||
>
|
||||
Intent Decoder
|
||||
</button>
|
||||
<div className="flex items-center justify-center gap-4 border-b bg-muted/40 px-6 py-5 overflow-x-auto">
|
||||
{/* Primary Pipeline (Linear flow to the left) */}
|
||||
<div className="flex items-center gap-3 shrink-0">
|
||||
<button
|
||||
onClick={() => onTabChange("actor")}
|
||||
disabled={!hasActor}
|
||||
className={`flex h-12 w-36 items-center justify-center border-2 text-xs font-semibold uppercase tracking-wider transition-all ${
|
||||
activeTab === "actor"
|
||||
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
||||
: "border-border bg-card text-foreground hover:border-primary/50"
|
||||
} disabled:cursor-not-allowed disabled:opacity-40 rounded`}
|
||||
>
|
||||
Actor Prompt
|
||||
</button>
|
||||
|
||||
<span className="text-lg text-muted-foreground">→</span>
|
||||
|
||||
<button
|
||||
onClick={() => onTabChange("decoder")}
|
||||
disabled={!hasDecoder}
|
||||
className={`flex h-12 w-36 items-center justify-center border-2 text-xs font-semibold uppercase tracking-wider transition-all ${
|
||||
activeTab === "decoder"
|
||||
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
||||
: "border-border bg-card text-foreground hover:border-primary/50"
|
||||
} disabled:cursor-not-allowed disabled:opacity-40 rounded`}
|
||||
>
|
||||
Intent Decoder
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Branching Validator Column to the right of Intent Decoder */}
|
||||
{validatorCalls.length > 0 && (
|
||||
<div className="flex items-center gap-3 shrink-0">
|
||||
<span className="text-lg text-muted-foreground">→</span>
|
||||
|
||||
<div className="flex flex-col gap-2 pl-3">
|
||||
<div className="flex flex-col gap-2">
|
||||
{validatorCalls.map((call) => {
|
||||
const tabKey = `validator-${call.intentIndex}`;
|
||||
return (
|
||||
<button
|
||||
key={tabKey}
|
||||
onClick={() => onTabChange(tabKey)}
|
||||
className={`flex h-12 w-36 items-center justify-center border-2 text-xs font-semibold uppercase tracking-wider transition-all rounded ${
|
||||
activeTab === tabKey
|
||||
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
||||
: "border-border bg-card text-foreground hover:border-primary/50"
|
||||
}`}
|
||||
title={call.intentContent}
|
||||
>
|
||||
LLM Validator (Intent #{call.intentIndex})
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,24 @@ export interface PromptBreakdown {
|
||||
components?: PromptComponent[];
|
||||
}
|
||||
|
||||
export interface ValidatorCall {
|
||||
intentIndex: number;
|
||||
intentContent: string;
|
||||
prompt?: PromptBreakdown;
|
||||
response: {
|
||||
isValid: boolean;
|
||||
reason: string;
|
||||
};
|
||||
usage?: {
|
||||
inputTokens: number;
|
||||
outputTokens: number;
|
||||
totalTokens: number;
|
||||
modelName?: string;
|
||||
providerInstanceName?: string;
|
||||
maxContext?: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface LogEntry {
|
||||
turn: number;
|
||||
entityId: string;
|
||||
@@ -29,6 +47,8 @@ export interface LogEntry {
|
||||
timestamp: string;
|
||||
isHandoff?: boolean;
|
||||
handoffResult?: any;
|
||||
decodedIntents?: IntentInfo[];
|
||||
validatorCalls?: ValidatorCall[];
|
||||
rawPrompt?: PromptBreakdown;
|
||||
usage?: {
|
||||
inputTokens: number;
|
||||
|
||||
Reference in New Issue
Block a user