feat: add LiteLLM as unified LLM provider#3182
Conversation
| headers["Authorization"] = f"Bearer {api_key}" | ||
|
|
||
| models_url = f"{base_url}/models" | ||
|
|
There was a problem hiding this comment.
安全风险:verify=False 禁用了 SSL 证书验证,生产环境下容易遭受 MITM 攻击。项目已有 ssl_verify 配置字段,应该从 provider_config 读取并默认为 True。
|
|
||
| model_list = [] | ||
| for item in data: | ||
| model_id = item.get("id", "") |
There was a problem hiding this comment.
所有通过 LiteLLM 发现的模型都使用同一个 DEFAULT_LLM_MAX_TOKENS,不区分实际能力。gpt-4o 有 128K context,gpt-3.5-turbo 只有 16K。这会与 PR #3293 的 capacity management 系统冲突。建议从 LiteLLM 的 model cost map 查询实际能力,或允许 operator 覆盖。
| "litellm is required for LiteLLMModel. " | ||
| "Install it with: pip install 'litellm>=1.80,<1.87'" | ||
| ) from e | ||
|
|
There was a problem hiding this comment.
ImportError 在 __call__ 时才抛出,意味着错误只在第一次调用时才暴露。建议在 __init__ 时就验证 litellm 是否可用,实现更早的失败反馈。
|
|
||
| return model_list | ||
|
|
||
| except Exception as e: |
There was a problem hiding this comment.
[代码规范] except Exception: 过于宽泛,建议捕获更具体的异常类型,避免掩盖潜在错误。
| message.role = MessageRole.ASSISTANT | ||
| return message | ||
|
|
||
| except Exception as e: |
There was a problem hiding this comment.
[代码规范] except Exception: 过于宽泛,建议捕获更具体的异常类型,避免掩盖潜在错误。
|
|
||
| await litellm.acompletion(**kwargs) | ||
| return True | ||
| except Exception as e: |
There was a problem hiding this comment.
[代码规范] except Exception: 过于宽泛,建议捕获更具体的异常类型,避免掩盖潜在错误。
|
LGTM. LiteLLM integration follows the existing provider pattern. No issues found. |
| @@ -0,0 +1,77 @@ | |||
| import logging | |||
There was a problem hiding this comment.
SSL Verification Disabled
litellm_provider.py uses verify=False in httpx.AsyncClient. Exposes application to MITM attacks. Should use proper certificate validation or make configurable.
| @@ -0,0 +1,201 @@ | |||
| """LiteLLM-backed LLM model for nexent. | |||
There was a problem hiding this comment.
OpenAI-Specific Stream Options
litellm_llm.py hardcodes stream_options:{include_usage:true} which is OpenAI-specific. May cause errors with non-OpenAI providers. Should conditionally apply based on provider.
| @@ -0,0 +1,201 @@ | |||
| """LiteLLM-backed LLM model for nexent. | |||
There was a problem hiding this comment.
Token Counting Assumption
Token extraction assumes usage data is in the last chunk. Some providers may return usage in different positions. Should scan all chunks or use LiteLLM built-in tracking.
| @@ -0,0 +1,201 @@ | |||
| """LiteLLM-backed LLM model for nexent. | |||
There was a problem hiding this comment.
Narrow Error Handling
Streaming error handling only catches context_length_exceeded. LiteLLM can throw various errors (rate limits, auth failures). Should catch broader exception types.
| @@ -0,0 +1,77 @@ | |||
| import logging | |||
There was a problem hiding this comment.
Missing URL Validation
litellm_provider.py lacks URL validation for base_url. Invalid URLs cause cryptic httpx errors. Should validate URL format and provide clear error messages.
| @@ -0,0 +1,201 @@ | |||
| """LiteLLM-backed LLM model for nexent. | |||
There was a problem hiding this comment.
Missing Dependency Declaration
LiteLLM not declared in sdk/pyproject.toml or backend/pyproject.toml. Import error suggests pip install but constraint not enforced in package metadata.
| @@ -0,0 +1,201 @@ | |||
| """LiteLLM-backed LLM model for nexent. | |||
There was a problem hiding this comment.
Async Pattern Inconsistency
call is synchronous while check_connectivity is async. Should align with existing provider interface or document the deviation.
| @@ -0,0 +1,201 @@ | |||
| """LiteLLM-backed LLM model for nexent. | |||
There was a problem hiding this comment.
Resource Cleanup Missing
Stop event handling raises RuntimeError but doesn't close streaming iterator or clean up observer state. Should ensure cleanup in finally block.
Summary
litellm.completion()as an SDK dependency.Changes
backend/consts/provider.py: addedLITELLM = "litellm"toProviderEnumbackend/services/providers/litellm_provider.py: newLiteLLMModelProviderfor model discovery via/v1/modelsbackend/services/model_provider_service.py: wired LiteLLM intoget_provider_models()dispatchsdk/nexent/core/models/litellm_llm.py: newLiteLLMModelwith streaming, token tracking, tool calling,drop_params=Truesdk/nexent/core/models/__init__.py: registeredLiteLLMModeltest/sdk/test_litellm_model.py: 17 tests (init, streaming, credentials, edge cases, live E2E)Tests
Unit tests (17/17 pass):
Live E2E (Anthropic claude-sonnet-4-6 via Azure Foundry, streaming):
Risk / Compatibility
OpenAIModeluntouched.litellmis lazy-imported so the base install is unaffected.drop_params=Trueensures cross-provider compatibility.Example usage