docs: Token limits user guide
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -0,0 +1,358 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user