startrz commited on
Commit
be1b585
·
verified ·
1 Parent(s): 10d41b6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -264
app.py CHANGED
@@ -1,276 +1,39 @@
1
- # app.py
2
  import streamlit as st
3
- import pandas as pd
4
- import plotly.express as px
5
- import plotly.graph_objects as go
6
- from datetime import datetime, timedelta
7
- import os
8
- from typing import Optional, Dict, List
9
  import requests
10
- import json
11
- import altair as alt
12
- from pathlib import Path
13
- import base64
14
 
15
- class OpenAIUsageTracker:
16
- def __init__(self, api_key: Optional[str] = None):
17
- """Initialize the OpenAI Usage Tracker."""
18
- self.api_key = api_key
19
- if not self.api_key:
20
- raise ValueError("API key must be provided")
21
-
22
- self.base_url = "https://api.openai.com/v1"
23
- self.headers = {
24
- "Authorization": f"Bearer {self.api_key}",
25
- "Content-Type": "application/json"
26
- }
27
-
28
- def get_usage(self, start_date: datetime, end_date: datetime) -> Dict:
29
- """Get API usage for a specific date range."""
30
- try:
31
- # Get daily usage
32
- usage_url = f"{self.base_url}/usage"
33
- params = {
34
- 'date': start_date.strftime('%Y-%m-%d'),
35
- 'end_date': end_date.strftime('%Y-%m-%d')
36
- }
37
-
38
- response = requests.get(
39
- usage_url,
40
- headers=self.headers,
41
- params=params
42
- )
43
- response.raise_for_status()
44
- usage_data = response.json()
45
-
46
- # Get cost data
47
- costs_url = f"{self.base_url}/dashboard/billing/usage"
48
- params = {
49
- 'start_date': start_date.strftime('%Y-%m-%d'),
50
- 'end_date': end_date.strftime('%Y-%m-%d')
51
- }
52
-
53
- cost_response = requests.get(
54
- costs_url,
55
- headers=self.headers,
56
- params=params
57
- )
58
- cost_response.raise_for_status()
59
- cost_data = cost_response.json()
60
-
61
- # Combine usage and cost data
62
- return {
63
- 'usage': usage_data,
64
- 'costs': cost_data
65
- }
66
-
67
- except requests.exceptions.RequestException as e:
68
- st.error(f"Error fetching usage data: {str(e)}")
69
- if hasattr(e, 'response') and e.response is not None:
70
- st.error(f"Response content: {e.response.text}")
71
- return None
72
-
73
- def get_billing_info(self) -> Dict:
74
- """Get billing information including credits and quotas."""
75
- try:
76
- # Get credit balance
77
- balance_url = f"{self.base_url}/dashboard/billing/credit_grants"
78
- response = requests.get(
79
- balance_url,
80
- headers=self.headers
81
- )
82
- response.raise_for_status()
83
- return response.json()
84
- except requests.exceptions.RequestException as e:
85
- st.error(f"Error fetching billing info: {str(e)}")
86
- if hasattr(e, 'response') and e.response is not None:
87
- st.error(f"Response content: {e.response.text}")
88
- return None
89
-
90
- def create_daily_usage_chart(usage_data: pd.DataFrame) -> alt.Chart:
91
- """Create an interactive daily usage chart using Altair."""
92
- chart = alt.Chart(usage_data).mark_bar().encode(
93
- x=alt.X('date:T', title='Date'),
94
- y=alt.Y('requests:Q', title='Number of Requests'),
95
- tooltip=['date', 'requests', 'cost']
96
- ).properties(
97
- title='Daily API Usage',
98
- width=600,
99
- height=400
100
- ).interactive()
101
 
102
- return chart
103
-
104
- def create_model_usage_chart(model_usage: pd.DataFrame) -> go.Figure:
105
- """Create a pie chart for model usage distribution."""
106
- if model_usage.empty:
107
- return None
108
-
109
- fig = px.pie(
110
- model_usage,
111
- values='requests',
112
- names='model',
113
- title='Usage Distribution by Model'
114
- )
115
- fig.update_traces(textposition='inside', textinfo='percent+label')
116
- return fig
117
-
118
- def format_large_number(num: float) -> str:
119
- """Format large numbers with K/M suffix."""
120
- if num >= 1_000_000:
121
- return f"${num/1_000_000:.2f}M"
122
- elif num >= 1_000:
123
- return f"${num/1_000:.2f}K"
124
- return f"${num:.2f}"
125
-
126
- def main():
127
- st.set_page_config(
128
- page_title="OpenAI API Usage Analytics",
129
- page_icon="📊",
130
- layout="wide"
131
- )
132
-
133
- # Custom CSS
134
- st.markdown("""
135
- <style>
136
- .stApp {
137
- max-width: 1200px;
138
- margin: 0 auto;
139
- }
140
- .metric-card {
141
- background-color: #f0f2f6;
142
- border-radius: 10px;
143
- padding: 20px;
144
- text-align: center;
145
- }
146
- .metric-value {
147
- font-size: 24px;
148
- font-weight: bold;
149
- color: #0068c9;
150
- }
151
- </style>
152
- """, unsafe_allow_html=True)
153
-
154
- st.title("📊 OpenAI API Usage Analytics Dashboard")
155
 
156
- # Sidebar
157
- st.sidebar.header("Configuration")
158
-
159
- # API Key input
160
- api_key = st.sidebar.text_input("Enter OpenAI API Key", type="password")
161
- if not api_key:
162
- st.warning("Please enter your OpenAI API key to continue.")
163
- st.stop()
164
-
165
- # Date range selection
166
- st.sidebar.subheader("Date Range")
167
- end_date = datetime.now()
168
- date_ranges = {
169
- "Last 7 days": 7,
170
- "Last 30 days": 30,
171
- "Last 90 days": 90,
172
- "Custom range": 0
173
- }
174
- selected_range = st.sidebar.selectbox("Select time period", list(date_ranges.keys()))
175
-
176
- if selected_range == "Custom range":
177
- col1, col2 = st.sidebar.columns(2)
178
- with col1:
179
- start_date = st.date_input("Start date", end_date - timedelta(days=30))
180
- with col2:
181
- end_date = st.date_input("End date", end_date)
182
  else:
183
- days = date_ranges[selected_range]
184
- start_date = end_date - timedelta(days=days)
185
-
186
- try:
187
- tracker = OpenAIUsageTracker(api_key)
188
-
189
- # Get usage and billing data
190
- usage_data = tracker.get_usage(start_date, end_date)
191
- billing_info = tracker.get_billing_info()
192
-
193
- if usage_data:
194
- # Process usage data
195
- daily_usage = pd.DataFrame(usage_data['usage'].get('data', []))
196
- total_cost = usage_data['costs'].get('total_usage', 0) / 100 # Convert to dollars
197
-
198
- if not daily_usage.empty:
199
- # Process daily usage data
200
- daily_usage['date'] = pd.to_datetime(daily_usage['created'])
201
- daily_usage['cost'] = daily_usage['n_requests'] * 0.0001 # Approximate cost
202
-
203
- # Create metrics row
204
- col1, col2, col3 = st.columns(3)
205
-
206
- with col1:
207
- st.markdown("""
208
- <div class="metric-card">
209
- <h3>Total Cost (Est.)</h3>
210
- <div class="metric-value">{}</div>
211
- </div>
212
- """.format(format_large_number(total_cost)), unsafe_allow_html=True)
213
-
214
- with col2:
215
- credit_balance = billing_info.get('total_granted', 0) if billing_info else 0
216
- st.markdown("""
217
- <div class="metric-card">
218
- <h3>Credit Balance</h3>
219
- <div class="metric-value">{}</div>
220
- </div>
221
- """.format(format_large_number(credit_balance)), unsafe_allow_html=True)
222
-
223
- with col3:
224
- daily_avg = total_cost / len(daily_usage) if len(daily_usage) > 0 else 0
225
- st.markdown("""
226
- <div class="metric-card">
227
- <h3>Daily Average</h3>
228
- <div class="metric-value">${:.2f}</div>
229
- </div>
230
- """.format(daily_avg), unsafe_allow_html=True)
231
 
232
- # Create and display charts
233
- st.subheader("Usage Analytics")
234
-
235
- # Daily usage chart
236
- usage_chart = create_daily_usage_chart(daily_usage)
237
- st.altair_chart(usage_chart, use_container_width=True)
238
 
239
- # Model distribution
240
- if 'model' in daily_usage.columns:
241
- model_usage = daily_usage.groupby('model').agg({
242
- 'n_requests': 'sum'
243
- }).reset_index()
244
- model_usage.columns = ['model', 'requests']
245
-
246
- model_chart = create_model_usage_chart(model_usage)
247
- if model_chart:
248
- st.plotly_chart(model_chart, use_container_width=True)
249
 
250
- # Display detailed data
251
- st.subheader("Detailed Usage Data")
252
-
253
- detailed_usage = daily_usage[['date', 'n_requests', 'cost']].copy()
254
- detailed_usage.columns = ['Date', 'Requests', 'Estimated Cost']
255
- st.dataframe(detailed_usage, use_container_width=True)
256
-
257
- # Download button
258
- csv = detailed_usage.to_csv(index=False)
259
- st.download_button(
260
- label="Download Usage Data",
261
- data=csv,
262
- file_name="openai_usage.csv",
263
- mime="text/csv"
264
- )
265
 
266
- else:
267
- st.info("No usage data available for the selected period.")
 
 
268
 
 
 
 
269
  else:
270
- st.error("Failed to fetch data. Please check your API key and try again.")
271
-
272
- except Exception as e:
273
- st.error(f"An error occurred: {str(e)}")
274
-
275
- if __name__ == "__main__":
276
- main()
 
 
1
  import streamlit as st
 
 
 
 
 
 
2
  import requests
3
+ import datetime
 
 
 
4
 
5
+ # Function to retrieve usage data for a specific date
6
+ def get_usage(api_key, date):
7
+ url = 'https://api.openai.com/v1/dashboard/billing/usage'
8
+ headers = {'Authorization': f'Bearer {api_key}'}
9
+ params = {'date': date.strftime('%Y-%m-%d')}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ response = requests.get(url, headers=headers, params=params)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
+ if response.status_code == 200:
14
+ return response.json()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  else:
16
+ st.error(f"Error: {response.status_code} - {response.text}")
17
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ # Streamlit application interface
20
+ st.title("OpenAI API Usage Tracker")
 
 
 
 
21
 
22
+ # Input for API key
23
+ api_key = st.text_input("Enter your OpenAI API Key", type="password")
 
 
 
 
 
 
 
 
24
 
25
+ # Date input
26
+ date = st.date_input("Select a date", datetime.date.today())
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ # Display usage data when button is clicked
29
+ if st.button("Get Usage Data"):
30
+ if api_key:
31
+ usage_data = get_usage(api_key, date)
32
 
33
+ if usage_data:
34
+ total_tokens_used = sum(item['n_generated_tokens_total'] + item['n_context_tokens_total'] for item in usage_data['data'])
35
+ st.write(f"Total tokens used on {date}: {total_tokens_used}")
36
  else:
37
+ st.write("No usage data available for the selected date.")
38
+ else:
39
+ st.warning("Please enter your API key.")