import streamlit as st import pandas as pd from pymongo import MongoClient from datetime import datetime, date import pytz import os from dotenv import load_dotenv load_dotenv() st.set_page_config( page_title="Agent Assistance Usage", page_icon=None, layout="wide", initial_sidebar_state="expanded" ) st.markdown(""" """, unsafe_allow_html=True) USD_TO_INR = 92.0 MODEL_PRICING = { "gpt-4.1-nano": {"input": 0.10, "output": 0.40}, "gpt-4o-mini": {"input": 0.15, "output": 0.60}, "gpt-4o": {"input": 2.50, "output": 10.00}, "gpt-3.5-turbo": {"input": 0.50, "output": 1.50}, "gpt-4-turbo": {"input": 10.00, "output": 30.00}, "claude-3-haiku": {"input": 0.25, "output": 1.25}, "claude-3-sonnet": {"input": 3.00, "output": 15.00}, "claude-3-opus": {"input": 15.00, "output": 75.00}, } FEATURE_REGISTRY = [ ("entity_extraction_logs", "Entity Extraction", None), ("generate_nps_questions_logs", "NPS Question Generation", None), ("grammer_correction_logs", "Grammar Correction", None), ("recommended_template_logs", "Recommended Templates", None), ("summarization_logs", "Summarization", None), ("template_recommendation_logs", "Template Recommendation (Chat)", "chat"), ("template_recommendation_logs", "Template Recommendation (Email)", "email"), ("text_expansion_logs", "Text Expansion", None), ("tone_change_logs", "Tone Change", None), ] FEATURE_DEFAULT_MODELS = { "Summarization": "gpt-4.1-nano", "Grammar Correction" : "gpt-4.1-nano" } NESTED_COLLECTIONS = {"template_recommendation_logs", "tone_change_logs"} def fmt_inr(usd_val): return f"₹{usd_val * USD_TO_INR:,.2f}" def build_excel(df): import io from openpyxl import Workbook from openpyxl.styles import Font, PatternFill, Alignment, Border, Side from openpyxl.utils import get_column_letter HEADER_FILL = PatternFill("solid", fgColor="2563EB") HEADER_FONT = Font(name="Calibri", bold=True, color="FFFFFF", size=10) TOTAL_FILL = PatternFill("solid", fgColor="EFF4FF") TOTAL_FONT = Font(name="Calibri", bold=True, color="111827", size=10) CELL_FONT = Font(name="Calibri", size=10) BORDER_SIDE = Side(style="thin", color="E2E5EF") THIN_BORDER = Border(left=BORDER_SIDE, right=BORDER_SIDE, top=BORDER_SIDE, bottom=BORDER_SIDE) COLUMNS = [ ("Client ID", "client_id", 18), ("Input Tokens", "input_tokens", 14), ("Output Tokens", "output_tokens", 14), ("Total Tokens", "total_tokens", 14), ("Input Cost (INR)", "input_cost_inr", 16), ("Output Cost (INR)", "output_cost_inr", 17), ("Total Cost (INR)", "total_cost_inr", 16), ("Model", "model", 16), ] wb = Workbook() wb.remove(wb.active) features = df["feature"].unique() for feature in features: sheet_name = feature[:31] ws = wb.create_sheet(title=sheet_name) ws.append([col[0] for col in COLUMNS]) for col_idx, (_, _, width) in enumerate(COLUMNS, start=1): cell = ws.cell(row=1, column=col_idx) cell.fill = HEADER_FILL cell.font = HEADER_FONT cell.alignment = Alignment(horizontal="center", vertical="center") cell.border = THIN_BORDER ws.column_dimensions[get_column_letter(col_idx)].width = width ws.row_dimensions[1].height = 20 fdf = df[df["feature"] == feature].copy() client_data = fdf.groupby("client_id").agg( input_tokens=("input_tokens", "sum"), output_tokens=("output_tokens", "sum"), total_tokens=("total_tokens", "sum"), input_cost_inr=("input_cost_inr", "sum"), output_cost_inr=("output_cost_inr","sum"), total_cost_inr=("total_cost_inr", "sum"), model=("model", "first"), ).reset_index().sort_values("total_cost_inr", ascending=False) for r_idx, row in enumerate(client_data.itertuples(index=False), start=2): values = [ row.client_id, row.input_tokens, row.output_tokens, row.total_tokens, round(row.input_cost_inr, 4), round(row.output_cost_inr, 4), round(row.total_cost_inr, 4), row.model, ] for c_idx, val in enumerate(values, start=1): cell = ws.cell(row=r_idx, column=c_idx, value=val) cell.font = CELL_FONT cell.border = THIN_BORDER cell.alignment = Alignment( horizontal="right" if c_idx > 1 else "left", vertical="center" ) total_row = len(client_data) + 2 totals = [ "TOTAL", int(client_data["input_tokens"].sum()), int(client_data["output_tokens"].sum()), int(client_data["total_tokens"].sum()), round(client_data["input_cost_inr"].sum(), 4), round(client_data["output_cost_inr"].sum(), 4), round(client_data["total_cost_inr"].sum(), 4), "", ] for c_idx, val in enumerate(totals, start=1): cell = ws.cell(row=total_row, column=c_idx, value=val) cell.fill = TOTAL_FILL cell.font = TOTAL_FONT cell.border = THIN_BORDER cell.alignment = Alignment( horizontal="right" if c_idx > 1 else "left", vertical="center" ) ws.freeze_panes = "A2" buf = io.BytesIO() wb.save(buf) buf.seek(0) return buf.getvalue() def calc_cost(input_tokens, output_tokens, model): p = MODEL_PRICING[model] ic = (input_tokens / 1_000_000) * p["input"] oc = (output_tokens / 1_000_000) * p["output"] return ic, oc, ic + oc @st.cache_resource def get_mongo_client(): conn = os.getenv("DEV_MONGO_CONNECTION") return MongoClient(conn) if conn else None def fetch_tokens(collection_name, label, ticket_filter, start_dt, end_dt, model): mongo = get_mongo_client() if mongo is None: return pd.DataFrame() col = mongo["agent_assistance"][collection_name] if collection_name == "template_recommendation_logs" and ticket_filter == "email": match = { "created_at": {"$gt": start_dt, "$lt": end_dt}, "ticket_type": "email", "template": {"$ne": []}, } elif collection_name == "template_recommendation_logs" and ticket_filter == "chat": match = { "created_at": {"$gt": start_dt, "$lt": end_dt}, "ticket_type": {"$ne": "email"}, "client_id": {"$exists": True, "$ne": None}, } else: match = { "created_at": {"$gte": start_dt, "$lt": end_dt}, "client_id": {"$exists": True, "$ne": None}, } if ticket_filter == "email": match["ticket_type"] = "email" elif ticket_filter == "chat": match["ticket_type"] = {"$ne": "email"} if collection_name in NESTED_COLLECTIONS: pipeline = [ {"$match": match}, {"$group": {"_id": "$client_id", "usage_arrays": {"$push": "$usage"}}}, {"$unwind": "$usage_arrays"}, {"$unwind": "$usage_arrays"}, {"$group": { "_id": "$_id", "total_tokens": {"$sum": "$usage_arrays.total_tokens"}, "input_tokens": {"$sum": "$usage_arrays.prompt_tokens"}, "output_tokens": {"$sum": "$usage_arrays.completion_tokens"}, }}, ] else: pipeline = [ {"$match": match}, {"$unwind": "$usage"}, {"$group": { "_id": "$client_id", "total_tokens": {"$sum": "$usage.total_tokens"}, "input_tokens": {"$sum": "$usage.prompt_tokens"}, "output_tokens": {"$sum": "$usage.completion_tokens"}, }}, ] pipeline.append({ "$project": { "_id": 0, "client_id": "$_id", "total_tokens": 1, "input_tokens": 1, "output_tokens": 1, } }) try: results = list(col.aggregate(pipeline)) if not results: return pd.DataFrame() df = pd.DataFrame(results) df["model"] = model df["collection"] = collection_name df["feature"] = label df["ticket_filter"] = ticket_filter or "all" ic, oc, tc = zip(*df.apply( lambda r: calc_cost(r["input_tokens"], r["output_tokens"], model), axis=1 )) df["input_cost_usd"] = ic df["output_cost_usd"] = oc df["total_cost_usd"] = tc df["input_cost_inr"] = df["input_cost_usd"] * USD_TO_INR df["output_cost_inr"] = df["output_cost_usd"] * USD_TO_INR df["total_cost_inr"] = df["total_cost_usd"] * USD_TO_INR return df except Exception as e: st.error(f"Error fetching `{collection_name}` ({label}): {e}") return pd.DataFrame() with st.sidebar: st.markdown('Agent Assistance', unsafe_allow_html=True) st.markdown('