|
| 1 | +from sqlalchemy import case, func, select |
| 2 | +from sqlmodel import col |
| 3 | + |
1 | 4 | from astrbot.api import sp, star |
2 | 5 | from astrbot.api.event import AstrMessageEvent, MessageEventResult |
3 | 6 | from astrbot.core import logger |
|
7 | 10 | DEERFLOW_THREAD_ID_KEY, |
8 | 11 | ) |
9 | 12 | from astrbot.core.agent.runners.deerflow.deerflow_api_client import DeerFlowAPIClient |
| 13 | +from astrbot.core.db.po import ProviderStat |
10 | 14 | from astrbot.core.utils.active_event_registry import active_event_registry |
11 | 15 |
|
12 | 16 | from .utils.rst_scene import RstScene |
@@ -246,3 +250,62 @@ async def new_conv(self, message: AstrMessageEvent) -> None: |
246 | 250 | f"✅ Switched to new conversation: {cid[:4]}。" |
247 | 251 | ), |
248 | 252 | ) |
| 253 | + |
| 254 | + async def stats(self, message: AstrMessageEvent) -> None: |
| 255 | + """Show token usage statistics for the current conversation.""" |
| 256 | + umo = message.unified_msg_origin |
| 257 | + cid = await self.context.conversation_manager.get_curr_conversation_id(umo) |
| 258 | + |
| 259 | + if not cid: |
| 260 | + message.set_result( |
| 261 | + MessageEventResult().message( |
| 262 | + "❌ You are not in a conversation. Use /new to create one." |
| 263 | + ), |
| 264 | + ) |
| 265 | + return |
| 266 | + |
| 267 | + db = self.context.get_db() |
| 268 | + async with db.get_db() as session: |
| 269 | + result = await session.execute( |
| 270 | + select( |
| 271 | + func.count(case((col(ProviderStat.id).is_not(None), 1))).label( |
| 272 | + "record_count", |
| 273 | + ), |
| 274 | + func.coalesce(func.sum(ProviderStat.token_input_other), 0).label( |
| 275 | + "total_input_other", |
| 276 | + ), |
| 277 | + func.coalesce(func.sum(ProviderStat.token_input_cached), 0).label( |
| 278 | + "total_input_cached", |
| 279 | + ), |
| 280 | + func.coalesce(func.sum(ProviderStat.token_output), 0).label( |
| 281 | + "total_output", |
| 282 | + ), |
| 283 | + ).where( |
| 284 | + col(ProviderStat.agent_type) == "internal", |
| 285 | + col(ProviderStat.conversation_id) == cid, |
| 286 | + ) |
| 287 | + ) |
| 288 | + stats = result.one() |
| 289 | + |
| 290 | + if stats.record_count == 0: |
| 291 | + message.set_result( |
| 292 | + MessageEventResult().message( |
| 293 | + "📊 No stats available for this conversation yet." |
| 294 | + ), |
| 295 | + ) |
| 296 | + return |
| 297 | + |
| 298 | + total_input_other = stats.total_input_other |
| 299 | + total_input_cached = stats.total_input_cached |
| 300 | + total_output = stats.total_output |
| 301 | + total_tokens = total_input_other + total_input_cached + total_output |
| 302 | + |
| 303 | + ret = ( |
| 304 | + f"📊 Conversation Token usage (ID: {cid[:8]}...)\n" |
| 305 | + f"Total: {total_tokens:,}\n" |
| 306 | + f"Input (cached): {total_input_cached:,}\n" |
| 307 | + f"Input (other): {total_input_other:,}\n" |
| 308 | + f"Output: {total_output:,}\n" |
| 309 | + ) |
| 310 | + |
| 311 | + message.set_result(MessageEventResult().message(ret)) |
0 commit comments