chore(bot): log assistant stage timings

This commit is contained in:
2026-03-11 03:41:03 +04:00
parent 0ec6aa585c
commit 4dd469a0fe
5 changed files with 44 additions and 4 deletions

View File

@@ -19,7 +19,7 @@ OPENAI_API_KEY=your-openai-api-key
PARSER_MODEL=gpt-4.1-mini PARSER_MODEL=gpt-4.1-mini
PURCHASE_PARSER_MODEL=gpt-5-mini PURCHASE_PARSER_MODEL=gpt-5-mini
ASSISTANT_MODEL=gpt-5-mini ASSISTANT_MODEL=gpt-5-mini
ASSISTANT_TIMEOUT_MS=15000 ASSISTANT_TIMEOUT_MS=20000
ASSISTANT_MEMORY_MAX_TURNS=12 ASSISTANT_MEMORY_MAX_TURNS=12
ASSISTANT_RATE_LIMIT_BURST=5 ASSISTANT_RATE_LIMIT_BURST=5
ASSISTANT_RATE_LIMIT_BURST_WINDOW_MS=60000 ASSISTANT_RATE_LIMIT_BURST_WINDOW_MS=60000

View File

@@ -133,7 +133,7 @@ export function getBotRuntimeConfig(env: NodeJS.ProcessEnv = process.env): BotRu
assistantModel: env.ASSISTANT_MODEL?.trim() || 'gpt-5-mini', assistantModel: env.ASSISTANT_MODEL?.trim() || 'gpt-5-mini',
assistantTimeoutMs: parsePositiveInteger( assistantTimeoutMs: parsePositiveInteger(
env.ASSISTANT_TIMEOUT_MS, env.ASSISTANT_TIMEOUT_MS,
15_000, 20_000,
'ASSISTANT_TIMEOUT_MS' 'ASSISTANT_TIMEOUT_MS'
), ),
assistantMemoryMaxTurns: parsePositiveInteger( assistantMemoryMaxTurns: parsePositiveInteger(

View File

@@ -73,6 +73,26 @@ interface PaymentProposalPayload {
currency: 'GEL' | 'USD' currency: 'GEL' | 'USD'
} }
function describeError(error: unknown): {
errorMessage?: string
errorName?: string
} {
if (error instanceof Error) {
return {
errorMessage: error.message,
errorName: error.name
}
}
if (typeof error === 'string') {
return {
errorMessage: error
}
}
return {}
}
function isPrivateChat(ctx: Context): boolean { function isPrivateChat(ctx: Context): boolean {
return ctx.chat?.type === 'private' return ctx.chat?.type === 'private'
} }
@@ -749,8 +769,13 @@ export function registerDmAssistant(options: {
const memory = options.memoryStore.get(telegramUserId) const memory = options.memoryStore.get(telegramUserId)
const typingIndicator = startTypingIndicator(ctx) const typingIndicator = startTypingIndicator(ctx)
let pendingReply: PendingAssistantReply | null = null let pendingReply: PendingAssistantReply | null = null
const assistantStartedAt = Date.now()
let stage: 'household_context' | 'assistant_response' = 'household_context'
let contextBuildMs: number | null = null
let assistantResponseMs: number | null = null
try { try {
const contextStartedAt = Date.now()
const householdContext = await buildHouseholdContext({ const householdContext = await buildHouseholdContext({
householdId: member.householdId, householdId: member.householdId,
memberId: member.id, memberId: member.id,
@@ -759,7 +784,10 @@ export function registerDmAssistant(options: {
householdConfigurationRepository: options.householdConfigurationRepository, householdConfigurationRepository: options.householdConfigurationRepository,
financeService financeService
}) })
contextBuildMs = Date.now() - contextStartedAt
pendingReply = await sendAssistantProcessingReply(ctx, t.processing) pendingReply = await sendAssistantProcessingReply(ctx, t.processing)
stage = 'assistant_response'
const assistantResponseStartedAt = Date.now()
const reply = await options.assistant.respond({ const reply = await options.assistant.respond({
locale, locale,
householdContext, householdContext,
@@ -767,6 +795,7 @@ export function registerDmAssistant(options: {
recentTurns: memory.turns, recentTurns: memory.turns,
userMessage: ctx.msg.text userMessage: ctx.msg.text
}) })
assistantResponseMs = Date.now() - assistantResponseStartedAt
options.usageTracker.record({ options.usageTracker.record({
householdId: member.householdId, householdId: member.householdId,
@@ -788,6 +817,12 @@ export function registerDmAssistant(options: {
event: 'assistant.reply', event: 'assistant.reply',
householdId: member.householdId, householdId: member.householdId,
telegramUserId, telegramUserId,
contextBuildMs,
assistantResponseMs,
totalDurationMs: Date.now() - assistantStartedAt,
householdContextChars: householdContext.length,
recentTurnsCount: memory.turns.length,
memorySummaryChars: memory.summary?.length ?? 0,
inputTokens: reply.usage.inputTokens, inputTokens: reply.usage.inputTokens,
outputTokens: reply.usage.outputTokens, outputTokens: reply.usage.outputTokens,
totalTokens: reply.usage.totalTokens totalTokens: reply.usage.totalTokens
@@ -802,6 +837,11 @@ export function registerDmAssistant(options: {
event: 'assistant.reply_failed', event: 'assistant.reply_failed',
householdId: member.householdId, householdId: member.householdId,
telegramUserId, telegramUserId,
stage,
contextBuildMs,
assistantResponseMs,
totalDurationMs: Date.now() - assistantStartedAt,
...describeError(error),
error error
}, },
'DM assistant reply failed' 'DM assistant reply failed'

View File

@@ -14,7 +14,7 @@ openai_api_key_secret_id = "openai-api-key"
bot_parser_model = "gpt-4.1-mini" bot_parser_model = "gpt-4.1-mini"
bot_purchase_parser_model = "gpt-5-mini" bot_purchase_parser_model = "gpt-5-mini"
bot_assistant_model = "gpt-5-mini" bot_assistant_model = "gpt-5-mini"
bot_assistant_timeout_ms = 15000 bot_assistant_timeout_ms = 20000
bot_assistant_memory_max_turns = 12 bot_assistant_memory_max_turns = 12
bot_assistant_rate_limit_burst = 5 bot_assistant_rate_limit_burst = 5
bot_assistant_rate_limit_burst_window_ms = 60000 bot_assistant_rate_limit_burst_window_ms = 60000

View File

@@ -34,7 +34,7 @@ const server = {
PARSER_MODEL: z.string().min(1).default('gpt-4.1-mini'), PARSER_MODEL: z.string().min(1).default('gpt-4.1-mini'),
PURCHASE_PARSER_MODEL: z.string().min(1).default('gpt-5-mini'), PURCHASE_PARSER_MODEL: z.string().min(1).default('gpt-5-mini'),
ASSISTANT_MODEL: z.string().min(1).default('gpt-5-mini'), ASSISTANT_MODEL: z.string().min(1).default('gpt-5-mini'),
ASSISTANT_TIMEOUT_MS: z.coerce.number().int().positive().default(15000), ASSISTANT_TIMEOUT_MS: z.coerce.number().int().positive().default(20000),
ASSISTANT_MEMORY_MAX_TURNS: z.coerce.number().int().positive().default(12), ASSISTANT_MEMORY_MAX_TURNS: z.coerce.number().int().positive().default(12),
ASSISTANT_RATE_LIMIT_BURST: z.coerce.number().int().positive().default(5), ASSISTANT_RATE_LIMIT_BURST: z.coerce.number().int().positive().default(5),
ASSISTANT_RATE_LIMIT_BURST_WINDOW_MS: z.coerce.number().int().positive().default(60000), ASSISTANT_RATE_LIMIT_BURST_WINDOW_MS: z.coerce.number().int().positive().default(60000),