Skip to content

Commit

Permalink
feat: session end analytics: tools, llms, duration (#392)
Browse files Browse the repository at this point in the history
* feat: session replay additional info: tools, llms, duration

* Updated formatting

---------

Co-authored-by: Howard Gil <howardbgil@gmail.com>
  • Loading branch information
heethjain21 and HowieG authored Sep 18, 2024
1 parent a246397 commit ffa5a15
Showing 1 changed file with 55 additions and 10 deletions.
65 changes: 55 additions & 10 deletions agentops/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from termcolor import colored
from typing import Optional, List, Union
from uuid import UUID, uuid4
from dateutil import parser

from .exceptions import ApiServerException
from .enums import EndState
Expand Down Expand Up @@ -52,6 +53,13 @@ def __init__(
self.jwt = None
self.lock = threading.Lock()
self.queue = []
self.event_counts = {
"llms": 0,
"tools": 0,
"actions": 0,
"errors": 0,
"apis": 0,
}

self.stop_flag = threading.Event()
self.thread = threading.Thread(target=self._run)
Expand Down Expand Up @@ -97,6 +105,20 @@ def end_session(
self.thread.join(timeout=1)
self._flush_queue()

def format_duration(start_time, end_time):
duration = parser.parse(end_time) - parser.parse(start_time)
hours, remainder = divmod(duration.total_seconds(), 3600)
minutes, seconds = divmod(remainder, 60)

parts = []
if hours > 0:
parts.append(f"{int(hours)}h")
if minutes > 0:
parts.append(f"{int(minutes)}m")
parts.append(f"{seconds:.1f}s")

return " ".join(parts)

with self.lock:
payload = {"session": self.__dict__}
try:
Expand All @@ -111,23 +133,31 @@ def end_session(
logger.debug(res.body)
token_cost = res.body.get("token_cost", "unknown")

formatted_duration = format_duration(self.init_timestamp, self.end_timestamp)

if token_cost == "unknown" or token_cost is None:
logger.info("Could not determine cost of run.")
token_cost_d = Decimal(0)
else:
token_cost_d = Decimal(token_cost)
logger.info(
"This run's cost ${}".format(
"{:.2f}".format(token_cost_d)
if token_cost_d == 0
else "{:.6f}".format(
token_cost_d.quantize(
Decimal("0.000001"), rounding=ROUND_HALF_UP
)
)
formatted_cost = (
"{:.2f}".format(token_cost_d)
if token_cost_d == 0
else "{:.6f}".format(
token_cost_d.quantize(Decimal("0.000001"), rounding=ROUND_HALF_UP)
)
)

analytics = (
f"Analytics for this run - "
f"LLM calls: {self.event_counts['llms']} | "
f"Tool calls: {self.event_counts['tools']} | "
f"Actions: {self.event_counts['actions']} | "
f"Errors: {self.event_counts['errors']} | "
f"Duration: {formatted_duration} | "
f"Cost: ${formatted_cost}"
)
logger.info(analytics)

logger.info(
colored(
f"\x1b[34mSession Replay: https://app.agentops.ai/drilldown?session_id={self.session_id}\x1b[0m",
Expand Down Expand Up @@ -293,6 +323,21 @@ def _flush_queue(self) -> None:
logger.debug(serialized_payload)
logger.debug("</AGENTOPS_DEBUG_OUTPUT>\n")

# Count total events created based on type
events = payload["events"]
for event in events:
event_type = event["event_type"]
if event_type == "llms":
self.event_counts["llms"] += 1
elif event_type == "tools":
self.event_counts["tools"] += 1
elif event_type == "actions":
self.event_counts["actions"] += 1
elif event_type == "errors":
self.event_counts["errors"] += 1
elif event_type == "apis":
self.event_counts["apis"] += 1

def _run(self) -> None:
while not self.stop_flag.is_set():
time.sleep(self.config.max_wait_time / 1000)
Expand Down

0 comments on commit ffa5a15

Please sign in to comment.