Tiny steps toward UI for hosts/endpoints/models

This commit is contained in:
Webifi 2023-06-12 19:20:31 -05:00
parent a9a49f490a
commit cd1803ed16
4 changed files with 82 additions and 36 deletions

View File

@ -13,7 +13,7 @@
checkStateChange, checkStateChange,
addChat addChat
} from './Storage.svelte' } from './Storage.svelte'
import { supportedModels, type Chat, type ChatSetting, type ResponseModels, type SettingSelect, type SelectOption, type ChatSettings } from './Types.svelte' import type { Chat, ChatSetting, ResponseModels, SettingSelect, SelectOption, ChatSettings } from './Types.svelte'
import { errorNotice, sizeTextElements } from './Util.svelte' import { errorNotice, sizeTextElements } from './Util.svelte'
import Fa from 'svelte-fa/src/fa.svelte' import Fa from 'svelte-fa/src/fa.svelte'
import { import {
@ -37,6 +37,7 @@
import { openModal } from 'svelte-modals' import { openModal } from 'svelte-modals'
import PromptConfirm from './PromptConfirm.svelte' import PromptConfirm from './PromptConfirm.svelte'
import { getApiBase, getEndpointModels } from './ApiUtil.svelte' import { getApiBase, getEndpointModels } from './ApiUtil.svelte'
import { supportedModelKeys } from './Models.svelte'
export let chatId:number export let chatId:number
export const show = () => { showSettings() } export const show = () => { showSettings() }
@ -194,7 +195,7 @@
} }
}) })
).json()) as ResponseModels ).json()) as ResponseModels
const filteredModels = supportedModels.filter((model) => allModels.data.find((m) => m.id === model)) const filteredModels = supportedModelKeys.filter((model) => allModels.data.find((m) => m.id === model))
const modelOptions:SelectOption[] = filteredModels.reduce((a, m) => { const modelOptions:SelectOption[] = filteredModels.reduce((a, m) => {
const o:SelectOption = { const o:SelectOption = {

68
src/lib/Models.svelte Normal file
View File

@ -0,0 +1,68 @@
<script context="module" lang="ts">
import type { ModelDetail, Model } from './Types.svelte'
// Reference: https://openai.com/pricing#language-models
// Eventually we'll add API hosts and endpoints to this
const modelDetails : Record<string, ModelDetail> = {
'gpt-4-32k': {
prompt: 0.00006, // $0.06 per 1000 tokens prompt
completion: 0.00012, // $0.12 per 1000 tokens completion
max: 32768 // 32k max token buffer
},
'gpt-4': {
prompt: 0.00003, // $0.03 per 1000 tokens prompt
completion: 0.00006, // $0.06 per 1000 tokens completion
max: 8192 // 8k max token buffer
},
'gpt-3.5': {
prompt: 0.000002, // $0.002 per 1000 tokens prompt
completion: 0.000002, // $0.002 per 1000 tokens completion
max: 4096 // 4k max token buffer
}
}
const unknownDetail = {
prompt: 0,
completion: 0,
max: 4096
}
// See: https://platform.openai.com/docs/models/model-endpoint-compatibility
// Eventually we'll add UI for managing this
export const supportedModels : Record<string, ModelDetail> = {
'gpt-4': modelDetails['gpt-4'],
'gpt-4-0314': modelDetails['gpt-4'],
'gpt-4-32k': modelDetails['gpt-4-32k'],
'gpt-4-32k-0314': modelDetails['gpt-4-32k'],
'gpt-3.5-turbo': modelDetails['gpt-3.5'],
'gpt-3.5-turbo-0301': modelDetails['gpt-3.5']
}
const lookupList = {
...modelDetails,
...supportedModels
}
export const supportedModelKeys = Object.keys(supportedModels)
const tpCache : Record<string, ModelDetail> = {}
export const getModelDetail = (model: Model) => {
// First try to get exact match, then from cache
let r = supportedModels[model] || tpCache[model]
if (r) return r
// If no exact match, find closest match
const k = Object.keys(lookupList)
.sort((a, b) => b.length - a.length) // Longest to shortest for best match
.find((k) => model.startsWith(k))
if (k) {
r = lookupList[k]
} else {
r = unknownDetail
}
// Cache it so we don't need to do that again
tpCache[model] = r
return r
}
</script>

View File

@ -1,32 +1,11 @@
<script context="module" lang="ts"> <script context="module" lang="ts">
import { getModelDetail } from './Models.svelte'
import type { Message, Model, Usage } from './Types.svelte' import type { Message, Model, Usage } from './Types.svelte'
import { encode } from 'gpt-tokenizer' import { encode } from 'gpt-tokenizer'
// Reference: https://openai.com/pricing#language-models
// TODO: Move to settings of some type
const modelDetails : Record<string, [number, number, number]> = {
'gpt-4-32k': [0.00006, 0.00012, 32768], // $0.06 per 1000 tokens prompt, $0.12 per 1000 tokens completion, max 32k
'gpt-4': [0.00003, 0.00006, 8192], // $0.03 per 1000 tokens prompt, $0.06 per 1000 tokens completion, max 8k
'gpt-3.5': [0.000002, 0.000002, 4096] // $0.002 per 1000 tokens (both prompt and completion), max 4k
}
const tpCache = {}
const getModelDetail = (model: Model) => {
let r = tpCache[model]
if (r) return r
const k = Object.keys(modelDetails).find((k) => model.startsWith(k))
if (k) {
r = modelDetails[k]
} else {
r = [0, 0, 4096]
}
tpCache[model] = r
return r
}
export const getPrice = (tokens: Usage, model: Model): number => { export const getPrice = (tokens: Usage, model: Model): number => {
const t = getModelDetail(model) const t = getModelDetail(model)
return ((tokens.prompt_tokens * t[0]) + (tokens.completion_tokens * t[1])) return ((tokens.prompt_tokens * t.prompt) + (tokens.completion_tokens * t.completion))
} }
export const countPromptTokens = (prompts:Message[], model:Model):number => { export const countPromptTokens = (prompts:Message[], model:Model):number => {
@ -44,7 +23,7 @@
} }
export const getModelMaxTokens = (model:Model):number => { export const getModelMaxTokens = (model:Model):number => {
return getModelDetail(model)[2] return getModelDetail(model).max
} }
</script> </script>

View File

@ -1,15 +1,13 @@
<script context="module" lang="ts"> <script context="module" lang="ts">
// import type internal from "stream"; import type { supportedModelKeys } from './Models.svelte'
export const supportedModels = [ // See: https://platform.openai.com/docs/models/model-endpoint-compatibility export type Model = typeof supportedModelKeys[number];
'gpt-4',
'gpt-4-0314', export type ModelDetail = {
'gpt-4-32k', prompt: number;
'gpt-4-32k-0314', completion: number;
'gpt-3.5-turbo', max: number;
'gpt-3.5-turbo-0301' };
]
export type Model = typeof supportedModels[number];
export type Usage = { export type Usage = {
completion_tokens: number; completion_tokens: number;