Files
openccb/TOKEN_LIMITS_GUIDE.md
T
2026-03-23 16:11:15 -03:00

359 lines
8.2 KiB
Markdown

# Límites de Tokens Mensuales por Usuario
## Visión General
OpenCCB ahora soporta límites de tokens de IA mensuales configurables por usuario, permitiendo controlar el consumo de IA y prevenir usos excesivos.
---
## Características
### Configuración por Usuario
Cada usuario puede tener:
- **Límite mensual personalizado**: Número máximo de tokens que puede consumir por mes
- **Día de reset**: Día del mes cuando se reinicia el contador (1-28)
- **Ilimitado**: Configurando límite en 0
### Valores por Defecto
- **Límite**: 100,000 tokens/mes
- **Día de reset**: 1 (primero del mes)
- **Unlimited**: `monthly_token_limit = 0`
---
## Esquema de Base de Datos
### Tabla `users` (Nuevas Columnas)
```sql
monthly_token_limit INTEGER DEFAULT 100000
-- Límite mensual de tokens (0 = ilimitado)
token_limit_reset_day INTEGER DEFAULT 1
-- Día del mes para resetear (1-28)
```
### Vista `ai_usage_monthly`
Muestra el uso actual del mes por usuario:
```sql
SELECT * FROM ai_usage_monthly
WHERE user_id = '{user-uuid}';
```
**Columnas:**
- `user_id`: UUID del usuario
- `organization_id`: UUID de la organización
- `usage_month`: Mes de uso
- `total_tokens`: Total de tokens consumidos
- `input_tokens`: Tokens de entrada (prompts)
- `output_tokens`: Tokens de salida (respuestas)
- `total_requests`: Número de peticiones a IA
- `total_cost_usd`: Costo estimado en USD
### Funciones SQL
#### `check_token_limit(user_id, additional_tokens)`
Verifica si un usuario tiene tokens disponibles.
```sql
SELECT * FROM check_token_limit(
'user-uuid'::UUID,
1000 -- Tokens adicionales a verificar
);
```
**Retorna:**
- `has_available_tokens`: BOOLEAN - ¿Tiene tokens disponibles?
- `monthly_limit`: INTEGER - Límite mensual configurado
- `used_tokens`: BIGINT - Tokens ya usados este mes
- `remaining_tokens`: BIGINT - Tokens restantes
- `reset_date`: TIMESTAMPTZ - Fecha del próximo reset
#### `get_user_usage_stats(user_id, months)`
Obtiene estadísticas históricas de uso.
```sql
SELECT * FROM get_user_usage_stats(
'user-uuid'::UUID,
3 -- Últimos 3 meses
);
```
**Retorna:**
- `month_start`: DATE - Inicio del mes
- `total_tokens`: BIGINT - Tokens totales
- `input_tokens`: BIGINT - Tokens de entrada
- `output_tokens`: BIGINT - Tokens de salida
- `total_requests`: BIGINT - Número de peticiones
- `total_cost_usd`: NUMERIC - Costo estimado
- `monthly_limit`: INTEGER - Límite del mes
- `percentage_used`: NUMERIC - Porcentaje usado
---
## API Endpoints
### 1. Establecer Límite Mensual
```http
PUT /api/admin/users/{user_id}/token-limit
Authorization: Bearer {admin_token}
Content-Type: application/json
{
"monthly_token_limit": 50000,
"token_limit_reset_day": 15
}
```
**Parámetros:**
- `monthly_token_limit` (integer): Límite mensual (0 = ilimitado)
- `token_limit_reset_day` (integer, opcional): Día de reset (1-28, default: 1)
**Respuesta:** `200 OK`
---
### 2. Ver Uso de Tokens de Usuario
```http
GET /api/admin/users/{user_id}/token-usage
Authorization: Bearer {admin_token}
```
**Respuesta:**
```json
{
"user_id": "uuid",
"email": "user@example.com",
"full_name": "Nombre Usuario",
"monthly_token_limit": 100000,
"token_limit_reset_day": 1,
"used_tokens": 45678,
"total_requests": 234,
"total_cost_usd": 0.05,
"last_used": "2026-03-23T10:30:00Z"
}
```
---
### 3. Verificar Límite Disponible
```http
GET /api/admin/users/{user_id}/token-limit/check
Authorization: Bearer {admin_token}
```
**Respuesta:**
```json
{
"has_available_tokens": true,
"monthly_limit": 100000,
"used_tokens": 45678,
"remaining_tokens": 54322,
"reset_date": "2026-04-01T00:00:00Z"
}
```
---
## Ejemplos de Uso
### Ejemplo 1: Establecer Límite de 50K Tokens
```bash
curl -X PUT "http://localhost:3001/api/admin/users/{user-id}/token-limit" \
-H "Authorization: Bearer {admin-token}" \
-H "Content-Type: application/json" \
-d '{
"monthly_token_limit": 50000,
"token_limit_reset_day": 1
}'
```
### Ejemplo 2: Verificar Tokens Disponibles
```bash
curl "http://localhost:3001/api/admin/users/{user-id}/token-limit/check" \
-H "Authorization: Bearer {admin-token}"
```
### Ejemplo 3: Obtener Uso del Mes
```bash
curl "http://localhost:3001/api/admin/users/{user-id}/token-usage" \
-H "Authorization: Bearer {admin-token}"
```
### Ejemplo 4: SQL Directo
```sql
-- Ver uso actual de todos los usuarios
SELECT
u.email,
u.full_name,
u.monthly_token_limit,
COALESCE(SUM(au.tokens_used), 0) as used_tokens,
u.monthly_token_limit - COALESCE(SUM(au.tokens_used), 0) as remaining_tokens,
CASE
WHEN u.monthly_token_limit = 0 THEN 'Unlimited'
ELSE ROUND((COALESCE(SUM(au.tokens_used), 0)::NUMERIC / u.monthly_token_limit * 100)::NUMERIC, 2) || '%'
END as usage_percentage
FROM users u
LEFT JOIN ai_usage_logs au ON u.id = au.user_id
AND au.created_at >= DATE_TRUNC('month', NOW())
GROUP BY u.id, u.email, u.full_name, u.monthly_token_limit
ORDER BY used_tokens DESC;
```
---
## Estrategias de Límites
### Por Rol de Usuario
```sql
-- Estudiantes: 50K tokens/mes
UPDATE users SET monthly_token_limit = 50000 WHERE role = 'student';
-- Instructores: 200K tokens/mes
UPDATE users SET monthly_token_limit = 200000 WHERE role = 'instructor';
-- Admins: Ilimitado
UPDATE users SET monthly_token_limit = 0 WHERE role = 'admin';
```
### Por Tipo de Plan
```sql
-- Plan Básico: 25K tokens
UPDATE users SET monthly_token_limit = 25000 WHERE plan = 'basic';
-- Plan Pro: 100K tokens
UPDATE users SET monthly_token_limit = 100000 WHERE plan = 'pro';
-- Plan Enterprise: Ilimitado
UPDATE users SET monthly_token_limit = 0 WHERE plan = 'enterprise';
```
### Reset en Días Diferentes
```sql
-- Reset el día 15 (mitad de mes)
UPDATE users SET token_limit_reset_day = 15 WHERE organization_id = 'org-uuid';
```
---
## Implementación de Enforce
Para hacer cumplir los límites a nivel de API, verifica antes de cada solicitud de IA:
```rust
// Ejemplo en handler de IA
pub async fn chat_with_tutor(...) -> Result<...> {
// 1. Verificar límite de tokens
let limit_check: TokenLimitCheck = sqlx::query_as(
"SELECT * FROM check_token_limit($1, 1000)" // 1000 tokens estimados
)
.bind(claims.sub)
.fetch_one(&pool)
.await?;
if !limit_check.has_available_tokens {
return Err((
StatusCode::TOO_MANY_REQUESTS,
format!(
"Monthly token limit exceeded. Reset date: {}",
limit_check.reset_date
)
));
}
// 2. Proceder con solicitud de IA
// ...
// 3. Loguear uso (ya implementado)
sqlx::query("SELECT log_ai_usage(...)").execute(&pool).await?;
Ok(response)
}
```
---
## Monitoreo y Alertas
### Dashboard de Uso
```sql
-- Usuarios que han usado > 80% de su límite
SELECT
u.email,
u.full_name,
u.monthly_token_limit,
SUM(au.tokens_used) as used_tokens,
ROUND((SUM(au.tokens_used)::NUMERIC / NULLIF(u.monthly_token_limit, 0) * 100)::NUMERIC, 2) as percentage_used
FROM users u
JOIN ai_usage_logs au ON u.id = au.user_id
WHERE au.created_at >= DATE_TRUNC('month', NOW())
AND u.monthly_token_limit > 0
GROUP BY u.id, u.email, u.full_name, u.monthly_token_limit
HAVING SUM(au.tokens_used)::NUMERIC / NULLIF(u.monthly_token_limit, 0) > 0.8
ORDER BY percentage_used DESC;
```
### Notificación de Límite Alcanzado
Configura webhooks o emails cuando un usuario alcance el 80%, 90% y 100% de su límite.
---
## Troubleshooting
### Usuario Reporta que No Puede Usar IA
```sql
-- Verificar límite y uso
SELECT * FROM check_token_limit('user-uuid'::UUID, 0);
-- Ver historial de uso
SELECT * FROM get_user_usage_stats('user-uuid'::UUID, 1);
-- Ver logs de errores
SELECT * FROM ai_usage_logs
WHERE user_id = 'user-uuid'
ORDER BY created_at DESC
LIMIT 10;
```
### Resetear Contador de Usuario
```sql
-- Establecer límite ilimitado temporalmente
UPDATE users SET monthly_token_limit = 0 WHERE id = 'user-uuid';
-- O aumentar límite
UPDATE users SET monthly_token_limit = 200000 WHERE id = 'user-uuid';
```
---
## Referencias
- **Migración:** `services/cms-service/migrations/20260323000000_monthly_token_limits.sql`
- **Handlers:** `services/cms-service/src/handlers_admin.rs`
- **Endpoints:** `services/cms-service/src/main.rs`
---
**Fecha:** 2026-03-23
**Versión:** OpenCCB 0.2.1