tryaii 0.3.0__py3-none-any.whl

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.
Files changed (41) hide show
  1. tryaii/__init__.py +69 -0
  2. tryaii/async_client.py +488 -0
  3. tryaii/benchmarks/__init__.py +4 -0
  4. tryaii/benchmarks/registry.py +193 -0
  5. tryaii/benchmarks/standard.py +105 -0
  6. tryaii/budget.py +592 -0
  7. tryaii/cache/__init__.py +3 -0
  8. tryaii/cache/lru.py +76 -0
  9. tryaii/centroids/__init__.py +4 -0
  10. tryaii/centroids/data/centroids_all-MiniLM-L6-v2.json +1 -0
  11. tryaii/centroids/data/training_queries.json +246 -0
  12. tryaii/centroids/generator.py +214 -0
  13. tryaii/centroids/loader.py +214 -0
  14. tryaii/classifiers/__init__.py +8 -0
  15. tryaii/classifiers/base.py +80 -0
  16. tryaii/classifiers/embedding.py +290 -0
  17. tryaii/cli/__init__.py +0 -0
  18. tryaii/cli/banner.py +162 -0
  19. tryaii/cli/main.py +780 -0
  20. tryaii/client.py +207 -0
  21. tryaii/config.py +105 -0
  22. tryaii/embeddings/__init__.py +9 -0
  23. tryaii/embeddings/base.py +54 -0
  24. tryaii/embeddings/local.py +83 -0
  25. tryaii/embeddings/openai_provider.py +83 -0
  26. tryaii/integrations/__init__.py +3 -0
  27. tryaii/integrations/openrouter.py +441 -0
  28. tryaii/registry/__init__.py +3 -0
  29. tryaii/registry/models.py +252 -0
  30. tryaii/registry/presets/__init__.py +0 -0
  31. tryaii/registry/presets/default_models.json +932 -0
  32. tryaii/router.py +283 -0
  33. tryaii/scoring/__init__.py +11 -0
  34. tryaii/scoring/benchmarks.py +82 -0
  35. tryaii/scoring/engine.py +284 -0
  36. tryaii/scoring/priorities.py +93 -0
  37. tryaii-0.3.0.dist-info/METADATA +186 -0
  38. tryaii-0.3.0.dist-info/RECORD +41 -0
  39. tryaii-0.3.0.dist-info/WHEEL +4 -0
  40. tryaii-0.3.0.dist-info/entry_points.txt +2 -0
  41. tryaii-0.3.0.dist-info/licenses/LICENSE +190 -0
@@ -0,0 +1,193 @@
1
+ """
2
+ Extensible benchmark registry.
3
+
4
+ Allows users to register custom benchmarks with their own training queries
5
+ and normalization ranges. Designed for high connectivity with external
6
+ benchmark-creation tools.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ import os
13
+ import tempfile
14
+ from dataclasses import dataclass, field
15
+ from pathlib import Path
16
+ from typing import Optional
17
+
18
+ from tryaii.scoring.benchmarks import BenchmarkNormalizer, NormalizationRange
19
+
20
+
21
+ @dataclass
22
+ class BenchmarkDefinition:
23
+ """
24
+ Complete definition of a benchmark.
25
+
26
+ Contains everything needed to integrate a new benchmark
27
+ into the routing system.
28
+ """
29
+
30
+ name: str
31
+ description: str
32
+ training_queries: list[str]
33
+ normalization: NormalizationRange
34
+ broad_category: str = "TECHNICAL"
35
+ subcategories: list[str] = field(default_factory=list)
36
+ metadata: dict = field(default_factory=dict)
37
+
38
+ def to_dict(self) -> dict:
39
+ return {
40
+ "name": self.name,
41
+ "description": self.description,
42
+ "training_queries": self.training_queries,
43
+ "normalization": {
44
+ "min_score": self.normalization.min_score,
45
+ "max_score": self.normalization.max_score,
46
+ },
47
+ "broad_category": self.broad_category,
48
+ "subcategories": self.subcategories,
49
+ "metadata": self.metadata,
50
+ }
51
+
52
+ @classmethod
53
+ def from_dict(cls, d: dict) -> BenchmarkDefinition:
54
+ norm = d.get("normalization", {})
55
+ return cls(
56
+ name=d["name"],
57
+ description=d.get("description", ""),
58
+ training_queries=d.get("training_queries", []),
59
+ normalization=NormalizationRange(
60
+ min_score=norm.get("min_score", 0),
61
+ max_score=norm.get("max_score", 100),
62
+ ),
63
+ broad_category=d.get("broad_category", "TECHNICAL"),
64
+ subcategories=d.get("subcategories", []),
65
+ metadata=d.get("metadata", {}),
66
+ )
67
+
68
+
69
+ class BenchmarkRegistry:
70
+ """
71
+ Registry for benchmark definitions.
72
+
73
+ Provides a clean interface for:
74
+ - Registering custom benchmarks
75
+ - Loading benchmarks from JSON files (for tool connectivity)
76
+ - Exporting benchmark definitions
77
+ - Integrating with the centroid generator and scoring engine
78
+
79
+ Usage:
80
+ registry = BenchmarkRegistry.default() # Standard 12 benchmarks
81
+
82
+ # Add a custom benchmark
83
+ registry.register(BenchmarkDefinition(
84
+ name="CustomerSupportQA",
85
+ description="Customer support query handling quality",
86
+ training_queries=[
87
+ "How do I reset my password?",
88
+ "I want to cancel my subscription",
89
+ "Where is my order?",
90
+ ...
91
+ ],
92
+ normalization=NormalizationRange(0, 100),
93
+ broad_category="CONVERSATIONAL",
94
+ ))
95
+
96
+ # Load from external tool output
97
+ registry.load_from_file("my_benchmarks.json")
98
+ """
99
+
100
+ def __init__(self):
101
+ self._benchmarks: dict[str, BenchmarkDefinition] = {}
102
+
103
+ @classmethod
104
+ def default(cls) -> BenchmarkRegistry:
105
+ """Create registry with the standard 12 benchmarks."""
106
+ from tryaii.benchmarks.standard import STANDARD_BENCHMARKS
107
+
108
+ registry = cls()
109
+ for benchmark in STANDARD_BENCHMARKS:
110
+ registry._benchmarks[benchmark.name] = benchmark
111
+ return registry
112
+
113
+ def register(self, benchmark: BenchmarkDefinition) -> None:
114
+ """Register a new benchmark or update an existing one."""
115
+ self._benchmarks[benchmark.name] = benchmark
116
+
117
+ def unregister(self, name: str) -> bool:
118
+ """Remove a benchmark. Returns True if it existed."""
119
+ return self._benchmarks.pop(name, None) is not None
120
+
121
+ def get(self, name: str) -> Optional[BenchmarkDefinition]:
122
+ """Get a benchmark by name."""
123
+ return self._benchmarks.get(name)
124
+
125
+ @property
126
+ def names(self) -> list[str]:
127
+ """All registered benchmark names."""
128
+ return list(self._benchmarks.keys())
129
+
130
+ @property
131
+ def all_benchmarks(self) -> list[BenchmarkDefinition]:
132
+ """All registered benchmarks."""
133
+ return list(self._benchmarks.values())
134
+
135
+ def get_training_queries(self) -> dict[str, list[str]]:
136
+ """Get all training queries grouped by benchmark name."""
137
+ return {
138
+ name: b.training_queries
139
+ for name, b in self._benchmarks.items()
140
+ if b.training_queries
141
+ }
142
+
143
+ def get_normalizer(self) -> BenchmarkNormalizer:
144
+ """Create a BenchmarkNormalizer from all registered benchmarks."""
145
+ normalizer = BenchmarkNormalizer()
146
+ for name, benchmark in self._benchmarks.items():
147
+ normalizer.register_range(
148
+ name,
149
+ benchmark.normalization.min_score,
150
+ benchmark.normalization.max_score,
151
+ benchmark.description,
152
+ )
153
+ return normalizer
154
+
155
+ def load_from_file(self, path: str | Path) -> int:
156
+ """
157
+ Load benchmarks from a JSON file.
158
+
159
+ Returns:
160
+ Number of benchmarks loaded.
161
+ """
162
+ with open(path) as f:
163
+ data = json.load(f)
164
+
165
+ count = 0
166
+ for item in data.get("benchmarks", []):
167
+ benchmark = BenchmarkDefinition.from_dict(item)
168
+ self.register(benchmark)
169
+ count += 1
170
+
171
+ return count
172
+
173
+ def export_to_file(self, path: str | Path) -> None:
174
+ """Export all benchmarks to a JSON file."""
175
+ path = Path(path)
176
+ data = {
177
+ "benchmarks": [b.to_dict() for b in self._benchmarks.values()]
178
+ }
179
+ # Write to temp file then atomically rename
180
+ fd, tmp_path = tempfile.mkstemp(dir=path.parent, suffix=".tmp")
181
+ try:
182
+ with os.fdopen(fd, "w") as f:
183
+ json.dump(data, f, indent=2)
184
+ os.replace(tmp_path, path)
185
+ except BaseException:
186
+ os.unlink(tmp_path)
187
+ raise
188
+
189
+ def __len__(self) -> int:
190
+ return len(self._benchmarks)
191
+
192
+ def __contains__(self, name: str) -> bool:
193
+ return name in self._benchmarks
@@ -0,0 +1,105 @@
1
+ """
2
+ Standard benchmark definitions -- the 12 benchmarks shipped with TryAii-DRE.
3
+ """
4
+
5
+ from tryaii.benchmarks.registry import BenchmarkDefinition
6
+ from tryaii.scoring.benchmarks import NormalizationRange
7
+
8
+ STANDARD_BENCHMARKS: list[BenchmarkDefinition] = [
9
+ BenchmarkDefinition(
10
+ name="MMLU",
11
+ description="Academic knowledge across 57 subjects",
12
+ training_queries=[], # Loaded from training_queries.json at runtime
13
+ normalization=NormalizationRange(25, 95),
14
+ broad_category="EDUCATIONAL",
15
+ subcategories=["ACADEMIC_INSTRUCTION", "RESEARCH_METHODOLOGY"],
16
+ ),
17
+ BenchmarkDefinition(
18
+ name="HellaSwag",
19
+ description="Commonsense reasoning about everyday situations",
20
+ training_queries=[],
21
+ normalization=NormalizationRange(50, 98),
22
+ broad_category="CONVERSATIONAL",
23
+ subcategories=["PERSONAL_ADVICE"],
24
+ ),
25
+ BenchmarkDefinition(
26
+ name="HumanEval",
27
+ description="Code generation and programming tasks",
28
+ training_queries=[],
29
+ normalization=NormalizationRange(20, 95),
30
+ broad_category="TECHNICAL",
31
+ subcategories=["CODE_TECHNICAL"],
32
+ ),
33
+ BenchmarkDefinition(
34
+ name="SWE-bench",
35
+ description="Real-world software engineering and debugging",
36
+ training_queries=[],
37
+ normalization=NormalizationRange(5, 85),
38
+ broad_category="TECHNICAL",
39
+ subcategories=["CODE_TECHNICAL", "DATA_SCIENCE"],
40
+ ),
41
+ BenchmarkDefinition(
42
+ name="TruthfulQA",
43
+ description="Truthful and accurate question answering",
44
+ training_queries=[],
45
+ normalization=NormalizationRange(20, 85),
46
+ broad_category="CONVERSATIONAL",
47
+ subcategories=["PERSONAL_ADVICE"],
48
+ ),
49
+ BenchmarkDefinition(
50
+ name="ARC",
51
+ description="Science exam questions requiring reasoning",
52
+ training_queries=[],
53
+ normalization=NormalizationRange(0, 95),
54
+ broad_category="EDUCATIONAL",
55
+ subcategories=["ACADEMIC_INSTRUCTION", "STUDY_ASSISTANCE"],
56
+ ),
57
+ BenchmarkDefinition(
58
+ name="GSM8K",
59
+ description="Grade school math word problems",
60
+ training_queries=[],
61
+ normalization=NormalizationRange(20, 98),
62
+ broad_category="TECHNICAL",
63
+ subcategories=["MATHEMATICAL_SCIENTIFIC"],
64
+ ),
65
+ BenchmarkDefinition(
66
+ name="DROP",
67
+ description="Reading comprehension requiring arithmetic and reasoning",
68
+ training_queries=[],
69
+ normalization=NormalizationRange(30, 90),
70
+ broad_category="TECHNICAL",
71
+ subcategories=["MATHEMATICAL_SCIENTIFIC", "DATA_SCIENCE"],
72
+ ),
73
+ BenchmarkDefinition(
74
+ name="SuperGLUE",
75
+ description="Natural language understanding tasks",
76
+ training_queries=[],
77
+ normalization=NormalizationRange(40, 95),
78
+ broad_category="BUSINESS",
79
+ subcategories=["PROFESSIONAL_COMMUNICATION"],
80
+ ),
81
+ BenchmarkDefinition(
82
+ name="Chatbot Arena (LMSys)",
83
+ description="Human-rated conversational quality",
84
+ training_queries=[],
85
+ normalization=NormalizationRange(1000, 1550),
86
+ broad_category="CONVERSATIONAL",
87
+ subcategories=["PERSONAL_ADVICE", "RECOMMENDATIONS"],
88
+ ),
89
+ BenchmarkDefinition(
90
+ name="MT-Bench",
91
+ description="Multi-turn conversation and instruction following",
92
+ training_queries=[],
93
+ normalization=NormalizationRange(5, 10),
94
+ broad_category="CREATIVE",
95
+ subcategories=["WRITING_LITERARY"],
96
+ ),
97
+ BenchmarkDefinition(
98
+ name="LiveBench",
99
+ description="Fresh, contamination-resistant evaluation tasks",
100
+ training_queries=[],
101
+ normalization=NormalizationRange(0, 100),
102
+ broad_category="TECHNICAL",
103
+ subcategories=["CODE_TECHNICAL", "MATHEMATICAL_SCIENTIFIC"],
104
+ ),
105
+ ]