cre-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.
- cre_router-0.1.0/.gitignore +36 -0
- cre_router-0.1.0/DEVELOP.md +26 -0
- cre_router-0.1.0/LICENSE +202 -0
- cre_router-0.1.0/PKG-INFO +97 -0
- cre_router-0.1.0/PYPI.md +46 -0
- cre_router-0.1.0/README.md +251 -0
- cre_router-0.1.0/REPRODUCE.md +174 -0
- cre_router-0.1.0/configs/aime_stats.json +14 -0
- cre_router-0.1.0/configs/teleqna_stats.json +10 -0
- cre_router-0.1.0/data/download.py +40 -0
- cre_router-0.1.0/img/system.svg +72 -0
- cre_router-0.1.0/pyproject.toml +64 -0
- cre_router-0.1.0/requirements-paper.txt +26 -0
- cre_router-0.1.0/src/cre_router/__init__.py +16 -0
- cre_router-0.1.0/src/cre_router/artifacts.py +47 -0
- cre_router-0.1.0/src/cre_router/cli.py +300 -0
- cre_router-0.1.0/src/cre_router/clustering.py +81 -0
- cre_router-0.1.0/src/cre_router/evaluate.py +355 -0
- cre_router-0.1.0/src/cre_router/qe/__init__.py +3 -0
- cre_router-0.1.0/src/cre_router/qe/classifier.py +96 -0
- cre_router-0.1.0/src/cre_router/qe/evaluate.py +120 -0
- cre_router-0.1.0/src/cre_router/qe/train.py +199 -0
- cre_router-0.1.0/src/cre_router/routing.py +279 -0
- cre_router-0.1.0/src/cre_router/server/__init__.py +3 -0
- cre_router-0.1.0/src/cre_router/server/app.py +188 -0
- cre_router-0.1.0/src/cre_router/server/cascade_router.py +291 -0
- cre_router-0.1.0/src/cre_router/server/example_config_aime24.yaml +43 -0
- cre_router-0.1.0/src/cre_router/server/example_config_teleqna.yaml +51 -0
- cre_router-0.1.0/tests/test_cascade.py +289 -0
- cre_router-0.1.0/tests/test_clustering.py +53 -0
- cre_router-0.1.0/tests/test_evaluate.py +166 -0
- cre_router-0.1.0/tests/test_integration.py +61 -0
- cre_router-0.1.0/tests/test_metrics.py +54 -0
- cre_router-0.1.0/tests/test_qe_eval.py +49 -0
- cre_router-0.1.0/tests/test_routing.py +135 -0
- cre_router-0.1.0/tests/test_serve_app.py +97 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
|
|
10
|
+
# Secrets
|
|
11
|
+
.env
|
|
12
|
+
.env.*
|
|
13
|
+
|
|
14
|
+
# Tooling
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.ipynb_checkpoints/
|
|
18
|
+
|
|
19
|
+
# Experiment outputs
|
|
20
|
+
artifacts/
|
|
21
|
+
logs/
|
|
22
|
+
results/
|
|
23
|
+
*.log
|
|
24
|
+
|
|
25
|
+
# Downloaded datasets (fetch with data/download.py; not redistributed here)
|
|
26
|
+
data/*.jsonl
|
|
27
|
+
|
|
28
|
+
# Model training outputs (e.g. cre qe-train --output-dir qe-aime)
|
|
29
|
+
qe-*/
|
|
30
|
+
*.safetensors
|
|
31
|
+
*.pt
|
|
32
|
+
|
|
33
|
+
# OS / editors
|
|
34
|
+
.DS_Store
|
|
35
|
+
.idea/
|
|
36
|
+
.vscode/
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
Local setup for working on the package and running its tests.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git clone https://github.com/ymoslem/CRE-Router
|
|
7
|
+
cd CRE-Router
|
|
8
|
+
pip install -e ".[qe,serve,dev]"
|
|
9
|
+
pytest
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The `dev` extra adds the test dependencies (`pytest`, plus `fastapi` and
|
|
13
|
+
`httpx` for the serve smoke test); `qe` and `serve` bring the runtime the
|
|
14
|
+
tests exercise.
|
|
15
|
+
|
|
16
|
+
The default `pytest` run is CPU-only and needs no model weights. Two smoke
|
|
17
|
+
tests that require real resources are marked `integration` and skipped unless
|
|
18
|
+
you point them at a GPU/server via environment variables, e.g.:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# QE classifier load + predict
|
|
22
|
+
CRE_TEST_QE_CHECKPOINT=ymoslem/ModernBERT-base-AIME-1983-2023-instruct-qe-classifier-binary-10ep-lr5e-05 \
|
|
23
|
+
pytest -m integration
|
|
24
|
+
# vLLM measurement (needs a running `vllm serve <model>`)
|
|
25
|
+
CRE_TEST_VLLM_MODEL=WeiboAI/VibeThinker-1.5B pytest -m integration
|
|
26
|
+
```
|
cre_router-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cre-router
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Cluster, Route, Escalate: a cascaded framework for cost-aware LLM serving
|
|
5
|
+
Project-URL: Homepage, https://github.com/ymoslem/CRE-Router
|
|
6
|
+
Project-URL: Repository, https://github.com/ymoslem/CRE-Router
|
|
7
|
+
Project-URL: Issues, https://github.com/ymoslem/CRE-Router/issues
|
|
8
|
+
Author: Yasmin Moslem
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cascades,litellm,llm,model-serving,quality-estimation,routing,vllm
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: anyio>=4.0
|
|
18
|
+
Requires-Dist: numpy>=1.26
|
|
19
|
+
Requires-Dist: pyyaml>=6.0
|
|
20
|
+
Requires-Dist: scikit-learn>=1.4
|
|
21
|
+
Requires-Dist: sentence-transformers>=3.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: fastapi>=0.115; extra == 'dev'
|
|
24
|
+
Requires-Dist: httpx>=0.27; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
26
|
+
Provides-Extra: eval
|
|
27
|
+
Requires-Dist: vllm>=0.19; extra == 'eval'
|
|
28
|
+
Provides-Extra: full
|
|
29
|
+
Requires-Dist: accelerate>=1.0; extra == 'full'
|
|
30
|
+
Requires-Dist: datasets>=3.0; extra == 'full'
|
|
31
|
+
Requires-Dist: fastapi>=0.115; extra == 'full'
|
|
32
|
+
Requires-Dist: httpx>=0.27; extra == 'full'
|
|
33
|
+
Requires-Dist: litellm>=1.60; extra == 'full'
|
|
34
|
+
Requires-Dist: torch>=2.4; extra == 'full'
|
|
35
|
+
Requires-Dist: transformers>=4.57; extra == 'full'
|
|
36
|
+
Requires-Dist: uvicorn>=0.30; extra == 'full'
|
|
37
|
+
Requires-Dist: vllm>=0.19; extra == 'full'
|
|
38
|
+
Provides-Extra: qe
|
|
39
|
+
Requires-Dist: accelerate>=1.0; extra == 'qe'
|
|
40
|
+
Requires-Dist: datasets>=3.0; extra == 'qe'
|
|
41
|
+
Requires-Dist: torch>=2.4; extra == 'qe'
|
|
42
|
+
Requires-Dist: transformers>=4.57; extra == 'qe'
|
|
43
|
+
Provides-Extra: serve
|
|
44
|
+
Requires-Dist: fastapi>=0.115; extra == 'serve'
|
|
45
|
+
Requires-Dist: httpx>=0.27; extra == 'serve'
|
|
46
|
+
Requires-Dist: litellm>=1.60; extra == 'serve'
|
|
47
|
+
Requires-Dist: torch>=2.4; extra == 'serve'
|
|
48
|
+
Requires-Dist: transformers>=4.57; extra == 'serve'
|
|
49
|
+
Requires-Dist: uvicorn>=0.30; extra == 'serve'
|
|
50
|
+
Description-Content-Type: text/markdown
|
|
51
|
+
|
|
52
|
+
# CRE-Router
|
|
53
|
+
|
|
54
|
+
Implementation of the paper [Cluster, Route, Escalate: Cascaded Framework for Cost-Aware LLM Serving](https://arxiv.org/abs/2606.27457).
|
|
55
|
+
|
|
56
|
+
Production LLM serving trades accuracy against cost. CRE-Router routes each
|
|
57
|
+
query to the most cost-effective model in a pool, then escalates low-quality
|
|
58
|
+
outputs to a stronger model:
|
|
59
|
+
|
|
60
|
+
- **Stage 1 (clustering-based routing).** Queries are embedded and clustered
|
|
61
|
+
offline; each cluster is routed to the model that minimizes a cost-adjusted
|
|
62
|
+
error score (Error + lambda * Cost), with lambda tuned once to satisfy a
|
|
63
|
+
latency (TPOT) budget.
|
|
64
|
+
- **Stage 2 (quality-estimation cascade).** A lightweight ModernBERT
|
|
65
|
+
classifier inspects each efficient-model output and escalates low-quality
|
|
66
|
+
answers up an ordered ladder of stronger models.
|
|
67
|
+
|
|
68
|
+
Both stages train only on task-correctness labels obtainable from standard
|
|
69
|
+
benchmark evaluation; no extra annotation is required.
|
|
70
|
+
|
|
71
|
+
## Install
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install "cre-router[full]"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`full` installs the whole pipeline on one machine. Narrower installs are
|
|
78
|
+
available through the `serve`, `qe`, and `eval` extras; see the
|
|
79
|
+
[installation guide](https://github.com/ymoslem/CRE-Router#installation).
|
|
80
|
+
|
|
81
|
+
## Usage
|
|
82
|
+
|
|
83
|
+
The workflow is driven by the `cre` CLI, one stage per step:
|
|
84
|
+
|
|
85
|
+
`cre cluster` → `cre evaluate` → `cre fit` → `cre qe-train` → `cre serve`
|
|
86
|
+
|
|
87
|
+
Run `cre <stage> --help` for options. Runnable end-to-end quickstarts (a
|
|
88
|
+
no-GPU routing-table demo and a full serving walkthrough) are in the
|
|
89
|
+
[README](https://github.com/ymoslem/CRE-Router#readme).
|
|
90
|
+
|
|
91
|
+
## Links
|
|
92
|
+
|
|
93
|
+
- **Source and documentation:** https://github.com/ymoslem/CRE-Router
|
|
94
|
+
- **Paper:** https://arxiv.org/abs/2606.27457
|
|
95
|
+
- **Reproducing the paper:** https://github.com/ymoslem/CRE-Router/blob/main/REPRODUCE.md
|
|
96
|
+
|
|
97
|
+
Apache-2.0 licensed.
|
cre_router-0.1.0/PYPI.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# CRE-Router
|
|
2
|
+
|
|
3
|
+
Implementation of the paper [Cluster, Route, Escalate: Cascaded Framework for Cost-Aware LLM Serving](https://arxiv.org/abs/2606.27457).
|
|
4
|
+
|
|
5
|
+
Production LLM serving trades accuracy against cost. CRE-Router routes each
|
|
6
|
+
query to the most cost-effective model in a pool, then escalates low-quality
|
|
7
|
+
outputs to a stronger model:
|
|
8
|
+
|
|
9
|
+
- **Stage 1 (clustering-based routing).** Queries are embedded and clustered
|
|
10
|
+
offline; each cluster is routed to the model that minimizes a cost-adjusted
|
|
11
|
+
error score (Error + lambda * Cost), with lambda tuned once to satisfy a
|
|
12
|
+
latency (TPOT) budget.
|
|
13
|
+
- **Stage 2 (quality-estimation cascade).** A lightweight ModernBERT
|
|
14
|
+
classifier inspects each efficient-model output and escalates low-quality
|
|
15
|
+
answers up an ordered ladder of stronger models.
|
|
16
|
+
|
|
17
|
+
Both stages train only on task-correctness labels obtainable from standard
|
|
18
|
+
benchmark evaluation; no extra annotation is required.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install "cre-router[full]"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`full` installs the whole pipeline on one machine. Narrower installs are
|
|
27
|
+
available through the `serve`, `qe`, and `eval` extras; see the
|
|
28
|
+
[installation guide](https://github.com/ymoslem/CRE-Router#installation).
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
The workflow is driven by the `cre` CLI, one stage per step:
|
|
33
|
+
|
|
34
|
+
`cre cluster` → `cre evaluate` → `cre fit` → `cre qe-train` → `cre serve`
|
|
35
|
+
|
|
36
|
+
Run `cre <stage> --help` for options. Runnable end-to-end quickstarts (a
|
|
37
|
+
no-GPU routing-table demo and a full serving walkthrough) are in the
|
|
38
|
+
[README](https://github.com/ymoslem/CRE-Router#readme).
|
|
39
|
+
|
|
40
|
+
## Links
|
|
41
|
+
|
|
42
|
+
- **Source and documentation:** https://github.com/ymoslem/CRE-Router
|
|
43
|
+
- **Paper:** https://arxiv.org/abs/2606.27457
|
|
44
|
+
- **Reproducing the paper:** https://github.com/ymoslem/CRE-Router/blob/main/REPRODUCE.md
|
|
45
|
+
|
|
46
|
+
Apache-2.0 licensed.
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# CRE-Router
|
|
2
|
+
|
|
3
|
+
Implementation of the paper, [**Cluster, Route, Escalate: Cascaded Framework for Cost-Aware LLM Serving**](https://arxiv.org/abs/2606.27457).
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## System overview
|
|
7
|
+
|
|
8
|
+
Production deployment of large language models forces a trade-off between
|
|
9
|
+
accuracy and cost. This framework routes each query to the most
|
|
10
|
+
cost-effective model in a pool, then escalates low-quality outputs to a
|
|
11
|
+
stronger model:
|
|
12
|
+
|
|
13
|
+
- **Stage 1 (clustering-based routing).** Queries are embedded and
|
|
14
|
+
clustered offline; each cluster is assigned to the model minimizing
|
|
15
|
+
`Error(m, c) + lambda * Cost_norm(m)`, where `lambda` ($\lambda$, the cost weight) is
|
|
16
|
+
tuned once to `lambda*` ($\lambda^*$) to satisfy a Time Per Output Token (TPOT) budget.
|
|
17
|
+
- **Stage 2 (quality-estimation cascade).** A lightweight classifier
|
|
18
|
+
inspects each efficient-model output and escalates low-quality answers to
|
|
19
|
+
a stronger model. With more than two models, escalation follows an ordered
|
|
20
|
+
ladder (weakest to strongest, following the $\lambda$ table): each model has
|
|
21
|
+
its own classifier and the router rolls up to the next stronger model until
|
|
22
|
+
an output is accepted or the top is reached.
|
|
23
|
+
|
|
24
|
+
Both stages train only on task-correctness labels obtainable from standard
|
|
25
|
+
benchmark evaluation; no extra annotation is required.
|
|
26
|
+
|
|
27
|
+
<p align="center"><img src="img/system.svg" alt="Two-stage cascaded routing system" width="640"></p>
|
|
28
|
+
|
|
29
|
+
## Pipeline
|
|
30
|
+
|
|
31
|
+
The full workflow is driven by the `cre` CLI, one stage per step:
|
|
32
|
+
|
|
33
|
+
`cre cluster` → `cre evaluate` → `cre fit` → `cre qe-train` → `cre serve`
|
|
34
|
+
|
|
35
|
+
Serving (`cre serve`) switches between the live vLLM backends through [LiteLLM](https://github.com/BerriAI/litellm).
|
|
36
|
+
|
|
37
|
+
| Stage | What it does | Input | Output | Key options |
|
|
38
|
+
|---|---|---|---|---|
|
|
39
|
+
| `cre cluster` | Embeds training queries and fits k-means centroids (k chosen by Silhouette) | JSONL of training queries | `centroids.npy` and `router.json`; `train_assignments.jsonl` | `--k`, `--embedding-model` |
|
|
40
|
+
| `cre evaluate` | Runs each model per cluster through vLLM's benchmark, scores answers, averages per-cluster error and TPOT. This is the slowest stage; cost scales with model size, output length, and `--runs`, and it runs once per model. | dataset JSONL, a running vLLM server, fitted centroids | per-model entry in the stats JSON; raw runs under `results/` | `--runs`, `--port`, `--concurrency` |
|
|
41
|
+
| `cre fit` | Pareto-prunes the pool, sweeps $\lambda$, selects $\lambda^*$ under the TPOT budget | stats JSON, budget B | routing table and $\lambda^*$ in `router.json` | `--budget` (required), `--output` |
|
|
42
|
+
| `cre qe-train` | Fine-tunes ModernBERT-base as the accept/escalate QE classifier | HF dataset of model outputs with correctness labels | QE classifier checkpoint | `--learning-rate`, `--max-length`, `--attn-implementation` |
|
|
43
|
+
| `cre serve` | Runs the live router: sends each incoming query to its cluster's assigned model, and escalates weak answers to a stronger model | serving config, running backends | live HTTP router on port 4000 | `--config`, `--port` |
|
|
44
|
+
|
|
45
|
+
Full flags for any stage: `cre <stage> --help`.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install "cre-router[full]"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This is the whole pipeline on one machine: clustering and routing, the
|
|
54
|
+
cascade router, QE classifier training/evaluation, and vLLM for measurement
|
|
55
|
+
and for hosting backend models. If you want a narrower install, pick from the
|
|
56
|
+
extras below.
|
|
57
|
+
|
|
58
|
+
| Extra | Adds | For |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| (core) | numpy, scikit-learn, sentence-transformers, pyyaml, anyio | `cre cluster`, `cre fit` — always installed |
|
|
61
|
+
| `serve` | + litellm, fastapi, uvicorn, httpx, torch, transformers | `cre serve` — the Stage 1 + Stage 2 cascade router (loads ModernBERT in-process) |
|
|
62
|
+
| `qe` | + torch, transformers, datasets, accelerate | `cre qe-train`, `cre qe-eval` — train and evaluate the QE classifier |
|
|
63
|
+
| `eval` | + vllm | `cre evaluate` — per-cluster measurement; also provides `vllm serve` for backends |
|
|
64
|
+
| `full` | qe + serve + eval | the whole pipeline on one machine |
|
|
65
|
+
|
|
66
|
+
The vLLM backends the router talks to are separate processes started with
|
|
67
|
+
`vllm serve <model>` (cf.
|
|
68
|
+
[Quickstart: serve CRE-Router](#quickstart-serve-cre-router-gpu-required)); a
|
|
69
|
+
`serve`-only host still needs vLLM installed wherever those backends run.
|
|
70
|
+
|
|
71
|
+
Efficient QE training also needs [FlashAttention](https://github.com/Dao-AILab/flash-attention)
|
|
72
|
+
(`flash-attn`), installed as a second step once torch is already present
|
|
73
|
+
(e.g. after `pip install "cre-router[qe]"`):
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install flash-attn --no-build-isolation
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
(the paper used `flash-attn==2.8.3`). The flag matters: without it, pip's
|
|
80
|
+
isolated build environment can't see your installed torch/CUDA, so the build
|
|
81
|
+
targets the wrong version. Without flash-attn at all, pass
|
|
82
|
+
`cre qe-train --attn-implementation sdpa` to fall back.
|
|
83
|
+
|
|
84
|
+
## Quickstart: routing table (no GPU)
|
|
85
|
+
|
|
86
|
+
A standalone, zero-setup demo of the routing math itself, no serving and no
|
|
87
|
+
GPU involved. Running it reproduces the paper's routing table and $\lambda^*$
|
|
88
|
+
selection directly from the checked-in stats, so you can see how Stage 1
|
|
89
|
+
decides which model handles which cluster before setting up any backends.
|
|
90
|
+
It is *not* a prerequisite for the end-to-end GPU-based serving,
|
|
91
|
+
which fits its own routing table as one of its steps (cf.
|
|
92
|
+
[Quickstart: serve CRE-Router](#quickstart-serve-cre-router-gpu-required)).
|
|
93
|
+
The per-cluster
|
|
94
|
+
stats measured in the paper are checked in under
|
|
95
|
+
[`configs/`](configs), so the routing table and budgeted $\lambda^*$ reproduce
|
|
96
|
+
without any GPU:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
cre fit --stats configs/aime_stats.json --budget 20
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This prints the Pareto analysis, the $\lambda$ sweep (routing regions), and the
|
|
103
|
+
$\lambda^*$ selection. To regenerate the stats from scratch (clustering plus
|
|
104
|
+
per-model measurement on a GPU), run `cre cluster` and `cre evaluate` on your
|
|
105
|
+
own dataset and models, the same commands used for the paper (see the
|
|
106
|
+
[Pipeline](#pipeline) table above). If you want to reproduce the paper's exact
|
|
107
|
+
numbers with its datasets and models, see [REPRODUCE.md](REPRODUCE.md) instead.
|
|
108
|
+
|
|
109
|
+
## Quickstart: serve CRE-Router (GPU required)
|
|
110
|
+
|
|
111
|
+
This walks through standing up the live router end to end, using the paper's
|
|
112
|
+
AIME pool as a concrete, runnable example. Swap in your own models, dataset,
|
|
113
|
+
and config the same way once you see the shape of it.
|
|
114
|
+
|
|
115
|
+
1. Start one vLLM server per pool model. `--max-model-len` must cover input +
|
|
116
|
+
the task's generation length (40,960 for AIME), or long outputs truncate:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
vllm serve WeiboAI/VibeThinker-1.5B --port 8001 --max-model-len 42000
|
|
120
|
+
vllm serve Qwen/Qwen3-30B-A3B-Thinking-2507-FP8 --port 8002 --max-model-len 42000
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
2. Fit centroids and write the routing table into an artifacts directory.
|
|
124
|
+
Reusing the checked-in stats skips the GPU measurement step:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
python data/download.py --dataset ymoslem/AIME-clustered --split train --output data/aime_train.jsonl
|
|
128
|
+
cre cluster --input data/aime_train.jsonl --embeddings-field embeddings --output artifacts/aime
|
|
129
|
+
cre fit --stats configs/aime_stats.json --budget 20 --output artifacts/aime
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
3. Write a serving config. It carries only deployment wiring — the model pool
|
|
133
|
+
(each model's endpoint) and the QE classifier checkpoints. The routing
|
|
134
|
+
table, $\lambda^*$, and the escalation ladder are read from the artifacts and
|
|
135
|
+
the arithmetic, never set by hand. Point
|
|
136
|
+
[`example_config_aime24.yaml`](src/cre_router/server/example_config_aime24.yaml)
|
|
137
|
+
at your backends and serve (a TeleQnA config,
|
|
138
|
+
[`example_config_teleqna.yaml`](src/cre_router/server/example_config_teleqna.yaml),
|
|
139
|
+
is also provided):
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
cre serve --config example_config_aime24.yaml
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
4. Send a standard chat-completions request:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
curl http://localhost:4000/v1/chat/completions \
|
|
149
|
+
-H "Content-Type: application/json" \
|
|
150
|
+
-d '{"messages": [{"role": "user", "content": "..."}]}'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Routing decisions are returned as `x-cre-cluster`, `x-cre-stage1-model`,
|
|
154
|
+
`x-cre-final-model`, `x-cre-escalated`, and `x-cre-path` response headers.
|
|
155
|
+
Streaming is not supported: Stage 2 must inspect the complete response before
|
|
156
|
+
deciding whether to escalate it.
|
|
157
|
+
|
|
158
|
+
5. Monitor the deployment. `GET /stats` returns live tallies (total requests,
|
|
159
|
+
escalation rate, and counts per cluster, per final model, and per
|
|
160
|
+
escalation path). Setting `decision_log: <path>` in the config also appends
|
|
161
|
+
one JSON record per request to that file. Both are designed to add no
|
|
162
|
+
latency to requests: `/stats` is in-memory counters, and the decision log
|
|
163
|
+
is written by a background task fed through a non-blocking queue.
|
|
164
|
+
|
|
165
|
+
## Supported models and datasets
|
|
166
|
+
|
|
167
|
+
**Models.** Any model you can serve behind a chat-completions HTTP endpoint
|
|
168
|
+
(the paper uses vLLM). The pool is arbitrary and can mix sizes and families;
|
|
169
|
+
routing, Pareto pruning, and the escalation ladder adapt to whatever pool you
|
|
170
|
+
measure. The paper's pools are Qwen 3 / Qwen 3.5, Gemma 4, and VibeThinker
|
|
171
|
+
(see [REPRODUCE.md](REPRODUCE.md)).
|
|
172
|
+
|
|
173
|
+
**Datasets.** `cre evaluate` ships two tasks, `aime` (numeric answers) and
|
|
174
|
+
`teleqna` (multiple choice), each defining an answer parser and sampling
|
|
175
|
+
preset. A new dataset with a different answer format needs one new `Task`
|
|
176
|
+
entry (a parser + sampling) in [evaluate.py](src/cre_router/evaluate.py);
|
|
177
|
+
clustering, routing, and the QE cascade are domain-agnostic and need no
|
|
178
|
+
changes.
|
|
179
|
+
|
|
180
|
+
## Data formats
|
|
181
|
+
|
|
182
|
+
Inputs are JSONL, one object per line. Cluster ids are strings ("0", "1", ...)
|
|
183
|
+
throughout.
|
|
184
|
+
|
|
185
|
+
- **Training queries** (`cre cluster`): `prompt` (text to embed). Any other
|
|
186
|
+
fields are ignored.
|
|
187
|
+
- **Evaluation dataset** (`cre evaluate`): `prompt` (sent to the model),
|
|
188
|
+
`answer` (ground truth), and optionally `cluster`. Without `cluster`, pass
|
|
189
|
+
`--artifacts` and each row is assigned to its nearest fitted centroid.
|
|
190
|
+
- **QE dataset** (`cre qe-train`, `cre qe-eval`): `question`, `full_output`
|
|
191
|
+
(the model's completion), `num_tokens` (output length), and `decision_label`
|
|
192
|
+
(1 = accept, 0/2 = escalate). Matches the released `ymoslem/*-router` datasets.
|
|
193
|
+
- **Model stats** (`cre fit`): JSON with `cluster_sizes` and per-model `errors`
|
|
194
|
+
and `cluster_tpot_ms`; see [`configs/aime_stats.json`](configs/aime_stats.json).
|
|
195
|
+
- **Serving config** (`cre serve`): YAML; see
|
|
196
|
+
[`example_config_aime24.yaml`](src/cre_router/server/example_config_aime24.yaml).
|
|
197
|
+
|
|
198
|
+
An artifacts directory (written by `cre cluster` / `cre fit`) holds
|
|
199
|
+
`centroids.npy`, `router.json` (embedding model, routing table, $\lambda^*$), and
|
|
200
|
+
`train_assignments.jsonl`.
|
|
201
|
+
|
|
202
|
+
## Repository layout
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
cre-router/
|
|
206
|
+
├── src/cre_router/
|
|
207
|
+
│ ├── clustering.py Stage 1: embed queries, fit k-means centroids
|
|
208
|
+
│ ├── routing.py Stage 1: cost-aware routing, Pareto, lambda*
|
|
209
|
+
│ ├── evaluate.py Stage 1: measure per-cluster accuracy and TPOT via vLLM
|
|
210
|
+
│ ├── artifacts.py load/save centroids + routing table
|
|
211
|
+
│ ├── cli.py the `cre` entry point
|
|
212
|
+
│ ├── qe/ Stage 2: QE classifier
|
|
213
|
+
│ │ ├── train.py fine-tune the accept/escalate classifier
|
|
214
|
+
│ │ ├── classifier.py inference wrapper used by the router
|
|
215
|
+
│ │ └── evaluate.py standalone QE metrics (`cre qe-eval`)
|
|
216
|
+
│ └── server/ live cascade router
|
|
217
|
+
│ ├── cascade_router.py Stage 1 routing + Stage 2 escalation ladder
|
|
218
|
+
│ ├── app.py HTTP endpoint, /stats, decision log
|
|
219
|
+
│ ├── example_config_aime24.yaml serving config (AIME)
|
|
220
|
+
│ └── example_config_teleqna.yaml serving config (TeleQnA)
|
|
221
|
+
├── configs/ checked-in per-model stats for `cre fit`
|
|
222
|
+
├── data/download.py fetch released datasets from the Hugging Face Hub
|
|
223
|
+
├── img/system.svg architecture figure
|
|
224
|
+
├── tests/ unit tests (routing math vs paper, cascade, ...)
|
|
225
|
+
├── requirements-paper.txt frozen environment behind the paper's numbers
|
|
226
|
+
├── REPRODUCE.md reproducing the paper
|
|
227
|
+
├── DEVELOP.md local development and running the tests
|
|
228
|
+
└── README.md
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Citation
|
|
232
|
+
|
|
233
|
+
```bibtex
|
|
234
|
+
@article{moslem2026clusterrouteescalate,
|
|
235
|
+
title={Cluster, Route, Escalate: Cascaded Framework for Cost-Aware LLM Serving},
|
|
236
|
+
author={Yasmin Moslem and Magdalena Kacmajor and Vasudevan Nedumpozhimana and Ammar Abbas and Solmaz Panahi and David Lynch and Zhuangzhuang Nie and Alexandros Agapitos and Aleksandar Milenovic and Hongmeng Song and Yucheng Shi and Yue Pan and Patricia Buffini and John D. Kelleher},
|
|
237
|
+
year={2026},
|
|
238
|
+
eprint={2606.27457},
|
|
239
|
+
archivePrefix={arXiv},
|
|
240
|
+
primaryClass={cs.PF},
|
|
241
|
+
url={https://arxiv.org/abs/2606.27457},
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Development
|
|
246
|
+
|
|
247
|
+
For local setup and running the test suite, see [DEVELOP.md](DEVELOP.md).
|
|
248
|
+
|
|
249
|
+
## License
|
|
250
|
+
|
|
251
|
+
Apache-2.0. See [LICENSE](LICENSE).
|