mirror of
https://github.com/morgan9e/chatgpt-web
synced 2026-04-13 16:04:05 +09:00
185 lines
5.3 KiB
Svelte
185 lines
5.3 KiB
Svelte
<script context="module" lang="ts">
|
|
|
|
import { getApiBase, getEndpointCompletions, getEndpointGenerations } from '../../ApiUtil.svelte'
|
|
import { countTokens } from '../../Models.svelte'
|
|
import { countMessageTokens } from '../../Stats.svelte'
|
|
import { globalStorage } from '../../Storage.svelte'
|
|
import type { Chat, Message, Model, ModelDetail } from '../../Types.svelte'
|
|
import { chatRequest, imageRequest } from './request.svelte'
|
|
import { checkModel } from './util.svelte'
|
|
// Lazy-load tokenizer to improve initial load time
|
|
let encode: any = null
|
|
|
|
// Simple token approximation for faster initial loads
|
|
const approximateTokens = (text: string): number[] => {
|
|
// Rough approximation: 1 token ≈ 4 characters for most text
|
|
return new Array(Math.ceil(text.length / 4)).fill(0)
|
|
}
|
|
|
|
const getTokenizer = async () => {
|
|
if (!encode) {
|
|
const tokenizer = await import('gpt-tokenizer')
|
|
encode = tokenizer.encode
|
|
}
|
|
return encode
|
|
}
|
|
import { get } from 'svelte/store'
|
|
import chatModelsJson from './models.json'
|
|
|
|
const hiddenSettings = {
|
|
startSequence: true,
|
|
stopSequence: true,
|
|
aggressiveStop: true,
|
|
delimiter: true,
|
|
userMessageStart: true,
|
|
userMessageEnd: true,
|
|
assistantMessageStart: true,
|
|
assistantMessageEnd: true,
|
|
systemMessageStart: true,
|
|
systemMessageEnd: true,
|
|
repetitionPenalty: true,
|
|
holdSocket: true
|
|
// leadPrompt: true
|
|
} as any
|
|
|
|
const chatModelBase = {
|
|
type: 'chat',
|
|
help: 'Below are the settings that OpenAI allows to be changed for the API calls. See the <a target="_blank" href="https://platform.openai.com/docs/api-reference/chat/create">OpenAI API docs</a> for more details.',
|
|
preFillMerge: (existingContent, newContent) => {
|
|
if (existingContent && !newContent.match(/^('(t|ll|ve|m|d|re)[^a-z]|\s|[.,;:(_-{}*^%$#@!?+=~`[\]])/i)) {
|
|
existingContent += ' '
|
|
}
|
|
return existingContent
|
|
},
|
|
request: chatRequest,
|
|
check: checkModel,
|
|
getTokens: (value) => {
|
|
// Use approximation for faster initial loads, actual tokenizer loads async
|
|
if (!encode) {
|
|
getTokenizer() // Start loading tokenizer for future use
|
|
return approximateTokens(value)
|
|
}
|
|
return encode(value)
|
|
},
|
|
getEndpoint: (model) => get(globalStorage).openAICompletionEndpoint || getApiBase() + getEndpointCompletions(),
|
|
hideSetting: (chatId, setting) => !!hiddenSettings[setting.key],
|
|
countMessageTokens: (message: Message, model: Model, chat: Chat) => {
|
|
return countTokens(model, '## ' + message.role + ' ##:\r\n\r\n' + message.content + '\r\n\r\n\r\n')
|
|
},
|
|
countPromptTokens: (prompts: Message[], model: Model, chat: Chat): number => {
|
|
return (
|
|
prompts.reduce((a, m) => {
|
|
a += countMessageTokens(m, model, chat)
|
|
return a
|
|
}, 0) + 3
|
|
)
|
|
}
|
|
} as ModelDetail
|
|
|
|
export const chatModels: Record<string, ModelDetail> = {}
|
|
|
|
for (const [key, { prompt, completion, max, reasoning, alias }] of Object.entries(chatModelsJson)) {
|
|
chatModels[key] = {
|
|
...chatModelBase,
|
|
prompt: prompt / 1_000_000,
|
|
completion: completion / 1_000_000,
|
|
max,
|
|
...(reasoning ? { reasoning } : {}),
|
|
...(alias ? { alias } : {})
|
|
}
|
|
}
|
|
|
|
const imageModelBase = {
|
|
type: 'image',
|
|
prompt: 0.0,
|
|
max: 1000, // 1000 char prompt, max
|
|
request: imageRequest,
|
|
check: checkModel,
|
|
getTokens: (value) => [0],
|
|
getEndpoint: (model) => getApiBase() + getEndpointGenerations(),
|
|
hideSetting: (chatId, setting) => false
|
|
} as ModelDetail
|
|
|
|
export const imageModels: Record<string, ModelDetail> = {
|
|
'dall-e-1024x1024': {
|
|
...imageModelBase,
|
|
completion: 0.02, // $0.020 per image
|
|
opt: {
|
|
size: '1024x1024'
|
|
}
|
|
},
|
|
'dall-e-512x512': {
|
|
...imageModelBase,
|
|
completion: 0.018, // $0.018 per image
|
|
opt: {
|
|
size: '512x512'
|
|
}
|
|
},
|
|
'dall-e-256x256': {
|
|
...imageModelBase,
|
|
type: 'image',
|
|
completion: 0.016, // $0.016 per image
|
|
opt: {
|
|
size: '256x256'
|
|
}
|
|
},
|
|
'dall-e-3-1024x1024': {
|
|
...imageModelBase,
|
|
type: 'image',
|
|
completion: 0.04, // $0.040 per image
|
|
opt: {
|
|
model: 'dall-e-3',
|
|
size: '1024x1024'
|
|
}
|
|
},
|
|
'dall-e-3-1024x1792-Portrait': {
|
|
...imageModelBase,
|
|
type: 'image',
|
|
completion: 0.08, // $0.080 per image
|
|
opt: {
|
|
model: 'dall-e-3',
|
|
size: '1024x1792'
|
|
}
|
|
},
|
|
'dall-e-3-1792x1024-Landscape': {
|
|
...imageModelBase,
|
|
type: 'image',
|
|
completion: 0.08, // $0.080 per image
|
|
opt: {
|
|
model: 'dall-e-3',
|
|
size: '1792x1024'
|
|
}
|
|
},
|
|
'dall-e-3-1024x1024-HD': {
|
|
...imageModelBase,
|
|
type: 'image',
|
|
completion: 0.08, // $0.080 per image
|
|
opt: {
|
|
model: 'dall-e-3',
|
|
size: '1024x1024',
|
|
quality: 'hd'
|
|
}
|
|
},
|
|
'dall-e-3-1024x1792-Portrait-HD': {
|
|
...imageModelBase,
|
|
type: 'image',
|
|
completion: 0.12, // $0.080 per image
|
|
opt: {
|
|
model: 'dall-e-3',
|
|
size: '1024x1792',
|
|
quality: 'hd'
|
|
}
|
|
},
|
|
'dall-e-3-1792x1024-Landscape-HD': {
|
|
...imageModelBase,
|
|
type: 'image',
|
|
completion: 0.12, // $0.080 per image
|
|
opt: {
|
|
model: 'dall-e-3',
|
|
size: '1792x1024',
|
|
quality: 'hd'
|
|
}
|
|
}
|
|
}
|
|
|
|
</script> |