mirror of
https://github.com/open-webui/open-webui.git
synced 2026-08-28 05:27:35 +00:00
refac
This commit is contained in:
parent
f730733bc4
commit
caa2457c17
6 changed files with 39 additions and 35 deletions
|
|
@ -37,6 +37,7 @@ from open_webui.env import (
|
|||
from open_webui.models.access_grants import AccessGrants
|
||||
from open_webui.models.chats import Chats
|
||||
from open_webui.models.files import Files
|
||||
from open_webui.models.folders import Folders
|
||||
from open_webui.models.knowledge import Knowledges
|
||||
from open_webui.models.notes import Notes
|
||||
from open_webui.models.config import Config
|
||||
|
|
@ -48,6 +49,7 @@ from open_webui.retrieval.vector.factory import VECTOR_DB_CLIENT
|
|||
from open_webui.retrieval.vector.main import GetResult, SearchResult
|
||||
from open_webui.retrieval.web.utils import get_web_loader
|
||||
from open_webui.utils.access_control.files import has_access_to_file
|
||||
from open_webui.utils.access_control.folders import has_folder_access
|
||||
from open_webui.utils.headers import include_user_info_headers
|
||||
from open_webui.utils.misc import get_message_list
|
||||
|
||||
|
|
@ -1323,6 +1325,25 @@ async def get_sources_from_items(
|
|||
bypass_embedding_and_retrieval = await Config.get('rag.bypass_embedding_and_retrieval')
|
||||
extracted_collections = []
|
||||
query_results = []
|
||||
folder_items = set()
|
||||
expanded_folders = set()
|
||||
|
||||
items = list(items)
|
||||
for item in items:
|
||||
if item.get('type') != 'folder' or not user:
|
||||
continue
|
||||
folder_id = item.get('id')
|
||||
if not folder_id or folder_id in expanded_folders:
|
||||
continue
|
||||
expanded_folders.add(folder_id)
|
||||
|
||||
folder = await Folders.get_folder_by_id(folder_id)
|
||||
if folder and (user.role == 'admin' or await has_folder_access(user.id, folder, 'read', db=None)):
|
||||
files = (folder.data or {}).get('files', [])
|
||||
folder_items.update(
|
||||
(entry.get('type'), entry.get('id')) for entry in files if isinstance(entry, dict)
|
||||
)
|
||||
items.extend(files)
|
||||
|
||||
for item in items:
|
||||
query_result = None
|
||||
|
|
@ -1429,6 +1450,7 @@ async def get_sources_from_items(
|
|||
user.role == 'admin'
|
||||
or file_object.user_id == user.id
|
||||
or await has_access_to_file(item.get('id'), 'read', user)
|
||||
or ('file', item.get('id')) in folder_items
|
||||
):
|
||||
query_result = {
|
||||
'documents': [[file_object.data.get('content', '')]],
|
||||
|
|
@ -1459,6 +1481,7 @@ async def get_sources_from_items(
|
|||
user.role == 'admin'
|
||||
or file_object.user_id == user.id
|
||||
or await has_access_to_file(file_id, 'read', user)
|
||||
or ('file', file_id) in folder_items
|
||||
):
|
||||
if item.get('legacy'):
|
||||
collection_names.append(f'{file_id}')
|
||||
|
|
@ -1478,6 +1501,7 @@ async def get_sources_from_items(
|
|||
resource_id=knowledge_base.id,
|
||||
permission='read',
|
||||
)
|
||||
or ('collection', item.get('id')) in folder_items
|
||||
):
|
||||
if (knowledge_base.meta or {}).get('source') == 'external':
|
||||
query_result = await retrieve_external_knowledge(
|
||||
|
|
@ -1500,6 +1524,7 @@ async def get_sources_from_items(
|
|||
resource_id=knowledge_base.id,
|
||||
permission='read',
|
||||
)
|
||||
or ('collection', item.get('id')) in folder_items
|
||||
):
|
||||
files = await Knowledges.get_files_by_id(knowledge_base.id)
|
||||
|
||||
|
|
@ -1570,7 +1595,7 @@ async def get_sources_from_items(
|
|||
continue
|
||||
|
||||
# Filter out collections the user cannot read
|
||||
if user:
|
||||
if user and (item.get('type'), item.get('id')) not in folder_items:
|
||||
collection_names = await filter_accessible_collections(collection_names, user)
|
||||
if not collection_names:
|
||||
log.debug(f'access denied for all collections in item {item}')
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ from open_webui.socket.main import (
|
|||
get_event_emitter,
|
||||
)
|
||||
from open_webui.utils.access_control import has_connection_access, has_permission
|
||||
from open_webui.utils.access_control.files import get_accessible_folder_files
|
||||
from open_webui.utils.access_control.folders import has_folder_access
|
||||
from open_webui.utils.chat import generate_chat_completion
|
||||
from open_webui.utils.code_interpreter import execute_code_jupyter
|
||||
|
|
@ -2363,16 +2362,15 @@ async def process_chat_payload(request, form_data, user, metadata, model):
|
|||
if 'system_prompt' in folder.data:
|
||||
form_data = await apply_system_prompt_to_body(folder.data['system_prompt'], form_data, metadata, user)
|
||||
if 'files' in folder.data:
|
||||
allowed_files = await get_accessible_folder_files(folder.data['files'], user)
|
||||
if metadata.get('params', {}).get('function_calling') == 'legacy':
|
||||
form_data['files'] = [
|
||||
*allowed_files,
|
||||
{'type': 'folder', 'id': folder.id},
|
||||
*form_data.get('files', []),
|
||||
]
|
||||
else:
|
||||
# Native FC: skip RAG injection, builtin tools
|
||||
# will read folder knowledge from metadata.
|
||||
metadata['folder_knowledge'] = allowed_files
|
||||
metadata['folder_knowledge'] = folder.data['files']
|
||||
|
||||
# Model "Knowledge" handling
|
||||
user_message = get_last_user_message(form_data['messages'])
|
||||
|
|
@ -2578,23 +2576,6 @@ async def process_chat_payload(request, form_data, user, metadata, model):
|
|||
# urls = extract_urls(prompt)
|
||||
|
||||
if files:
|
||||
if not files:
|
||||
files = []
|
||||
|
||||
for file_item in files:
|
||||
if file_item.get('type', 'file') == 'folder':
|
||||
# Get folder files
|
||||
folder_id = file_item.get('id', None)
|
||||
if folder_id:
|
||||
folder = await Folders.get_folder_by_id(folder_id)
|
||||
if folder and user.role != 'admin' and not await has_folder_access(
|
||||
user.id, folder, 'read', db=None
|
||||
):
|
||||
folder = None
|
||||
if folder and folder.data and 'files' in folder.data:
|
||||
files = [f for f in files if f.get('id', None) != folder_id]
|
||||
files = [*files, *await get_accessible_folder_files(folder.data['files'], user)]
|
||||
|
||||
# files = [*files, *[{"type": "url", "url": url, "name": url} for url in urls]]
|
||||
# Remove duplicate files based on their content
|
||||
files = list({json.dumps(f, sort_keys=True): f for f in files}.values())
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
triggerClass={className
|
||||
? className
|
||||
: 'flex shrink-0 items-center gap-2 bg-transparent px-0.5 text-sm placeholder-gray-400 outline-hidden focus:outline-hidden'}
|
||||
itemClass="flex w-full gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl"
|
||||
itemClass="flex w-full h-[1.6875rem] gap-2 items-center rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
||||
onChange={(v) => {
|
||||
onChange(v);
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { flyAndScale } from '$lib/utils/transitions';
|
||||
import { tick } from 'svelte';
|
||||
import DropdownMenu from '$lib/components/common/DropdownMenu.svelte';
|
||||
|
||||
/** Currently selected value */
|
||||
export let value = '';
|
||||
|
|
@ -21,8 +22,7 @@
|
|||
export let labelClass = '';
|
||||
|
||||
/** CSS classes for the dropdown content container */
|
||||
export let contentClass =
|
||||
'rounded-2xl min-w-[170px] p-1 border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-850 dark:text-white shadow-lg';
|
||||
export let contentClass = 'min-w-[170px]';
|
||||
|
||||
/** Max height for the dropdown content */
|
||||
export let maxHeight = '18rem';
|
||||
|
|
@ -127,7 +127,7 @@
|
|||
|
||||
{#if open}
|
||||
<div use:portal bind:this={contentEl} transition:flyAndScale>
|
||||
<div class={contentClass} style:max-height={maxHeight} style:overflow-y="auto">
|
||||
<DropdownMenu className={contentClass} style={`max-height: ${maxHeight}; overflow-y: auto;`}>
|
||||
<slot {open} {selectItem}>
|
||||
{#each items as item}
|
||||
<button class={itemClass} type="button" on:click={() => selectItem(item)}>
|
||||
|
|
@ -137,6 +137,6 @@
|
|||
</button>
|
||||
{/each}
|
||||
</slot>
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
import { splitStream } from '$lib/utils';
|
||||
import Collapsible from '../common/Collapsible.svelte';
|
||||
import Dropdown from '../common/Dropdown.svelte';
|
||||
import DropdownMenu from '../common/DropdownMenu.svelte';
|
||||
import DropdownSub from '../common/DropdownSub.svelte';
|
||||
|
||||
import Messages from '$lib/components/playground/Chat/Messages.svelte';
|
||||
|
|
@ -394,9 +395,7 @@
|
|||
</button>
|
||||
|
||||
<div slot="content">
|
||||
<div
|
||||
class="min-w-[200px] rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg"
|
||||
>
|
||||
<DropdownMenu className="min-w-[200px]">
|
||||
<DropdownSub>
|
||||
<button
|
||||
slot="trigger"
|
||||
|
|
@ -426,7 +425,7 @@
|
|||
<div class="flex items-center line-clamp-1">{$i18n.t('Plain text (.txt)')}</div>
|
||||
</button>
|
||||
</DropdownSub>
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
import EllipsisHorizontal from '$lib/components/icons/EllipsisHorizontal.svelte';
|
||||
import Select from '$lib/components/common/Select.svelte';
|
||||
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
||||
import DropdownMenu from '$lib/components/common/DropdownMenu.svelte';
|
||||
import ChevronDown from '$lib/components/icons/ChevronDown.svelte';
|
||||
import Check from '$lib/components/icons/Check.svelte';
|
||||
import CheckCircle from '$lib/components/icons/CheckCircle.svelte';
|
||||
|
|
@ -384,9 +385,7 @@
|
|||
</Tooltip>
|
||||
|
||||
<div slot="content">
|
||||
<div
|
||||
class="w-[170px] rounded-xl p-1 border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-850 dark:text-white shadow-sm"
|
||||
>
|
||||
<DropdownMenu className="w-[170px] shadow-sm">
|
||||
<button
|
||||
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
|
||||
type="button"
|
||||
|
|
@ -403,7 +402,7 @@
|
|||
<Minus className="size-4" />
|
||||
{$i18n.t('Disable All')}
|
||||
</button>
|
||||
</div>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue