Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add persona stats #3282

Merged
merged 6 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions backend/ee/danswer/db/analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,67 @@ def fetch_danswerbot_analytics(
)

return results


def fetch_persona_message_analytics(
db_session: Session,
persona_id: int,
hagen-danswer marked this conversation as resolved.
Show resolved Hide resolved
start: datetime.datetime,
end: datetime.datetime,
) -> list[tuple[int, datetime.date]]:
"""Gets the daily message counts for a specific persona within the given time range."""
query = (
select(
func.count(ChatMessage.id),
cast(ChatMessage.time_sent, Date),
)
.join(
ChatSession,
ChatMessage.chat_session_id == ChatSession.id,
)
.where(
or_(
ChatMessage.alternate_assistant_id == persona_id,
ChatSession.persona_id == persona_id,
),
ChatMessage.time_sent >= start,
ChatMessage.time_sent <= end,
ChatMessage.message_type == MessageType.ASSISTANT,
)
.group_by(cast(ChatMessage.time_sent, Date))
.order_by(cast(ChatMessage.time_sent, Date))
)

return [tuple(row) for row in db_session.execute(query).all()]


def fetch_persona_unique_users(
db_session: Session,
persona_id: int,
start: datetime.datetime,
end: datetime.datetime,
) -> list[tuple[int, datetime.date]]:
"""Gets the daily unique user counts for a specific persona within the given time range."""
query = (
select(
func.count(func.distinct(ChatSession.user_id)),
cast(ChatMessage.time_sent, Date),
)
.join(
ChatSession,
ChatMessage.chat_session_id == ChatSession.id,
)
.where(
or_(
ChatMessage.alternate_assistant_id == persona_id,
ChatSession.persona_id == persona_id,
),
ChatMessage.time_sent >= start,
ChatMessage.time_sent <= end,
ChatMessage.message_type == MessageType.ASSISTANT,
)
.group_by(cast(ChatMessage.time_sent, Date))
.order_by(cast(ChatMessage.time_sent, Date))
)

return [tuple(row) for row in db_session.execute(query).all()]
82 changes: 79 additions & 3 deletions backend/ee/danswer/server/analytics/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@
from danswer.db.models import User
from ee.danswer.db.analytics import fetch_danswerbot_analytics
from ee.danswer.db.analytics import fetch_per_user_query_analytics
from ee.danswer.db.analytics import fetch_persona_message_analytics
from ee.danswer.db.analytics import fetch_persona_unique_users
from ee.danswer.db.analytics import fetch_query_analytics

router = APIRouter(prefix="/analytics")


_DEFAULT_LOOKBACK_DAYS = 30


class QueryAnalyticsResponse(BaseModel):
total_queries: int
total_likes: int
Expand All @@ -33,7 +38,7 @@ def get_query_analytics(
daily_query_usage_info = fetch_query_analytics(
start=start
or (
datetime.datetime.utcnow() - datetime.timedelta(days=30)
datetime.datetime.utcnow() - datetime.timedelta(days=_DEFAULT_LOOKBACK_DAYS)
), # default is 30d lookback
end=end or datetime.datetime.utcnow(),
db_session=db_session,
Expand Down Expand Up @@ -64,7 +69,7 @@ def get_user_analytics(
daily_query_usage_info_per_user = fetch_per_user_query_analytics(
start=start
or (
datetime.datetime.utcnow() - datetime.timedelta(days=30)
datetime.datetime.utcnow() - datetime.timedelta(days=_DEFAULT_LOOKBACK_DAYS)
), # default is 30d lookback
end=end or datetime.datetime.utcnow(),
db_session=db_session,
Expand Down Expand Up @@ -98,7 +103,7 @@ def get_danswerbot_analytics(
daily_danswerbot_info = fetch_danswerbot_analytics(
start=start
or (
datetime.datetime.utcnow() - datetime.timedelta(days=30)
datetime.datetime.utcnow() - datetime.timedelta(days=_DEFAULT_LOOKBACK_DAYS)
), # default is 30d lookback
end=end or datetime.datetime.utcnow(),
db_session=db_session,
Expand All @@ -115,3 +120,74 @@ def get_danswerbot_analytics(
]

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
66 changes: 66 additions & 0 deletions web/src/app/ee/admin/performance/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,69 @@ export function getDatesList(startDate: Date): string[] {

return datesList;
}

export interface PersonaMessageAnalytics {
total_messages: number;
date: string;
persona_id: number;
}

export interface PersonaSnapshot {
id: number;
name: string;
description: string;
is_visible: boolean;
is_public: boolean;
}

hagen-danswer marked this conversation as resolved.
Show resolved Hide resolved
export const usePersonaMessages = (
personaId: number | undefined,
timeRange: DateRangePickerValue
) => {
const url = buildApiPath(`/api/analytics/admin/persona/messages`, {
persona_id: personaId?.toString(),
start: convertDateToStartOfDay(timeRange.from)?.toISOString(),
end: convertDateToEndOfDay(timeRange.to)?.toISOString(),
});

const { data, error, isLoading } = useSWR<PersonaMessageAnalytics[]>(
personaId !== undefined ? url : null,
errorHandlingFetcher
);

return {
data,
error,
isLoading,
refreshPersonaMessages: () => mutate(url),
};
};

export interface PersonaUniqueUserAnalytics {
unique_users: number;
date: string;
persona_id: number;
}

export const usePersonaUniqueUsers = (
personaId: number | undefined,
timeRange: DateRangePickerValue
) => {
const url = buildApiPath(`/api/analytics/admin/persona/unique-users`, {
persona_id: personaId?.toString(),
start: convertDateToStartOfDay(timeRange.from)?.toISOString(),
end: convertDateToEndOfDay(timeRange.to)?.toISOString(),
});

const { data, error, isLoading } = useSWR<PersonaUniqueUserAnalytics[]>(
personaId !== undefined ? url : null,
errorHandlingFetcher
);

return {
data,
error,
isLoading,
refreshPersonaUniqueUsers: () => mutate(url),
};
};
Loading
Loading