Commits
Click on a commit to change the comparison rangefeat(perplexity): add comprehensive cost tracking for API calls
Add production-grade cost tracking with the following features:
## Core Cost Tracking
- `calculate_cost()` - Simple cost calculation from usage metadata
- `calculate_cost_breakdown()` - Detailed itemized cost breakdown
- `estimate_cost()` - Pre-call cost estimation before API requests
- `format_cost()` - Format costs as currency strings
## Cost Tracker Callback
- `PerplexityCostTracker` - LangChain callback handler that:
- Aggregates costs across multiple API calls
- Tracks per-model usage and costs
- Supports budget limits with configurable warnings
- Thread-safe for concurrent usage
- Provides detailed `CostSummary` with statistics
## Data Classes
- `CostBreakdown` - Itemized costs (input, output, citation, reasoning, search)
- `UsageRecord` - Individual API call record with full metadata
- `CostSummary` - Aggregated statistics with per-model breakdown
- `BudgetExceededError` - Raised when budget limits are exceeded
## Integration
- Cost breakdown automatically added to `response_metadata`
- Works with all Perplexity models including deep-research
- Comprehensive pricing data for all current models
## Testing
- 90+ unit tests covering all functionality
- Concurrency/thread-safety tests
- Edge case and error handling tests
- Integration scenario tests
- Pricing data integrity tests
## Example Usage
```python
from langchain_perplexity import (
ChatPerplexity,
PerplexityCostTracker,
estimate_cost,
)
# Pre-call estimation
cost = estimate_cost("sonar-pro", "What is quantum computing?")
print(f"Estimated: ${cost:.4f}")
# Track costs with budget
tracker = PerplexityCostTracker(budget=1.00, warn_at=0.80)
model = ChatPerplexity(model="sonar", callbacks=[tracker])
response = model.invoke("Hello!")
print(f"Cost: ${response.response_metadata['cost']:.4f}")
print(tracker.summary)
```
Closes #31647
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>7 days ago
by joshuarg007 fix: resolve lint and mypy type errors
- Fix ruff E501 line length violations
- Fix ruff I001 import sorting issues
- Fix mypy type errors for pricing field comparisons
- Add type narrowing for optional dict values
- Add int() casts for token values from get() calls
- Fix remaining_budget type assertion in tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>2 hours ago
by joshuarg007 fix: handle None values in usage metadata and update imports test
- Use `or 0` pattern to handle None token values gracefully
- Update test_imports.py to include all new cost tracking exports
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>53 minutes ago
by joshuarg007