Advanced FastAPI Usage Example
This example demonstrates advanced usage patterns of eval-track with FastAPI, including asynchronous processing, error handling, and Pydantic model integration.
Overview
The Advanced FastAPI Usage example showcases more sophisticated integration patterns with eval-track, demonstrating how to handle complex scenarios in production environments.
Installation
Prerequisites
Install using uv
# Clone the repository
git clone https://github.com/tied-inc/eval-track
# Navigate to the example directory
cd example/advanced-fastapi-usage
# Install dependencies
uv sync --frozen
Install using Task (recommended for development)
# Install Task if not already installed
npm install -g @go-task/cli
# Install uv if not already installed
task setup-uv
# Install dependencies
task install-tracker
Running the Application
uv main:app
Available Endpoints
This application includes the following endpoints:
Basic eval-track Endpoints
GET /eval-track/health
- Health check endpointGET /eval-track/traces
- Retrieve all tracesPUT /eval-track/traces/{trace_id}
- Store trace data
Example Endpoints
GET /hello
- Basic trace functionality demoGET /async-calc/{x}/{y}
- Async processing and calculation demoGET /error-demo
- Error handling demonstration
Implementation
Here's how to implement advanced eval-track features in your FastAPI application:
from fastapi import FastAPI, HTTPException, BackgroundTasks
from tracker.tracer import capture_response
from tracker.client import EvalTrackClient
from pydantic import BaseModel
from typing import List, Optional
class ProcessingRequest(BaseModel):
text: str
options: Optional[List[str]] = None
class ProcessingResponse(BaseModel):
result: str
processed_options: Optional[List[str]] = None
app = FastAPI()
client = EvalTrackClient()
@app.post("/process", response_model=ProcessingResponse)
@capture_response
async def process_text(request: ProcessingRequest, background_tasks: BackgroundTasks) -> ProcessingResponse:
try:
# Simulate async processing
result = await process_text_async(request.text)
# Handle options if provided
processed_options = await process_options(request.options) if request.options else None
response = ProcessingResponse(
result=result,
processed_options=processed_options
)
# Add background task for additional processing
background_tasks.add_task(store_processing_result, response)
return response
except Exception as e:
# Error handling with proper status codes
raise HTTPException(status_code=500, detail=str(e))
Features Demonstrated
1. Asynchronous Processing
- Use of
async/await
for non-blocking operations - Integration with FastAPI's
BackgroundTasks
- Parallel processing of options
2. Error Handling
- Custom exception handling with proper HTTP status codes
- Integration with eval-track's trace capture
- Graceful error reporting
3. Pydantic Model Integration
- Request/Response model validation
- Optional field handling
- Type safety with Python type hints
Trace Data
The @capture_response
decorator automatically captures:
- Request payload including text and options
- Response data with results
- Processing time and errors (if any)
Advanced Usage Patterns
Background Processing
async def store_processing_result(response: ProcessingResponse) -> None:
# Store results asynchronously
await client.put_trace(
trace_id=generate_trace_id(),
data=response.dict()
)
Error Handling Pattern
@capture_response
async def handle_with_fallback(request: ProcessingRequest) -> ProcessingResponse:
try:
result = await primary_processing(request)
except Exception:
# Fallback to secondary processing
result = await secondary_processing(request)
return result
Best Practices
- Always use Pydantic models for request/response handling
- Implement proper error handling with specific status codes
- Utilize background tasks for non-critical operations
- Structure your code for maintainability and testing
For more details about error handling and router configuration, see the Router documentation.