Repository navigation
fix(core): read the model map where LiteLLM would ask a provider's server - #131
Merged
Merged
Conversation
gopaljigaur
commented
Oct 15, 2026
gopaljigaur
left a comment
Owner
Author
There was a problem hiding this comment.
Two findings, details inline:
_model_infoshould be the single local model info helper. #127's_takes_inputshould call it, and its bare-name fallback should check the entry's provider (ollama/gpt-4onow reads OpenAI'sgpt-4o).- The docs note covers compaction but not overflow recovery, which is now silently off for unmapped Ollama models, including the docs' own
ollama/qwen3:4b. Aregister_modelexample would help, along with the fact that registering also stops LiteLLM's per-completion/api/showrequests.
Checked and fine:
- The provider probe is complete. I blocked every socket and DNS lookup and called
get_model_info, fivesupports_*functions,get_supported_openai_paramsandget_llm_providerfor all 165 providers, with mapped and unmapped names, with and without every*_API_BASEenv var set. Onlyollamaandollama_chat(unmapped models only),lemonadeandhuggingfacereach the network, plus thechatgptandgithub_copilotOAuth inget_llm_provider. OnlyOllamaModelInfo, Ollama's completion config andLemonadeChatConfigdefineget_model_info; Hugging Face has its own branch in_get_model_info_helper. The env vars change only the host. - The Ollama change is acceptable. Before, the lookup went to
OLLAMA_API_BASEor localhost, ignoring the deployment'sapi_base, and blocked the loop. Ollama's runtime info carries nosupports_response_schema, so the structured output paths are unchanged. - Router merge. It matches
get_router_model_infofor mappedollama/llama3with and withoutmodel_info.max_input_tokens, forbase_modelinmodel_infoand inlitellm_params, and forollama_chat/llama3. No request is sent. - Memoization.
_native_schemaand_response_schemago through #125's_holdswith the same stale-after-register_modeledge it documents._windowis not memoized, so a registered window is read at once. - Tests. The 40 new tests pass. With main's
cyclops/they give 29 failed and 11 passed, exactly the Ollama router cases and the registered model, as the body says. - Remaining LiteLLM-side requests. Router builds and the OAuth providers are fine as they are. The per-completion
/api/showrequests deserve an upstream LiteLLM report, since its pricing ignoresapi_base. On the cyclops side, the docs note in finding 2 is enough; no separate issue is needed. - Checks.
uv run pytest -p no:xdist: 637 passed, 1 xfailed. Pre-commit andmypy cyclopspass, and CI is green. The confidentiality grep and the dash check are clean.--is-ancestororigin/main is false: main gained #128 and #132 since. A local merge is clean and passes (639 passed), so it needs a rebase.
…rver LiteLLM's get_model_info and supports_* lookups send a synchronous HTTP request for Ollama models its map lacks (POST /api/show to OLLAMA_API_BASE or localhost, ignoring the deployment's api_base), and always for Lemonade and Hugging Face models. The context window, the compaction window and the response schema checks ran them on the event loop. For those providers, read litellm.model_cost under provider/model, else model, as the multimodal input check does. Other providers keep LiteLLM's own lookups. A router deployment of those providers merges its model_info over the map entry, as the router does.
The input check reads _model_info, so other providers get LiteLLM's lookup and its normalization (bedrock/converse/ routes, fine-tuned ids), and Ollama, Lemonade and Hugging Face still read only the model map. The map's bare name entry is read only when it is for the same provider or none, as LiteLLM matches entries. Docs: the context window section says how to register an unmapped Ollama model's limits, which also stops LiteLLM's own per-completion /api/show requests.
gopaljigaur
force-pushed
the
fix/model-info-network
branch
from
October 15, 2026 07:07
8b6c671 to
146d968
Compare
gopaljigaur
commented
Oct 15, 2026
gopaljigaur
left a comment
Owner
Author
There was a problem hiding this comment.
One docs nit, inline. Everything else is verified at 146d968.
- One helper.
_takes_inputnow returns_model_info(...).get(flag) is not False. For the four network providers, the map read takesprovider/model, then the bare name, and only accepts an entry whoselitellm_provideris the model's provider or unset. That is the same rule as LiteLLM's_check_provider_match.ollama/gpt-4onow reads nothing, andollama/llama2still gets its window.test_another_providers_entry_is_not_readand thebedrock/converse/moonshotai.kimi-k2.5audio case fail on 110885d and pass here. - No network. I blocked every socket and DNS lookup and ran
_model_info,_native_schema,_response_schema,_takes_input(vision, PDF, audio) and_windowfor all 165 providers, with mapped and unmapped names, with and without the*_API_BASEenv vars. Onlychatgptandgithub_copilotreach the network, through the OAuth inget_llm_provider. Over every mapped chat key,_model_inforeaches the network only forgithub_copilotkeys, for the same reason. The other request in the process is LiteLLM's remote cost map fetch at import, which is unrelated to this PR. - #127's decisions.
azure/gpt-5.1-chat,ft:gpt-4o-2024-11-20,ft:gpt-4o-2024-08-06:my-org::abc123,databricks/databricks-claude-sonnet-4-5,deepinfra/meta-llama/Llama-3.2-11B-Vision-Instruct,ollama/llama3.2-vision,ollama/llavaandgpt-3.5-turboall still get images.o3-mini(vision) andbedrock/moonshotai.kimi-k2.5(audio) are still refused. Over every mapped chat model and all three flags, the old map read and the new helper decide alike: 0 newly refused, 0 newly allowed. The only change is the converse route, now refused for audio as the map says. - Docs. The context window introduction now covers compaction and overflow, with the
ollama/qwen3:4bsnippet keyed by the model string. The multimodal guides describe the shared lookup. - Rebase.
git range-diffshows 110885d equal to 8b6c671 apart from theproviders.pycontext from #127, plus the new 146d968.--is-ancestororigin/main (8f77ba0) holds. - Checks.
uv run pytest -n 4: 690 passed, 1 xfailed. Pre-commit andmypy cyclopspass, and CI is green on 3.10 to 3.14. The confidentiality grep and the dash check are clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LiteLLM's model info lookups send a synchronous HTTP request for some providers, and Cyclops ran them on the event loop. This reads LiteLLM's local model map for those providers instead.
Where LiteLLM 1.105.1 goes to the network
_get_model_info_helperasks the provider's model-info config before the static map, and Hugging Face has its own branch. Probing every provider inlitellm.provider_listwith the HTTP clients patched to fail:get_model_info,supports_*get_supported_openai_paramsollama,ollama_chatPOST /api/showtoOLLAMA_API_BASEor localhost, for a model the map lackslemonadeGET /models/{model}, always, even for the 5 models in the maphuggingfaceGET huggingface.co/{model}/raw/main/config.json, alwaysNo other provider reaches the network from these lookups.
token_counteris local for all of them.Cyclops call sites, before this change
compaction._window, so_context_window(feat: retry a completion that overflows the context window #120) on every run, the compaction window (feat: summarize older messages near the model's input limit #118), the summarizing model's window andAgent.compact():litellm.get_model_info, orRouter.get_router_model_infoper deployment. A Router registers its Ollama deployments as stubs in the map when it is built, so through a router only Lemonade and Hugging Face deployments reached the network._native_schema(response_modelwith native tools):get_model_info.litellm.supports_response_schema(response_modelwithout tools)._caches_at_markers(only asks for Anthropic and Bedrock),_takes_paramand_lacks_tools(get_supported_openai_params),_takes_tool_message_images(get_llm_provideronly).What changed
providers._SERVER_INFO_PROVIDERSlists those four providers, next to the module's other provider sets._model_info(model, provider)readslitellm.model_costunderprovider/model, elsemodel, for them, using an entry only when itslitellm_provideris that provider or unset, as LiteLLM's_check_provider_matchdoes (soollama/gpt-4onever reads OpenAI's entry). Every other provider callslitellm.get_model_infoas before._takes_input, the input check from feat: accept images, files and audio as run input #127, is now_model_info(...).get(flag) is not False. Other providers get LiteLLM's normalization, which fixes ids the direct map read missed, such asbedrock/converse/...._native_schemauses_model_info. A new_response_schemareads the map flag for those providers and callslitellm.supports_response_schemaotherwise._windowuses_model_info. Through a router, a deployment of those providers gets its ownmodel_infomerged over the map entry, asget_router_model_infomerges them. Other deployments still go throughget_router_model_info.register_modelforollama/qwen3:4band says registering also stops LiteLLM's own per-completion/api/showrequests. The multimodal guide describes the input check's lookup.Decisions
api_basepoints elsewhere, and would need the capability checks moved out of the sync_completion_kwargs. Reading the map is local and keeps everything sync.supports_response_schemadiffers for 334 of them (the providers it supports globally, a fallback to the bare model's entry, provider info), and the windows differ for 20. So every other provider keeps LiteLLM's own lookups unchanged. For all 29 mapped Ollama entries, underollama/andollama_chat/, the map read gives the same windows and flags asget_model_info.max_input_tokens=None, so compaction raised itsValueErrornaminglitellm.register_model, and overflow recovery was skipped. Both still happen. What changes is a running Ollama server: itscontext_lengthis no longer picked up, so an unmapped Ollama model needslitellm.register_modelfor compaction. Mapped Lemonade models now get their window andsupports_response_schemafrom the map, where LiteLLM ignored the map and asked the server.Not covered (LiteLLM's own calls)
litellm.acompletion, LiteLLM prices each response, which sends/api/showfor an unmapped Ollama model (4 requests per non-streamed completion in a probe). Registering the model avoids that._usagereads theresponse_costLiteLLM sets, so itscompletion_costfallback isn't reached for LiteLLM's responses, streamed ones included.litellm.Routerasks each Ollama, Lemonade and Hugging Face deployment's server once.chatgpt/andgithub_copilot/run OAuth device-code requests inget_llm_provider. That is credential setup the completion needs anyway.Tests
tests/test_model_info.py. httpx'sClient.sendandAsyncClient.sendare patched to record each URL and fail. Each test uses a fresh unmapped model name forollama,ollama_chat,lemonadeandhuggingface, alone and through a router:response_model,reasoning_effortandprompt_caching, with and without tools, so every capability check runs: no request;ContextWindowExceededError, no request;compact()raise theregister_modelValueErrorbefore any completion, no request; the same for an unmapped summarizing model;ollama/gpt-4oreads no entry,ollama/llama2reads its own;model_infosets its window. None of them sends a request.Without the fix, 29 of the 40 fail. The 11 that pass anyway are the Ollama router cases (covered by the Router's stubs) and the registered Ollama model.
tests/test_provider_options.pyputs_response_schemainto the memoized check table, and checks it decides aslitellm.supports_response_schemafor the mapped models there.tests/test_multimodal.pyadds abedrock/converse/id to the unsupported input cases.uv run pytest(690 passed),uv run pre-commit run --all-filesanduv run mypy cyclopspass. The touched test files also pass on Python 3.10.Closes #130