fairbench-ai 0.3.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.
Files changed (37) hide show
  1. fairbench_ai-0.3.0/LICENSE +99 -0
  2. fairbench_ai-0.3.0/MANIFEST.in +3 -0
  3. fairbench_ai-0.3.0/PKG-INFO +65 -0
  4. fairbench_ai-0.3.0/README.md +35 -0
  5. fairbench_ai-0.3.0/fairbench/__init__.py +4 -0
  6. fairbench_ai-0.3.0/fairbench/backend.py +211 -0
  7. fairbench_ai-0.3.0/fairbench/benchmarks/__init__.py +0 -0
  8. fairbench_ai-0.3.0/fairbench/benchmarks/swebench/__init__.py +0 -0
  9. fairbench_ai-0.3.0/fairbench/cli.py +377 -0
  10. fairbench_ai-0.3.0/fairbench/config.py +106 -0
  11. fairbench_ai-0.3.0/fairbench/data/__init__.py +102 -0
  12. fairbench_ai-0.3.0/fairbench/engine.py +270 -0
  13. fairbench_ai-0.3.0/fairbench/quality.py +165 -0
  14. fairbench_ai-0.3.0/fairbench/registry.py +87 -0
  15. fairbench_ai-0.3.0/fairbench/reporter.py +152 -0
  16. fairbench_ai-0.3.0/fairbench/scripts/__init__.py +0 -0
  17. fairbench_ai-0.3.0/fairbench/swebench.py +512 -0
  18. fairbench_ai-0.3.0/fairbench/tests/__init__.py +0 -0
  19. fairbench_ai-0.3.0/fairbench/tests/benchmarks/__init__.py +0 -0
  20. fairbench_ai-0.3.0/fairbench/tests/benchmarks/swebench/__init__.py +0 -0
  21. fairbench_ai-0.3.0/fairbench/tests/test_swebench.py +327 -0
  22. fairbench_ai-0.3.0/fairbench/types.py +125 -0
  23. fairbench_ai-0.3.0/fairbench_ai.egg-info/PKG-INFO +65 -0
  24. fairbench_ai-0.3.0/fairbench_ai.egg-info/SOURCES.txt +35 -0
  25. fairbench_ai-0.3.0/fairbench_ai.egg-info/dependency_links.txt +1 -0
  26. fairbench_ai-0.3.0/fairbench_ai.egg-info/entry_points.txt +2 -0
  27. fairbench_ai-0.3.0/fairbench_ai.egg-info/requires.txt +18 -0
  28. fairbench_ai-0.3.0/fairbench_ai.egg-info/top_level.txt +1 -0
  29. fairbench_ai-0.3.0/pyproject.toml +51 -0
  30. fairbench_ai-0.3.0/setup.cfg +4 -0
  31. fairbench_ai-0.3.0/setup.py +46 -0
  32. fairbench_ai-0.3.0/tests/test_backend.py +51 -0
  33. fairbench_ai-0.3.0/tests/test_cli.py +29 -0
  34. fairbench_ai-0.3.0/tests/test_engine.py +88 -0
  35. fairbench_ai-0.3.0/tests/test_quality.py +86 -0
  36. fairbench_ai-0.3.0/tests/test_registry.py +53 -0
  37. fairbench_ai-0.3.0/tests/test_reporter.py +158 -0
@@ -0,0 +1,99 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity.
18
+
19
+ "You" (or "Your") shall mean an individual or Legal Entity
20
+ exercising permissions granted by this License.
21
+
22
+ "Source" form shall mean the preferred form for making modifications,
23
+ including but not limited to software source code, documentation
24
+ source, and configuration files.
25
+
26
+ "Object" form shall mean any form resulting from mechanical
27
+ transformation or translation of a Source form, including but
28
+ not limited to compiled object code, generated documentation,
29
+ and conversions to other media types.
30
+
31
+ "Work" shall mean the work of authorship, whether in Source or
32
+ Object form, made available under the License, as indicated by a
33
+ copyright notice that is included in or attached to the work.
34
+
35
+ "Derivative Works" shall mean any work, whether in Source or Object
36
+ form, that is based on (or derived from) the Work and for which the
37
+ revisions are patentable; regardless of whether the work is made
38
+ available under the License.
39
+
40
+ "Contribution" shall mean any Work of authorship that is submitted
41
+ by a Contributor.
42
+
43
+ "Contributor" shall mean any individual or entity that creates or
44
+ contributes to the Work.
45
+
46
+ "Submission" shall mean any original work of authorship that is
47
+ submitted to the Work for inclusion in the Work.
48
+
49
+ 2. Grant of Copyright License. Subject to the terms and conditions of
50
+ this License, each Contributor hereby grants to You a perpetual,
51
+ worldwide, non-exclusive, sublicensable, royalty-free, irrevocable
52
+ copyright license to reproduce, prepare Derivative Works of,
53
+ publicly display, publicly perform, sublicense, and distribute the
54
+ Work and Derivative Works thereof.
55
+
56
+ 3. Grant of Patent License. Subject to the terms and conditions of
57
+ this License, each Contributor hereby grants to You a perpetual,
58
+ worldwide, non-exclusive, sublicensable, royalty-free, irrevocable
59
+ patent license to make, have made, use, offer to sell, sell, import,
60
+ and otherwise transfer the Work.
61
+
62
+ 4. Redistribution. You may reproduce and distribute copies of the
63
+ Work or Derivative Works thereof in any medium, with or without
64
+ modifications, provided that you meet the following conditions:
65
+
66
+ (a) You must give any other recipients of the Work or
67
+ Derivative Works a copy of this License; and
68
+
69
+ (b) You must cause any modified files to carry prominent notices
70
+ stating that You changed the files; and
71
+
72
+ (c) You must retain, in the Source form of any Derivative Works
73
+ that You distribute, all copyright, patent, trademark, and
74
+ attribution notices from the Source form of the Work, excluding
75
+ those notices that do not pertain to any part of the Derivative
76
+ Works; and
77
+
78
+ (d) If the Work includes a "NOTICE" text file as part of its
79
+ distribution, then any Derivative Works that You distribute must
80
+ include a readable copy of the attribution notices contained
81
+ within such NOTICE file, excluding any notices that do not
82
+ pertain to any part of the Derivative Works.
83
+
84
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
85
+ any Contribution submitted is under this License.
86
+
87
+ 6. Trademarks. This License does not grant permission to use the trade
88
+ names, trademarks, service marks, or product names of the Licensor.
89
+
90
+ 7. Disclaimer of Warranty. Unless required by applicable law or
91
+ agreed to in writing, the Work is provided on an "AS IS" BASIS,
92
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
93
+ implied.
94
+
95
+ 8. Limitation of Liability. In no event shall the Licensor be liable
96
+ for any damages arising from use of the Work.
97
+
98
+ 9. Acceptance. By using, copying, modifying, or distributing the Work,
99
+ You accept this License.
@@ -0,0 +1,3 @@
1
+ include LICENSE
2
+ include README.md
3
+ recursive-include fairbench/tests *.py
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: fairbench-ai
3
+ Version: 0.3.0
4
+ Summary: FairBench - AI model benchmarking suite with SWE-bench integration
5
+ Home-page: https://github.com/AlessandroBernini/fairbench
6
+ Author: Alessandro Bernini
7
+ Author-email: alessandro@mair.it
8
+ License: Apache-2.0
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: click>=8.1
12
+ Requires-Dist: pyyaml>=6.0
13
+ Requires-Dist: requests>=2.31
14
+ Requires-Dist: psutil>=5.9
15
+ Provides-Extra: ml
16
+ Requires-Dist: lm-eval>=0.4; extra == "ml"
17
+ Requires-Dist: llama-cpp-python>=0.2; extra == "ml"
18
+ Provides-Extra: swebench
19
+ Requires-Dist: swebench>=2.0; extra == "swebench"
20
+ Requires-Dist: datasets>=2.14; extra == "swebench"
21
+ Requires-Dist: rich>=13.0; extra == "swebench"
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.0; extra == "dev"
24
+ Requires-Dist: ruff>=0.1; extra == "dev"
25
+ Requires-Dist: mypy>=1.0; extra == "dev"
26
+ Dynamic: author
27
+ Dynamic: author-email
28
+ Dynamic: home-page
29
+ Dynamic: requires-python
30
+
31
+ # FairBench
32
+
33
+ AI model benchmarking suite with SWE-bench integration.
34
+
35
+ ## Quick Start
36
+
37
+ ```bash
38
+ pip install fair-bench
39
+ fairbench run -m model.gguf
40
+ ```
41
+
42
+ ## Benchmarks
43
+
44
+ - **Quality**: MMLU, HellaSwag, GSM8K, HumanEval, IFEval, TruthfulQA, ARC-Challenge, LiveBench
45
+ - **Speed**: TTFT, TPOT, throughput (llama-cpp-python)
46
+ - **Memory**: VRAM peak, RAM peak
47
+ - **SWE-bench**: GitHub issue resolution capability
48
+
49
+ ## Configuration
50
+
51
+ Edit `~/.fairbench/config.yaml`:
52
+
53
+ ```yaml
54
+ api_url: https://fairbench.vercel.app/api
55
+ default_n_ctx: 4096
56
+ default_n_gpu_layers: -1
57
+ default_quant: q4_k_m
58
+ default_threads: 0
59
+ publish: true
60
+ results_dir: /home/jarvispi/.fairbench/results
61
+ ```
62
+
63
+ ## Publishing
64
+
65
+ By default, every benchmark run is **automatically published** to the public leaderboard. Set `publish: false` to disable.
@@ -0,0 +1,35 @@
1
+ # FairBench
2
+
3
+ AI model benchmarking suite with SWE-bench integration.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ pip install fair-bench
9
+ fairbench run -m model.gguf
10
+ ```
11
+
12
+ ## Benchmarks
13
+
14
+ - **Quality**: MMLU, HellaSwag, GSM8K, HumanEval, IFEval, TruthfulQA, ARC-Challenge, LiveBench
15
+ - **Speed**: TTFT, TPOT, throughput (llama-cpp-python)
16
+ - **Memory**: VRAM peak, RAM peak
17
+ - **SWE-bench**: GitHub issue resolution capability
18
+
19
+ ## Configuration
20
+
21
+ Edit `~/.fairbench/config.yaml`:
22
+
23
+ ```yaml
24
+ api_url: https://fairbench.vercel.app/api
25
+ default_n_ctx: 4096
26
+ default_n_gpu_layers: -1
27
+ default_quant: q4_k_m
28
+ default_threads: 0
29
+ publish: true
30
+ results_dir: /home/jarvispi/.fairbench/results
31
+ ```
32
+
33
+ ## Publishing
34
+
35
+ By default, every benchmark run is **automatically published** to the public leaderboard. Set `publish: false` to disable.
@@ -0,0 +1,4 @@
1
+ """FairBench - AI model benchmarking suite with SWE-bench integration."""
2
+
3
+ __version__ = "0.3.0"
4
+ __all__ = ["backend", "cli", "config", "data", "engine", "quality", "reporter"]
@@ -0,0 +1,211 @@
1
+ """Speed and memory benchmarking for AI models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import subprocess
7
+ import time
8
+
9
+ import psutil
10
+
11
+ from fairbench.types import MemoryResult, SpeedResult
12
+
13
+
14
+ def benchmark_speed(
15
+ model_path: str,
16
+ prompt: str = "The quick brown fox jumps over the lazy dog. " * 10,
17
+ n_ctx: int = 4096,
18
+ n_gpu_layers: int = -1,
19
+ n_threads: int = 0,
20
+ runs: int = 3,
21
+ ) -> SpeedResult:
22
+ """Measure TTFT, TPOT, and throughput using llama-cpp-python bindings.
23
+
24
+ Falls back to llama-bench CLI if bindings unavailable.
25
+ """
26
+ try:
27
+ from llama_cpp import Llama as _Llama # type: ignore
28
+ except ImportError:
29
+ return _benchmark_with_llama_bench(model_path, prompt, runs)
30
+
31
+ return _benchmark_with_llama_cpp(
32
+ model_path, prompt, n_ctx, n_gpu_layers, n_threads, runs, _Llama
33
+ )
34
+
35
+
36
+ def _benchmark_with_llama_cpp(
37
+ model_path: str,
38
+ prompt: str,
39
+ n_ctx: int,
40
+ n_gpu_layers: int,
41
+ n_threads: int,
42
+ runs: int,
43
+ Llama: type, # type: ignore[type-arg]
44
+ ) -> SpeedResult:
45
+ """Benchmark using llama-cpp-python directly."""
46
+ ttfts: list[float] = []
47
+ tpots: list[float] = []
48
+ throughputs: list[float] = []
49
+
50
+ for i in range(runs):
51
+ try:
52
+ llm = Llama( # type: ignore[no-untyped-call]
53
+ model_path=model_path,
54
+ n_ctx=n_ctx,
55
+ n_gpu_layers=n_gpu_layers,
56
+ n_threads=n_threads if n_threads > 0 else None,
57
+ verbose=False,
58
+ )
59
+
60
+ start = time.time()
61
+ response = llm.create_completion(
62
+ prompt=prompt,
63
+ max_tokens=512,
64
+ temperature=0.7,
65
+ stream=True,
66
+ )
67
+
68
+ ttft = time.time() - start
69
+ ttfts.append(ttft * 1000) # ms
70
+
71
+ token_count = 0
72
+ last_time = time.time()
73
+ for chunk in response:
74
+ if time.time() - last_time > 0.01:
75
+ elapsed = time.time() - last_time
76
+ tpots.append((token_count / elapsed) if elapsed > 0 else 0)
77
+ token_count = 0
78
+ last_time = time.time()
79
+ token_count += 1
80
+
81
+ total_time = time.time() - start
82
+ throughput = token_count / total_time if total_time > 0 else 0
83
+ throughputs.append(throughput)
84
+
85
+ llm.close()
86
+ except (OSError, RuntimeError) as e:
87
+ print(f" Run {i + 1} failed: {e}")
88
+
89
+ return SpeedResult(
90
+ ttft_avg=sum(ttfts) / len(ttfts) if ttfts else 0.0,
91
+ tpot_avg=sum(tpots) / len(tpots) if tpots else 0.0,
92
+ throughput_avg=sum(throughputs) / len(throughputs) if throughputs else 0.0,
93
+ runs=len(ttfts),
94
+ )
95
+
96
+
97
+ def _benchmark_with_llama_bench(model_path: str, prompt: str, runs: int) -> SpeedResult:
98
+ """Fallback: use llama-bench CLI tool."""
99
+ try:
100
+ cmd = [
101
+ "llama-bench",
102
+ "-m",
103
+ model_path,
104
+ "-n",
105
+ "512",
106
+ "-ngl",
107
+ "0",
108
+ "-p",
109
+ str(len(prompt.split())),
110
+ "-t",
111
+ "0",
112
+ "-r",
113
+ str(runs),
114
+ ]
115
+ result = subprocess.run(cmd, check=False, capture_output=True, text=True, timeout=300)
116
+ # Parse output - llama-bench format varies by version
117
+ output = result.stdout
118
+ return SpeedResult(runs=runs, metadata={"raw_output": output})
119
+ except (FileNotFoundError, subprocess.TimeoutExpired) as e:
120
+ return SpeedResult(runs=runs, metadata={"error": str(e)})
121
+
122
+
123
+ def benchmark_memory(
124
+ model_path: str,
125
+ prompt: str = "The quick brown fox jumps over the lazy dog. " * 10,
126
+ n_ctx: int = 4096,
127
+ n_gpu_layers: int = -1,
128
+ n_threads: int = 0,
129
+ ) -> MemoryResult:
130
+ """Measure VRAM and RAM peak usage during inference."""
131
+ try:
132
+ from llama_cpp import Llama as _Llama # type: ignore
133
+ except ImportError:
134
+ return MemoryResult(metadata={"reason": "llama-cpp-python not installed"})
135
+
136
+ return _measure_memory_llama_cpp(
137
+ model_path,
138
+ prompt,
139
+ n_ctx,
140
+ n_gpu_layers,
141
+ n_threads,
142
+ _Llama, # type: ignore[arg-type]
143
+ )
144
+
145
+
146
+ def _measure_memory_llama_cpp(
147
+ model_path: str,
148
+ prompt: str,
149
+ n_ctx: int,
150
+ n_gpu_layers: int,
151
+ n_threads: int,
152
+ Llama: type, # type: ignore[type-arg]
153
+ ) -> MemoryResult:
154
+ """Measure memory using llama-cpp-python with peak tracking."""
155
+ vram_samples: list[float] = []
156
+ ram_samples: list[float] = []
157
+
158
+ try:
159
+ # Get initial memory state
160
+ initial_ram = psutil.Process().memory_info().rss
161
+
162
+ llm = Llama( # type: ignore[no-untyped-call]
163
+ model_path=model_path,
164
+ n_ctx=n_ctx,
165
+ n_gpu_layers=n_gpu_layers,
166
+ n_threads=n_threads if n_threads > 0 else None,
167
+ verbose=False,
168
+ )
169
+
170
+ # Measure VRAM via nvidia-smi if available
171
+ if os.path.exists("/usr/bin/nvidia-smi"):
172
+ result = subprocess.run(
173
+ [
174
+ "nvidia-smi",
175
+ "--query-gpu=memory.used",
176
+ "--format=csv,noheader,nounits",
177
+ ],
178
+ check=False,
179
+ capture_output=True,
180
+ text=True,
181
+ )
182
+ if result.returncode == 0:
183
+ vram_samples = [
184
+ float(line.strip())
185
+ for line in result.stdout.strip().split("\n")
186
+ if line.strip()
187
+ ]
188
+
189
+ # Run inference
190
+ llm.create_completion(
191
+ prompt=prompt,
192
+ max_tokens=256,
193
+ temperature=0.7,
194
+ )
195
+
196
+ # Peak RAM
197
+ current_ram = psutil.Process().memory_info().rss
198
+ ram_peak = (current_ram - initial_ram) / (1024 * 1024) # MB
199
+ ram_samples.append(ram_peak)
200
+
201
+ llm.close()
202
+
203
+ return MemoryResult(
204
+ vram_peak_mb=sum(vram_samples) / len(vram_samples) if vram_samples else 0.0,
205
+ ram_peak_mb=ram_peak,
206
+ vram_avg_mb=sum(vram_samples) / len(vram_samples) if vram_samples else 0.0,
207
+ ram_avg_mb=sum(ram_samples) / len(ram_samples) if ram_samples else 0.0,
208
+ metadata={"model_size_gb": os.path.getsize(model_path) / (1024**3)},
209
+ )
210
+ except (OSError, RuntimeError) as e:
211
+ return MemoryResult(metadata={"error": str(e)})
File without changes