Skip to content

Commit e4401dd

Browse files
committed
update to usage schema
1 parent fe5e27f commit e4401dd

File tree

4 files changed

+47
-23
lines changed

4 files changed

+47
-23
lines changed

apps/web/src/app/api/ai/journl-agent/route.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,20 @@ export async function POST(req: Request) {
2020
const provider = Object.keys(result.providerMetadata ?? {})[0] || "";
2121

2222
if (result.usage && session.user?.id) {
23-
await api.ai.trackLLMUsage({
24-
inputTokens: result.usage.promptTokens,
25-
metadata: {
26-
message_count: messages.length,
27-
request_type: "chat",
28-
},
29-
model,
30-
outputTokens: result.usage.completionTokens,
31-
provider,
23+
await api.usage.trackAiModelUsage({
24+
metrics: [
25+
{
26+
quantity: result.usage.promptTokens,
27+
unit: "input_tokens",
28+
},
29+
{
30+
quantity: result.usage.completionTokens,
31+
unit: "output_tokens",
32+
},
33+
],
34+
model_id: model,
35+
model_provider: provider,
36+
user_id: session.user.id,
3237
});
3338
}
3439
},

apps/web/src/app/api/supabase/embed-document/route.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import removeMarkdown from "remove-markdown";
1010
import type { z } from "zod/v4";
1111
import { model } from "~/ai/providers/openai/embedding";
1212
import { schema } from "~/components/editor/block-schema";
13-
import { embedder } from "~/trpc/server";
13+
import { api, embedder } from "~/trpc/server";
1414
import { handler } from "../_lib/webhook-handler";
1515

1616
const CHUNK_PARAMS: ChunkParams = {
@@ -102,14 +102,33 @@ export const POST = handler(zDocumentEmbeddingTask, async (payload) => {
102102
const mDocument =
103103
await MDocument.fromMarkdown(markdown).chunk(CHUNK_PARAMS);
104104

105-
// ! TODO: Here's where we get the usage tokens, we must process these in a different transaction
106-
// ! To guarantee that the usage is tracked regardless of the success of the embedding.
107-
const { embeddings, usage: _usage } = await embedMany({
105+
const { embeddings, usage } = await embedMany({
108106
maxRetries: 5,
109107
model,
110108
values: mDocument.map((chunk) => chunk.text),
111109
});
112110

111+
if (usage) {
112+
try {
113+
await api.usage.trackAiModelUsage({
114+
metadata: {
115+
document_id: document.id,
116+
model_version: model.specificationVersion,
117+
},
118+
metrics: [{ quantity: usage.tokens, unit: "tokens" }],
119+
model_id: model.modelId,
120+
model_provider: model.provider,
121+
user_id: document.user_id,
122+
});
123+
} catch (error) {
124+
console.error(
125+
"Failed to track AI usage for document embedding:",
126+
error,
127+
);
128+
// Continue with embedding even if usage tracking fails
129+
}
130+
}
131+
113132
const insertions: z.infer<typeof zInsertDocumentEmbedding>[] = [];
114133

115134
for (const [index, embedding] of embeddings.entries()) {

packages/api/src/api-router/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { documentRouter } from "./document.js";
55
import { journalRouter } from "./journal.js";
66
import { notesRouter } from "./notes.js";
77
import { pagesRouter } from "./pages.js";
8+
import { usageRouter } from "./usage.js";
89

910
export const apiRouter = createTRPCRouter({
1011
auth: authRouter,
@@ -13,6 +14,7 @@ export const apiRouter = createTRPCRouter({
1314
journal: journalRouter,
1415
notes: notesRouter,
1516
pages: pagesRouter,
17+
usage: usageRouter,
1618
});
1719

1820
export type ApiRouter = typeof apiRouter;

packages/api/src/api-router/usage.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
11
import { eq } from "@acme/db";
22
import { UsageEvent, UsageEventStatus } from "@acme/db/schema";
3-
import { TRPCError } from "@trpc/server";
3+
import { TRPCError, type TRPCRouterRecord } from "@trpc/server";
44
import { z } from "zod/v4";
5-
import { protectedProcedure } from "../trpc.js";
5+
import { publicProcedure } from "../trpc.js";
66

77
export const usageRouter = {
8-
createUsageEvent: protectedProcedure
8+
trackAiModelUsage: publicProcedure
99
.input(
1010
z.object({
11-
metadata: z.record(z.string(), z.string()),
11+
metadata: z.record(z.string(), z.string()).optional(),
1212
metrics: z.array(z.object({ quantity: z.number(), unit: z.string() })),
1313
model_id: z.string(),
1414
model_provider: z.string(),
15+
user_id: z.string(),
1516
}),
1617
)
1718
.mutation(async ({ ctx, input }) => {
1819
try {
19-
return await ctx.db.insert(UsageEvent).values({
20-
...input,
21-
user_id: ctx.session.user.id,
22-
});
20+
return await ctx.db.insert(UsageEvent).values(input);
2321
} catch (error) {
2422
console.error("Database error in usage.createUsageEvent:", error);
2523
throw new TRPCError({
@@ -28,7 +26,7 @@ export const usageRouter = {
2826
});
2927
}
3028
}),
31-
processUsageEvent: protectedProcedure
29+
updateUsageEventStatus: publicProcedure
3230
.input(
3331
z.object({
3432
id: z.string(),
@@ -51,4 +49,4 @@ export const usageRouter = {
5149
});
5250
}
5351
}),
54-
};
52+
} satisfies TRPCRouterRecord;

0 commit comments

Comments
 (0)