diff --git a/messages/en-US.json b/messages/en-US.json index 0784fdf2e..164f110e7 100644 --- a/messages/en-US.json +++ b/messages/en-US.json @@ -3405,6 +3405,8 @@ "aiSessionNoData": "No data captured", "aiSessionCouldNotParse": "(raw, could not parse transcript)", "aiSessionLogTruncated": "This session was truncated before storage and may be incomplete.", + "aiSessionViewRaw": "View Raw JSON", + "aiSessionViewChat": "View Chat", "requestAnalyticsDescription": "View detailed request analytics for resources in this organization", "logRetentionRequestLabel": "HTTP Request Log Retention", "logRetentionRequestDescription": "How long to retain request logs", diff --git a/server/routers/auditLogs/queryAiSessionLog.ts b/server/routers/auditLogs/queryAiSessionLog.ts index 913eacf65..2412f8980 100644 --- a/server/routers/auditLogs/queryAiSessionLog.ts +++ b/server/routers/auditLogs/queryAiSessionLog.ts @@ -66,6 +66,7 @@ export const queryAiSessionLogsQuery = z.strictObject({ .pipe(z.int().positive()) .optional(), actor: z.string().optional(), + model: z.string().optional(), isStream: z .union([z.boolean(), z.string()]) .transform((val) => (typeof val === "string" ? val === "true" : val)) @@ -123,6 +124,9 @@ function getWhere(data: Q) { ) : undefined, data.actor ? eq(aiSessionLog.userId, data.actor) : undefined, + data.model + ? eq(aiSessionLog.requestedModel, data.model) + : undefined, data.isStream !== undefined ? eq(aiSessionLog.isStream, data.isStream) : undefined @@ -333,7 +337,8 @@ async function queryUniqueFilterAttributes( uniqueProviders, uniqueUsers, uniqueResources, - uniqueSiteResources + uniqueSiteResources, + uniqueModels ] = await Promise.all([ logsDb .selectDistinct({ id: aiSessionLog.providerId }) @@ -354,9 +359,18 @@ async function queryUniqueFilterAttributes( .selectDistinct({ id: aiSessionLog.siteResourceId }) .from(aiSessionLog) .where(and(baseConditions, isNull(aiSessionLog.resourceId))) + .limit(DISTINCT_LIMIT + 1), + logsDb + .selectDistinct({ model: aiSessionLog.requestedModel }) + .from(aiSessionLog) + .where(baseConditions) .limit(DISTINCT_LIMIT + 1) ]); + const models = uniqueModels + .map((row) => row.model) + .filter((model): model is string => model !== null); + const providerIds = uniqueProviders .map((row) => row.id) .filter((id): id is number => id !== null); @@ -440,7 +454,8 @@ async function queryUniqueFilterAttributes( return { providers: sortNamedFilterOptions(providers), resources: sortNamedFilterOptions(resourcesWithNames), - users: userList + users: userList, + models: models.sort() }; } diff --git a/server/routers/auditLogs/types.ts b/server/routers/auditLogs/types.ts index cf85e5a2f..42b93904e 100644 --- a/server/routers/auditLogs/types.ts +++ b/server/routers/auditLogs/types.ts @@ -138,6 +138,7 @@ export type QueryAiSessionLogResponse = { id: string; email: string | null; }[]; + models: string[]; }; }; diff --git a/src/app/[orgId]/settings/logs/ai/page.tsx b/src/app/[orgId]/settings/logs/ai/page.tsx index 2c4c2ed32..67d18b94c 100644 --- a/src/app/[orgId]/settings/logs/ai/page.tsx +++ b/src/app/[orgId]/settings/logs/ai/page.tsx @@ -50,12 +50,14 @@ export default function AiSessionLogsPage() { capability?: string; resourceId?: string; actor?: string; + model?: string; isStream?: string; }>({ providerId: searchParams.get("providerId") || undefined, capability: searchParams.get("capability") || undefined, resourceId: searchParams.get("resourceId") || undefined, actor: searchParams.get("actor") || undefined, + model: searchParams.get("model") || undefined, isStream: searchParams.get("isStream") || undefined }); @@ -132,7 +134,8 @@ export default function AiSessionLogsPage() { const filterAttributes = data?.filterAttributes ?? { providers: [], resources: [], - users: [] + users: [], + models: [] }; const handleDateRangeChange = ( @@ -309,15 +312,27 @@ export default function AiSessionLogsPage() { }, { accessorKey: "requestedModel", - header: ({ column }) => ( - {t("model")} - ), - cell: ({ row }) => { + header: ({ column }) => { return ( - - {row.original.requestedModel || "-"} - +
@@ -457,18 +472,6 @@ export default function AiSessionLogsPage() { {row.statusCode ?? "N/A"}
- {row.requestedModel || "N/A"} -
-- {capabilityLabels[row.capability] || row.capability} -
-