open-webui/backend/open_webui/models/feedbacks.py

261 lines
7.9 KiB
Python
Raw Normal View History

2024-10-23 11:14:10 +08:00
import logging
import time
import uuid
from typing import Optional
2024-12-10 16:54:13 +08:00
from open_webui.internal.db import Base, get_db
from open_webui.models.chats import Chats
2024-10-23 11:14:10 +08:00
from open_webui.env import SRC_LOG_LEVELS
from pydantic import BaseModel, ConfigDict
from sqlalchemy import BigInteger, Column, Text, JSON, Boolean
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
####################
# Feedback DB Schema
####################
class Feedback(Base):
__tablename__ = "feedback"
id = Column(Text, primary_key=True)
user_id = Column(Text)
2024-10-23 13:55:34 +08:00
version = Column(BigInteger, default=0)
2024-10-23 11:14:10 +08:00
type = Column(Text)
data = Column(JSON, nullable=True)
meta = Column(JSON, nullable=True)
2024-10-23 13:55:34 +08:00
snapshot = Column(JSON, nullable=True)
2024-10-23 11:14:10 +08:00
created_at = Column(BigInteger)
updated_at = Column(BigInteger)
class FeedbackModel(BaseModel):
id: str
user_id: str
2024-10-23 13:55:34 +08:00
version: int
2024-10-23 11:14:10 +08:00
type: str
data: Optional[dict] = None
meta: Optional[dict] = None
2024-10-23 13:55:34 +08:00
snapshot: Optional[dict] = None
2024-10-23 11:14:10 +08:00
created_at: int
updated_at: int
model_config = ConfigDict(from_attributes=True)
####################
# Forms
####################
2024-10-23 13:55:34 +08:00
class FeedbackResponse(BaseModel):
id: str
user_id: str
version: int
type: str
data: Optional[dict] = None
meta: Optional[dict] = None
created_at: int
updated_at: int
2024-10-23 11:14:10 +08:00
2024-10-23 13:55:34 +08:00
class RatingData(BaseModel):
rating: Optional[str | int] = None
model_id: Optional[str] = None
sibling_model_ids: Optional[list[str]] = None
reason: Optional[str] = None
comment: Optional[str] = None
2024-10-24 03:33:00 +08:00
model_config = ConfigDict(extra="allow", protected_namespaces=())
2024-10-23 11:14:10 +08:00
class MetaData(BaseModel):
2024-10-23 13:55:34 +08:00
arena: Optional[bool] = None
chat_id: Optional[str] = None
2024-10-23 11:14:10 +08:00
message_id: Optional[str] = None
tags: Optional[list[str]] = None
model_config = ConfigDict(extra="allow")
2024-10-23 13:55:34 +08:00
class SnapshotData(BaseModel):
chat: Optional[dict] = None
model_config = ConfigDict(extra="allow")
2024-10-23 11:14:10 +08:00
class FeedbackForm(BaseModel):
type: str
2024-10-23 13:55:34 +08:00
data: Optional[RatingData] = None
2024-10-23 11:14:10 +08:00
meta: Optional[dict] = None
2024-10-23 13:55:34 +08:00
snapshot: Optional[SnapshotData] = None
2024-10-23 11:14:10 +08:00
model_config = ConfigDict(extra="allow")
class FeedbackTable:
2025-08-14 19:46:18 +08:00
async def insert_new_feedback(
2024-10-23 11:14:10 +08:00
self, user_id: str, form_data: FeedbackForm
) -> Optional[FeedbackModel]:
2025-08-14 19:46:18 +08:00
async with get_db() as db:
2024-10-23 11:14:10 +08:00
id = str(uuid.uuid4())
feedback = FeedbackModel(
**{
"id": id,
"user_id": user_id,
2024-10-23 13:55:34 +08:00
"version": 0,
**form_data.model_dump(),
2024-10-23 11:14:10 +08:00
"created_at": int(time.time()),
2024-10-23 13:55:34 +08:00
"updated_at": int(time.time()),
2024-10-23 11:14:10 +08:00
}
)
try:
result = Feedback(**feedback.model_dump())
2025-08-14 19:46:18 +08:00
await db.add(result)
await db.commit()
await db.refresh(result)
2024-10-23 11:14:10 +08:00
if result:
return FeedbackModel.model_validate(result)
else:
return None
except Exception as e:
log.exception(f"Error creating a new feedback: {e}")
2024-10-23 11:14:10 +08:00
return None
2025-08-14 19:46:18 +08:00
async def get_feedback_by_id(self, id: str) -> Optional[FeedbackModel]:
2024-10-23 11:14:10 +08:00
try:
2025-08-14 19:46:18 +08:00
async with get_db() as db:
feedback = await db.query(Feedback).filter_by(id=id).first()
2024-10-23 11:14:10 +08:00
if not feedback:
return None
return FeedbackModel.model_validate(feedback)
except Exception:
return None
2025-08-14 19:46:18 +08:00
async def get_feedback_by_id_and_user_id(
2024-10-23 13:55:34 +08:00
self, id: str, user_id: str
) -> Optional[FeedbackModel]:
try:
2025-08-14 19:46:18 +08:00
async with get_db() as db:
feedback = (
await db.query(Feedback).filter_by(id=id, user_id=user_id).first()
)
2024-10-23 13:55:34 +08:00
if not feedback:
return None
return FeedbackModel.model_validate(feedback)
except Exception:
return None
2025-08-14 19:46:18 +08:00
async def get_all_feedbacks(self) -> list[FeedbackModel]:
async with get_db() as db:
2024-10-23 13:55:34 +08:00
return [
FeedbackModel.model_validate(feedback)
2025-08-14 19:46:18 +08:00
for feedback in await db.query(Feedback)
2024-10-23 14:24:49 +08:00
.order_by(Feedback.updated_at.desc())
.all()
2024-10-23 13:55:34 +08:00
]
2025-08-14 19:46:18 +08:00
async def get_feedbacks_by_type(self, type: str) -> list[FeedbackModel]:
async with get_db() as db:
2024-10-23 11:14:10 +08:00
return [
FeedbackModel.model_validate(feedback)
2025-08-14 19:46:18 +08:00
for feedback in await db.query(Feedback)
2024-10-23 14:24:49 +08:00
.filter_by(type=type)
.order_by(Feedback.updated_at.desc())
.all()
2024-10-23 11:14:10 +08:00
]
2025-08-14 19:46:18 +08:00
async def get_feedbacks_by_user_id(self, user_id: str) -> list[FeedbackModel]:
async with get_db() as db:
2024-10-23 11:14:10 +08:00
return [
FeedbackModel.model_validate(feedback)
2025-08-14 19:46:18 +08:00
for feedback in await db.query(Feedback)
2024-10-23 14:24:49 +08:00
.filter_by(user_id=user_id)
.order_by(Feedback.updated_at.desc())
.all()
2024-10-23 11:14:10 +08:00
]
2025-08-14 19:46:18 +08:00
async def update_feedback_by_id(
2024-10-23 11:14:10 +08:00
self, id: str, form_data: FeedbackForm
) -> Optional[FeedbackModel]:
2025-08-14 19:46:18 +08:00
async with get_db() as db:
feedback = await db.query(Feedback).filter_by(id=id).first()
2024-10-23 11:14:10 +08:00
if not feedback:
return None
if form_data.data:
2024-10-23 13:55:34 +08:00
feedback.data = form_data.data.model_dump()
if form_data.meta:
feedback.meta = form_data.meta
if form_data.snapshot:
feedback.snapshot = form_data.snapshot.model_dump()
feedback.updated_at = int(time.time())
2025-08-14 19:46:18 +08:00
await db.commit()
2024-10-23 13:55:34 +08:00
return FeedbackModel.model_validate(feedback)
2025-08-14 19:46:18 +08:00
async def update_feedback_by_id_and_user_id(
2024-10-23 13:55:34 +08:00
self, id: str, user_id: str, form_data: FeedbackForm
) -> Optional[FeedbackModel]:
2025-08-14 19:46:18 +08:00
async with get_db() as db:
feedback = (
await db.query(Feedback).filter_by(id=id, user_id=user_id).first()
)
2024-10-23 13:55:34 +08:00
if not feedback:
return None
if form_data.data:
feedback.data = form_data.data.model_dump()
2024-10-23 11:14:10 +08:00
if form_data.meta:
feedback.meta = form_data.meta
2024-10-23 13:55:34 +08:00
if form_data.snapshot:
feedback.snapshot = form_data.snapshot.model_dump()
2024-10-23 11:14:10 +08:00
feedback.updated_at = int(time.time())
2025-08-14 19:46:18 +08:00
await db.commit()
2024-10-23 11:14:10 +08:00
return FeedbackModel.model_validate(feedback)
2025-08-14 19:46:18 +08:00
async def delete_feedback_by_id(self, id: str) -> bool:
async with get_db() as db:
feedback = await db.query(Feedback).filter_by(id=id).first()
2024-10-23 11:14:10 +08:00
if not feedback:
return False
2025-08-14 19:46:18 +08:00
await db.delete(feedback)
await db.commit()
2024-10-23 11:14:10 +08:00
return True
2025-08-14 19:46:18 +08:00
async def delete_feedback_by_id_and_user_id(self, id: str, user_id: str) -> bool:
async with get_db() as db:
feedback = (
await db.query(Feedback).filter_by(id=id, user_id=user_id).first()
)
2024-10-23 13:55:34 +08:00
if not feedback:
return False
2025-08-14 19:46:18 +08:00
await db.delete(feedback)
await db.commit()
2024-10-23 13:55:34 +08:00
return True
2025-08-14 19:46:18 +08:00
async def delete_feedbacks_by_user_id(self, user_id: str) -> bool:
async with get_db() as db:
feedbacks = await db.query(Feedback).filter_by(user_id=user_id).all()
2024-10-23 13:55:34 +08:00
if not feedbacks:
return False
for feedback in feedbacks:
2025-08-14 19:46:18 +08:00
await db.delete(feedback)
await db.commit()
2024-10-23 13:55:34 +08:00
return True
2025-08-14 19:46:18 +08:00
async def delete_all_feedbacks(self) -> bool:
async with get_db() as db:
feedbacks = await db.query(Feedback).all()
2024-10-23 13:55:34 +08:00
if not feedbacks:
return False
for feedback in feedbacks:
2025-08-14 19:46:18 +08:00
await db.delete(feedback)
await db.commit()
2024-10-23 13:55:34 +08:00
return True
2024-10-23 11:14:10 +08:00
Feedbacks = FeedbackTable()