Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions docs/docs/ai/llm.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,68 @@ cocoindex.LlmSpec(

You can find the full list of models supported by Anthropic [here](https://docs.anthropic.com/en/docs/about-claude/models/all-models).

### LiteLLM

To use the LiteLLM API, you need to set the environment variable `LITELLM_API_KEY`.

#### 1. Install LiteLLM Proxy

```bash
pip install 'litellm[proxy]'
```

#### 2. Create a `config.yml` for LiteLLM

**Example for OpenAI:**
```yaml
model_list:
- model_name: "*"
litellm_params:
model: openai/*
api_key: os.environ/LITELLM_API_KEY
```

**Example for DeepSeek:**

First, pull the DeepSeek model with Ollama:
```bash
ollama pull deepseek-r1
```
Then run it if it's not running:
```bash
ollama run deepseek-r1
```

Then, use this in your `config.yml`:
```yaml
model_list:
- model_name: "deepseek-r1"
litellm_params:
model: "ollama_chat/deepseek-r1"
api_base: "http://localhost:11434"
```

#### 3. Run LiteLLM Proxy

```bash
litellm --config config.yml
```

#### 4. A Spec for LiteLLM will look like this:

<Tabs>
<TabItem value="python" label="Python" default>

```python
cocoindex.LlmSpec(
api_type=cocoindex.LlmApiType.LITELLM,
model="deepseek-r1",
address="http://127.0.0.1:4000", # default url of LiteLLM
)
```

</TabItem>
</Tabs>

You can find the full list of models supported by LiteLLM [here](https://docs.litellm.ai/docs/providers).

1 change: 1 addition & 0 deletions python/cocoindex/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class LlmApiType(Enum):
OLLAMA = "Ollama"
GEMINI = "Gemini"
ANTHROPIC = "Anthropic"
LITELLM = "LiteLlm"


@dataclass
Expand Down
16 changes: 16 additions & 0 deletions src/llm/litellm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use async_openai::config::OpenAIConfig;
use async_openai::Client as OpenAIClient;

pub use super::openai::Client;

impl Client {
pub async fn new_litellm(spec: super::LlmSpec) -> anyhow::Result<Self> {
let address = spec.address.clone().unwrap_or_else(|| "http://127.0.0.1:4000".to_string());
let api_key = std::env::var("LITELLM_API_KEY").ok();
let mut config = OpenAIConfig::new().with_api_base(address);
if let Some(api_key) = api_key {
config = config.with_api_key(api_key);
}
Ok(Client::from_parts(OpenAIClient::with_config(config), spec.model))
}
}
5 changes: 5 additions & 0 deletions src/llm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub enum LlmApiType {
OpenAi,
Gemini,
Anthropic,
LiteLlm,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -56,6 +57,7 @@ mod anthropic;
mod gemini;
mod ollama;
mod openai;
mod litellm;

pub async fn new_llm_generation_client(spec: LlmSpec) -> Result<Box<dyn LlmGenerationClient>> {
let client = match spec.api_type {
Expand All @@ -71,6 +73,9 @@ pub async fn new_llm_generation_client(spec: LlmSpec) -> Result<Box<dyn LlmGener
LlmApiType::Anthropic => {
Box::new(anthropic::Client::new(spec).await?) as Box<dyn LlmGenerationClient>
}
LlmApiType::LiteLlm => {
Box::new(litellm::Client::new_litellm(spec).await?) as Box<dyn LlmGenerationClient>
}
};
Ok(client)
}
4 changes: 4 additions & 0 deletions src/llm/openai.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ pub struct Client {
}

impl Client {
pub(crate) fn from_parts(client: async_openai::Client<OpenAIConfig>, model: String) -> Self {
Self { client, model }
}

pub async fn new(spec: super::LlmSpec) -> Result<Self> {
if let Some(address) = spec.address {
api_bail!("OpenAI doesn't support custom API address: {address}");
Expand Down
Loading