ai-functions
Version:
Core AI primitives for building intelligent applications
272 lines • 7.46 kB
TypeScript
/**
* Budget Tracking and Request Tracing for AI Functions
*
* Provides:
* - Token counting and estimation
* - Cost tracking by model
* - Budget limits with alerts
* - Request ID generation and tracing
* - User/tenant context isolation
*
* @packageDocumentation
*/
/** Token usage for a single request */
export interface TokenUsage {
inputTokens: number;
outputTokens: number;
model?: string;
}
/** Model pricing per million tokens */
export interface ModelPricing {
inputPricePerMillion: number;
outputPricePerMillion: number;
}
/** Budget configuration */
export interface BudgetConfig {
/** Maximum total tokens allowed */
maxTokens?: number;
/** Maximum cost in USD */
maxCost?: number;
/** Alert thresholds as fractions (e.g., [0.5, 0.8, 1.0]) */
alertThresholds?: number[];
/** Callback when threshold is reached */
onAlert?: (alert: BudgetAlert) => void;
/** Custom pricing for models not in default pricing table */
customPricing?: Record<string, ModelPricing>;
/** Maximum number of requests to keep in history */
maxRequestHistory?: number;
}
/** Budget alert payload */
export interface BudgetAlert {
threshold: number;
currentUsage: number;
limit: number;
type: 'tokens' | 'cost';
}
/** Check budget options */
export interface CheckBudgetOptions {
estimatedTokens?: number;
model?: string;
}
/** Remaining budget info */
export interface RemainingBudget {
tokens?: number;
cost?: number;
}
/** Request info for tracking */
export interface RequestInfo {
requestId: string;
model: string;
startTime: number;
endTime: number;
inputTokens: number;
outputTokens: number;
duration?: number;
}
/** Stored request with computed duration */
interface StoredRequest extends RequestInfo {
duration: number;
}
/** Budget snapshot for export/import */
export interface BudgetSnapshot {
totalInputTokens: number;
totalOutputTokens: number;
totalCost: number;
usageByModel: Record<string, {
inputTokens: number;
outputTokens: number;
cost: number;
}>;
triggeredThresholds: number[];
}
/** Request context options */
export interface RequestContextOptions {
requestId?: string;
userId?: string;
tenantId?: string;
parentRequestId?: string;
metadata?: Record<string, unknown>;
}
/** Request context with tracing */
export interface IRequestContext {
requestId: string;
userId?: string;
tenantId?: string;
parentRequestId?: string;
depth: number;
metadata?: Record<string, unknown>;
createChild(options?: Partial<RequestContextOptions>): IRequestContext;
toTraceHeaders(): Record<string, string>;
toTraceparent(): string;
}
/** Message format for token counting */
interface Message {
role: string;
content: string;
}
/**
* Token counter for estimating token usage
*
* Uses a simple character-based estimation that works across models.
* For production, consider integrating tiktoken for more accurate counts.
*/
export declare class TokenCounter {
/** Average characters per token (rough estimate) */
private readonly charsPerToken;
/** Overhead tokens per message for formatting */
private readonly messageOverhead;
/**
* Estimate tokens for a text string
*/
estimateTokens(text: string, _model?: string): number;
/**
* Count tokens in a message array including formatting overhead
*/
countMessageTokens(messages: Message[], model?: string): number;
}
/**
* Error thrown when budget is exceeded
*/
export declare class BudgetExceededError extends Error {
readonly type: 'tokens' | 'cost';
readonly limit: number;
readonly current: number;
readonly requested?: number | undefined;
constructor(message: string, type: 'tokens' | 'cost', limit: number, current: number, requested?: number | undefined);
}
/**
* Tracks token usage and costs with budget limits
*/
export declare class BudgetTracker {
private totalInputTokens;
private totalOutputTokens;
private usageByModel;
private triggeredThresholds;
private requests;
private readonly config;
constructor(config?: BudgetConfig);
/**
* Record token usage from a request
*/
recordUsage(usage: TokenUsage): void;
/**
* Record a complete request with timing info
*/
recordRequest(info: RequestInfo): void;
/**
* Get all recorded requests
*/
getRequests(): StoredRequest[];
/**
* Check if a proposed request would exceed budget
*/
checkBudget(options: CheckBudgetOptions): void;
/**
* Check limits after recording and throw if exceeded
*/
private checkLimitsAfterRecording;
/**
* Check and trigger alerts
*/
private checkAlerts;
/**
* Get total input tokens
*/
getTotalInputTokens(): number;
/**
* Get total output tokens
*/
getTotalOutputTokens(): number;
/**
* Get total tokens (input + output)
*/
getTotalTokens(): number;
/**
* Get total cost in USD
*/
getTotalCost(): number;
/**
* Get cost breakdown by model
*/
getCostByModel(): Record<string, number>;
/**
* Get remaining budget
*/
getRemainingBudget(): RemainingBudget;
/**
* Reset all tracking
*/
reset(): void;
/**
* Export current state for persistence
*/
export(): BudgetSnapshot;
/**
* Import previously exported state
*/
import(snapshot: BudgetSnapshot): void;
/**
* Get pricing for a model
*/
private getPricing;
/**
* Calculate cost for token usage
*/
private calculateCost;
}
/**
* Request context for tracing and user isolation
*/
export declare class RequestContext implements IRequestContext {
readonly requestId: string;
readonly userId?: string;
readonly tenantId?: string;
readonly parentRequestId?: string;
readonly depth: number;
readonly metadata?: Record<string, unknown>;
private readonly traceId;
private readonly spanId;
constructor(options?: RequestContextOptions & {
depth?: number;
});
/**
* Create a child context that inherits from this one
*/
createChild(options?: Partial<RequestContextOptions>): RequestContext;
/**
* Serialize to trace headers
*/
toTraceHeaders(): Record<string, string>;
/**
* Generate W3C traceparent header
* Format: version-trace_id-parent_id-flags
*/
toTraceparent(): string;
/**
* Create a RequestContext from trace headers
*/
static fromHeaders(headers: Record<string, string>): RequestContext;
}
/**
* Create a new request context
*/
export declare function createRequestContext(options?: RequestContextOptions): RequestContext;
/** Options for withBudget */
export interface WithBudgetOptions extends BudgetConfig {
userId?: string;
tenantId?: string;
}
/**
* Execute a function with budget tracking
*
* @example
* ```ts
* const result = await withBudget({ maxTokens: 1000 }, async (tracker) => {
* tracker.recordUsage({ inputTokens: 100, outputTokens: 50 })
* return 'success'
* })
* ```
*/
export declare function withBudget<T>(options: WithBudgetOptions, fn: (tracker: BudgetTracker, ctx?: RequestContext) => Promise<T>): Promise<T>;
export {};
//# sourceMappingURL=budget.d.ts.map