From ab37d696c3dbb8feb5976f893ae5519cbca3b4d2 Mon Sep 17 00:00:00 2001
From: mogith-pn <143642606+mogith-pn@users.noreply.github.com>
Date: Fri, 17 Oct 2025 04:15:34 +0530
Subject: [PATCH] updated clarifai functions to openai compatible (#15615)
---
docs/my-website/docs/providers/clarifai.md | 368 +++++++++++-------
litellm/__init__.py | 2 +
litellm/constants.py | 97 ++---
.../get_llm_provider_logic.py | 9 +
litellm/llms/clarifai/chat/transformation.py | 309 +++++----------
litellm/llms/clarifai/common_utils.py | 6 -
litellm/main.py | 37 +-
litellm/utils.py | 2 +
8 files changed, 364 insertions(+), 466 deletions(-)
delete mode 100644 litellm/llms/clarifai/common_utils.py
diff --git a/docs/my-website/docs/providers/clarifai.md b/docs/my-website/docs/providers/clarifai.md
index cb498650385..7c3f8607684 100644
--- a/docs/my-website/docs/providers/clarifai.md
+++ b/docs/my-website/docs/providers/clarifai.md
@@ -1,21 +1,24 @@
# Clarifai
-Anthropic, OpenAI, Mistral, Llama and Gemini LLMs are Supported on Clarifai.
+Anthropic, OpenAI, Qwen, xAI, Gemini and most of Open soured LLMs are Supported on Clarifai.
-:::warning
-
-Streaming is not yet supported on using clarifai and litellm. Tracking support here: https://github.com/BerriAI/litellm/issues/4162
-
-:::
+| Property | Details |
+|-------|-------|
+| Description | Clarifai is a powerful AI platform that provides access to a wide range of LLMs through a unified API. LiteLLM enables seamless integration with Clarifai's models using an OpenAI-compatible interface. |
+| Provider Doc | [Clarifai ↗](https://docs.clarifai.com/) |
+|OpenAI compatible Endpoint for Provider | `https://api.clarifai.com/v2/ext/openai/v1` |
+| Supported Endpoints | `/chat/completions` |
## Pre-Requisites
-`pip install litellm`
+
+```bash
+pip install litellm
+```
## Required Environment Variables
-To obtain your Clarifai Personal access token follow this [link](https://docs.clarifai.com/clarifai-basics/authentication/personal-access-tokens/). Optionally the PAT can also be passed in `completion` function.
+To obtain your Clarifai Personal access token follow this [link](https://docs.clarifai.com/clarifai-basics/authentication/personal-access-tokens/).
```python
-os.environ["CLARIFAI_API_KEY"] = "YOUR_CLARIFAI_PAT" # CLARIFAI_PAT
-
+os.environ["CLARIFAI_PAT"] = "CLARIFAI_API_KEY" # CLARIFAI_PAT
```
## Usage
@@ -27,154 +30,231 @@ from litellm import completion
os.environ["CLARIFAI_API_KEY"] = ""
response = completion(
- model="clarifai/mistralai.completion.mistral-large",
+ model="clarifai/openai.chat-completion.gpt-oss-20b",
messages=[{ "content": "Tell me a joke about physics?","role": "user"}]
)
```
+## Streaming Support
-**Output**
-```json
-{
- "id": "chatcmpl-572701ee-9ab2-411c-ac75-46c1ba18e781",
- "choices": [
- {
- "finish_reason": "stop",
- "index": 1,
- "message": {
- "content": "Sure, here's a physics joke for you:\n\nWhy can't you trust an atom?\n\nBecause they make up everything!",
- "role": "assistant"
- }
- }
+LiteLLM supports streaming responses with Clarifai models:
+
+```python
+import litellm
+
+for chunk in litellm.completion(
+ model="clarifai/openai.chat-completion.gpt-oss-20b",
+ api_key="CLARIFAI_API_KEY",
+ messages=[
+ {"role": "user", "content": "Tell me a fun fact about space."}
],
- "created": 1714410197,
- "model": "https://api.clarifai.com/v2/users/mistralai/apps/completion/models/mistral-large/outputs",
- "object": "chat.completion",
- "system_fingerprint": null,
- "usage": {
- "prompt_tokens": 14,
- "completion_tokens": 24,
- "total_tokens": 38
+ stream=True,
+):
+ print(chunk.choices[0].delta)
+```
+
+## Tool Calling (Function Calling)
+
+Clarifai models accessed via LiteLLM support function calling:
+
+```python
+import litellm
+
+tools = [{
+ "type": "function",
+ "function": {
+ "name": "get_weather",
+ "description": "Get current temperature for a given location.",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "location": {
+ "type": "string",
+ "description": "City and country e.g. Tokyo, Japan"
+ }
+ },
+ "required": ["location"],
+ "additionalProperties": False
+ },
}
}
+}]
+
+response = litellm.completion(
+ model="clarifai/openai.chat-completion.gpt-oss-20b",
+ api_key="CLARIFAI_API_KEY",
+ messages=[{"role": "user", "content": "What is the weather in Paris today?"}],
+ tools=tools,
+)
+
+print(response.choices[0].message.tool_calls)
```
## Clarifai models
liteLLM supports all models on [Clarifai community](https://clarifai.com/explore/models?filterData=%5B%7B%22field%22%3A%22use_cases%22%2C%22value%22%3A%5B%22llm%22%5D%7D%5D&page=1&perPage=24)
-Example Usage - Note: liteLLM supports all models deployed on Clarifai
-
-## Llama LLMs
-| Model Name | Function Call |
----------------------------|---------------------------------|
-| clarifai/meta.Llama-2.llama2-7b-chat | `completion('clarifai/meta.Llama-2.llama2-7b-chat', messages)`
-| clarifai/meta.Llama-2.llama2-13b-chat | `completion('clarifai/meta.Llama-2.llama2-13b-chat', messages)`
-| clarifai/meta.Llama-2.llama2-70b-chat | `completion('clarifai/meta.Llama-2.llama2-70b-chat', messages)` |
-| clarifai/meta.Llama-2.codeLlama-70b-Python | `completion('clarifai/meta.Llama-2.codeLlama-70b-Python', messages)`|
-| clarifai/meta.Llama-2.codeLlama-70b-Instruct | `completion('clarifai/meta.Llama-2.codeLlama-70b-Instruct', messages)` |
-
-## Mistral LLMs
-| Model Name | Function Call |
-|---------------------------------------------|------------------------------------------------------------------------|
-| clarifai/mistralai.completion.mixtral-8x22B | `completion('clarifai/mistralai.completion.mixtral-8x22B', messages)` |
-| clarifai/mistralai.completion.mistral-large | `completion('clarifai/mistralai.completion.mistral-large', messages)` |
-| clarifai/mistralai.completion.mistral-medium | `completion('clarifai/mistralai.completion.mistral-medium', messages)` |
-| clarifai/mistralai.completion.mistral-small | `completion('clarifai/mistralai.completion.mistral-small', messages)` |
-| clarifai/mistralai.completion.mixtral-8x7B-Instruct-v0_1 | `completion('clarifai/mistralai.completion.mixtral-8x7B-Instruct-v0_1', messages)`
-| clarifai/mistralai.completion.mistral-7B-OpenOrca | `completion('clarifai/mistralai.completion.mistral-7B-OpenOrca', messages)` |
-| clarifai/mistralai.completion.openHermes-2-mistral-7B | `completion('clarifai/mistralai.completion.openHermes-2-mistral-7B', messages)` |
+### 🧠 OpenAI Models
+- [gpt-oss-20b](https://clarifai.com/openai/chat-completion/models/gpt-oss-20b)
+- [gpt-oss-120b](https://clarifai.com/openai/chat-completion/models/gpt-oss-120b)
+- [gpt-5-nano](https://clarifai.com/openai/chat-completion/models/gpt-5-nano)
+- [gpt-5-mini](https://clarifai.com/openai/chat-completion/models/gpt-5-mini)
+- [gpt-5](https://clarifai.com/openai/chat-completion/models/gpt-5)
+- [gpt-4o](https://clarifai.com/openai/chat-completion/models/gpt-4o)
+- [o3](https://clarifai.com/openai/chat-completion/models/o3)
+- Many more...
-## Jurassic LLMs
-| Model Name | Function Call |
-|-----------------------------------------------|---------------------------------------------------------------------|
-| clarifai/ai21.complete.Jurassic2-Grande | `completion('clarifai/ai21.complete.Jurassic2-Grande', messages)` |
-| clarifai/ai21.complete.Jurassic2-Grande-Instruct | `completion('clarifai/ai21.complete.Jurassic2-Grande-Instruct', messages)` |
-| clarifai/ai21.complete.Jurassic2-Jumbo-Instruct | `completion('clarifai/ai21.complete.Jurassic2-Jumbo-Instruct', messages)` |
-| clarifai/ai21.complete.Jurassic2-Jumbo | `completion('clarifai/ai21.complete.Jurassic2-Jumbo', messages)` |
-| clarifai/ai21.complete.Jurassic2-Large | `completion('clarifai/ai21.complete.Jurassic2-Large', messages)` |
-
-## Wizard LLMs
-
-| Model Name | Function Call |
-|-----------------------------------------------|---------------------------------------------------------------------|
-| clarifai/wizardlm.generate.wizardCoder-Python-34B | `completion('clarifai/wizardlm.generate.wizardCoder-Python-34B', messages)` |
-| clarifai/wizardlm.generate.wizardLM-70B | `completion('clarifai/wizardlm.generate.wizardLM-70B', messages)` |
-| clarifai/wizardlm.generate.wizardLM-13B | `completion('clarifai/wizardlm.generate.wizardLM-13B', messages)` |
-| clarifai/wizardlm.generate.wizardCoder-15B | `completion('clarifai/wizardlm.generate.wizardCoder-15B', messages)` |
-
-## Anthropic models
-
-| Model Name | Function Call |
-|-----------------------------------------------|---------------------------------------------------------------------|
-| clarifai/anthropic.completion.claude-v1 | `completion('clarifai/anthropic.completion.claude-v1', messages)` |
-| clarifai/anthropic.completion.claude-instant-1_2 | `completion('clarifai/anthropic.completion.claude-instant-1_2', messages)` |
-| clarifai/anthropic.completion.claude-instant | `completion('clarifai/anthropic.completion.claude-instant', messages)` |
-| clarifai/anthropic.completion.claude-v2 | `completion('clarifai/anthropic.completion.claude-v2', messages)` |
-| clarifai/anthropic.completion.claude-2_1 | `completion('clarifai/anthropic.completion.claude-2_1', messages)` |
-| clarifai/anthropic.completion.claude-3-opus | `completion('clarifai/anthropic.completion.claude-3-opus', messages)` |
-| clarifai/anthropic.completion.claude-3-sonnet | `completion('clarifai/anthropic.completion.claude-3-sonnet', messages)` |
-
-## OpenAI GPT LLMs
-
-| Model Name | Function Call |
-|-----------------------------------------------|---------------------------------------------------------------------|
-| clarifai/openai.chat-completion.GPT-4 | `completion('clarifai/openai.chat-completion.GPT-4', messages)` |
-| clarifai/openai.chat-completion.GPT-3_5-turbo | `completion('clarifai/openai.chat-completion.GPT-3_5-turbo', messages)` |
-| clarifai/openai.chat-completion.gpt-4-turbo | `completion('clarifai/openai.chat-completion.gpt-4-turbo', messages)` |
-| clarifai/openai.completion.gpt-3_5-turbo-instruct | `completion('clarifai/openai.completion.gpt-3_5-turbo-instruct', messages)` |
-
-## GCP LLMs
-
-| Model Name | Function Call |
-|-----------------------------------------------|---------------------------------------------------------------------|
-| clarifai/gcp.generate.gemini-1_5-pro | `completion('clarifai/gcp.generate.gemini-1_5-pro', messages)` |
-| clarifai/gcp.generate.imagen-2 | `completion('clarifai/gcp.generate.imagen-2', messages)` |
-| clarifai/gcp.generate.code-gecko | `completion('clarifai/gcp.generate.code-gecko', messages)` |
-| clarifai/gcp.generate.code-bison | `completion('clarifai/gcp.generate.code-bison', messages)` |
-| clarifai/gcp.generate.text-bison | `completion('clarifai/gcp.generate.text-bison', messages)` |
-| clarifai/gcp.generate.gemma-2b-it | `completion('clarifai/gcp.generate.gemma-2b-it', messages)` |
-| clarifai/gcp.generate.gemma-7b-it | `completion('clarifai/gcp.generate.gemma-7b-it', messages)` |
-| clarifai/gcp.generate.gemini-pro | `completion('clarifai/gcp.generate.gemini-pro', messages)` |
-| clarifai/gcp.generate.gemma-1_1-7b-it | `completion('clarifai/gcp.generate.gemma-1_1-7b-it', messages)` |
-
-## Cohere LLMs
-| Model Name | Function Call |
-|-----------------------------------------------|---------------------------------------------------------------------|
-| clarifai/cohere.generate.cohere-generate-command | `completion('clarifai/cohere.generate.cohere-generate-command', messages)` |
- clarifai/cohere.generate.command-r-plus' | `completion('clarifai/clarifai/cohere.generate.command-r-plus', messages)`|
-
-## Databricks LLMs
-
-| Model Name | Function Call |
-|---------------------------------------------------|---------------------------------------------------------------------|
-| clarifai/databricks.drbx.dbrx-instruct | `completion('clarifai/databricks.drbx.dbrx-instruct', messages)` |
-| clarifai/databricks.Dolly-v2.dolly-v2-12b | `completion('clarifai/databricks.Dolly-v2.dolly-v2-12b', messages)`|
-
-## Microsoft LLMs
-
-| Model Name | Function Call |
-|---------------------------------------------------|---------------------------------------------------------------------|
-| clarifai/microsoft.text-generation.phi-2 | `completion('clarifai/microsoft.text-generation.phi-2', messages)` |
-| clarifai/microsoft.text-generation.phi-1_5 | `completion('clarifai/microsoft.text-generation.phi-1_5', messages)`|
-
-## Salesforce models
-
-| Model Name | Function Call |
-|-----------------------------------------------------------|-------------------------------------------------------------------------------|
-| clarifai/salesforce.blip.general-english-image-caption-blip-2 | `completion('clarifai/salesforce.blip.general-english-image-caption-blip-2', messages)` |
-| clarifai/salesforce.xgen.xgen-7b-8k-instruct | `completion('clarifai/salesforce.xgen.xgen-7b-8k-instruct', messages)` |
+### 🤖 Anthropic Models
+- [claude-sonnet-4](https://clarifai.com/anthropic/completion/models/claude-sonnet-4)
+- [claude-opus-4](https://clarifai.com/anthropic/completion/models/claude-opus-4)
+- [claude-3_5-haiku](https://clarifai.com/anthropic/completion/models/claude-3_5-haiku)
+- [claude-3_7-sonnet](https://clarifai.com/anthropic/completion/models/claude-3_7-sonnet)
+- Many more...
-## Other Top performing LLMs
+### 🪄 xAI Models
+- [grok-3](https://clarifai.com/xai/chat-completion/models/grok-3)
+- [grok-2-vision-1212](https://clarifai.com/xai/chat-completion/models/grok-2-vision-1212)
+- [grok-2-1212](https://clarifai.com/xai/chat-completion/models/grok-2-1212)
+- [grok-code-fast-1](https://clarifai.com/xai/chat-completion/models/grok-code-fast-1)
+- [grok-2-image-1212](https://clarifai.com/xai/image-generation/models/grok-2-image-1212)
+- Many more...
-| Model Name | Function Call |
-|---------------------------------------------------|---------------------------------------------------------------------|
-| clarifai/deci.decilm.deciLM-7B-instruct | `completion('clarifai/deci.decilm.deciLM-7B-instruct', messages)` |
-| clarifai/upstage.solar.solar-10_7b-instruct | `completion('clarifai/upstage.solar.solar-10_7b-instruct', messages)` |
-| clarifai/openchat.openchat.openchat-3_5-1210 | `completion('clarifai/openchat.openchat.openchat-3_5-1210', messages)` |
-| clarifai/togethercomputer.stripedHyena.stripedHyena-Nous-7B | `completion('clarifai/togethercomputer.stripedHyena.stripedHyena-Nous-7B', messages)` |
-| clarifai/fblgit.una-cybertron.una-cybertron-7b-v2 | `completion('clarifai/fblgit.una-cybertron.una-cybertron-7b-v2', messages)` |
-| clarifai/tiiuae.falcon.falcon-40b-instruct | `completion('clarifai/tiiuae.falcon.falcon-40b-instruct', messages)` |
-| clarifai/togethercomputer.RedPajama.RedPajama-INCITE-7B-Chat | `completion('clarifai/togethercomputer.RedPajama.RedPajama-INCITE-7B-Chat', messages)` |
-| clarifai/bigcode.code.StarCoder | `completion('clarifai/bigcode.code.StarCoder', messages)` |
-| clarifai/mosaicml.mpt.mpt-7b-instruct | `completion('clarifai/mosaicml.mpt.mpt-7b-instruct', messages)` |
+
+### 🔷 Google Gemini Models
+- [gemini-2_5-pro](https://clarifai.com/gcp/generate/models/gemini-2_5-pro)
+- [gemini-2_5-flash-lite](https://clarifai.com/gcp/generate/models/gemini-2_5-flash-lite)
+- [gemini-2_0-flash](https://clarifai.com/gcp/generate/models/gemini-2_0-flash)
+- [gemini-2_0-flash-lite](https://clarifai.com/gcp/generate/models/gemini-2_0-flash-lite)
+- Many more...
+
+
+### 🧩 Qwen Models
+- [Qwen3-30B-A3B-Instruct-2507](https://clarifai.com/qwen/qwenLM/models/Qwen3-30B-A3B-Instruct-2507)
+- [Qwen3-30B-A3B-Thinking-2507](https://clarifai.com/qwen/qwenLM/models/Qwen3-30B-A3B-Thinking-2507)
+- [Qwen3-14B](https://clarifai.com/qwen/qwenLM/models/Qwen3-14B)
+- [QwQ-32B-AWQ](https://clarifai.com/qwen/qwenLM/models/QwQ-32B-AWQ)
+- [Qwen2_5-VL-7B-Instruct](https://clarifai.com/qwen/qwen-VL/models/Qwen2_5-VL-7B-Instruct)
+- [Qwen3-Coder-30B-A3B-Instruct](https://clarifai.com/qwen/qwenCoder/models/Qwen3-Coder-30B-A3B-Instruct)
+- Many more...
+
+
+### 💡 MiniCPM (OpenBMB) Models
+- [MiniCPM-o-2_6-language](https://clarifai.com/openbmb/miniCPM/models/MiniCPM-o-2_6-language)
+- [MiniCPM3-4B](https://clarifai.com/openbmb/miniCPM/models/MiniCPM3-4B)
+- [MiniCPM4-8B](https://clarifai.com/openbmb/miniCPM/models/MiniCPM4-8B)
+- Many more...
+
+
+### 🧬 Microsoft Phi Models
+- [Phi-4-reasoning-plus](https://clarifai.com/microsoft/text-generation/models/Phi-4-reasoning-plus)
+- [phi-4](https://clarifai.com/microsoft/text-generation/models/phi-4)
+- Many more...
+
+
+### 🦙 Meta Llama Models
+- [Llama-3_2-3B-Instruct](https://clarifai.com/meta/Llama-3/models/Llama-3_2-3B-Instruct)
+- Many more...
+
+
+### 🔍 DeepSeek Models
+- [DeepSeek-R1-0528-Qwen3-8B](https://clarifai.com/deepseek-ai/deepseek-chat/models/DeepSeek-R1-0528-Qwen3-8B)
+- Many more...
+
+## Usage with LiteLLM Proxy
+
+Here's how to call Clarifai with the LiteLLM Proxy Server
+
+### 1. Save key in your environment
+
+```bash
+export CLARIFAI_PAT="CLARIFAI_API_KEY"
+```
+
+### 2. Start the proxy
+
+
+
+
+```yaml
+model_list:
+ - model_name: clarifai-model
+ litellm_params:
+ model: clarifai/openai.chat-completion.gpt-oss-20b
+ api_key: os.environ/CLARIFAI_PAT
+```
+
+```bash
+litellm --config /path/to/config.yaml
+
+# Server running on http://0.0.0.0:4000
+```
+
+
+
+### 3. Test it
+
+
+
+
+```shell
+curl --location 'http://0.0.0.0:4000/chat/completions' \
+--header 'Content-Type: application/json' \
+--data ' {
+ "model": "clarifai-model",
+ "messages": [
+ {
+ "role": "user",
+ "content": "what llm are you"
+ }
+ ]
+ }
+'
+```
+
+
+
+```python
+import openai
+client = openai.OpenAI(
+ api_key="anything",
+ base_url="http://0.0.0.0:4000"
+)
+
+response = client.chat.completions.create(
+ model="clarifai-model",
+ messages = [
+ {
+ "role": "user",
+ "content": "this is a test request, write a short poem"
+ }
+ ]
+)
+
+print(response)
+```
+
+
+
+## Important Notes
+
+- Always prefix Clarifai model IDs with `clarifai/` when specifying the model name
+- Use your Clarifai Personal Access Token (PAT) as the API key
+- Usage is tracked and billed through Clarifai
+- API rate limits are subject to your Clarifai account settings
+- Most OpenAI parameters are supported, but some advanced features may vary by model
+
+
+## FAQs
+
+| Question | Answer |
+|----------|---------|
+| Can I use all Clarifai models with LiteLLM? | Most chat-completion models are supported. Use the Clarifai model URL as the `model`. |
+| Do I need a separate Clarifai PAT? | Yes, you must use a valid Clarifai Personal Access Token. |
+| Is tool calling supported? | Yes, provided the underlying Clarifai model supports function/tool calling. |
+| How is billing handled? | Clarifai usage is billed independently via Clarifai. |
+
+## Additional Resources
+
+- [Clarifai Documentation](https://docs.clarifai.com/)
+- [LiteLLM GitHub](https://github.com/BerriAI/litellm)
+- [Clarifai Runners Examples](https://github.com/Clarifai/runners-examples)
\ No newline at end of file
diff --git a/litellm/__init__.py b/litellm/__init__.py
index 02bfaaf72f9..dddcc6c2574 100644
--- a/litellm/__init__.py
+++ b/litellm/__init__.py
@@ -849,6 +849,7 @@ model_list = list(
| wandb_models
| ovhcloud_models
| lemonade_models
+ | set(clarifai_models)
)
model_list_set = set(model_list)
@@ -934,6 +935,7 @@ models_by_provider: dict = {
"wandb": wandb_models,
"ovhcloud": ovhcloud_models | ovhcloud_embedding_models,
"lemonade": lemonade_models,
+ "clarifai": clarifai_models,
}
# mapping for those models which have larger equivalents
diff --git a/litellm/constants.py b/litellm/constants.py
index d1858bdfd84..24657c90014 100644
--- a/litellm/constants.py
+++ b/litellm/constants.py
@@ -480,6 +480,7 @@ openai_compatible_endpoints: List = [
"https://api.hyperbolic.xyz/v1",
"https://ai-gateway.vercel.sh/v1",
"https://api.inference.wandb.ai/v1",
+ "https://api.clarifai.com/v2/ext/openai/v1",
]
@@ -526,6 +527,7 @@ openai_compatible_providers: List = [
"aiml",
"wandb",
"cometapi",
+ "clarifai",
]
openai_text_completion_compatible_providers: List = (
[ # providers that support `/v1/completions`
@@ -569,69 +571,37 @@ replicate_models: set = set(
clarifai_models: set = set(
[
- "clarifai/meta.Llama-3.Llama-3-8B-Instruct",
- "clarifai/gcp.generate.gemma-1_1-7b-it",
- "clarifai/mistralai.completion.mixtral-8x22B",
- "clarifai/cohere.generate.command-r-plus",
- "clarifai/databricks.drbx.dbrx-instruct",
- "clarifai/mistralai.completion.mistral-large",
- "clarifai/mistralai.completion.mistral-medium",
- "clarifai/mistralai.completion.mistral-small",
- "clarifai/mistralai.completion.mixtral-8x7B-Instruct-v0_1",
- "clarifai/gcp.generate.gemma-2b-it",
- "clarifai/gcp.generate.gemma-7b-it",
- "clarifai/deci.decilm.deciLM-7B-instruct",
- "clarifai/mistralai.completion.mistral-7B-Instruct",
- "clarifai/gcp.generate.gemini-pro",
- "clarifai/anthropic.completion.claude-v1",
- "clarifai/anthropic.completion.claude-instant-1_2",
- "clarifai/anthropic.completion.claude-instant",
- "clarifai/anthropic.completion.claude-v2",
- "clarifai/anthropic.completion.claude-2_1",
- "clarifai/meta.Llama-2.codeLlama-70b-Python",
- "clarifai/meta.Llama-2.codeLlama-70b-Instruct",
- "clarifai/openai.completion.gpt-3_5-turbo-instruct",
- "clarifai/meta.Llama-2.llama2-7b-chat",
- "clarifai/meta.Llama-2.llama2-13b-chat",
- "clarifai/meta.Llama-2.llama2-70b-chat",
- "clarifai/openai.chat-completion.gpt-4-turbo",
- "clarifai/microsoft.text-generation.phi-2",
- "clarifai/meta.Llama-2.llama2-7b-chat-vllm",
- "clarifai/upstage.solar.solar-10_7b-instruct",
- "clarifai/openchat.openchat.openchat-3_5-1210",
- "clarifai/togethercomputer.stripedHyena.stripedHyena-Nous-7B",
- "clarifai/gcp.generate.text-bison",
- "clarifai/meta.Llama-2.llamaGuard-7b",
- "clarifai/fblgit.una-cybertron.una-cybertron-7b-v2",
- "clarifai/openai.chat-completion.GPT-4",
- "clarifai/openai.chat-completion.GPT-3_5-turbo",
- "clarifai/ai21.complete.Jurassic2-Grande",
- "clarifai/ai21.complete.Jurassic2-Grande-Instruct",
- "clarifai/ai21.complete.Jurassic2-Jumbo-Instruct",
- "clarifai/ai21.complete.Jurassic2-Jumbo",
- "clarifai/ai21.complete.Jurassic2-Large",
- "clarifai/cohere.generate.cohere-generate-command",
- "clarifai/wizardlm.generate.wizardCoder-Python-34B",
- "clarifai/wizardlm.generate.wizardLM-70B",
- "clarifai/tiiuae.falcon.falcon-40b-instruct",
- "clarifai/togethercomputer.RedPajama.RedPajama-INCITE-7B-Chat",
- "clarifai/gcp.generate.code-gecko",
- "clarifai/gcp.generate.code-bison",
- "clarifai/mistralai.completion.mistral-7B-OpenOrca",
- "clarifai/mistralai.completion.openHermes-2-mistral-7B",
- "clarifai/wizardlm.generate.wizardLM-13B",
- "clarifai/huggingface-research.zephyr.zephyr-7B-alpha",
- "clarifai/wizardlm.generate.wizardCoder-15B",
- "clarifai/microsoft.text-generation.phi-1_5",
- "clarifai/databricks.Dolly-v2.dolly-v2-12b",
- "clarifai/bigcode.code.StarCoder",
- "clarifai/salesforce.xgen.xgen-7b-8k-instruct",
- "clarifai/mosaicml.mpt.mpt-7b-instruct",
- "clarifai/anthropic.completion.claude-3-opus",
- "clarifai/anthropic.completion.claude-3-sonnet",
- "clarifai/gcp.generate.gemini-1_5-pro",
- "clarifai/gcp.generate.imagen-2",
- "clarifai/salesforce.blip.general-english-image-caption-blip-2",
+ "clarifai/openai.chat-completion.gpt-oss-20b",
+ "clarifai/qwen.qwenLM.Qwen3-30B-A3B-Instruct-2507",
+ "clarifai/qwen.qwen3.qwen3-next-80B-A3B-Thinking",
+ "clarifai/openai.chat-completion.gpt-oss-120b",
+ "clarifai/qwen.qwenLM.Qwen3-30B-A3B-Thinking-2507"
+ "clarifai/openai.chat-completion.gpt-5-nano",
+ "clarifai/openai.chat-completion.gpt-4o",
+ "clarifai/gcp.generate.gemini-2_5-pro",
+ "clarifai/anthropic.completion.claude-sonnet-4",
+ "clarifai/xai.chat-completion.grok-2-vision-1212",
+ "clarifai/openbmb.miniCPM.MiniCPM-o-2_6-language",
+ "clarifai/microsoft.text-generation.Phi-4-reasoning-plus",
+ "clarifai/openbmb.miniCPM.MiniCPM3-4B",
+ "clarifai/openbmb.miniCPM.MiniCPM4-8B",
+ "clarifai/xai.chat-completion.grok-2-1212",
+ "clarifai/anthropic.completion.claude-opus-4",
+ "clarifai/xai.chat-completion.grok-code-fast-1",
+ "clarifai/qwen.qwenCoder.Qwen3-Coder-30B-A3B-Instruct",
+ "clarifai/deepseek-ai.deepseek-chat.DeepSeek-R1-0528-Qwen3-8B",
+ "clarifai/openai.chat-completion.gpt-5-mini",
+ "clarifai/microsoft.text-generation.phi-4",
+ "clarifai/openai.chat-completion.gpt-5",
+ "clarifai/meta.Llama-3.Llama-3_2-3B-Instruct",
+ "clarifai/xai.image-generation.grok-2-image-1212",
+ "clarifai/xai.chat-completion.grok-3",
+ "clarifai/openai.chat-completion.o3",
+ "clarifai/qwen.qwen-VL.Qwen2_5-VL-7B-Instruct",
+ "clarifai/qwen.qwenLM.Qwen3-14B",
+ "clarifai/qwen.qwenLM.QwQ-32B-AWQ",
+ "clarifai/anthropic.completion.claude-3_5-haiku",
+ "clarifai/anthropic.completion.claude-3_7-sonnet",
]
)
@@ -1118,6 +1088,7 @@ SENTRY_DENYLIST = [
"FIREWORKS_AI_API_KEY",
"FIREWORKSAI_API_KEY",
"OVHCLOUD_API_KEY",
+ "CLARIFAI_API_KEY",
# Database and Connection Strings
"database_url",
"redis_url",
diff --git a/litellm/litellm_core_utils/get_llm_provider_logic.py b/litellm/litellm_core_utils/get_llm_provider_logic.py
index f209aed483c..275f2a63a1b 100644
--- a/litellm/litellm_core_utils/get_llm_provider_logic.py
+++ b/litellm/litellm_core_utils/get_llm_provider_logic.py
@@ -383,6 +383,8 @@ def get_llm_provider( # noqa: PLR0915
custom_llm_provider = "ovhcloud"
elif model.startswith("lemonade/"):
custom_llm_provider = "lemonade"
+ elif model.startswith("clarifai/"):
+ custom_llm_provider = "clarifai"
if not custom_llm_provider:
if litellm.suppress_debug_info is False:
print() # noqa
@@ -794,6 +796,13 @@ def _get_openai_compatible_provider_info( # noqa: PLR0915
) = litellm.LemonadeChatConfig()._get_openai_compatible_provider_info(
api_base, api_key
)
+ elif custom_llm_provider == "clarifai":
+ (
+ api_base,
+ dynamic_api_key,
+ ) = litellm.ClarifaiConfig()._get_openai_compatible_provider_info(
+ api_base, api_key
+ )
if api_base is not None and not isinstance(api_base, str):
raise Exception("api base needs to be a string. api_base={}".format(api_base))
diff --git a/litellm/llms/clarifai/chat/transformation.py b/litellm/llms/clarifai/chat/transformation.py
index 73be89fc6e7..48884ff0139 100644
--- a/litellm/llms/clarifai/chat/transformation.py
+++ b/litellm/llms/clarifai/chat/transformation.py
@@ -1,262 +1,133 @@
-import json
-from typing import TYPE_CHECKING, Any, AsyncIterator, Iterator, List, Optional, Union
+from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Union
import httpx
-from litellm.litellm_core_utils.prompt_templates.common_utils import (
- convert_content_list_to_str,
+from litellm.secret_managers.main import get_secret_str
+from litellm.types.utils import ModelResponse
+from litellm.types.llms.openai import (
+ AllMessageValues,
)
-from litellm.llms.base_llm.base_model_iterator import FakeStreamResponseIterator
-from litellm.llms.base_llm.chat.transformation import BaseConfig, BaseLLMException
-from litellm.types.llms.openai import AllMessageValues
-from litellm.types.utils import (
- ChatCompletionToolCallChunk,
- ChatCompletionUsageBlock,
- Choices,
- GenericStreamingChunk,
- Message,
- ModelResponse,
- Usage,
-)
-from litellm.utils import token_counter
+from litellm.llms.openai.common_utils import OpenAIError
+from litellm.llms.base_llm.chat.transformation import BaseLLMException
-from ..common_utils import ClarifaiError
+from ...openai.chat.gpt_transformation import OpenAIGPTConfig
if TYPE_CHECKING:
- from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
+ from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
- LoggingClass = LiteLLMLoggingObj
+ LiteLLMLoggingObj = _LiteLLMLoggingObj
else:
- LoggingClass = Any
+ LiteLLMLoggingObj = Any
-class ClarifaiConfig(BaseConfig):
+class ClarifaiConfig(OpenAIGPTConfig):
"""
- Reference: https://clarifai.com/meta/Llama-2/models/llama2-70b-chat
+ Configuration class for Clarifai chat completions.
+ Since Clarifai is OpenAI-compatible, we extend OpenAIGPTConfig.
"""
-
- max_tokens: Optional[int] = None
- temperature: Optional[int] = None
- top_k: Optional[int] = None
-
- def __init__(
- self,
- max_tokens: Optional[int] = None,
- temperature: Optional[int] = None,
- top_k: Optional[int] = None,
- ) -> None:
- locals_ = locals().copy()
- for key, value in locals_.items():
- if key != "self" and value is not None:
- setattr(self.__class__, key, value)
-
- @classmethod
- def get_config(cls):
- return super().get_config()
-
def get_supported_openai_params(self, model: str) -> list:
+ """
+ Get the supported OpenAI params for the given model
+ """
return [
- "temperature",
"max_tokens",
+ "max_completion_tokens",
+ "response_format",
+ "stream",
+ "temperature",
+ "top_p",
+ "tool_choice",
+ "tools",
+ "presence_penalty",
+ "frequency_penalty",
+ "stream_options",
]
-
- def map_openai_params(
- self,
- non_default_params: dict,
- optional_params: dict,
- model: str,
- drop_params: bool,
- ) -> dict:
- for param, value in non_default_params.items():
- if param == "temperature":
- optional_params["temperature"] = value
- elif param == "max_tokens":
- optional_params["max_tokens"] = value
-
- return optional_params
-
- def _completions_to_model(self, prompt: str, optional_params: dict) -> dict:
- params = {}
- if temperature := optional_params.get("temperature"):
- params["temperature"] = temperature
- if max_tokens := optional_params.get("max_tokens"):
- params["max_tokens"] = max_tokens
- return {
- "inputs": [{"data": {"text": {"raw": prompt}}}],
- "model": {"output_info": {"params": params}},
- }
-
- def _convert_model_to_url(self, model: str, api_base: str):
- user_id, app_id, model_id = model.split(".")
- return f"{api_base}/users/{user_id}/apps/{app_id}/models/{model_id}/outputs"
-
- def transform_request(
- self,
- model: str,
- messages: List[AllMessageValues],
- optional_params: dict,
- litellm_params: dict,
- headers: dict,
- ) -> dict:
- prompt = " ".join(convert_content_list_to_str(message) for message in messages)
-
- ## Load Config
- config = self.get_config()
- for k, v in config.items():
- if k not in optional_params:
- optional_params[k] = v
-
- data = self._completions_to_model(
- prompt=prompt, optional_params=optional_params
+
+ @staticmethod
+ def get_api_key(api_key: Optional[str] = None) -> Optional[str]:
+ return (
+ api_key
+ or get_secret_str("CLARIFAI_API_KEY")
)
+
+ @staticmethod
+ def get_api_base(api_base: Optional[str] = None) -> Optional[str]:
+ return api_base or "https://api.clarifai.com/v2/ext/openai/v1"
+
+ @staticmethod
+ def get_base_model(model: Optional[str] = None) -> Optional[str]:
+ if model:
+ user_id, app_id, model_id = model.split(".")
+ return f"https://clarifai.com/{user_id}/{app_id}/models/{model_id}"
+ return None
- return data
-
- def validate_environment(
+ def _get_openai_compatible_provider_info(
self,
- headers: dict,
- model: str,
- messages: List[AllMessageValues],
- optional_params: dict,
- litellm_params: dict,
- api_key: Optional[str] = None,
- api_base: Optional[str] = None,
- ) -> dict:
- headers = {
- "accept": "application/json",
- "content-type": "application/json",
- }
-
- if api_key:
- headers["Authorization"] = f"Bearer {api_key}"
- return headers
-
- def get_error_class(
- self, error_message: str, status_code: int, headers: Union[dict, httpx.Headers]
- ) -> BaseLLMException:
- return ClarifaiError(message=error_message, status_code=status_code)
-
+ api_base: Optional[str],
+ api_key: Optional[str],
+ ) -> Tuple[Optional[str], Optional[str]]:
+ """
+ Get API base and key for Clarifai provider.
+ """
+ api_base = api_base or "https://api.clarifai.com/v2/ext/openai/v1"
+ dynamic_api_key = api_key or get_secret_str("CLARIFAI_API_KEY") or ""
+ return api_base, dynamic_api_key
+
+ def transform_request(self, model, messages, optional_params, litellm_params, headers):
+ model = self.get_base_model(model) or model
+ return super().transform_request(model, messages, optional_params, litellm_params, headers)
+
def transform_response(
self,
model: str,
raw_response: httpx.Response,
model_response: ModelResponse,
- logging_obj: LoggingClass,
+ logging_obj: LiteLLMLoggingObj,
request_data: dict,
messages: List[AllMessageValues],
optional_params: dict,
litellm_params: dict,
- encoding: str,
+ encoding: Any,
api_key: Optional[str] = None,
json_mode: Optional[bool] = None,
) -> ModelResponse:
+ """
+ Transform the Clarifai response to a standard ModelResponse.
+ Since Clarifai is OpenAI-compatible, we use OpenAI response transformation.
+ """
+ ## Logging
logging_obj.post_call(
input=messages,
api_key=api_key,
original_response=raw_response.text,
additional_args={"complete_input_dict": request_data},
)
- ## RESPONSE OBJECT
+ ## Reponse
try:
completion_response = raw_response.json()
- except httpx.HTTPStatusError as e:
- raise ClarifaiError(
- message=str(e),
+ except Exception as e:
+ raise OpenAIError(
status_code=raw_response.status_code,
- )
- except Exception as e:
- raise ClarifaiError(
- message=str(e),
- status_code=422,
- )
- # print(completion_response)
- try:
- choices_list = []
- for idx, item in enumerate(completion_response["outputs"]):
- if len(item["data"]["text"]["raw"]) > 0:
- message_obj = Message(content=item["data"]["text"]["raw"])
- else:
- message_obj = Message(content=None)
- choice_obj = Choices(
- finish_reason="stop",
- index=idx + 1, # check
- message=message_obj,
- )
- choices_list.append(choice_obj)
- model_response.choices = choices_list # type: ignore
+ message=f"Failed to parse Clarifai response: {str(e)}",
+ headers=raw_response.headers,
+ ) from e
+
+ response = ModelResponse(**completion_response)
+
+ if response.model is not None:
+ response.model = "clarifai/" + model
- except Exception as e:
- raise ClarifaiError(
- message=str(e),
- status_code=422,
- )
+ return response
- # Calculate Usage
- prompt_tokens = token_counter(model=model, messages=messages)
- completion_tokens = len(
- encoding.encode(model_response["choices"][0]["message"].get("content"))
- )
- model_response.model = model
- setattr(
- model_response,
- "usage",
- Usage(
- prompt_tokens=prompt_tokens,
- completion_tokens=completion_tokens,
- total_tokens=prompt_tokens + completion_tokens,
- ),
- )
- return model_response
-
- def get_model_response_iterator(
- self,
- streaming_response: Union[Iterator[str], AsyncIterator[str], ModelResponse],
- sync_stream: bool,
- json_mode: Optional[bool] = False,
- ) -> Any:
- return ClarifaiModelResponseIterator(
- model_response=streaming_response,
- json_mode=json_mode,
- )
-
-
-class ClarifaiModelResponseIterator(FakeStreamResponseIterator):
- def __init__(
- self,
- model_response: Union[Iterator[str], AsyncIterator[str], ModelResponse],
- json_mode: Optional[bool] = False,
- ):
- super().__init__(
- model_response=model_response,
- json_mode=json_mode,
- )
-
- def chunk_parser(self, chunk: dict) -> GenericStreamingChunk:
- try:
- text = ""
- tool_use: Optional[ChatCompletionToolCallChunk] = None
- is_finished = False
- finish_reason = ""
- usage: Optional[ChatCompletionUsageBlock] = None
- provider_specific_fields = None
-
- text = (
- chunk.get("outputs", "")[0]
- .get("data", "")
- .get("text", "")
- .get("raw", "")
- )
-
- index: int = 0
-
- return GenericStreamingChunk(
- text=text,
- tool_use=tool_use,
- is_finished=is_finished,
- finish_reason=finish_reason,
- usage=usage,
- index=index,
- provider_specific_fields=provider_specific_fields,
- )
- except json.JSONDecodeError:
- raise ValueError(f"Failed to decode JSON from chunk: {chunk}")
+ def get_error_class(
+ self, error_message: str, status_code: int, headers: Union[dict, httpx.Headers]
+ ) -> BaseLLMException:
+ """
+ Get the appropriate error class for Clarifai errors.
+ Since Clarifai is OpenAI-compatible, we use OpenAI error handling.
+ """
+ return OpenAIError(
+ status_code=status_code,
+ message=error_message,
+ headers=headers,
+ )
\ No newline at end of file
diff --git a/litellm/llms/clarifai/common_utils.py b/litellm/llms/clarifai/common_utils.py
deleted file mode 100644
index 611d2ccf30b..00000000000
--- a/litellm/llms/clarifai/common_utils.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from litellm.llms.base_llm.chat.transformation import BaseLLMException
-
-
-class ClarifaiError(BaseLLMException):
- def __init__(self, status_code: int, message: str):
- super().__init__(status_code=status_code, message=message)
diff --git a/litellm/main.py b/litellm/main.py
index 5c50f096460..fa505f3fac5 100644
--- a/litellm/main.py
+++ b/litellm/main.py
@@ -154,6 +154,7 @@ from .llms.bedrock.chat import BedrockConverseLLM, BedrockLLM
from .llms.bedrock.embed.embedding import BedrockEmbedding
from .llms.bedrock.image.image_handler import BedrockImageGeneration
from .llms.bytez.chat.transformation import BytezChatConfig
+from .llms.clarifai.chat.transformation import ClarifaiConfig
from .llms.codestral.completion.handler import CodestralTextCompletion
from .llms.cohere.embed import handler as cohere_embed
from .llms.custom_httpx.aiohttp_handler import BaseLLMAIOHTTPHandler
@@ -2027,6 +2028,7 @@ def completion( # type: ignore # noqa: PLR0915
or custom_llm_provider == "together_ai"
or custom_llm_provider == "nebius"
or custom_llm_provider == "wandb"
+ or custom_llm_provider == "clarifai"
or custom_llm_provider in litellm.openai_compatible_providers
or "ft:gpt-3.5-turbo" in model # finetune gpt-3.5-turbo
): # allow user to make an openai call with a custom base
@@ -2221,40 +2223,7 @@ def completion( # type: ignore # noqa: PLR0915
or custom_llm_provider == "clarifai"
or model in litellm.clarifai_models
):
- clarifai_key = None
- clarifai_key = (
- api_key
- or litellm.clarifai_key
- or litellm.api_key
- or get_secret("CLARIFAI_API_KEY")
- or get_secret("CLARIFAI_API_TOKEN")
- )
-
- api_base = (
- api_base
- or litellm.api_base
- or get_secret("CLARIFAI_API_BASE")
- or "https://api.clarifai.com/v2"
- )
- api_base = litellm.ClarifaiConfig()._convert_model_to_url(model, api_base)
- response = base_llm_http_handler.completion(
- model=model,
- stream=stream,
- fake_stream=True, # clarifai does not support streaming, we fake it
- messages=messages,
- acompletion=acompletion,
- api_base=api_base,
- model_response=model_response,
- optional_params=optional_params,
- litellm_params=litellm_params,
- shared_session=shared_session,
- custom_llm_provider="clarifai",
- timeout=timeout,
- headers=headers,
- encoding=encoding,
- api_key=clarifai_key,
- logging_obj=logging, # model call logging done inside the class as we make need to modify I/O to fit aleph alpha's requirements
- )
+ pass # Deprecated - handled in the openai compatible provider section above
elif custom_llm_provider == "anthropic_text":
api_key = (
api_key
diff --git a/litellm/utils.py b/litellm/utils.py
index f017543ceaa..dd42f4aebf1 100644
--- a/litellm/utils.py
+++ b/litellm/utils.py
@@ -7360,6 +7360,8 @@ class ProviderConfigManager:
return VLLMModelInfo()
elif LlmProviders.LEMONADE == provider:
return litellm.LemonadeChatConfig()
+ elif LlmProviders.CLARIFAI == provider:
+ return litellm.ClarifaiConfig()
return None
@staticmethod