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

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 46 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
- **Ask Feature**: Chat with your repository using RAG-powered AI to get accurate answers
- **DeepResearch**: Multi-turn research process that thoroughly investigates complex topics
- **Multiple Model Providers**: Support for Google Gemini, OpenAI, OpenRouter, and local Ollama models
- **Flexible Embeddings**: Choose between OpenAI, Google AI, or local Ollama embeddings for optimal performance
- **Flexible Embeddings**: Choose between OpenAI, Google AI, OpenRouter, or local Ollama embeddings for optimal performance

## 🚀 Quick Start (Super Easy!)

Expand Down Expand Up @@ -341,6 +341,7 @@ docker-compose up
|------|-------------|------------------|-------|
| `openai` | OpenAI embeddings (default) | `OPENAI_API_KEY` | Uses `text-embedding-3-small` model |
| `google` | Google AI embeddings | `GOOGLE_API_KEY` | Uses `text-embedding-004` model |
| `openrouter` | OpenRouter embeddings | `OPENROUTER_API_KEY` | Uses `openai/text-embedding-3-small` via OpenRouter |
| `ollama` | Local Ollama embeddings | None | Requires local Ollama installation |

### Why Use Google AI Embeddings?
Expand All @@ -361,12 +362,52 @@ export DEEPWIKI_EMBEDDER_TYPE=openai
# Use Google AI embeddings
export DEEPWIKI_EMBEDDER_TYPE=google

# Use OpenRouter embeddings
export DEEPWIKI_EMBEDDER_TYPE=openrouter

# Use local Ollama embeddings
export DEEPWIKI_EMBEDDER_TYPE=ollama
```

**Note**: When switching embedders, you may need to regenerate your repository embeddings as different models produce different vector spaces.

## 🔀 Using OpenRouter Embeddings

DeepWiki supports OpenRouter as an embedding provider. OpenRouter exposes an OpenAI-compatible embeddings endpoint, so any embedding model available on OpenRouter can be used.

### How to Enable OpenRouter Embeddings

Set the embedder type and your OpenRouter API key in your `.env` file:

```bash
OPENROUTER_API_KEY=your_openrouter_api_key
DEEPWIKI_EMBEDDER_TYPE=openrouter
```

**Docker:**

```bash
docker run -p 8001:8001 -p 3000:3000 \
-e OPENROUTER_API_KEY=your_openrouter_api_key \
-e DEEPWIKI_EMBEDDER_TYPE=openrouter \
-v ~/.adalflow:/root/.adalflow \
ghcr.io/asyncfuncai/deepwiki-open:latest
```

### Changing the Embedding Model

The default model is `openai/text-embedding-3-small`. To use a different model, edit `api/config/embedder.json` and change the `model` field under `embedder_openrouter`:

```json
"embedder_openrouter": {
"model_kwargs": {
"model": "openai/text-embedding-3-large"
}
}
```

Any embedding model listed on [OpenRouter](https://openrouter.ai/models) that exposes an OpenAI-compatible embeddings endpoint can be used here.

### Logging

DeepWiki uses Python's built-in `logging` module for diagnostic output. You can configure the verbosity and log file destination via environment variables:
Expand Down Expand Up @@ -411,7 +452,7 @@ docker-compose up
|----------------------|--------------------------------------------------------------|----------|----------------------------------------------------------------------------------------------------------|
| `GOOGLE_API_KEY` | Google Gemini API key for AI generation and embeddings | No | Required for Google Gemini models and Google AI embeddings
| `OPENAI_API_KEY` | OpenAI API key for embeddings and models | Conditional | Required if using OpenAI embeddings or models |
| `OPENROUTER_API_KEY` | OpenRouter API key for alternative models | No | Required only if you want to use OpenRouter models |
| `OPENROUTER_API_KEY` | OpenRouter API key for alternative models and embeddings | No | Required if using OpenRouter models or `DEEPWIKI_EMBEDDER_TYPE=openrouter` |
| `AWS_ACCESS_KEY_ID` | AWS access key ID for Bedrock | No | Required for Bedrock if not using instance/role-based credentials |
| `AWS_SECRET_ACCESS_KEY` | AWS secret access key for Bedrock | No | Required for Bedrock if not using instance/role-based credentials |
| `AWS_SESSION_TOKEN` | AWS session token for Bedrock (STS) | No | Required when using temporary credentials |
Expand All @@ -421,15 +462,16 @@ docker-compose up
| `AZURE_OPENAI_ENDPOINT` | Azure OpenAI endpoint | No | Required only if you want to use Azure OpenAI models |
| `AZURE_OPENAI_VERSION` | Azure OpenAI version | No | Required only if you want to use Azure OpenAI models |
| `OLLAMA_HOST` | Ollama Host (default: http://localhost:11434) | No | Required only if you want to use external Ollama server |
| `DEEPWIKI_EMBEDDER_TYPE` | Embedder type: `openai`, `google`, `ollama`, or `bedrock` (default: `openai`) | No | Controls which embedding provider to use |
| `DEEPWIKI_EMBEDDER_TYPE` | Embedder type: `openai`, `google`, `ollama`, `bedrock`, or `openrouter` (default: `openai`) | No | Controls which embedding provider to use |
| `PORT` | Port for the API server (default: 8001) | No | If you host API and frontend on the same machine, make sure change port of `SERVER_BASE_URL` accordingly |
| `SERVER_BASE_URL` | Base URL for the API server (default: http://localhost:8001) | No |
| `DEEPWIKI_AUTH_MODE` | Set to `true` or `1` to enable authorization mode. | No | Defaults to `false`. If enabled, `DEEPWIKI_AUTH_CODE` is required. |
| `DEEPWIKI_AUTH_CODE` | The secret code required for wiki generation when `DEEPWIKI_AUTH_MODE` is enabled. | No | Only used if `DEEPWIKI_AUTH_MODE` is `true` or `1`. |

**API Key Requirements:**
- If using `DEEPWIKI_EMBEDDER_TYPE=openai` (default): `OPENAI_API_KEY` is required
- If using `DEEPWIKI_EMBEDDER_TYPE=google`: `GOOGLE_API_KEY` is required
- If using `DEEPWIKI_EMBEDDER_TYPE=google`: `GOOGLE_API_KEY` is required
- If using `DEEPWIKI_EMBEDDER_TYPE=openrouter`: `OPENROUTER_API_KEY` is required
- If using `DEEPWIKI_EMBEDDER_TYPE=ollama`: No API key required (local processing)
- If using `DEEPWIKI_EMBEDDER_TYPE=bedrock`: AWS credentials (or role-based credentials) are required

Expand Down
4 changes: 2 additions & 2 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ GOOGLE_API_KEY=your_google_api_key # Required for Google Gemini models
OPENAI_API_KEY=your_openai_api_key # Required for embeddings and OpenAI models

# Optional API Keys
OPENROUTER_API_KEY=your_openrouter_api_key # Required only if using OpenRouter models
OPENROUTER_API_KEY=your_openrouter_api_key # Required if using OpenRouter models or embeddings (DEEPWIKI_EMBEDDER_TYPE=openrouter)

# AWS Bedrock Configuration
AWS_ACCESS_KEY_ID=your_aws_access_key_id # Required for AWS Bedrock models
Expand All @@ -47,7 +47,7 @@ OLLAMA_HOST=https://your_ollama_host" # Optional: Add Ollama host if not local.
PORT=8001 # Optional, defaults to 8001
```

If you're not using Ollama mode, you need to configure an OpenAI API key for embeddings. Other API keys are only required when configuring and using models from the corresponding providers.
The embedder type is controlled by `DEEPWIKI_EMBEDDER_TYPE` (`openai`, `google`, `openrouter`, `ollama`, or `bedrock`; default: `openai`). The corresponding API key is required for the chosen embedder. Other API keys are only required when configuring and using models from the corresponding providers.

> 💡 **Where to get these keys:**
> - Get a Google API key from [Google AI Studio](https://makersuite.google.com/app/apikey)
Expand Down
38 changes: 34 additions & 4 deletions api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def load_embedder_config():
embedder_config = load_json_config("embedder.json")

# Process client classes
for key in ["embedder", "embedder_ollama", "embedder_google", "embedder_bedrock"]:
for key in ["embedder", "embedder_ollama", "embedder_google", "embedder_bedrock", "embedder_openrouter"]:
if key in embedder_config and "client_class" in embedder_config[key]:
class_name = embedder_config[key]["client_class"]
if class_name in CLIENT_CLASSES:
Expand All @@ -174,6 +174,8 @@ def get_embedder_config():
return configs.get("embedder_google", {})
elif embedder_type == 'ollama' and 'embedder_ollama' in configs:
return configs.get("embedder_ollama", {})
elif embedder_type == 'openrouter' and 'embedder_openrouter' in configs:
return configs.get("embedder_openrouter", {})
else:
return configs.get("embedder", {})

Expand Down Expand Up @@ -235,19 +237,47 @@ def is_bedrock_embedder():
client_class = embedder_config.get("client_class", "")
return client_class == "BedrockClient"

def is_openrouter_embedder():
"""
Check if the current embedder configuration uses OpenRouter for embeddings.

Detects OpenRouter by inspecting the loaded configuration's initialize_kwargs
for a base_url pointing to openrouter.ai, consistent with how other is_*_embedder
helpers inspect the config rather than reading environment variables directly.

Returns:
bool: True if using OpenRouter for embeddings, False otherwise
"""
embedder_config = get_embedder_config()
if not embedder_config:
return False

initialize_kwargs = embedder_config.get("initialize_kwargs", {})
base_url = initialize_kwargs.get("base_url", "")
if base_url and "openrouter.ai" in base_url:
return True

# Fallback: explicit OpenRouterClient class
model_client = embedder_config.get("model_client")
if model_client:
return model_client.__name__ == "OpenRouterClient"
return embedder_config.get("client_class", "") == "OpenRouterClient"

def get_embedder_type():
"""
Get the current embedder type based on configuration.

Returns:
str: 'bedrock', 'ollama', 'google', or 'openai' (default)
str: 'bedrock', 'ollama', 'google', 'openrouter', or 'openai' (default)
"""
if is_bedrock_embedder():
return 'bedrock'
elif is_ollama_embedder():
return 'ollama'
elif is_google_embedder():
return 'google'
elif is_openrouter_embedder():
return 'openrouter'
else:
return 'openai'

Expand Down Expand Up @@ -341,7 +371,7 @@ def load_lang_config():

# Update embedder configuration
if embedder_config:
for key in ["embedder", "embedder_ollama", "embedder_google", "embedder_bedrock", "retriever", "text_splitter"]:
for key in ["embedder", "embedder_ollama", "embedder_google", "embedder_bedrock", "embedder_openrouter", "retriever", "text_splitter"]:
if key in embedder_config:
configs[key] = embedder_config[key]

Expand Down
12 changes: 12 additions & 0 deletions api/config/embedder.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@
"dimensions": 256
}
},
"embedder_openrouter": {
"client_class": "OpenAIClient",
"initialize_kwargs": {
"base_url": "https://openrouter.ai/api/v1",
"env_api_key_name": "OPENROUTER_API_KEY"
},
"batch_size": 500,
"model_kwargs": {
"model": "openai/text-embedding-3-small",
"encoding_format": "float"
}
},
"retriever": {
"top_k": 20
},
Expand Down
6 changes: 5 additions & 1 deletion api/tools/embedder.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def get_embedder(is_local_ollama: bool = False, use_google_embedder: bool = Fals
Args:
is_local_ollama: Legacy parameter for Ollama embedder
use_google_embedder: Legacy parameter for Google embedder
embedder_type: Direct specification of embedder type ('ollama', 'google', 'bedrock', 'openai')
embedder_type: Direct specification of embedder type ('ollama', 'google', 'bedrock', 'openrouter', 'openai')

Returns:
adal.Embedder: Configured embedder instance
Expand All @@ -22,6 +22,8 @@ def get_embedder(is_local_ollama: bool = False, use_google_embedder: bool = Fals
embedder_config = configs["embedder_google"]
elif embedder_type == 'bedrock':
embedder_config = configs["embedder_bedrock"]
elif embedder_type == 'openrouter':
embedder_config = configs["embedder_openrouter"]
else: # default to openai
embedder_config = configs["embedder"]
elif is_local_ollama:
Expand All @@ -37,6 +39,8 @@ def get_embedder(is_local_ollama: bool = False, use_google_embedder: bool = Fals
embedder_config = configs["embedder_ollama"]
elif current_type == 'google':
embedder_config = configs["embedder_google"]
elif current_type == 'openrouter':
embedder_config = configs["embedder_openrouter"]
else:
embedder_config = configs["embedder"]

Expand Down