Add prompt cache

This commit is contained in:
Saoud Rizwan
2024-08-15 03:34:54 -04:00
parent ace4596fe3
commit ec2bfa352a
10 changed files with 235 additions and 64 deletions

View File

@@ -105,6 +105,7 @@ const App: React.FC = () => {
vscodeThemeName={vscodeThemeName}
showAnnouncement={showAnnouncement}
selectedModelSupportsImages={selectedModelInfo.supportsImages}
selectedModelSupportsPromptCache={selectedModelInfo.supportsPromptCache}
hideAnnouncement={() => setShowAnnouncement(false)}
/>
</>

View File

@@ -217,25 +217,17 @@ const ModelInfoView = ({ modelInfo }: { modelInfo: ModelInfo }) => {
return (
<p style={{ fontSize: "12px", marginTop: "2px", color: "var(--vscode-descriptionForeground)" }}>
<span
style={{
fontWeight: 500,
color: modelInfo.supportsImages
? "var(--vscode-testing-iconPassed)"
: "var(--vscode-errorForeground)",
}}>
<i
className={`codicon codicon-${modelInfo.supportsImages ? "check" : "x"}`}
style={{
marginRight: 4,
marginBottom: modelInfo.supportsImages ? 1 : -1,
fontSize: modelInfo.supportsImages ? 11 : 13,
fontWeight: 700,
display: "inline-block",
verticalAlign: "bottom",
}}></i>
{modelInfo.supportsImages ? "Supports images" : "Does not support images"}
</span>
<ModelInfoSupportsItem
isSupported={modelInfo.supportsPromptCache}
supportsLabel="Supports prompt cache"
doesNotSupportLabel="Does not support prompt cache"
/>
<br />
<ModelInfoSupportsItem
isSupported={modelInfo.supportsImages}
supportsLabel="Supports images"
doesNotSupportLabel="Does not support images"
/>
<br />
<span style={{ fontWeight: 500 }}>Max output:</span> {modelInfo.maxTokens.toLocaleString()} tokens
<br />
@@ -247,6 +239,34 @@ const ModelInfoView = ({ modelInfo }: { modelInfo: ModelInfo }) => {
)
}
const ModelInfoSupportsItem = ({
isSupported,
supportsLabel,
doesNotSupportLabel,
}: {
isSupported: boolean
supportsLabel: string
doesNotSupportLabel: string
}) => (
<span
style={{
fontWeight: 500,
color: isSupported ? "var(--vscode-testing-iconPassed)" : "var(--vscode-errorForeground)",
}}>
<i
className={`codicon codicon-${isSupported ? "check" : "x"}`}
style={{
marginRight: 4,
marginBottom: isSupported ? 1 : -1,
fontSize: isSupported ? 11 : 13,
fontWeight: 700,
display: "inline-block",
verticalAlign: "bottom",
}}></i>
{isSupported ? supportsLabel : doesNotSupportLabel}
</span>
)
export function normalizeApiConfiguration(apiConfiguration?: ApiConfiguration) {
const provider = apiConfiguration?.apiProvider || "anthropic"
const modelId = apiConfiguration?.apiModelId

View File

@@ -22,6 +22,7 @@ interface ChatViewProps {
vscodeThemeName?: string
showAnnouncement: boolean
selectedModelSupportsImages: boolean
selectedModelSupportsPromptCache: boolean
hideAnnouncement: () => void
}
@@ -34,6 +35,7 @@ const ChatView = ({
vscodeThemeName,
showAnnouncement,
selectedModelSupportsImages,
selectedModelSupportsPromptCache,
hideAnnouncement,
}: ChatViewProps) => {
//const task = messages.length > 0 ? (messages[0].say === "task" ? messages[0] : undefined) : undefined
@@ -448,6 +450,9 @@ const ChatView = ({
task={task}
tokensIn={apiMetrics.totalTokensIn}
tokensOut={apiMetrics.totalTokensOut}
doesModelSupportPromptCache={selectedModelSupportsPromptCache}
cacheWrites={apiMetrics.totalCacheWrites}
cacheReads={apiMetrics.totalCacheReads}
totalCost={apiMetrics.totalCost}
onClose={handleTaskCloseButtonClick}
isHidden={isHidden}

View File

@@ -9,12 +9,25 @@ interface TaskHeaderProps {
task: ClaudeMessage
tokensIn: number
tokensOut: number
doesModelSupportPromptCache: boolean
cacheWrites?: number
cacheReads?: number
totalCost: number
onClose: () => void
isHidden: boolean
}
const TaskHeader: React.FC<TaskHeaderProps> = ({ task, tokensIn, tokensOut, totalCost, onClose, isHidden }) => {
const TaskHeader: React.FC<TaskHeaderProps> = ({
task,
tokensIn,
tokensOut,
doesModelSupportPromptCache,
cacheWrites,
cacheReads,
totalCost,
onClose,
isHidden,
}) => {
const [isExpanded, setIsExpanded] = useState(false)
const [showSeeMore, setShowSeeMore] = useState(false)
const textContainerRef = useRef<HTMLDivElement>(null)
@@ -194,6 +207,25 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({ task, tokensIn, tokensOut, tota
{tokensOut.toLocaleString()}
</span>
</div>
{(doesModelSupportPromptCache || cacheReads !== undefined || cacheWrites !== undefined) && (
<div style={{ display: "flex", alignItems: "center", gap: "4px", flexWrap: "wrap" }}>
<span style={{ fontWeight: "bold" }}>Prompt Cache:</span>
<span style={{ display: "flex", alignItems: "center", gap: "3px" }}>
<i
className="codicon codicon-database"
style={{ fontSize: "12px", fontWeight: "bold", marginBottom: "-1px" }}
/>
+{(cacheWrites || 0).toLocaleString()}
</span>
<span style={{ display: "flex", alignItems: "center", gap: "3px" }}>
<i
className="codicon codicon-arrow-right"
style={{ fontSize: "12px", fontWeight: "bold", marginBottom: 0 }}
/>
{(cacheReads || 0).toLocaleString()}
</span>
</div>
)}
<div
style={{
display: "flex",

View File

@@ -3,6 +3,8 @@ import { ClaudeMessage } from "../../../src/shared/ExtensionMessage"
interface ApiMetrics {
totalTokensIn: number
totalTokensOut: number
totalCacheWrites?: number
totalCacheReads?: number
totalCost: number
}
@@ -11,10 +13,10 @@ interface ApiMetrics {
*
* This function processes 'api_req_started' messages that have been combined with their
* corresponding 'api_req_finished' messages by the combineApiRequests function.
* It extracts and sums up the tokensIn, tokensOut, and cost from these messages.
* It extracts and sums up the tokensIn, tokensOut, cacheWrites, cacheReads, and cost from these messages.
*
* @param messages - An array of ClaudeMessage objects to process.
* @returns An ApiMetrics object containing totalTokensIn, totalTokensOut, and totalCost.
* @returns An ApiMetrics object containing totalTokensIn, totalTokensOut, totalCacheWrites, totalCacheReads, and totalCost.
*
* @example
* const messages = [
@@ -27,6 +29,8 @@ export function getApiMetrics(messages: ClaudeMessage[]): ApiMetrics {
const result: ApiMetrics = {
totalTokensIn: 0,
totalTokensOut: 0,
totalCacheWrites: undefined,
totalCacheReads: undefined,
totalCost: 0,
}
@@ -34,7 +38,7 @@ export function getApiMetrics(messages: ClaudeMessage[]): ApiMetrics {
if (message.type === "say" && message.say === "api_req_started" && message.text) {
try {
const parsedData = JSON.parse(message.text)
const { tokensIn, tokensOut, cost } = parsedData
const { tokensIn, tokensOut, cacheWrites, cacheReads, cost } = parsedData
if (typeof tokensIn === "number") {
result.totalTokensIn += tokensIn
@@ -42,6 +46,12 @@ export function getApiMetrics(messages: ClaudeMessage[]): ApiMetrics {
if (typeof tokensOut === "number") {
result.totalTokensOut += tokensOut
}
if (typeof cacheWrites === "number") {
result.totalCacheWrites = (result.totalCacheWrites ?? 0) + cacheWrites
}
if (typeof cacheReads === "number") {
result.totalCacheReads = (result.totalCacheReads ?? 0) + cacheReads
}
if (typeof cost === "number") {
result.totalCost += cost
}