From 30b82c3a0cef9ffa3abcdbd1768ee9cc026f3825 Mon Sep 17 00:00:00 2001 From: tristanolive Date: Tue, 10 Mar 2026 03:46:43 +0000 Subject: [PATCH] feat(charity_engine): add Charity Engine provider (#23223) * feat(charity_engine): add Charity Engine provider Charity Engine is a crowdsourced distributed computing platform that donates processing power to charitable causes. Its inference API provides OpenAI-compatible chat, completions, and embeddings endpoints. * test(charity_engine): add provider config and resolution tests Verify JSONProviderRegistry config, provider list membership, model routing for charity_engine/, and Router compatibility. * feat(charity_engine): add Charity Engine to LlmProviders enum Enables provider_list membership and LlmProviders.CHARITY_ENGINE resolution required by the provider and test suite. * fix(charity_engine): remove api_base_env to fix non-deterministic test The CHARITY_ENGINE_API_BASE env var could override the base_url in CI, causing test_charity_engine_provider_resolution to fail intermittently. * fix(charity_engine): remove trailing slash from base_url --- litellm/llms/openai_like/providers.json | 7 ++ litellm/types/utils.py | 1 + .../llms/openai_like/test_charity_engine.py | 101 ++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 tests/test_litellm/llms/openai_like/test_charity_engine.py diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json index b3125d4ad3..275c352b39 100644 --- a/litellm/llms/openai_like/providers.json +++ b/litellm/llms/openai_like/providers.json @@ -94,5 +94,12 @@ "assemblyai": { "base_url": "https://llm-gateway.assemblyai.com/v1", "api_key_env": "ASSEMBLYAI_API_KEY" + }, + "charity_engine": { + "base_url": "https://api.charityengine.services/remotejobs/v2/inference", + "api_key_env": "CHARITY_ENGINE_API_KEY", + "param_mappings": { + "max_completion_tokens": "max_tokens" + } } } diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 8ae0cf2892..b5d5c06924 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -3177,6 +3177,7 @@ class LlmProviders(str, Enum): TOPAZ = "topaz" SAP_GENERATIVE_AI_HUB = "sap" ASSEMBLYAI = "assemblyai" + CHARITY_ENGINE = "charity_engine" GITHUB_COPILOT = "github_copilot" SNOWFLAKE = "snowflake" GRADIENT_AI = "gradient_ai" diff --git a/tests/test_litellm/llms/openai_like/test_charity_engine.py b/tests/test_litellm/llms/openai_like/test_charity_engine.py new file mode 100644 index 0000000000..5d6a751b62 --- /dev/null +++ b/tests/test_litellm/llms/openai_like/test_charity_engine.py @@ -0,0 +1,101 @@ +""" +Tests for Charity Engine provider configuration and integration. +""" + +import os +import sys + +try: + import pytest +except ImportError: + pytest = None + +# Add workspace to path +workspace_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../..")) +sys.path.insert(0, workspace_path) + +import litellm + + +class TestCharityEngineProviderConfig: + """Test Charity Engine provider configuration""" + + def test_charity_engine_in_provider_list(self): + """Test that charity_engine is in the provider list""" + from litellm import LlmProviders + + assert hasattr(LlmProviders, "CHARITY_ENGINE") + assert LlmProviders.CHARITY_ENGINE.value == "charity_engine" + assert "charity_engine" in litellm.provider_list + + def test_charity_engine_json_config_exists(self): + """Test that charity_engine is configured in providers.json""" + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + assert JSONProviderRegistry.exists("charity_engine") + + charity_engine = JSONProviderRegistry.get("charity_engine") + assert charity_engine is not None + assert charity_engine.base_url == "https://api.charityengine.services/remotejobs/v2/inference" + assert charity_engine.api_key_env == "CHARITY_ENGINE_API_KEY" + assert charity_engine.param_mappings.get("max_completion_tokens") == "max_tokens" + + def test_charity_engine_provider_resolution(self): + """Test that provider resolution finds charity_engine""" + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + model, provider, api_key, api_base = get_llm_provider( + model="charity_engine/gemma3:270m", + custom_llm_provider=None, + api_base=None, + api_key=None, + ) + + assert model == "gemma3:270m" + assert provider == "charity_engine" + assert api_base == "https://api.charityengine.services/remotejobs/v2/inference" + + def test_charity_engine_router_config(self): + """Test that charity_engine can be used in Router configuration""" + from litellm import Router + + router = Router( + model_list=[ + { + "model_name": "gemma3-270m", + "litellm_params": { + "model": "charity_engine/gemma3:270m", + "api_key": "test-key", + }, + } + ] + ) + + assert len(router.model_list) == 1 + assert router.model_list[0]["model_name"] == "gemma3-270m" + + +if __name__ == "__main__": + print("Testing Charity Engine Provider...") + + test_config = TestCharityEngineProviderConfig() + + print("\n1. Testing provider in list...") + test_config.test_charity_engine_in_provider_list() + print(" ✓ charity_engine in provider list") + + print("\n2. Testing JSON config...") + test_config.test_charity_engine_json_config_exists() + print(" ✓ charity_engine JSON config loaded") + + print("\n3. Testing provider resolution...") + test_config.test_charity_engine_provider_resolution() + print(" ✓ Provider resolution works") + + print("\n4. Testing router configuration...") + test_config.test_charity_engine_router_config() + print(" ✓ Router configuration works") + + print("\n" + "=" * 50) + print("✓ All configuration tests passed!") + print("=" * 50)