Skip to content

Commit 60e4d75

Browse files
committed
refac
1 parent 4632f20 commit 60e4d75

4 files changed

Lines changed: 383 additions & 225 deletions

File tree

backend/open_webui/models/feedbacks.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,13 @@ def get_feedback_items(
215215
query = db.query(Feedback, User).join(User, Feedback.user_id == User.id)
216216

217217
if filter:
218+
# Apply model_id filter (exact match)
219+
model_id = filter.get('model_id')
220+
if model_id:
221+
query = query.filter(
222+
Feedback.data['model_id'].as_string() == model_id
223+
)
224+
218225
order_by = filter.get('order_by')
219226
direction = filter.get('direction')
220227

@@ -288,6 +295,17 @@ def get_all_feedback_ids(self, db: Optional[Session] = None) -> list[FeedbackIdR
288295
.all()
289296
]
290297

298+
def get_distinct_model_ids(self, db: Optional[Session] = None) -> list[str]:
299+
"""Get distinct model_ids from feedback data for filter dropdowns."""
300+
with get_db_context(db) as db:
301+
rows = (
302+
db.query(Feedback.data['model_id'].as_string())
303+
.filter(Feedback.data['model_id'].as_string().isnot(None))
304+
.distinct()
305+
.all()
306+
)
307+
return sorted([row[0] for row in rows if row[0]])
308+
291309
def get_feedbacks_for_leaderboard(self, db: Optional[Session] = None) -> list[LeaderboardFeedbackData]:
292310
"""Fetch only id and data for leaderboard computation (excludes snapshot/meta)."""
293311
with get_db_context(db) as db:

backend/open_webui/routers/evaluations.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,11 @@ async def update_config(
291291
}
292292

293293

294+
@router.get('/feedbacks/models', response_model=list[str])
295+
async def get_feedback_model_ids(user=Depends(get_admin_user), db: Session = Depends(get_session)):
296+
return Feedbacks.get_distinct_model_ids(db=db)
297+
298+
294299
@router.get('/feedbacks/all', response_model=list[FeedbackResponse])
295300
async def get_all_feedbacks(user=Depends(get_admin_user), db: Session = Depends(get_session)):
296301
feedbacks = Feedbacks.get_all_feedbacks(db=db)
@@ -309,8 +314,17 @@ async def delete_all_feedbacks(user=Depends(get_admin_user), db: Session = Depen
309314

310315

311316
@router.get('/feedbacks/all/export', response_model=list[FeedbackModel])
312-
async def export_all_feedbacks(user=Depends(get_admin_user), db: Session = Depends(get_session)):
317+
async def export_all_feedbacks(
318+
model_id: Optional[str] = None,
319+
user=Depends(get_admin_user),
320+
db: Session = Depends(get_session),
321+
):
313322
feedbacks = Feedbacks.get_all_feedbacks(db=db)
323+
if model_id:
324+
feedbacks = [
325+
f for f in feedbacks
326+
if f.data and f.data.get('model_id') == model_id
327+
]
314328
return feedbacks
315329

316330

@@ -334,6 +348,7 @@ async def get_feedbacks(
334348
order_by: Optional[str] = None,
335349
direction: Optional[str] = None,
336350
page: Optional[int] = 1,
351+
model_id: Optional[str] = None,
337352
user=Depends(get_admin_user),
338353
db: Session = Depends(get_session),
339354
):
@@ -347,6 +362,8 @@ async def get_feedbacks(
347362
filter['order_by'] = order_by
348363
if direction:
349364
filter['direction'] = direction
365+
if model_id:
366+
filter['model_id'] = model_id
350367

351368
result = Feedbacks.get_feedback_items(filter=filter, skip=skip, limit=limit, db=db)
352369
return result

src/lib/apis/evaluations/index.ts

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,42 @@ export const getModelHistory = async (token: string = '', modelId: string, days:
161161
return res;
162162
};
163163

164-
export const getFeedbackItems = async (token: string = '', orderBy, direction, page) => {
164+
export const getFeedbackModelIds = async (token: string = '') => {
165+
let error = null;
166+
167+
const res = await fetch(`${WEBUI_API_BASE_URL}/evaluations/feedbacks/models`, {
168+
method: 'GET',
169+
headers: {
170+
Accept: 'application/json',
171+
'Content-Type': 'application/json',
172+
authorization: `Bearer ${token}`
173+
}
174+
})
175+
.then(async (res) => {
176+
if (!res.ok) throw await res.json();
177+
return res.json();
178+
})
179+
.catch((err) => {
180+
error = err.detail;
181+
console.error(err);
182+
return null;
183+
});
184+
185+
if (error) {
186+
throw error;
187+
}
188+
189+
return res;
190+
};
191+
192+
export const getFeedbackItems = async (token: string = '', orderBy, direction, page, modelId: string = '') => {
165193
let error = null;
166194

167195
const searchParams = new URLSearchParams();
168196
if (orderBy) searchParams.append('order_by', orderBy);
169197
if (direction) searchParams.append('direction', direction);
170198
if (page) searchParams.append('page', page.toString());
199+
if (modelId) searchParams.append('model_id', modelId);
171200

172201
const res = await fetch(
173202
`${WEBUI_API_BASE_URL}/evaluations/feedbacks/list?${searchParams.toString()}`,
@@ -200,10 +229,13 @@ export const getFeedbackItems = async (token: string = '', orderBy, direction, p
200229
return res;
201230
};
202231

203-
export const exportAllFeedbacks = async (token: string = '') => {
232+
export const exportAllFeedbacks = async (token: string = '', modelId: string = '') => {
204233
let error = null;
205234

206-
const res = await fetch(`${WEBUI_API_BASE_URL}/evaluations/feedbacks/all/export`, {
235+
const searchParams = new URLSearchParams();
236+
if (modelId) searchParams.append('model_id', modelId);
237+
238+
const res = await fetch(`${WEBUI_API_BASE_URL}/evaluations/feedbacks/all/export?${searchParams.toString()}`, {
207239
method: 'GET',
208240
headers: {
209241
Accept: 'application/json',

0 commit comments

Comments
 (0)