refac
This commit is contained in:
@@ -53,18 +53,16 @@ class UserAnalyticsResponse(BaseModel):
|
||||
####################
|
||||
|
||||
|
||||
@router.get("/models", response_model=ModelAnalyticsResponse)
|
||||
@router.get('/models', response_model=ModelAnalyticsResponse)
|
||||
async def get_model_analytics(
|
||||
start_date: Optional[int] = Query(None, description="Start timestamp (epoch)"),
|
||||
end_date: Optional[int] = Query(None, description="End timestamp (epoch)"),
|
||||
group_id: Optional[str] = Query(None, description="Filter by user group ID"),
|
||||
start_date: Optional[int] = Query(None, description='Start timestamp (epoch)'),
|
||||
end_date: Optional[int] = Query(None, description='End timestamp (epoch)'),
|
||||
group_id: Optional[str] = Query(None, description='Filter by user group ID'),
|
||||
user=Depends(get_admin_user),
|
||||
db: Session = Depends(get_session),
|
||||
):
|
||||
"""Get message counts per model."""
|
||||
counts = ChatMessages.get_message_count_by_model(
|
||||
start_date=start_date, end_date=end_date, group_id=group_id, db=db
|
||||
)
|
||||
counts = ChatMessages.get_message_count_by_model(start_date=start_date, end_date=end_date, group_id=group_id, db=db)
|
||||
models = [
|
||||
ModelAnalyticsEntry(model_id=model_id, count=count)
|
||||
for model_id, count in sorted(counts.items(), key=lambda x: -x[1])
|
||||
@@ -72,27 +70,23 @@ async def get_model_analytics(
|
||||
return ModelAnalyticsResponse(models=models)
|
||||
|
||||
|
||||
@router.get("/users", response_model=UserAnalyticsResponse)
|
||||
@router.get('/users', response_model=UserAnalyticsResponse)
|
||||
async def get_user_analytics(
|
||||
start_date: Optional[int] = Query(None, description="Start timestamp (epoch)"),
|
||||
end_date: Optional[int] = Query(None, description="End timestamp (epoch)"),
|
||||
group_id: Optional[str] = Query(None, description="Filter by user group ID"),
|
||||
limit: int = Query(50, description="Max users to return"),
|
||||
start_date: Optional[int] = Query(None, description='Start timestamp (epoch)'),
|
||||
end_date: Optional[int] = Query(None, description='End timestamp (epoch)'),
|
||||
group_id: Optional[str] = Query(None, description='Filter by user group ID'),
|
||||
limit: int = Query(50, description='Max users to return'),
|
||||
user=Depends(get_admin_user),
|
||||
db: Session = Depends(get_session),
|
||||
):
|
||||
"""Get message counts and token usage per user with user info."""
|
||||
counts = ChatMessages.get_message_count_by_user(
|
||||
start_date=start_date, end_date=end_date, group_id=group_id, db=db
|
||||
)
|
||||
counts = ChatMessages.get_message_count_by_user(start_date=start_date, end_date=end_date, group_id=group_id, db=db)
|
||||
token_usage = ChatMessages.get_token_usage_by_user(
|
||||
start_date=start_date, end_date=end_date, group_id=group_id, db=db
|
||||
)
|
||||
|
||||
# Get user info for top users
|
||||
top_user_ids = [
|
||||
uid for uid, _ in sorted(counts.items(), key=lambda x: -x[1])[:limit]
|
||||
]
|
||||
top_user_ids = [uid for uid, _ in sorted(counts.items(), key=lambda x: -x[1])[:limit]]
|
||||
user_info = {u.id: u for u in Users.get_users_by_user_ids(top_user_ids, db=db)}
|
||||
|
||||
users = []
|
||||
@@ -105,22 +99,22 @@ async def get_user_analytics(
|
||||
name=u.name if u else None,
|
||||
email=u.email if u else None,
|
||||
count=counts[user_id],
|
||||
input_tokens=tokens.get("input_tokens", 0),
|
||||
output_tokens=tokens.get("output_tokens", 0),
|
||||
total_tokens=tokens.get("total_tokens", 0),
|
||||
input_tokens=tokens.get('input_tokens', 0),
|
||||
output_tokens=tokens.get('output_tokens', 0),
|
||||
total_tokens=tokens.get('total_tokens', 0),
|
||||
)
|
||||
)
|
||||
|
||||
return UserAnalyticsResponse(users=users)
|
||||
|
||||
|
||||
@router.get("/messages", response_model=list[ChatMessageModel])
|
||||
@router.get('/messages', response_model=list[ChatMessageModel])
|
||||
async def get_messages(
|
||||
model_id: Optional[str] = Query(None, description="Filter by model ID"),
|
||||
user_id: Optional[str] = Query(None, description="Filter by user ID"),
|
||||
chat_id: Optional[str] = Query(None, description="Filter by chat ID"),
|
||||
start_date: Optional[int] = Query(None, description="Start timestamp (epoch)"),
|
||||
end_date: Optional[int] = Query(None, description="End timestamp (epoch)"),
|
||||
model_id: Optional[str] = Query(None, description='Filter by model ID'),
|
||||
user_id: Optional[str] = Query(None, description='Filter by user ID'),
|
||||
chat_id: Optional[str] = Query(None, description='Filter by chat ID'),
|
||||
start_date: Optional[int] = Query(None, description='Start timestamp (epoch)'),
|
||||
end_date: Optional[int] = Query(None, description='End timestamp (epoch)'),
|
||||
skip: int = Query(0),
|
||||
limit: int = Query(50, le=100),
|
||||
user=Depends(get_admin_user),
|
||||
@@ -139,9 +133,7 @@ async def get_messages(
|
||||
db=db,
|
||||
)
|
||||
elif user_id:
|
||||
return ChatMessages.get_messages_by_user_id(
|
||||
user_id=user_id, skip=skip, limit=limit, db=db
|
||||
)
|
||||
return ChatMessages.get_messages_by_user_id(user_id=user_id, skip=skip, limit=limit, db=db)
|
||||
else:
|
||||
# Return empty if no filter specified
|
||||
return []
|
||||
@@ -154,11 +146,11 @@ class SummaryResponse(BaseModel):
|
||||
total_users: int
|
||||
|
||||
|
||||
@router.get("/summary", response_model=SummaryResponse)
|
||||
@router.get('/summary', response_model=SummaryResponse)
|
||||
async def get_summary(
|
||||
start_date: Optional[int] = Query(None, description="Start timestamp (epoch)"),
|
||||
end_date: Optional[int] = Query(None, description="End timestamp (epoch)"),
|
||||
group_id: Optional[str] = Query(None, description="Filter by user group ID"),
|
||||
start_date: Optional[int] = Query(None, description='Start timestamp (epoch)'),
|
||||
end_date: Optional[int] = Query(None, description='End timestamp (epoch)'),
|
||||
group_id: Optional[str] = Query(None, description='Filter by user group ID'),
|
||||
user=Depends(get_admin_user),
|
||||
db: Session = Depends(get_session),
|
||||
):
|
||||
@@ -190,29 +182,24 @@ class DailyStatsResponse(BaseModel):
|
||||
data: list[DailyStatsEntry]
|
||||
|
||||
|
||||
@router.get("/daily", response_model=DailyStatsResponse)
|
||||
@router.get('/daily', response_model=DailyStatsResponse)
|
||||
async def get_daily_stats(
|
||||
start_date: Optional[int] = Query(None, description="Start timestamp (epoch)"),
|
||||
end_date: Optional[int] = Query(None, description="End timestamp (epoch)"),
|
||||
group_id: Optional[str] = Query(None, description="Filter by user group ID"),
|
||||
granularity: str = Query("daily", description="Granularity: 'hourly' or 'daily'"),
|
||||
start_date: Optional[int] = Query(None, description='Start timestamp (epoch)'),
|
||||
end_date: Optional[int] = Query(None, description='End timestamp (epoch)'),
|
||||
group_id: Optional[str] = Query(None, description='Filter by user group ID'),
|
||||
granularity: str = Query('daily', description="Granularity: 'hourly' or 'daily'"),
|
||||
user=Depends(get_admin_user),
|
||||
db: Session = Depends(get_session),
|
||||
):
|
||||
"""Get message counts grouped by model for time-series chart."""
|
||||
if granularity == "hourly":
|
||||
counts = ChatMessages.get_hourly_message_counts_by_model(
|
||||
start_date=start_date, end_date=end_date, db=db
|
||||
)
|
||||
if granularity == 'hourly':
|
||||
counts = ChatMessages.get_hourly_message_counts_by_model(start_date=start_date, end_date=end_date, db=db)
|
||||
else:
|
||||
counts = ChatMessages.get_daily_message_counts_by_model(
|
||||
start_date=start_date, end_date=end_date, group_id=group_id, db=db
|
||||
)
|
||||
return DailyStatsResponse(
|
||||
data=[
|
||||
DailyStatsEntry(date=date, models=models)
|
||||
for date, models in sorted(counts.items())
|
||||
]
|
||||
data=[DailyStatsEntry(date=date, models=models) for date, models in sorted(counts.items())]
|
||||
)
|
||||
|
||||
|
||||
@@ -231,22 +218,20 @@ class TokenUsageResponse(BaseModel):
|
||||
total_tokens: int
|
||||
|
||||
|
||||
@router.get("/tokens", response_model=TokenUsageResponse)
|
||||
@router.get('/tokens', response_model=TokenUsageResponse)
|
||||
async def get_token_usage(
|
||||
start_date: Optional[int] = Query(None),
|
||||
end_date: Optional[int] = Query(None),
|
||||
group_id: Optional[str] = Query(None, description="Filter by user group ID"),
|
||||
group_id: Optional[str] = Query(None, description='Filter by user group ID'),
|
||||
user=Depends(get_admin_user),
|
||||
db: Session = Depends(get_session),
|
||||
):
|
||||
"""Get token usage aggregated by model."""
|
||||
usage = ChatMessages.get_token_usage_by_model(
|
||||
start_date=start_date, end_date=end_date, group_id=group_id, db=db
|
||||
)
|
||||
usage = ChatMessages.get_token_usage_by_model(start_date=start_date, end_date=end_date, group_id=group_id, db=db)
|
||||
|
||||
models = [
|
||||
TokenUsageEntry(model_id=model_id, **data)
|
||||
for model_id, data in sorted(usage.items(), key=lambda x: -x[1]["total_tokens"])
|
||||
for model_id, data in sorted(usage.items(), key=lambda x: -x[1]['total_tokens'])
|
||||
]
|
||||
|
||||
total_input = sum(m.input_tokens for m in models)
|
||||
@@ -278,7 +263,7 @@ class ModelChatsResponse(BaseModel):
|
||||
total: int
|
||||
|
||||
|
||||
@router.get("/models/{model_id:path}/chats", response_model=ModelChatsResponse)
|
||||
@router.get('/models/{model_id:path}/chats', response_model=ModelChatsResponse)
|
||||
async def get_model_chats(
|
||||
model_id: str,
|
||||
start_date: Optional[int] = Query(None),
|
||||
@@ -311,7 +296,7 @@ async def get_model_chats(
|
||||
continue
|
||||
|
||||
# Get user_id from first user message
|
||||
first_user_msg = next((m for m in messages if m.role == "user"), None)
|
||||
first_user_msg = next((m for m in messages if m.role == 'user'), None)
|
||||
user_id = first_user_msg.user_id if first_user_msg else None
|
||||
|
||||
# Extract first message content as preview
|
||||
@@ -321,8 +306,8 @@ async def get_model_chats(
|
||||
if isinstance(content, str):
|
||||
first_message = content[:200]
|
||||
elif isinstance(content, list):
|
||||
text_parts = [b.get("text", "") for b in content if isinstance(b, dict)]
|
||||
first_message = " ".join(text_parts)[:200]
|
||||
text_parts = [b.get('text', '') for b in content if isinstance(b, dict)]
|
||||
first_message = ' '.join(text_parts)[:200]
|
||||
|
||||
# Get user info
|
||||
user_name = None
|
||||
@@ -367,10 +352,10 @@ class ModelOverviewResponse(BaseModel):
|
||||
tags: list[TagEntry]
|
||||
|
||||
|
||||
@router.get("/models/{model_id:path}/overview", response_model=ModelOverviewResponse)
|
||||
@router.get('/models/{model_id:path}/overview', response_model=ModelOverviewResponse)
|
||||
async def get_model_overview(
|
||||
model_id: str,
|
||||
days: int = Query(30, description="Number of days of history (0 for all)"),
|
||||
days: int = Query(30, description='Number of days of history (0 for all)'),
|
||||
user=Depends(get_admin_user),
|
||||
db: Session = Depends(get_session),
|
||||
):
|
||||
@@ -387,7 +372,7 @@ async def get_model_overview(
|
||||
)
|
||||
|
||||
# Get feedback history per day
|
||||
history_counts: dict[str, dict] = defaultdict(lambda: {"won": 0, "lost": 0})
|
||||
history_counts: dict[str, dict] = defaultdict(lambda: {'won': 0, 'lost': 0})
|
||||
|
||||
# Calculate start date for history
|
||||
now = datetime.now()
|
||||
@@ -398,19 +383,19 @@ async def get_model_overview(
|
||||
for chat_id in chat_ids:
|
||||
feedbacks = Feedbacks.get_feedbacks_by_chat_id(chat_id, db=db)
|
||||
for fb in feedbacks:
|
||||
if fb.data and "rating" in fb.data:
|
||||
rating = fb.data["rating"]
|
||||
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")
|
||||
date_str = fb_date.strftime('%Y-%m-%d')
|
||||
if rating == 1:
|
||||
history_counts[date_str]["won"] += 1
|
||||
history_counts[date_str]['won'] += 1
|
||||
elif rating == -1:
|
||||
history_counts[date_str]["lost"] += 1
|
||||
history_counts[date_str]['lost'] += 1
|
||||
|
||||
# Fill in missing days
|
||||
history = []
|
||||
@@ -421,18 +406,18 @@ async def get_model_overview(
|
||||
elif history_counts:
|
||||
# Find earliest date
|
||||
min_date = min(history_counts.keys())
|
||||
current = datetime.strptime(min_date, "%Y-%m-%d")
|
||||
current = datetime.strptime(min_date, '%Y-%m-%d')
|
||||
else:
|
||||
current = now
|
||||
|
||||
while current <= end_dt:
|
||||
date_str = current.strftime("%Y-%m-%d")
|
||||
counts = history_counts.get(date_str, {"won": 0, "lost": 0})
|
||||
date_str = current.strftime('%Y-%m-%d')
|
||||
counts = history_counts.get(date_str, {'won': 0, 'lost': 0})
|
||||
history.append(
|
||||
HistoryEntry(
|
||||
date=date_str,
|
||||
won=counts["won"],
|
||||
lost=counts["lost"],
|
||||
won=counts['won'],
|
||||
lost=counts['lost'],
|
||||
)
|
||||
)
|
||||
current += timedelta(days=1)
|
||||
@@ -442,13 +427,10 @@ async def get_model_overview(
|
||||
for chat_id in chat_ids:
|
||||
chat = Chats.get_chat_by_id(chat_id, db=db)
|
||||
if chat and chat.meta:
|
||||
for tag in chat.meta.get("tags", []):
|
||||
for tag in chat.meta.get('tags', []):
|
||||
tag_counts[tag] += 1
|
||||
|
||||
# Sort by count and take top 10
|
||||
tags = [
|
||||
TagEntry(tag=tag, count=count)
|
||||
for tag, count in sorted(tag_counts.items(), key=lambda x: -x[1])[:10]
|
||||
]
|
||||
tags = [TagEntry(tag=tag, count=count) for tag, count in sorted(tag_counts.items(), key=lambda x: -x[1])[:10]]
|
||||
|
||||
return ModelOverviewResponse(history=history, tags=tags)
|
||||
|
||||
Reference in New Issue
Block a user