assafelovic/gpt-researcher
120 source files scanned · 23 LLM call site(s) · ~8% of LLM spend looks recoverable (static heuristics · repo looks like an app)

[](https://tokenzero.sh/audit/assafelovic/gpt-researcher)
Models referenced
gpt-4-turbo ×4
Findings
| Severity | Where | Finding | Est. |
|---|---|---|---|
| medium | evals/quality_eval/perturbation.py:234 | LLM call inside a loop Per-item calls repeat the full prompt prefix for every element. If items are independent and latency-tolerant, the provider Batch API is 50% cheaper, and OpenAI Flex processing (`service_tier: "flex"`) gives the same 50% on ordinary calls without restructuring; if the prefix is shared, caching pays off immediately. Fix: Batch where possible, or set `service_tier: "flex"` on OpenAI calls that can wait; otherwise keep the shared prefix cache-formatted (TokenZero does this automatically). | 25% |
| medium | evals/simple_evals/simpleqa_eval.py:14 | 8 static prompt template(s), ~4,282 tokens, and no caching directive anywhere in the repo Most call sites use providers with automatic prefix caching, which only pays off when these templates are sent as a byte-identical prefix: static template first, nothing volatile (dates, ids, user data) interpolated into it. Fix: Keep templates first and static; TokenZero adds a stable `prompt_cache_key` so related requests land on the same cache. | 12% |
| info | evals/quality_eval/benchmark.py:507 | Unrecognised model id "gpt-4-turbo" Not in the current pricing table: it may be retired or renamed. Retired models return errors or are silently remapped by some providers. Fix: Check the provider model list; TokenZero flags unpriced models in `X-TokenZero-Warning`. | 0% |
Fix all of it with one line
OPENAI_BASE_URL=https://tokenzero.sh/v1 ANTHROPIC_BASE_URL=https://tokenzero.sh
Keys pass through untouched. Cache formatting and exact caching are on by default; cascade routing stays opt-in. How it works