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
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ GPT2GIGA_LOG_LEVEL=INFO
GPT2GIGA_ENABLE_API_KEY_AUTH=True
GPT2GIGA_API_KEY="<REPLACE_WITH_STRONG_SECRET>"

# Включить reasoning по умолчанию (добавляет reasoning_effort="high" в запросы к GigaChat,
# если клиент не указал reasoning_effort явно).
# GPT2GIGA_ENABLE_REASONING=False

# Глобальный лимит размера HTTP-тела запроса (в байтах, по умолчанию 10 МБ).
# GPT2GIGA_MAX_REQUEST_BODY_BYTES=10485760

Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.0.0/),
и проект придерживается [Семантического версионирования](https://semver.org/lang/ru/).

## [0.1.3.post1] - 2026-02-20

### Добавлено
- **Traefik**: Добавлена интеграция Traefik
- **MITMProxy**: Добавлен mitmproxy в `docker-compose-observability.yaml`
- **Reasoning toggle**: Добавлена переменная окружения `GPT2GIGA_ENABLE_REASONING`

### Изменено
- **Docker Compose профили**: Профиль `dev` установлен как профиль по умолчанию

## [0.1.3] - 2026-02-16

### Добавлено
Expand Down Expand Up @@ -164,6 +174,7 @@

---

[0.1.3.post1]: https://github.com/ai-forever/gpt2giga/compare/v0.1.3...v0.1.3.post1
[0.1.3]: https://github.com/ai-forever/gpt2giga/compare/v0.1.2.post1...v0.1.3
[0.1.2.post1]: https://github.com/ai-forever/gpt2giga/compare/v0.1.2...v0.1.2.post1
[0.1.2]: https://github.com/ai-forever/gpt2giga/compare/v0.1.1...v0.1.2
Expand Down
13 changes: 12 additions & 1 deletion CHANGELOG_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to the gpt2giga project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.3.post1] - 2026-02-20

### Added
- **Traefik**: Added Traefik integration
- **MITMProxy**: Added mitmproxy to `docker-compose-observability.yaml`
- **Reasoning toggle**: Added `GPT2GIGA_ENABLE_REASONING` environment variable

### Changed
- **Docker Compose profiles**: Set `dev` as the default profile

## [0.1.3] - 2026-02-16

### Added
Expand All @@ -13,7 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Graceful shutdown**: Added graceful server shutdown handling
- **Gitleaks**: Added gitleaks to pre-commit for secret detection
- **OpenAPI for count_tokens**: Added OpenAPI documentation for count_tokens endpoint
- - **Profiles in Docker**: Added profiles DEV and PROD in `docker-compose.yaml`
- **Profiles in Docker**: Added profiles DEV and PROD in `docker-compose.yaml`

### Changed
- **Structure Refactoring**: Split large files into modules:
Expand Down Expand Up @@ -164,6 +174,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

---

[0.1.3.post1]: https://github.com/ai-forever/gpt2giga/compare/v0.1.3...v0.1.3.post1
[0.1.3]: https://github.com/ai-forever/gpt2giga/compare/v0.1.2.post1...v0.1.3
[0.1.2.post1]: https://github.com/ai-forever/gpt2giga/compare/v0.1.2...v0.1.2.post1
[0.1.2]: https://github.com/ai-forever/gpt2giga/compare/v0.1.1...v0.1.2
Expand Down
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
2. [Возможности gpt2giga](#возможности-gpt2giga)
3. [Начало работы](#начало-работы)
1. [Запуск в Docker](#запуск-в-docker)
2. [Локальный запуск](#локальный-запуск)
2. [Запуск в Docker с Traefik](#запуск-в-docker-с-traefik)
3. [Локальный запуск](#локальный-запуск)
4. [Примеры](#примеры)
5. [Параметры](#изменение-параметров-gpt2giga)
1. [Аргументы командной строки](#аргументы-командной-строки)
Expand Down Expand Up @@ -92,7 +93,11 @@ sequenceDiagram
GIGACHAT_VERIFY_SSL_CERTS=True
```

3. (Опционально) Выберите образ с нужной версией Python (3.10–3.14) и обновите `image:` в `docker-compose.yaml`.
3. (Опционально) Используйте образ/сборку с нужной версией Python (3.10–3.14).

В `docker-compose.yaml` по умолчанию задан `image: ghcr.io/ai-forever/gpt2giga:latest` и `build.args.PYTHON_VERSION`. При необходимости:
- обновите `build.args.PYTHON_VERSION` (если собираете образ локально);
- или замените `image:` на нужный тег из реестра.

```sh
PYTHON_VERSION=3.10
Expand All @@ -113,6 +118,24 @@ sequenceDiagram
docker compose --profile DEV up -d
```

> В профиле `PROD` порт по умолчанию пробрасывается только на `127.0.0.1` (см. `docker-compose.yaml`). Для доступа извне используйте reverse proxy (nginx/Traefik/Caddy) или измените bind-адрес в `ports:`.

### Запуск в Docker с Traefik

В репозитории есть готовый стек `Traefik + несколько инстансов gpt2giga` в файле [`docker-compose.traefik.yaml`](./docker-compose.traefik.yaml):
- `gpt2giga` (модель по умолчанию `GigaChat`) → `http://localhost:8090`
- `gpt2giga-pro` (модель по умолчанию `GigaChat-Pro`) → `http://localhost:8091`
- `gpt2giga-max` (модель по умолчанию `GigaChat-Max`) → `http://localhost:8092`
- Traefik Dashboard → `http://localhost:8080/dashboard/`

1. Запустите стек:

```sh
docker compose -f docker-compose.traefik.yaml up -d
```

> Важно: роутинг в Traefik в этой конфигурации завязан на HTTP `Host` (см. `traefik/rules.yml`). Если вы обращаетесь по IP (например, `127.0.0.1`), задайте `HOST=127.0.0.1` или отправляйте корректный заголовок `Host:`.

### Локальный запуск

Для управления зависимостями и запуска проекта рекомендуется использовать [uv](https://github.com/astral-sh/uv).
Expand Down Expand Up @@ -189,6 +212,7 @@ sequenceDiagram
- `--proxy.pass-token <true/false>` — передавать токен, полученный в заголовке `Authorization`, в GigaChat API. С помощью него можно настраивать передачу ключей в GigaChat через `OPENAI_API_KEY`;
- `--proxy.embeddings <EMBED_MODEL>` — модель, которая будет использоваться для создания эмбеддингов. По умолчанию `EmbeddingsGigaR`;
- `--proxy.enable-images <true/false>` — включить/выключить передачу изображений в формате OpenAI в GigaChat API (по умолчанию `True`);
- `--proxy.enable-reasoning <true/false>` — включить reasoning по умолчанию (добавляет `reasoning_effort="high"` в payload к GigaChat, если клиент не указал `reasoning_effort` явно);
- `--proxy.log-level` — уровень логов `{CRITICAL,ERROR,WARNING,INFO,DEBUG}`. По умолчанию `INFO`;
- `--proxy.log-filename` — имя лог файла. По умолчанию `gpt2giga.log`;
- `--proxy.log-max-size` — максимальный размер файла в байтах. По умолчанию `10 * 1024 * 1024` (10 MB);
Expand Down Expand Up @@ -257,6 +281,7 @@ gpt2giga \
- `GPT2GIGA_PASS_TOKEN="False"` — передавать токен, полученный в заголовке `Authorization`, в GigaChat API;
- `GPT2GIGA_EMBEDDINGS="EmbeddingsGigaR"` — модель для создания эмбеддингов.
- `GPT2GIGA_ENABLE_IMAGES="True"` — флаг, который включает передачу изображений в формате OpenAI в GigaChat API;
- `GPT2GIGA_ENABLE_REASONING="False"` — включить reasoning по умолчанию (добавляет `reasoning_effort="high"` в payload к GigaChat, если клиент не указал `reasoning_effort` явно);
- `GPT2GIGA_LOG_LEVEL="INFO"` — Уровень логов `{CRITICAL,ERROR,WARNING,INFO,DEBUG}`. По умолчанию `INFO`
- `GPT2GIGA_LOG_FILENAME="gpt2giga.log"` — Имя лог файла. По умолчанию `gpt2giga.log`
- `GPT2GIGA_LOG_MAX_SIZE="10*1024*1024"` Максимальный размер файла в байтах. По умолчанию `10 * 1024 * 1024` (10 MB)
Expand Down Expand Up @@ -323,6 +348,9 @@ GPT2GIGA_HTTPS_CERT_FILE="Path to cert.pem"
```
После этого укажите пути к сертификатам в переменных окружения или CLI-аргументах и включите HTTPS.

Альтернатива: разместите `gpt2giga` за reverse proxy с TLS-терминацией:
- пример стека с Traefik: [`docker-compose.traefik.yaml`](./docker-compose.traefik.yaml) и правила в `traefik/` (при необходимости добавьте ACME/сертификаты под свой домен).

## Использование API ключа
```dotenv
GPT2GIGA_ENABLE_API_KEY_AUTH=True
Expand Down
54 changes: 54 additions & 0 deletions docker-compose-observability.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
x-gpt2giga-common: &gpt2giga-common
image: ghcr.io/ai-forever/gpt2giga:latest
restart: unless-stopped
env_file:
- .env

x-mitmproxy-common: &mitmproxy-common
restart: always
container_name: mitmproxy
image: mitmproxy/mitmproxy:latest
volumes:
- ~/.mitmproxy:/home/mitmproxy/.mitmproxy
command: mitmweb --web-host 0.0.0.0 --web-port 8081 --ssl-insecure
stdin_open: true
tty: true
services:
gpt2giga-prod:
<<: *gpt2giga-common
profiles: ["PROD"]
pull_policy: always
container_name: gpt2giga
environment:
GPT2GIGA_MODE: "PROD"
ports:
- "127.0.0.1:${GPT2GIGA_PORT:-8090}:${GPT2GIGA_PORT:-8090}"

gpt2giga-dev:
<<: *gpt2giga-common
profiles: ["DEV"]
build:
context: .
dockerfile: Dockerfile
args:
PYTHON_VERSION: "3.13"
container_name: gpt2giga
environment:
GPT2GIGA_MODE: "DEV"
ports:
- "${GPT2GIGA_PORT:-8090}:${GPT2GIGA_PORT:-8090}"


mitmproxy-prod:
<<: *mitmproxy-common
profiles: ["PROD"]
ports:
- "8080:8080"
- "127.0.0.1:8081:8081"

mitmproxy-dev:
<<: *mitmproxy-common
profiles: [ "DEV" ]
ports:
- "8080:8080"
- "8081:8081"
73 changes: 73 additions & 0 deletions docker-compose.traefik.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
x-gpt2giga-common: &gpt2giga-common
image: ghcr.io/ai-forever/gpt2giga:latest
restart: unless-stopped
env_file:
- .env
build:
context: .
dockerfile: Dockerfile

services:
gpt2giga:
<<: *gpt2giga-common
pull_policy: always
container_name: gpt2giga
environment:
GIGACHAT_MODEL: GigaChat
networks:
gpt2giga:
aliases:
- gpt2giga

gpt2giga-pro:
<<: *gpt2giga-common
pull_policy: always
container_name: gpt2giga_pro
environment:
GIGACHAT_MODEL: GigaChat-Pro
networks:
gpt2giga:
aliases:
- gpt2giga-pro

gpt2giga-max:
<<: *gpt2giga-common
pull_policy: always
container_name: gpt2giga_max
environment:
GIGACHAT_MODEL: GigaChat-Max
networks:
gpt2giga:
aliases:
- gpt2giga-max

traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- 80:80
- 443:443
- 8080:8080
- 8090:8090
- 8091:8091
- 8092:8092
environment:
HOST: ${HOST:-localhost}
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro
- ./traefik/:/etc/traefik/rules/:ro
depends_on:
- gpt2giga
- gpt2giga-pro
- gpt2giga-max
networks:
gpt2giga:
aliases:
- traefik
networks:
gpt2giga:
17 changes: 8 additions & 9 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
x-gpt2giga-common: &gpt2giga-common
image: ghcr.io/ai-forever/gpt2giga:latest
restart: unless-stopped
pull_policy: always
build:
context: .
dockerfile: Dockerfile
args:
PYTHON_VERSION: "3.13"
container_name: gpt2giga
env_file:
- .env

services:
gpt2giga-prod:
<<: *gpt2giga-common
profiles: ["PROD"]
pull_policy: always
container_name: gpt2giga
environment:
GPT2GIGA_MODE: "PROD"
ports:
- "127.0.0.1:${GPT2GIGA_PORT:-8090}:${GPT2GIGA_PORT:-8090}"

gpt2giga-dev:
<<: *gpt2giga-common
profiles: ["DEV"]
build:
context: .
dockerfile: Dockerfile
args:
PYTHON_VERSION: "3.13"
container_name: gpt2giga
profiles: ["", "DEV"]
environment:
GPT2GIGA_MODE: "DEV"
ports:
Expand Down
7 changes: 7 additions & 0 deletions gpt2giga/models/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ class ProxySettings(BaseSettings):
enable_images: bool = Field(
default=True, description="Включить загрузку изображений"
)
enable_reasoning: bool = Field(
default=False,
description=(
"Включить reasoning по умолчанию: добавляет reasoning_effort='high' "
"в payload к GigaChat, если клиент не указал reasoning_effort явно"
),
)
max_request_body_bytes: int = Field(
default=DEFAULT_MAX_REQUEST_BODY_BYTES,
description="Глобальный лимит размера HTTP-тела запроса в байтах (до парсинга JSON)",
Expand Down
10 changes: 6 additions & 4 deletions gpt2giga/protocol/request/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,9 @@ async def transform_messages(
# Process tool_calls
if "tool_calls" in message and message["tool_calls"]:
message["function_call"] = message["tool_calls"][0]["function"]
if (
isinstance(message.get("function_call"), dict)
and message["function_call"].get("name")
):
if isinstance(message.get("function_call"), dict) and message[
"function_call"
].get("name"):
message["function_call"]["name"] = map_tool_name_to_gigachat(
message["function_call"]["name"]
)
Expand Down Expand Up @@ -248,6 +247,9 @@ def _transform_common_parameters(self, data: Dict) -> Dict:
"""Common parameter transformation logic for Chat Completions and Responses API."""
transformed = data.copy()

if getattr(self.config.proxy_settings, "enable_reasoning", False):
transformed.setdefault("reasoning_effort", "high")

gpt_model = data.get("model", None)
if not self.config.proxy_settings.pass_model and gpt_model:
del transformed["model"]
Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ dev = [
"ruff (>=0.14.2,<0.15.0)",
"pytest-cov (>=7.0.0,<8.0.0)",
"pre-commit (>=4.3.0,<5.0.0)",
"codeflash (>=0.18.3,<0.19.0)",
]
integrations = [
"openai-agents (>=0.8.0,<0.9.0)",
Expand Down
3 changes: 2 additions & 1 deletion tests/test_api_server/test_api_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ def test_docs_disabled_in_prod_mode():
assert client.get("/openapi.json").status_code == 404


def test_prod_mode_requires_api_key():
def test_prod_mode_requires_api_key(monkeypatch):
import pytest

monkeypatch.delenv("GPT2GIGA_API_KEY", raising=False)
with pytest.raises(RuntimeError, match="API key must be configured"):
create_app(config=ProxyConfig(proxy=ProxySettings(mode="PROD")))

Expand Down
3 changes: 3 additions & 0 deletions tests/test_api_server/test_api_server_lifespan.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@


def test_app_lifespan_initializes_state(monkeypatch):
monkeypatch.delenv("GPT2GIGA_ENABLE_API_KEY_AUTH", raising=False)
monkeypatch.delenv("GPT2GIGA_MODE", raising=False)
monkeypatch.delenv("GPT2GIGA_API_KEY", raising=False)
app = create_app()

class Dummy:
Expand Down
1 change: 1 addition & 0 deletions tests/test_config/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def test_proxy_settings_defaults(monkeypatch):
assert s.host == "localhost"
assert isinstance(s.port, int)
assert isinstance(s.log_level, str)
assert s.enable_reasoning is False
assert s.max_audio_file_size_bytes == 35 * 1024 * 1024
assert s.max_image_file_size_bytes == 15 * 1024 * 1024
assert s.max_text_file_size_bytes == 40 * 1024 * 1024
Expand Down
Loading
Loading