clef-router 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ environment: pypi
11
+ permissions:
12
+ id-token: write
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: astral-sh/setup-uv@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: uv build
19
+ - run: uv publish
@@ -0,0 +1,62 @@
1
+ Metadata-Version: 2.5
2
+ Name: clef-router
3
+ Version: 0.1.0
4
+ Summary: Route prompts between cheap and frontier LLMs using Cloudflare's Clef decision model.
5
+ Author: Youssef Ouhaghi Ahmian
6
+ License: Apache-2.0
7
+ Keywords: ai,clef,cloudflare,cost-optimization,decision-model,llm,routing
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: httpx>=0.25
10
+ Provides-Extra: dev
11
+ Requires-Dist: pytest>=7; extra == 'dev'
12
+ Description-Content-Type: text/markdown
13
+
14
+ # clef-router
15
+
16
+ Route prompts between cheap and frontier LLMs using Cloudflare's [Clef](https://blog.cloudflare.com/clef-decision-models/) decision model.
17
+
18
+ ## Quick start
19
+
20
+ ```bash
21
+ pip install clef-router
22
+ export CLEF_ACCOUNT_ID=your_cloudflare_account_id
23
+ export CLEF_API_TOKEN=your_cloudflare_api_token
24
+ ```
25
+
26
+ ```python
27
+ from clef_router import ClefRouter
28
+
29
+ router = ClefRouter()
30
+ result = router.route("What is the capital of France?")
31
+ print(result.tier) # "cheap"
32
+ print(result.reason) # "classified as simple, confidence 0.90"
33
+
34
+ result = router.route("Design a distributed consensus algorithm")
35
+ print(result.tier) # "frontier"
36
+ ```
37
+
38
+ ## How it works
39
+
40
+ ```
41
+ prompt → Clef decision model (Cloudflare Workers AI) → tier
42
+ ├─ simple → cheap model
43
+ ├─ standard → cheap model
44
+ ├─ complex → frontier model
45
+ └─ uncertain → frontier (confidence gate)
46
+ ```
47
+
48
+ ## clef vs laya
49
+
50
+ | | laya | Clef |
51
+ |---|---|---|
52
+ | Latency | 5.8ms | 38.8ms (flash) / 209.3ms (full) |
53
+ | Quality (BFCL) | 38.13 | 98.76 |
54
+ | Context | 32k | 64k |
55
+ | Hosting | local CPU | Cloudflare API |
56
+ | Cost | $0 | Workers AI pricing |
57
+
58
+ Use [laya-router](https://github.com/Gjusev/laya-router) for sub-10ms local routing. Use clef-router when quality matters more than latency.
59
+
60
+ ## License
61
+
62
+ Apache 2.0
@@ -0,0 +1,49 @@
1
+ # clef-router
2
+
3
+ Route prompts between cheap and frontier LLMs using Cloudflare's [Clef](https://blog.cloudflare.com/clef-decision-models/) decision model.
4
+
5
+ ## Quick start
6
+
7
+ ```bash
8
+ pip install clef-router
9
+ export CLEF_ACCOUNT_ID=your_cloudflare_account_id
10
+ export CLEF_API_TOKEN=your_cloudflare_api_token
11
+ ```
12
+
13
+ ```python
14
+ from clef_router import ClefRouter
15
+
16
+ router = ClefRouter()
17
+ result = router.route("What is the capital of France?")
18
+ print(result.tier) # "cheap"
19
+ print(result.reason) # "classified as simple, confidence 0.90"
20
+
21
+ result = router.route("Design a distributed consensus algorithm")
22
+ print(result.tier) # "frontier"
23
+ ```
24
+
25
+ ## How it works
26
+
27
+ ```
28
+ prompt → Clef decision model (Cloudflare Workers AI) → tier
29
+ ├─ simple → cheap model
30
+ ├─ standard → cheap model
31
+ ├─ complex → frontier model
32
+ └─ uncertain → frontier (confidence gate)
33
+ ```
34
+
35
+ ## clef vs laya
36
+
37
+ | | laya | Clef |
38
+ |---|---|---|
39
+ | Latency | 5.8ms | 38.8ms (flash) / 209.3ms (full) |
40
+ | Quality (BFCL) | 38.13 | 98.76 |
41
+ | Context | 32k | 64k |
42
+ | Hosting | local CPU | Cloudflare API |
43
+ | Cost | $0 | Workers AI pricing |
44
+
45
+ Use [laya-router](https://github.com/Gjusev/laya-router) for sub-10ms local routing. Use clef-router when quality matters more than latency.
46
+
47
+ ## License
48
+
49
+ Apache 2.0
@@ -0,0 +1,23 @@
1
+ [project]
2
+ name = "clef-router"
3
+ version = "0.1.0"
4
+ description = "Route prompts between cheap and frontier LLMs using Cloudflare's Clef decision model."
5
+ readme = "README.md"
6
+ license = { text = "Apache-2.0" }
7
+ requires-python = ">=3.10"
8
+ authors = [{ name = "Youssef Ouhaghi Ahmian" }]
9
+ keywords = ["llm", "routing", "ai", "clef", "cloudflare", "decision-model", "cost-optimization"]
10
+ dependencies = ["httpx>=0.25"]
11
+
12
+ [project.scripts]
13
+ clef-route = "clef_router.cli:main"
14
+
15
+ [project.optional-dependencies]
16
+ dev = ["pytest>=7"]
17
+
18
+ [build-system]
19
+ requires = ["hatchling"]
20
+ build-backend = "hatchling.build"
21
+
22
+ [tool.hatch.build.targets.wheel]
23
+ packages = ["src/clef_router"]
@@ -0,0 +1,93 @@
1
+ """clef-router: Route prompts between cheap and frontier LLMs using Cloudflare's Clef."""
2
+
3
+ import os
4
+ from dataclasses import dataclass, field
5
+ from typing import Optional
6
+
7
+ import httpx
8
+
9
+
10
+ @dataclass
11
+ class RouteResult:
12
+ tier: str
13
+ complexity: str
14
+ confidence: float
15
+ reason: str
16
+ raw_response: dict = field(default_factory=dict, repr=False)
17
+
18
+
19
+ @dataclass
20
+ class ClefRouter:
21
+ account_id: str = field(default_factory=lambda: os.environ.get("CLEF_ACCOUNT_ID", ""))
22
+ api_token: str = field(default_factory=lambda: os.environ.get("CLEF_API_TOKEN", ""))
23
+ model: str = "@cf/cloudflare/clef-flash"
24
+ base_url: str = "https://api.cloudflare.com/client/v4"
25
+ min_confidence: float = 0.45
26
+ timeout: float = 30.0
27
+
28
+ def __post_init__(self):
29
+ if not self.account_id:
30
+ raise ValueError("Set CLEF_ACCOUNT_ID env var or pass account_id")
31
+ if not self.api_token:
32
+ raise ValueError("Set CLEF_API_TOKEN env var or pass api_token")
33
+
34
+ @property
35
+ def _endpoint(self) -> str:
36
+ return f"{self.base_url}/accounts/{self.account_id}/ai/run/{self.model}"
37
+
38
+ def _headers(self) -> dict:
39
+ return {"Authorization": f"Bearer {self.api_token}", "Content-Type": "application/json"}
40
+
41
+ def route(self, prompt: str, context: Optional[str] = None) -> RouteResult:
42
+ state = f"User prompt to classify:\n{prompt}"
43
+ if context:
44
+ state = f"Context: {context}\n\n{state}"
45
+
46
+ payload = {
47
+ "state": state,
48
+ "questions": {
49
+ "complexity": {
50
+ "type": "choice",
51
+ "context": "How computationally complex is this prompt? "
52
+ "simple = greeting, translation, basic lookup. "
53
+ "standard = summarization, rewording, simple analysis. "
54
+ "complex = reasoning, coding, multi-step, creative.",
55
+ "choices": ["simple", "standard", "complex"],
56
+ },
57
+ "confidence": {
58
+ "type": "score",
59
+ "context": "How confident are you in this classification?",
60
+ "levels": ["very_low", "low", "medium", "high", "very_high"],
61
+ },
62
+ },
63
+ }
64
+
65
+ resp = httpx.post(
66
+ self._endpoint, json=payload, headers=self._headers(), timeout=self.timeout,
67
+ )
68
+ resp.raise_for_status()
69
+ data = resp.json()
70
+
71
+ result = data.get("result", {})
72
+ complexity = result.get("complexity", "complex")
73
+ conf_map = {"very_low": 0.1, "low": 0.3, "medium": 0.5, "high": 0.7, "very_high": 0.9}
74
+ confidence = conf_map.get(result.get("confidence", "low"), 0.3)
75
+
76
+ if confidence < self.min_confidence:
77
+ tier = "frontier"
78
+ reason = f"confidence {confidence:.2f} below threshold {self.min_confidence}, escalated"
79
+ elif complexity == "complex":
80
+ tier = "frontier"
81
+ reason = f"classified as {complexity}"
82
+ else:
83
+ tier = "cheap"
84
+ reason = f"classified as {complexity}, confidence {confidence:.2f}"
85
+
86
+ return RouteResult(
87
+ tier=tier, complexity=complexity, confidence=confidence,
88
+ reason=reason, raw_response=data,
89
+ )
90
+
91
+
92
+ __version__ = "0.1.0"
93
+ __all__ = ["ClefRouter", "RouteResult"]
@@ -0,0 +1,34 @@
1
+ """CLI for clef-router."""
2
+
3
+ import argparse
4
+ import json
5
+
6
+ from . import ClefRouter
7
+
8
+
9
+ def main():
10
+ p = argparse.ArgumentParser(prog="clef-route", description="Route a prompt using Clef")
11
+ p.add_argument("prompt", help="The prompt to classify")
12
+ p.add_argument("--context", "-c", default=None)
13
+ p.add_argument("--json", action="store_true")
14
+ args = p.parse_args()
15
+
16
+ router = ClefRouter()
17
+ result = router.route(args.prompt, context=args.context)
18
+
19
+ if args.json:
20
+ print(json.dumps({
21
+ "tier": result.tier,
22
+ "complexity": result.complexity,
23
+ "confidence": result.confidence,
24
+ "reason": result.reason,
25
+ }, indent=2))
26
+ else:
27
+ print(f"tier: {result.tier}")
28
+ print(f"complexity: {result.complexity}")
29
+ print(f"confidence: {result.confidence:.2f}")
30
+ print(f"reason: {result.reason}")
31
+
32
+
33
+ if __name__ == "__main__":
34
+ main()