diff --git a/backend/open_webui/apps/retrieval/utils.py b/backend/open_webui/apps/retrieval/utils.py index 80b0ce2a0..153bd804f 100644 --- a/backend/open_webui/apps/retrieval/utils.py +++ b/backend/open_webui/apps/retrieval/utils.py @@ -411,13 +411,14 @@ def get_rag_context( ) if "metadatas" in context: - citations.append( - { - "source": context["file"], - "document": context["documents"][0], - "metadata": context["metadatas"][0], - } - ) + citation = { + "source": context["file"], + "document": context["documents"][0], + "metadata": context["metadatas"][0], + } + if "distances" in context and context["distances"]: + citation["distances"] = context["distances"][0] + citations.append(citation) except Exception as e: log.exception(e) diff --git a/backend/open_webui/apps/retrieval/vector/dbs/chroma.py b/backend/open_webui/apps/retrieval/vector/dbs/chroma.py index 84f80b253..c6d95bd52 100644 --- a/backend/open_webui/apps/retrieval/vector/dbs/chroma.py +++ b/backend/open_webui/apps/retrieval/vector/dbs/chroma.py @@ -109,7 +109,10 @@ class ChromaClient: def insert(self, collection_name: str, items: list[VectorItem]): # Insert the items into the collection, if the collection does not exist, it will be created. - collection = self.client.get_or_create_collection(name=collection_name) + collection = self.client.get_or_create_collection( + name=collection_name, + metadata={"hnsw:space": "cosine"} + ) ids = [item["id"] for item in items] documents = [item["text"] for item in items] @@ -127,7 +130,10 @@ class ChromaClient: def upsert(self, collection_name: str, items: list[VectorItem]): # Update the items in the collection, if the items are not present, insert them. If the collection does not exist, it will be created. - collection = self.client.get_or_create_collection(name=collection_name) + collection = self.client.get_or_create_collection( + name=collection_name, + metadata={"hnsw:space": "cosine"} + ) ids = [item["id"] for item in items] documents = [item["text"] for item in items] diff --git a/src/lib/components/chat/Messages/Citations.svelte b/src/lib/components/chat/Messages/Citations.svelte index 2c23e87a4..0a09b3b55 100644 --- a/src/lib/components/chat/Messages/Citations.svelte +++ b/src/lib/components/chat/Messages/Citations.svelte @@ -1,67 +1,219 @@ - + {#if _citations.length > 0}
- {#each _citations as citation, idx} -
- +
+ {/each} + {:else} + +
-
- {idx + 1} +
+ +
+ {#if _citations.length > 1 && _citations + .slice(0, 2) + .reduce((acc, citation) => acc + citation.source.name.length, 0) <= 50} + {#each _citations.slice(0, 2) as citation, idx} +
+ + {#if idx === 0}, + {/if} +
+ {/each} + {:else} + {#each _citations.slice(0, 1) as citation, idx} +
+ +
+ {/each} + {/if} +
+
+ + + {_citations.length - + (_citations.length > 1 && + _citations + .slice(0, 2) + .reduce((acc, citation) => acc + citation.source.name.length, 0) <= 50 + ? 2 + : 1)} + + {$i18n.t('more')} +
-
- {citation.source.name} +
+ {#if isCollapsibleOpen} + + {:else} + + {/if}
- -
- {/each} +
+
+
+ {#each _citations as citation, idx} +
+ +
+ {/each} +
+
+ + {/if}
{/if} diff --git a/src/lib/components/chat/Messages/CitationsModal.svelte b/src/lib/components/chat/Messages/CitationsModal.svelte index 923fdea54..ad965e350 100644 --- a/src/lib/components/chat/Messages/CitationsModal.svelte +++ b/src/lib/components/chat/Messages/CitationsModal.svelte @@ -2,21 +2,44 @@ import { getContext, onMount, tick } from 'svelte'; import Modal from '$lib/components/common/Modal.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte'; + const i18n = getContext('i18n'); export let show = false; export let citation; + export let showPercentage = false; + export let showRelevance = true; let mergedDocuments = []; + function calculatePercentage(distance: number) { + if (distance < 0) return 100; + if (distance > 1) return 0; + return Math.round((1 - distance) * 10000) / 100; + } + + function getRelevanceColor(percentage: number) { + if (percentage >= 80) + return 'bg-green-200 dark:bg-green-800 text-green-800 dark:text-green-200'; + if (percentage >= 60) + return 'bg-yellow-200 dark:bg-yellow-800 text-yellow-800 dark:text-yellow-200'; + if (percentage >= 40) + return 'bg-orange-200 dark:bg-orange-800 text-orange-800 dark:text-orange-200'; + return 'bg-red-200 dark:bg-red-800 text-red-800 dark:text-red-200'; + } + $: if (citation) { mergedDocuments = citation.document?.map((c, i) => { return { source: citation.source, document: c, - metadata: citation.metadata?.[i] + metadata: citation.metadata?.[i], + distance: citation.distances?.[i] }; }); + if (mergedDocuments.every((doc) => doc.distance !== undefined)) { + mergedDocuments.sort((a, b) => (a.distance ?? Infinity) - (b.distance ?? Infinity)); + } } @@ -59,11 +82,11 @@ -
+
{document?.metadata?.name ?? document.source.name} - {document?.metadata?.page - ? `(${$i18n.t('page')} ${document.metadata.page + 1})` - : ''} + {#if document?.metadata?.page} + + ({$i18n.t('page')} + {document.metadata.page + 1}) + + {/if}
+ {#if showRelevance} +
+ {$i18n.t('Relevance')} +
+ {#if document.distance !== undefined} + +
+ {#if showPercentage} + {@const percentage = calculatePercentage(document.distance)} + + {percentage.toFixed(2)}% + + + ({document.distance.toFixed(4)}) + + {:else} + + {document.distance.toFixed(4)} + + {/if} +
+
+ {:else} +
+ {$i18n.t('No distance available')} +
+ {/if} + {/if} {:else}
{$i18n.t('No source available')} @@ -85,7 +143,7 @@ {/if}
-
+
{$i18n.t('Content')}
diff --git a/src/lib/components/common/Collapsible.svelte b/src/lib/components/common/Collapsible.svelte
index 68cafdb75..c15512de7 100644
--- a/src/lib/components/common/Collapsible.svelte
+++ b/src/lib/components/common/Collapsible.svelte
@@ -38,9 +38,9 @@
 
 				
{#if open} - + {:else} - + {/if}
@@ -68,5 +68,5 @@
- {/if} +
diff --git a/src/lib/i18n/locales/de-DE/translation.json b/src/lib/i18n/locales/de-DE/translation.json index 4a6c28141..307d1226c 100644 --- a/src/lib/i18n/locales/de-DE/translation.json +++ b/src/lib/i18n/locales/de-DE/translation.json @@ -441,6 +441,7 @@ "Modelfile Content": "Modelfile-Inhalt", "Models": "Modelle", "More": "Mehr", + "more": "mehr", "Move to Top": "", "Name": "Name", "Name your model": "Benennen Sie Ihr Modell", @@ -788,5 +789,6 @@ "Your account status is currently pending activation.": "Ihr Kontostatus ist derzeit ausstehend und wartet auf Aktivierung.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Youtube": "YouTube", - "Youtube Loader Settings": "YouTube-Ladeeinstellungen" + "Youtube Loader Settings": "YouTube-Ladeeinstellungen", + "References from": "Referenzen aus" }