Skip to content

Commit 0f0ba7d

Browse files
committed
refac
1 parent 5d7766e commit 0f0ba7d

2 files changed

Lines changed: 85 additions & 121 deletions

File tree

backend/open_webui/tools/builtin.py

Lines changed: 82 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,9 +1528,11 @@ async def search_knowledge_files(
15281528
skip: int = 0,
15291529
__request__: Request = None,
15301530
__user__: dict = None,
1531+
__model_knowledge__: Optional[list[dict]] = None,
15311532
) -> str:
15321533
"""
1533-
Search files across knowledge bases the user has access to.
1534+
Search files by filename across knowledge bases the user has access to.
1535+
When the model has attached knowledge, searches only within attached KBs and files.
15341536
15351537
:param query: The search query to find matching files by filename
15361538
:param knowledge_id: Optional KB id to limit search to a specific knowledge base
@@ -1546,10 +1548,87 @@ async def search_knowledge_files(
15461548

15471549
try:
15481550
from open_webui.models.knowledge import Knowledges
1551+
from open_webui.models.files import Files
1552+
from open_webui.models.access_grants import AccessGrants
15491553

15501554
user_id = __user__.get('id')
1555+
user_role = __user__.get('role', 'user')
15511556
user_group_ids = [group.id for group in Groups.get_groups_by_member_id(user_id)]
15521557

1558+
# When model has attached knowledge, scope to attached KBs/files only
1559+
if __model_knowledge__:
1560+
attached_kb_ids = set()
1561+
attached_file_ids = set()
1562+
1563+
for item in __model_knowledge__:
1564+
item_type = item.get('type')
1565+
item_id = item.get('id')
1566+
if item_type == 'collection':
1567+
attached_kb_ids.add(item_id)
1568+
elif item_type == 'file':
1569+
attached_file_ids.add(item_id)
1570+
1571+
# If knowledge_id specified, verify it's in the attached set
1572+
if knowledge_id:
1573+
if knowledge_id not in attached_kb_ids:
1574+
return json.dumps({'error': f'Knowledge base {knowledge_id} is not attached to this model'})
1575+
attached_kb_ids = {knowledge_id}
1576+
1577+
all_files = []
1578+
1579+
# Search within attached KBs
1580+
for kb_id in attached_kb_ids:
1581+
knowledge = Knowledges.get_knowledge_by_id(kb_id)
1582+
if not knowledge:
1583+
continue
1584+
1585+
if not (
1586+
user_role == 'admin'
1587+
or knowledge.user_id == user_id
1588+
or AccessGrants.has_access(
1589+
user_id=user_id,
1590+
resource_type='knowledge',
1591+
resource_id=knowledge.id,
1592+
permission='read',
1593+
user_group_ids=set(user_group_ids),
1594+
)
1595+
):
1596+
continue
1597+
1598+
result = Knowledges.search_files_by_id(
1599+
knowledge_id=kb_id,
1600+
user_id=user_id,
1601+
filter={'query': query},
1602+
skip=0,
1603+
limit=count + skip,
1604+
)
1605+
1606+
for file in result.items:
1607+
all_files.append({
1608+
'id': file.id,
1609+
'filename': file.filename,
1610+
'knowledge_id': knowledge.id,
1611+
'knowledge_name': knowledge.name,
1612+
'updated_at': file.updated_at,
1613+
})
1614+
1615+
# Search within directly attached files (filename match)
1616+
if not knowledge_id and attached_file_ids:
1617+
query_lower = query.lower() if query else ''
1618+
for file_id in attached_file_ids:
1619+
file = Files.get_file_by_id(file_id)
1620+
if file and (not query_lower or query_lower in file.filename.lower()):
1621+
all_files.append({
1622+
'id': file.id,
1623+
'filename': file.filename,
1624+
'updated_at': file.updated_at,
1625+
})
1626+
1627+
# Apply pagination across combined results
1628+
all_files = all_files[skip:skip + count]
1629+
return json.dumps(all_files, ensure_ascii=False)
1630+
1631+
# No attached knowledge - search all accessible KBs
15531632
if knowledge_id:
15541633
result = Knowledges.search_files_by_id(
15551634
knowledge_id=knowledge_id,
@@ -1793,7 +1872,7 @@ async def view_knowledge_file(
17931872
return json.dumps({'error': str(e)})
17941873

17951874

1796-
async def list_attached_knowledge(
1875+
async def list_knowledge(
17971876
__request__: Request = None,
17981877
__user__: dict = None,
17991878
__model_knowledge__: Optional[list[dict]] = None,
@@ -1895,121 +1974,7 @@ async def list_attached_knowledge(
18951974
'notes': notes,
18961975
}, ensure_ascii=False)
18971976
except Exception as e:
1898-
log.exception(f'list_attached_knowledge error: {e}')
1899-
return json.dumps({'error': str(e)})
1900-
1901-
1902-
async def search_attached_files(
1903-
query: str,
1904-
knowledge_id: Optional[str] = None,
1905-
count: int = 10,
1906-
skip: int = 0,
1907-
__request__: Request = None,
1908-
__user__: dict = None,
1909-
__model_knowledge__: Optional[list[dict]] = None,
1910-
) -> str:
1911-
"""
1912-
Search files by filename within the attached knowledge scope.
1913-
Only searches knowledge bases and files that are attached to the current model.
1914-
1915-
:param query: The filename search query
1916-
:param knowledge_id: Optional KB id to limit search to a specific attached knowledge base
1917-
:param count: Maximum number of results to return (default: 10)
1918-
:param skip: Number of results to skip for pagination (default: 0)
1919-
:return: JSON with matching files containing id, filename, knowledge_id, and knowledge_name
1920-
"""
1921-
if __request__ is None:
1922-
return json.dumps({'error': 'Request context not available'})
1923-
1924-
if not __user__:
1925-
return json.dumps({'error': 'User context not available'})
1926-
1927-
if not __model_knowledge__:
1928-
return json.dumps([])
1929-
1930-
try:
1931-
from open_webui.models.knowledge import Knowledges
1932-
from open_webui.models.files import Files
1933-
from open_webui.models.access_grants import AccessGrants
1934-
1935-
user_id = __user__.get('id')
1936-
user_role = __user__.get('role', 'user')
1937-
user_group_ids = [group.id for group in Groups.get_groups_by_member_id(user_id)]
1938-
1939-
# Collect attached KB IDs and direct file IDs
1940-
attached_kb_ids = set()
1941-
attached_file_ids = set()
1942-
1943-
for item in __model_knowledge__:
1944-
item_type = item.get('type')
1945-
item_id = item.get('id')
1946-
if item_type == 'collection':
1947-
attached_kb_ids.add(item_id)
1948-
elif item_type == 'file':
1949-
attached_file_ids.add(item_id)
1950-
1951-
# If knowledge_id is specified, verify it's in the attached set
1952-
if knowledge_id:
1953-
if knowledge_id not in attached_kb_ids:
1954-
return json.dumps({'error': f'Knowledge base {knowledge_id} is not attached to this model'})
1955-
attached_kb_ids = {knowledge_id}
1956-
1957-
all_files = []
1958-
1959-
# Search within attached KBs
1960-
for kb_id in attached_kb_ids:
1961-
knowledge = Knowledges.get_knowledge_by_id(kb_id)
1962-
if not knowledge:
1963-
continue
1964-
1965-
if not (
1966-
user_role == 'admin'
1967-
or knowledge.user_id == user_id
1968-
or AccessGrants.has_access(
1969-
user_id=user_id,
1970-
resource_type='knowledge',
1971-
resource_id=knowledge.id,
1972-
permission='read',
1973-
user_group_ids=set(user_group_ids),
1974-
)
1975-
):
1976-
continue
1977-
1978-
result = Knowledges.search_files_by_id(
1979-
knowledge_id=kb_id,
1980-
user_id=user_id,
1981-
filter={'query': query},
1982-
skip=0,
1983-
limit=count + skip, # Fetch enough for pagination across KBs
1984-
)
1985-
1986-
for file in result.items:
1987-
all_files.append({
1988-
'id': file.id,
1989-
'filename': file.filename,
1990-
'knowledge_id': knowledge.id,
1991-
'knowledge_name': knowledge.name,
1992-
'updated_at': file.updated_at,
1993-
})
1994-
1995-
# Search within directly attached files (filename match)
1996-
if not knowledge_id and attached_file_ids:
1997-
query_lower = query.lower() if query else ''
1998-
for file_id in attached_file_ids:
1999-
file = Files.get_file_by_id(file_id)
2000-
if file and (not query_lower or query_lower in file.filename.lower()):
2001-
all_files.append({
2002-
'id': file.id,
2003-
'filename': file.filename,
2004-
'updated_at': file.updated_at,
2005-
})
2006-
2007-
# Apply pagination across combined results
2008-
all_files = all_files[skip:skip + count]
2009-
2010-
return json.dumps(all_files, ensure_ascii=False)
2011-
except Exception as e:
2012-
log.exception(f'search_attached_files error: {e}')
1977+
log.exception(f'list_knowledge error: {e}')
20131978
return json.dumps({'error': str(e)})
20141979

20151980

backend/open_webui/utils/tools.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@
7979
query_knowledge_bases,
8080
search_knowledge_files,
8181
query_knowledge_files,
82-
list_attached_knowledge,
83-
search_attached_files,
82+
list_knowledge,
8483
view_file,
8584
view_knowledge_file,
8685
view_skill,
@@ -408,8 +407,8 @@ def is_builtin_tool_enabled(category: str) -> bool:
408407
if is_builtin_tool_enabled('knowledge'):
409408
if model_knowledge:
410409
# Model has attached knowledge - provide discovery, search and semantic tools
411-
builtin_functions.append(list_attached_knowledge)
412-
builtin_functions.append(search_attached_files)
410+
builtin_functions.append(list_knowledge)
411+
builtin_functions.append(search_knowledge_files)
413412
builtin_functions.append(query_knowledge_files)
414413

415414
knowledge_types = {item.get('type') for item in model_knowledge}

0 commit comments

Comments
 (0)