Volver a Documentación
Ejemplos avanzados — Python
Casos de uso reales y patrones avanzados para integrar Rayuela en aplicaciones Python de producción.
Cliente Python Completo
Clase completa con manejo de errores, retry logic y logging
from rayuela import RayuelaClient, RayuelaConfig, RecommendationOptions
from rayuela import InteractionEvent
import logging
from typing import List, Dict, Optional
class RecommendationService:
"""Servicio de recomendaciones usando el SDK oficial de Rayuela"""
def __init__(self, api_key: str):
self.client = RayuelaClient(RayuelaConfig(
api_key=api_key,
timeout=30
))
self.logger = logging.getLogger(__name__)
def get_recommendations(
self,
user_id: str,
limit: int = 10,
strategy: str = "hybrid",
context: Optional[Dict] = None
) -> List[Dict]:
"""Obtener recomendaciones personalizadas"""
try:
response = self.client.recommend(user_id, RecommendationOptions(
limit=limit,
strategy=strategy,
explain=False,
context=context
))
return [
{
"externalId": item.external_id,
"name": item.name,
"score": item.score,
"source": item.source
}
for item in response.items
]
except Exception as e:
self.logger.error(f"Error getting recommendations: {e}")
return []
def track_interaction(
self,
user_id: str,
product_id: str,
interaction_type: str,
value: float = 1.0
):
"""Registrar interacción del usuario"""
try:
self.client.track(InteractionEvent(
user_id=user_id,
product_id=product_id,
type=interaction_type,
value=value
))
except Exception as e:
self.logger.error(f"Error tracking interaction: {e}")Integración E-commerce
Ejemplo completo para tienda online con Django/Flask
from rayuela import RayuelaClient, RayuelaConfig, RecommendationOptions
from rayuela import InteractionEvent
class RecommendationService:
def __init__(self, api_key: str):
self.client = RayuelaClient(RayuelaConfig(api_key=api_key))
def get_homepage_recommendations(self, user_id: str) -> list:
"""Recomendaciones para la página principal"""
try:
response = self.client.recommend(user_id, RecommendationOptions(
limit=8,
strategy="hybrid",
filters={
"logic": "and",
"filters": [
{"field": "inStock", "op": "eq", "value": True},
{"field": "price", "op": "gt", "value": 10}
]
}
))
return response.items
except Exception as e:
return self._get_fallback_recommendations()
def get_product_page_recommendations(
self, user_id: str, current_product_id: str
) -> list:
"""Recomendaciones para página de producto"""
response = self.client.recommend(user_id, RecommendationOptions(
limit=4,
strategy="content_based",
context={
"page_type": "product_detail",
"source_external_product_id": current_product_id
}
))
return response.items
def track_interaction(
self, user_id: str, product_id: str,
interaction_type: str, value: float = 1.0
):
try:
self.client.track(InteractionEvent(
user_id=user_id,
product_id=product_id,
type=interaction_type,
value=value
))
except Exception as e:
self.logger.error(f"Error tracking: {e}")Sincronización de Datos
Script para sincronizar datos desde base de datos existente
import pandas as pd
from datetime import datetime, timedelta
import asyncio
import aiohttp
class DataSyncService:
def __init__(self, rayuela_client: RayuelaClient):
self.rayuela = rayuela_client
self.batch_size = 1000
def sync_products_from_db(self):
"""Sincronizar productos desde base de datos"""
# Obtener productos de la BD
products_df = pd.read_sql('''
SELECT
id as externalId,
name,
description,
price,
category,
brand,
inStock,
created_at
FROM products
WHERE is_active = true
''', connection=db_connection)
# Procesar en lotes
for i in range(0, len(products_df), self.batch_size):
batch = products_df.iloc[i:i+self.batch_size]
products_data = batch.to_dict('records')
try:
self.rayuela._make_request(
"POST",
"/ingestion/batch",
json={"products": products_data}
)
print(f"Synced {len(products_data)} products")
except Exception as e:
print(f"Error syncing batch {i}: {e}")
def sync_recent_interactions(self, days_back: int = 7):
"""Sincronizar interacciones recientes"""
cutoff_date = datetime.now() - timedelta(days=days_back)
interactions_df = pd.read_sql('''
SELECT
user_id as external_user_id,
product_id as external_product_id,
action_type as interaction_type,
CASE
WHEN action_type = 'view' THEN 1.0
WHEN action_type = 'cart_add' THEN 2.0
WHEN action_type = 'purchase' THEN 5.0
ELSE 1.0
END as value,
created_at as timestamp
FROM user_interactions
WHERE created_at >= %s
''', connection=db_connection, params=[cutoff_date])
# Procesar en lotes
for i in range(0, len(interactions_df), self.batch_size):
batch = interactions_df.iloc[i:i+self.batch_size]
interactions_data = batch.to_dict('records')
try:
self.rayuela._make_request(
"POST",
"/ingestion/batch",
json={"interactions": interactions_data}
)
print(f"Synced {len(interactions_data)} interactions")
except Exception as e:
print(f"Error syncing interactions batch {i}: {e}")
# Uso del servicio
sync_service = DataSyncService(rayuela_client)
sync_service.sync_products_from_db()
sync_service.sync_recent_interactions(days_back=30)Tracking en Tiempo Real
Sistema de tracking asíncrono para alta concurrencia
import asyncio
import aiohttp
from queue import Queue
import threading
import time
class AsyncTrackingService:
def __init__(self, api_key: str, max_workers: int = 5):
self.api_key = api_key
self.base_url = "https://rayuela-backend-yrbkgws2wq-uc.a.run.app/api/v1"
self.queue = Queue()
self.max_workers = max_workers
self.running = False
async def _send_interaction(self, session: aiohttp.ClientSession, data: Dict):
"""Enviar interacción individual"""
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
try:
async with session.post(
f"{self.base_url}/interactions",
json=data,
headers=headers,
timeout=aiohttp.ClientTimeout(total=10)
) as response:
if response.status == 200:
return await response.json()
else:
print(f"Error {response.status}: {await response.text()}")
except Exception as e:
print(f"Failed to send interaction: {e}")
async def _worker(self):
"""Worker para procesar cola de interacciones"""
async with aiohttp.ClientSession() as session:
while self.running:
try:
# Procesar hasta 10 interacciones por lote
batch = []
for _ in range(10):
if not self.queue.empty():
batch.append(self.queue.get_nowait())
if batch:
# Enviar en paralelo
tasks = [
self._send_interaction(session, interaction)
for interaction in batch
]
await asyncio.gather(*tasks, return_exceptions=True)
else:
await asyncio.sleep(0.1)
except Exception as e:
print(f"Worker error: {e}")
def start(self):
"""Iniciar servicio de tracking"""
self.running = True
# Crear workers asíncronos
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
workers = [self._worker() for _ in range(self.max_workers)]
loop.run_until_complete(asyncio.gather(*workers))
def track(self, user_id: str, product_id: str, interaction_type: str, value: float = 1.0):
"""Agregar interacción a la cola"""
interaction = {
"external_user_id": user_id,
"external_product_id": product_id,
"interaction_type": interaction_type,
"value": value,
"timestamp": datetime.utcnow().isoformat()
}
self.queue.put(interaction)
def stop(self):
"""Detener servicio"""
self.running = False
# Uso en aplicación web
tracking_service = AsyncTrackingService(api_key="sk_prod_...")
# En una vista de Django/Flask
def product_view(request, product_id):
# Tracking asíncrono
tracking_service.track(
user_id=request.user.id,
product_id=product_id,
interaction_type="view"
)
# Continuar con la lógica normal
return render(request, 'product.html', context)Optimización de Rendimiento
Mejores prácticas
- • Usa connection pooling con requests.Session()
- • Implementa retry logic con backoff exponencial
- • Cachea recomendaciones por 5-15 minutos
- • Usa tracking asíncrono para interacciones
- • Implementa fallbacks para alta disponibilidad
⚠️ Consideraciones
- • No bloquees el hilo principal con llamadas síncronas
- • Monitorea rate limits y ajusta frecuencia
- • Usa timeouts apropiados (10-30 segundos)
- • Logea errores pero no expongas detalles al usuario
Siguientes Pasos