@track decorator
Overview
The Pay-i Python SDK offers a powerful function decorator, @track
, that makes it easy to organize and track your GenAI consumption at the function level. This decorator provides parameter inheritance capabilities that are especially useful for sequences of related GenAI calls that share the same business context.
Purpose of the @track Decorator
The primary purpose of this decorator is to annotate your functions with metadata such as:
- Use case names and IDs
- Limit IDs for budget tracking
- User IDs for attribution
When used with Pay-i's instrumentation system (via payi_instrument()
), the @track
decorator helps maintain consistent tracking across multiple API calls while reducing boilerplate code.
Best Suited For
The @track
decorator is particularly well-suited for:
- Function-level annotations that remain consistent across multiple API calls
- Hierarchical tracking structures where nested functions inherit parameters
- Consistent metadata like use case names, limit and user IDs
- Complex applications with many GenAI calls
For request-specific attributes that vary with each call, consider combining decorators with Custom Headers.
Setup & Installation
Prerequisites
- Pay-i Python SDK installed (
pip install payi
) - A valid Pay-i API key
- One or more supported GenAI providers (OpenAI, Azure OpenAI, Anthropic, AWS Bedrock)
Initializing Pay-i Instrumentation
Before you can use the @track
decorator, you must initialize payi_instrument()
:
import os
from payi.lib.instrument import payi_instrument
# Method 1: Initialize with config dictionary (simplest approach)
# This automatically creates Pay-i clients internally using environment variables
payi_instrument(config={"proxy": False}) # False for Direct Provider Call with Telemetry
You can also explicitly create and pass a Pay-i client:
import os
from payi import Payi # [Payi](/docs/payi-clients) client class
from payi.lib.instrument import payi_instrument
# Read API key from environment variables (best practice)
payi_key = os.getenv("PAYI_API_KEY", "YOUR_PAYI_API_KEY")
# Method 2: Create and provide a Pay-i client
payi = Payi(api_key=payi_key)
payi_instrument(payi)
Once you've initialized the instrumentation, import the @track
decorator:
from payi.lib.instrument import track
GenAI Provider Client Configuration
For Direct Provider Call with Telemetry
When using Direct Provider Call with Telemetry, configure your GenAI provider client normally (direct to provider):
import os
from openai import OpenAI
# Configure a standard provider client with direct access
openai_key = os.getenv("OPENAI_API_KEY", "YOUR_OPENAI_API_KEY")
client = OpenAI(api_key=openai_key)
For Pay-i as a Proxy
When using Pay-i as a Proxy, configure your GenAI provider client to use Pay-i as a proxy:
import os
from openai import OpenAI # Can also be AzureOpenAI or other providers
from payi.lib.helpers import payi_openai_url
# Read API keys from environment variables
payi_key = os.getenv("PAYI_API_KEY", "YOUR_PAYI_API_KEY")
openai_key = os.getenv("OPENAI_API_KEY", "YOUR_OPENAI_API_KEY")
# Configure provider client to use Pay-i as a proxy
client = OpenAI(
api_key=openai_key,
base_url=payi_openai_url(), # Use Pay-i's URL as the base
default_headers={"xProxy-api-key": payi_key} # Authenticate with Pay-i
)
Note:
- For detailed configuration examples with other providers (Azure OpenAI, Anthropic, AWS Bedrock), refer to the Provider Configuration guide.
- With proxy setup alone, Pay-i will track all API calls but won't have function annotations. To add annotations, you must also initialize
payi_instrument()
and use the@track
decorator in your code.
Using the @track Decorator
After initializing payi_instrument()
and configuring your provider client, you can use the @track
decorator to annotate your functions.
How @track works: The decorator first executes your decorated function and then handles the GenAI calls based on your Pay-i configuration (Direct Provider Call with Telemetry or Proxy Routing).
from payi.lib.instrument import track
# Apply @track to a function to add business context
@track(
use_case_name='document_summary',
limit_ids=['daily_budget'],
user_id='user_123'
)
def summarize_document(client, document_text):
# Every API call inside this function will automatically
# include the use_case_name, limit_ids and user_id
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": f"Summarize this: {document_text}"}]
)
return response.choices[0].message.content
When using the @track
decorator:
- The decorator's metadata (use_case_name, limit_ids, user_id, etc.) is added to a context stack
- All API calls inside the function automatically inherit these parameters
- Pay-i captures usage data with all the annotations you've provided
- When specifying
use_case_name
(withoutuse_case_id
), the decorator will create an ID automatically
Examples
The @track
decorator works for different types of GenAI applications:
# Example: Document summarization with use case tracking
@track(use_case_name='document_summary')
def summarize_document(client, document_text):
# Simple annotation with just use case name
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": f"Summarize this: {document_text}"}]
)
return response.choices[0].message.content
# Example: Customer support function with multiple limits
@track(
use_case_name='customer_support',
limit_ids=['support_budget', 'quality_limit']
)
def get_support_response(client, question):
# Automatically tracks against both limits
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": question}]
)
return response.choices[0].message.content
# Example: Using application context for user ID
from flask import g # Application context example
@track(
use_case_name='user_dashboard',
user_id=g.user.id # User ID from application context
)
def generate_dashboard_summary(client):
# Automatically attributes API usage to the current user
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "Summarize dashboard data"}]
)
return response.choices[0].message.content
Supported Parameters
The @track
decorator supports these parameters:
Parameter | Description |
---|---|
use_case_name | Name of the use case for tracking purposes |
use_case_id | ID of the use case (generated automatically if not provided) |
use_case_version | Version number of the use case |
limit_ids | List of limit IDs to apply to the wrapped function |
user_id | ID of the user making the request (from application context) |
proxy | Control whether to use proxy mode (True) or ingest mode (False) |
For request-specific parameters not directly supported by @track
, see the track_context()
function and Custom Headers documentation.
Note: For combining
@track
with request-specific parameters, see Combined Annotations.
Understanding Parameter Inheritance
When nesting decorated functions or using them with other annotation methods, Pay-i follows a "latest wins" strategy based on execution order.
Here's a simple example showing how parameter inheritance works when calling a decorated function from another decorated function:
from payi.lib.instrument import track
@track(use_case_name='outer_function')
def outer_function():
# All API calls here use use_case_name='outer_function'
# Call another decorated function
inner_function() # Inherits use_case_name='outer_function'
# Call a function with its own annotation
specific_function() # Does NOT inherit - uses its own use_case_name
@track() # Empty decorator - will inherit from caller
def inner_function():
# When called from outer_function():
# - Inherits use_case_name='outer_function'
client.chat.completions.create(...)
@track(use_case_name='specific_function')
def specific_function():
# Always uses its own annotation regardless of caller
# - use_case_name='specific_function' (overrides any inherited value)
client.chat.completions.create(...)
This shows the basic pattern of inheritance. For comprehensive details on parameter precedence, including how different parameter types behave and how they combine with other annotation methods, see:
- Combined Annotations - For practical examples of combining different annotation approaches
- Parameter Precedence in Pay-i Instrumentation - For detailed technical reference on parameter behavior
Related Resources
Updated 5 days ago