feat: comprehensive token usage tracking for V2
Add provider-specific usage details, fix streaming usage, and return usage from all high-level APIs (Chat.Send, Generate[T], Agent.Run). Breaking changes: - Chat.Send/SendMessage/SendWithImages now return (string, *Usage, error) - Generate[T]/GenerateWith[T] now return (T, *Usage, error) - Agent.Run/RunMessages now return (string, *Usage, error) New features: - Usage.Details map for provider-specific token breakdowns (reasoning, cached, audio, thoughts tokens) - OpenAI streaming now captures usage via StreamOptions.IncludeUsage - Google streaming now captures UsageMetadata from final chunk - UsageTracker.Details() for accumulated detail totals - ModelPricing and PricingRegistry for cost computation Closes #2 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,14 +13,16 @@ const structuredOutputToolName = "structured_output"
|
||||
// Generate sends a single user prompt to the model and parses the response into T.
|
||||
// T must be a struct. The model is forced to return structured output matching T's schema
|
||||
// by using a hidden tool call internally.
|
||||
func Generate[T any](ctx context.Context, model *Model, prompt string, opts ...RequestOption) (T, error) {
|
||||
// Returns the parsed value, token usage, and any error.
|
||||
func Generate[T any](ctx context.Context, model *Model, prompt string, opts ...RequestOption) (T, *Usage, error) {
|
||||
return GenerateWith[T](ctx, model, []Message{UserMessage(prompt)}, opts...)
|
||||
}
|
||||
|
||||
// GenerateWith sends the given messages to the model and parses the response into T.
|
||||
// T must be a struct. The model is forced to return structured output matching T's schema
|
||||
// by using a hidden tool call internally.
|
||||
func GenerateWith[T any](ctx context.Context, model *Model, messages []Message, opts ...RequestOption) (T, error) {
|
||||
// Returns the parsed value, token usage, and any error.
|
||||
func GenerateWith[T any](ctx context.Context, model *Model, messages []Message, opts ...RequestOption) (T, *Usage, error) {
|
||||
var zero T
|
||||
|
||||
s := schema.FromStruct(zero)
|
||||
@@ -36,7 +38,7 @@ func GenerateWith[T any](ctx context.Context, model *Model, messages []Message,
|
||||
|
||||
resp, err := model.Complete(ctx, messages, opts...)
|
||||
if err != nil {
|
||||
return zero, err
|
||||
return zero, nil, err
|
||||
}
|
||||
|
||||
// Find the structured_output tool call in the response.
|
||||
@@ -44,11 +46,11 @@ func GenerateWith[T any](ctx context.Context, model *Model, messages []Message,
|
||||
if tc.Name == structuredOutputToolName {
|
||||
var result T
|
||||
if err := json.Unmarshal([]byte(tc.Arguments), &result); err != nil {
|
||||
return zero, fmt.Errorf("failed to parse structured output: %w", err)
|
||||
return zero, resp.Usage, fmt.Errorf("failed to parse structured output: %w", err)
|
||||
}
|
||||
return result, nil
|
||||
return result, resp.Usage, nil
|
||||
}
|
||||
}
|
||||
|
||||
return zero, ErrNoStructuredOutput
|
||||
return zero, resp.Usage, ErrNoStructuredOutput
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user