2024-12-13 09:56:10 -08:00

194 lines
5.6 KiB
Python

import datetime
from collections import defaultdict
from fastapi import APIRouter
from fastapi import Depends
from pydantic import BaseModel
from sqlalchemy.orm import Session
from ee.onyx.db.analytics import fetch_onyxbot_analytics
from ee.onyx.db.analytics import fetch_per_user_query_analytics
from ee.onyx.db.analytics import fetch_persona_message_analytics
from ee.onyx.db.analytics import fetch_persona_unique_users
from ee.onyx.db.analytics import fetch_query_analytics
from onyx.auth.users import current_admin_user
from onyx.db.engine import get_session
from onyx.db.models import User
router = APIRouter(prefix="/analytics")
_DEFAULT_LOOKBACK_DAYS = 30
class QueryAnalyticsResponse(BaseModel):
total_queries: int
total_likes: int
total_dislikes: int
date: datetime.date
@router.get("/admin/query")
def get_query_analytics(
start: datetime.datetime | None = None,
end: datetime.datetime | None = None,
_: User | None = Depends(current_admin_user),
db_session: Session = Depends(get_session),
) -> list[QueryAnalyticsResponse]:
daily_query_usage_info = fetch_query_analytics(
start=start
or (
datetime.datetime.utcnow() - datetime.timedelta(days=_DEFAULT_LOOKBACK_DAYS)
), # default is 30d lookback
end=end or datetime.datetime.utcnow(),
db_session=db_session,
)
return [
QueryAnalyticsResponse(
total_queries=total_queries,
total_likes=total_likes,
total_dislikes=total_dislikes,
date=date,
)
for total_queries, total_likes, total_dislikes, date in daily_query_usage_info
]
class UserAnalyticsResponse(BaseModel):
total_active_users: int
date: datetime.date
@router.get("/admin/user")
def get_user_analytics(
start: datetime.datetime | None = None,
end: datetime.datetime | None = None,
_: User | None = Depends(current_admin_user),
db_session: Session = Depends(get_session),
) -> list[UserAnalyticsResponse]:
daily_query_usage_info_per_user = fetch_per_user_query_analytics(
start=start
or (
datetime.datetime.utcnow() - datetime.timedelta(days=_DEFAULT_LOOKBACK_DAYS)
), # default is 30d lookback
end=end or datetime.datetime.utcnow(),
db_session=db_session,
)
user_analytics: dict[datetime.date, int] = defaultdict(int)
for __, ___, ____, date, _____ in daily_query_usage_info_per_user:
user_analytics[date] += 1
return [
UserAnalyticsResponse(
total_active_users=cnt,
date=date,
)
for date, cnt in user_analytics.items()
]
class OnyxbotAnalyticsResponse(BaseModel):
total_queries: int
auto_resolved: int
date: datetime.date
@router.get("/admin/onyxbot")
def get_onyxbot_analytics(
start: datetime.datetime | None = None,
end: datetime.datetime | None = None,
_: User | None = Depends(current_admin_user),
db_session: Session = Depends(get_session),
) -> list[OnyxbotAnalyticsResponse]:
daily_onyxbot_info = fetch_onyxbot_analytics(
start=start
or (
datetime.datetime.utcnow() - datetime.timedelta(days=_DEFAULT_LOOKBACK_DAYS)
), # default is 30d lookback
end=end or datetime.datetime.utcnow(),
db_session=db_session,
)
resolution_results = [
OnyxbotAnalyticsResponse(
total_queries=total_queries,
# If it hits negatives, something has gone wrong...
auto_resolved=max(0, total_queries - total_negatives),
date=date,
)
for total_queries, total_negatives, date in daily_onyxbot_info
]
return resolution_results
class PersonaMessageAnalyticsResponse(BaseModel):
total_messages: int
date: datetime.date
persona_id: int
@router.get("/admin/persona/messages")
def get_persona_messages(
persona_id: int,
start: datetime.datetime | None = None,
end: datetime.datetime | None = None,
_: User | None = Depends(current_admin_user),
db_session: Session = Depends(get_session),
) -> list[PersonaMessageAnalyticsResponse]:
"""Fetch daily message counts for a single persona within the given time range."""
start = start or (
datetime.datetime.utcnow() - datetime.timedelta(days=_DEFAULT_LOOKBACK_DAYS)
)
end = end or datetime.datetime.utcnow()
persona_message_counts = []
for count, date in fetch_persona_message_analytics(
db_session=db_session,
persona_id=persona_id,
start=start,
end=end,
):
persona_message_counts.append(
PersonaMessageAnalyticsResponse(
total_messages=count,
date=date,
persona_id=persona_id,
)
)
return persona_message_counts
class PersonaUniqueUsersResponse(BaseModel):
unique_users: int
date: datetime.date
persona_id: int
@router.get("/admin/persona/unique-users")
def get_persona_unique_users(
persona_id: int,
start: datetime.datetime,
end: datetime.datetime,
_: User | None = Depends(current_admin_user),
db_session: Session = Depends(get_session),
) -> list[PersonaUniqueUsersResponse]:
"""Get unique users per day for a single persona."""
unique_user_counts = []
daily_counts = fetch_persona_unique_users(
db_session=db_session,
persona_id=persona_id,
start=start,
end=end,
)
for count, date in daily_counts:
unique_user_counts.append(
PersonaUniqueUsersResponse(
unique_users=count,
date=date,
persona_id=persona_id,
)
)
return unique_user_counts