open-webui/backend/open_webui/apps/webui/models/knowledge.py

219 lines
6.3 KiB
Python
Raw Normal View History

2024-10-02 00:35:35 +00:00
import json
import logging
import time
from typing import Optional
2024-10-02 04:32:59 +00:00
import uuid
2024-10-02 00:35:35 +00:00
from open_webui.apps.webui.internal.db import Base, get_db
from open_webui.env import SRC_LOG_LEVELS
from open_webui.apps.webui.models.files import FileMetadataResponse
2024-11-18 13:51:01 +00:00
from open_webui.apps.webui.models.users import Users, UserResponse
2024-10-02 00:35:35 +00:00
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Column, String, Text, JSON
2024-11-17 00:51:55 +00:00
from open_webui.utils.access_control import has_access
2024-10-02 00:35:35 +00:00
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
2024-10-02 05:45:04 +00:00
# Knowledge DB Schema
2024-10-02 00:35:35 +00:00
####################
2024-10-02 05:45:04 +00:00
class Knowledge(Base):
__tablename__ = "knowledge"
2024-10-02 00:35:35 +00:00
id = Column(Text, unique=True, primary_key=True)
user_id = Column(Text)
name = Column(Text)
description = Column(Text)
data = Column(JSON, nullable=True)
meta = Column(JSON, nullable=True)
2024-11-15 02:57:25 +00:00
access_control = Column(JSON, nullable=True) # Controls data access levels.
2024-11-15 04:13:43 +00:00
# Defines access control rules for this entry.
# - `None`: Public access, available to all users with the "user" role.
# - `{}`: Private access, restricted exclusively to the owner.
# - Custom permissions: Specific access control for reading and writing;
# Can specify group or user-level restrictions:
# {
# "read": {
# "group_ids": ["group_id1", "group_id2"],
# "user_ids": ["user_id1", "user_id2"]
# },
# "write": {
# "group_ids": ["group_id1", "group_id2"],
# "user_ids": ["user_id1", "user_id2"]
# }
# }
2024-11-15 02:57:25 +00:00
2024-10-02 00:35:35 +00:00
created_at = Column(BigInteger)
updated_at = Column(BigInteger)
2024-10-02 05:45:04 +00:00
class KnowledgeModel(BaseModel):
2024-10-02 00:35:35 +00:00
model_config = ConfigDict(from_attributes=True)
id: str
user_id: str
name: str
description: str
data: Optional[dict] = None
meta: Optional[dict] = None
2024-11-15 04:13:43 +00:00
access_control: Optional[dict] = None
2024-11-15 02:57:25 +00:00
2024-10-02 00:35:35 +00:00
created_at: int # timestamp in epoch
updated_at: int # timestamp in epoch
####################
# Forms
####################
2024-11-18 13:51:01 +00:00
class KnowledgeUserModel(KnowledgeModel):
user: Optional[UserResponse] = None
class KnowledgeResponse(KnowledgeModel):
files: Optional[list[FileMetadataResponse | dict]] = None
2024-11-17 04:47:45 +00:00
2024-10-02 00:35:35 +00:00
2024-11-18 13:51:01 +00:00
class KnowledgeUserResponse(KnowledgeUserModel):
files: Optional[list[FileMetadataResponse | dict]] = None
2024-10-02 00:35:35 +00:00
2024-10-02 05:45:04 +00:00
class KnowledgeForm(BaseModel):
2024-10-02 00:35:35 +00:00
name: str
description: str
data: Optional[dict] = None
2024-11-17 04:47:45 +00:00
access_control: Optional[dict] = None
2024-10-03 03:42:10 +00:00
2024-10-02 05:45:04 +00:00
class KnowledgeTable:
def insert_new_knowledge(
self, user_id: str, form_data: KnowledgeForm
) -> Optional[KnowledgeModel]:
2024-10-02 00:35:35 +00:00
with get_db() as db:
2024-10-02 05:45:04 +00:00
knowledge = KnowledgeModel(
2024-10-02 00:35:35 +00:00
**{
**form_data.model_dump(),
2024-10-02 04:32:59 +00:00
"id": str(uuid.uuid4()),
2024-10-02 00:35:35 +00:00
"user_id": user_id,
"created_at": int(time.time()),
"updated_at": int(time.time()),
}
)
try:
2024-10-02 05:45:04 +00:00
result = Knowledge(**knowledge.model_dump())
2024-10-02 00:35:35 +00:00
db.add(result)
db.commit()
db.refresh(result)
if result:
2024-10-02 05:45:04 +00:00
return KnowledgeModel.model_validate(result)
2024-10-02 00:35:35 +00:00
else:
return None
except Exception:
return None
2024-11-18 13:51:01 +00:00
def get_knowledge_bases(self) -> list[KnowledgeUserModel]:
2024-10-02 00:35:35 +00:00
with get_db() as db:
return [
2024-11-18 13:51:01 +00:00
KnowledgeUserModel.model_validate(
{
**KnowledgeModel.model_validate(knowledge).model_dump(),
"user": Users.get_user_by_id(knowledge.user_id).model_dump(),
}
)
2024-10-02 05:45:04 +00:00
for knowledge in db.query(Knowledge)
.order_by(Knowledge.updated_at.desc())
2024-10-02 04:35:18 +00:00
.all()
2024-10-02 00:35:35 +00:00
]
2024-11-17 00:51:55 +00:00
def get_knowledge_bases_by_user_id(
self, user_id: str, permission: str = "write"
2024-11-18 13:51:01 +00:00
) -> list[KnowledgeUserModel]:
2024-11-17 00:51:55 +00:00
knowledge_bases = self.get_knowledge_bases()
return [
knowledge_base
for knowledge_base in knowledge_bases
if knowledge_base.user_id == user_id
or has_access(user_id, permission, knowledge_base.access_control)
]
2024-10-02 05:45:04 +00:00
def get_knowledge_by_id(self, id: str) -> Optional[KnowledgeModel]:
2024-10-02 00:35:35 +00:00
try:
with get_db() as db:
2024-10-02 05:45:04 +00:00
knowledge = db.query(Knowledge).filter_by(id=id).first()
return KnowledgeModel.model_validate(knowledge) if knowledge else None
2024-10-02 00:35:35 +00:00
except Exception:
return None
2024-10-02 05:45:04 +00:00
def update_knowledge_by_id(
2024-11-17 04:47:45 +00:00
self, id: str, form_data: KnowledgeForm, overwrite: bool = False
) -> Optional[KnowledgeModel]:
try:
with get_db() as db:
knowledge = self.get_knowledge_by_id(id=id)
db.query(Knowledge).filter_by(id=id).update(
{
**form_data.model_dump(),
"updated_at": int(time.time()),
}
)
db.commit()
return self.get_knowledge_by_id(id=id)
except Exception as e:
log.exception(e)
return None
def update_knowledge_data_by_id(
self, id: str, data: dict
2024-10-02 05:45:04 +00:00
) -> Optional[KnowledgeModel]:
2024-10-02 00:35:35 +00:00
try:
with get_db() as db:
2024-10-03 13:46:20 +00:00
knowledge = self.get_knowledge_by_id(id=id)
2024-10-02 05:45:04 +00:00
db.query(Knowledge).filter_by(id=id).update(
2024-10-02 00:35:35 +00:00
{
2024-11-17 04:47:45 +00:00
"data": data,
2024-10-03 03:42:10 +00:00
"updated_at": int(time.time()),
2024-10-02 00:35:35 +00:00
}
)
db.commit()
2024-10-03 03:42:10 +00:00
return self.get_knowledge_by_id(id=id)
2024-10-02 00:35:35 +00:00
except Exception as e:
log.exception(e)
return None
2024-10-02 05:45:04 +00:00
def delete_knowledge_by_id(self, id: str) -> bool:
2024-10-02 00:35:35 +00:00
try:
with get_db() as db:
2024-10-02 05:45:04 +00:00
db.query(Knowledge).filter_by(id=id).delete()
2024-10-02 00:35:35 +00:00
db.commit()
return True
except Exception:
return False
2024-10-13 10:02:02 +00:00
def delete_all_knowledge(self) -> bool:
with get_db() as db:
try:
db.query(Knowledge).delete()
db.commit()
return True
except Exception:
return False
2024-10-02 00:35:35 +00:00
2024-10-02 05:45:04 +00:00
Knowledges = KnowledgeTable()