如何使用 Usage API 和 Cost API 监控您的 OpenAI 使用量

,
2025年1月14日
在 Github 中打开

对于我们的大多数用户来说,默认的使用量和成本仪表板已经足够了。但是,如果您需要更详细的数据或自定义仪表板,您可以使用 Completions Usage API。

本笔记本演示了如何从 OpenAI Completions Usage API 和 Costs API 中检索和可视化使用量数据。我们将:

  • 调用 API 获取 completions 使用量数据。
  • 将 JSON 响应解析为 pandas DataFrame。
  • 使用 matplotlib 可视化随时间变化的 token 使用量。
  • 使用按模型分组来分析不同模型之间的 token 使用量。
  • 使用饼图显示模型分布。

我们还包含了所有可能的 API 参数的占位符,以便进行全面的概述。

# Install required libraries (if not already installed)
!pip install requests pandas numpy matplotlib --quiet

# Import libraries
import requests
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import time
import json

# For inline plotting in Jupyter
%matplotlib inline
# Reusable function for retrieving paginated data from the API
def get_data(url, params):
    # Set up the API key and headers
    OPENAI_ADMIN_KEY = 'PLACEHOLDER'

    headers = {
        "Authorization": f"Bearer {OPENAI_ADMIN_KEY}",
        "Content-Type": "application/json",
    }

    # Initialize an empty list to store all data
    all_data = []

    # Initialize pagination cursor
    page_cursor = None

    # Loop to handle pagination
    while True:
        if page_cursor:
            params["page"] = page_cursor

        response = requests.get(url, headers=headers, params=params)

        if response.status_code == 200:
            data_json = response.json()
            all_data.extend(data_json.get("data", []))

            page_cursor = data_json.get("next_page")
            if not page_cursor:
                break
        else:
            print(f"Error: {response.status_code}")
            break

    if all_data:
        print("Data retrieved successfully!")
    else:
        print("Issue: No data available to retrieve.")
    return all_data
# Define the API endpoint
url = "https://api.openai.com/v1/organization/usage/completions"

# Calculate start time: n days ago from now
days_ago = 30
start_time = int(time.time()) - (days_ago * 24 * 60 * 60)

# Define parameters with placeholders for all possible options
params = {
    "start_time": start_time,  # Required: Start time (Unix seconds)
    # "end_time": end_time,  # Optional: End time (Unix seconds)
    "bucket_width": "1d",  # Optional: '1m', '1h', or '1d' (default '1d')
    # "project_ids": ["proj_example"],  # Optional: List of project IDs
    # "user_ids": ["user_example"],     # Optional: List of user IDs
    # "api_key_ids": ["key_example"],   # Optional: List of API key IDs
    # "models": ["o1-2024-12-17", "gpt-4o-2024-08-06", "gpt-4o-mini-2024-07-18"],  # Optional: List of models
    # "batch": False,             # Optional: True for batch jobs, False for non-batch
    # "group_by": ["model"],     # Optional: Fields to group by
    "limit": 7,  # Optional: Number of buckets to return, this will chunk the data into 7 buckets
    # "page": "cursor_string"   # Optional: Cursor for pagination
}

usage_data = get_data(url, params)
Data retrieved successfully!

检查 JSON 响应

让我们看看来自 API 的原始 JSON 响应,以了解其结构。

print(json.dumps(usage_data, indent=2))
[
  {
    "object": "bucket",
    "start_time": 1736616660,
    "end_time": 1736640000,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 141201,
        "output_tokens": 9756,
        "num_model_requests": 470,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1736640000,
    "end_time": 1736726400,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 45949,
        "output_tokens": 282,
        "num_model_requests": 150,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1736726400,
    "end_time": 1736812800,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 3718360,
        "output_tokens": 97756,
        "num_model_requests": 3053,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 76544,
        "input_audio_tokens": 5776,
        "output_audio_tokens": 3166
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1736812800,
    "end_time": 1736899200,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 52786,
        "output_tokens": 38204,
        "num_model_requests": 157,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 5440,
        "input_audio_tokens": 4066,
        "output_audio_tokens": 1097
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1736899200,
    "end_time": 1736985600,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 35664,
        "output_tokens": 1835,
        "num_model_requests": 55,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 192,
        "input_audio_tokens": 2520,
        "output_audio_tokens": 1549
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1736985600,
    "end_time": 1737072000,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 5464,
        "output_tokens": 2667,
        "num_model_requests": 8,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737072000,
    "end_time": 1737158400,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 3390547,
        "output_tokens": 38604,
        "num_model_requests": 2687,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 25344,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737158400,
    "end_time": 1737244800,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 8117824,
        "output_tokens": 105662,
        "num_model_requests": 6335,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 46464,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737244800,
    "end_time": 1737331200,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 13542,
        "output_tokens": 85,
        "num_model_requests": 46,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737331200,
    "end_time": 1737417600,
    "results": []
  },
  {
    "object": "bucket",
    "start_time": 1737417600,
    "end_time": 1737504000,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 29806,
        "output_tokens": 57604,
        "num_model_requests": 98,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737504000,
    "end_time": 1737590400,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 1823,
        "output_tokens": 1467,
        "num_model_requests": 7,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737590400,
    "end_time": 1737676800,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 7126,
        "output_tokens": 1896,
        "num_model_requests": 19,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737676800,
    "end_time": 1737763200,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 22187,
        "output_tokens": 822,
        "num_model_requests": 75,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 640,
        "input_audio_tokens": 2557,
        "output_audio_tokens": 3103
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737763200,
    "end_time": 1737849600,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 30204,
        "output_tokens": 65673,
        "num_model_requests": 99,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737849600,
    "end_time": 1737936000,
    "results": []
  },
  {
    "object": "bucket",
    "start_time": 1737936000,
    "end_time": 1738022400,
    "results": []
  },
  {
    "object": "bucket",
    "start_time": 1738022400,
    "end_time": 1738108800,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 2541,
        "output_tokens": 1604,
        "num_model_requests": 14,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738108800,
    "end_time": 1738195200,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 68339,
        "output_tokens": 49525,
        "num_model_requests": 217,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 7296,
        "input_audio_tokens": 20033,
        "output_audio_tokens": 3168
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738195200,
    "end_time": 1738281600,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 18481,
        "output_tokens": 17500,
        "num_model_requests": 84,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 2944,
        "input_audio_tokens": 10076,
        "output_audio_tokens": 4966
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738281600,
    "end_time": 1738368000,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 1187894,
        "output_tokens": 139134,
        "num_model_requests": 5528,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 2112,
        "input_audio_tokens": 4935,
        "output_audio_tokens": 993
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738368000,
    "end_time": 1738454400,
    "results": []
  },
  {
    "object": "bucket",
    "start_time": 1738454400,
    "end_time": 1738540800,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 7268,
        "output_tokens": 30563,
        "num_model_requests": 24,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738540800,
    "end_time": 1738627200,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 15121,
        "output_tokens": 22866,
        "num_model_requests": 48,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738627200,
    "end_time": 1738713600,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 16735,
        "output_tokens": 16177,
        "num_model_requests": 50,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 1152,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738713600,
    "end_time": 1738800000,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 6573,
        "output_tokens": 4238,
        "num_model_requests": 43,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738800000,
    "end_time": 1738886400,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 1402,
        "output_tokens": 2042,
        "num_model_requests": 18,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738886400,
    "end_time": 1738972800,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 11847,
        "output_tokens": 21938,
        "num_model_requests": 47,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738972800,
    "end_time": 1739059200,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 1993,
        "output_tokens": 12,
        "num_model_requests": 7,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1739059200,
    "end_time": 1739145600,
    "results": []
  },
  {
    "object": "bucket",
    "start_time": 1739145600,
    "end_time": 1739208663,
    "results": [
      {
        "object": "organization.usage.completions.result",
        "input_tokens": 332,
        "output_tokens": 1509,
        "num_model_requests": 8,
        "project_id": null,
        "user_id": null,
        "api_key_id": null,
        "model": null,
        "batch": null,
        "input_cached_tokens": 0,
        "input_audio_tokens": 0,
        "output_audio_tokens": 0
      }
    ]
  }
]
# Initialize a list to hold parsed records
records = []

# Iterate through the data to extract bucketed data
for bucket in usage_data:
    start_time = bucket.get("start_time")
    end_time = bucket.get("end_time")
    for result in bucket.get("results", []):
        records.append(
            {
                "start_time": start_time,
                "end_time": end_time,
                "input_tokens": result.get("input_tokens", 0),
                "output_tokens": result.get("output_tokens", 0),
                "input_cached_tokens": result.get("input_cached_tokens", 0),
                "input_audio_tokens": result.get("input_audio_tokens", 0),
                "output_audio_tokens": result.get("output_audio_tokens", 0),
                "num_model_requests": result.get("num_model_requests", 0),
                "project_id": result.get("project_id"),
                "user_id": result.get("user_id"),
                "api_key_id": result.get("api_key_id"),
                "model": result.get("model"),
                "batch": result.get("batch"),
            }
        )

# Create a DataFrame from the records
df = pd.DataFrame(records)

# Convert Unix timestamps to datetime for readability
df["start_datetime"] = pd.to_datetime(df["start_time"], unit="s")
df["end_datetime"] = pd.to_datetime(df["end_time"], unit="s")

# Reorder columns for better readability
df = df[
    [
        "start_datetime",
        "end_datetime",
        "start_time",
        "end_time",
        "input_tokens",
        "output_tokens",
        "input_cached_tokens",
        "input_audio_tokens",
        "output_audio_tokens",
        "num_model_requests",
        "project_id",
        "user_id",
        "api_key_id",
        "model",
        "batch",
    ]
]

# Display the DataFrame
df.head()
start_datetime end_datetime start_time end_time input_tokens output_tokens input_cached_tokens input_audio_tokens output_audio_tokens num_model_requests project_id user_id api_key_id model batch
0 2025-01-11 17:31:00 2025-01-12 1736616660 1736640000 141201 9756 0 0 0 470 None None None None None
1 2025-01-12 00:00:00 2025-01-13 1736640000 1736726400 45949 282 0 0 0 150 None None None None None
2 2025-01-13 00:00:00 2025-01-14 1736726400 1736812800 3718360 97756 76544 5776 3166 3053 None None None None None
3 2025-01-14 00:00:00 2025-01-15 1736812800 1736899200 52786 38204 5440 4066 1097 157 None None None None None
4 2025-01-15 00:00:00 2025-01-16 1736899200 1736985600 35664 1835 192 2520 1549 55 None None None None None
if not df.empty:
    plt.figure(figsize=(12, 6))

    # Create bar charts for input and output tokens
    width = 0.35  # width of the bars
    indices = range(len(df))

    plt.bar(indices, df["input_tokens"], width=width, label="Input Tokens", alpha=0.7)
    plt.bar(
        [i + width for i in indices],
        df["output_tokens"],
        width=width,
        label="Output Tokens",
        alpha=0.7,
    )

    # Set labels and ticks
    plt.xlabel("Time Bucket")
    plt.ylabel("Number of Tokens")
    plt.title("Daily Input vs Output Token Usage Last 30 Days")
    plt.xticks(
        [i + width / 2 for i in indices],
        [dt.strftime("%Y-%m-%d") for dt in df["start_datetime"]],
        rotation=45,
    )
    plt.legend()
    plt.tight_layout()
    plt.show()
else:
    print("No data available to plot.")
image generated by notebook

可视化示例:按模型分组

在本节中,我们检索并可视化按模型和 project_id 分组的使用量数据。这可以帮助您查看每个模型在指定期间内使用的总 token 数。

关于分组参数的说明

  • 如果您不指定 group_by 参数,则 project_idmodel 等字段将返回为 null。虽然 group_by 参数是可选的,但建议在大多数情况下包含它以检索有意义的数据。

  • 您可以通过逗号分隔来指定多个分组字段。例如:group_by=["model", "project_id"]

# Calculate start time: n days ago from now
days_ago = 30
start_time = int(time.time()) - (days_ago * 24 * 60 * 60)

# Define parameters with grouping by model and project_id
params = {
    "start_time": start_time,  # Required: Start time (Unix seconds)
    "bucket_width": "1d",  # Optional: '1m', '1h', or '1d' (default '1d')
    "group_by": ["model", "project_id"],  # Group data by model and project_id
    "limit": 7,  # Optional: Number of buckets to return
}

# Initialize an empty list to store all data
all_group_data = get_data(url, params)

# Initialize a list to hold parsed records
records = []

# Iterate through the data to extract bucketed data
for bucket in all_group_data:
    start_time = bucket.get("start_time")
    end_time = bucket.get("end_time")
    for result in bucket.get("results", []):
        records.append(
            {
                "start_time": start_time,
                "end_time": end_time,
                "input_tokens": result.get("input_tokens", 0),
                "output_tokens": result.get("output_tokens", 0),
                "input_cached_tokens": result.get("input_cached_tokens", 0),
                "input_audio_tokens": result.get("input_audio_tokens", 0),
                "output_audio_tokens": result.get("output_audio_tokens", 0),
                "num_model_requests": result.get("num_model_requests", 0),
                "project_id": result.get("project_id", "N/A"),
                "user_id": result.get("user_id", "N/A"),
                "api_key_id": result.get("api_key_id", "N/A"),
                "model": result.get("model", "N/A"),
                "batch": result.get("batch", "N/A"),
            }
        )

# Create a DataFrame from the records
df = pd.DataFrame(records)

# Convert Unix timestamps to datetime for readability
df["start_datetime"] = pd.to_datetime(df["start_time"], unit="s", errors="coerce")
df["end_datetime"] = pd.to_datetime(df["end_time"], unit="s", errors="coerce")

# Reorder columns for better readability
df = df[
    [
        "start_datetime",
        "end_datetime",
        "start_time",
        "end_time",
        "input_tokens",
        "output_tokens",
        "input_cached_tokens",
        "input_audio_tokens",
        "output_audio_tokens",
        "num_model_requests",
        "project_id",
        "user_id",
        "api_key_id",
        "model",
        "batch",
    ]
]

# Display the DataFrame
df.head()
Data retrieved successfully!
start_datetime end_datetime start_time end_time input_tokens output_tokens input_cached_tokens input_audio_tokens output_audio_tokens num_model_requests project_id user_id api_key_id model batch
0 2025-01-11 17:31:39 2025-01-12 1736616699 1736640000 6897 97 0 0 0 97 proj_hNhhQzyYu7HxySZWs7cA3Ugu None None gpt-4o-mini-2024-07-18 None
1 2025-01-11 17:31:39 2025-01-12 1736616699 1736640000 33984 206 0 0 0 95 proj_hNhhQzyYu7HxySZWs7cA3Ugu None None ft:gpt-4o-2024-08-06:distillation-test:wordle2... None
2 2025-01-11 17:31:39 2025-01-12 1736616699 1736640000 2846 8874 0 0 0 8 proj_hNhhQzyYu7HxySZWs7cA3Ugu None None o1-mini-2024-09-12 None
3 2025-01-11 17:31:39 2025-01-12 1736616699 1736640000 97474 579 0 0 0 270 proj_hNhhQzyYu7HxySZWs7cA3Ugu None None gpt-4o-2024-08-06 None
4 2025-01-12 00:00:00 2025-01-13 1736640000 1736726400 1989 28 0 0 0 28 proj_hNhhQzyYu7HxySZWs7cA3Ugu None None gpt-4o-mini-2024-07-18 None
# Group data by model and project_id and aggregate model request counts
grouped_by_model_project = (
    df.groupby(["model", "project_id"])
    .agg(
        {
            "num_model_requests": "sum",
        }
    )
    .reset_index()
)

# Determine unique models and project IDs for plotting and color mapping
models = sorted(grouped_by_model_project["model"].unique())
project_ids = sorted(grouped_by_model_project["project_id"].unique())
distinct_colors = [
    "#1f77b4",
    "#ff7f0e",
    "#2ca02c",
    "#d62728",
    "#9467bd",
    "#8c564b",
    "#e377c2",
    "#7f7f7f",
    "#bcbd22",
    "#17becf",
]
project_color_mapping = {
    pid: distinct_colors[i % len(distinct_colors)] for i, pid in enumerate(project_ids)
}

# Calculate total number of requests per project_id for legend
project_totals = (
    grouped_by_model_project.groupby("project_id")["num_model_requests"]
    .sum()
    .sort_values(ascending=False)  # Sort by highest total first
)

# Set up bar positions
n_models = len(models)
bar_width = 0.6
x = np.arange(n_models)

plt.figure(figsize=(12, 6))

# Plot stacked bars for each model
for model_idx, model in enumerate(models):
    # Filter data for the current model
    model_data = grouped_by_model_project[grouped_by_model_project["model"] == model]

    bottom = 0
    # Stack segments for each project ID within the bars
    for _, row in model_data.iterrows():
        color = project_color_mapping[row["project_id"]]
        plt.bar(
            x[model_idx],
            row["num_model_requests"],
            width=bar_width,
            bottom=bottom,
            color=color,
        )
        bottom += row["num_model_requests"]

# Labeling and styling
plt.xlabel("Model")
plt.ylabel("Number of Model Requests")
plt.title("Total Model Requests by Model and Project ID Last 30 Days")
plt.xticks(x, models, rotation=45, ha="right")

# Create a sorted legend with totals
handles = [
    mpatches.Patch(color=project_color_mapping[pid], label=f"{pid} (Total: {total})")
    for pid, total in project_totals.items()
]
plt.legend(handles=handles, bbox_to_anchor=(1.05, 1), loc="upper left")

plt.tight_layout()
plt.show()
image generated by notebook
records = []
for bucket in all_group_data:
    for result in bucket.get("results", []):
        records.append(
            {
                "project_id": result.get("project_id", "N/A"),
                "num_model_requests": result.get("num_model_requests", 0),
            }
        )

# Create a DataFrame
df = pd.DataFrame(records)

# Aggregate data by project_id
grouped_by_project = (
    df.groupby("project_id").agg({"num_model_requests": "sum"}).reset_index()
)

# Visualize Pie Chart
if not grouped_by_project.empty:
    # Filter out rows where num_model_requests == 0
    filtered_grouped_by_project = grouped_by_project[
        grouped_by_project["num_model_requests"] > 0
    ]

    # Calculate the total model requests after filtering
    total_requests = filtered_grouped_by_project["num_model_requests"].sum()

    if total_requests > 0:
        # Calculate percentage of total for each project
        filtered_grouped_by_project["percentage"] = (
            filtered_grouped_by_project["num_model_requests"] / total_requests
        ) * 100

        # Separate "Other" projects (below 5%)
        other_projects = filtered_grouped_by_project[
            filtered_grouped_by_project["percentage"] < 5
        ]
        main_projects = filtered_grouped_by_project[
            filtered_grouped_by_project["percentage"] >= 5
        ]

        # Sum up "Other" projects
        if not other_projects.empty:
            other_row = pd.DataFrame(
                {
                    "project_id": ["Other"],
                    "num_model_requests": [other_projects["num_model_requests"].sum()],
                    "percentage": [other_projects["percentage"].sum()],
                }
            )
            filtered_grouped_by_project = pd.concat(
                [main_projects, other_row], ignore_index=True
            )

        # Sort by number of requests for better legend organization
        filtered_grouped_by_project = filtered_grouped_by_project.sort_values(
            by="num_model_requests", ascending=False
        )

        # Main pie chart for distribution of model requests by project_id
        plt.figure(figsize=(10, 8))
        plt.pie(
            filtered_grouped_by_project["num_model_requests"],
            labels=filtered_grouped_by_project["project_id"],
            autopct=lambda p: f"{p:.1f}%\n({int(p * total_requests / 100):,})",
            startangle=140,
            textprops={"fontsize": 10},
        )
        plt.title("Distribution of Model Requests by Project ID", fontsize=14)
        plt.axis("equal")  # Equal aspect ratio ensures pie chart is circular.
        plt.tight_layout()
        plt.show()

        # If there are "Other" projects, generate a second pie chart for breakdown
        if not other_projects.empty:
            other_total_requests = other_projects["num_model_requests"].sum()

            plt.figure(figsize=(10, 8))
            plt.pie(
                other_projects["num_model_requests"],
                labels=other_projects["project_id"],
                autopct=lambda p: f"{p:.1f}%\n({int(p * other_total_requests / 100):,})",
                startangle=140,
                textprops={"fontsize": 10},
            )
            plt.title('Breakdown of "Other" Projects by Model Requests', fontsize=14)
            plt.axis("equal")  # Equal aspect ratio ensures pie chart is circular.
            plt.tight_layout()
            plt.show()
    else:
        print("Total model requests is zero. Pie chart will not be rendered.")
else:
    print("No grouped data available for pie chart.")
image generated by notebookimage generated by notebook

Costs API 示例

在本节中,我们将使用 OpenAI Costs API 来检索和可视化成本数据。与 completions 数据类似,我们将:

  • 调用 Costs API 获取聚合成本数据。
  • 将 JSON 响应解析为 pandas DataFrame。
  • 使用条形图可视化按行项目分组的成本。
# Calculate start time: n days ago from now
days_ago = 30
start_time = int(time.time()) - (days_ago * 24 * 60 * 60)

# Define the Costs API endpoint
costs_url = "https://api.openai.com/v1/organization/costs"

costs_params = {
    "start_time": start_time,  # Required: Start time (Unix seconds)
    "bucket_width": "1d",  # Optional: Currently only '1d' is supported
    "limit": 30,  # Optional: Number of buckets to return
}

# Initialize an empty list to store all data
all_costs_data = get_data(costs_url, costs_params)
Data retrieved successfully!
print(json.dumps(all_costs_data, indent=2))
[
  {
    "object": "bucket",
    "start_time": 1736553600,
    "end_time": 1736640000,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.13080438340307526,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1736640000,
    "end_time": 1736726400,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.12270423340307525,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1736726400,
    "end_time": 1736812800,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 9.888144383403077,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1736812800,
    "end_time": 1736899200,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.3507639334030752,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1736899200,
    "end_time": 1736985600,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.2977481185324674,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1736985600,
    "end_time": 1737072000,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.00925485477848094,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737072000,
    "end_time": 1737158400,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 8.889884136532304,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737158400,
    "end_time": 1737244800,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 21.167310118127915,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737244800,
    "end_time": 1737331200,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.04955636812791847,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737331200,
    "end_time": 1737417600,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.0003226181279184669,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737417600,
    "end_time": 1737504000,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.6320363681279185,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737504000,
    "end_time": 1737590400,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 52.41558761812793,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737590400,
    "end_time": 1737676800,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 104.88761235323427,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737676800,
    "end_time": 1737763200,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.3376030385950106,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737763200,
    "end_time": 1737849600,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.062551042553524,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737849600,
    "end_time": 1737936000,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.00032195744715549047,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1737936000,
    "end_time": 1738022400,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.0003084210662774742,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738022400,
    "end_time": 1738108800,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.00032195744715549047,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738108800,
    "end_time": 1738195200,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.5142559074471554,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738195200,
    "end_time": 1738281600,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.21870350744715547,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738281600,
    "end_time": 1738368000,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 1.4528752074471551,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738368000,
    "end_time": 1738454400,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.00042714787262957543,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738454400,
    "end_time": 1738540800,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.00032195744715549047,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738540800,
    "end_time": 1738627200,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.0031147346857709622,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738627200,
    "end_time": 1738713600,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 68.30023964957941,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738713600,
    "end_time": 1738800000,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 14.858330207447157,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738800000,
    "end_time": 1738886400,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.3137180574471555,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738886400,
    "end_time": 1738972800,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.02677460744715549,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1738972800,
    "end_time": 1739059200,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.007399792553524012,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1739059200,
    "end_time": 1739145600,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.00032195744715549047,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  },
  {
    "object": "bucket",
    "start_time": 1739145600,
    "end_time": 1739232000,
    "results": [
      {
        "object": "organization.costs.result",
        "amount": {
          "value": 0.00012073404268330895,
          "currency": "usd"
        },
        "line_item": null,
        "project_id": null,
        "organization_id": "org-GLHrIv00VVN9dEQC2b4wsBkf"
      }
    ]
  }
]
# Initialize a list to hold parsed cost records
cost_records = []

# Extract bucketed cost data from all_costs_data
for bucket in all_costs_data:
    start_time = bucket.get("start_time")
    end_time = bucket.get("end_time")
    for result in bucket.get("results", []):
        cost_records.append(
            {
                "start_time": start_time,
                "end_time": end_time,
                "amount_value": result.get("amount", {}).get("value", 0),
                "currency": result.get("amount", {}).get("currency", "usd"),
                "line_item": result.get("line_item"),
                "project_id": result.get("project_id"),
            }
        )

# Create a DataFrame from the cost records
cost_df = pd.DataFrame(cost_records)

# Convert Unix timestamps to datetime for readability
cost_df["start_datetime"] = pd.to_datetime(cost_df["start_time"], unit="s")
cost_df["end_datetime"] = pd.to_datetime(cost_df["end_time"], unit="s")

# Display the first few rows of the DataFrame
cost_df.head()
start_time end_time amount_value currency line_item project_id start_datetime end_datetime
0 1736553600 1736640000 0.130804 usd None None 2025-01-11 2025-01-12
1 1736640000 1736726400 0.122704 usd None None 2025-01-12 2025-01-13
2 1736726400 1736812800 9.888144 usd None None 2025-01-13 2025-01-14
3 1736812800 1736899200 0.350764 usd None None 2025-01-14 2025-01-15
4 1736899200 1736985600 0.297748 usd None None 2025-01-15 2025-01-16

可视化每日总成本

我们将创建一个条形图,以可视化按天聚合的总成本。这有助于从宏观层面了解组织支出。

if not cost_df.empty:
    # Ensure datetime conversion for 'start_datetime' column
    if (
        "start_datetime" not in cost_df.columns
        or not pd.api.types.is_datetime64_any_dtype(cost_df["start_datetime"])
    ):
        cost_df["start_datetime"] = pd.to_datetime(
            cost_df["start_time"], unit="s", errors="coerce"
        )

    # Create a new column for just the date part of 'start_datetime'
    cost_df["date"] = cost_df["start_datetime"].dt.date

    # Group by date and sum the amounts
    cost_per_day = cost_df.groupby("date")["amount_value"].sum().reset_index()

    # Plot the data
    plt.figure(figsize=(12, 6))
    plt.bar(
        cost_per_day["date"],
        cost_per_day["amount_value"],
        width=0.6,
        color="skyblue",
        alpha=0.8,
    )
    plt.xlabel("Date")
    plt.ylabel("Total Cost (USD)")
    plt.title("Total Cost per Day (Last 30 Days)")
    plt.xticks(rotation=45, ha="right")
    plt.tight_layout()
    plt.show()
else:
    print("No cost data available to plot.")
image generated by notebook

可视化按行项目划分的成本

我们将创建一个条形图,以可视化按行项目聚合的总成本。这有助于确定哪些类别(例如,模型或其他服务)对费用贡献最大。

days_ago = 30
start_time = int(time.time()) - (days_ago * 24 * 60 * 60)

costs_params = {
    "start_time": start_time,  # Required: Start time (Unix seconds)
    "bucket_width": "1d",  # Optional: Currently only '1d' is supported
    "limit": 30,  # Optional: Number of buckets to return
    "group_by": ["line_item"],
}

line_item_cost_data = get_data(costs_url, costs_params)

# Initialize a list to hold parsed cost records
cost_records = []

# Extract bucketed cost data from all_costs_data
for bucket in line_item_cost_data:
    start_time = bucket.get("start_time")
    end_time = bucket.get("end_time")
    for result in bucket.get("results", []):
        cost_records.append(
            {
                "start_time": start_time,
                "end_time": end_time,
                "amount_value": result.get("amount", {}).get("value", 0),
                "currency": result.get("amount", {}).get("currency", "usd"),
                "line_item": result.get("line_item"),
                "project_id": result.get("project_id"),
            }
        )

# Create a DataFrame from the cost records
cost_df = pd.DataFrame(cost_records)

# Convert Unix timestamps to datetime for readability
cost_df["start_datetime"] = pd.to_datetime(cost_df["start_time"], unit="s")
cost_df["end_datetime"] = pd.to_datetime(cost_df["end_time"], unit="s")

# Display the first few rows of the DataFrame
cost_df.head()
Data retrieved successfully!
start_time end_time amount_value currency line_item project_id start_datetime end_datetime
0 1736553600 1736640000 0.127440 usd ft-gpt-4o-2024-08-06, 输入 proj_hNhhQzyYu7HxySZWs7cA3Ugu 2025-01-11 2025-01-12
1 1736553600 1736640000 0.003090 usd ft-gpt-4o-2024-08-06, 输出 proj_hNhhQzyYu7HxySZWs7cA3Ugu 2025-01-11 2025-01-12
2 1736553600 1736640000 0.000271 usd assistants api | 文件搜索 proj_L67gOme4S2nBA8aQieEOwLy7 2025-01-11 2025-01-12
3 1736553600 1736640000 0.000003 usd assistants api | 文件搜索 proj_VV4ZAjd6ALfFd9uh0vY8joR1 2025-01-11 2025-01-12
4 1736640000 1736726400 0.028607 usd evals | gpt-4o-mini-2024-07-18, 输入 proj_L67gOme4S2nBA8aQieEOwLy7 2025-01-12 2025-01-13
if not cost_df.empty:
    # Ensure datetime conversion for 'start_datetime' column
    if "start_datetime" not in cost_df.columns or not pd.api.types.is_datetime64_any_dtype(cost_df["start_datetime"]):
        cost_df["start_datetime"] = pd.to_datetime(cost_df["start_time"], unit="s", errors="coerce")

    # Create a new column for just the date part of 'start_datetime'
    cost_df["date"] = cost_df["start_datetime"].dt.date

    # Group by date and line_item and sum the amounts
    cost_per_day = cost_df.groupby(["date", "line_item"])["amount_value"].sum().reset_index()

    # Pivot the DataFrame so each date has one bar with line_item stacks
    cost_pivot = cost_per_day.pivot(index="date", columns="line_item", values="amount_value").fillna(0)
    cost_pivot = cost_pivot.sort_index()

    # Plot a stacked bar chart with one bar for each grouped day
    plt.figure(figsize=(12, 6))
    ax = cost_pivot.plot(kind="bar", stacked=True, ax=plt.gca(), width=0.8)
    plt.xlabel("Date")
    plt.ylabel("Total Cost (USD)")
    plt.title("Total Cost by Line Item")
    plt.xticks(rotation=45, ha="right")
    # Update legend so it doesn't overlay the graph by placing it outside the plot area
    plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left", borderaxespad=0.)
    plt.tight_layout()
    plt.show()
else:
    print("No cost data available to plot.")
/var/folders/r_/g8r2dz8s2qd104th5p5yxljr0000gp/T/ipykernel_49468/2813361465.py:25: UserWarning: Tight layout not applied. The bottom and top margins cannot be made large enough to accommodate all Axes decorations.
  plt.tight_layout()
image generated by notebook

其他可视化(可选)

您可以为 Completions 和 Costs API 扩展此笔记本,添加更多可视化效果。例如:

Completions API

  • 按用户、项目或模型分组,以查看哪些消耗的 token 最多。
  • 创建折线图,用于分析几天或几小时内 token 使用量的时间序列。
  • 使用饼图可视化 token 在模型、用户或项目之间的分布。
  • 尝试不同的 group_by 参数(例如,["model", "user_id"])以获得更深入的见解。

Costs API

  • 按项目或行项目分组,以识别支出模式。
  • 创建折线图或条形图,以可视化每日成本趋势。
  • 使用饼图显示成本如何在项目、服务或行项目之间分布。
  • 尝试各种 group_by 选项(例如,["project_id"], ["line_item"])以进行精细分析。

使用 pandasmatplotlib(或 Plotly/Bokeh 等库)尝试不同的参数和可视化技术,以获得更深入的见解,并考虑将这些可视化集成到交互式仪表板中以进行实时监控。

与第三方仪表板平台集成

要将 OpenAI 使用量和成本数据引入 Tableau、Power BI 或自定义平台(例如,Plotly Dash、Bokeh)等外部仪表板工具,请按照以下步骤操作:

  1. 数据收集与准备

    • 使用 Python 脚本定期从 Completions 和 Costs API 获取数据。
    • 使用 pandas 处理和聚合数据,然后将其存储在数据库、数据仓库中,或将其导出为 CSV/JSON 文件。
  2. 连接到仪表板

    • BI 工具(Tableau、Power BI)
      • 直接连接到准备好的数据源(SQL 数据库、CSV 文件或 Web API)。
      • 使用内置连接器来安排数据刷新,确保仪表板始终显示当前信息。
    • 自定义仪表板(Plotly Dash、Bokeh)
      • 将 API 调用和数据处理嵌入到仪表板代码中。
      • 构建交互式可视化组件,以便在新数据获取时自动更新。
  3. 实时与自动更新

    • 使用 cron 任务、任务计划程序或工作流工具(例如,Apache Airflow)来安排脚本定期刷新数据。
    • 实施 webhook 或流式 API(如果可用)以实现近实时数据更新。

通过将 API 数据集成到第三方平台,您可以创建交互式、实时的仪表板,将 OpenAI 指标与其他业务数据相结合,从而提供全面的见解和自动监控。