usage frontend
This commit is contained in:
parent
8c26e03114
commit
38072b27f5
5 changed files with 65 additions and 1 deletions
|
|
@ -3,9 +3,10 @@ import { motion } from "motion/react";
|
|||
import DogIcon from "@/components/icons/dog-icon";
|
||||
import { MarkdownRenderer } from "@/components/markdown-renderer";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { FunctionCall } from "../_types/types";
|
||||
import type { FunctionCall, TokenUsage as TokenUsageType } from "../_types/types";
|
||||
import { FunctionCalls } from "./function-calls";
|
||||
import { Message } from "./message";
|
||||
import { TokenUsage } from "./token-usage";
|
||||
|
||||
interface AssistantMessageProps {
|
||||
content: string;
|
||||
|
|
@ -21,6 +22,7 @@ interface AssistantMessageProps {
|
|||
animate?: boolean;
|
||||
delay?: number;
|
||||
isInitialGreeting?: boolean;
|
||||
usage?: TokenUsageType;
|
||||
}
|
||||
|
||||
export function AssistantMessage({
|
||||
|
|
@ -37,6 +39,7 @@ export function AssistantMessage({
|
|||
animate = true,
|
||||
delay = 0.2,
|
||||
isInitialGreeting = false,
|
||||
usage,
|
||||
}: AssistantMessageProps) {
|
||||
return (
|
||||
<motion.div
|
||||
|
|
@ -135,6 +138,7 @@ export function AssistantMessage({
|
|||
: content
|
||||
}
|
||||
/>
|
||||
{usage && !isStreaming && <TokenUsage usage={usage} />}
|
||||
</motion.div>
|
||||
</div>
|
||||
</Message>
|
||||
|
|
|
|||
27
frontend/app/chat/_components/token-usage.tsx
Normal file
27
frontend/app/chat/_components/token-usage.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { Zap } from "lucide-react";
|
||||
import type { TokenUsage as TokenUsageType } from "../_types/types";
|
||||
|
||||
interface TokenUsageProps {
|
||||
usage: TokenUsageType;
|
||||
}
|
||||
|
||||
export function TokenUsage({ usage }: TokenUsageProps) {
|
||||
// Guard against partial/malformed usage data
|
||||
if (typeof usage.input_tokens !== "number" || typeof usage.output_tokens !== "number") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 mt-2 text-xs text-muted-foreground">
|
||||
<Zap className="h-3 w-3" />
|
||||
<span>
|
||||
{usage.input_tokens.toLocaleString()} in / {usage.output_tokens.toLocaleString()} out
|
||||
{usage.input_tokens_details?.cached_tokens ? (
|
||||
<span className="text-green-500 ml-1">
|
||||
({usage.input_tokens_details.cached_tokens.toLocaleString()} cached)
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,3 +1,15 @@
|
|||
export interface TokenUsage {
|
||||
input_tokens: number;
|
||||
output_tokens: number;
|
||||
total_tokens: number;
|
||||
input_tokens_details?: {
|
||||
cached_tokens?: number;
|
||||
};
|
||||
output_tokens_details?: {
|
||||
reasoning_tokens?: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
role: "user" | "assistant";
|
||||
content: string;
|
||||
|
|
@ -5,6 +17,7 @@ export interface Message {
|
|||
functionCalls?: FunctionCall[];
|
||||
isStreaming?: boolean;
|
||||
source?: "langflow" | "chat";
|
||||
usage?: TokenUsage;
|
||||
}
|
||||
|
||||
export interface FunctionCall {
|
||||
|
|
|
|||
|
|
@ -501,6 +501,17 @@ function ChatPage() {
|
|||
} else {
|
||||
console.log("No function calls found in message");
|
||||
}
|
||||
|
||||
// Extract usage data from response_data
|
||||
if (msg.response_data && typeof msg.response_data === "object") {
|
||||
const responseData =
|
||||
typeof msg.response_data === "string"
|
||||
? JSON.parse(msg.response_data)
|
||||
: msg.response_data;
|
||||
if (responseData.usage) {
|
||||
message.usage = responseData.usage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
|
|
@ -849,6 +860,7 @@ function ChatPage() {
|
|||
role: "assistant",
|
||||
content: result.response,
|
||||
timestamp: new Date(),
|
||||
usage: result.usage,
|
||||
};
|
||||
setMessages((prev) => [...prev, assistantMessage]);
|
||||
if (result.response_id) {
|
||||
|
|
@ -1164,6 +1176,7 @@ function ChatPage() {
|
|||
messages.length === 1 &&
|
||||
message.content === "How can I assist?"
|
||||
}
|
||||
usage={message.usage}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import type {
|
|||
FunctionCall,
|
||||
Message,
|
||||
SelectedFilters,
|
||||
TokenUsage,
|
||||
} from "@/app/chat/_types/types";
|
||||
import { useChat } from "@/contexts/chat-context";
|
||||
|
||||
|
|
@ -130,6 +131,7 @@ export function useChatStreaming({
|
|||
let currentContent = "";
|
||||
const currentFunctionCalls: FunctionCall[] = [];
|
||||
let newResponseId: string | null = null;
|
||||
let usageData: TokenUsage | undefined;
|
||||
|
||||
// Initialize streaming message
|
||||
if (!controller.signal.aborted && thisStreamId === streamIdRef.current) {
|
||||
|
|
@ -448,6 +450,10 @@ export function useChatStreaming({
|
|||
else if (chunk.type === "response.output_text.delta") {
|
||||
currentContent += chunk.delta || "";
|
||||
}
|
||||
// Handle response.completed event - capture usage
|
||||
else if (chunk.type === "response.completed" && chunk.response?.usage) {
|
||||
usageData = chunk.response.usage;
|
||||
}
|
||||
// Handle OpenRAG backend format
|
||||
else if (chunk.output_text) {
|
||||
currentContent += chunk.output_text;
|
||||
|
|
@ -567,6 +573,7 @@ export function useChatStreaming({
|
|||
currentFunctionCalls.length > 0 ? currentFunctionCalls : undefined,
|
||||
timestamp: new Date(),
|
||||
isStreaming: false,
|
||||
usage: usageData,
|
||||
};
|
||||
|
||||
if (!controller.signal.aborted && thisStreamId === streamIdRef.current) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue