generated from coulomb/repo-seed
feat: WP-0003 — RoutingPolicy (FR-2) and HTTP serve mode (FR-1)
FR-2 RoutingPolicy: - RoutingPolicy + RoutingRule dataclasses in llm_connect/routing.py - resolve(task_type, estimated_cost_per_1k=None) with cost-cap fallback - Exported from llm_connect.__init__; contract doc at contracts/functional/routing-policy.md - 11 tests covering rule match, cost-cap, fallback, unknown type, no-match FR-1 HTTP serve mode: - LLMServer in llm_connect/server.py (stdlib http.server, zero extra deps) - POST /execute + GET /health; CLI via python -m llm_connect.server - [server] optional-dep group added to pyproject.toml - Contract doc at contracts/functional/server.md - 9 tests: health, round-trip, 400/404/500 errors, config forwarding - Added "mock" provider to factory for CLI default All 101 tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
53
contracts/functional/routing-policy.md
Normal file
53
contracts/functional/routing-policy.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Contract: RoutingPolicy
|
||||
|
||||
**layer:** Functional
|
||||
**maturity:** Beta
|
||||
**module:** `llm_connect.routing`
|
||||
**since:** WP-0003
|
||||
|
||||
## Purpose
|
||||
|
||||
Route logical task types to concrete `LLMAdapter` instances based on a
|
||||
prioritised rule list, with optional per-rule cost-cap fallback.
|
||||
|
||||
## Public surface
|
||||
|
||||
```python
|
||||
@dataclass
|
||||
class RoutingRule:
|
||||
task_type: str
|
||||
prefer: LLMAdapter
|
||||
max_cost_per_1k: Optional[float] = None # USD per 1 000 tokens
|
||||
fallback: Optional[LLMAdapter] = None
|
||||
|
||||
@dataclass
|
||||
class RoutingPolicy:
|
||||
rules: List[RoutingRule] = field(default_factory=list)
|
||||
default: Optional[LLMAdapter] = None
|
||||
|
||||
def resolve(
|
||||
self,
|
||||
task_type: str,
|
||||
estimated_cost_per_1k: Optional[float] = None,
|
||||
) -> LLMAdapter: ...
|
||||
```
|
||||
|
||||
## Invariants
|
||||
|
||||
1. Rules are evaluated in list order; the first rule whose `task_type` matches wins.
|
||||
2. When `estimated_cost_per_1k` is supplied and a matching rule has `max_cost_per_1k` set:
|
||||
- If `estimated_cost_per_1k > max_cost_per_1k` **and** `fallback is not None` → return `fallback`.
|
||||
- Otherwise → return `prefer` (no fallback configured or cost within cap).
|
||||
3. When no rule matches and `default is not None` → return `default`.
|
||||
4. When no rule matches and `default is None` → raise `LookupError`.
|
||||
5. `resolve()` never mutates policy state.
|
||||
|
||||
## Error contract
|
||||
|
||||
| Condition | Exception |
|
||||
|-----------|-----------|
|
||||
| No matching rule, no default | `LookupError` |
|
||||
|
||||
## Known consumers
|
||||
|
||||
- `inter-hub` (IHUB-WP-0012 Phase 11): uses `RoutingPolicy` to select federation adapters per task class.
|
||||
Reference in New Issue
Block a user