refac
This commit is contained in:
1 parent
56ae99e96a
commit
40c09167cd
5 files changed
+112
-37
No files matched your search
@@ -957,6 +957,20 @@ class ChatTable:
|
|||||||
all_chats = result.scalars().all()
|
all_chats = result.scalars().all()
|
||||||
return [ChatModel.model_validate(chat) for chat in all_chats]
|
return [ChatModel.model_validate(chat) for chat in all_chats]
|
||||||
|
|
||||||
|
async def get_chat_metas_by_chat_ids(
|
||||||
|
self,
|
||||||
|
chat_ids: list[str],
|
||||||
|
include_archived: bool = False,
|
||||||
|
db: AsyncSession | None = None,
|
||||||
|
) -> list[dict]:
|
||||||
|
async with get_async_db_context(db) as session:
|
||||||
|
stmt = select(Chat.meta).filter(Chat.id.in_(chat_ids))
|
||||||
|
if not include_archived:
|
||||||
|
stmt = stmt.filter_by(archived=False)
|
||||||
|
|
||||||
|
result = await session.execute(stmt)
|
||||||
|
return [meta for meta in result.scalars().all() if isinstance(meta, dict)]
|
||||||
|
|
||||||
# retrieve conversation
|
# retrieve conversation
|
||||||
async def get_chat_by_id(
|
async def get_chat_by_id(
|
||||||
self,
|
self,
|
||||||
@@ -1389,7 +1403,6 @@ class ChatTable:
|
|||||||
for chat in all_chats
|
for chat in all_chats
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
async def get_chats_by_folder_ids_and_user_id(
|
async def get_chats_by_folder_ids_and_user_id(
|
||||||
self, folder_ids: list[str], user_id: str, db: AsyncSession | None = None
|
self, folder_ids: list[str], user_id: str, db: AsyncSession | None = None
|
||||||
) -> list[ChatModel]:
|
) -> list[ChatModel]:
|
||||||
|
|||||||
@@ -133,6 +133,12 @@ class ModelHistoryEntry(BaseModel):
|
|||||||
lost: int
|
lost: int
|
||||||
|
|
||||||
|
|
||||||
|
class ModelHistoryCounts(BaseModel):
|
||||||
|
date: str
|
||||||
|
won: int = 0
|
||||||
|
lost: int = 0
|
||||||
|
|
||||||
|
|
||||||
class ModelHistoryResponse(BaseModel):
|
class ModelHistoryResponse(BaseModel):
|
||||||
model_id: str
|
model_id: str
|
||||||
history: list[ModelHistoryEntry]
|
history: list[ModelHistoryEntry]
|
||||||
@@ -375,6 +381,45 @@ class FeedbackTable:
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
async def get_model_feedback_counts_by_day(
|
||||||
|
self,
|
||||||
|
model_id: str,
|
||||||
|
start_date: Optional[int] = None,
|
||||||
|
db: Optional[AsyncSession] = None,
|
||||||
|
) -> list[ModelHistoryCounts]:
|
||||||
|
"""Get aggregated feedback counts per day for a model, preserving all matching days."""
|
||||||
|
from collections import defaultdict
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
async with get_async_db_context(db) as db:
|
||||||
|
stmt = select(Feedback.created_at, Feedback.data).filter(Feedback.data['model_id'].as_string() == model_id)
|
||||||
|
if start_date is not None:
|
||||||
|
stmt = stmt.filter(Feedback.created_at >= start_date)
|
||||||
|
|
||||||
|
result = await db.execute(stmt.order_by(Feedback.created_at.asc()))
|
||||||
|
rows = result.all()
|
||||||
|
|
||||||
|
daily_counts = defaultdict(lambda: {'won': 0, 'lost': 0})
|
||||||
|
|
||||||
|
for created_at, data in rows:
|
||||||
|
if not data:
|
||||||
|
continue
|
||||||
|
|
||||||
|
rating_str = str(data.get('rating', ''))
|
||||||
|
if rating_str not in ('1', '-1'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
date_str = datetime.fromtimestamp(created_at).strftime('%Y-%m-%d')
|
||||||
|
if rating_str == '1':
|
||||||
|
daily_counts[date_str]['won'] += 1
|
||||||
|
else:
|
||||||
|
daily_counts[date_str]['lost'] += 1
|
||||||
|
|
||||||
|
return [
|
||||||
|
ModelHistoryCounts(date=date_str, won=counts['won'], lost=counts['lost'])
|
||||||
|
for date_str, counts in sorted(daily_counts.items())
|
||||||
|
]
|
||||||
|
|
||||||
async def get_feedbacks_by_type(self, type: str, db: Optional[AsyncSession] = None) -> list[FeedbackModel]:
|
async def get_feedbacks_by_type(self, type: str, db: Optional[AsyncSession] = None) -> list[FeedbackModel]:
|
||||||
async with get_async_db_context(db) as db:
|
async with get_async_db_context(db) as db:
|
||||||
result = await db.execute(select(Feedback).filter_by(type=type).order_by(Feedback.updated_at.desc()))
|
result = await db.execute(select(Feedback).filter_by(type=type).order_by(Feedback.updated_at.desc()))
|
||||||
|
|||||||
@@ -367,6 +367,12 @@ async def get_model_overview(
|
|||||||
):
|
):
|
||||||
"""Get model overview with feedback history and chat tags."""
|
"""Get model overview with feedback history and chat tags."""
|
||||||
|
|
||||||
|
# Calculate start date for history
|
||||||
|
now = datetime.now()
|
||||||
|
start_dt = None
|
||||||
|
if days > 0:
|
||||||
|
start_dt = now - timedelta(days=days)
|
||||||
|
|
||||||
# Get chat IDs that used this model
|
# Get chat IDs that used this model
|
||||||
chat_ids = await ChatMessages.get_chat_ids_by_model_id(
|
chat_ids = await ChatMessages.get_chat_ids_by_model_id(
|
||||||
model_id=model_id,
|
model_id=model_id,
|
||||||
@@ -377,31 +383,18 @@ async def get_model_overview(
|
|||||||
db=db,
|
db=db,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get feedback history per day
|
history_rows = await Feedbacks.get_model_feedback_counts_by_day(
|
||||||
history_counts: dict[str, dict] = defaultdict(lambda: {'won': 0, 'lost': 0})
|
model_id=model_id,
|
||||||
|
start_date=int(start_dt.timestamp()) if start_dt else None,
|
||||||
# Calculate start date for history
|
db=db,
|
||||||
now = datetime.now()
|
)
|
||||||
start_dt = None
|
history_counts = {
|
||||||
if days > 0:
|
entry.date: {
|
||||||
start_dt = now - timedelta(days=days)
|
'won': entry.won,
|
||||||
|
'lost': entry.lost,
|
||||||
for chat_id in chat_ids:
|
}
|
||||||
feedbacks = await Feedbacks.get_feedbacks_by_chat_id(chat_id, db=db)
|
for entry in history_rows
|
||||||
for fb in feedbacks:
|
}
|
||||||
if fb.data and 'rating' in fb.data:
|
|
||||||
rating = fb.data['rating']
|
|
||||||
fb_date = datetime.fromtimestamp(fb.created_at)
|
|
||||||
|
|
||||||
# Filter by date range
|
|
||||||
if start_dt and fb_date < start_dt:
|
|
||||||
continue
|
|
||||||
|
|
||||||
date_str = fb_date.strftime('%Y-%m-%d')
|
|
||||||
if rating == 1:
|
|
||||||
history_counts[date_str]['won'] += 1
|
|
||||||
elif rating == -1:
|
|
||||||
history_counts[date_str]['lost'] += 1
|
|
||||||
|
|
||||||
# Fill in missing days
|
# Fill in missing days
|
||||||
history = []
|
history = []
|
||||||
@@ -430,10 +423,14 @@ async def get_model_overview(
|
|||||||
|
|
||||||
# Get chat tags
|
# Get chat tags
|
||||||
tag_counts: dict[str, int] = defaultdict(int)
|
tag_counts: dict[str, int] = defaultdict(int)
|
||||||
for chat_id in chat_ids:
|
if chat_ids:
|
||||||
chat = await Chats.get_chat_by_id(chat_id, db=db)
|
chat_metas = await Chats.get_chat_metas_by_chat_ids(
|
||||||
if chat and chat.meta:
|
chat_ids,
|
||||||
for tag in chat.meta.get('tags', []):
|
include_archived=True,
|
||||||
|
db=db,
|
||||||
|
)
|
||||||
|
for meta in chat_metas:
|
||||||
|
for tag in meta.get('tags', []):
|
||||||
tag_counts[tag] += 1
|
tag_counts[tag] += 1
|
||||||
|
|
||||||
# Sort by count and take top 10
|
# Sort by count and take top 10
|
||||||
|
|||||||
@@ -368,7 +368,11 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None)
|
|||||||
|
|
||||||
models_dict = {model['id']: model for model in models}
|
models_dict = {model['id']: model for model in models}
|
||||||
if isinstance(request.app.state.MODELS, RedisDict):
|
if isinstance(request.app.state.MODELS, RedisDict):
|
||||||
request.app.state.MODELS.set(models_dict)
|
try:
|
||||||
|
request.app.state.MODELS.set(models_dict)
|
||||||
|
except Exception as e:
|
||||||
|
log.warning(f'Failed to update Redis model cache, using in-process cache: {e}')
|
||||||
|
request.app.state.MODELS = models_dict
|
||||||
else:
|
else:
|
||||||
request.app.state.MODELS = models_dict
|
request.app.state.MODELS = models_dict
|
||||||
|
|
||||||
|
|||||||
@@ -46,8 +46,9 @@
|
|||||||
try {
|
try {
|
||||||
const result = await getLeaderboard(localStorage.token, searchQuery);
|
const result = await getLeaderboard(localStorage.token, searchQuery);
|
||||||
const statsMap = new Map((result?.entries ?? []).map((e) => [e.model_id, e]));
|
const statsMap = new Map((result?.entries ?? []).map((e) => [e.model_id, e]));
|
||||||
|
const modelMap = new Map(($models ?? []).map((m) => [m.id, m]));
|
||||||
|
|
||||||
rankedModels = $models
|
const activeModels = $models
|
||||||
.filter((m) => m?.owned_by !== 'arena' && !m?.info?.meta?.hidden)
|
.filter((m) => m?.owned_by !== 'arena' && !m?.info?.meta?.hidden)
|
||||||
.map((model) => {
|
.map((model) => {
|
||||||
const s = statsMap.get(model.id);
|
const s = statsMap.get(model.id);
|
||||||
@@ -61,12 +62,27 @@
|
|||||||
},
|
},
|
||||||
top_tags: s?.top_tags ?? []
|
top_tags: s?.top_tags ?? []
|
||||||
};
|
};
|
||||||
})
|
|
||||||
.sort((a, b) => {
|
|
||||||
if (a.rating === '-') return 1;
|
|
||||||
if (b.rating === '-') return -1;
|
|
||||||
return b.rating - a.rating;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const evaluatedModels = (result?.entries ?? [])
|
||||||
|
.filter((entry) => !modelMap.has(entry.model_id))
|
||||||
|
.map((entry) => ({
|
||||||
|
id: entry.model_id,
|
||||||
|
name: entry.model_id,
|
||||||
|
rating: entry.rating,
|
||||||
|
stats: {
|
||||||
|
count: entry.won + entry.lost,
|
||||||
|
won: entry.won.toString(),
|
||||||
|
lost: entry.lost.toString()
|
||||||
|
},
|
||||||
|
top_tags: entry.top_tags ?? []
|
||||||
|
}));
|
||||||
|
|
||||||
|
rankedModels = [...activeModels, ...evaluatedModels].sort((a, b) => {
|
||||||
|
if (a.rating === '-') return 1;
|
||||||
|
if (b.rating === '-') return -1;
|
||||||
|
return b.rating - a.rating;
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Leaderboard load failed:', err);
|
console.error('Leaderboard load failed:', err);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user