Tiny steps toward UI for hosts/endpoints/models
This commit is contained in:
		
							parent
							
								
									a9a49f490a
								
							
						
					
					
						commit
						cd1803ed16
					
				| 
						 | 
					@ -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 = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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>
 | 
				
			||||||
| 
						 | 
					@ -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>
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue