Guides

Annotations

Overview

Pay-i provides four complementary approaches for adding metadata to your GenAI requests. Each method operates at a different scope and is ideal for different use cases.

The Four Annotation Approaches

ApproachScopeBest ForDocumentation
Global DefaultsApplication-wideDefault parameters for the entire applicationpayi_instrument()
@track DecoratorFunctionFunction-level annotations that propagate through the call treetrack_decorator
track_context()Code Block/RequestArbitrary code blocks and request-specific annotations in Pythontrack_context
Custom HeadersRequestRequest annotations in non-Python environmentsCustom Headers

Choosing the Right Approach

Each annotation approach has different strengths and is suited for different types of tasks:

Global Defaults with payi_instrument()

Use when you need:

  • Application-wide defaults that apply to all requests
  • Consistent base values across your entire application
  • A simple foundation for all other annotations to build upon

Example:

from payi.lib.instrument import payi_instrument

# Set global defaults for the entire application
payi_instrument(config={
    "use_case_name": "my_application",
    "limit_ids": ["application_budget"],
    "proxy": False  # Direct Provider Call with Telemetry
})

Function-Level with @track

Use when you need:

  • Function-level annotations that apply to all API calls within a function
  • Parameter inheritance across a call tree
  • Consistent business context across related operations
  • User attribution from application context (like session data)

Example:

from payi.lib.instrument import track

@track(use_case_name="summarization", limit_ids=["daily_budget"])
def process_document(client, text):
    # All API calls inside this function inherit the parameters
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": text}]
    )
    return response

Learn more about @track

Block-Level with track_context()

Use when you need:

  • Code block-specific annotations without creating a function
  • Support for additional parameters like request_tags
  • Temporary parameter overrides within a larger function
  • Dynamic user attribution that changes during execution

Example:

from payi.lib.instrument import track_context

def process_multiple_documents(client, documents):
    for i, doc in enumerate(documents):
        # Each document gets its own tracking context
        with track_context(
            use_case_name="doc_processing",
            request_tags=[f"document_{i}"]
        ):
            process_document(client, doc)

Learn more about track_context()

Request-Level with Custom Headers

In Python applications, track_context() is generally cleaner and more explicit for request-level annotations. Custom headers are primarily useful in:

  • Non-Python environments (JavaScript, Java, etc.) where Pay-i Python SDK isn't available
  • Systems already working extensively with headers (like API gateways or proxies)
  • Existing code where header manipulation is already part of the workflow

Example:

from payi.lib.helpers import create_headers

def process_priority_request(client, query, priority_level):
    # Parameters specific to this individual request
    headers = create_headers(
        request_tags=[f"priority_{priority_level}", "customer_support"],
        limit_ids=["priority_requests", "support_team"]
    )
    
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": query}],
        extra_headers=headers
    )
    return response

Learn more about Custom Headers

Combined Approaches

These approaches can be combined to provide comprehensive annotation at every level of your application. For example:

  1. Set application defaults with payi_instrument()
  2. Use @track for function-level business context
  3. Apply track_context() for specific code blocks with additional parameters
  4. Use custom headers for request-specific values

This creates a layered approach to annotations, allowing you to control metadata at every level of your application.

Learn more about combining annotation approaches

Parameter Precedence

When using multiple annotation methods together, Pay-i follows a "latest wins" strategy:

  1. Whichever context is created later in the execution flow takes precedence
  2. Custom headers have final say at the individual request level
  3. Some parameters (like limit_ids and request_tags) combine values rather than strictly overriding

For detailed information on parameter precedence, see Combined Annotations and Parameter Precedence in Pay-i Instrumentation.

Parameter Documentation

Each parameter has dedicated documentation with comprehensive implementation details:

  • Business Context: See Use Cases for using the use_case_name parameter
  • Budget Management: See Limits for using the limit_ids parameter
  • User Attribution: See User-level Attribution for using the user_id parameter
  • Request Metadata: See Request Tags for using the request_tags parameter

Related Resources