Add usage totals

This commit is contained in:
Webifi 2023-05-28 11:57:07 -05:00
parent b1acf6806a
commit 5d7b51ba1d
5 changed files with 80 additions and 37 deletions

View File

@ -17,7 +17,10 @@
updateChatSettings,
resetChatSettings,
setChatSettingValue,
addChatFromJSON
addChatFromJSON,
updateRunningTotal
} from './Storage.svelte'
import { getChatSettingObjectByKey, getChatSettingList, getRequestSettingList } from './Settings.svelte'
import {
@ -59,6 +62,7 @@
import { v4 as uuidv4 } from 'uuid'
import { exportChatAsJSON, exportProfileAsJSON } from './Export.svelte'
import { clickOutside } from 'svelte-use-click-outside'
import { getPrice } from './Stats.svelte';
// This makes it possible to override the OpenAI API base URL in the .env file
const apiBase = import.meta.env.VITE_API_BASE || 'https://api.openai.com'
@ -86,9 +90,10 @@
$: chatSettings = chat.settings
$: globalStore = $globalStorage
// Make sure chat object is ready to go
updateChatSettings(chatId)
onMount(async () => {
// Make sure chat object is ready to go
updateChatSettings(chatId)
// Focus the input on mount
focusInput()
@ -147,7 +152,6 @@
const sendRequest = async (messages: Message[], doingSummary?:boolean, withSummary?:boolean): Promise<Response> => {
// Show updating bar
updating = true
updatingMessage = ''
let response: Response
@ -207,6 +211,7 @@
content: summaryPrompt
} as Message)
// Wait for the summary completion
updatingMessage = 'Building Summary...'
const summary = await sendRequest(summarizeReq, true)
if (summary.error) {
// Failed to some API issue. let the original caller handle it.
@ -241,6 +246,7 @@
saveChatStore()
// Re-run request with summarized prompts
// return { error: { message: "End for now" } } as Response
updatingMessage = 'Continuing...'
return await sendRequest(chat.messages, false, true)
}
} else if (!summaryPrompt) {
@ -313,10 +319,7 @@
updatingMessage = ''
if (!response.error) {
// tc.completions++
// tc.completionsTokens += response.usage.completion_tokens
// chat.totals.push(tc)
// console.log('got response:', response)
updateRunningTotal(chatId, response.usage, response.model)
}
return response
@ -777,7 +780,15 @@
<button title="Send" class="button is-info" type="submit"><Fa icon={faPaperPlane} /></button>
</p>
</form>
<div class="chat-focus-point" style="height.4em"></div>
<!-- a target to scroll to -->
<div class="chat-focus-point running-total-container">
{#each Object.entries(chat.usage||{}) as [model, usage]}
<p class="is-size-7 running-totals">
<em>{model}</em> total <span class="has-text-weight-bold">{usage.total_tokens}</span>
tokens ~= <span class="has-text-weight-bold">${getPrice(usage, model).toFixed(6)}</span>
</p>
{/each}
</div>
<svelte:window
on:keydown={(event) => {
@ -959,3 +970,15 @@
</div>
</form>
<!-- end -->
<style>
.running-total-container {
min-height:2em;
padding-bottom:.6em;
padding-left: 1.9em;
margin-bottom:-2.6em
}
.running-totals {
opacity: 0.5;
}
</style>

View File

@ -82,6 +82,7 @@
console.error("Can't find element with message ID", uuid)
}
}
</script>
{#key message.uuid}
@ -137,19 +138,22 @@
<div id={'edit-' + message.uuid} class="message-editor" bind:innerText={message.content} contenteditable on:input={update} on:blur={exit} />
</form>
{:else}
<a href={'#'} class="message-display" on:click|preventDefault={() => {}} on:dblclick|preventDefault={() => edit('edit-' + message.uuid)}>
<div
class="message-display"
on:dblclick|preventDefault={() => edit('edit-' + message.uuid)}
>
<SvelteMarkdown
source={message.content}
options={markedownOptions}
renderers={{ code: Code, html: Code }}
/>
</a>
</div>
{/if}
{#if message.role === 'system'}
<p class="is-size-7">System Prompt</p>
<p class="is-size-7 message-note">System Prompt</p>
{:else if message.usage}
<p class="is-size-7">
This message was generated on <em>{message.model || defaultModel}</em> using <span class="has-text-weight-bold">{message.usage.total_tokens}</span>
<p class="is-size-7 message-note">
<em>{message.model || defaultModel}</em> using <span class="has-text-weight-bold">{message.usage.total_tokens}</span>
tokens ~= <span class="has-text-weight-bold">${getPrice(message.usage, message.model || defaultModel).toFixed(6)}</span>
</p>
{/if}
@ -158,6 +162,11 @@
{/key}
<style>
.message-note {
padding-top: .6em;
margin-bottom: -0.6em;
opacity: 0.5;
}
.message-edit {
display: block;
}

View File

@ -29,21 +29,4 @@
return ((tokens.prompt_tokens * t[0]) + (tokens.completion_tokens * t[1]))
}
export const totalUse = (totals: Usage[]): Usage => {
const r = {
completion_tokens: 0,
prompt_tokens: 0,
total_tokens: 0,
total: 0
} as Usage
(totals || ([] as Usage[])).forEach((t) => {
r.total += getPrice(t, t.model as any)
r.completion_tokens += t.completion_tokens
r.prompt_tokens += t.prompt_tokens
r.total_tokens += t.prompt_tokens
})
return r
}
</script>

View File

@ -1,7 +1,7 @@
<script context="module" lang="ts">
import { persisted } from 'svelte-local-storage-store'
import { get } from 'svelte/store'
import type { Chat, ChatSettings, GlobalSettings, Message, ChatSetting, GlobalSetting } from './Types.svelte'
import type { Chat, ChatSettings, GlobalSettings, Message, ChatSetting, GlobalSetting, Usage, Model } from './Types.svelte'
import { getChatSettingObjectByKey, getGlobalSettingObjectByKey, getChatDefaults, getExcludeFromProfile } from './Settings.svelte'
import { v4 as uuidv4 } from 'uuid'
import { applyProfile, getProfile, isStaticProfile } from './Profiles.svelte'
@ -29,7 +29,8 @@
id: chatId,
name: `Chat ${chatId}`,
settings: {} as ChatSettings,
messages: []
messages: [],
usage:{} as Record<Model,Usage>,
})
chatsStorage.set(chats)
// Apply defaults and prepare it to start
@ -60,10 +61,12 @@
// Add a new chat
chats.push(chat)
chatsStorage.set(chats)
// make sure it's up-to-date
updateChatSettings(chatId)
return chatId
}
// Make sure all chat settings are set with current values or defaults
// Make sure a chat's settings are set with current values or defaults
export const updateChatSettings = (chatId) => {
const chats = get(chatsStorage)
const chat = chats.find((chat) => chat.id === chatId) as Chat
@ -78,6 +81,15 @@
chat.messages.forEach((m) => {
m.uuid = m.uuid || uuidv4()
})
// Make sure the usage totals object is set
// (some earlier versions of this had different structures)
const hasUsage = chat.usage && !Array.isArray(chat.usage)
&& typeof chat.usage === 'object'
&& Object.values(chat.usage).find(v=>'prompt_tokens' in v)
if (!hasUsage) {
const usageMap:Record<Model,Usage> = {}
chat.usage = usageMap
}
chatsStorage.set(chats)
}
@ -118,6 +130,24 @@
return (chats.find((chat) => chat.id === chatId) as Chat).settings
}
export const updateRunningTotal = (chatId: number, usage: Usage, model:Model) => {
const chats = get(chatsStorage)
const chat = chats.find((chat) => chat.id === chatId) as Chat
let total:Usage = chat.usage[model]
if (!total) {
total = {
prompt_tokens: 0,
completion_tokens: 0,
total_tokens: 0,
}
chat.usage[model] = total
}
total.completion_tokens += usage.completion_tokens
total.prompt_tokens += usage.prompt_tokens
total.total_tokens += usage.total_tokens
chatsStorage.set(chats)
}
export const addMessage = (chatId: number, message: Message) => {
const chats = get(chatsStorage)
const chat = chats.find((chat) => chat.id === chatId) as Chat

View File

@ -15,8 +15,6 @@
completion_tokens: number;
prompt_tokens: number;
total_tokens: number;
total: number;
model?: Model;
};
export type Message = {
@ -69,7 +67,7 @@
id: number;
name: string;
messages: Message[];
usage?: Usage[];
usage: Record<Model, Usage>;
settings: ChatSettings;
};