feat: Add generation info to messages
This commit introduces a new feature that displays generation information for each message in the chat. The generation info is displayed in a popover and includes details about the model used, the prompt, and other relevant information. This helps users understand how their messages were generated and troubleshoot any issues that may arise. The generation info is retrieved from the LLM response and is stored in the database alongside other message details. This commit also includes translations for the generation info label in all supported languages.
This commit is contained in:
65
src/components/Common/Playground/GenerationInfo.tsx
Normal file
65
src/components/Common/Playground/GenerationInfo.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
type GenerationMetrics = {
|
||||
total_duration?: number
|
||||
load_duration?: number
|
||||
prompt_eval_count?: number
|
||||
prompt_eval_duration?: number
|
||||
eval_count?: number
|
||||
eval_duration?: number
|
||||
context?: string
|
||||
response?: string
|
||||
}
|
||||
|
||||
type Props = {
|
||||
generationInfo: GenerationMetrics
|
||||
}
|
||||
|
||||
export const GenerationInfo = ({ generationInfo }: Props) => {
|
||||
if (!generationInfo) return null
|
||||
|
||||
const calculateTokensPerSecond = (
|
||||
evalCount?: number,
|
||||
evalDuration?: number
|
||||
) => {
|
||||
if (!evalCount || !evalDuration) return 0
|
||||
return (evalCount / evalDuration) * 1e9
|
||||
}
|
||||
|
||||
const formatDuration = (nanoseconds?: number) => {
|
||||
if (!nanoseconds) return "0ms"
|
||||
const ms = nanoseconds / 1e6
|
||||
if (ms < 1) return `${ms.toFixed(3)}ms`
|
||||
if (ms < 1000) return `${Math.round(ms)}ms`
|
||||
return `${(ms / 1000).toFixed(2)}s`
|
||||
}
|
||||
|
||||
const metricsToDisplay = {
|
||||
...generationInfo,
|
||||
...(generationInfo?.eval_count && generationInfo?.eval_duration
|
||||
? {
|
||||
tokens_per_second: calculateTokensPerSecond(
|
||||
generationInfo.eval_count,
|
||||
generationInfo.eval_duration
|
||||
).toFixed(2)
|
||||
}
|
||||
: {})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="p-2 w-full">
|
||||
<div className="flex flex-col gap-2">
|
||||
{Object.entries(metricsToDisplay)
|
||||
.filter(([key]) => key !== "model")
|
||||
.map(([key, value]) => (
|
||||
<div key={key} className="flex flex-wrap justify-between">
|
||||
<div className="font-medium text-xs">{key}</div>
|
||||
<div className="font-medium text-xs break-all">
|
||||
{key.includes("duration")
|
||||
? formatDuration(value as number)
|
||||
: String(value)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import Markdown from "../../Common/Markdown"
|
||||
import React from "react"
|
||||
import { Tag, Image, Tooltip, Collapse } from "antd"
|
||||
import { Tag, Image, Tooltip, Collapse, Popover } from "antd"
|
||||
import { WebSearch } from "./WebSearch"
|
||||
import {
|
||||
CheckIcon,
|
||||
ClipboardIcon,
|
||||
InfoIcon,
|
||||
Pen,
|
||||
PlayIcon,
|
||||
RotateCcw,
|
||||
@@ -16,6 +17,7 @@ import { MessageSource } from "./MessageSource"
|
||||
import { useTTS } from "@/hooks/useTTS"
|
||||
import { tagColors } from "@/utils/color"
|
||||
import { removeModelSuffix } from "@/db/models"
|
||||
import { GenerationInfo } from "./GenerationInfo"
|
||||
|
||||
type Props = {
|
||||
message: string
|
||||
@@ -37,6 +39,7 @@ type Props = {
|
||||
hideEditAndRegenerate?: boolean
|
||||
onSourceClick?: (source: any) => void
|
||||
isTTSEnabled?: boolean
|
||||
generationInfo?: any
|
||||
}
|
||||
|
||||
export const PlaygroundMessage = (props: Props) => {
|
||||
@@ -206,6 +209,18 @@ export const PlaygroundMessage = (props: Props) => {
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{props.generationInfo && (
|
||||
<Popover
|
||||
content={
|
||||
<GenerationInfo generationInfo={props.generationInfo} />
|
||||
}
|
||||
title={t("generationInfo")}>
|
||||
<button className="flex items-center justify-center w-6 h-6 rounded-full bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500">
|
||||
<InfoIcon className="w-3 h-3 text-gray-400 group-hover:text-gray-500" />
|
||||
</button>
|
||||
</Popover>
|
||||
)}
|
||||
|
||||
{!props.hideEditAndRegenerate &&
|
||||
props.currentMessageIndex === props.totalMessages - 1 && (
|
||||
<Tooltip title={t("regenerate")}>
|
||||
|
||||
@@ -54,6 +54,7 @@ export const PlaygroundChat = () => {
|
||||
setIsSourceOpen(true)
|
||||
}}
|
||||
isTTSEnabled={ttsEnabled}
|
||||
generationInfo={message?.generationInfo}
|
||||
/>
|
||||
))}
|
||||
{messages.length > 0 && (
|
||||
|
||||
@@ -47,6 +47,7 @@ export const SidePanelBody = () => {
|
||||
setIsSourceOpen(true)
|
||||
}}
|
||||
isTTSEnabled={ttsEnabled}
|
||||
generationInfo={message?.generationInfo}
|
||||
/>
|
||||
))}
|
||||
<div className="w-full h-48 flex-shrink-0"></div>
|
||||
|
||||
Reference in New Issue
Block a user