Client
Basic Configuration
from cerevox import Lexa
# Minimal configuration
client = Lexa(api_key="your-api-key")
# Full configuration
client = Lexa(
api_key="your-api-key",
base_url="https://data.cerevox.ai",
timeout=120.0,
max_retries=5,
retry_delay=2.0,
poll_interval=3.0,
max_concurrent=10
)
from cerevox import AsyncLexa
# Async client with custom configuration
async with AsyncLexa(
api_key="your-api-key",
timeout=300.0,
max_retries=3,
retry_delay=1.0,
max_concurrent=20
) as client:
documents = await client.parse(["document.pdf"])
Configuration Parameters
Your Cerevox API key. Get one at cerevox.ai/lexa
Base URL for the Cerevox API. Change for custom endpoints or testing
Default timeout for API requests in seconds. Individual operations can override this
Maximum number of automatic retry attempts for failed requests
Base delay between retry attempts. Uses exponential backoff
Default interval between job status checks during parsing
Maximum number of concurrent requests (async client only)
Environment Variables
Standard Environment Variables
# Required
export CEREVOX_API_KEY="your-api-key"
# Optional Configuration
export CEREVOX_BASE_URL="https://data.cerevox.ai"
export CEREVOX_TIMEOUT="120"
export CEREVOX_MAX_RETRIES="5"
export CEREVOX_RETRY_DELAY="2.0"
export CEREVOX_POLL_INTERVAL="3.0"
export CEREVOX_MAX_CONCURRENT="20"
# Logging Configuration
export CEREVOX_LOG_LEVEL="INFO"
export CEREVOX_LOG_FORMAT="json"
import os
from cerevox import Lexa
# Client automatically uses environment variables
client = Lexa()
# Override specific settings
client = Lexa(
timeout=float(os.getenv("CUSTOM_TIMEOUT", 60)),
max_retries=int(os.getenv("CUSTOM_MAX_RETRIES", 3))
)
Development vs Production
# Development settings - more verbose, shorter timeouts
export CEREVOX_API_KEY="dev-api-key"
export CEREVOX_BASE_URL="https://dev.cerevox.ai"
export CEREVOX_TIMEOUT="30"
export CEREVOX_MAX_RETRIES="2"
export CEREVOX_LOG_LEVEL="DEBUG"
# Production settings - optimized for reliability
export CEREVOX_API_KEY="prod-api-key"
export CEREVOX_BASE_URL="https://data.cerevox.ai"
export CEREVOX_TIMEOUT="300"
export CEREVOX_MAX_RETRIES="5"
export CEREVOX_RETRY_DELAY="2.0"
export CEREVOX_LOG_LEVEL="WARNING"
export CEREVOX_MAX_CONCURRENT="50"
Performance Tuning
Timeout Configuration
import os
from cerevox import Lexa
def get_optimal_timeout(files):
"""Calculate optimal timeout based on file characteristics"""
if isinstance(files, str):
files = [files]
total_size = 0
for file in files:
if isinstance(file, str) and os.path.exists(file):
total_size += os.path.getsize(file)
# Base timeout + 1 second per MB
base_timeout = 60
size_timeout = total_size / (1024 * 1024) # MB
return base_timeout + size_timeout
# Usage
client = Lexa(api_key="your-api-key")
files = ["large-document.pdf", "report.docx"]
optimal_timeout = get_optimal_timeout(files)
documents = client.parse(
files,
timeout=optimal_timeout,
poll_interval=min(5.0, optimal_timeout / 20)
)
from cerevox import Lexa, ProcessingMode
# Different timeouts for different modes
timeout_config = {
ProcessingMode.DEFAULT: 120.0, # Accurate and fast
ProcessingMode.ADVANCED: 600.0 # Even more accurate but slower
}
def parse_with_mode_timeout(client, files, mode):
return client.parse(
files,
mode=mode,
timeout=timeout_config.get(mode, 120.0)
)
Concurrency Configuration
import asyncio
from cerevox import AsyncLexa
async def process_large_batch(files, batch_size=10, max_concurrent=5):
"""Process large batches with controlled concurrency"""
# Configure client with concurrency limits
async with AsyncLexa(
api_key="your-api-key",
max_concurrent=max_concurrent,
timeout=300.0
) as client:
# Create semaphore to limit concurrent batches
semaphore = asyncio.Semaphore(max_concurrent)
async def process_batch(batch):
async with semaphore:
return await client.parse(batch)
# Create batches
batches = [files[i:i + batch_size] for i in range(0, len(files), batch_size)]
# Process batches concurrently
tasks = [process_batch(batch) for batch in batches]
results = await asyncio.gather(*tasks, return_exceptions=True)
# Handle results
all_documents = []
for result in results:
if isinstance(result, Exception):
print(f"Batch failed: {result}")
else:
all_documents.extend(result)
return all_documents
from cerevox import Lexa
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
def process_batch_sync(files, max_workers=3):
"""Process files in parallel using threads"""
client = Lexa(
api_key="your-api-key",
timeout=180.0,
max_retries=3
)
def parse_single_file(file):
try:
return client.parse([file])
except Exception as e:
print(f"Failed to parse {file}: {e}")
return None
all_documents = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
# Submit all files
future_to_file = {
executor.submit(parse_single_file, file): file
for file in files
}
# Collect results
for future in as_completed(future_to_file):
file = future_to_file[future]
try:
documents = future.result()
if documents:
all_documents.extend(documents)
except Exception as e:
print(f"Error processing {file}: {e}")
return all_documents
Security
API Key Management
import os
from pathlib import Path
from cerevox import Lexa
class SecureLexaClient:
def __init__(self):
self.api_key = self._get_secure_api_key()
self.client = Lexa(api_key=self.api_key)
def _get_secure_api_key(self):
"""Get API key from secure sources"""
# 1. Environment variable (recommended)
api_key = os.getenv("CEREVOX_API_KEY")
if api_key:
return api_key
# 2. Secure file (if environment variable not available)
key_file = Path.home() / ".cerevox" / "api_key"
if key_file.exists():
return key_file.read_text().strip()
# 3. AWS Secrets Manager, Azure Key Vault, etc.
# api_key = self._get_from_secrets_manager()
raise ValueError("No API key found. Set CEREVOX_API_KEY environment variable.")
def parse(self, *args, **kwargs):
return self.client.parse(*args, **kwargs)
# Usage
client = SecureLexaClient()
documents = client.parse(["document.pdf"])
import boto3
from cerevox import Lexa
def get_api_key_from_aws_secrets():
"""Get API key from AWS Secrets Manager"""
secrets_client = boto3.client('secretsmanager')
try:
response = secrets_client.get_secret_value(
SecretId='cerevox/api-key'
)
return response['SecretString']
except Exception as e:
raise ValueError(f"Failed to get API key from AWS Secrets: {e}")
# Azure Key Vault example
def get_api_key_from_azure():
"""Get API key from Azure Key Vault"""
from azure.keyvault.secrets import SecretClient
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
client = SecretClient(
vault_url="https://your-vault.vault.azure.net/",
credential=credential
)
secret = client.get_secret("cerevox-api-key")
return secret.value
# Usage
api_key = get_api_key_from_aws_secrets()
client = Lexa(api_key=api_key)
Network Security
import ssl
from cerevox import Lexa
# Custom SSL context for enterprise environments
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = True
ssl_context.verify_mode = ssl.CERT_REQUIRED
# For self-signed certificates (development only)
# ssl_context.check_hostname = False
# ssl_context.verify_mode = ssl.CERT_NONE
client = Lexa(
api_key="your-api-key",
ssl_context=ssl_context
)
import os
from cerevox import Lexa
# Configure proxy settings
proxies = {
'http': os.getenv('HTTP_PROXY'),
'https': os.getenv('HTTPS_PROXY')
}
client = Lexa(
api_key="your-api-key",
proxies=proxies,
timeout=180.0 # Longer timeout for proxy connections
)
Logging
Basic Logging Setup
import logging
from cerevox import Lexa
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Enable Cerevox SDK logging
cerevox_logger = logging.getLogger('cerevox')
cerevox_logger.setLevel(logging.DEBUG)
client = Lexa(api_key="your-api-key")
documents = client.parse(["document.pdf"])
import logging
import json
from datetime import datetime
from cerevox import Lexa
class JSONFormatter(logging.Formatter):
def format(self, record):
log_entry = {
'timestamp': datetime.utcnow().isoformat(),
'level': record.levelname,
'logger': record.name,
'message': record.getMessage(),
'module': record.module,
'function': record.funcName,
'line': record.lineno
}
# Add extra fields
if hasattr(record, 'request_id'):
log_entry['request_id'] = record.request_id
if hasattr(record, 'error_code'):
log_entry['error_code'] = record.error_code
return json.dumps(log_entry)
# Setup structured logging
handler = logging.StreamHandler()
handler.setFormatter(JSONFormatter())
logger = logging.getLogger('cerevox')
logger.addHandler(handler)
logger.setLevel(logging.INFO)
Production Logging
import logging
import logging.handlers
from pathlib import Path
from cerevox import Lexa
def setup_production_logging():
"""Setup production-grade logging"""
# Create logs directory
log_dir = Path("logs")
log_dir.mkdir(exist_ok=True)
# Configure root logger
logging.basicConfig(
level=logging.WARNING,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Cerevox-specific logger with file rotation
cerevox_logger = logging.getLogger('cerevox')
cerevox_logger.setLevel(logging.INFO)
# Rotating file handler
file_handler = logging.handlers.RotatingFileHandler(
log_dir / "cerevox.log",
maxBytes=10*1024*1024, # 10MB
backupCount=5
)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
))
cerevox_logger.addHandler(file_handler)
# Error-specific handler
error_handler = logging.handlers.RotatingFileHandler(
log_dir / "cerevox_errors.log",
maxBytes=5*1024*1024, # 5MB
backupCount=10
)
error_handler.setLevel(logging.ERROR)
error_handler.setFormatter(logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s\n%(exc_info)s'
))
cerevox_logger.addHandler(error_handler)
return cerevox_logger
# Setup logging
logger = setup_production_logging()
client = Lexa(api_key="your-api-key")
Framework Integration
Django
# settings.py
import os
# Cerevox configuration
CEREVOX_API_KEY = os.getenv('CEREVOX_API_KEY')
CEREVOX_TIMEOUT = 300.0
CEREVOX_MAX_RETRIES = 5
# Django logging configuration
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
},
'handlers': {
'cerevox_file': {
'level': 'INFO',
'class': 'logging.FileHandler',
'filename': 'logs/cerevox.log',
'formatter': 'verbose',
},
},
'loggers': {
'cerevox': {
'handlers': ['cerevox_file'],
'level': 'INFO',
'propagate': True,
},
},
}
# services.py
from django.conf import settings
from cerevox import Lexa, LexaError
import logging
logger = logging.getLogger(__name__)
class DocumentParsingService:
def __init__(self):
self.client = Lexa(
api_key=settings.CEREVOX_API_KEY,
timeout=settings.CEREVOX_TIMEOUT,
max_retries=settings.CEREVOX_MAX_RETRIES
)
def parse_documents(self, files):
"""Parse documents with Django integration"""
try:
documents = self.client.parse(files)
logger.info(f"Successfully parsed {len(documents)} documents")
return documents
except LexaError as e:
logger.error(f"Document parsing failed: {e.message}")
raise
FastAPI
# config.py
from pydantic import BaseSettings
class Settings(BaseSettings):
cerevox_api_key: str
cerevox_timeout: float = 120.0
cerevox_max_retries: int = 3
cerevox_base_url: str = "https://data.cerevox.ai"
class Config:
env_file = ".env"
settings = Settings()
# dependencies.py
from fastapi import Depends
from cerevox import AsyncLexa
from .config import settings
async def get_lexa_client():
"""FastAPI dependency for Lexa client"""
async with AsyncLexa(
api_key=settings.cerevox_api_key,
timeout=settings.cerevox_timeout,
max_retries=settings.cerevox_max_retries
) as client:
yield client
# Usage in routes
from fastapi import FastAPI, Depends, UploadFile
from .dependencies import get_lexa_client
app = FastAPI()
@app.post("/parse")
async def parse_documents(
files: list[UploadFile],
client: AsyncLexa = Depends(get_lexa_client)
):
# Parse uploaded files
file_contents = [await f.read() for f in files]
documents = await client.parse(file_contents)
return {"documents": len(documents)}
Validation
from cerevox import Lexa, LexaError
import os
from typing import Optional
class ValidatedLexaConfig:
def __init__(
self,
api_key: Optional[str] = None,
base_url: Optional[str] = None,
timeout: float = 60.0,
max_retries: int = 3
):
self.api_key = self._validate_api_key(api_key)
self.base_url = self._validate_base_url(base_url)
self.timeout = self._validate_timeout(timeout)
self.max_retries = self._validate_max_retries(max_retries)
def _validate_api_key(self, api_key: Optional[str]) -> str:
if not api_key:
api_key = os.getenv('CEREVOX_API_KEY')
if not api_key:
raise ValueError("API key is required")
if not api_key.startswith('cx_'):
raise ValueError("Invalid API key format")
return api_key
def _validate_base_url(self, base_url: Optional[str]) -> str:
if not base_url:
base_url = os.getenv('CEREVOX_BASE_URL', 'https://data.cerevox.ai')
if not base_url.startswith(('http://', 'https://')):
raise ValueError("Base URL must start with http:// or https://")
return base_url
def _validate_timeout(self, timeout: float) -> float:
if timeout <= 0:
raise ValueError("Timeout must be positive")
if timeout > 3600: # 1 hour max
raise ValueError("Timeout too large (max 3600 seconds)")
return timeout
def _validate_max_retries(self, max_retries: int) -> int:
if max_retries < 0:
raise ValueError("Max retries cannot be negative")
if max_retries > 10:
raise ValueError("Max retries too large (max 10)")
return max_retries
def create_client(self) -> Lexa:
"""Create validated Lexa client"""
return Lexa(
api_key=self.api_key,
base_url=self.base_url,
timeout=self.timeout,
max_retries=self.max_retries
)
# Usage
try:
config = ValidatedLexaConfig(
timeout=120.0,
max_retries=5
)
client = config.create_client()
print("Client configured successfully")
except ValueError as e:
print(f"Configuration error: {e}")
Next Steps
Explore real-world examples to see these configurations in action.

