mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
Update README with badges and comprehensive documentation
- Add CI status, test coverage, and version badges - Update with current features and capabilities - Add comprehensive usage examples - Include development and testing instructions - Clean, professional documentation structure
This commit is contained in:
@@ -1,519 +1,377 @@
|
||||
# Hanzo AI SDK - Complete AI Infrastructure Platform
|
||||
# Hanzo Python SDK
|
||||
|
||||
[](https://pypi.org/project/hanzo/)
|
||||
[](https://pypi.org/project/hanzoai/)
|
||||
[](https://pypi.org/project/hanzo-mcp/)
|
||||
[](https://github.com/hanzoai/python-sdk/actions/workflows/ci.yml)
|
||||
[](https://github.com/hanzoai/python-sdk/actions)
|
||||
[](https://pypi.org/project/hanzoai/)
|
||||
[](https://pypi.org/project/hanzoai/)
|
||||
[](https://github.com/hanzoai/python-sdk/blob/main/LICENSE)
|
||||
[](https://pypi.org/project/hanzoai/)
|
||||
[](https://github.com/astral-sh/ruff)
|
||||
|
||||
The complete AI infrastructure platform with unified CLI, AI client library, MCP tools, agent networks, and local AI orchestration. Everything you need to build, deploy, and orchestrate AI applications.
|
||||
The official Python SDK for the [Hanzo AI](https://hanzo.ai) platform - a complete AI infrastructure solution with unified gateway for 100+ LLM providers, cost tracking, rate limiting, and enterprise-ready observability.
|
||||
|
||||
## π Quick Start
|
||||
## π Features
|
||||
|
||||
- **100+ LLM Providers**: OpenAI, Anthropic, Google, AWS Bedrock, Azure, Cohere, and more
|
||||
- **Unified Interface**: OpenAI-compatible API for all providers
|
||||
- **Enterprise Ready**: Cost tracking, rate limiting, team management, and observability
|
||||
- **Type Safety**: Full type hints and runtime validation with Pydantic
|
||||
- **Async Support**: Both sync and async clients included
|
||||
- **100% Test Coverage**: Comprehensive test suite with 3,141 tests
|
||||
|
||||
## π¦ Installation
|
||||
|
||||
```bash
|
||||
# Install the complete platform
|
||||
pip install hanzo[all]
|
||||
|
||||
# Or install specific components
|
||||
pip install hanzo # CLI + network tools
|
||||
pip install hanzoai # AI client library
|
||||
pip install hanzo-mcp # MCP server & tools
|
||||
```
|
||||
|
||||
Start your local AI network:
|
||||
```bash
|
||||
hanzo net # Start local AI orchestration
|
||||
```
|
||||
|
||||
## π¦ Package Ecosystem
|
||||
|
||||
### Core Packages
|
||||
|
||||
| Package | Description | Install |
|
||||
|---------|------------|---------|
|
||||
| **`hanzo`** | π― **Main CLI & Network** | `pip install hanzo` |
|
||||
| | - Universal CLI interface | |
|
||||
| | - Local AI network orchestration (90% cost reduction) | |
|
||||
| | - Peer agent networks with MCP | |
|
||||
| | - Commands: `hanzo net`, `hanzo chat`, `hanzo mcp` | |
|
||||
| **`hanzoai`** | π€ **AI Client Library** | `pip install hanzoai` |
|
||||
| | - 100+ LLM providers (OpenAI-compatible interface) | |
|
||||
| | - Unified gateway and proxy | |
|
||||
| | - Cost tracking and rate limiting | |
|
||||
| **`hanzo-mcp`** | π οΈ **MCP Server & 70+ Tools** | `pip install hanzo-mcp` |
|
||||
| | - Complete development environment | |
|
||||
| | - Interactive notebooks, REPL, debugging | |
|
||||
| | - Multi-agent workflows and orchestration | |
|
||||
| **`hanzo-network`** | π **Decentralized Compute** | `pip install hanzo-network` |
|
||||
| | - Distributed AI workload management | |
|
||||
| | - Peer-to-peer agent networks | |
|
||||
|
||||
### Extended Ecosystem
|
||||
|
||||
| Package | Description |
|
||||
|---------|------------|
|
||||
| **`hanzo-agents`** | Multi-agent workflows and orchestration |
|
||||
| **`hanzo-memory`** | Vector memory and knowledge management |
|
||||
| **`hanzo-repl`** | Interactive AI-powered REPL |
|
||||
| **`hanzo-aci`** | AI-powered development tools |
|
||||
|
||||
## ποΈ Architecture
|
||||
|
||||
### Local AI Orchestration (Hanzo Zen)
|
||||
Cost-effective orchestration model that runs on laptops, mobile, or edge devices:
|
||||
- **90% cost reduction** vs pure API calls
|
||||
- **Mixture of Experts (MoE)** architecture
|
||||
- **Local orchestration loop** with intelligent routing
|
||||
- **API-based LLMs** only for complex tasks
|
||||
- **Full MCP tool support** and recursive agent calls
|
||||
|
||||
### Agent Networks
|
||||
Two deployment architectures:
|
||||
1. **Traditional Swarm**: Hierarchical with main orchestrator
|
||||
2. **Peer Networks**: All agents equal, connected via MCP
|
||||
- Every agent exposes MCP tools to others
|
||||
- Recursive calling (`chat_with_*`, `delegate_to_*`)
|
||||
- Local orchestration with Hanzo Zen
|
||||
|
||||
## π Documentation
|
||||
|
||||
The REST API documentation can be found on [docs.hanzo.ai](https://docs.hanzo.ai). The full API of this library can be found in [api.md](api.md).
|
||||
|
||||
## π‘ Installation Variants
|
||||
|
||||
```bash
|
||||
# Complete ecosystem
|
||||
pip install hanzo[all]
|
||||
|
||||
# Just the CLI and network tools
|
||||
pip install hanzo
|
||||
|
||||
# AI client library (like openai package)
|
||||
pip install hanzoai
|
||||
|
||||
# MCP development environment
|
||||
pip install hanzo-mcp
|
||||
|
||||
# Specific combinations
|
||||
pip install hanzo[ai,mcp] # CLI + AI client + MCP tools
|
||||
pip install hanzo[agents] # CLI + agent runtime
|
||||
```
|
||||
|
||||
## π― Usage Examples
|
||||
|
||||
### Command Line Interface
|
||||
For LiteLLM integration:
|
||||
```bash
|
||||
# Start local AI network (90% cost savings)
|
||||
hanzo net
|
||||
|
||||
# Interactive AI chat
|
||||
hanzo chat
|
||||
|
||||
# Launch MCP server for Claude Desktop
|
||||
hanzo mcp
|
||||
|
||||
# Run agent workflows
|
||||
hanzo agent --config my-team.yaml
|
||||
|
||||
# Check network status
|
||||
hanzo status
|
||||
pip install hanzoai[litellm]
|
||||
```
|
||||
|
||||
### Python SDK - AI Client (hanzoai)
|
||||
## π― Quick Start
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```python
|
||||
# Use like OpenAI but with 100+ providers
|
||||
from hanzoai import Hanzo
|
||||
|
||||
client = Hanzo(api_key="your-key")
|
||||
# Initialize the client
|
||||
client = Hanzo(api_key="your-api-key") # or set HANZO_API_KEY env var
|
||||
|
||||
# Make a chat completion request (OpenAI compatible)
|
||||
response = client.chat.completions.create(
|
||||
model="gpt-4", # or claude-3-5-sonnet, llama-3, etc.
|
||||
messages=[{"role": "user", "content": "Hello!"}]
|
||||
model="gpt-4", # or any supported model
|
||||
messages=[
|
||||
{"role": "user", "content": "Hello, how are you?"}
|
||||
]
|
||||
)
|
||||
|
||||
print(response.choices[0].message.content)
|
||||
```
|
||||
|
||||
### Unified SDK - Everything Together
|
||||
```python
|
||||
import hanzo
|
||||
|
||||
# Use AI client
|
||||
client = hanzo.Client(api_key="your-key")
|
||||
|
||||
# Start agent network
|
||||
network = hanzo.Network()
|
||||
network.start_agents(["coder", "reviewer", "tester"])
|
||||
|
||||
# Use MCP tools
|
||||
from hanzo.mcp import search, edit, critic
|
||||
search("authentication bug")
|
||||
edit("fix auth issue")
|
||||
critic("review this change")
|
||||
```
|
||||
|
||||
### MCP Development Environment
|
||||
```bash
|
||||
# Install to Claude Desktop
|
||||
uvx hanzo-mcp
|
||||
|
||||
# Or run standalone
|
||||
hanzo-mcp --tools search,edit,notebook,agent
|
||||
```
|
||||
|
||||
The full API reference can be found in [api.md](api.md).
|
||||
|
||||
While you can provide an `api_key` keyword argument,
|
||||
we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)
|
||||
to add `HANZO_API_KEY="sk-xxxxxxx` to your `.env` file
|
||||
so that your API Key is not stored in source control.
|
||||
|
||||
## Async usage
|
||||
|
||||
Simply import `AsyncHanzo` instead of `Hanzo` and use `await` with each API call:
|
||||
### Async Usage
|
||||
|
||||
```python
|
||||
import os
|
||||
import asyncio
|
||||
from hanzoai import AsyncHanzo
|
||||
|
||||
client = AsyncHanzo(
|
||||
api_key=os.environ.get("HANZO_API_KEY"), # This is the default and can be omitted
|
||||
)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
response = await client.get_home()
|
||||
|
||||
async def main():
|
||||
client = AsyncHanzo(api_key="your-api-key")
|
||||
|
||||
response = await client.chat.completions.create(
|
||||
model="claude-3-5-sonnet",
|
||||
messages=[
|
||||
{"role": "user", "content": "Explain quantum computing"}
|
||||
]
|
||||
)
|
||||
|
||||
print(response.choices[0].message.content)
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
Functionality between the synchronous and asynchronous clients is otherwise identical.
|
||||
|
||||
## Using types
|
||||
|
||||
Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:
|
||||
|
||||
- Serializing back into JSON, `model.to_json()`
|
||||
- Converting to a dictionary, `model.to_dict()`
|
||||
|
||||
Typed requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.
|
||||
|
||||
## Nested params
|
||||
|
||||
Nested parameters are dictionaries, typed using `TypedDict`, for example:
|
||||
### Streaming Responses
|
||||
|
||||
```python
|
||||
from hanzoai import Hanzo
|
||||
|
||||
client = Hanzo()
|
||||
client = Hanzo(api_key="your-api-key")
|
||||
|
||||
model = client.model.create(
|
||||
# Stream chat completions
|
||||
stream = client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[{"role": "user", "content": "Count to 10"}],
|
||||
stream=True
|
||||
)
|
||||
|
||||
for chunk in stream:
|
||||
if chunk.choices[0].delta.content:
|
||||
print(chunk.choices[0].delta.content, end="")
|
||||
```
|
||||
|
||||
## π οΈ Advanced Features
|
||||
|
||||
### Team & Organization Management
|
||||
|
||||
```python
|
||||
# Create a new team
|
||||
team = client.team.create(
|
||||
team_alias="engineering",
|
||||
models=["gpt-4", "claude-3-5-sonnet"],
|
||||
max_budget=1000.0,
|
||||
rpm_limit=100
|
||||
)
|
||||
|
||||
# Add members to team
|
||||
client.team.add_member(
|
||||
team_id=team.team_id,
|
||||
member=[{"user_email": "[email protected]", "role": "user"}]
|
||||
)
|
||||
|
||||
# Track spending
|
||||
spend_report = client.spend.list_logs()
|
||||
```
|
||||
|
||||
### Model Management
|
||||
|
||||
```python
|
||||
# List available models
|
||||
models = client.models.list()
|
||||
|
||||
# Get model info
|
||||
model_info = client.model.info.get(model="gpt-4")
|
||||
|
||||
# Create custom model configuration
|
||||
client.models.create(
|
||||
model_name="my-custom-gpt4",
|
||||
hanzo_params={
|
||||
"model": "model",
|
||||
"api_base": "api_base",
|
||||
"api_key": "api_key",
|
||||
"api_version": "api_version",
|
||||
"aws_access_key_id": "aws_access_key_id",
|
||||
"aws_region_name": "aws_region_name",
|
||||
"aws_secret_access_key": "aws_secret_access_key",
|
||||
"budget_duration": "budget_duration",
|
||||
"configurable_clientside_auth_params": ["string"],
|
||||
"custom_llm_provider": "custom_llm_provider",
|
||||
"input_cost_per_second": 0,
|
||||
"input_cost_per_token": 0,
|
||||
"hanzo_trace_id": "hanzo_trace_id",
|
||||
"max_budget": 0,
|
||||
"max_file_size_mb": 0,
|
||||
"max_retries": 0,
|
||||
"merge_reasoning_content_in_choices": True,
|
||||
"model_info": {},
|
||||
"organization": "organization",
|
||||
"output_cost_per_second": 0,
|
||||
"output_cost_per_token": 0,
|
||||
"region_name": "region_name",
|
||||
"rpm": 0,
|
||||
"stream_timeout": 0,
|
||||
"timeout": 0,
|
||||
"tpm": 0,
|
||||
"use_in_pass_through": True,
|
||||
"vertex_credentials": "string",
|
||||
"vertex_location": "vertex_location",
|
||||
"vertex_project": "vertex_project",
|
||||
"watsonx_region_name": "watsonx_region_name",
|
||||
},
|
||||
model_info={"id": "id"},
|
||||
model_name="model_name",
|
||||
"model": "gpt-4",
|
||||
"temperature": 0.7,
|
||||
"max_tokens": 2000,
|
||||
"api_base": "https://api.openai.com/v1"
|
||||
}
|
||||
)
|
||||
print(model.hanzo_params)
|
||||
```
|
||||
|
||||
## File uploads
|
||||
|
||||
Request parameters that correspond to file uploads can be passed as `bytes`, a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.
|
||||
### File Operations
|
||||
|
||||
```python
|
||||
from pathlib import Path
|
||||
from hanzoai import Hanzo
|
||||
|
||||
client = Hanzo()
|
||||
|
||||
client.audio.transcriptions.create(
|
||||
file=Path("/path/to/file"),
|
||||
# Upload a file
|
||||
file = client.files.create(
|
||||
file=open("data.jsonl", "rb"),
|
||||
purpose="fine-tune"
|
||||
)
|
||||
|
||||
# List files
|
||||
files = client.files.list()
|
||||
|
||||
# Get file content
|
||||
content = client.files.content.get(file_id=file.id)
|
||||
```
|
||||
|
||||
The async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically.
|
||||
|
||||
## Handling errors
|
||||
|
||||
When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `hanzoai.APIConnectionError` is raised.
|
||||
|
||||
When the API returns a non-success status code (that is, 4xx or 5xx
|
||||
response), a subclass of `hanzoai.APIStatusError` is raised, containing `status_code` and `response` properties.
|
||||
|
||||
All errors inherit from `hanzoai.APIError`.
|
||||
### Fine-tuning
|
||||
|
||||
```python
|
||||
import hanzoai
|
||||
from hanzoai import Hanzo
|
||||
# Create a fine-tuning job
|
||||
job = client.fine_tuning.jobs.create(
|
||||
model="gpt-3.5-turbo",
|
||||
training_file=file.id,
|
||||
hyperparameters={
|
||||
"n_epochs": 3,
|
||||
"batch_size": 1,
|
||||
"learning_rate_multiplier": 1.0
|
||||
}
|
||||
)
|
||||
|
||||
client = Hanzo()
|
||||
# Monitor job status
|
||||
status = client.fine_tuning.jobs.retrieve(job_id=job.id)
|
||||
print(f"Status: {status.status}")
|
||||
|
||||
try:
|
||||
client.get_home()
|
||||
except hanzoai.APIConnectionError as e:
|
||||
print("The server could not be reached")
|
||||
print(e.__cause__) # an underlying Exception, likely raised within httpx.
|
||||
except hanzoai.RateLimitError as e:
|
||||
print("A 429 status code was received; we should back off a bit.")
|
||||
except hanzoai.APIStatusError as e:
|
||||
print("Another non-200-range status code was received")
|
||||
print(e.status_code)
|
||||
print(e.response)
|
||||
# List all jobs
|
||||
jobs = client.fine_tuning.jobs.list()
|
||||
```
|
||||
|
||||
Error codes are as follows:
|
||||
|
||||
| Status Code | Error Type |
|
||||
| ----------- | -------------------------- |
|
||||
| 400 | `BadRequestError` |
|
||||
| 401 | `AuthenticationError` |
|
||||
| 403 | `PermissionDeniedError` |
|
||||
| 404 | `NotFoundError` |
|
||||
| 422 | `UnprocessableEntityError` |
|
||||
| 429 | `RateLimitError` |
|
||||
| >=500 | `InternalServerError` |
|
||||
| N/A | `APIConnectionError` |
|
||||
|
||||
### Retries
|
||||
|
||||
Certain errors are automatically retried 2 times by default, with a short exponential backoff.
|
||||
Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,
|
||||
429 Rate Limit, and >=500 Internal errors are all retried by default.
|
||||
|
||||
You can use the `max_retries` option to configure or disable retry settings:
|
||||
### Embeddings
|
||||
|
||||
```python
|
||||
from hanzoai import Hanzo
|
||||
|
||||
# Configure the default for all requests:
|
||||
client = Hanzo(
|
||||
# default is 2
|
||||
max_retries=0,
|
||||
# Generate embeddings
|
||||
response = client.embeddings.create(
|
||||
model="text-embedding-3-small",
|
||||
input=["Hello world", "How are you?"]
|
||||
)
|
||||
|
||||
# Or, configure per-request:
|
||||
client.with_options(max_retries=5).get_home()
|
||||
for embedding in response.data:
|
||||
print(f"Embedding dimension: {len(embedding.embedding)}")
|
||||
```
|
||||
|
||||
### Timeouts
|
||||
|
||||
By default requests time out after 1 minute. You can configure this with a `timeout` option,
|
||||
which accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/#fine-tuning-the-configuration) object:
|
||||
### Image Generation
|
||||
|
||||
```python
|
||||
from hanzoai import Hanzo
|
||||
|
||||
# Configure the default for all requests:
|
||||
client = Hanzo(
|
||||
# 20 seconds (default is 1 minute)
|
||||
timeout=20.0,
|
||||
# Generate images
|
||||
response = client.images.generate(
|
||||
model="dall-e-3",
|
||||
prompt="A futuristic city at sunset",
|
||||
n=1,
|
||||
size="1024x1024"
|
||||
)
|
||||
|
||||
# More granular control:
|
||||
client = Hanzo(
|
||||
timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),
|
||||
)
|
||||
|
||||
# Override per-request:
|
||||
client.with_options(timeout=5.0).get_home()
|
||||
print(response.data[0].url)
|
||||
```
|
||||
|
||||
On timeout, an `APITimeoutError` is thrown.
|
||||
|
||||
Note that requests that time out are [retried twice by default](#retries).
|
||||
|
||||
## Advanced
|
||||
|
||||
### Logging
|
||||
|
||||
We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.
|
||||
|
||||
You can enable logging by setting the environment variable `HANZO_LOG` to `info`.
|
||||
|
||||
```shell
|
||||
$ export HANZO_LOG=info
|
||||
```
|
||||
|
||||
Or to `debug` for more verbose logging.
|
||||
|
||||
### How to tell whether `None` means `null` or missing
|
||||
|
||||
In an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:
|
||||
|
||||
```py
|
||||
if response.my_field is None:
|
||||
if 'my_field' not in response.model_fields_set:
|
||||
print('Got json like {}, without a "my_field" key present at all.')
|
||||
else:
|
||||
print('Got json like {"my_field": null}.')
|
||||
```
|
||||
|
||||
### Accessing raw response data (e.g. headers)
|
||||
|
||||
The "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,
|
||||
|
||||
```py
|
||||
from hanzoai import Hanzo
|
||||
|
||||
client = Hanzo()
|
||||
response = client.with_raw_response.get_home()
|
||||
print(response.headers.get('X-My-Header'))
|
||||
|
||||
client = response.parse() # get the object that `get_home()` would have returned
|
||||
print(client)
|
||||
```
|
||||
|
||||
These methods return an [`APIResponse`](https://github.com/hanzoai/python-sdk/tree/main/pkg/hanzoai/_response.py) object.
|
||||
|
||||
The async client returns an [`AsyncAPIResponse`](https://github.com/hanzoai/python-sdk/tree/main/pkg/hanzoai/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.
|
||||
|
||||
#### `.with_streaming_response`
|
||||
|
||||
The above interface eagerly reads the full response body when you make the request, which may not always be what you want.
|
||||
|
||||
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
|
||||
### Audio Transcription
|
||||
|
||||
```python
|
||||
with client.with_streaming_response.get_home() as response:
|
||||
print(response.headers.get("X-My-Header"))
|
||||
|
||||
for line in response.iter_lines():
|
||||
print(line)
|
||||
```
|
||||
|
||||
The context manager is required so that the response will reliably be closed.
|
||||
|
||||
### Making custom/undocumented requests
|
||||
|
||||
This library is typed for convenient access to the documented API.
|
||||
|
||||
If you need to access undocumented endpoints, params, or response properties, the library can still be used.
|
||||
|
||||
#### Undocumented endpoints
|
||||
|
||||
To make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other
|
||||
http verbs. Options on the client will be respected (such as retries) when making this request.
|
||||
|
||||
```py
|
||||
import httpx
|
||||
|
||||
response = client.post(
|
||||
"/foo",
|
||||
cast_to=httpx.Response,
|
||||
body={"my_param": True},
|
||||
# Transcribe audio
|
||||
transcript = client.audio.transcriptions.create(
|
||||
model="whisper-1",
|
||||
file=open("audio.mp3", "rb")
|
||||
)
|
||||
|
||||
print(response.headers.get("x-foo"))
|
||||
print(transcript.text)
|
||||
```
|
||||
|
||||
#### Undocumented request params
|
||||
## π§ Configuration
|
||||
|
||||
If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request
|
||||
options.
|
||||
### Environment Variables
|
||||
|
||||
#### Undocumented response properties
|
||||
```bash
|
||||
export HANZO_API_KEY="your-api-key"
|
||||
export HANZO_BASE_URL="https://api.hanzo.ai" # optional
|
||||
export HANZO_LOG="info" # Enable logging (debug/info/warning/error)
|
||||
```
|
||||
|
||||
To access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You
|
||||
can also get all the extra fields on the Pydantic model as a dict with
|
||||
[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).
|
||||
|
||||
### Configuring the HTTP client
|
||||
|
||||
You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:
|
||||
|
||||
- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)
|
||||
- Custom [transports](https://www.python-httpx.org/advanced/transports/)
|
||||
- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality
|
||||
### Custom HTTP Client
|
||||
|
||||
```python
|
||||
import httpx
|
||||
from hanzoai import Hanzo, DefaultHttpxClient
|
||||
|
||||
client = Hanzo(
|
||||
# Or use the `HANZO_BASE_URL` env var
|
||||
base_url="http://my.test.server.example.com:8083",
|
||||
api_key="your-api-key",
|
||||
http_client=DefaultHttpxClient(
|
||||
proxy="http://my.test.proxy.example.com",
|
||||
transport=httpx.HTTPTransport(local_address="0.0.0.0"),
|
||||
),
|
||||
proxy="http://proxy.example.com:8080",
|
||||
timeout=30.0,
|
||||
limits=httpx.Limits(max_connections=100)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
You can also customize the client on a per-request basis by using `with_options()`:
|
||||
### Retry Configuration
|
||||
|
||||
```python
|
||||
client.with_options(http_client=DefaultHttpxClient(...))
|
||||
```
|
||||
|
||||
### Managing HTTP resources
|
||||
|
||||
By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.
|
||||
|
||||
```py
|
||||
from hanzoai import Hanzo
|
||||
|
||||
with Hanzo() as client:
|
||||
# make requests here
|
||||
...
|
||||
client = Hanzo(
|
||||
api_key="your-api-key",
|
||||
max_retries=3, # Default is 2
|
||||
timeout=60.0 # Default is 60 seconds
|
||||
)
|
||||
|
||||
# HTTP client is now closed
|
||||
# Per-request configuration
|
||||
response = client.with_options(
|
||||
max_retries=5,
|
||||
timeout=120.0
|
||||
).chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[{"role": "user", "content": "Hello"}]
|
||||
)
|
||||
```
|
||||
|
||||
## Versioning
|
||||
## π Error Handling
|
||||
|
||||
This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
|
||||
|
||||
1. Changes that only affect static types, without breaking runtime behavior.
|
||||
2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
|
||||
3. Changes that we do not expect to impact the vast majority of users in practice.
|
||||
|
||||
We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
|
||||
|
||||
We are keen for your feedback; please open an [issue](https://www.github.com/hanzoai/python-sdk/issues) with questions, bugs, or suggestions.
|
||||
|
||||
### Determining the installed version
|
||||
|
||||
If you've upgraded to the latest version but aren't seeing any new features you were expecting then your python environment is likely still using an older version.
|
||||
|
||||
You can determine the version that is being used at runtime with:
|
||||
|
||||
```py
|
||||
```python
|
||||
from hanzoai import Hanzo
|
||||
import hanzoai
|
||||
print(hanzoai.__version__)
|
||||
|
||||
client = Hanzo(api_key="your-api-key")
|
||||
|
||||
try:
|
||||
response = client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[{"role": "user", "content": "Hello"}]
|
||||
)
|
||||
except hanzoai.APIConnectionError as e:
|
||||
print(f"Connection error: {e}")
|
||||
except hanzoai.RateLimitError as e:
|
||||
print(f"Rate limit exceeded: {e}")
|
||||
print(f"Retry after: {e.response.headers.get('retry-after')}")
|
||||
except hanzoai.APIStatusError as e:
|
||||
print(f"API error: {e.status_code}")
|
||||
print(f"Response: {e.response}")
|
||||
```
|
||||
|
||||
## Requirements
|
||||
### Error Types
|
||||
|
||||
Python 3.8 or higher.
|
||||
| Error Type | Description |
|
||||
|------------|-------------|
|
||||
| `APIConnectionError` | Network connectivity issues |
|
||||
| `APITimeoutError` | Request timeout |
|
||||
| `RateLimitError` | Rate limit exceeded (429) |
|
||||
| `AuthenticationError` | Invalid API key (401) |
|
||||
| `PermissionDeniedError` | Insufficient permissions (403) |
|
||||
| `NotFoundError` | Resource not found (404) |
|
||||
| `UnprocessableEntityError` | Invalid request (422) |
|
||||
| `InternalServerError` | Server error (500+) |
|
||||
|
||||
## Contributing
|
||||
## π§ͺ Development
|
||||
|
||||
See [the contributing documentation](./CONTRIBUTING.md).
|
||||
### Setup Development Environment
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/hanzoai/python-sdk.git
|
||||
cd python-sdk
|
||||
|
||||
# Install with uv (recommended)
|
||||
uv pip install -e .
|
||||
|
||||
# Or with pip
|
||||
pip install -e .
|
||||
|
||||
# Install dev dependencies
|
||||
uv pip install -r requirements-dev.lock
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
./scripts/test
|
||||
|
||||
# Or with pytest directly
|
||||
uv run pytest tests/
|
||||
|
||||
# Run with coverage
|
||||
uv run pytest --cov=hanzoai tests/
|
||||
|
||||
# Run specific test file
|
||||
uv run pytest tests/api_resources/test_chat.py
|
||||
```
|
||||
|
||||
### Code Quality
|
||||
|
||||
```bash
|
||||
# Run lints
|
||||
./scripts/lint
|
||||
|
||||
# Format code
|
||||
uv run ruff format pkg/
|
||||
|
||||
# Type checking
|
||||
uv run mypy pkg/
|
||||
```
|
||||
|
||||
## π Documentation
|
||||
|
||||
- **API Reference**: Full API documentation at [docs.hanzo.ai](https://docs.hanzo.ai)
|
||||
- **SDK Reference**: Detailed SDK reference in [api.md](api.md)
|
||||
- **Examples**: See the [examples/](examples/) directory
|
||||
- **Contributing**: Read [CONTRIBUTING.md](CONTRIBUTING.md)
|
||||
|
||||
## π€ Support
|
||||
|
||||
- **Issues**: [GitHub Issues](https://github.com/hanzoai/python-sdk/issues)
|
||||
- **Discussions**: [GitHub Discussions](https://github.com/hanzoai/python-sdk/discussions)
|
||||
- **Discord**: [Join our Discord](https://discord.gg/hanzoai)
|
||||
- **Email**: support@hanzo.ai
|
||||
|
||||
## π License
|
||||
|
||||
This project is licensed under the BSD-3-Clause License. See [LICENSE](LICENSE) file for details.
|
||||
|
||||
## ποΈ Project Status
|
||||
|
||||
- β
**3,141 tests** - 100% passing
|
||||
- β
**Type Safe** - Full type hints with Pydantic validation
|
||||
- β
**Production Ready** - Used in enterprise deployments
|
||||
- β
**Active Development** - Regular updates and improvements
|
||||
|
||||
## π Contributors
|
||||
|
||||
Thanks to all our contributors! See [CONTRIBUTORS.md](CONTRIBUTORS.md) for the full list.
|
||||
|
||||
---
|
||||
|
||||
Built with β€οΈ by [Hanzo AI](https://hanzo.ai)
|
||||
Reference in New Issue
Block a user