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
e98cb452
Unverified
Commit
e98cb452
authored
May 06, 2024
by
Timothy Jaeryang Baek
Committed by
GitHub
May 06, 2024
Browse files
Merge pull request #2011 from cheahjs/feat/rag-citations
feat: show RAG query results as citations
parents
ba09fcd5
c84e0aa2
Changes
35
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
690 additions
and
469 deletions
+690
-469
backend/apps/rag/utils.py
backend/apps/rag/utils.py
+27
-22
backend/config.py
backend/config.py
+12
-10
backend/main.py
backend/main.py
+36
-3
src/lib/apis/streaming/index.ts
src/lib/apis/streaming/index.ts
+11
-0
src/lib/components/chat/Messages/CitationsModal.svelte
src/lib/components/chat/Messages/CitationsModal.svelte
+75
-0
src/lib/components/chat/Messages/ResponseMessage.svelte
src/lib/components/chat/Messages/ResponseMessage.svelte
+473
-420
src/lib/i18n/locales/ar-BH/translation.json
src/lib/i18n/locales/ar-BH/translation.json
+4
-1
src/lib/i18n/locales/bg-BG/translation.json
src/lib/i18n/locales/bg-BG/translation.json
+4
-1
src/lib/i18n/locales/bn-BD/translation.json
src/lib/i18n/locales/bn-BD/translation.json
+4
-1
src/lib/i18n/locales/ca-ES/translation.json
src/lib/i18n/locales/ca-ES/translation.json
+4
-1
src/lib/i18n/locales/de-DE/translation.json
src/lib/i18n/locales/de-DE/translation.json
+4
-1
src/lib/i18n/locales/dg-DG/translation.json
src/lib/i18n/locales/dg-DG/translation.json
+4
-1
src/lib/i18n/locales/en-GB/translation.json
src/lib/i18n/locales/en-GB/translation.json
+4
-1
src/lib/i18n/locales/en-US/translation.json
src/lib/i18n/locales/en-US/translation.json
+4
-1
src/lib/i18n/locales/es-ES/translation.json
src/lib/i18n/locales/es-ES/translation.json
+4
-1
src/lib/i18n/locales/fa-IR/translation.json
src/lib/i18n/locales/fa-IR/translation.json
+4
-1
src/lib/i18n/locales/fr-CA/translation.json
src/lib/i18n/locales/fr-CA/translation.json
+4
-1
src/lib/i18n/locales/fr-FR/translation.json
src/lib/i18n/locales/fr-FR/translation.json
+4
-1
src/lib/i18n/locales/it-IT/translation.json
src/lib/i18n/locales/it-IT/translation.json
+4
-1
src/lib/i18n/locales/ja-JP/translation.json
src/lib/i18n/locales/ja-JP/translation.json
+4
-1
No files found.
backend/apps/rag/utils.py
View file @
e98cb452
...
...
@@ -271,14 +271,14 @@ def rag_messages(
for
doc
in
docs
:
context
=
None
collection
=
doc
.
get
(
"collection_name"
)
if
collection
:
collection
=
[
collection
]
else
:
collection
=
doc
.
get
(
"collection_names"
,
[]
)
collection
_names
=
(
doc
[
"
collection
_names"
]
if
doc
[
"type"
]
=
=
"
collection
"
else
[
doc
[
"collection_name"
]]
)
collection
=
set
(
collection
).
difference
(
extracted_collections
)
if
not
collection
:
collection
_names
=
set
(
collection
_names
).
difference
(
extracted_collections
)
if
not
collection
_names
:
log
.
debug
(
f
"skipping
{
doc
}
as it has already been extracted"
)
continue
...
...
@@ -288,11 +288,7 @@ def rag_messages(
else
:
if
hybrid_search
:
context
=
query_collection_with_hybrid_search
(
collection_names
=
(
doc
[
"collection_names"
]
if
doc
[
"type"
]
==
"collection"
else
[
doc
[
"collection_name"
]]
),
collection_names
=
collection_names
,
query
=
query
,
embedding_function
=
embedding_function
,
k
=
k
,
...
...
@@ -301,11 +297,7 @@ def rag_messages(
)
else
:
context
=
query_collection
(
collection_names
=
(
doc
[
"collection_names"
]
if
doc
[
"type"
]
==
"collection"
else
[
doc
[
"collection_name"
]]
),
collection_names
=
collection_names
,
query
=
query
,
embedding_function
=
embedding_function
,
k
=
k
,
...
...
@@ -315,18 +307,31 @@ def rag_messages(
context
=
None
if
context
:
relevant_contexts
.
append
(
context
)
relevant_contexts
.
append
(
{
**
context
,
"source"
:
doc
}
)
extracted_collections
.
extend
(
collection
)
extracted_collections
.
extend
(
collection
_names
)
context_string
=
""
citations
=
[]
for
context
in
relevant_contexts
:
try
:
if
"documents"
in
context
:
items
=
[
item
for
item
in
context
[
"documents"
][
0
]
if
item
is
not
None
]
context_string
+=
"
\n\n
"
.
join
(
items
)
context_string
+=
"
\n\n
"
.
join
(
[
text
for
text
in
context
[
"documents"
][
0
]
if
text
is
not
None
]
)
if
"metadatas"
in
context
:
citations
.
append
(
{
"source"
:
context
[
"source"
],
"document"
:
context
[
"documents"
][
0
],
"metadata"
:
context
[
"metadatas"
][
0
],
}
)
except
Exception
as
e
:
log
.
exception
(
e
)
context_string
=
context_string
.
strip
()
ra_content
=
rag_template
(
...
...
@@ -355,7 +360,7 @@ def rag_messages(
messages
[
last_user_message_idx
]
=
new_user_message
return
messages
return
messages
,
citations
def
get_model_path
(
model
:
str
,
update_model
:
bool
=
False
):
...
...
backend/config.py
View file @
e98cb452
...
...
@@ -18,6 +18,18 @@ from secrets import token_bytes
from
constants
import
ERROR_MESSAGES
####################################
# Load .env file
####################################
try
:
from
dotenv
import
load_dotenv
,
find_dotenv
load_dotenv
(
find_dotenv
(
"../.env"
))
except
ImportError
:
print
(
"dotenv not installed, skipping..."
)
####################################
# LOGGING
####################################
...
...
@@ -59,16 +71,6 @@ for source in log_sources:
log
.
setLevel
(
SRC_LOG_LEVELS
[
"CONFIG"
])
####################################
# Load .env file
####################################
try
:
from
dotenv
import
load_dotenv
,
find_dotenv
load_dotenv
(
find_dotenv
(
"../.env"
))
except
ImportError
:
log
.
warning
(
"dotenv not installed, skipping..."
)
WEBUI_NAME
=
os
.
environ
.
get
(
"WEBUI_NAME"
,
"Open WebUI"
)
if
WEBUI_NAME
!=
"Open WebUI"
:
...
...
backend/main.py
View file @
e98cb452
...
...
@@ -15,7 +15,7 @@ from fastapi.middleware.wsgi import WSGIMiddleware
from
fastapi.middleware.cors
import
CORSMiddleware
from
starlette.exceptions
import
HTTPException
as
StarletteHTTPException
from
starlette.middleware.base
import
BaseHTTPMiddleware
from
starlette.responses
import
StreamingResponse
from
apps.ollama.main
import
app
as
ollama_app
from
apps.openai.main
import
app
as
openai_app
...
...
@@ -102,6 +102,8 @@ origins = ["*"]
class
RAGMiddleware
(
BaseHTTPMiddleware
):
async
def
dispatch
(
self
,
request
:
Request
,
call_next
):
return_citations
=
False
if
request
.
method
==
"POST"
and
(
"/api/chat"
in
request
.
url
.
path
or
"/chat/completions"
in
request
.
url
.
path
):
...
...
@@ -114,11 +116,15 @@ class RAGMiddleware(BaseHTTPMiddleware):
# Parse string to JSON
data
=
json
.
loads
(
body_str
)
if
body_str
else
{}
return_citations
=
data
.
get
(
"citations"
,
False
)
if
"citations"
in
data
:
del
data
[
"citations"
]
# Example: Add a new key-value pair or modify existing ones
# data["modified"] = True # Example modification
if
"docs"
in
data
:
data
=
{
**
data
}
data
[
"messages"
]
=
rag_messages
(
data
[
"messages"
]
,
citations
=
rag_messages
(
docs
=
data
[
"docs"
],
messages
=
data
[
"messages"
],
template
=
rag_app
.
state
.
RAG_TEMPLATE
,
...
...
@@ -130,7 +136,9 @@ class RAGMiddleware(BaseHTTPMiddleware):
)
del
data
[
"docs"
]
log
.
debug
(
f
"data['messages']:
{
data
[
'messages'
]
}
"
)
log
.
debug
(
f
"data['messages']:
{
data
[
'messages'
]
}
, citations:
{
citations
}
"
)
modified_body_bytes
=
json
.
dumps
(
data
).
encode
(
"utf-8"
)
...
...
@@ -148,11 +156,36 @@ class RAGMiddleware(BaseHTTPMiddleware):
]
response
=
await
call_next
(
request
)
if
return_citations
:
# Inject the citations into the response
if
isinstance
(
response
,
StreamingResponse
):
# If it's a streaming response, inject it as SSE event or NDJSON line
content_type
=
response
.
headers
.
get
(
"Content-Type"
)
if
"text/event-stream"
in
content_type
:
return
StreamingResponse
(
self
.
openai_stream_wrapper
(
response
.
body_iterator
,
citations
),
)
if
"application/x-ndjson"
in
content_type
:
return
StreamingResponse
(
self
.
ollama_stream_wrapper
(
response
.
body_iterator
,
citations
),
)
return
response
async
def
_receive
(
self
,
body
:
bytes
):
return
{
"type"
:
"http.request"
,
"body"
:
body
,
"more_body"
:
False
}
async
def
openai_stream_wrapper
(
self
,
original_generator
,
citations
):
yield
f
"data:
{
json
.
dumps
(
{
'citations'
:
citations
}
)
}
\n\n
"
async
for
data
in
original_generator
:
yield
data
async
def
ollama_stream_wrapper
(
self
,
original_generator
,
citations
):
yield
f
"
{
json
.
dumps
(
{
'citations'
:
citations
}
)
}
\n
"
async
for
data
in
original_generator
:
yield
data
app
.
add_middleware
(
RAGMiddleware
)
...
...
src/lib/apis/streaming/index.ts
View file @
e98cb452
...
...
@@ -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/chat/Messages/CitationsModal.svelte
0 → 100644
View file @
e98cb452
<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-5 pb-5 md:space-x-4">
<div class="flex flex-col w-full dark:text-gray-200 overflow-y-scroll max-h-[22rem]">
{#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/ResponseMessage.svelte
View file @
e98cb452
...
...
@@ -32,6 +32,7 @@
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
...
...
@@ -360,7 +366,6 @@
{/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"
>
...
...
@@ -441,6 +446,66 @@
{/each}
<!-- {@html marked(message.content.replaceAll('\\', '\\\\'))} -->
{/if}
</div>
{/if}
</div>
</div>
<!-- if (message.citations) {
citations = message.citations.forEach((citation) => {
citation.document.forEach((document, index) => {
const metadata = citation.metadata?.[index];
const source = citation?.source?.name ?? metadata?.source ?? 'N/A';
citations[source] = citations[source] || {
source: citation.source,
document: [],
metadata: []
};
citations[source].document.push(document);
citations[source].metadata.push(metadata);
});
});
} -->
{#if message.citations}
<hr class=" dark:border-gray-800" />
<div class="my-2.5 w-full flex overflow-x-auto gap-2 flex-wrap">
{#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>
<button
class="dark:text-gray-500 underline"
on:click={() => {
showCitationModal = true;
selectedCitation = citation;
}}
>
{citation.source.name}
</button>
</div>
{/each}
</div>
{/if}
{#if message.done}
<div
...
...
@@ -553,8 +618,8 @@
<button
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded {message?.annotation
?.rating ===
1
: 'invisible group-hover:visible'} p-1 rounded {message?.annotation
?.rating ===
1
? 'bg-gray-100 dark:bg-gray-800'
: ''} dark:hover:text-white hover:text-black transition"
on:click={() => {
...
...
@@ -562,9 +627,7 @@
showRateComment = true;
window.setTimeout(() => {
document
.getElementById(`message-feedback-${message.id}`)
?.scrollIntoView();
document.getElementById(`message-feedback-${message.id}`)?.scrollIntoView();
}, 0);
}}
>
...
...
@@ -577,10 +640,11 @@
stroke-linejoin="round"
class="w-4 h-4"
xmlns="http://www.w3.org/2000/svg"
><path
d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"
/></svg
>
<path
d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"
/>
</svg>
</button>
</Tooltip>
...
...
@@ -588,17 +652,15 @@
<button
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded {message?.annotation
?.rating ===
-1
: 'invisible group-hover:visible'} p-1 rounded {message?.annotation
?.rating ===
-1
? 'bg-gray-100 dark:bg-gray-800'
: ''} dark:hover:text-white hover:text-black transition"
on:click={() => {
rateMessage(message.id, -1);
showRateComment = true;
window.setTimeout(() => {
document
.getElementById(`message-feedback-${message.id}`)
?.scrollIntoView();
document.getElementById(`message-feedback-${message.id}`)?.scrollIntoView();
}, 0);
}}
>
...
...
@@ -611,10 +673,11 @@
stroke-linejoin="round"
class="w-4 h-4"
xmlns="http://www.w3.org/2000/svg"
><path
d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"
/></svg
>
<path
d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"
/>
</svg>
</button>
</Tooltip>
{/if}
...
...
@@ -637,35 +700,32 @@
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
><style>
>
<style>
.spinner_S1WN {
animation: spinner_MGfb 0.8s linear infinite;
animation-delay: -0.8s;
}
.spinner_Km9P {
animation-delay: -0.65s;
}
.spinner_JApP {
animation-delay: -0.5s;
}
@keyframes spinner_MGfb {
93.75%,
100% {
opacity: 0.2;
}
}
</style><circle class="spinner_S1WN" cx="4" cy="12" r="3" /><circle
class="spinner_S1WN spinner_Km9P"
cx="12"
cy="12"
r="3"
/><circle
class="spinner_S1WN spinner_JApP"
cx="20"
cy="12"
r="3"
/></svg
>
</style>
<circle class="spinner_S1WN" cx="4" cy="12" r="3" />
<circle class="spinner_S1WN spinner_Km9P" cx="12" cy="12" r="3" />
<circle class="spinner_S1WN spinner_JApP" cx="20" cy="12" r="3" />
</svg>
{:else if speaking}
<svg
xmlns="http://www.w3.org/2000/svg"
...
...
@@ -718,35 +778,32 @@
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
><style>
>
<style>
.spinner_S1WN {
animation: spinner_MGfb 0.8s linear infinite;
animation-delay: -0.8s;
}
.spinner_Km9P {
animation-delay: -0.65s;
}
.spinner_JApP {
animation-delay: -0.5s;
}
@keyframes spinner_MGfb {
93.75%,
100% {
opacity: 0.2;
}
}
</style><circle class="spinner_S1WN" cx="4" cy="12" r="3" /><circle
class="spinner_S1WN spinner_Km9P"
cx="12"
cy="12"
r="3"
/><circle
class="spinner_S1WN spinner_JApP"
cx="20"
cy="12"
r="3"
/></svg
>
</style>
<circle class="spinner_S1WN" cx="4" cy="12" r="3" />
<circle class="spinner_S1WN spinner_Km9P" cx="12" cy="12" r="3" />
<circle class="spinner_S1WN spinner_JApP" cx="20" cy="12" r="3" />
</svg>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
...
...
@@ -867,10 +924,6 @@
}}
/>
{/if}
</div>
{/if}
</div>
</div>
{/if}
</div>
</div>
...
...
src/lib/i18n/locales/ar-BH/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"Chunk تداخل"
,
"Chunk Params"
:
"Chunk المتغيرات"
,
"Chunk Size"
:
"Chunk حجم"
,
"Citation"
:
""
,
"Click here for help."
:
"أضغط هنا للمساعدة"
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"انقر هنا للتحقق من ملفات الموديلات الأخرى."
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"دردشة جديدة"
,
"New Password"
:
"كلمة المرور الجديدة"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
"ليس صحيحا من حيث الواقع"
,
"Not sure what to add?"
:
"لست متأكدا ما يجب إضافته؟"
,
"Not sure what to write? Switch to"
:
"لست متأكدا ماذا أكتب؟ التبديل إلى"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"تسجيل الخروج"
,
"Sign up"
:
"تسجيل"
,
"Signing in"
:
"جاري الدخول"
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"خطأ في التعرف على الكلام: {{error}}"
,
"Speech-to-Text Engine"
:
"محرك تحويل الكلام إلى نص"
,
"SpeechRecognition API is not supported in this browser."
:
"API SpeechRecognition غير مدعومة في هذا المتصفح."
,
...
...
src/lib/i18n/locales/bg-BG/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"Chunk Overlap"
,
"Chunk Params"
:
"Chunk Params"
,
"Chunk Size"
:
"Chunk Size"
,
"Citation"
:
""
,
"Click here for help."
:
"Натиснете тук за помощ."
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"Натиснете тук за проверка на други моделфайлове."
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"Нов чат"
,
"New Password"
:
"Нова парола"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
"Не сте сигурни, какво да добавите?"
,
"Not sure what to write? Switch to"
:
"Не сте сигурни, какво да напишете? Превключете към"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"Изход"
,
"Sign up"
:
"Регистрация"
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"Speech recognition error: {{error}}"
,
"Speech-to-Text Engine"
:
"Speech-to-Text Engine"
,
"SpeechRecognition API is not supported in this browser."
:
"SpeechRecognition API is not supported in this browser."
,
...
...
src/lib/i18n/locales/bn-BD/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"চাঙ্ক ওভারল্যাপ"
,
"Chunk Params"
:
"চাঙ্ক প্যারামিটার্স"
,
"Chunk Size"
:
"চাঙ্ক সাইজ"
,
"Citation"
:
""
,
"Click here for help."
:
"সাহায্যের জন্য এখানে ক্লিক করুন"
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"অন্যান্য মডেলফাইল চেক করার জন্য এখানে ক্লিক করুন"
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"নতুন চ্যাট"
,
"New Password"
:
"নতুন পাসওয়ার্ড"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
"কী যুক্ত করতে হবে নিশ্চিত না?"
,
"Not sure what to write? Switch to"
:
"কী লিখতে হবে নিশ্চিত না? পরিবর্তন করুন:"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"সাইন আউট"
,
"Sign up"
:
"সাইন আপ"
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"স্পিচ রিকগনিশনে সমস্যা: {{error}}"
,
"Speech-to-Text Engine"
:
"স্পিচ-টু-টেক্সট ইঞ্জিন"
,
"SpeechRecognition API is not supported in this browser."
:
"এই ব্রাউজার স্পিচরিকগনিশন এপিআই সাপোর্ট করে না।"
,
...
...
src/lib/i18n/locales/ca-ES/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"Solapament de Blocs"
,
"Chunk Params"
:
"Paràmetres de Blocs"
,
"Chunk Size"
:
"Mida del Bloc"
,
"Citation"
:
""
,
"Click here for help."
:
"Fes clic aquí per ajuda."
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"Fes clic aquí per comprovar altres fitxers de model."
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"Xat Nou"
,
"New Password"
:
"Nova Contrasenya"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
"No estàs segur del que afegir?"
,
"Not sure what to write? Switch to"
:
"No estàs segur del que escriure? Canvia a"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"Tanca sessió"
,
"Sign up"
:
"Registra't"
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"Error de reconeixement de veu: {{error}}"
,
"Speech-to-Text Engine"
:
"Motor de Veu a Text"
,
"SpeechRecognition API is not supported in this browser."
:
"L'API de Reconèixer Veu no és compatible amb aquest navegador."
,
...
...
src/lib/i18n/locales/de-DE/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"Chunk Overlap"
,
"Chunk Params"
:
"Chunk Parameter"
,
"Chunk Size"
:
"Chunk Size"
,
"Citation"
:
""
,
"Click here for help."
:
"Klicke hier für Hilfe."
,
"Click here to"
:
"Klicke hier, um"
,
"Click here to check other modelfiles."
:
"Klicke hier, um andere Modelfiles zu überprüfen."
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"Neuer Chat"
,
"New Password"
:
"Neues Passwort"
,
"No results found"
:
"Keine Ergebnisse gefunden"
,
"No source available"
:
""
,
"Not factually correct"
:
"Nicht sachlich korrekt."
,
"Not sure what to add?"
:
"Nicht sicher, was hinzugefügt werden soll?"
,
"Not sure what to write? Switch to"
:
"Nicht sicher, was Du schreiben sollst? Wechsel zu"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"Abmelden"
,
"Sign up"
:
"Registrieren"
,
"Signing in"
:
"Anmeldung"
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"Spracherkennungsfehler: {{error}}"
,
"Speech-to-Text Engine"
:
"Sprache-zu-Text-Engine"
,
"SpeechRecognition API is not supported in this browser."
:
"Die Spracherkennungs-API wird in diesem Browser nicht unterstützt."
,
...
...
src/lib/i18n/locales/dg-DG/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"Chunk Overlap"
,
"Chunk Params"
:
"Chunk Params"
,
"Chunk Size"
:
"Chunk Size"
,
"Citation"
:
""
,
"Click here for help."
:
"Click for help. Much assist."
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"Click to check other modelfiles."
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"New Bark"
,
"New Password"
:
"New Barkword"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
"Not sure what to add?"
,
"Not sure what to write? Switch to"
:
"Not sure what to write? Switch to"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"Sign Out much logout"
,
"Sign up"
:
"Sign up much join"
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"Speech recognition error: {{error}} so error"
,
"Speech-to-Text Engine"
:
"Speech-to-Text Engine much speak"
,
"SpeechRecognition API is not supported in this browser."
:
"SpeechRecognition API is not supported in this browser. Much sad."
,
...
...
src/lib/i18n/locales/en-GB/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
""
,
"Chunk Params"
:
""
,
"Chunk Size"
:
""
,
"Citation"
:
""
,
"Click here for help."
:
""
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
""
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
""
,
"New Password"
:
""
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
""
,
"Not sure what to write? Switch to"
:
""
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
""
,
"Sign up"
:
""
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
""
,
"Speech-to-Text Engine"
:
""
,
"SpeechRecognition API is not supported in this browser."
:
""
,
...
...
src/lib/i18n/locales/en-US/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
""
,
"Chunk Params"
:
""
,
"Chunk Size"
:
""
,
"Citation"
:
""
,
"Click here for help."
:
""
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
""
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
""
,
"New Password"
:
""
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
""
,
"Not sure what to write? Switch to"
:
""
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
""
,
"Sign up"
:
""
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
""
,
"Speech-to-Text Engine"
:
""
,
"SpeechRecognition API is not supported in this browser."
:
""
,
...
...
src/lib/i18n/locales/es-ES/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"Superposición de fragmentos"
,
"Chunk Params"
:
"Parámetros de fragmentos"
,
"Chunk Size"
:
"Tamaño de fragmentos"
,
"Citation"
:
""
,
"Click here for help."
:
"Presiona aquí para obtener ayuda."
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"Presiona aquí para consultar otros modelfiles."
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"Nuevo Chat"
,
"New Password"
:
"Nueva Contraseña"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
"¿No sabes qué añadir?"
,
"Not sure what to write? Switch to"
:
"¿No sabes qué escribir? Cambia a"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"Cerrar sesión"
,
"Sign up"
:
"Crear una cuenta"
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"Error de reconocimiento de voz: {{error}}"
,
"Speech-to-Text Engine"
:
"Motor de voz a texto"
,
"SpeechRecognition API is not supported in this browser."
:
"La API SpeechRecognition no es compatible con este navegador."
,
...
...
src/lib/i18n/locales/fa-IR/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"همپوشانی تکه"
,
"Chunk Params"
:
"پارامترهای تکه"
,
"Chunk Size"
:
"اندازه تکه"
,
"Citation"
:
""
,
"Click here for help."
:
"برای کمک اینجا را کلیک کنید."
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"برای بررسی سایر فایل
\u
200cهای مدل اینجا را کلیک کنید."
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"گپ جدید"
,
"New Password"
:
"رمز عبور جدید"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
"مطمئن نیستید چه چیزی را اضافه کنید؟"
,
"Not sure what to write? Switch to"
:
"مطمئن نیستید چه بنویسید؟ تغییر به"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"خروج"
,
"Sign up"
:
"ثبت نام"
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"خطای تشخیص گفتار: {{error}}"
,
"Speech-to-Text Engine"
:
"موتور گفتار به متن"
,
"SpeechRecognition API is not supported in this browser."
:
"API تشخیص گفتار در این مرورگر پشتیبانی نمی شود."
,
...
...
src/lib/i18n/locales/fr-CA/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"Chevauchement de bloc"
,
"Chunk Params"
:
"Paramètres de bloc"
,
"Chunk Size"
:
"Taille de bloc"
,
"Citation"
:
""
,
"Click here for help."
:
"Cliquez ici pour de l'aide."
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"Cliquez ici pour vérifier d'autres fichiers de modèle."
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"Nouvelle discussion"
,
"New Password"
:
"Nouveau mot de passe"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
"Pas sûr de quoi ajouter ?"
,
"Not sure what to write? Switch to"
:
"Pas sûr de quoi écrire ? Changez pour"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"Se déconnecter"
,
"Sign up"
:
"S'inscrire"
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"Erreur de reconnaissance vocale : {{error}}"
,
"Speech-to-Text Engine"
:
"Moteur reconnaissance vocale"
,
"SpeechRecognition API is not supported in this browser."
:
"L'API SpeechRecognition n'est pas prise en charge dans ce navigateur."
,
...
...
src/lib/i18n/locales/fr-FR/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"Chevauchement de bloc"
,
"Chunk Params"
:
"Paramètres de bloc"
,
"Chunk Size"
:
"Taille de bloc"
,
"Citation"
:
""
,
"Click here for help."
:
"Cliquez ici pour de l'aide."
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"Cliquez ici pour vérifier d'autres fichiers de modèle."
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"Nouveau chat"
,
"New Password"
:
"Nouveau mot de passe"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
"Vous ne savez pas quoi ajouter ?"
,
"Not sure what to write? Switch to"
:
"Vous ne savez pas quoi écrire ? Basculer vers"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"Se déconnecter"
,
"Sign up"
:
"S'inscrire"
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"Erreur de reconnaissance vocale : {{error}}"
,
"Speech-to-Text Engine"
:
"Moteur de reconnaissance vocale"
,
"SpeechRecognition API is not supported in this browser."
:
"L'API SpeechRecognition n'est pas prise en charge dans ce navigateur."
,
...
...
src/lib/i18n/locales/it-IT/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"Sovrapposizione chunk"
,
"Chunk Params"
:
"Parametri chunk"
,
"Chunk Size"
:
"Dimensione chunk"
,
"Citation"
:
""
,
"Click here for help."
:
"Clicca qui per aiuto."
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"Clicca qui per controllare altri file modello."
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"Nuova chat"
,
"New Password"
:
"Nuova password"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
"Non sei sicuro di cosa aggiungere?"
,
"Not sure what to write? Switch to"
:
"Non sei sicuro di cosa scrivere? Passa a"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"Esci"
,
"Sign up"
:
"Registrati"
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"Errore di riconoscimento vocale: {{error}}"
,
"Speech-to-Text Engine"
:
"Motore da voce a testo"
,
"SpeechRecognition API is not supported in this browser."
:
"L'API SpeechRecognition non è supportata in questo browser."
,
...
...
src/lib/i18n/locales/ja-JP/translation.json
View file @
e98cb452
...
...
@@ -73,6 +73,7 @@
"Chunk Overlap"
:
"チャンクオーバーラップ"
,
"Chunk Params"
:
"チャンクパラメーター"
,
"Chunk Size"
:
"チャンクサイズ"
,
"Citation"
:
""
,
"Click here for help."
:
"ヘルプについてはここをクリックしてください。"
,
"Click here to"
:
""
,
"Click here to check other modelfiles."
:
"他のモデルファイルを確認するにはここをクリックしてください。"
,
...
...
@@ -270,6 +271,7 @@
"New Chat"
:
"新しいチャット"
,
"New Password"
:
"新しいパスワード"
,
"No results found"
:
""
,
"No source available"
:
""
,
"Not factually correct"
:
""
,
"Not sure what to add?"
:
"何を追加すればよいかわからない?"
,
"Not sure what to write? Switch to"
:
"何を書けばよいかわからない? 次に切り替える"
,
...
...
@@ -385,6 +387,7 @@
"Sign Out"
:
"サインアウト"
,
"Sign up"
:
"サインアップ"
,
"Signing in"
:
""
,
"Source"
:
""
,
"Speech recognition error: {{error}}"
:
"音声認識エラー: {{error}}"
,
"Speech-to-Text Engine"
:
"音声テキスト変換エンジン"
,
"SpeechRecognition API is not supported in this browser."
:
"このブラウザでは SpeechRecognition API がサポートされていません。"
,
...
...
Prev
1
2
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