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
9fefddd8
Commit
9fefddd8
authored
May 08, 2024
by
AnkurSachdeva22
Browse files
Merge branch 'main' of
https://github.com/AnkurSachdeva22/open-webui-hindi
parents
7dade071
0ed54055
Changes
90
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
352 additions
and
287 deletions
+352
-287
kubernetes/helm/values-minikube.yaml
kubernetes/helm/values-minikube.yaml
+0
-27
kubernetes/helm/values.yaml
kubernetes/helm/values.yaml
+0
-75
src/app.css
src/app.css
+9
-0
src/app.html
src/app.html
+6
-0
src/lib/apis/chats/index.ts
src/lib/apis/chats/index.ts
+19
-6
src/lib/apis/ollama/index.ts
src/lib/apis/ollama/index.ts
+6
-2
src/lib/apis/openai/index.ts
src/lib/apis/openai/index.ts
+4
-2
src/lib/apis/rag/index.ts
src/lib/apis/rag/index.ts
+3
-2
src/lib/apis/streaming/index.ts
src/lib/apis/streaming/index.ts
+11
-0
src/lib/components/ChangelogModal.svelte
src/lib/components/ChangelogModal.svelte
+2
-4
src/lib/components/admin/AddUserModal.svelte
src/lib/components/admin/AddUserModal.svelte
+1
-1
src/lib/components/chat/MessageInput/Documents.svelte
src/lib/components/chat/MessageInput/Documents.svelte
+1
-1
src/lib/components/chat/MessageInput/Suggestions.svelte
src/lib/components/chat/MessageInput/Suggestions.svelte
+5
-3
src/lib/components/chat/Messages/CitationsModal.svelte
src/lib/components/chat/Messages/CitationsModal.svelte
+77
-0
src/lib/components/chat/Messages/RateComment.svelte
src/lib/components/chat/Messages/RateComment.svelte
+1
-1
src/lib/components/chat/Messages/ResponseMessage.svelte
src/lib/components/chat/Messages/ResponseMessage.svelte
+199
-155
src/lib/components/chat/Messages/Skeleton.svelte
src/lib/components/chat/Messages/Skeleton.svelte
+1
-1
src/lib/components/chat/ModelSelector.svelte
src/lib/components/chat/ModelSelector.svelte
+1
-1
src/lib/components/chat/ModelSelector/Selector.svelte
src/lib/components/chat/ModelSelector/Selector.svelte
+4
-4
src/lib/components/chat/Settings/Account.svelte
src/lib/components/chat/Settings/Account.svelte
+2
-2
No files found.
kubernetes/helm/values-minikube.yaml
deleted
100644 → 0
View file @
7dade071
ollama
:
resources
:
requests
:
cpu
:
"
2000m"
memory
:
"
2Gi"
limits
:
cpu
:
"
4000m"
memory
:
"
4Gi"
nvidia.com/gpu
:
"
0"
service
:
type
:
ClusterIP
gpu
:
enabled
:
false
webui
:
resources
:
requests
:
cpu
:
"
500m"
memory
:
"
500Mi"
limits
:
cpu
:
"
1000m"
memory
:
"
1Gi"
ingress
:
enabled
:
true
host
:
open-webui.minikube.local
service
:
type
:
NodePort
kubernetes/helm/values.yaml
deleted
100644 → 0
View file @
7dade071
nameOverride
:
"
"
ollama
:
externalHost
:
"
"
annotations
:
{}
podAnnotations
:
{}
replicaCount
:
1
image
:
repository
:
ollama/ollama
tag
:
latest
pullPolicy
:
Always
resources
:
{}
persistence
:
enabled
:
true
size
:
30Gi
existingClaim
:
"
"
accessModes
:
-
ReadWriteOnce
storageClass
:
"
"
selector
:
{}
annotations
:
{}
nodeSelector
:
{}
# -- If using a special runtime container such as nvidia, set it here.
runtimeClassName
:
"
"
tolerations
:
-
key
:
nvidia.com/gpu
operator
:
Exists
effect
:
NoSchedule
service
:
type
:
ClusterIP
annotations
:
{}
port
:
80
containerPort
:
11434
gpu
:
# -- Enable additional ENV values to help Ollama discover GPU usage
enabled
:
false
webui
:
annotations
:
{}
podAnnotations
:
{}
replicaCount
:
1
image
:
repository
:
ghcr.io/open-webui/open-webui
tag
:
"
"
pullPolicy
:
Always
resources
:
{}
ingress
:
enabled
:
false
class
:
"
"
# -- Use appropriate annotations for your Ingress controller, e.g., for NGINX:
# nginx.ingress.kubernetes.io/rewrite-target: /
annotations
:
{}
host
:
"
"
tls
:
false
existingSecret
:
"
"
persistence
:
enabled
:
true
size
:
2Gi
existingClaim
:
"
"
# -- If using multiple replicas, you must update accessModes to ReadWriteMany
accessModes
:
-
ReadWriteOnce
storageClass
:
"
"
selector
:
{}
annotations
:
{}
nodeSelector
:
{}
tolerations
:
[]
service
:
type
:
ClusterIP
annotations
:
{}
port
:
80
containerPort
:
8080
nodePort
:
"
"
labels
:
{}
loadBalancerClass
:
"
"
src/app.css
View file @
9fefddd8
...
...
@@ -82,3 +82,12 @@ select {
.katex-mathml
{
display
:
none
;
}
.scrollbar-none
:active::-webkit-scrollbar-thumb
,
.scrollbar-none
:focus::-webkit-scrollbar-thumb
,
.scrollbar-none
:hover::-webkit-scrollbar-thumb
{
visibility
:
visible
;
}
.scrollbar-none
::-webkit-scrollbar-thumb
{
visibility
:
hidden
;
}
src/app.html
View file @
9fefddd8
...
...
@@ -6,6 +6,12 @@
<link
rel=
"manifest"
href=
"%sveltekit.assets%/manifest.json"
crossorigin=
"use-credentials"
/>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1, maximum-scale=1"
/>
<meta
name=
"robots"
content=
"noindex,nofollow"
/>
<link
rel=
"search"
type=
"application/opensearchdescription+xml"
title=
"Open WebUI"
href=
"/opensearch.xml"
/>
<script>
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
(()
=>
{
...
...
src/lib/apis/chats/index.ts
View file @
9fefddd8
import
{
WEBUI_API_BASE_URL
}
from
'
$lib/constants
'
;
import
{
getTimeRange
}
from
'
$lib/utils
'
;
export
const
createNewChat
=
async
(
token
:
string
,
chat
:
object
)
=>
{
let
error
=
null
;
...
...
@@ -59,7 +60,10 @@ export const getChatList = async (token: string = '') => {
throw
error
;
}
return
res
;
return
res
.
map
((
chat
)
=>
({
...
chat
,
time_range
:
getTimeRange
(
chat
.
updated_at
)
}));
};
export
const
getChatListByUserId
=
async
(
token
:
string
=
''
,
userId
:
string
)
=>
{
...
...
@@ -90,7 +94,10 @@ export const getChatListByUserId = async (token: string = '', userId: string) =>
throw
error
;
}
return
res
;
return
res
.
map
((
chat
)
=>
({
...
chat
,
time_range
:
getTimeRange
(
chat
.
updated_at
)
}));
};
export
const
getArchivedChatList
=
async
(
token
:
string
=
''
)
=>
{
...
...
@@ -220,13 +227,16 @@ export const getAllChatTags = async (token: string) => {
export
const
getChatListByTagName
=
async
(
token
:
string
=
''
,
tagName
:
string
)
=>
{
let
error
=
null
;
const
res
=
await
fetch
(
`
${
WEBUI_API_BASE_URL
}
/chats/tags
/tag/
${
tagName
}
`
,
{
method
:
'
GE
T
'
,
const
res
=
await
fetch
(
`
${
WEBUI_API_BASE_URL
}
/chats/tags`
,
{
method
:
'
POS
T
'
,
headers
:
{
Accept
:
'
application/json
'
,
'
Content-Type
'
:
'
application/json
'
,
...(
token
&&
{
authorization
:
`Bearer
${
token
}
`
})
}
},
body
:
JSON
.
stringify
({
name
:
tagName
})
})
.
then
(
async
(
res
)
=>
{
if
(
!
res
.
ok
)
throw
await
res
.
json
();
...
...
@@ -245,7 +255,10 @@ export const getChatListByTagName = async (token: string = '', tagName: string)
throw
error
;
}
return
res
;
return
res
.
map
((
chat
)
=>
({
...
chat
,
time_range
:
getTimeRange
(
chat
.
updated_at
)
}));
};
export
const
getChatById
=
async
(
token
:
string
,
id
:
string
)
=>
{
...
...
src/lib/apis/ollama/index.ts
View file @
9fefddd8
...
...
@@ -159,7 +159,11 @@ export const generateTitle = async (
body
:
JSON
.
stringify
({
model
:
model
,
prompt
:
template
,
stream
:
false
stream
:
false
,
options
:
{
// Restrict the number of tokens generated to 50
num_predict
:
50
}
})
})
.
then
(
async
(
res
)
=>
{
...
...
@@ -178,7 +182,7 @@ export const generateTitle = async (
throw
error
;
}
return
res
?.
response
??
'
New Chat
'
;
return
res
?.
response
.
replace
(
/
[
"'
]
/g
,
''
)
??
'
New Chat
'
;
};
export
const
generatePrompt
=
async
(
token
:
string
=
''
,
model
:
string
,
conversation
:
string
)
=>
{
...
...
src/lib/apis/openai/index.ts
View file @
9fefddd8
...
...
@@ -295,7 +295,9 @@ export const generateTitle = async (
content
:
template
}
],
stream
:
false
stream
:
false
,
// Restricting the max tokens to 50 to avoid long titles
max_tokens
:
50
})
})
.
then
(
async
(
res
)
=>
{
...
...
@@ -314,5 +316,5 @@ export const generateTitle = async (
throw
error
;
}
return
res
?.
choices
[
0
]?.
message
?.
content
??
'
New Chat
'
;
return
res
?.
choices
[
0
]?.
message
?.
content
.
replace
(
/
[
"'
]
/g
,
''
)
??
'
New Chat
'
;
};
src/lib/apis/rag/index.ts
View file @
9fefddd8
...
...
@@ -33,8 +33,9 @@ type ChunkConfigForm = {
};
type
RAGConfigForm
=
{
pdf_extract_images
:
boolean
;
chunk
:
ChunkConfigForm
;
pdf_extract_images
?:
boolean
;
chunk
?:
ChunkConfigForm
;
web_loader_ssl_verification
?:
boolean
;
};
export
const
updateRAGConfig
=
async
(
token
:
string
,
payload
:
RAGConfigForm
)
=>
{
...
...
src/lib/apis/streaming/index.ts
View file @
9fefddd8
...
...
@@ -4,6 +4,8 @@ import type { ParsedEvent } from 'eventsource-parser';
type
TextStreamUpdate
=
{
done
:
boolean
;
value
:
string
;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
citations
?:
any
;
};
// createOpenAITextStream takes a responseBody with a SSE response,
...
...
@@ -45,6 +47,11 @@ async function* openAIStreamToIterator(
const
parsedData
=
JSON
.
parse
(
data
);
console
.
log
(
parsedData
);
if
(
parsedData
.
citations
)
{
yield
{
done
:
false
,
value
:
''
,
citations
:
parsedData
.
citations
};
continue
;
}
yield
{
done
:
false
,
value
:
parsedData
.
choices
?.[
0
]?.
delta
?.
content
??
''
};
}
catch
(
e
)
{
console
.
error
(
'
Error extracting delta from SSE event:
'
,
e
);
...
...
@@ -62,6 +69,10 @@ async function* streamLargeDeltasAsRandomChunks(
yield
textStreamUpdate
;
return
;
}
if
(
textStreamUpdate
.
citations
)
{
yield
textStreamUpdate
;
continue
;
}
let
content
=
textStreamUpdate
.
value
;
if
(
content
.
length
<
5
)
{
yield
{
done
:
false
,
value
:
content
};
...
...
src/lib/components/ChangelogModal.svelte
View file @
9fefddd8
...
...
@@ -22,7 +22,7 @@
</script>
<Modal bind:show>
<div class="px-5 p
y
-4 dark:text-gray-300 text-gray-700">
<div class="px-5 p
t
-4 dark:text-gray-300 text-gray-700">
<div class="flex justify-between items-start">
<div class="text-xl font-bold">
{$i18n.t('What’s New in')}
...
...
@@ -57,10 +57,8 @@
</div>
</div>
<hr class=" dark:border-gray-800" />
<div class=" w-full p-4 px-5 text-gray-700 dark:text-gray-100">
<div class=" overflow-y-scroll max-h-80">
<div class=" overflow-y-scroll max-h-80
scrollbar-none
">
<div class="mb-3">
{#if changelog}
{#each Object.keys(changelog) as version}
...
...
src/lib/components/admin/AddUserModal.svelte
View file @
9fefddd8
...
...
@@ -107,7 +107,7 @@
reader.readAsText(file);
} else {
toast.error(
`
File not found.
`
);
toast.error(
$i18n.t('
File not found.
')
);
}
}
};
...
...
src/lib/components/chat/MessageInput/Documents.svelte
View file @
9fefddd8
...
...
@@ -24,7 +24,7 @@
{
name: 'All Documents',
type: 'collection',
title: 'All Documents',
title:
$i18n.t(
'All Documents'
)
,
collection_names: $documents.map((doc) => doc.collection_name)
}
]
...
...
src/lib/components/chat/MessageInput/Suggestions.svelte
View file @
9fefddd8
<script lang="ts">
import Bolt from '$lib/components/icons/Bolt.svelte';
import { onMount } from 'svelte';
import { onMount, getContext } from 'svelte';
const i18n = getContext('i18n');
export let submitPrompt: Function;
export let suggestionPrompts = [];
...
...
@@ -33,7 +35,7 @@
{#if prompts.length > 0}
<div class="mb-2 flex gap-1 text-sm font-medium items-center text-gray-400 dark:text-gray-600">
<Bolt />
Suggested
{$i18n.t('
Suggested
')}
</div>
{/if}
...
...
@@ -71,7 +73,7 @@
<div
class="text-xs text-gray-400 group-hover:text-gray-500 dark:text-gray-600 dark:group-hover:text-gray-500 transition self-center"
>
Prompt
{$i18n.t('
Prompt
')}
</div>
<div
...
...
src/lib/components/chat/Messages/CitationsModal.svelte
0 → 100644
View file @
9fefddd8
<script lang="ts">
import { getContext, onMount, tick } from 'svelte';
import Modal from '$lib/components/common/Modal.svelte';
const i18n = getContext('i18n');
export let show = false;
export let citation;
let mergedDocuments = [];
$: if (citation) {
mergedDocuments = citation.document?.map((c, i) => {
return {
source: citation.source,
document: c,
metadata: citation.metadata?.[i]
};
});
}
</script>
<Modal size="lg" bind:show>
<div>
<div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-2">
<div class=" text-lg font-medium self-center capitalize">
{$i18n.t('Citation')}
</div>
<button
class="self-center"
on:click={() => {
show = false;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-5 h-5"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
<div class="flex flex-col md:flex-row w-full px-6 pb-5 md:space-x-4">
<div
class="flex flex-col w-full dark:text-gray-200 overflow-y-scroll max-h-[22rem] scrollbar-none"
>
{#each mergedDocuments as document, documentIdx}
<div class="flex flex-col w-full">
<div class="text-sm font-medium dark:text-gray-300">
{$i18n.t('Source')}
</div>
<div class="text-sm dark:text-gray-400">
{document.source?.name ?? $i18n.t('No source available')}
</div>
</div>
<div class="flex flex-col w-full">
<div class=" text-sm font-medium dark:text-gray-300">
{$i18n.t('Content')}
</div>
<pre class="text-sm dark:text-gray-400 whitespace-pre-line">
{document.document}
</pre>
</div>
{#if documentIdx !== mergedDocuments.length - 1}
<hr class=" dark:border-gray-850 my-3" />
{/if}
{/each}
</div>
</div>
</div>
</Modal>
src/lib/components/chat/Messages/RateComment.svelte
View file @
9fefddd8
...
...
@@ -123,7 +123,7 @@
submitHandler();
}}
>
Submit
{$i18n.t('
Submit
')}
</button>
</div>
</div>
src/lib/components/chat/Messages/ResponseMessage.svelte
View file @
9fefddd8
...
...
@@ -23,15 +23,16 @@
revertSanitizedResponseContent,
sanitizeResponseContent
} from '$lib/utils';
import { WEBUI_BASE_URL } from '$lib/constants';
import Name from './Name.svelte';
import ProfileImage from './ProfileImage.svelte';
import Skeleton from './Skeleton.svelte';
import CodeBlock from './CodeBlock.svelte';
import Image from '$lib/components/common/Image.svelte';
import { WEBUI_BASE_URL } from '$lib/constants';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import RateComment from './RateComment.svelte';
import CitationsModal from '$lib/components/chat/Messages/CitationsModal.svelte';
export let modelfiles = [];
export let message;
...
...
@@ -65,6 +66,9 @@
let showRateComment = false;
let showCitationModal = false;
let selectedCitation = null;
$: tokens = marked.lexer(sanitizeResponseContent(message.content));
const renderer = new marked.Renderer();
...
...
@@ -324,6 +328,8 @@
});
</script>
<CitationsModal bind:show={showCitationModal} citation={selectedCitation} />
{#key message.id}
<div class=" flex w-full message-{message.id}" id="message-{message.id}">
<ProfileImage
...
...
@@ -346,154 +352,192 @@
{/if}
</Name>
{#if message.content === ''}
<Skeleton />
{:else}
{#if message.files}
<div class="my-2.5 w-full flex overflow-x-auto gap-2 flex-wrap">
{#each message.files as file}
<div>
{#if file.type === 'image'}
<Image src={file.url} />
{/if}
</div>
{/each}
</div>
{/if}
{#if message.files}
<div class="my-2.5 w-full flex overflow-x-auto gap-2 flex-wrap">
{#each message.files as file}
<div>
{#if file.type === 'image'}
<Image src={file.url} />
{/if}
</div>
{/each}
</div>
{/if}
<div
class="prose chat-{message.role} w-full max-w-full dark:prose-invert prose-headings:my-0 prose-p:m-0 prose-p:-mb-6 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-6 prose-ol:-mb-8 prose-ol:p-0 prose-li:-mb-4 whitespace-pre-line"
>
<div>
{#if edit === true}
<div class=" w-full">
<textarea
id="message-edit-{message.id}"
bind:this={editTextAreaElement}
class=" bg-transparent outline-none w-full resize-none"
bind:value={editedContent}
on:input={(e) => {
e.target.style.height = '';
e.target.style.height = `${e.target.scrollHeight}px`;
<div
class="prose chat-{message.role} w-full max-w-full dark:prose-invert prose-headings:my-0 prose-p:m-0 prose-p:-mb-6 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-6 prose-ol:-mb-8 prose-ol:p-0 prose-li:-mb-4 whitespace-pre-line"
>
<div>
{#if edit === true}
<div class=" w-full">
<textarea
id="message-edit-{message.id}"
bind:this={editTextAreaElement}
class=" bg-transparent outline-none w-full resize-none"
bind:value={editedContent}
on:input={(e) => {
e.target.style.height = '';
e.target.style.height = `${e.target.scrollHeight}px`;
}}
/>
<div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium">
<button
class="px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
on:click={() => {
editMessageConfirmHandler();
}}
/>
<div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium">
<button
class="px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
on:click={() => {
editMessageConfirmHandler();
}}
>
{$i18n.t('Save')}
</button>
<button
class=" px-4 py-2 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-100 transition outline outline-1 outline-gray-200 dark:outline-gray-600 rounded-lg"
on:click={() => {
cancelEditMessage();
}}
>
{$i18n.t('Cancel')}
</button>
</div>
>
{$i18n.t('Save')}
</button>
<button
class=" px-4 py-2 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-100 transition outline outline-1 outline-gray-200 dark:outline-gray-600 rounded-lg"
on:click={() => {
cancelEditMessage();
}}
>
{$i18n.t('Cancel')}
</button>
</div>
{:else}
<div class="w-full">
{#if message?.error === true}
<div
class="flex mt-2 mb-4 space-x-2 border px-4 py-3 border-red-800 bg-red-800/30 font-medium rounded-lg"
</div>
{:else}
<div class="w-full">
{#if message?.error === true}
<div
class="flex mt-2 mb-4 space-x-2 border px-4 py-3 border-red-800 bg-red-800/30 font-medium rounded-lg"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-5 h-5 self-center"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-5 h-5 self-center"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
/>
</svg>
<div class=" self-center">
{message.content}
</div>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
/>
</svg>
<div class=" self-center">
{message.content}
</div>
{:else}
{#each tokens as token}
{#if token.type === 'code'}
<CodeBlock
lang={token.lang}
code={revertSanitizedResponseContent(token.text)}
/>
{:else}
{@html marked.parse(token.raw, {
...defaults,
gfm: true,
breaks: true,
renderer
})}
{/if}
{/each}
<!-- {@html marked(message.content.replaceAll('\\', '\\\\'))} -->
{/if}
</div>
{:else if message.content === ''}
<Skeleton />
{:else}
{#each tokens as token}
{#if token.type === 'code'}
<CodeBlock
lang={token.lang}
code={revertSanitizedResponseContent(token.text)}
/>
{:else}
{@html marked.parse(token.raw, {
...defaults,
gfm: true,
breaks: true,
renderer
})}
{/if}
{/each}
<!-- {@html marked(message.content.replaceAll('\\', '\\\\'))} -->
{/if}
{#if message.citations}
<hr class=" dark:border-gray-800 my-1" />
<div class="my-2.5 w-full flex flex-col gap-1">
{#each message.citations.reduce((acc, citation) => {
citation.document.forEach((document, index) => {
const metadata = citation.metadata?.[index];
const id = metadata?.source ?? 'N/A';
const existingSource = acc.find((item) => item.id === id);
if (existingSource) {
existingSource.document.push(document);
existingSource.metadata.push(metadata);
} else {
acc.push( { id: id, source: citation?.source, document: [document], metadata: metadata ? [metadata] : [] } );
}
});
return acc;
}, []) as citation, idx}
<div class="flex gap-1 text-xs font-semibold">
<div>
[{idx + 1}]
</div>
{#if message.done}
<div
class=" flex justify-start space-x-1 overflow-x-auto buttons text-gray-700 dark:text-gray-500"
>
{#if siblings.length > 1}
<div class="flex self-center min-w-fit">
<button
class="self-center dark:hover:text-white hover:text-black transition"
on:click={() => {
showPreviousMessage(message);
}}
<button
class="dark:text-gray-500 underline"
on:click={() => {
showCitationModal = true;
selectedCitation = citation;
}}
>
{citation.source.name}
</button>
</div>
{/each}
</div>
{/if}
{#if message.done || siblings.length > 1}
<div
class=" flex justify-start space-x-1 overflow-x-auto buttons text-gray-700 dark:text-gray-500"
>
{#if siblings.length > 1}
<div class="flex self-center min-w-fit">
<button
class="self-center dark:hover:text-white hover:text-black transition"
on:click={() => {
showPreviousMessage(message);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
clip-rule="evenodd"
/>
</svg>
</button>
<path
fill-rule="evenodd"
d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
clip-rule="evenodd"
/>
</svg>
</button>
<div class="text-xs font-bold self-center min-w-fit dark:text-gray-100">
{siblings.indexOf(message.id) + 1} / {siblings.length}
</div>
<div class="text-xs font-bold self-center min-w-fit dark:text-gray-100">
{siblings.indexOf(message.id) + 1} / {siblings.length}
</div>
<button
class="self-center dark:hover:text-white hover:text-black transition"
on:click={() => {
showNextMessage(message);
}}
<button
class="self-center dark:hover:text-white hover:text-black transition"
on:click={() => {
showNextMessage(message);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
clip-rule="evenodd"
/>
</svg>
</button>
</div>
{/if}
<path
fill-rule="evenodd"
d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
clip-rule="evenodd"
/>
</svg>
</button>
</div>
{/if}
{#if message.done}
{#if !readOnly}
<Tooltip content={$i18n.t('Edit')} placement="bottom">
<button
...
...
@@ -854,24 +898,24 @@
</button>
</Tooltip>
{/if}
</div>
{/if}
{#if showRateComment}
<
RateComment
messageId={message.id}
bind:show={showRateComment
}
bind:
message
on:submit={() => {
updateChatMessages();
}}
/>
{/if}
</div>
{/if}
</div>
{/if}
</div>
{/if}
{#if show
RateComment
}
<RateComment
messageId={message.id
}
bind:
show={showRateComment}
bind:message
on:submit={() => {
updateChatMessages();
}}
/>
{/if}
</div>
{/if}
</div>
{/if}
</div>
</div>
</div>
{/key}
...
...
src/lib/components/chat/Messages/Skeleton.svelte
View file @
9fefddd8
<div class="w-full mt-3">
<div class="w-full mt-3
mb-4
">
<div class="animate-pulse flex w-full">
<div class="space-y-2 w-full">
<div class="h-2 bg-gray-200 dark:bg-gray-600 rounded mr-14" />
...
...
src/lib/components/chat/ModelSelector.svelte
View file @
9fefddd8
...
...
@@ -82,7 +82,7 @@
</div>
{:else}
<div class=" self-center disabled:text-gray-600 disabled:hover:text-gray-600 mr-2">
<Tooltip content=
"
Remove Model
"
>
<Tooltip content=
{$i18n.t('
Remove Model
')}
>
<button
{disabled}
on:click={() => {
...
...
src/lib/components/chat/ModelSelector/Selector.svelte
View file @
9fefddd8
...
...
@@ -151,7 +151,7 @@
models.set(await getModels(localStorage.token));
} else {
toast.error('Download canceled');
toast.error(
$i18n.t(
'Download canceled')
)
;
}
delete $MODEL_DOWNLOAD_POOL[sanitizedModelTag];
...
...
@@ -305,7 +305,7 @@
{:else}
<div>
<div class="block px-3 py-2 text-sm text-gray-700 dark:text-gray-100">
No results found
{$i18n.t('
No results found
')}
</div>
</div>
{/each}
...
...
@@ -317,7 +317,7 @@
pullModelHandler();
}}
>
Pull "{searchValue}" from Ollama.com
{$i18n.t(`
Pull "{
{
searchValue}
}
" from Ollama.com
`, { searchValue: searchValue })}
</button>
{/if}
...
...
@@ -368,7 +368,7 @@
</div>
<div class="mr-2 translate-y-0.5">
<Tooltip content=
"
Cancel
"
>
<Tooltip content=
{$i18n.t('
Cancel
')}
>
<button
class="text-gray-800 dark:text-gray-100"
on:click={() => {
...
...
src/lib/components/chat/Settings/Account.svelte
View file @
9fefddd8
...
...
@@ -447,7 +447,7 @@
{/if}
</button>
<Tooltip content=
"
Create new key
"
>
<Tooltip content=
{$i18n.t('
Create new key
')}
>
<button
class=" px-1.5 py-1 dark:hover:bg-gray-850transition rounded-lg"
on:click={() => {
...
...
@@ -479,7 +479,7 @@
>
<Plus strokeWidth="2" className=" size-3.5" />
Create new secret key</button
{$i18n.t('
Create new secret key
')}
</button
>
{/if}
</div>
...
...
Prev
1
2
3
4
5
Next
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