feat: add LiteLLM as a first-class chat model provider - #196
Conversation
|
I'm concerned about the supply-chain boundary of this LiteLLM integration. The upstream incident report confirms compromised PyPI releases 1.82.7/1.82.8 in March 2026; those releases were removed. At reviewed head That upper bound permits later 1.x releases beyond a single tested version when dependencies are resolved afresh or upgraded. Please document tested versions, artifact verification, and whether installation of the SDK is opt-in. A disabled application feature cannot prevent an installed malicious Python-startup hook. This is one of 49 observed LiteLLM integration PRs from the same account, whose author acknowledged the cross-project effort. The pattern prompted this review; it does not establish malicious intent or connect the author to the incident. The consolidated questions and corrections are in YouDub #130; this PR's review snapshot preserves the revision and scope. |
OpenJudge Version
0.2.0Description
Background and purpose
OpenJudge ships first class chat providers as
BaseChatModelsubclasses (OpenAIChatModel,MiniMaxChatModel,QiniuChatModel,QwenVLModel), each selected by instantiating the class directly. This PR addsLiteLLMChatModel, a first class provider backed by the LiteLLM SDK, so a single provider class reaches 100+ LLM backends (OpenAI, Anthropic, Gemini, Bedrock, Vertex, Groq, Mistral, DeepSeek, etc.).Calling the SDK directly lets LiteLLM use each provider's native authentication (Bedrock SigV4, Vertex ADC, Azure AD), not just an OpenAI style bearer token.
Changes
openjudge/models/litellm_chat_model.py: newLiteLLMChatModel(OpenAIChatModel). LiteLLM returns OpenAI shaped responses, so it reusesOpenAIChatModel's response handling and only swaps the transport tolitellm.acompletion. Notable behavior:drop_params=Trueby default, so params a provider rejects (Anthropicseed, Geminiresponse_format) are dropped, not errored.api_key/base_urlfor a proxy.achat(...)signature andtool_choicevalidation as the OpenAI provider;structured_modelfalls back tojson_objectfor qwen, gemini, and pai-judge.openjudge/models/__init__.py: exportLiteLLMChatModel.pyproject.toml: optionallitellmextra (litellm>=1.89.0,<2.0.0), lazy imported insideachat.tests/models/test_litellm_chat_model.py: 11 unit tests.Checklist
Please check the following items before code is ready to be reviewed.
pre-commit run --all-filescommandTests
1. Unit tests (11, stubbed litellm so the suite needs no network):
Covers: inheritance and export; no persistent client built; defaults (
drop_params=True, blank creds); dispatch setsdrop_paramsand omits blank creds; proxy creds plusnum_retries/timeoutforwarded when set;structured_modelsetsresponse_formatand drops tools; gemini usesjson_object; invalidtool_choiceraises; amessagesvalue that isn't a list raises.2. Full pre-commit gate, all hooks pass (
black,isort,flake8,pylint10/10 on the new module,pyroma, and the repo's localpytesthook):Sibling provider suites (
test_openai_chat_model.py,test_minimax_chat_model.py,test_qiniu_chat_model.py) still pass (49 passed, 3 skipped), no regressions.3. Live E2E through the real
LiteLLMChatModel.achat(LiteLLM SDK to a local LiteLLM proxy to two different upstreams), exercising non streaming, structured output, and streaming:One
LiteLLMChatModelreached both an OpenAI model and a Google model unchanged, proving cross provider routing plus the reused non streaming, streaming, and structured parsing paths end to end.4. Dependency pin verified:
litellm>=1.89.0,<2.0.0resolves cleanly (installed 1.100.0).Example usage
Risk / Compatibility
litellmis an optional extra and is lazy imported insideachat, sofrom openjudge.models import LiteLLMChatModelworks without it installed; only a live call requires the package.