feat: trackeo de coste por llamada Claude — tabla api_usage + /costs
Build & Deploy ResearchOwl / build-and-push (push) Successful in 6s
Build & Deploy ResearchOwl / build-and-push (push) Successful in 6s
This commit is contained in:
@@ -78,6 +78,7 @@ async def cmd_start(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||
"`/generate <type>` — Generate output (podcast|blog|report|thread)\n"
|
||||
"`/sources` — List all sources found\n"
|
||||
"`/outputs` — List generated outputs\n"
|
||||
"`/costs` — Show API usage costs\n"
|
||||
"`/cancel` — Cancel current research\n"
|
||||
"`/help` — Show this message",
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
@@ -419,6 +420,57 @@ async def cmd_outputs(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||
await db_conn.close()
|
||||
|
||||
|
||||
async def cmd_costs(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||
if not is_authorized(update.effective_user.id):
|
||||
return
|
||||
|
||||
chat_id = update.effective_chat.id
|
||||
db_conn = await get_db()
|
||||
db = ResearchDB(db_conn)
|
||||
|
||||
try:
|
||||
cursor = await db_conn.execute(
|
||||
"SELECT * FROM research_sessions WHERE telegram_chat_id = ? ORDER BY created_at DESC LIMIT 1",
|
||||
(chat_id,)
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
if not row:
|
||||
await update.message.reply_text("No sessions found.")
|
||||
return
|
||||
|
||||
session_id = row["id"]
|
||||
topic = row["topic"]
|
||||
|
||||
by_type = {r["call_type"]: r for r in await db.get_usage_stats(session_id)}
|
||||
totals = await db.get_total_usage_stats()
|
||||
|
||||
lines = [f"📊 *Costes ResearchOwl*\n"]
|
||||
lines.append(f"Última sesión (`{topic}`):")
|
||||
|
||||
session_total = 0.0
|
||||
for call_type, label in [("scoring", "Scoring"), ("generation", "Generación")]:
|
||||
row_data = by_type.get(call_type)
|
||||
if row_data:
|
||||
calls = row_data["calls"]
|
||||
tokens = row_data["total_tokens"]
|
||||
cost = row_data["total_cost"]
|
||||
session_total += cost
|
||||
lines.append(f" {label}: {calls} llamadas · {tokens:,} tokens · ${cost:.4f}")
|
||||
else:
|
||||
lines.append(f" {label}: —")
|
||||
|
||||
lines.append(f" Total: ${session_total:.4f}")
|
||||
lines.append("")
|
||||
lines.append("Acumulado total:")
|
||||
acc_cost = totals.get("total_cost") or 0.0
|
||||
acc_sessions = totals.get("sessions") or 0
|
||||
lines.append(f" ${acc_cost:.4f} ({acc_sessions} sesiones)")
|
||||
|
||||
await update.message.reply_text("\n".join(lines), parse_mode=ParseMode.MARKDOWN)
|
||||
finally:
|
||||
await db_conn.close()
|
||||
|
||||
|
||||
async def cmd_process(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||
if not is_authorized(update.effective_user.id):
|
||||
return
|
||||
@@ -576,6 +628,7 @@ def create_bot() -> Application:
|
||||
app.add_handler(CommandHandler("generate", cmd_generate))
|
||||
app.add_handler(CommandHandler("sources", cmd_sources))
|
||||
app.add_handler(CommandHandler("outputs", cmd_outputs))
|
||||
app.add_handler(CommandHandler("costs", cmd_costs))
|
||||
app.add_handler(CommandHandler("process", cmd_process))
|
||||
app.add_handler(CommandHandler("cancel", cmd_cancel))
|
||||
app.add_handler(CommandHandler("purge", cmd_purge))
|
||||
|
||||
Reference in New Issue
Block a user