Cost-aware LLM language-pivot router: decide per request whether to translate Japanese/Arabic through English to cut token cost.
Project description
langpivot — Adaptive Language Pivoting for Reducing LLM API Cost
Japanese and Arabic cost more per request on LLM APIs because their tokenizer fertility is higher — the same content costs 1.3–2.5× the tokens of its English equivalent (measured, see REPORT.md). This package implements a cost-aware routing layer ("query optimizer for tokens") that decides per request whether to:
- direct — send the JA/AR text to the main model as-is, or
- pivot — translate to English with a cheap model, run the main model in English, translate the answer back.
The router skips everything that is already English, estimates the English token count without translating (linear predictor trained on real parallel corpora), and pivots only when the projected saving clears a break-even margin. Measured savings: 26% (JA) / 12% (AR) on gpt-4o with gpt-4o-mini as translator; 33–37% with free local MT. See REPORT.md for the full study, the break-even table, and the honest caveats (quality is not yet evaluated; latency ~2–3×).
Layout
| Path | Purpose |
|---|---|
| langpivot/costmodel.py | Pricing table + pivot-vs-direct arithmetic + closed-form break-even |
| langpivot/detect.py | Free script-based language detection (skip rule) |
| langpivot/predictor.py | EN-token predictor (least squares, no dependencies) |
| langpivot/router.py | The routing decision with full cost breakdown |
| langpivot/middleware.py | PivotClient — drop-in chat wrapper (OpenAI-compatible APIs) |
| langpivot/corpus.py | Tatoeba parallel-pair builder |
| scripts/run_study.py | Full empirical study → results.json + trained predictor |
Setup
pip install tiktoken # only dependency (token counting for OpenAI models)
Data for the study (place in data/):
curl -LO https://downloads.tatoeba.org/exports/per_language/jpn/jpn_sentences.tsv.bz2
curl -LO https://downloads.tatoeba.org/exports/per_language/ara/ara_sentences.tsv.bz2
curl -LO https://downloads.tatoeba.org/exports/per_language/eng/eng_sentences.tsv.bz2
curl -LO https://downloads.tatoeba.org/exports/per_language/jpn/jpn-eng_links.tsv.bz2
curl -LO https://downloads.tatoeba.org/exports/per_language/ara/ara-eng_links.tsv.bz2
Reproduce the study
python -X utf8 scripts/run_study.py # writes results.json + predictor_weights.json
python -X utf8 -m unittest discover -s tests
Use the router / middleware
from langpivot import EnTokenPredictor, PivotRouter, PivotClient
predictor = EnTokenPredictor.load("predictor_weights.json")
router = PivotRouter(
main_model="gpt-4o",
translator_model="gpt-4o-mini",
predictor=predictor,
r_out={"ja": 1.57, "ar": 1.30}, # measured output-side inflation (o200k)
)
# Decision only (no API call, no key needed):
d = router.decide("現在の大規模言語モデルは日本語の処理コストが高すぎます。" * 30)
print(d.route, d.reason) # e.g. "pivot pivot saves 24.1%"
# Full middleware (needs OPENAI_API_KEY; dry-runs without one):
client = PivotClient(router)
result = client.chat([
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "気候変動が日本の農業に与える影響を詳しく説明してください。"},
])
print(result["decision"].route, result["response"])
For Claude models, pass count_tokens_fn= backed by Anthropic's
count_tokens API (Claude's tokenizer is not public — tiktoken counts are
wrong for it).
Security & privacy
- The routing decision is fully local.
PivotRouter.decide(),default_predictor(),detect_language(), and the cost model make no network calls — they run offline on your text and never transmit it anywhere. The bundled model is plain JSON (nopickle, noeval/exec, no subprocess); the core package has zero required dependencies. - Only
PivotClient.chat()talks to the outside world. It calls the LLM API you configure, over TLS. API keys are read from environment variables (never hard-coded), are never written to logs or error messages, and the client refuses to send a key over a non-https://endpoint (raisesValueError). - Report vulnerabilities privately — see SECURITY.md.
Honest limitations
- Quality is unmeasured. Pivoting adds two machine translations; register, cultural nuance, and intended ambiguity are at risk. See REPORT.md §4 for the evaluation protocol before any production use.
- Ratios come from Tatoeba (short, conversational). Domain text (legal,
medical) should be re-measured with
scripts/run_study.pyon your own data. - Prices drift; the table in
costmodel.pyis config, verified 2026-07-04.
MIT licensed. Created by Bashar Kellawi — BasharKilawe@gmail.com
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file langpivot-1.0.0.tar.gz.
File metadata
- Download URL: langpivot-1.0.0.tar.gz
- Upload date:
- Size: 14.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a48e72427f7b5652407f90d67b99df71817242997894a12408bcc58832b0a25
|
|
| MD5 |
bad40ad529c74e71bc2ece30701c09b8
|
|
| BLAKE2b-256 |
95c8aaa296dbd8e35ee26daf92e257e3f2baf4ff1ad01a0cb392a79de5dcf4a6
|
Provenance
The following attestation bundles were made for langpivot-1.0.0.tar.gz:
Publisher:
release.yml on Kellawi/langpivot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
langpivot-1.0.0.tar.gz -
Subject digest:
2a48e72427f7b5652407f90d67b99df71817242997894a12408bcc58832b0a25 - Sigstore transparency entry: 2113068005
- Sigstore integration time:
-
Permalink:
Kellawi/langpivot@326cecdba4fad68f8b1a00de47e84bcf9db9cc08 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Kellawi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@326cecdba4fad68f8b1a00de47e84bcf9db9cc08 -
Trigger Event:
release
-
Statement type:
File details
Details for the file langpivot-1.0.0-py3-none-any.whl.
File metadata
- Download URL: langpivot-1.0.0-py3-none-any.whl
- Upload date:
- Size: 15.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e94c5342238b66e012fba8940ba9e7a7af025450f96bce37d14ac7416255a60
|
|
| MD5 |
acd6dda6703bf307fda72b8ee153a6b0
|
|
| BLAKE2b-256 |
da5ba95a8d843f9fea7c21e3396c65b085ce42d10727b4ee98d9ca8b04d799ed
|
Provenance
The following attestation bundles were made for langpivot-1.0.0-py3-none-any.whl:
Publisher:
release.yml on Kellawi/langpivot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
langpivot-1.0.0-py3-none-any.whl -
Subject digest:
0e94c5342238b66e012fba8940ba9e7a7af025450f96bce37d14ac7416255a60 - Sigstore transparency entry: 2113068047
- Sigstore integration time:
-
Permalink:
Kellawi/langpivot@326cecdba4fad68f8b1a00de47e84bcf9db9cc08 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Kellawi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@326cecdba4fad68f8b1a00de47e84bcf9db9cc08 -
Trigger Event:
release
-
Statement type: