Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
open-webui
Commits
d8d14fbf
Commit
d8d14fbf
authored
Nov 03, 2023
by
Timothy J. Baek
Browse files
feat: openAI model support added
parent
6f1eaf03
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
344 additions
and
155 deletions
+344
-155
src/lib/components/chat/SettingsModal.svelte
src/lib/components/chat/SettingsModal.svelte
+110
-44
src/routes/+page.svelte
src/routes/+page.svelte
+234
-111
No files found.
src/lib/components/chat/SettingsModal.svelte
View file @
d8d14fbf
...
...
@@ -8,16 +8,21 @@
export let saveSettings: Function;
export let getModelTags: Function;
let selectedTab = 'general';
// General
let API_BASE_URL = BUILD_TIME_API_BASE_URL;
let OPENAI_API_KEY = '';
let system = '';
let temperature = 0.8;
let selectedMenu = 'general';
// Models
let modelTag = '';
let deleteModelTag = '';
let digest = '';
let pullProgress = '';
let pullProgress = null;
// Advanced
let temperature = 0.8;
const splitStream = (splitOn) => {
let buffer = '';
...
...
@@ -42,11 +47,9 @@
if (res) {
toast.success('Server connection verified');
saveSettings(
API_BASE_URL,
system != '' ? system : null,
temperature != 0.8 ? temperature : null
);
saveSettings({
API_BASE_URL: API_BASE_URL
});
}
};
...
...
@@ -156,7 +159,10 @@
$: if (show) {
let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
console.log(settings);
API_BASE_URL = settings.API_BASE_URL ?? BUILD_TIME_API_BASE_URL;
OPENAI_API_KEY = settings.OPENAI_API_KEY ?? '';
system = settings.system ?? '';
temperature = settings.temperature ?? 0.8;
}
...
...
@@ -191,12 +197,12 @@
class="flex flex-row space-x-1 md:space-x-0 md:space-y-1 md:flex-col flex-1 md:flex-none md:w-40 text-gray-200 text-xs text-left mb-3 md:mb-0"
>
<button
class="px-2 py-2 rounded flex-1 md:flex-none flex text-right transition {selected
Menu
===
class="px-2
.5
py-2
.5
rounded
-lg
flex-1 md:flex-none flex text-right transition {selected
Tab
===
'general'
? 'bg-gray-700'
: 'hover:bg-gray-800'}"
on:click={() => {
selected
Menu
= 'general';
selected
Tab
= 'general';
}}
>
<div class=" self-center mr-2">
...
...
@@ -217,12 +223,12 @@
</button>
<button
class="px-2 py-2 rounded flex-1 md:flex-none flex text-right transition {selected
Menu
===
class="px-2
.5
py-2
.5
rounded
-lg
flex-1 md:flex-none flex text-right transition {selected
Tab
===
'models'
? 'bg-gray-700'
: 'hover:bg-gray-800'}"
on:click={() => {
selected
Menu
= 'models';
selected
Tab
= 'models';
}}
>
<div class=" self-center mr-2">
...
...
@@ -241,9 +247,33 @@
</div>
<div class=" self-center">Models</div>
</button>
<button
class="px-2.5 py-2.5 rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
'advanced'
? 'bg-gray-700'
: 'hover:bg-gray-800'}"
on:click={() => {
selectedTab = 'advanced';
}}
>
<div class=" self-center mr-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M12 4.467c0-.405.262-.75.559-1.027.276-.257.441-.584.441-.94 0-.828-.895-1.5-2-1.5s-2 .672-2 1.5c0 .362.171.694.456.953.29.265.544.6.544.994a.968.968 0 01-1.024.974 39.655 39.655 0 01-3.014-.306.75.75 0 00-.847.847c.14.993.242 1.999.306 3.014A.968.968 0 014.447 10c-.393 0-.729-.253-.994-.544C3.194 9.17 2.862 9 2.5 9 1.672 9 1 9.895 1 11s.672 2 1.5 2c.356 0 .683-.165.94-.441.276-.297.622-.559 1.027-.559a.997.997 0 011.004 1.03 39.747 39.747 0 01-.319 3.734.75.75 0 00.64.842c1.05.146 2.111.252 3.184.318A.97.97 0 0010 16.948c0-.394-.254-.73-.545-.995C9.171 15.693 9 15.362 9 15c0-.828.895-1.5 2-1.5s2 .672 2 1.5c0 .356-.165.683-.441.94-.297.276-.559.622-.559 1.027a.998.998 0 001.03 1.005c1.337-.05 2.659-.162 3.961-.337a.75.75 0 00.644-.644c.175-1.302.288-2.624.337-3.961A.998.998 0 0016.967 12c-.405 0-.75.262-1.027.559-.257.276-.584.441-.94.441-.828 0-1.5-.895-1.5-2s.672-2 1.5-2c.362 0 .694.17.953.455.265.291.601.545.995.545a.97.97 0 00.976-1.024 41.159 41.159 0 00-.318-3.184.75.75 0 00-.842-.64c-1.228.164-2.473.271-3.734.319A.997.997 0 0112 4.467z"
/>
</svg>
</div>
<div class=" self-center">Advanced</div>
</button>
</div>
<div class="flex-1 md:min-h-[300px]">
{#if selected
Menu
=== 'general'}
{#if selected
Tab
=== 'general'}
<div class="flex flex-col space-y-3">
<div>
<div class=" mb-2.5 text-sm font-medium">Ollama Server URL</div>
...
...
@@ -290,42 +320,44 @@
<hr class=" border-gray-700" />
<div>
<div class=" mb-2.5 text-sm font-medium">System Prompt</div>
<textarea
bind:value={system}
class="w-full rounded p-4 text-sm text-gray-300 bg-gray-800 outline-none"
rows="4"
<div class=" mb-2.5 text-sm font-medium">
OpenAI API Key <span class=" text-gray-400 text-sm">(optional)</span>
</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<input
class="w-full rounded py-2 px-4 text-sm text-gray-300 bg-gray-800 outline-none"
placeholder="Enter OpenAI API Key"
bind:value={OPENAI_API_KEY}
autocomplete="off"
/>
</div>
</div>
<div class="mt-2 text-xs text-gray-500">
Adds optional support for 'gpt-3.5-turbo'.
</div>
</div>
<hr class=" border-gray-700" />
<div>
<label for="steps-range" class=" mb-2 text-sm font-medium flex justify-between">
<div>Temperature</div>
<div>
{temperature}
</div></label
>
<input
id="steps-range"
type="range"
min="0"
max="1"
bind:value={temperature}
step="0.05"
class="w-full h-2 rounded-lg appearance-none cursor-pointer bg-gray-700"
<div class=" mb-2.5 text-sm font-medium">System Prompt</div>
<textarea
bind:value={system}
class="w-full rounded p-4 text-sm text-gray-300 bg-gray-800 outline-none resize-none"
rows="4"
/>
</div>
<div class="flex justify-end pt-3 text-sm font-medium">
<button
class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 transition rounded"
on:click={() => {
saveSettings(
API_BASE_URL === '' ? BUILD_TIME_API_BASE_URL : API_BASE_URL,
system
!= '' ?
system : null
,
temperature
!=
0.8 ? temperature : null
);
saveSettings(
{
API_BASE_URL:
API_BASE_URL === '' ? BUILD_TIME_API_BASE_URL : API_BASE_URL,
OPENAI_API_KEY: OPENAI_API_KEY
!=
=
'' ?
OPENAI_API_KEY : undefined
,
system: system
!=
=
'' ? system : undefined
}
);
show = false;
}}
>
...
...
@@ -333,8 +365,8 @@
</button>
</div>
</div>
{:else if selected
Menu
=== 'models'}
<div class="flex flex-col space-y-3 text-sm">
{:else if selected
Tab
=== 'models'}
<div class="flex flex-col space-y-3 text-sm
mb-10
">
<div>
<div class=" mb-2.5 text-sm font-medium">Pull a model</div>
<div class="flex w-full">
...
...
@@ -375,15 +407,15 @@
>
</div>
{#if pullProgress !==
''
}
{#if pullProgress !==
null
}
<div class="mt-2">
<div class=" mb-2 text-xs">Pull Progress</div>
<div class="w-full rounded-full bg-gray-800">
<div
class="bg-gray-600 text-xs font-medium text-blue-100 text-center p-0.5 leading-none rounded-full"
style="width: {Math.max(15, pullProgress)}%"
style="width: {Math.max(15, pullProgress
?? 0
)}%"
>
{pullProgress}%
{pullProgress
?? 0
}%
</div>
</div>
<div class="mt-1 text-xs text-gray-700" style="font-size: 0.5rem;">
...
...
@@ -426,6 +458,40 @@
</div>
</div>
</div>
{:else if selectedTab === 'advanced'}
<div class="flex flex-col h-full justify-between space-y-3 text-sm">
<div>
<label for="steps-range" class=" mb-2 text-sm font-medium flex justify-between">
<div>Temperature</div>
<div>
{temperature}
</div></label
>
<input
id="steps-range"
type="range"
min="0"
max="1"
bind:value={temperature}
step="0.05"
class="w-full h-2 rounded-lg appearance-none cursor-pointer bg-gray-700"
/>
</div>
<div class="flex justify-end pt-3 text-sm font-medium">
<button
class=" px-4 py-2 bg-emerald-600 hover:bg-emerald-700 transition rounded"
on:click={() => {
saveSettings({
temperature: temperature !== 0.8 ? temperature : undefined
});
show = false;
}}
>
Save
</button>
</div>
</div>
{/if}
</div>
</div>
...
...
src/routes/+page.svelte
View file @
d8d14fbf
...
...
@@ -18,55 +18,30 @@
import
Suggestions
from
'
$lib/components/chat/Suggestions.svelte
'
;
let
API_BASE_URL
=
BUILD_TIME_API_BASE_URL
;
let
suggestions
=
''
;
// $page.url.searchParams.get('suggestions');
let
models
=
[];
let
textareaElement
;
let
showSettings
=
false
;
let
db
;
let
selectedModel
=
''
;
let
system
=
null
;
let
temperature
=
null
;
let
settings
=
{
system
:
null
,
temperature
:
null
};
let
models
=
[];
let
chats
=
[];
let
chatId
=
uuidv4
();
let
title
=
''
;
let
prompt
=
''
;
let
messages
=
[];
let
showSettings
=
false
;
let
stopResponseFlag
=
false
;
let
autoScroll
=
true
;
let
suggestions
=
''
;
// $page.url.searchParams.get('suggestions');
onMount
(
async
()
=>
{
let
settings
=
JSON
.
parse
(
localStorage
.
getItem
(
'
settings
'
)
??
'
{}
'
);
API_BASE_URL
=
settings
.
API_BASE_URL
??
BUILD_TIME_API_BASE_URL
;
console
.
log
(
API_BASE_URL
);
system
=
settings
.
system
??
null
;
temperature
=
settings
.
temperature
??
null
;
await
getModelTags
();
selectedModel
=
settings
.
model
&&
models
.
map
((
model
)
=>
model
.
name
).
includes
(
settings
.
model
)
?
settings
.
model
:
''
;
db
=
await
openDB
(
'
Chats
'
,
1
,
{
upgrade
(
db
)
{
const
store
=
db
.
createObjectStore
(
'
chats
'
,
{
keyPath
:
'
id
'
,
autoIncrement
:
true
});
store
.
createIndex
(
'
timestamp
'
,
'
timestamp
'
);
}
});
chats
=
await
db
.
getAllFromIndex
(
'
chats
'
,
'
timestamp
'
);
console
.
log
(
chats
);
console
.
log
(
chatId
);
await
createNewChat
(
true
);
await
setDBandLoadChats
();
});
//////////////////////////
...
...
@@ -184,58 +159,54 @@
// Web functions
//////////////////////////
const
saveDefaultModel
=
()
=>
{
let
settings
=
localStorage
.
getItem
(
'
settings
'
)
??
'
{}
'
;
if
(
settings
)
{
settings
=
JSON
.
parse
(
settings
);
settings
.
model
=
selectedModel
;
localStorage
.
setItem
(
'
settings
'
,
JSON
.
stringify
(
settings
));
}
console
.
log
(
'
saved
'
);
toast
.
success
(
'
Default model updated
'
);
};
const
saveSettings
=
async
(
_api_base_url
,
_system
,
_temperature
)
=>
{
API_BASE_URL
=
_api_base_url
;
system
=
_system
;
temperature
=
_temperature
;
let
settings
=
localStorage
.
getItem
(
'
settings
'
)
??
'
{}
'
;
if
(
settings
)
{
settings
=
JSON
.
parse
(
settings
);
settings
.
API_BASE_URL
=
API_BASE_URL
;
settings
.
system
=
system
;
settings
.
temperature
=
temperature
;
localStorage
.
setItem
(
'
settings
'
,
JSON
.
stringify
(
settings
));
}
console
.
log
(
settings
);
await
getModelTags
();
};
const
createNewChat
=
()
=>
{
if
(
messages
.
length
>
0
)
{
const
createNewChat
=
async
(
init
=
false
)
=>
{
if
(
init
||
messages
.
length
>
0
)
{
chatId
=
uuidv4
();
messages
=
[];
title
=
''
;
console
.
log
(
localStorage
.
settings
.
model
);
let
settings
=
localStorage
.
getItem
(
'
settings
'
);
if
(
settings
)
{
settings
=
JSON
.
parse
(
settings
);
console
.
log
(
settings
);
settings
=
JSON
.
parse
(
localStorage
.
getItem
(
'
settings
'
)
??
JSON
.
stringify
(
settings
));
API_BASE_URL
=
settings
?.
API_BASE_URL
??
BUILD_TIME_API_BASE_URL
;
console
.
log
(
API_BASE_URL
);
if
(
models
.
length
===
0
)
{
await
getModelTags
();
}
selectedModel
=
settings
.
model
&&
models
.
map
((
model
)
=>
model
.
name
).
includes
(
settings
.
model
)
?
settings
.
model
:
''
;
system
=
settings
.
system
??
system
;
temperature
=
settings
.
temperature
??
temperature
;
console
.
log
(
chatId
)
;
}
};
const
setDBandLoadChats
=
async
()
=>
{
db
=
await
openDB
(
'
Chats
'
,
1
,
{
upgrade
(
db
)
{
const
store
=
db
.
createObjectStore
(
'
chats
'
,
{
keyPath
:
'
id
'
,
autoIncrement
:
true
});
store
.
createIndex
(
'
timestamp
'
,
'
timestamp
'
);
}
});
chats
=
await
db
.
getAllFromIndex
(
'
chats
'
,
'
timestamp
'
);
};
const
saveDefaultModel
=
()
=>
{
settings
.
model
=
selectedModel
;
localStorage
.
setItem
(
'
settings
'
,
JSON
.
stringify
(
settings
));
toast
.
success
(
'
Default model updated
'
);
};
const
saveSettings
=
async
(
updated
)
=>
{
settings
=
{
...
settings
,
...
updated
};
localStorage
.
setItem
(
'
settings
'
,
JSON
.
stringify
(
settings
));
await
getModelTags
();
};
const
loadChat
=
async
(
id
)
=>
{
...
...
@@ -248,8 +219,8 @@
title
=
chat
.
title
;
chatId
=
chat
.
id
;
selectedModel
=
chat
.
model
??
selectedModel
;
system
=
chat
.
system
??
system
;
temperature
=
chat
.
temperature
??
temperature
;
settings
.
system
=
chat
.
system
??
settings
.
system
;
settings
.
temperature
=
chat
.
temperature
??
settings
.
temperature
;
await
tick
();
hljs
.
highlightAll
();
...
...
@@ -285,8 +256,8 @@
chats
=
await
db
.
getAllFromIndex
(
'
chats
'
,
'
timestamp
'
);
};
const
importChatHistory
=
async
(
results
)
=>
{
for
(
const
chat
of
results
)
{
const
importChatHistory
=
async
(
chatHistory
)
=>
{
for
(
const
chat
of
chatHistory
)
{
console
.
log
(
chat
);
await
db
.
put
(
'
chats
'
,
{
...
...
@@ -357,9 +328,9 @@
id
:
chatId
,
title
:
title
===
''
?
'
New Chat
'
:
title
,
model
:
selectedModel
,
system
:
system
,
system
:
settings
.
system
,
options
:
{
temperature
:
temperature
temperature
:
settings
.
temperature
},
timestamp
:
Date
.
now
(),
messages
:
messages
...
...
@@ -391,11 +362,53 @@
});
console
.
log
(
res
);
if
(
settings
.
OPENAI_API_KEY
)
{
// Validate OPENAI_API_KEY
const
openaiModels
=
await
fetch
(
`https://api.openai.com/v1/models`
,
{
method
:
'
GET
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
Authorization
:
`Bearer
${
settings
.
OPENAI_API_KEY
}
`
}
})
.
then
(
async
(
res
)
=>
{
if
(
!
res
.
ok
)
throw
await
res
.
json
();
return
res
.
json
();
})
.
catch
((
error
)
=>
{
console
.
log
(
error
);
toast
.
error
(
`OpenAI:
${
error
.
error
.
message
}
`
);
return
null
;
});
console
.
log
(
openaiModels
);
if
(
openaiModels
)
{
models
=
[
...(
res
?.
models
??
[]),
{
name
:
'
hr
'
},
{
name
:
'
gpt-3.5-turbo
'
,
label
:
'
(OpenAI)
'
}
];
}
else
{
models
=
res
?.
models
??
[];
return
res
;
}
}
else
{
models
=
res
?.
models
??
[];
}
return
models
;
};
const
sendPrompt
=
async
(
userPrompt
)
=>
{
if
(
selectedModel
===
'
gpt-3.5-turbo
'
)
{
await
sendPromptOpenAI
(
userPrompt
);
}
else
{
await
sendPromptOllama
(
userPrompt
);
}
};
const
sendPromptOllama
=
async
(
userPrompt
)
=>
{
let
responseMessage
=
{
role
:
'
assistant
'
,
content
:
''
...
...
@@ -412,11 +425,11 @@
body
:
JSON
.
stringify
({
model
:
selectedModel
,
prompt
:
userPrompt
,
system
:
system
??
undefined
,
system
:
settings
.
system
??
undefined
,
options
:
temperature
!=
null
settings
.
temperature
!=
null
?
{
temperature
:
temperature
temperature
:
settings
.
temperature
}
:
undefined
,
context
:
...
...
@@ -481,9 +494,9 @@
id
:
chatId
,
title
:
title
===
''
?
'
New Chat
'
:
title
,
model
:
selectedModel
,
system
:
system
,
system
:
settings
.
system
,
options
:
{
temperature
:
temperature
temperature
:
settings
.
temperature
},
timestamp
:
Date
.
now
(),
messages
:
messages
...
...
@@ -495,6 +508,111 @@
if
(
autoScroll
)
{
window
.
scrollTo
({
top
:
document
.
body
.
scrollHeight
});
}
if
(
messages
.
length
==
2
)
{
await
generateChatTitle
(
chatId
,
userPrompt
);
}
};
const
sendPromptOpenAI
=
async
(
userPrompt
)
=>
{
if
(
settings
.
OPENAI_API_KEY
)
{
if
(
models
)
{
let
responseMessage
=
{
role
:
'
assistant
'
,
content
:
''
};
messages
=
[...
messages
,
responseMessage
];
window
.
scrollTo
({
top
:
document
.
body
.
scrollHeight
});
const
res
=
await
fetch
(
`https://api.openai.com/v1/chat/completions`
,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
Authorization
:
`Bearer
${
settings
.
OPENAI_API_KEY
}
`
},
body
:
JSON
.
stringify
({
model
:
'
gpt-3.5-turbo
'
,
stream
:
true
,
messages
:
messages
.
map
((
message
)
=>
({
...
message
,
done
:
undefined
}))
})
});
const
reader
=
res
.
body
.
pipeThrough
(
new
TextDecoderStream
())
.
pipeThrough
(
splitStream
(
'
\n
'
))
.
getReader
();
while
(
true
)
{
const
{
value
,
done
}
=
await
reader
.
read
();
if
(
done
||
stopResponseFlag
)
{
if
(
stopResponseFlag
)
{
responseMessage
.
done
=
true
;
messages
=
messages
;
}
break
;
}
try
{
let
lines
=
value
.
split
(
'
\n
'
);
for
(
const
line
of
lines
)
{
if
(
line
!==
''
)
{
console
.
log
(
line
);
if
(
line
===
'
data: [DONE]
'
)
{
responseMessage
.
done
=
true
;
messages
=
messages
;
}
else
{
let
data
=
JSON
.
parse
(
line
.
replace
(
/^data: /
,
''
));
console
.
log
(
data
);
if
(
responseMessage
.
content
==
''
&&
data
.
choices
[
0
].
delta
.
content
==
'
\n
'
)
{
continue
;
}
else
{
responseMessage
.
content
+=
data
.
choices
[
0
].
delta
.
content
??
''
;
messages
=
messages
;
}
}
}
}
}
catch
(
error
)
{
console
.
log
(
error
);
}
if
(
autoScroll
)
{
window
.
scrollTo
({
top
:
document
.
body
.
scrollHeight
});
}
await
db
.
put
(
'
chats
'
,
{
id
:
chatId
,
title
:
title
===
''
?
'
New Chat
'
:
title
,
model
:
selectedModel
,
system
:
settings
.
system
,
options
:
{
temperature
:
settings
.
temperature
},
timestamp
:
Date
.
now
(),
messages
:
messages
});
}
stopResponseFlag
=
false
;
hljs
.
highlightAll
();
createCopyCodeBlockButton
();
renderLatex
();
await
tick
();
if
(
autoScroll
)
{
window
.
scrollTo
({
top
:
document
.
body
.
scrollHeight
});
}
if
(
messages
.
length
==
2
)
{
await
setChatTitle
(
chatId
,
userPrompt
);
}
}
}
};
const
submitPrompt
=
async
(
userPrompt
)
=>
{
...
...
@@ -509,9 +627,9 @@
await
db
.
put
(
'
chats
'
,
{
id
:
chatId
,
model
:
selectedModel
,
system
:
system
,
system
:
settings
.
system
,
options
:
{
temperature
:
temperature
temperature
:
settings
.
temperature
},
title
:
'
New Chat
'
,
timestamp
:
Date
.
now
(),
...
...
@@ -529,7 +647,6 @@
];
prompt
=
''
;
textareaElement
.
style
.
height
=
''
;
setTimeout
(()
=>
{
window
.
scrollTo
({
top
:
document
.
body
.
scrollHeight
,
behavior
:
'
smooth
'
});
...
...
@@ -537,9 +654,6 @@
await
sendPrompt
(
userPrompt
);
if
(
messages
.
length
==
2
)
{
await
generateTitle
(
chatId
,
userPrompt
);
}
chats
=
await
db
.
getAllFromIndex
(
'
chats
'
,
'
timestamp
'
);
}
};
...
...
@@ -552,7 +666,9 @@
let
userMessage
=
messages
.
at
(
-
1
);
let
userPrompt
=
userMessage
.
content
;
await
sendPrompt
(
userPrompt
);
chats
=
await
db
.
getAllFromIndex
(
'
chats
'
,
'
timestamp
'
);
}
};
...
...
@@ -562,8 +678,8 @@
console
.
log
(
'
stopResponse
'
);
};
const
generateTitle
=
async
(
_chatId
,
userPrompt
)
=>
{
console
.
log
(
'
generateTitle
'
);
const
generate
Chat
Title
=
async
(
_chatId
,
userPrompt
)
=>
{
console
.
log
(
'
generate
Chat
Title
'
);
const
res
=
await
fetch
(
`
${
API_BASE_URL
}
/generate`
,
{
method
:
'
POST
'
,
...
...
@@ -586,12 +702,15 @@
});
if
(
res
)
{
console
.
log
(
res
);
await
setChatTitle
(
_chatId
,
res
.
response
===
''
?
'
New Chat
'
:
res
.
response
);
}
};
const
setChatTitle
=
async
(
_chatId
,
_title
)
=>
{
const
chat
=
await
db
.
get
(
'
chats
'
,
_chatId
);
await
db
.
put
(
'
chats
'
,
{
...
chat
,
title
:
res
.
response
===
''
?
'
New Chat
'
:
res
.
respons
e
});
await
db
.
put
(
'
chats
'
,
{
...
chat
,
title
:
_titl
e
});
if
(
chat
.
id
===
chatId
)
{
title
=
res
.
response
;
}
title
=
_title
;
}
};
</script>
...
...
@@ -669,7 +788,11 @@
<option
value=
""
selected
>
Select a model
</option>
{#each models as model}
{#if model.name === 'hr'}
<hr
/>
{:else}
<option
value=
{model.name}
>
{model.name}
</option>
{/if}
{/each}
</select>
<div
class=
"text-right mt-1.5 text-xs text-gray-500"
>
...
...
@@ -728,7 +851,7 @@
</div>
{:else}
<div
class=
"prose chat-{message.role} w-full max-w-full prose-invert prose-headings:my-0 prose-p:my-0 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-img:my-0 prose-ul:-my-4 prose-ol:-my-4 prose-li:-my-3 prose-ul:-mb-8 prose-ol:-mb-8 prose-li:-mb-4 whitespace-pre-line"
class=
"prose chat-{message.role} w-full max-w-full prose-invert prose-headings:my-0 prose-p:my-0
prose-p:-mb-4
prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-img:my-0 prose-ul:-my-4 prose-ol:-my-4 prose-li:-my-3 prose-ul:-mb-8 prose-ol:-mb-8 prose-li:-mb-4 whitespace-pre-line"
>
{#if message.role == 'user'}
{#if message?.edit === true}
...
...
@@ -948,7 +1071,6 @@
<textarea
class=
"rounded-xl bg-gray-700 outline-none w-full py-3 px-5 pr-12 resize-none"
placeholder=
"Send a message"
bind:this=
{textareaElement}
bind:value=
{prompt}
on:keypress=
{(e)
=
>
{
if (e.keyCode == 13
&&
!e.shiftKey) {
...
...
@@ -956,12 +1078,13 @@
}
if (prompt !== ''
&&
e.keyCode == 13
&&
!e.shiftKey) {
submitPrompt(prompt);
e.target.style.height = '';
}
}}
rows="1"
on:input={() => {
textareaElemen
t.style.height = '';
textareaElemen
t.style.height = Math.min(
textareaElemen
t.scrollHeight, 200) + 'px';
on:input={(
e
) => {
e.targe
t.style.height = '';
e.targe
t.style.height = Math.min(
e.targe
t.scrollHeight, 200) + 'px';
}}
/>
<div
class=
" absolute right-0 bottom-0"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment