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
4 changes: 3 additions & 1 deletion src/pygpt_net/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ def run(**kwargs):
from pygpt_net.provider.llms.perplexity import PerplexityLLM
from pygpt_net.provider.llms.x_ai import xAILLM
from pygpt_net.provider.llms.open_router import OpenRouterLLM
from pygpt_net.provider.llms.api_route import APIRouteLLM
from pygpt_net.provider.llms.litellm import LiteLLMProvider
from pygpt_net.provider.llms.forge import ForgeLLM
from pygpt_net.provider.llms.edenai import EdenAILLM
Expand Down Expand Up @@ -492,6 +493,7 @@ def run(**kwargs):
launcher.add_llm(PerplexityLLM())
launcher.add_llm(xAILLM())
launcher.add_llm(OpenRouterLLM())
launcher.add_llm(APIRouteLLM())
launcher.add_llm(ForgeLLM())
launcher.add_llm(EdenAILLM())
launcher.add_llm(LiteLLMProvider())
Expand Down Expand Up @@ -584,4 +586,4 @@ def run(**kwargs):


if __name__ == '__main__':
run()
run()
16 changes: 15 additions & 1 deletion src/pygpt_net/controller/model/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,20 @@ def get_provider_available(self) -> Dict:
'type': 'str'
}
]
elif self.provider == "api_route":
m.tool_calls = True
m.llama_index['args'].extend([
{
'name': 'api_key',
'value': '{api_key_api_route}',
'type': 'str'
},
{
'name': 'api_base',
'value': '{api_endpoint_api_route}',
'type': 'str'
}
])
elif self.provider == "x_ai":
m.tool_calls = True
m.llama_index['env'] = [
Expand Down Expand Up @@ -807,4 +821,4 @@ def hook_update(
self.provider = value
self.init(reload=True, on_change=True)
if value == "_":
self.set_status("")
self.set_status("")
8 changes: 8 additions & 0 deletions src/pygpt_net/core/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,14 @@ def prepare_client_args(
args["api_key"] = cfg.get('api_key_open_router', "")
args["base_url"] = cfg.get('api_endpoint_open_router', "")
self.window.core.debug.info("[api] Using client: OpenRouter API")
elif model.provider == "api_route":
args["api_key"] = cfg.get('api_key_api_route', "") or os.environ.get(
"API_ROUTE_API_KEY", ""
)
args["base_url"] = cfg.get('api_endpoint_api_route', "") or os.environ.get(
"API_ROUTE_API_BASE", "https://global.api-route.com/v1"
)
self.window.core.debug.info("[api] Using client: API Route")
elif model.provider == "forge":
args["api_key"] = cfg.get('api_key_forge', "") or os.environ.get("FORGE_API_KEY", "")
args["base_url"] = cfg.get('api_endpoint_forge', "") or os.environ.get(
Expand Down
1 change: 1 addition & 0 deletions src/pygpt_net/core/types/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"deepseek_api",
"x_ai",
"open_router",
"api_route",
"forge",
"edenai",
]
Expand Down
2 changes: 2 additions & 0 deletions src/pygpt_net/data/config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"api_azure_endpoint": "https://<your-resource-name>.openai.azure.com/",
"api_azure_version": "2023-07-01-preview",
"api_endpoint": "https://api.openai.com/v1",
"api_endpoint_api_route": "https://global.api-route.com/v1",
"api_endpoint_anthropic": "https://api.anthropic.com/v1",
"api_endpoint_deepseek": "https://api.deepseek.com/v1",
"api_endpoint_edenai": "https://api.edenai.run/v3",
Expand All @@ -84,6 +85,7 @@
"api_endpoint_perplexity": "https://api.perplexity.ai",
"api_endpoint_xai": "https://api.x.ai/v1",
"api_key": "",
"api_key_api_route": "",
"api_key_anthropic": "",
"api_key_deepseek": "",
"api_key_edenai": "",
Expand Down
37 changes: 37 additions & 0 deletions src/pygpt_net/data/config/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,43 @@
"advanced": false,
"tab": "OpenRouter"
},
"api_key_api_route": {
"section": "api_keys",
"type": "text",
"slider": false,
"label": "settings.api_key.api_route",
"description": "settings.api_key.api_route.desc",
"value": "",
"min": null,
"max": null,
"multiplier": null,
"step": null,
"extra": {
"bold": true
},
"urls": {
"API Keys": "https://www.api-route.com/api-keys"
},
"secret": true,
"persist": true,
"advanced": false,
"tab": "API Route"
},
"api_endpoint_api_route": {
"section": "api_keys",
"type": "text",
"slider": false,
"label": "settings.api_endpoint_api_route",
"description": "settings.api_endpoint_api_route.desc",
"value": "https://global.api-route.com/v1",
"min": null,
"max": null,
"multiplier": null,
"step": null,
"secret": false,
"advanced": false,
"tab": "API Route"
},
"api_key_forge": {
"section": "api_keys",
"type": "text",
Expand Down
5 changes: 5 additions & 0 deletions src/pygpt_net/data/locale/locale.en.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,8 @@ settings.api_azure_endpoint.desc = Azure OpenAI API endpoint, https://<your-reso
settings.api_azure_version = OpenAI API version
settings.api_azure_version.desc = Azure OpenAI API version, e.g., 2023-07-01-preview
settings.api_endpoint = API Endpoint
settings.api_endpoint_api_route = API Endpoint
settings.api_endpoint_api_route.desc = API Route endpoint URL, default: https://global.api-route.com/v1
settings.api_endpoint_anthropic = API Endpoint
settings.api_endpoint_anthropic.desc = Anthropic API endpoint URL, default: https://api.anthropic.com/v1
settings.api_endpoint_deepseek = API Endpoint
Expand All @@ -1295,6 +1297,8 @@ settings.api_endpoint_perplexity.desc = Perplexity API endpoint URL, default: ht
settings.api_endpoint_xai = API Endpoint
settings.api_endpoint_xai.desc = xAI API endpoint URL, default: https://api.x.ai/v1
settings.api_key = OpenAI API key
settings.api_key.api_route = API Route API key
settings.api_key.api_route.desc = Required for the API Route API.
settings.api_key.anthropic = Anthropic API key
settings.api_key.anthropic.desc = Required for the Anthropic API and Claude models.
settings.api_key.deepseek = DeepSeek API key
Expand Down Expand Up @@ -1697,6 +1701,7 @@ settings.section.agent.llama = Agents
settings.section.agent.general = General / v2
settings.section.agent.legacy = Legacy
settings.section.api_keys = API Keys
settings.section.api_keys.api_route = API Route
settings.section.api_keys.anthropic = Anthropic
settings.section.api_keys.azure_openai = Azure OpenAI
settings.section.api_keys.eden_ai = Eden AI
Expand Down
66 changes: 66 additions & 0 deletions src/pygpt_net/provider/llms/api_route.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ================================================== #
# This file is a part of PYGPT package #
# Website: https://pygpt.net #
# GitHub: https://github.com/szczyglis-dev/py-gpt #
# MIT License #
# Created By : Marcin Szczygliński #
# Updated Date: 2026.09.08 00:00:00 #
# ================================================== #

import os
from typing import Dict, List

from llama_index.core.llms.llm import BaseLLM as LlamaBaseLLM

from pygpt_net.core.types import MODE_LLAMA_INDEX
from pygpt_net.item.model import ModelItem
from pygpt_net.provider.llms.base import BaseLLM


API_ROUTE_DEFAULT_BASE_URL = "https://global.api-route.com/v1"


class APIRouteLLM(BaseLLM):
def __init__(self, *args, **kwargs):
super(APIRouteLLM, self).__init__(*args, **kwargs)
self.id = "api_route"
self.name = "API Route"
self.type = [MODE_LLAMA_INDEX]

def _apply_auth(self, args: Dict, window) -> Dict:
if "api_key" not in args or args["api_key"] == "":
args["api_key"] = os.environ.get("API_ROUTE_API_KEY") or window.core.config.get(
"api_key_api_route", ""
)
if "api_base" not in args or args["api_base"] == "":
args["api_base"] = os.environ.get("API_ROUTE_API_BASE") or window.core.config.get(
"api_endpoint_api_route", ""
) or API_ROUTE_DEFAULT_BASE_URL
return args

def llama(self, window, model: ModelItem, stream: bool = False) -> LlamaBaseLLM:
from llama_index.llms.openai_like import OpenAILike

args = self.parse_args(model.llama_index, window)
if "model" not in args:
args["model"] = model.id
args = self._apply_auth(args, window)
if "is_chat_model" not in args:
args["is_chat_model"] = True
if "is_function_calling_model" not in args:
args["is_function_calling_model"] = model.tool_calls
args = self.inject_llamaindex_http_clients(args, window.core.config)
return OpenAILike(**args)

def get_models(self, window) -> List[Dict]:
items = []
models_list = self.get_client(window).models.list()
if models_list.data:
for item in models_list.data:
items.append({
"id": item.id,
"name": item.id,
})
return items