Skip to content

Commit ceca482

Browse files
authored
Merge pull request #494 from stadtwerk/main
Allow alternative OpenAI-compatible endpoints
2 parents 7aff5db + 5f25f90 commit ceca482

18 files changed

+302
-160
lines changed

src/lib/ApiUtil.svelte

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
<script context="module" lang="ts">
22
// This makes it possible to override the OpenAI API base URL in the .env file
3-
const apiBase = import.meta.env.VITE_API_BASE || 'https://api.openai.com'
43
const endpointCompletions = import.meta.env.VITE_ENDPOINT_COMPLETIONS || '/v1/chat/completions'
54
const endpointGenerations = import.meta.env.VITE_ENDPOINT_GENERATIONS || '/v1/images/generations'
65
const endpointModels = import.meta.env.VITE_ENDPOINT_MODELS || '/v1/models'
76
const endpointEmbeddings = import.meta.env.VITE_ENDPOINT_EMBEDDINGS || '/v1/embeddings'
87
const petalsBase = import.meta.env.VITE_PEDALS_WEBSOCKET || 'wss://chat.petals.dev'
98
const endpointPetals = import.meta.env.VITE_PEDALS_WEBSOCKET || '/api/v2/generate'
109
11-
export const getApiBase = ():string => apiBase
1210
export const getEndpointCompletions = ():string => endpointCompletions
1311
export const getEndpointGenerations = ():string => endpointGenerations
1412
export const getEndpointModels = ():string => endpointModels

src/lib/Chat.svelte

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@
5656
let showSettingsModal
5757
5858
let scDelay
59-
const onStateChange = (...args:any) => {
59+
const onStateChange = async (...args:any) => {
6060
if (!chat) return
6161
clearTimeout(scDelay)
62-
setTimeout(() => {
62+
setTimeout(async () => {
6363
if (chat.startSession) {
64-
restartProfile(chatId)
64+
await restartProfile(chatId)
6565
if (chat.startSession) {
6666
chat.startSession = false
6767
saveChatStore()
@@ -112,7 +112,7 @@
112112
setCurrentChat(chatId)
113113
114114
chatRequest = new ChatRequest()
115-
chatRequest.setChat(chat)
115+
await chatRequest.setChat(chat)
116116
117117
chat.lastAccess = Date.now()
118118
saveChatStore()
@@ -148,7 +148,7 @@
148148
console.log('Speech recognition not supported')
149149
}
150150
if (chat.startSession) {
151-
restartProfile(chatId)
151+
await restartProfile(chatId)
152152
if (chat.startSession) {
153153
chat.startSession = false
154154
saveChatStore()

src/lib/ChatOptionMenu.svelte

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@
9999
showChatMenu = false
100100
}
101101
102-
const restartChatSession = () => {
102+
const restartChatSession = async () => {
103103
close()
104-
restartProfile(chatId)
104+
await restartProfile(chatId)
105105
$checkStateChange++ // signal chat page to start profile
106106
}
107107
@@ -125,17 +125,17 @@
125125
})
126126
}
127127
128-
const importProfileFromFile = (e) => {
128+
const importProfileFromFile = async (e) => {
129129
const image = e.target.files[0]
130130
e.target.value = null
131131
const reader = new FileReader()
132-
reader.onload = e => {
132+
reader.onload = async (e) => {
133133
const json = (e.target || {}).result as string
134134
try {
135135
const profile = JSON.parse(json) as ChatSettings
136-
profile.profileName = newNameForProfile(profile.profileName || '')
136+
profile.profileName = await newNameForProfile(profile.profileName || '')
137137
profile.profile = null as any
138-
saveCustomProfile(profile)
138+
await saveCustomProfile(profile)
139139
openModal(PromptConfirm, {
140140
title: 'Profile Restored',
141141
class: 'is-info',
@@ -174,17 +174,17 @@
174174
<span class="menu-icon"><Fa icon={faGear}/></span> Chat Profile Settings
175175
</a>
176176
<hr class="dropdown-divider">
177-
<a href={'#'} class:is-disabled={!hasActiveModels()} on:click|preventDefault={() => { hasActiveModels() && close(); hasActiveModels() && startNewChatWithWarning(chatId) }} class="dropdown-item">
177+
<a href={'#'} class:is-disabled={!hasActiveModels()} on:click|preventDefault={async () => { hasActiveModels() && close(); hasActiveModels() && await startNewChatWithWarning(chatId) }} class="dropdown-item">
178178
<span class="menu-icon"><Fa icon={faSquarePlus}/></span> New Chat from Default
179179
</a>
180-
<a href={'#'} class:is-disabled={!chatId} on:click|preventDefault={() => { chatId && close(); chatId && startNewChatFromChatId(chatId) }} class="dropdown-item">
180+
<a href={'#'} class:is-disabled={!chatId} on:click|preventDefault={async () => { chatId && close(); chatId && await startNewChatFromChatId(chatId) }} class="dropdown-item">
181181
<span class="menu-icon"><Fa icon={faSquarePlusOutline}/></span> New Chat from Current
182182
</a>
183183
<a href={'#'} class="dropdown-item" class:is-disabled={!chatId} on:click|preventDefault={() => { if (chatId) close(); copyChat(chatId) }}>
184184
<span class="menu-icon"><Fa icon={faClone}/></span> Clone Chat
185185
</a>
186186
<hr class="dropdown-divider">
187-
<a href={'#'} class="dropdown-item" class:is-disabled={!chatId} on:click|preventDefault={() => { if (chatId) restartChatSession() }}>
187+
<a href={'#'} class="dropdown-item" class:is-disabled={!chatId} on:click|preventDefault={async () => { if (chatId) await restartChatSession() }}>
188188
<span class="menu-icon"><Fa icon={faRotateRight}/></span> Restart Chat Session
189189
</a>
190190
<a href={'#'} class="dropdown-item" class:is-disabled={!chatId} on:click|preventDefault={() => { if (chatId) close(); clearMessages(chatId) }}>
@@ -231,4 +231,4 @@
231231
</div>
232232

233233
<input style="display:none" type="file" accept=".json" on:change={(e) => importChatFromFile(e)} bind:this={chatFileInput} >
234-
<input style="display:none" type="file" accept=".json" on:change={(e) => importProfileFromFile(e)} bind:this={profileFileInput} >
234+
<input style="display:none" type="file" accept=".json" on:change={async (e) => await importProfileFromFile(e)} bind:this={profileFileInput} >

src/lib/ChatRequest.svelte

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ export class ChatRequest {
2323
controller:AbortController
2424
providerData: Record<string, any> = {}
2525
26-
setChat (chat: Chat) {
26+
async setChat (chat: Chat) {
2727
this.chat = chat
28-
this.chat.settings.model = this.getModel()
28+
this.chat.settings.model = await this.getModel()
2929
}
3030
3131
getChat (): Chat {
@@ -63,7 +63,7 @@ export class ChatRequest {
6363
// TODO: Continue to break this method down to smaller chunks
6464
const _this = this
6565
const chat = getChat(_this.chat.id)
66-
this.setChat(chat)
66+
await this.setChat(chat)
6767
const chatSettings = _this.chat.settings
6868
const chatId = chat.id
6969
const imagePromptDetect = /^\s*(please|can\s+you|will\s+you)*\s*(give|generate|create|show|build|design)\s+(me)*\s*(an|a|set|a\s+set\s+of)*\s*([0-9]+|one|two|three|four)*\s+(image|photo|picture|pic)s*\s*(for\s+me)*\s*(of|[^a-z0-9]+|about|that\s+has|showing|with|having|depicting)\s+[^a-z0-9]*(.*)$/i
@@ -100,7 +100,7 @@ export class ChatRequest {
100100
}
101101
}
102102
103-
const model = this.getModel()
103+
const model = await this.getModel()
104104
const modelDetail = getModelDetail(model)
105105
const maxTokens = getModelMaxTokens(model)
106106
@@ -117,7 +117,7 @@ export class ChatRequest {
117117
118118
// Inject hidden prompts if requested
119119
// if (!opts.summaryRequest)
120-
this.buildHiddenPromptPrefixMessages(filtered, true)
120+
await this.buildHiddenPromptPrefixMessages(filtered, true)
121121
const messagePayload = filtered
122122
.filter(m => { if (m.skipOnce) { delete m.skipOnce; return false } return true })
123123
.map(m => {
@@ -231,11 +231,11 @@ export class ChatRequest {
231231
return chatResponse
232232
}
233233
234-
getModel (): Model {
235-
return this.chat.settings.model || getDefaultModel()
234+
async getModel (): Promise<Model> {
235+
return this.chat.settings.model || await getDefaultModel()
236236
}
237237
238-
private buildHiddenPromptPrefixMessages (messages: Message[], insert:boolean = false): Message[] {
238+
private async buildHiddenPromptPrefixMessages (messages: Message[], insert:boolean = false): Promise<Message[]> {
239239
const chat = this.chat
240240
const chatSettings = chat.settings
241241
const hiddenPromptPrefix = mergeProfileFields(chatSettings, chatSettings.hiddenPromptPrefix).trim()
@@ -271,7 +271,7 @@ export class ChatRequest {
271271
}
272272
if (injectedPrompt) messages.pop()
273273
}
274-
const model = this.getModel()
274+
const model = await this.getModel()
275275
const messageDetail = getModelDetail(model)
276276
if (getLeadPrompt(this.getChat()).trim() && messageDetail.type === 'chat') {
277277
const lastMessage = (results.length && injectedPrompt && !isContinue) ? results[results.length - 1] : messages[messages.length - 1]
@@ -291,11 +291,12 @@ export class ChatRequest {
291291
* Gets an estimate of how many extra tokens will be added that won't be part of the visible messages
292292
* @param filtered
293293
*/
294-
private getTokenCountPadding (filtered: Message[], chat: Chat): number {
294+
private async getTokenCountPadding (filtered: Message[], chat: Chat): Promise<number> {
295+
const model = await this.getModel()
295296
let result = 0
296297
// add cost of hiddenPromptPrefix
297-
result += this.buildHiddenPromptPrefixMessages(filtered)
298-
.reduce((a, m) => a + countMessageTokens(m, this.getModel(), chat), 0)
298+
result += (await this.buildHiddenPromptPrefixMessages(filtered))
299+
.reduce((a, m) => a + countMessageTokens(m, model, chat), 0)
299300
// more here eventually?
300301
return result
301302
}
@@ -306,7 +307,7 @@ export class ChatRequest {
306307
const chatSettings = chat.settings
307308
const chatId = chat.id
308309
const reductionMode = chatSettings.continuousChat
309-
const model = _this.getModel()
310+
const model = await _this.getModel()
310311
const maxTokens = getModelMaxTokens(model) // max tokens for model
311312
312313
const continueRequest = async () => {

src/lib/ChatSettingsModal.svelte

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
let showSettingsModal = 0
4444
let showProfileMenu:boolean = false
4545
let profileFileInput
46-
let defaultProfile = getDefaultProfileKey()
46+
let defaultProfile
4747
let isDefault = false
4848
4949
const settingsList = getChatSettingList()
@@ -63,6 +63,8 @@
6363
onMount(async () => {
6464
originalProfile = chatSettings && chatSettings.profile
6565
originalSettings = chatSettings && JSON.parse(JSON.stringify(chatSettings))
66+
67+
defaultProfile = await getDefaultProfileKey()
6668
})
6769
6870
afterUpdate(() => {
@@ -112,17 +114,17 @@
112114
return profileUri
113115
}
114116
115-
const cloneProfile = () => {
117+
const cloneProfile = async () => {
116118
showProfileMenu = false
117119
const clone = JSON.parse(JSON.stringify(chat.settings))
118120
const name = chat.settings.profileName
119-
clone.profileName = newNameForProfile(name || '')
121+
clone.profileName = await newNameForProfile(name || '')
120122
clone.profile = null
121123
try {
122-
saveCustomProfile(clone)
124+
await saveCustomProfile(clone)
123125
chat.settings.profile = clone.profile
124126
chat.settings.profileName = clone.profileName
125-
applyProfile(chatId, clone.profile)
127+
await applyProfile(chatId, clone.profile)
126128
refreshSettings()
127129
} catch (e) {
128130
errorNotice('Error cloning profile:', e)
@@ -140,14 +142,14 @@
140142
})
141143
}
142144
143-
const deleteProfile = () => {
145+
const deleteProfile = async () => {
144146
showProfileMenu = false
145147
try {
146-
deleteCustomProfile(chatId, chat.settings.profile)
148+
await deleteCustomProfile(chatId, chat.settings.profile)
147149
chat.settings.profile = globalStore.defaultProfile || ''
148150
saveChatStore()
149151
setGlobalSettingValueByKey('lastProfile', chat.settings.profile)
150-
applyProfile(chatId, chat.settings.profile)
152+
await applyProfile(chatId, chat.settings.profile)
151153
refreshSettings()
152154
} catch (e) {
153155
console.error(e)
@@ -161,42 +163,42 @@
161163
refreshSettings()
162164
}
163165
164-
const importProfileFromFile = (e) => {
166+
const importProfileFromFile = async (e) => {
165167
const image = e.target.files[0]
166168
e.target.value = null
167169
const reader = new FileReader()
168170
reader.readAsText(image)
169-
reader.onload = e => {
171+
reader.onload = async (e) => {
170172
const json = (e.target || {}).result as string
171173
try {
172174
const profile = JSON.parse(json)
173-
profile.profileName = newNameForProfile(profile.profileName || '')
175+
profile.profileName = await newNameForProfile(profile.profileName || '')
174176
profile.profile = null
175-
saveCustomProfile(profile)
177+
await saveCustomProfile(profile)
176178
refreshSettings()
177179
} catch (e) {
178180
errorNotice('Unable to import profile:', e)
179181
}
180182
}
181183
}
182184
183-
const updateProfileSelectOptions = () => {
185+
const updateProfileSelectOptions = async () => {
184186
const profileSelect = getChatSettingObjectByKey('profile') as ChatSetting & SettingSelect
185-
profileSelect.options = getProfileSelect()
186-
chatDefaults.profile = getDefaultProfileKey()
187+
profileSelect.options = await getProfileSelect()
188+
chatDefaults.profile = await getDefaultProfileKey()
187189
chatDefaults.max_tokens = getModelMaxTokens(chatSettings.model)
188190
// const defaultProfile = globalStore.defaultProfile || profileSelect.options[0].value
189-
defaultProfile = getDefaultProfileKey()
191+
defaultProfile = await getDefaultProfileKey()
190192
isDefault = defaultProfile === chatSettings.profile
191193
}
192194
193195
const showSettings = async () => {
194-
setDirty()
196+
await setDirty()
195197
// Show settings modal
196198
showSettingsModal++
197199
198200
// Get profile options
199-
updateProfileSelectOptions()
201+
await updateProfileSelectOptions()
200202
201203
// Refresh settings modal
202204
showSettingsModal++
@@ -215,20 +217,20 @@
215217
setTimeout(() => sizeTextElements(profileChanged))
216218
}
217219
218-
const saveProfile = () => {
220+
const saveProfile = async () => {
219221
showProfileMenu = false
220222
try {
221-
saveCustomProfile(chat.settings)
223+
await saveCustomProfile(chat.settings)
222224
refreshSettings()
223225
} catch (e) {
224226
errorNotice('Error saving profile:', e)
225227
}
226228
}
227229
228-
const startNewChat = () => {
230+
const startNewChat = async () => {
229231
const differentProfile = originalSettings.profile !== chatSettings.profile
230232
// start new
231-
const newChatId = addChat(chatSettings)
233+
const newChatId = await addChat(chatSettings)
232234
// restore original
233235
if (differentProfile) {
234236
chat.settings = originalSettings
@@ -247,13 +249,13 @@
247249
: (x === y || ((x === undefined || x === null || x === false) && (y === undefined || y === null || y === false)))
248250
}
249251
250-
const setDirty = (e:CustomEvent|undefined = undefined) => {
252+
const setDirty = async (e:CustomEvent|undefined = undefined) => {
251253
if (e) {
252254
const setting = e.detail as ChatSetting
253255
const key = setting.key
254256
if (key === 'profile') return
255257
}
256-
const profile = getProfile(chatSettings.profile)
258+
const profile = await getProfile(chatSettings.profile)
257259
chatSettings.isDirty = !deepEqual(profile, chatSettings)
258260
}
259261
@@ -343,4 +345,4 @@
343345
</div>
344346
</div>
345347

346-
<input style="display:none" type="file" accept=".json" on:change={(e) => importProfileFromFile(e)} bind:this={profileFileInput} >
348+
<input style="display:none" type="file" accept=".json" on:change={async (e) => await importProfileFromFile(e)} bind:this={profileFileInput} >

0 commit comments

Comments
 (0)