Pular para conteúdo

API: LLM Usage

Visão Geral

Endpoints para monitoramento de uso de LLM (tokens e custos). Permite visualizar consumo agregado por modelo, tipo de operação, tenant e período.

A seção "By Operation" agrupa por OperationType + Model, permitindo visualizar qual modelo foi utilizado em cada tipo de operação.

O tracking é feito automaticamente pelo sistema em todas as chamadas aos LLMs (Claude e OpenAI) e armazena: - Provider e modelo utilizado - Tipo de operação (Chat, Vision, Transcription, etc.) - Tokens de entrada e saída - Custo estimado (baseado na tabela de preços configurada) - Metadados estruturados em JSONB (agentId, traceId, conversationId, whatsAppMessageIds e campos específicos por operação)

Autorização e Rate Limiting

Todos os endpoints de LLM Usage requerem autorização SuperAdmin (RequireAuthorization(AuthConstants.Roles.SuperAdmin)) e estão sob a política de rate limiting SuperAdmin (RateLimitPolicies.SuperAdmin): 20 requisições por 60 segundos.

Endpoints

GET /api/admin/llm-usage/summary

Retorna um sumário agregado do uso de LLM no período especificado.

Query Parameters:

Parâmetro Tipo Obrigatório Descrição
startDate DateTime Sim Data inicial do período (UTC)
endDate DateTime Sim Data final do período (UTC)
provider string Não Filtrar por provider (Anthropic, OpenAI)
operationType string Não Filtrar por tipo de operação
tenantId Guid Não Filtrar por tenant

Response (200 OK):

{
  "totalRequests": 542,
  "totalInputTokens": 1250000,
  "totalOutputTokens": 380000,
  "totalCost": 12.45,
  "cacheHitRequests": 310,
  "totalCacheReadTokens": 450000,
  "totalCacheWriteTokens": 120000
}


GET /api/admin/llm-usage/by-model

Retorna o uso de LLM agrupado por provider e modelo.

Query Parameters:

Parâmetro Tipo Obrigatório Descrição
startDate DateTime Sim Data inicial do período (UTC)
endDate DateTime Sim Data final do período (UTC)
provider string Não Filtrar por provider (Anthropic, OpenAI)
operationType string Não Filtrar por tipo de operação
tenantId Guid Não Filtrar por tenant

Response (200 OK):

[
  {
    "provider": "Anthropic",
    "model": "claude-3-5-sonnet-20241022",
    "totalRequests": 450,
    "totalInputTokens": 1000000,
    "totalOutputTokens": 300000,
    "totalCost": 9.50
  },
  {
    "provider": "OpenAI",
    "model": "gpt-4o-mini",
    "totalRequests": 92,
    "totalInputTokens": 250000,
    "totalOutputTokens": 80000,
    "totalCost": 2.95
  }
]


GET /api/admin/llm-usage/by-operation

Retorna o uso de LLM agrupado por tipo de operação e modelo.

Query Parameters:

Parâmetro Tipo Obrigatório Descrição
startDate DateTime Sim Data inicial do período (UTC)
endDate DateTime Sim Data final do período (UTC)
provider string Não Filtrar por provider (Anthropic, OpenAI)
operationType string Não Filtrar por tipo de operação
tenantId Guid Não Filtrar por tenant

Response (200 OK):

[
  {
    "operationType": "Chat",
    "model": "claude-3-5-sonnet-20241022",
    "totalRequests": 480,
    "totalTokens": 1500000,
    "totalCost": 11.00
  },
  {
    "operationType": "Vision",
    "model": "claude-3-5-sonnet-20241022",
    "totalRequests": 62,
    "totalTokens": 130000,
    "totalCost": 1.45
  }
]


GET /api/admin/llm-usage/by-tenant

Retorna o uso de LLM agrupado por tenant, com paginação.

Query Parameters:

Parâmetro Tipo Obrigatório Descrição
startDate DateTime Sim Data inicial do período (UTC)
endDate DateTime Sim Data final do período (UTC)
provider string Não Filtrar por provider (Anthropic, OpenAI)
operationType string Não Filtrar por tipo de operação
tenantId Guid Não Filtrar por tenant
page int Sim Página (default: 1)
pageSize int Sim Itens por página (default: 10)

Response (200 OK):

{
  "items": [
    {
      "tenantId": "110e8400-e29b-41d4-a716-446655440099",
      "tenantName": "Pizzaria Exemplo",
      "totalRequests": 450,
      "totalInputTokens": 1000000,
      "totalOutputTokens": 300000,
      "totalCost": 9.50
    }
  ],
  "totalCount": 15
}


GET /api/admin/llm-usage/margin

Retorna dados de margem por tenant (custo LLM vs créditos consumidos/adicionados e preço da assinatura).

Autorização: SuperAdmin

Query Parameters:

Parâmetro Tipo Obrigatório Descrição
startDate DateTime Sim Data inicial do período (UTC)
endDate DateTime Sim Data final do período (UTC)
provider string Não Filtrar por provider (Anthropic, OpenAI)
operationType string Não Filtrar por tipo de operação
tenantId Guid Não Filtrar por tenant
page int Sim Página (default: 1)
pageSize int Sim Itens por página (default: 10)

Response (200 OK):

{
  "items": [
    {
      "tenantId": "110e8400-e29b-41d4-a716-446655440099",
      "tenantName": "Pizzaria Exemplo",
      "totalCostUsd": 8.50,
      "creditsConsumed": 150,
      "creditsAdded": 500,
      "monthlyPriceBrl": 199.90,
      "costPerCreditUsd": 0.057
    }
  ],
  "totalCount": 15
}


Tipos de Operação (LlmOperationType)

Valor Descrição
Chat Resposta em conversa (pipelines aggregation, deferred, outgoing)
Vision Descrição de imagem via Claude Vision
Transcription Transcrição de áudio via OpenAI Whisper
Embedding Geração de embeddings para busca semântica (knowledge, faq, search)
Chunking Processamento de knowledge blocks
Playground Testes no playground do agente
AiAssistant Assistente IA para configuração de agentes
QueryRewrite Reescrita de queries para busca semântica
IntentClassification Classificação de intenção da mensagem

Providers (LlmProvider)

Valor Descrição
Anthropic Claude API
OpenAI OpenAI API

Configuração de Preços

Os preços são configurados em appsettings.json na seção LlmPricing:

{
  "LlmPricing": {
    "Models": [
      { "Model": "claude-opus-4-5-20251101", "InputPricePerMillion": 5.00, "OutputPricePerMillion": 25.00 },
      { "Model": "claude-sonnet-4-5-20251001", "InputPricePerMillion": 3.00, "OutputPricePerMillion": 15.00 },
      { "Model": "claude-haiku-4-5-20251001", "InputPricePerMillion": 1.00, "OutputPricePerMillion": 5.00 },
      { "Model": "claude-3-5-sonnet-20241022", "InputPricePerMillion": 3.00, "OutputPricePerMillion": 15.00 },
      { "Model": "gpt-4-turbo", "InputPricePerMillion": 10.00, "OutputPricePerMillion": 30.00 },
      { "Model": "gpt-4o", "InputPricePerMillion": 2.50, "OutputPricePerMillion": 10.00 },
      { "Model": "gpt-4o-mini", "InputPricePerMillion": 0.15, "OutputPricePerMillion": 0.60 },
      { "Model": "gpt-3.5-turbo", "InputPricePerMillion": 0.50, "OutputPricePerMillion": 1.50 }
    ]
  }
}

Cálculo de Custo

O custo é calculado automaticamente pelo LlmPricingService:

EstimatedCost = (InputTokens / 1_000_000) * InputPricePerMillion
              + (OutputTokens / 1_000_000) * OutputPricePerMillion

Se o modelo não estiver configurado na tabela de preços, EstimatedCost será null.


Tracking Automático

O tracking é feito via LlmUsageTracker (fire-and-forget com Channel) + LlmUsageBackgroundService (consumer que persiste no banco).

Campos comuns são injetados automaticamente pelo Track(): - agentId — parâmetro obrigatório - traceId — capturado de Activity.Current - conversationId — capturado de Activity.Current.GetTagItem("ciba.conversationId") - whatsAppMessageIds — capturado de Activity.Current.GetTagItem("ciba.whatsAppMessageIds")

Campos específicos por operação são passados via metadata records tipados (ChatUsageMetadata, VisionUsageMetadata, etc.).


Multi-tenancy

Os dados de LlmUsage respeitam o filtro de tenant: - Cada registro tem TenantId - Query filter global filtra automaticamente por tenant - SuperAdmins podem ver dados de todos os tenants


Índices

A tabela llm_usages possui índices otimizados para: - (tenant_id, created_at) — Consultas por tenant e período - (tenant_id, operation_type, created_at) — Consultas por tipo de operação - (created_at) — Consultas globais por período