mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
docs(lib): add core library documentation
- lib/index.md: Overview of all core utility packages - lib/async.md: High-performance async I/O with uvloop - lib/consensus.md: Metastable consensus protocol for multi-agent agreement - lib/network.md: Agent network orchestration - lib/aci.md: Agent-Computer Interface for development agents - lib/repl.md: Interactive REPL with voice and LLM integration
This commit is contained in:
+260
@@ -0,0 +1,260 @@
|
||||
# hanzo-aci
|
||||
|
||||
Agent-Computer Interface (ACI) designed for software development agents.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install hanzo-aci
|
||||
```
|
||||
|
||||
## Overview
|
||||
|
||||
hanzo-aci provides a comprehensive interface for AI agents to interact with codebases, enabling:
|
||||
|
||||
- **Code Understanding** - AST parsing with tree-sitter
|
||||
- **Repository Analysis** - Git integration and file operations
|
||||
- **Semantic Search** - Code search and pattern matching
|
||||
- **Diff Generation** - Create and apply patches
|
||||
|
||||
## Features
|
||||
|
||||
### AST Parsing
|
||||
|
||||
Parse code into abstract syntax trees using tree-sitter:
|
||||
|
||||
```python
|
||||
from dev_aci import parse_code
|
||||
|
||||
# Parse Python code
|
||||
ast = parse_code("""
|
||||
def hello(name: str) -> str:
|
||||
return f"Hello, {name}!"
|
||||
""", language="python")
|
||||
|
||||
# Get functions
|
||||
functions = ast.get_functions()
|
||||
for func in functions:
|
||||
print(f"{func.name}: {func.line_number}")
|
||||
```
|
||||
|
||||
### Supported Languages
|
||||
|
||||
| Language | tree-sitter Package |
|
||||
|----------|---------------------|
|
||||
| Python | `tree-sitter-python` |
|
||||
| JavaScript | `tree-sitter-javascript` |
|
||||
| TypeScript | `tree-sitter-typescript` |
|
||||
| Ruby | `tree-sitter-ruby` |
|
||||
|
||||
### Repository Analysis
|
||||
|
||||
Work with Git repositories:
|
||||
|
||||
```python
|
||||
from dev_aci import Repository
|
||||
|
||||
# Open repository
|
||||
repo = Repository("/path/to/repo")
|
||||
|
||||
# Get file tree
|
||||
tree = repo.get_tree()
|
||||
|
||||
# Get file content
|
||||
content = repo.read_file("src/main.py")
|
||||
|
||||
# Get recent changes
|
||||
changes = repo.get_recent_commits(limit=10)
|
||||
|
||||
# Search for patterns
|
||||
matches = repo.search("TODO")
|
||||
```
|
||||
|
||||
### Code Search
|
||||
|
||||
Find code patterns:
|
||||
|
||||
```python
|
||||
from dev_aci import CodeSearch
|
||||
|
||||
search = CodeSearch("/path/to/repo")
|
||||
|
||||
# Search by pattern
|
||||
results = search.find_pattern("class.*Service")
|
||||
|
||||
# Search by function name
|
||||
funcs = search.find_functions("handle_*")
|
||||
|
||||
# Search by reference
|
||||
refs = search.find_references("MyClass")
|
||||
```
|
||||
|
||||
### Diff Operations
|
||||
|
||||
Generate and apply patches:
|
||||
|
||||
```python
|
||||
from dev_aci import DiffGenerator
|
||||
|
||||
diff = DiffGenerator()
|
||||
|
||||
# Generate diff
|
||||
patch = diff.create_patch(
|
||||
original="def foo(): pass",
|
||||
modified="def foo():\n return 42",
|
||||
)
|
||||
|
||||
# Apply patch
|
||||
result = diff.apply_patch(content, patch)
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Dependencies
|
||||
|
||||
hanzo-aci includes these dependencies:
|
||||
|
||||
- **numpy, pandas, scipy** - Data processing
|
||||
- **networkx** - Graph analysis
|
||||
- **litellm** - LLM integration
|
||||
- **gitpython** - Git operations
|
||||
- **tree-sitter** - AST parsing
|
||||
- **grep-ast** - Code search
|
||||
|
||||
### Optional Dependencies
|
||||
|
||||
```bash
|
||||
# Development tools
|
||||
pip install hanzo-aci[dev]
|
||||
|
||||
# Testing tools
|
||||
pip install hanzo-aci[test]
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Agent Code Understanding
|
||||
|
||||
```python
|
||||
from dev_aci import Repository, CodeSearch
|
||||
|
||||
async def understand_codebase(repo_path: str):
|
||||
repo = Repository(repo_path)
|
||||
search = CodeSearch(repo_path)
|
||||
|
||||
# Get structure
|
||||
tree = repo.get_tree()
|
||||
|
||||
# Find entry points
|
||||
main_files = search.find_pattern("if __name__ == .__main__.")
|
||||
|
||||
# Find tests
|
||||
test_files = search.find_functions("test_*")
|
||||
|
||||
return {
|
||||
"structure": tree,
|
||||
"entry_points": main_files,
|
||||
"test_files": test_files,
|
||||
}
|
||||
```
|
||||
|
||||
### Code Modification Agent
|
||||
|
||||
```python
|
||||
from dev_aci import Repository, DiffGenerator, parse_code
|
||||
|
||||
async def modify_code(repo_path: str, file_path: str, modification: str):
|
||||
repo = Repository(repo_path)
|
||||
diff = DiffGenerator()
|
||||
|
||||
# Read original
|
||||
original = repo.read_file(file_path)
|
||||
|
||||
# Parse and understand
|
||||
ast = parse_code(original, language="python")
|
||||
|
||||
# Generate modification
|
||||
modified = apply_modification(original, modification)
|
||||
|
||||
# Create patch
|
||||
patch = diff.create_patch(original, modified)
|
||||
|
||||
return patch
|
||||
```
|
||||
|
||||
### Code Review Agent
|
||||
|
||||
```python
|
||||
from dev_aci import Repository, CodeSearch, parse_code
|
||||
|
||||
async def review_code(repo_path: str, file_path: str):
|
||||
repo = Repository(repo_path)
|
||||
|
||||
# Get file content
|
||||
content = repo.read_file(file_path)
|
||||
|
||||
# Parse AST
|
||||
ast = parse_code(content, language="python")
|
||||
|
||||
# Analyze
|
||||
issues = []
|
||||
|
||||
# Check function length
|
||||
for func in ast.get_functions():
|
||||
if func.line_count > 50:
|
||||
issues.append(f"Function {func.name} is too long ({func.line_count} lines)")
|
||||
|
||||
# Check for TODOs
|
||||
search = CodeSearch(repo_path)
|
||||
todos = search.find_pattern("TODO|FIXME", file=file_path)
|
||||
if todos:
|
||||
issues.append(f"Found {len(todos)} TODO/FIXME comments")
|
||||
|
||||
return issues
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Repository
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `get_tree()` | Get file tree structure |
|
||||
| `read_file(path)` | Read file content |
|
||||
| `write_file(path, content)` | Write file content |
|
||||
| `get_recent_commits(limit)` | Get recent commits |
|
||||
| `search(pattern)` | Search repository |
|
||||
|
||||
### CodeSearch
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `find_pattern(pattern)` | Search by regex pattern |
|
||||
| `find_functions(pattern)` | Find function definitions |
|
||||
| `find_classes(pattern)` | Find class definitions |
|
||||
| `find_references(name)` | Find symbol references |
|
||||
|
||||
### DiffGenerator
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `create_patch(original, modified)` | Generate diff patch |
|
||||
| `apply_patch(content, patch)` | Apply patch to content |
|
||||
| `validate_patch(patch)` | Validate patch format |
|
||||
|
||||
### AST Functions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `parse_code(code, language)` | Parse code into AST |
|
||||
| `get_functions()` | Get function definitions |
|
||||
| `get_classes()` | Get class definitions |
|
||||
| `get_imports()` | Get import statements |
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use AST for Analysis**: Prefer AST over regex for code analysis
|
||||
2. **Cache Repositories**: Reuse Repository instances for efficiency
|
||||
3. **Validate Patches**: Always validate patches before applying
|
||||
4. **Handle Errors**: Code parsing can fail - handle ParseError exceptions
|
||||
5. **Language Detection**: Use file extensions to detect language automatically
|
||||
@@ -0,0 +1,209 @@
|
||||
# hanzo-async
|
||||
|
||||
High-performance async I/O for Hanzo AI with automatic uvloop configuration.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install hanzo-async
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- **Automatic uvloop** - 2-4x faster async on macOS/Linux
|
||||
- **Async file I/O** - Non-blocking file operations
|
||||
- **Async subprocess** - Non-blocking command execution
|
||||
- **Consistent API** - Used across all Hanzo packages
|
||||
|
||||
## Quick Start
|
||||
|
||||
```python
|
||||
from hanzo_async import (
|
||||
read_file, write_file,
|
||||
path_exists, mkdir,
|
||||
run_command,
|
||||
using_uvloop,
|
||||
)
|
||||
|
||||
# Check if using high-performance backend
|
||||
if using_uvloop():
|
||||
print("Using uvloop for 2-4x faster async")
|
||||
|
||||
# Async file operations
|
||||
content = await read_file("/path/to/file.txt")
|
||||
await write_file("/path/to/output.txt", "content")
|
||||
|
||||
# Async path operations
|
||||
if await path_exists("/path/to/dir"):
|
||||
...
|
||||
|
||||
# Async subprocess
|
||||
stdout, stderr, code = await run_command("ls", "-la")
|
||||
```
|
||||
|
||||
## Loop Configuration
|
||||
|
||||
```python
|
||||
from hanzo_async import configure_loop, using_uvloop, get_loop
|
||||
|
||||
# Configure on import (automatic)
|
||||
configure_loop()
|
||||
|
||||
# Check backend
|
||||
if using_uvloop():
|
||||
print("uvloop active")
|
||||
else:
|
||||
print("Using asyncio (Windows or uvloop not installed)")
|
||||
|
||||
# Get current loop
|
||||
loop = get_loop()
|
||||
```
|
||||
|
||||
## File Operations
|
||||
|
||||
### Reading Files
|
||||
|
||||
```python
|
||||
from hanzo_async import read_file, read_json, read_lines
|
||||
|
||||
# Read text file
|
||||
content = await read_file("/path/to/file.txt")
|
||||
|
||||
# Read JSON file
|
||||
data = await read_json("/path/to/config.json")
|
||||
|
||||
# Read lines
|
||||
lines = await read_lines("/path/to/file.txt")
|
||||
```
|
||||
|
||||
### Writing Files
|
||||
|
||||
```python
|
||||
from hanzo_async import write_file, write_json, write_lines, append_file
|
||||
|
||||
# Write text file
|
||||
await write_file("/path/to/file.txt", "content")
|
||||
|
||||
# Write JSON file
|
||||
await write_json("/path/to/config.json", {"key": "value"})
|
||||
|
||||
# Write lines
|
||||
await write_lines("/path/to/file.txt", ["line1", "line2"])
|
||||
|
||||
# Append to file
|
||||
await append_file("/path/to/log.txt", "new entry\n")
|
||||
```
|
||||
|
||||
## Path Operations
|
||||
|
||||
```python
|
||||
from hanzo_async import (
|
||||
path_exists, is_file, is_dir,
|
||||
mkdir, rmdir, unlink,
|
||||
stat, listdir, glob,
|
||||
)
|
||||
|
||||
# Check existence
|
||||
if await path_exists("/path"):
|
||||
...
|
||||
|
||||
# Check type
|
||||
if await is_file("/path/file.txt"):
|
||||
...
|
||||
if await is_dir("/path/dir"):
|
||||
...
|
||||
|
||||
# Create directory
|
||||
await mkdir("/path/new/dir", parents=True, exist_ok=True)
|
||||
|
||||
# Remove
|
||||
await unlink("/path/file.txt") # Remove file
|
||||
await rmdir("/path/dir") # Remove directory
|
||||
|
||||
# List directory
|
||||
files = await listdir("/path/dir")
|
||||
|
||||
# Glob pattern
|
||||
matches = await glob("/path/**/*.py")
|
||||
|
||||
# Get file info
|
||||
info = await stat("/path/file.txt")
|
||||
print(f"Size: {info.st_size}, Modified: {info.st_mtime}")
|
||||
```
|
||||
|
||||
## Process Operations
|
||||
|
||||
```python
|
||||
from hanzo_async import run_command, run_shell, check_command
|
||||
|
||||
# Run command with arguments
|
||||
stdout, stderr, code = await run_command("git", "status")
|
||||
|
||||
# Run shell command
|
||||
stdout, stderr, code = await run_shell("ls -la | grep .py")
|
||||
|
||||
# Check if command succeeds (raises on failure)
|
||||
await check_command("make", "build")
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Loop Functions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `configure_loop()` | Configure uvloop (automatic on import) |
|
||||
| `using_uvloop()` | Check if uvloop is active |
|
||||
| `get_loop()` | Get current event loop |
|
||||
|
||||
### File Functions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `read_file(path)` | Read file as string |
|
||||
| `read_json(path)` | Read and parse JSON file |
|
||||
| `read_lines(path)` | Read file as list of lines |
|
||||
| `write_file(path, content)` | Write string to file |
|
||||
| `write_json(path, data)` | Write data as JSON |
|
||||
| `write_lines(path, lines)` | Write list of lines |
|
||||
| `append_file(path, content)` | Append to file |
|
||||
|
||||
### Path Functions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `path_exists(path)` | Check if path exists |
|
||||
| `is_file(path)` | Check if path is a file |
|
||||
| `is_dir(path)` | Check if path is a directory |
|
||||
| `mkdir(path, ...)` | Create directory |
|
||||
| `rmdir(path)` | Remove directory |
|
||||
| `unlink(path)` | Remove file |
|
||||
| `stat(path)` | Get file information |
|
||||
| `listdir(path)` | List directory contents |
|
||||
| `glob(pattern)` | Find files matching pattern |
|
||||
|
||||
### Process Functions
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `run_command(*args)` | Run command with arguments |
|
||||
| `run_shell(cmd)` | Run shell command |
|
||||
| `check_command(*args)` | Run and raise on failure |
|
||||
|
||||
## Platform Support
|
||||
|
||||
| Platform | Backend | Performance |
|
||||
|----------|---------|-------------|
|
||||
| macOS | uvloop | 2-4x faster |
|
||||
| Linux | uvloop | 2-4x faster |
|
||||
| Windows | asyncio | Standard |
|
||||
|
||||
## Why uvloop?
|
||||
|
||||
uvloop is a fast, drop-in replacement for asyncio's event loop that uses libuv under the hood. It provides:
|
||||
|
||||
- **2-4x faster** async operations
|
||||
- **Lower latency** for I/O bound tasks
|
||||
- **Better scalability** under high concurrency
|
||||
|
||||
The hanzo-async package automatically configures uvloop when available, falling back to asyncio on Windows or when uvloop isn't installed.
|
||||
@@ -0,0 +1,285 @@
|
||||
# hanzo-consensus
|
||||
|
||||
Metastable consensus protocol for multi-agent agreement.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install hanzo-consensus
|
||||
```
|
||||
|
||||
## Overview
|
||||
|
||||
The metastable consensus protocol enables multiple AI agents to reach agreement through a two-phase process:
|
||||
|
||||
1. **Phase I (Sampling)**: Agents propose responses and refine based on peer feedback
|
||||
2. **Phase II (Finality)**: Agreement threshold determines winner and synthesis
|
||||
|
||||
Reference: [github.com/luxfi/consensus](https://github.com/luxfi/consensus)
|
||||
|
||||
## Quick Start
|
||||
|
||||
```python
|
||||
from hanzo_consensus import Consensus, run, State, Result
|
||||
|
||||
# Define execution function
|
||||
async def execute(agent_id: str, prompt: str) -> Result:
|
||||
# Call your LLM here
|
||||
response = await call_llm(agent_id, prompt)
|
||||
return Result(
|
||||
id=agent_id,
|
||||
output=response,
|
||||
ok=True,
|
||||
ms=100 # Response time in ms
|
||||
)
|
||||
|
||||
# Run consensus
|
||||
state = await run(
|
||||
prompt="What's the best approach for error handling?",
|
||||
participants=["gpt-4", "claude-3", "gemini"],
|
||||
execute=execute,
|
||||
rounds=3,
|
||||
k=3,
|
||||
alpha=0.6,
|
||||
beta_1=0.5,
|
||||
beta_2=0.8,
|
||||
)
|
||||
|
||||
print(f"Winner: {state.winner}")
|
||||
print(f"Finalized: {state.finalized}")
|
||||
print(f"Synthesis: {state.synthesis}")
|
||||
```
|
||||
|
||||
## Protocol Parameters
|
||||
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `rounds` | 3 | Number of sampling rounds |
|
||||
| `k` | 3 | Sample size per round |
|
||||
| `alpha` | 0.6 | Agreement threshold (0-1) |
|
||||
| `beta_1` | 0.5 | Preference threshold (Phase I) |
|
||||
| `beta_2` | 0.8 | Decision threshold (Phase II) |
|
||||
|
||||
### Parameter Tuning
|
||||
|
||||
**Higher `rounds`**: More refinement, better consensus, slower
|
||||
```python
|
||||
run(..., rounds=5) # More thorough consensus
|
||||
```
|
||||
|
||||
**Higher `k`**: More peers sampled, broader agreement
|
||||
```python
|
||||
run(..., k=5) # Sample more peers per round
|
||||
```
|
||||
|
||||
**Higher `beta_2`**: Stricter finality requirement
|
||||
```python
|
||||
run(..., beta_2=0.9) # Require strong agreement
|
||||
```
|
||||
|
||||
## Classes
|
||||
|
||||
### Result
|
||||
|
||||
Represents a participant's response:
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class Result:
|
||||
id: str # Participant ID
|
||||
output: str # Response text
|
||||
ok: bool # Success flag
|
||||
error: Optional[str] # Error message if failed
|
||||
ms: int = 0 # Response time (affects luminance)
|
||||
round: int = 0 # Round number
|
||||
```
|
||||
|
||||
### State
|
||||
|
||||
Consensus state throughout the protocol:
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class State:
|
||||
prompt: str # Original query
|
||||
participants: List[str] # Participant IDs
|
||||
rounds: int # Total rounds
|
||||
k: int # Sample size
|
||||
alpha: float # Agreement threshold
|
||||
beta_1: float # Preference threshold
|
||||
beta_2: float # Decision threshold
|
||||
|
||||
# State (updated during protocol)
|
||||
responses: Dict[str, List[str]] # Responses per participant
|
||||
confidence: Dict[str, float] # Confidence scores
|
||||
luminance: Dict[str, float] # Performance scores
|
||||
finalized: bool # Whether consensus reached
|
||||
winner: Optional[str] # Winning participant
|
||||
synthesis: Optional[str] # Final synthesized response
|
||||
```
|
||||
|
||||
### Consensus
|
||||
|
||||
Main consensus class:
|
||||
|
||||
```python
|
||||
consensus = Consensus(
|
||||
participants=["agent-1", "agent-2", "agent-3"],
|
||||
execute=my_execute_fn,
|
||||
rounds=3,
|
||||
k=3,
|
||||
alpha=0.6,
|
||||
beta_1=0.5,
|
||||
beta_2=0.8,
|
||||
)
|
||||
|
||||
state = await consensus.run("Your question here")
|
||||
```
|
||||
|
||||
## MCP Mesh Integration
|
||||
|
||||
For MCP-based agents, use the MCPMesh:
|
||||
|
||||
```python
|
||||
from hanzo_consensus import MCPMesh, MCPAgent, run_mcp_consensus
|
||||
|
||||
# Create MCP agents
|
||||
agents = [
|
||||
MCPAgent(id="agent-1", endpoint="http://localhost:8001"),
|
||||
MCPAgent(id="agent-2", endpoint="http://localhost:8002"),
|
||||
]
|
||||
|
||||
# Create mesh
|
||||
mesh = MCPMesh(agents)
|
||||
|
||||
# Run consensus through MCP
|
||||
state = await run_mcp_consensus(
|
||||
mesh=mesh,
|
||||
prompt="Design an API for user authentication",
|
||||
rounds=3,
|
||||
)
|
||||
```
|
||||
|
||||
## Protocol Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PHASE I: SAMPLING │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Round 0: Initial Proposals │
|
||||
│ Agent-1 ───► "Use try/except blocks..." │
|
||||
│ Agent-2 ───► "Implement error types..." │
|
||||
│ Agent-3 ───► "Use Result types..." │
|
||||
│ │
|
||||
│ Round 1-N: Refinement │
|
||||
│ Sample k peers (weighted by luminance) │
|
||||
│ Share peer responses as context │
|
||||
│ Each agent refines response │
|
||||
│ Update confidence scores │
|
||||
│ │
|
||||
│ if max(confidence) >= β₁: proceed to Phase II │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ PHASE II: FINALITY │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Calculate final scores: confidence × luminance │
|
||||
│ Winner = agent with highest score │
|
||||
│ if score >= β₂: finalized = True │
|
||||
│ Synthesis = winner's final response │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Luminance
|
||||
|
||||
Luminance measures agent performance based on response time:
|
||||
|
||||
```python
|
||||
luminance = 1.0 / (1.0 + response_time_ms / 1000.0)
|
||||
```
|
||||
|
||||
Faster agents get higher luminance, increasing their influence in peer sampling.
|
||||
|
||||
### Confidence
|
||||
|
||||
Confidence measures agreement with sampled peers:
|
||||
|
||||
```python
|
||||
confidence = previous_confidence * 0.5 + current_agreement * 0.5
|
||||
```
|
||||
|
||||
Agreement is calculated using word overlap (Jaccard similarity).
|
||||
|
||||
### Finalization
|
||||
|
||||
Consensus is finalized when the winner's combined score exceeds β₂:
|
||||
|
||||
```python
|
||||
score = confidence * luminance
|
||||
finalized = score >= beta_2
|
||||
```
|
||||
|
||||
## Example: Multi-LLM Consensus
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from hanzo_consensus import run, Result
|
||||
|
||||
async def call_openai(prompt: str) -> str:
|
||||
# Your OpenAI API call
|
||||
...
|
||||
|
||||
async def call_anthropic(prompt: str) -> str:
|
||||
# Your Anthropic API call
|
||||
...
|
||||
|
||||
async def call_google(prompt: str) -> str:
|
||||
# Your Google API call
|
||||
...
|
||||
|
||||
PROVIDERS = {
|
||||
"openai": call_openai,
|
||||
"anthropic": call_anthropic,
|
||||
"google": call_google,
|
||||
}
|
||||
|
||||
async def execute(agent_id: str, prompt: str) -> Result:
|
||||
import time
|
||||
start = time.time()
|
||||
try:
|
||||
output = await PROVIDERS[agent_id](prompt)
|
||||
return Result(
|
||||
id=agent_id,
|
||||
output=output,
|
||||
ok=True,
|
||||
ms=int((time.time() - start) * 1000),
|
||||
)
|
||||
except Exception as e:
|
||||
return Result(
|
||||
id=agent_id,
|
||||
output="",
|
||||
ok=False,
|
||||
error=str(e),
|
||||
)
|
||||
|
||||
async def main():
|
||||
state = await run(
|
||||
prompt="What's the most efficient way to sort a list in Python?",
|
||||
participants=list(PROVIDERS.keys()),
|
||||
execute=execute,
|
||||
)
|
||||
|
||||
print(f"Consensus reached: {state.finalized}")
|
||||
print(f"Winner: {state.winner}")
|
||||
print(f"Answer: {state.synthesis}")
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Diverse Participants**: Use different LLM providers for better consensus
|
||||
2. **Appropriate Rounds**: Start with 3 rounds, increase for complex queries
|
||||
3. **Tune Thresholds**: Lower β₂ for faster consensus, higher for stricter agreement
|
||||
4. **Handle Failures**: Always check `result.ok` in your execute function
|
||||
5. **Monitor Latency**: Response time affects luminance and peer selection
|
||||
@@ -0,0 +1,21 @@
|
||||
# Core Libraries
|
||||
|
||||
This section documents the foundational utility packages that power the Hanzo AI ecosystem.
|
||||
|
||||
## Overview
|
||||
|
||||
| Package | Description | Install |
|
||||
|---------|-------------|---------|
|
||||
| `hanzo-async` | High-performance async I/O | `pip install hanzo-async` |
|
||||
| `hanzo-consensus` | Metastable consensus protocol | `pip install hanzo-consensus` |
|
||||
| `hanzo-network` | Agent network orchestration | `pip install hanzo-network` |
|
||||
| `hanzo-aci` | Agent-Computer Interface | `pip install hanzo-aci` |
|
||||
| `hanzo-repl` | Interactive REPL | `pip install hanzo-repl` |
|
||||
|
||||
## Quick Links
|
||||
|
||||
- [Async I/O](async.md) - Unified async operations with uvloop
|
||||
- [Consensus](consensus.md) - Multi-agent agreement protocol
|
||||
- [Network](network.md) - Distributed agent orchestration
|
||||
- [ACI](aci.md) - Agent-Computer Interface for development agents
|
||||
- [REPL](repl.md) - Interactive command-line interface
|
||||
@@ -0,0 +1,284 @@
|
||||
# hanzo-network
|
||||
|
||||
Agent network orchestration for distributed AI systems.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install hanzo-network
|
||||
```
|
||||
|
||||
## Overview
|
||||
|
||||
hanzo-network enables building distributed agent networks with:
|
||||
|
||||
- **Topology Management** - Define and manage agent network structures
|
||||
- **Device Capabilities** - Track compute resources across nodes
|
||||
- **Partitioning Strategies** - Distribute work across agents
|
||||
- **Local LLM Support** - Run models locally for development
|
||||
|
||||
## Quick Start
|
||||
|
||||
```python
|
||||
from hanzo_network.core import AgentNetwork, NetworkConfig
|
||||
from hanzo_network.topology import RingMemoryWeightedPartitioningStrategy
|
||||
|
||||
# Create network
|
||||
config = NetworkConfig(
|
||||
name="my-network",
|
||||
strategy=RingMemoryWeightedPartitioningStrategy(),
|
||||
)
|
||||
network = AgentNetwork(config)
|
||||
|
||||
# Add agents
|
||||
network.add_agent("agent-1", capabilities={"memory": 16, "gpu": True})
|
||||
network.add_agent("agent-2", capabilities={"memory": 8, "gpu": False})
|
||||
|
||||
# Route work
|
||||
result = await network.route("Process this complex task")
|
||||
```
|
||||
|
||||
## Core Components
|
||||
|
||||
### AgentNetwork
|
||||
|
||||
The main network orchestrator:
|
||||
|
||||
```python
|
||||
from hanzo_network.core import AgentNetwork, NetworkConfig
|
||||
|
||||
# Configuration
|
||||
config = NetworkConfig(
|
||||
name="production-network",
|
||||
max_agents=100,
|
||||
timeout=30.0,
|
||||
retry_count=3,
|
||||
)
|
||||
|
||||
# Create network
|
||||
network = AgentNetwork(config)
|
||||
|
||||
# Add agents
|
||||
network.add_agent(
|
||||
agent_id="worker-1",
|
||||
endpoint="http://localhost:8001",
|
||||
capabilities={"memory": 32, "gpu": True, "cores": 8}
|
||||
)
|
||||
|
||||
# Remove agents
|
||||
network.remove_agent("worker-1")
|
||||
|
||||
# List agents
|
||||
agents = network.list_agents()
|
||||
|
||||
# Get agent status
|
||||
status = network.get_status("worker-1")
|
||||
```
|
||||
|
||||
### Router
|
||||
|
||||
Route requests to appropriate agents:
|
||||
|
||||
```python
|
||||
from hanzo_network.core import Router, RoutingStrategy
|
||||
|
||||
# Create router
|
||||
router = Router(strategy=RoutingStrategy.ROUND_ROBIN)
|
||||
|
||||
# Route request
|
||||
agent = router.route("Process this task")
|
||||
|
||||
# Available strategies
|
||||
RoutingStrategy.ROUND_ROBIN # Cycle through agents
|
||||
RoutingStrategy.LEAST_LOADED # Pick agent with lowest load
|
||||
RoutingStrategy.CAPABILITY_MATCH # Match task to capabilities
|
||||
RoutingStrategy.RANDOM # Random selection
|
||||
```
|
||||
|
||||
## Topology
|
||||
|
||||
### Device Capabilities
|
||||
|
||||
Track and match device capabilities:
|
||||
|
||||
```python
|
||||
from hanzo_network.topology import DeviceCapabilities
|
||||
|
||||
# Define capabilities
|
||||
caps = DeviceCapabilities(
|
||||
memory_gb=32,
|
||||
gpu_memory_gb=24,
|
||||
cpu_cores=16,
|
||||
gpu_available=True,
|
||||
gpu_model="RTX 4090",
|
||||
)
|
||||
|
||||
# Check if capable
|
||||
can_run = caps.can_handle(
|
||||
min_memory=16,
|
||||
requires_gpu=True,
|
||||
)
|
||||
```
|
||||
|
||||
### Partitioning Strategies
|
||||
|
||||
Distribute work across the network:
|
||||
|
||||
```python
|
||||
from hanzo_network.topology import (
|
||||
RingMemoryWeightedPartitioningStrategy,
|
||||
PartitioningStrategy,
|
||||
)
|
||||
|
||||
# Memory-weighted ring partitioning
|
||||
strategy = RingMemoryWeightedPartitioningStrategy()
|
||||
|
||||
# Partition data
|
||||
partitions = strategy.partition(
|
||||
data=large_dataset,
|
||||
agents=network.list_agents(),
|
||||
)
|
||||
|
||||
# Process partitions
|
||||
for agent_id, partition in partitions.items():
|
||||
await network.send(agent_id, partition)
|
||||
```
|
||||
|
||||
## Local LLM
|
||||
|
||||
Run models locally for development:
|
||||
|
||||
```python
|
||||
from hanzo_network.llm import LocalLLM
|
||||
|
||||
# Create local LLM
|
||||
llm = LocalLLM(
|
||||
model_path="/path/to/model",
|
||||
context_size=4096,
|
||||
)
|
||||
|
||||
# Generate response
|
||||
response = await llm.generate(
|
||||
prompt="Explain quantum computing",
|
||||
max_tokens=500,
|
||||
)
|
||||
```
|
||||
|
||||
## Tools
|
||||
|
||||
### Memory Tool
|
||||
|
||||
Shared memory across the network:
|
||||
|
||||
```python
|
||||
from hanzo_network.tools import MemoryTool
|
||||
|
||||
memory = MemoryTool(network)
|
||||
|
||||
# Store data
|
||||
await memory.store("key", {"data": "value"})
|
||||
|
||||
# Retrieve data
|
||||
data = await memory.retrieve("key")
|
||||
|
||||
# Search
|
||||
results = await memory.search("query")
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Distributed Demo
|
||||
|
||||
```python
|
||||
from hanzo_network.core import AgentNetwork, NetworkConfig
|
||||
from hanzo_network.topology import DeviceCapabilities
|
||||
|
||||
async def main():
|
||||
# Create network
|
||||
network = AgentNetwork(NetworkConfig(name="distributed"))
|
||||
|
||||
# Add workers with capabilities
|
||||
for i in range(4):
|
||||
caps = DeviceCapabilities(
|
||||
memory_gb=16 + i * 8,
|
||||
gpu_available=i % 2 == 0,
|
||||
)
|
||||
network.add_agent(f"worker-{i}", capabilities=caps)
|
||||
|
||||
# Distribute task
|
||||
task = "Process large dataset"
|
||||
results = await network.broadcast(task)
|
||||
|
||||
# Aggregate results
|
||||
final = aggregate(results)
|
||||
return final
|
||||
```
|
||||
|
||||
### Local LLM Demo
|
||||
|
||||
```python
|
||||
from hanzo_network.llm import LocalLLM
|
||||
|
||||
async def main():
|
||||
# Setup local model
|
||||
llm = LocalLLM(model_path="./models/llama-7b")
|
||||
|
||||
# Development queries
|
||||
response = await llm.generate("Write a Python function to sort a list")
|
||||
print(response)
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `HANZO_NETWORK_TIMEOUT` | `30` | Request timeout in seconds |
|
||||
| `HANZO_NETWORK_RETRIES` | `3` | Max retry attempts |
|
||||
| `HANZO_NETWORK_LOG_LEVEL` | `INFO` | Logging level |
|
||||
|
||||
### Network Config
|
||||
|
||||
```python
|
||||
NetworkConfig(
|
||||
name="my-network", # Network identifier
|
||||
max_agents=100, # Maximum agents
|
||||
timeout=30.0, # Request timeout
|
||||
retry_count=3, # Retry attempts
|
||||
health_check_interval=60, # Health check frequency
|
||||
load_balancing=True, # Enable load balancing
|
||||
)
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Agent Network │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ Router │ │ Topology │ │
|
||||
│ │ │ │ Manager │ │
|
||||
│ └────────┬────────┘ └────────┬────────┘ │
|
||||
│ │ │ │
|
||||
│ ┌────────▼────────────────────▼────────┐ │
|
||||
│ │ Partitioning Strategy │ │
|
||||
│ └──────────────────┬───────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────────▼───────────────────┐ │
|
||||
│ │ Agent Pool │ │
|
||||
│ │ ┌────────┐ ┌────────┐ ┌────────┐ │ │
|
||||
│ │ │Agent 1 │ │Agent 2 │ │Agent N │ │ │
|
||||
│ │ └────────┘ └────────┘ └────────┘ │ │
|
||||
│ └──────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Capability Matching**: Define accurate device capabilities for optimal routing
|
||||
2. **Health Checks**: Enable health checks to detect failed agents
|
||||
3. **Retry Logic**: Configure retries for transient failures
|
||||
4. **Load Balancing**: Use load-aware routing for production
|
||||
5. **Local Development**: Use LocalLLM for testing without network overhead
|
||||
@@ -0,0 +1,321 @@
|
||||
# hanzo-repl
|
||||
|
||||
Interactive REPL (Read-Eval-Print Loop) for Hanzo AI.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install hanzo-repl
|
||||
```
|
||||
|
||||
## Overview
|
||||
|
||||
hanzo-repl provides an interactive command-line interface for AI agents with:
|
||||
|
||||
- **Multiple Backends** - IPython, Textual, and standard REPL
|
||||
- **Voice Mode** - Speech-to-text input
|
||||
- **Command Palette** - Quick access to commands
|
||||
- **Command Suggestions** - Context-aware suggestions
|
||||
- **LLM Integration** - Direct AI assistant access
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Start the REPL
|
||||
hanzo-repl
|
||||
|
||||
# Or with Python
|
||||
python -m hanzo_repl
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### Standard REPL
|
||||
|
||||
```python
|
||||
from hanzo_repl import REPL
|
||||
|
||||
# Create and run REPL
|
||||
repl = REPL()
|
||||
repl.run()
|
||||
```
|
||||
|
||||
### IPython Backend
|
||||
|
||||
Enhanced REPL with IPython features:
|
||||
|
||||
```python
|
||||
from hanzo_repl import IPythonREPL
|
||||
|
||||
repl = IPythonREPL()
|
||||
repl.run()
|
||||
```
|
||||
|
||||
Features:
|
||||
- Tab completion
|
||||
- Syntax highlighting
|
||||
- Magic commands
|
||||
- History persistence
|
||||
|
||||
### Textual Backend
|
||||
|
||||
Modern TUI (Text User Interface) REPL:
|
||||
|
||||
```python
|
||||
from hanzo_repl import TextualREPL
|
||||
|
||||
repl = TextualREPL()
|
||||
repl.run()
|
||||
```
|
||||
|
||||
Features:
|
||||
- Rich UI components
|
||||
- Multiple panes
|
||||
- Mouse support
|
||||
- Keyboard shortcuts
|
||||
|
||||
## Voice Mode
|
||||
|
||||
Enable voice input:
|
||||
|
||||
```python
|
||||
from hanzo_repl import REPL, VoiceMode
|
||||
|
||||
repl = REPL()
|
||||
voice = VoiceMode()
|
||||
|
||||
# Enable voice
|
||||
repl.enable_voice(voice)
|
||||
|
||||
# Start listening
|
||||
repl.run()
|
||||
```
|
||||
|
||||
### Voice Commands
|
||||
|
||||
| Command | Action |
|
||||
|---------|--------|
|
||||
| "Hey Hanzo" | Activate voice input |
|
||||
| "Stop" | Cancel current input |
|
||||
| "Execute" | Run current command |
|
||||
| "Clear" | Clear screen |
|
||||
|
||||
## Command Palette
|
||||
|
||||
Quick access to common commands:
|
||||
|
||||
```python
|
||||
from hanzo_repl import CommandPalette
|
||||
|
||||
palette = CommandPalette()
|
||||
|
||||
# Add custom commands
|
||||
palette.add_command("build", "npm run build", category="dev")
|
||||
palette.add_command("test", "pytest", category="dev")
|
||||
|
||||
# Open palette (Ctrl+Shift+P)
|
||||
palette.show()
|
||||
```
|
||||
|
||||
### Default Commands
|
||||
|
||||
| Category | Commands |
|
||||
|----------|----------|
|
||||
| File | Open, Save, Close |
|
||||
| Edit | Cut, Copy, Paste, Undo |
|
||||
| View | Zoom In, Zoom Out, Toggle Panel |
|
||||
| Git | Status, Commit, Push, Pull |
|
||||
| Run | Execute, Debug, Profile |
|
||||
|
||||
## Command Suggestions
|
||||
|
||||
Context-aware suggestions:
|
||||
|
||||
```python
|
||||
from hanzo_repl import CommandSuggestions
|
||||
|
||||
suggestions = CommandSuggestions()
|
||||
|
||||
# Get suggestions based on context
|
||||
ctx = {"language": "python", "file": "main.py"}
|
||||
sugg = suggestions.get(ctx)
|
||||
|
||||
# Returns relevant commands like:
|
||||
# - python main.py
|
||||
# - pytest
|
||||
# - black main.py
|
||||
```
|
||||
|
||||
## LLM Integration
|
||||
|
||||
Direct AI assistant access:
|
||||
|
||||
```python
|
||||
from hanzo_repl import LLMClient
|
||||
|
||||
client = LLMClient()
|
||||
|
||||
# Ask the AI
|
||||
response = await client.ask("How do I sort a list in Python?")
|
||||
print(response)
|
||||
|
||||
# With context
|
||||
response = await client.ask(
|
||||
"Explain this code",
|
||||
context=code_snippet,
|
||||
)
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```python
|
||||
LLMClient(
|
||||
model="gpt-4",
|
||||
temperature=0.7,
|
||||
max_tokens=1000,
|
||||
)
|
||||
```
|
||||
|
||||
## CLI Options
|
||||
|
||||
```bash
|
||||
# Choose backend
|
||||
hanzo-repl --backend ipython
|
||||
hanzo-repl --backend textual
|
||||
hanzo-repl --backend standard
|
||||
|
||||
# Enable voice
|
||||
hanzo-repl --voice
|
||||
|
||||
# Set LLM model
|
||||
hanzo-repl --model claude-3
|
||||
|
||||
# Debug mode
|
||||
hanzo-repl --debug
|
||||
```
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
### Navigation
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Ctrl+C` | Cancel/interrupt |
|
||||
| `Ctrl+D` | Exit REPL |
|
||||
| `Ctrl+L` | Clear screen |
|
||||
| `Ctrl+R` | Search history |
|
||||
| `Tab` | Complete command |
|
||||
|
||||
### Editing
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Ctrl+A` | Beginning of line |
|
||||
| `Ctrl+E` | End of line |
|
||||
| `Ctrl+K` | Kill to end of line |
|
||||
| `Ctrl+U` | Kill to start of line |
|
||||
| `Ctrl+W` | Delete word backward |
|
||||
|
||||
### Command Palette
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Ctrl+Shift+P` | Open command palette |
|
||||
| `Ctrl+P` | Quick open file |
|
||||
| `Ctrl+Shift+F` | Search in files |
|
||||
|
||||
## Configuration
|
||||
|
||||
### Config File
|
||||
|
||||
Create `~/.hanzo/repl.yaml`:
|
||||
|
||||
```yaml
|
||||
backend: ipython
|
||||
voice:
|
||||
enabled: true
|
||||
wake_word: "hey hanzo"
|
||||
llm:
|
||||
model: claude-3
|
||||
temperature: 0.7
|
||||
theme: dark
|
||||
history:
|
||||
size: 10000
|
||||
file: ~/.hanzo/history
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `HANZO_REPL_BACKEND` | Default backend |
|
||||
| `HANZO_REPL_VOICE` | Enable voice (true/false) |
|
||||
| `HANZO_REPL_MODEL` | LLM model |
|
||||
| `HANZO_REPL_THEME` | Color theme |
|
||||
|
||||
## Custom Commands
|
||||
|
||||
Register custom commands:
|
||||
|
||||
```python
|
||||
from hanzo_repl import REPL, command
|
||||
|
||||
@command("hello")
|
||||
def hello_command(args):
|
||||
"""Say hello"""
|
||||
name = args.get("name", "World")
|
||||
print(f"Hello, {name}!")
|
||||
|
||||
repl = REPL()
|
||||
repl.register_command(hello_command)
|
||||
repl.run()
|
||||
```
|
||||
|
||||
## Plugins
|
||||
|
||||
Extend the REPL with plugins:
|
||||
|
||||
```python
|
||||
from hanzo_repl import Plugin, REPL
|
||||
|
||||
class MyPlugin(Plugin):
|
||||
name = "my-plugin"
|
||||
|
||||
def on_load(self, repl):
|
||||
print("Plugin loaded!")
|
||||
|
||||
def on_command(self, cmd):
|
||||
# Process commands
|
||||
pass
|
||||
|
||||
repl = REPL()
|
||||
repl.load_plugin(MyPlugin())
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### REPL Class
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `run()` | Start the REPL |
|
||||
| `eval(code)` | Evaluate code |
|
||||
| `register_command(cmd)` | Add custom command |
|
||||
| `enable_voice(mode)` | Enable voice input |
|
||||
| `load_plugin(plugin)` | Load a plugin |
|
||||
|
||||
### LLMClient Class
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `ask(prompt, context)` | Ask the AI |
|
||||
| `stream(prompt)` | Stream response |
|
||||
| `set_model(model)` | Change model |
|
||||
|
||||
### VoiceMode Class
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `start()` | Start listening |
|
||||
| `stop()` | Stop listening |
|
||||
| `set_wake_word(word)` | Set activation word |
|
||||
Reference in New Issue
Block a user