Skip to content
Open
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
6 changes: 5 additions & 1 deletion api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ OPENAI_API_KEY=your_openai_api_key # Required for embeddings and OpenAI m

# Optional API Keys
OPENROUTER_API_KEY=your_openrouter_api_key # Required only if using OpenRouter models
REQUESTY_API_KEY=your_requesty_api_key # Required only if using Requesty models
REQUESTY_BASE_URL=https://router.requesty.ai/v1 # Optional, use https://router.eu.requesty.ai/v1 for the EU region

# AWS Bedrock Configuration
AWS_ACCESS_KEY_ID=your_aws_access_key_id # Required for AWS Bedrock models
Expand All @@ -53,6 +55,7 @@ If you're not using Ollama mode, you need to configure an OpenAI API key for emb
> - Get a Google API key from [Google AI Studio](https://makersuite.google.com/app/apikey)
> - Get an OpenAI API key from [OpenAI Platform](https://platform.openai.com/api-keys)
> - Get an OpenRouter API key from [OpenRouter](https://openrouter.ai/keys)
> - Get a Requesty API key from [Requesty](https://app.requesty.ai/api-keys)
> - Get AWS credentials from [AWS IAM Console](https://console.aws.amazon.com/iam/)

#### Advanced Environment Configuration
Expand All @@ -63,6 +66,7 @@ DeepWiki supports multiple LLM providers. The environment variables above are re
- **Google Gemini**: Requires `GOOGLE_API_KEY`
- **OpenAI**: Requires `OPENAI_API_KEY`
- **OpenRouter**: Requires `OPENROUTER_API_KEY`
- **Requesty**: Requires `REQUESTY_API_KEY`
- **AWS Bedrock**: Requires `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
- **Ollama**: No API key required (runs locally)

Expand All @@ -83,7 +87,7 @@ DeepWiki now uses JSON configuration files to manage various system components i

1. **`generator.json`**: Configuration for text generation models
- Located in `api/config/` by default
- Defines available model providers (Google, OpenAI, OpenRouter, AWS Bedrock, Ollama)
- Defines available model providers (Google, OpenAI, OpenRouter, Requesty, AWS Bedrock, Ollama)
- Specifies default and available models for each provider
- Contains model-specific parameters like temperature and top_p

Expand Down
22 changes: 22 additions & 0 deletions api/chat/_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
LITELLM_API_KEY,
OPENAI_API_KEY,
OPENROUTER_API_KEY,
REQUESTY_API_KEY,
)
from api.logger import get_logger

Expand Down Expand Up @@ -228,6 +229,27 @@ def _build_client(self):
return LiteLLMClient()


class RequestyChatStreamer(_OpenAICompatStreamer):
provider = "requesty"
error_hint = (
"Please check that you have set the REQUESTY_API_KEY "
"environment variable with a valid API key."
)

def __init__(self, *, model: str, model_config: MODEL_CFG):
if not REQUESTY_API_KEY:
logger.warning(
"REQUESTY_API_KEY not configured, but continuing with request"
)

super().__init__(model=model, model_config=model_config)

def _build_client(self):
from api.clients import RequestyClient

return RequestyClient()


class BedrockChatStreamer(ChatStreamer):
provider = "bedrock"
error_hint = (
Expand Down
2 changes: 2 additions & 0 deletions api/clients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from .litellm import LiteLLMClient
from .ollama import OllamaClient
from .openrouter import OpenRouterClient
from .requesty import RequestyClient

__all__ = [
"AnthropicBedrockClient",
Expand All @@ -27,4 +28,5 @@
"OllamaClient",
"OpenAIClient",
"OpenRouterClient",
"RequestyClient",
]
101 changes: 101 additions & 0 deletions api/clients/requesty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""Requesty ModelClient integration."""

import os
from typing import Any, Dict, Literal, Optional

from adalflow.components.model_client.openai_client import OpenAIClient
from adalflow.core.types import ModelType
from openai import AsyncOpenAI, OpenAI

REQUESTY_DEFAULT_HEADERS = {
"HTTP-Referer": "https://github.com/AsyncFuncAI/deepwiki-open",
"X-Title": "DeepWiki",
}


class RequestyClient(OpenAIClient):
"""
Requesty OpenAI-compatible client.

Requesty is an LLM gateway that gives access to hundreds of models from
many providers through a single OpenAI-compatible endpoint, so we can
reuse almost all OpenAIClient behavior while overriding only the client
initialization.

Visit https://docs.requesty.ai for more details.

Expected environment variables:

REQUESTY_API_KEY=your_requesty_api_key
REQUESTY_BASE_URL=https://router.requesty.ai/v1 (optional, use https://router.eu.requesty.ai/v1 for EU)

Example model names:
openai/gpt-4o-mini
anthropic/claude-sonnet-4-5
google/gemini-2.5-flash
"""

def __init__(
self,
api_key: Optional[str] = None,
input_type: Literal["text", "messages"] = "text",
base_url: Optional[str] = None,
env_api_key_name: str = "REQUESTY_API_KEY",
):
resolved_base_url = base_url or os.getenv(
"REQUESTY_BASE_URL", "https://router.requesty.ai/v1"
)
super().__init__(
api_key=api_key,
input_type=input_type,
base_url=resolved_base_url,
env_api_key_name=env_api_key_name,
)

def _resolve_api_key(self) -> str:
api_key = self._api_key or os.getenv(self._env_api_key_name)
if not api_key:
raise ValueError(
f"Environment variable {self._env_api_key_name} must be set"
)
return api_key

def init_sync_client(self):
"""Initialize synchronous Requesty client."""
return OpenAI(
api_key=self._resolve_api_key(),
base_url=self.base_url,
default_headers=REQUESTY_DEFAULT_HEADERS,
)

def init_async_client(self):
"""Initialize asynchronous Requesty client."""
return AsyncOpenAI(
api_key=self._resolve_api_key(),
base_url=self.base_url,
default_headers=REQUESTY_DEFAULT_HEADERS,
)

def convert_inputs_to_api_kwargs(
self,
input: Optional[Any] = None,
model_kwargs: Optional[Dict] = None,
model_type: ModelType = ModelType.UNDEFINED,
) -> Dict:
"""Send a plain text prompt as a user message, like the OpenRouter client.

OpenAIClient sends a plain text prompt as a single system message, which
Anthropic and Gemini models reject.
"""
api_kwargs = super().convert_inputs_to_api_kwargs(
input=input, model_kwargs=model_kwargs or {}, model_type=model_type
)
messages = api_kwargs.get("messages")
if (
model_type == ModelType.LLM
and messages
and len(messages) == 1
and messages[0].get("role") == "system"
):
messages[0] = {"role": "user", "content": messages[0]["content"]}
return api_kwargs
6 changes: 6 additions & 0 deletions api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
OllamaClient,
OpenAIClient,
OpenRouterClient,
RequestyClient,
)
from api.logger import get_logger

Expand All @@ -30,6 +31,7 @@
LITELLM_API_KEY = os.environ.get("LITELLM_API_KEY")
GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY")
REQUESTY_API_KEY = os.environ.get("REQUESTY_API_KEY")
AWS_ACCESS_KEY_ID = os.environ.get("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ACCESS_KEY")
AWS_SESSION_TOKEN = os.environ.get("AWS_SESSION_TOKEN")
Expand All @@ -45,6 +47,8 @@
os.environ["GOOGLE_API_KEY"] = GOOGLE_API_KEY
if OPENROUTER_API_KEY:
os.environ["OPENROUTER_API_KEY"] = OPENROUTER_API_KEY
if REQUESTY_API_KEY:
os.environ["REQUESTY_API_KEY"] = REQUESTY_API_KEY
if AWS_ACCESS_KEY_ID:
os.environ["AWS_ACCESS_KEY_ID"] = AWS_ACCESS_KEY_ID
if AWS_SECRET_ACCESS_KEY:
Expand Down Expand Up @@ -74,6 +78,7 @@
OpenAIClient.__name__: OpenAIClient,
LiteLLMClient.__name__: LiteLLMClient,
OpenRouterClient.__name__: OpenRouterClient,
RequestyClient.__name__: RequestyClient,
OllamaClient.__name__: OllamaClient,
BedrockClient.__name__: BedrockClient,
AzureAIClient.__name__: AzureAIClient,
Expand All @@ -87,6 +92,7 @@
"openai": OpenAIClient,
"litellm": LiteLLMClient,
"openrouter": OpenRouterClient,
"requesty": RequestyClient,
"ollama": OllamaClient,
"bedrock": BedrockClient,
"azure": AzureAIClient,
Expand Down
28 changes: 28 additions & 0 deletions api/config/generator.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,34 @@
}
}
},
"requesty": {
"default_model": "openai/gpt-4o-mini",
"supportsCustomModel": true,
"models": {
"openai/gpt-4o-mini": {
"temperature": 0.7,
"top_p": 0.8
},
"openai/gpt-4.1": {
"temperature": 0.7,
"top_p": 0.8
},
"openai/gpt-5-mini": {
"temperature": 1.0
},
"anthropic/claude-sonnet-4-5": {
"temperature": 0.7
},
"google/gemini-2.5-flash": {
"temperature": 1.0,
"top_p": 0.8
},
"deepseek/deepseek-chat": {
"temperature": 0.7,
"top_p": 0.8
}
}
},
"ollama": {
"default_model": "qwen3:1.7b",
"supportsCustomModel": true,
Expand Down
28 changes: 28 additions & 0 deletions api/config/generator.litellm.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,34 @@
}
}
},
"requesty": {
"default_model": "openai/gpt-4o-mini",
"supportsCustomModel": true,
"models": {
"openai/gpt-4o-mini": {
"temperature": 0.7,
"top_p": 0.8
},
"openai/gpt-4.1": {
"temperature": 0.7,
"top_p": 0.8
},
"openai/gpt-5-mini": {
"temperature": 1.0
},
"anthropic/claude-sonnet-4-5": {
"temperature": 0.7
},
"google/gemini-2.5-flash": {
"temperature": 1.0,
"top_p": 0.8
},
"deepseek/deepseek-chat": {
"temperature": 0.7,
"top_p": 0.8
}
}
},
"ollama": {
"default_model": "qwen3:1.7b",
"supportsCustomModel": true,
Expand Down
1 change: 1 addition & 0 deletions src/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"providerGoogle": "Google",
"providerOpenAI": "OpenAI",
"providerOpenRouter": "OpenRouter",
"providerRequesty": "Requesty",
"providerOllama": "Ollama (Local)",
"localOllama": "Local Ollama Model",
"experimental": "Experimental",
Expand Down
1 change: 1 addition & 0 deletions src/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"providerGoogle": "Google",
"providerOpenAI": "OpenAI",
"providerOpenRouter": "OpenRouter",
"providerRequesty": "Requesty",
"providerOllama": "Ollama (Local)",
"localOllama": "Modelo Ollama Local",
"experimental": "Experimental",
Expand Down
1 change: 1 addition & 0 deletions src/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"providerGoogle": "Google",
"providerOpenAI": "OpenAI",
"providerOpenRouter": "OpenRouter",
"providerRequesty": "Requesty",
"providerOllama": "Ollama (Local)",
"localOllama": "Modèle Ollama local",
"experimental": "Expérimental",
Expand Down
1 change: 1 addition & 0 deletions src/messages/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"providerGoogle": "Google",
"providerOpenAI": "OpenAI",
"providerOpenRouter": "OpenRouter",
"providerRequesty": "Requesty",
"providerOllama": "Ollama(ローカル)",
"localOllama": "ローカルOllamaモデル",
"experimental": "実験的",
Expand Down
1 change: 1 addition & 0 deletions src/messages/kr.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"providerGoogle": "구글",
"providerOpenAI": "OpenAI",
"providerOpenRouter": "OpenRouter",
"providerRequesty": "Requesty",
"providerOllama": "Ollama (로컬)",
"localOllama": "로컬 Ollama 모델",
"experimental": "실험적",
Expand Down
1 change: 1 addition & 0 deletions src/messages/pt-br.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"providerGoogle": "Google",
"providerOpenAI": "OpenAI",
"providerOpenRouter": "OpenRouter",
"providerRequesty": "Requesty",
"providerOllama": "Ollama (Local)",
"localOllama": "Modelo Ollama Local",
"experimental": "Experimental",
Expand Down
1 change: 1 addition & 0 deletions src/messages/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"providerGoogle": "Google",
"providerOpenAI": "OpenAI",
"providerOpenRouter": "OpenRouter",
"providerRequesty": "Requesty",
"providerOllama": "Ollama (локально)",
"localOllama": "Локальная модель Ollama",
"experimental": "Экспериментально",
Expand Down
1 change: 1 addition & 0 deletions src/messages/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"providerGoogle": "Google",
"providerOpenAI": "OpenAI",
"providerOpenRouter": "OpenRouter",
"providerRequesty": "Requesty",
"providerOllama": "Ollama (Cục bộ)",
"localOllama": "Mô hình Ollama cục bộ",
"experimental": "Thử nghiệm",
Expand Down
1 change: 1 addition & 0 deletions src/messages/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"providerGoogle": "Google",
"providerOpenAI": "OpenAI",
"providerOpenRouter": "OpenRouter",
"providerRequesty": "Requesty",
"providerOllama": "Ollama(本機)",
"localOllama": "本機 Ollama 模型",
"experimental": "實驗性",
Expand Down
1 change: 1 addition & 0 deletions src/messages/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"providerGoogle": "Google",
"providerOpenAI": "OpenAI",
"providerOpenRouter": "OpenRouter",
"providerRequesty": "Requesty",
"providerOllama": "Ollama (本地)",
"localOllama": "本地Ollama模型",
"experimental": "实验性",
Expand Down
Loading