gateway-llm 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gateway_llm-0.1.0/.github/workflows/ci.yml +97 -0
- gateway_llm-0.1.0/.github/workflows/secret-scan.yml +29 -0
- gateway_llm-0.1.0/.github/workflows/update-benchmarks.yml +48 -0
- gateway_llm-0.1.0/.gitignore +84 -0
- gateway_llm-0.1.0/CHANGELOG.md +202 -0
- gateway_llm-0.1.0/CONTRIBUTING.md +330 -0
- gateway_llm-0.1.0/LICENSE.txt +202 -0
- gateway_llm-0.1.0/PKG-INFO +348 -0
- gateway_llm-0.1.0/README.MD +314 -0
- gateway_llm-0.1.0/README.md +314 -0
- gateway_llm-0.1.0/benchmarks_cache/f5_safety.json +6 -0
- gateway_llm-0.1.0/benchmarks_cache/rws_translation.json +6 -0
- gateway_llm-0.1.0/config/models.example.yaml +105 -0
- gateway_llm-0.1.0/config/policy.example.yaml +26 -0
- gateway_llm-0.1.0/docs/GUIDE_EN.md +103 -0
- gateway_llm-0.1.0/docs/GUIDE_FR.md +103 -0
- gateway_llm-0.1.0/docs/THREAT_MODEL.md +201 -0
- gateway_llm-0.1.0/pyproject.toml +115 -0
- gateway_llm-0.1.0/scripts/refresh.py +101 -0
- gateway_llm-0.1.0/scripts/refresh_rws.py +106 -0
- gateway_llm-0.1.0/src/gateway_llm/__init__.py +80 -0
- gateway_llm-0.1.0/src/gateway_llm/batch.py +487 -0
- gateway_llm-0.1.0/src/gateway_llm/benchmarks/__init__.py +0 -0
- gateway_llm-0.1.0/src/gateway_llm/benchmarks/aggregator.py +75 -0
- gateway_llm-0.1.0/src/gateway_llm/benchmarks/base.py +49 -0
- gateway_llm-0.1.0/src/gateway_llm/benchmarks/benchlm.py +75 -0
- gateway_llm-0.1.0/src/gateway_llm/benchmarks/cache.py +58 -0
- gateway_llm-0.1.0/src/gateway_llm/benchmarks/f5_safety.py +65 -0
- gateway_llm-0.1.0/src/gateway_llm/benchmarks/normalizer.py +54 -0
- gateway_llm-0.1.0/src/gateway_llm/benchmarks/rankllms.py +67 -0
- gateway_llm-0.1.0/src/gateway_llm/benchmarks/rws_translation.py +55 -0
- gateway_llm-0.1.0/src/gateway_llm/budget.py +81 -0
- gateway_llm-0.1.0/src/gateway_llm/checkpoint.py +57 -0
- gateway_llm-0.1.0/src/gateway_llm/classifier.py +232 -0
- gateway_llm-0.1.0/src/gateway_llm/cli.py +654 -0
- gateway_llm-0.1.0/src/gateway_llm/config.py +93 -0
- gateway_llm-0.1.0/src/gateway_llm/doctor.py +241 -0
- gateway_llm-0.1.0/src/gateway_llm/guardrails/__init__.py +9 -0
- gateway_llm-0.1.0/src/gateway_llm/guardrails/base.py +51 -0
- gateway_llm-0.1.0/src/gateway_llm/guardrails/nemo.py +88 -0
- gateway_llm-0.1.0/src/gateway_llm/guardrails/noop.py +21 -0
- gateway_llm-0.1.0/src/gateway_llm/gui.py +604 -0
- gateway_llm-0.1.0/src/gateway_llm/hardware.py +114 -0
- gateway_llm-0.1.0/src/gateway_llm/installer.py +106 -0
- gateway_llm-0.1.0/src/gateway_llm/intake.py +224 -0
- gateway_llm-0.1.0/src/gateway_llm/logging.py +68 -0
- gateway_llm-0.1.0/src/gateway_llm/policy.py +64 -0
- gateway_llm-0.1.0/src/gateway_llm/providers/base.py +64 -0
- gateway_llm-0.1.0/src/gateway_llm/providers/cloudflare.py +84 -0
- gateway_llm-0.1.0/src/gateway_llm/providers/ollama.py +75 -0
- gateway_llm-0.1.0/src/gateway_llm/providers/openai_compat.py +111 -0
- gateway_llm-0.1.0/src/gateway_llm/quota.py +49 -0
- gateway_llm-0.1.0/src/gateway_llm/router.py +228 -0
- gateway_llm-0.1.0/src/gateway_llm/secrets.py +339 -0
- gateway_llm-0.1.0/tests/__init__.py +0 -0
- gateway_llm-0.1.0/tests/conftest.py +32 -0
- gateway_llm-0.1.0/tests/fixtures/.gitkeep +0 -0
- gateway_llm-0.1.0/tests/helpers.py +37 -0
- gateway_llm-0.1.0/tests/test_budget.py +106 -0
- gateway_llm-0.1.0/tests/test_classifier.py +162 -0
- gateway_llm-0.1.0/tests/test_doctor.py +147 -0
- gateway_llm-0.1.0/tests/test_guardrails.py +128 -0
- gateway_llm-0.1.0/tests/test_installer.py +81 -0
- gateway_llm-0.1.0/tests/test_policy.py +132 -0
- gateway_llm-0.1.0/tests/test_providers.py +197 -0
- gateway_llm-0.1.0/tests/test_quota.py +82 -0
- gateway_llm-0.1.0/tests/test_router.py +275 -0
- gateway_llm-0.1.0/tests/test_security.py +338 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Amandine Dennieau
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
name: CI
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main]
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
name: Tests (Python ${{ matrix.python-version }})
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
strategy:
|
|
20
|
+
fail-fast: false
|
|
21
|
+
matrix:
|
|
22
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: ${{ matrix.python-version }}
|
|
29
|
+
cache: pip
|
|
30
|
+
|
|
31
|
+
- name: Installer (sans guardrails)
|
|
32
|
+
run: |
|
|
33
|
+
python -m pip install --upgrade pip
|
|
34
|
+
pip install -e ".[dev]"
|
|
35
|
+
|
|
36
|
+
- name: Pytest
|
|
37
|
+
run: pytest tests/ -v --cov=gateway_llm --cov-report=term-missing
|
|
38
|
+
|
|
39
|
+
test-guardrails:
|
|
40
|
+
name: Tests avec NeMo Guardrails
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
- uses: actions/setup-python@v5
|
|
45
|
+
with:
|
|
46
|
+
python-version: "3.12"
|
|
47
|
+
cache: pip
|
|
48
|
+
- name: Installer avec extra [guardrails]
|
|
49
|
+
run: |
|
|
50
|
+
python -m pip install --upgrade pip
|
|
51
|
+
pip install -e ".[dev,guardrails]"
|
|
52
|
+
- name: Pytest
|
|
53
|
+
run: pytest tests/ -v -m "guardrails or not guardrails"
|
|
54
|
+
|
|
55
|
+
lint:
|
|
56
|
+
name: Lint (ruff)
|
|
57
|
+
runs-on: ubuntu-latest
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@v4
|
|
60
|
+
- uses: actions/setup-python@v5
|
|
61
|
+
with:
|
|
62
|
+
python-version: "3.12"
|
|
63
|
+
cache: pip
|
|
64
|
+
- run: pip install ruff
|
|
65
|
+
- run: ruff check src/ tests/
|
|
66
|
+
- run: ruff format --check src/ tests/
|
|
67
|
+
|
|
68
|
+
typecheck:
|
|
69
|
+
name: Type check (mypy)
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v4
|
|
73
|
+
- uses: actions/setup-python@v5
|
|
74
|
+
with:
|
|
75
|
+
python-version: "3.12"
|
|
76
|
+
cache: pip
|
|
77
|
+
- run: |
|
|
78
|
+
pip install -e ".[dev]"
|
|
79
|
+
- run: mypy src/
|
|
80
|
+
|
|
81
|
+
security:
|
|
82
|
+
name: Sécurité (bandit + pip-audit)
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v4
|
|
86
|
+
- uses: actions/setup-python@v5
|
|
87
|
+
with:
|
|
88
|
+
python-version: "3.12"
|
|
89
|
+
cache: pip
|
|
90
|
+
- name: Installer
|
|
91
|
+
run: |
|
|
92
|
+
pip install bandit pip-audit
|
|
93
|
+
pip install -e .
|
|
94
|
+
- name: Bandit
|
|
95
|
+
run: bandit -r src/ -c pyproject.toml
|
|
96
|
+
- name: pip-audit
|
|
97
|
+
run: pip-audit --strict --progress-spinner=off
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Amandine Dennieau
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
name: Secret Scan
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
pull_request:
|
|
10
|
+
schedule:
|
|
11
|
+
- cron: "0 3 * * 1" # chaque lundi 3h UTC
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
gitleaks:
|
|
18
|
+
name: Gitleaks
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0
|
|
24
|
+
- name: Télécharger gitleaks
|
|
25
|
+
run: |
|
|
26
|
+
curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.21.2/gitleaks_8.21.2_linux_x64.tar.gz \
|
|
27
|
+
| tar -xz -C /usr/local/bin gitleaks
|
|
28
|
+
- name: Scanner
|
|
29
|
+
run: gitleaks detect --source . --verbose --redact
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Amandine Dennieau
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
name: Update Benchmarks (F5 / RWS)
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: "0 4 */14 * *" # tous les 14 jours à 4h UTC
|
|
9
|
+
workflow_dispatch: # manuel possible
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
update:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
21
|
+
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
cache: pip
|
|
26
|
+
|
|
27
|
+
- name: Installer dépendances de scraping
|
|
28
|
+
run: pip install requests beautifulsoup4
|
|
29
|
+
|
|
30
|
+
- name: Rafraîchir F5
|
|
31
|
+
continue-on-error: true
|
|
32
|
+
run: python scripts/refresh_f5.py
|
|
33
|
+
|
|
34
|
+
- name: Rafraîchir RWS
|
|
35
|
+
continue-on-error: true
|
|
36
|
+
run: python scripts/refresh_rws.py
|
|
37
|
+
|
|
38
|
+
- name: Commit si changements
|
|
39
|
+
run: |
|
|
40
|
+
git config user.name "gateway-llm-bot"
|
|
41
|
+
git config user.email "bot@users.noreply.github.com"
|
|
42
|
+
git add benchmarks_cache/f5_safety.json benchmarks_cache/rws_translation.json || true
|
|
43
|
+
if git diff --cached --quiet; then
|
|
44
|
+
echo "Aucun changement, skip commit."
|
|
45
|
+
else
|
|
46
|
+
git commit -m "chore: auto-update F5/RWS benchmarks ($(date +%Y-%m-%d))"
|
|
47
|
+
git push
|
|
48
|
+
fi
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Amandine Dennieau
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0.
|
|
5
|
+
|
|
6
|
+
# ─── Python byte-compiled / cache ────────────────────────────────
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.py[cod]
|
|
9
|
+
*$py.class
|
|
10
|
+
*.so
|
|
11
|
+
|
|
12
|
+
# ─── Distribution / packaging ────────────────────────────────────
|
|
13
|
+
.Python
|
|
14
|
+
build/
|
|
15
|
+
dist/
|
|
16
|
+
*.egg-info/
|
|
17
|
+
*.egg
|
|
18
|
+
.eggs/
|
|
19
|
+
wheels/
|
|
20
|
+
|
|
21
|
+
# ─── Environnements virtuels ─────────────────────────────────────
|
|
22
|
+
.venv/
|
|
23
|
+
venv/
|
|
24
|
+
env/
|
|
25
|
+
ENV/
|
|
26
|
+
|
|
27
|
+
# ─── Tests & couverture ──────────────────────────────────────────
|
|
28
|
+
.pytest_cache/
|
|
29
|
+
.coverage
|
|
30
|
+
.coverage.*
|
|
31
|
+
htmlcov/
|
|
32
|
+
coverage.xml
|
|
33
|
+
.tox/
|
|
34
|
+
.nox/
|
|
35
|
+
|
|
36
|
+
# ─── Linters & typage ────────────────────────────────────────────
|
|
37
|
+
.mypy_cache/
|
|
38
|
+
.ruff_cache/
|
|
39
|
+
.dmypy.json
|
|
40
|
+
|
|
41
|
+
# ─── IDE / éditeurs ──────────────────────────────────────────────
|
|
42
|
+
.idea/
|
|
43
|
+
.vscode/
|
|
44
|
+
*.swp
|
|
45
|
+
*~
|
|
46
|
+
*.code-workspace
|
|
47
|
+
|
|
48
|
+
# ─── Secrets & config locale ─────────────────────────────────────
|
|
49
|
+
.env
|
|
50
|
+
.env.*
|
|
51
|
+
!.env.example
|
|
52
|
+
config/models.yaml
|
|
53
|
+
config/policy.yaml
|
|
54
|
+
secrets.yaml
|
|
55
|
+
*.key
|
|
56
|
+
*.pem
|
|
57
|
+
*.p12
|
|
58
|
+
|
|
59
|
+
# ─── Données locales de batch (I/O) ──────────────────────────────
|
|
60
|
+
data/
|
|
61
|
+
inputs/
|
|
62
|
+
outputs/
|
|
63
|
+
reports/
|
|
64
|
+
*.jsonl
|
|
65
|
+
!tests/fixtures/*.jsonl
|
|
66
|
+
|
|
67
|
+
# ─── Benchmarks : on garde uniquement les exemples manuels ───────
|
|
68
|
+
# Les fichiers f5_safety.json et rws_translation.json sont COMMITTÉS
|
|
69
|
+
# (ce sont des exemples/documentation, pas des caches).
|
|
70
|
+
# Les caches auto-fetchés (BenchLM, RankLLMs) sont ignorés.
|
|
71
|
+
benchmarks_cache/benchlm_*.json
|
|
72
|
+
benchmarks_cache/rankllms_*.json
|
|
73
|
+
|
|
74
|
+
# ─── Logs ────────────────────────────────────────────────────────
|
|
75
|
+
*.log
|
|
76
|
+
logs/
|
|
77
|
+
|
|
78
|
+
# ─── OS ──────────────────────────────────────────────────────────
|
|
79
|
+
.DS_Store
|
|
80
|
+
Thumbs.db
|
|
81
|
+
|
|
82
|
+
# ─── Artefacts de build ──────────────────────────────────────────
|
|
83
|
+
*.whl
|
|
84
|
+
*.tar.gz
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Toutes les évolutions notables de ce projet sont documentées dans ce fichier.
|
|
4
|
+
|
|
5
|
+
Le format s'inspire de [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/),
|
|
6
|
+
et ce projet adhère à [Semantic Versioning](https://semver.org/lang/fr/).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
_(Rien pour l'instant — les prochaines évolutions seront ajoutées ici.)_
|
|
11
|
+
|
|
12
|
+
## [0.1.0] - 2026-01-01
|
|
13
|
+
|
|
14
|
+
Première version publique de `gateway-llm`, après refactorisation complète
|
|
15
|
+
du projet initial (`pipeline/`, `process_batch.py` de 880 lignes).
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
#### Architecture
|
|
20
|
+
|
|
21
|
+
- Package Python installable (`src/gateway_llm/`, `pyproject.toml` avec hatchling).
|
|
22
|
+
- Layout `src/` pour éviter les imports accidentels et supprimer les `sys.path.insert` dans les tests.
|
|
23
|
+
- Exports publics centralisés dans `gateway_llm/__init__.py`.
|
|
24
|
+
|
|
25
|
+
#### Providers
|
|
26
|
+
|
|
27
|
+
- Classe abstraite `Provider` avec `complete(model, prompt, max_tokens, temperature, image_b64)`.
|
|
28
|
+
- `OpenAICompatibleProvider` couvrant Groq, OpenRouter, Mistral, NVIDIA, Google AI Studio.
|
|
29
|
+
- `OllamaProvider` avec désactivation du Thinking (`think: false`) et support multimodal (`images`).
|
|
30
|
+
- `CloudflareProvider` avec format de réponse spécifique.
|
|
31
|
+
- Support multimodal : `image_b64` transmis à `/chat/completions` (format OpenAI) ou `/api/chat` (format Ollama).
|
|
32
|
+
|
|
33
|
+
#### Router et orchestration
|
|
34
|
+
|
|
35
|
+
- Classe `Router` avec cascade par domaine, filtres policy/quota/hardware, guardrail en filtre final.
|
|
36
|
+
- `QuotaManager` avec **cooldown temporel** par provider (corrige le bug de compteur 429 cumulatif).
|
|
37
|
+
- `BudgetTracker` avec plafond en euros et arrêt contrôlé (`budget_exceeded`).
|
|
38
|
+
- `PolicyConfig` avec wildcards (`groq-*`), règle `default`, et `default_allow`.
|
|
39
|
+
- `HardwareInfo` avec détection VRAM (`nvidia-smi`, `rocm-smi`) et estimation de fit non bloquante.
|
|
40
|
+
- `BatchRunner` avec checkpointing, reprise (`--resume`), dry-run, et rapport final.
|
|
41
|
+
- `Checkpoint` avec écriture append + fsync.
|
|
42
|
+
|
|
43
|
+
#### Benchmarks dynamiques
|
|
44
|
+
|
|
45
|
+
- Module `benchmarks/` avec `BenchmarkSource` (ABC) et 4 adaptateurs :
|
|
46
|
+
- `BenchLMAdapter` (BenchLM.ai)
|
|
47
|
+
- `RankLLMsAdapter` (RankLLMs)
|
|
48
|
+
- `F5SafetyAdapter` (F5 Labs CASI/ARS)
|
|
49
|
+
- `RWSTranslationAdapter` (RWS TrainAI M-GATE)
|
|
50
|
+
- `BenchmarkCache` avec TTL 24h et refetch forcé.
|
|
51
|
+
- `BenchmarkAggregator` avec fusion multi-sources (moyenne) et re-ranking des chaînes.
|
|
52
|
+
- `normalize_model_name()` et `fuzzy_match()` pour appariement automatique des noms de modèles sans table d'alias manuelle.
|
|
53
|
+
- **Refresh lazy au démarrage d'un batch** : si le cache a plus de 14 jours (`gateway_llm_BENCHMARK_TTL_DAYS`), il est rafraîchi automatiquement.
|
|
54
|
+
- Workflow GitHub Actions `.github/workflows/update-benchmarks.yml` pour mise à jour bi-hebdomadaire des caches F5 et RWS.
|
|
55
|
+
|
|
56
|
+
#### Secrets
|
|
57
|
+
|
|
58
|
+
- Classe abstraite `SecretBackend` avec `get()`, `is_available()`, `set()` (défaut : retourne `False`).
|
|
59
|
+
- **6 backends** :
|
|
60
|
+
- `PowerShellVaultBackend` (Windows)
|
|
61
|
+
- `OnePasswordBackend` (multi-OS)
|
|
62
|
+
- `HashiCorpVaultBackend` (entreprise)
|
|
63
|
+
- `AWSSecretsManagerBackend` (cloud AWS)
|
|
64
|
+
- `AzureKeyVaultBackend` (cloud Azure)
|
|
65
|
+
- `EnvSecretBackend` (fallback explicite, déconseillé)
|
|
66
|
+
- Imports cloud **lazy** : `import gateway_llm.secrets` fonctionne sans `boto3` ni `azure`.
|
|
67
|
+
- `get_backend()` avec résolution explicite (aucune bascule silencieuse vers `.env`).
|
|
68
|
+
- `save_backend_config()` qui persiste le choix dans `~/.gateway-llm/secrets.yaml` (hors repo, non commité).
|
|
69
|
+
- `missing_requirements()` qui détecte les packages pip manquants avant que l'utilisateur ne choisisse un backend.
|
|
70
|
+
- Commande CLI `gateway-llm setup-secrets` avec assistant interactif (machine perso / entreprise / cloud).
|
|
71
|
+
|
|
72
|
+
#### Classification
|
|
73
|
+
|
|
74
|
+
- `TaskClassifier` avec mode LLM (qwen3:4b-instruct) + fallback regex.
|
|
75
|
+
- 9 domaines supportés dont `multimodal_extraction` (images, screenshots, KPI).
|
|
76
|
+
- Priorité humaine, flags de risque (`MULTIMODAL_BLOCKED` supprimé, `POST_2024_FACT_CHECK`, `HIGH_RISK`, `SUBJECTIVE_NORMAL`).
|
|
77
|
+
|
|
78
|
+
#### Guardrails
|
|
79
|
+
|
|
80
|
+
- Classe abstraite `Guardrail` avec `GuardrailResult`.
|
|
81
|
+
- `NoOpGuardrail` (défaut, aucune dépendance).
|
|
82
|
+
- `NemoGuardrail` (extra `[guardrails]`), avec normalisation `str` / `dict` / `GenerationResponse` et fail-open sur exception.
|
|
83
|
+
|
|
84
|
+
#### Intake (convertisseur de données)
|
|
85
|
+
|
|
86
|
+
- `intake_from_folder` : dossier d'images → JSONL.
|
|
87
|
+
- `intake_from_text` : dossier de fichiers texte → JSONL.
|
|
88
|
+
- `intake_from_csv` : colonne CSV → JSONL.
|
|
89
|
+
- `intake_from_urls` : liste d'URLs → JSONL, avec vérification `robots.txt` par défaut.
|
|
90
|
+
- Commande CLI `gateway-llm intake from-folder|from-text|from-csv|from-urls`.
|
|
91
|
+
|
|
92
|
+
#### Diagnostic et installation
|
|
93
|
+
|
|
94
|
+
- `Doctor` avec checks deps Python, binaire Ollama, daemon Ollama, modèles locaux, stockage des secrets.
|
|
95
|
+
- `Installer` avec téléchargement `ollama pull` interactif ou automatique (`--yes`).
|
|
96
|
+
- Commande CLI `gateway-llm doctor` et `gateway-llm setup`.
|
|
97
|
+
|
|
98
|
+
#### Interface graphique
|
|
99
|
+
|
|
100
|
+
- Application `tkinter` unifiée (`python -m gateway_llm.gui`) avec **4 onglets** :
|
|
101
|
+
1. Configuration (backend de secrets)
|
|
102
|
+
2. Préparer les données (intake)
|
|
103
|
+
3. Lancer le traitement (batch)
|
|
104
|
+
4. Voir les résultats (rapport, à revoir, tout)
|
|
105
|
+
- Ouverture automatique de l'onglet Configuration au premier lancement.
|
|
106
|
+
- Boutons Accepter / Rejeter pour les tâches `human_review`, décisions écrites dans `decisions.jsonl`.
|
|
107
|
+
|
|
108
|
+
#### CLI
|
|
109
|
+
|
|
110
|
+
- `gateway-llm doctor` : diagnostic.
|
|
111
|
+
- `gateway-llm setup` : installation des modèles Ollama manquants.
|
|
112
|
+
- `gateway-llm setup-secrets` : configuration du backend de secrets.
|
|
113
|
+
- `gateway-llm intake` : convertisseur de données (4 sous-commandes).
|
|
114
|
+
- `gateway-llm benchmarks refresh` : rafraîchissement forcé.
|
|
115
|
+
- `gateway-llm batch run` : traitement par lot avec `--resume`, `--dry-run`, `--max-cost-eur`, `--no-classifier`, `--classifier-model`, `--no-doctor`, `--no-install`, `--yes`, `--verbose`.
|
|
116
|
+
- `--help` exhaustif pour chaque commande avec épilogues et exemples.
|
|
117
|
+
|
|
118
|
+
#### Tests
|
|
119
|
+
|
|
120
|
+
- Suite complète de tests unitaires avec mocks (aucun réseau requis).
|
|
121
|
+
- `test_router.py`, `test_quota.py`, `test_budget.py`, `test_policy.py`, `test_classifier.py`, `test_checkpoint.py`, `test_benchmarks.py`, `test_hardware.py`, `test_providers.py`, `test_security.py`, `test_doctor.py`, `test_installer.py`.
|
|
122
|
+
- Tests de sécurité explicites : pas de `shell=True`, échappement d'apostrophes, absence d'import cloud au niveau module.
|
|
123
|
+
|
|
124
|
+
#### CI/CD
|
|
125
|
+
|
|
126
|
+
- `.github/workflows/ci.yml` : matrice Python 3.11/3.12/3.13, ruff, mypy, bandit, pip-audit.
|
|
127
|
+
- `.github/workflows/secret-scan.yml` : gitleaks hebdomadaire.
|
|
128
|
+
- `.github/workflows/update-benchmarks.yml` : mise à jour automatique F5/RWS tous les 14 jours.
|
|
129
|
+
|
|
130
|
+
#### Documentation
|
|
131
|
+
|
|
132
|
+
- `README.md` : installation, quickstart, CLI complet, architecture, OOP, GUI, tests.
|
|
133
|
+
- `docs/THREAT_MODEL.md` : 15 menaces documentées (T1 à T15), actifs, hors périmètre, recommandations.
|
|
134
|
+
- `docs/GUIDE_FR.md` : guide utilisateur non technique (français).
|
|
135
|
+
- `docs/GUIDE_EN.md` : guide utilisateur non technique (anglais).
|
|
136
|
+
- `benchmarks_cache/f5_safety.json` et `rws_translation.json` : exemples documentés, mis à jour par CI.
|
|
137
|
+
|
|
138
|
+
### Changed
|
|
139
|
+
|
|
140
|
+
- **Refactorisation complète** du projet initial (`process_batch.py` de 880 lignes) en 20+ modules de < 200 lignes chacun.
|
|
141
|
+
- **Programmation orientée objet** systématique : chaque responsabilité est une classe, aucune variable module-level mutable.
|
|
142
|
+
- **Logging** remplace les 92 `print` du projet initial : `NullHandler` sur le logger racine, `dictConfig` pour le CLI, format texte ou JSON.
|
|
143
|
+
- `guardrail_passed=False` **arrête la cascade** au lieu de relancer sur le modèle suivant (comportement fidèle au projet original, corrigé par rapport à une première itération erronée).
|
|
144
|
+
- Le fichier de sortie JSONL contient désormais `status` (`approved` / `human_review` / `failed` / `budget_exceeded`) au lieu d'un booléen `success`.
|
|
145
|
+
- `models.example.yaml` : `qwen2.5vl:7b` remplacé par `qwen2.5vl:7b-q4_K_M` (quantification explicite Q4_K_M, ~6 Go).
|
|
146
|
+
- `policy.yaml` accepte trois formes : `{allowed_providers: [...]}`, `[...]`, ou `ResidencyRule`.
|
|
147
|
+
|
|
148
|
+
### Removed
|
|
149
|
+
|
|
150
|
+
- `Playwright` et toutes les dépendances de navigateur (`playwright`, `playwright-stealth`).
|
|
151
|
+
- Patches de stealth (`add_stealth_patches`, `USER_AGENT_BRAVE`, `PROFIL_ISOLE`, `BRAVE_PATH`).
|
|
152
|
+
- `extract_sources.py`, `auto_detect_selectors.py`, `config_urls.json` (scraping web).
|
|
153
|
+
- `Nemoguardrails` en dépendance obligatoire → devenu extra `[guardrails]`.
|
|
154
|
+
- Dossiers `approved/`, `sent/`, `human_review/`, `history/`, `site/` du projet initial.
|
|
155
|
+
- Scripts `run_batch.bat` et `run_batch.sh` (remplacés par la GUI et le CLI).
|
|
156
|
+
- `APScheduler` (le refresh lazy + GitHub Actions couvrent le besoin).
|
|
157
|
+
- Toute trace de `shell=True` dans le code.
|
|
158
|
+
- Compteur 429 cumulatif (`_PROVIDER_CALLS["__429_xxx"]`) remplacé par cooldown temporel.
|
|
159
|
+
|
|
160
|
+
### Fixed
|
|
161
|
+
|
|
162
|
+
- **Bug du compteur 429** : le compteur original n'était jamais remis à zéro, bannissant un provider pour la session entière après 2× 429. Corrigé par `QuotaManager` avec `time.monotonic()` et expiration naturelle.
|
|
163
|
+
- **`shell=True` avec f-string** dans `_get_secret` : remplacé par `subprocess.run([...])` avec liste d'arguments et échappement d'apostrophes.
|
|
164
|
+
- **`sys.path.insert` dans les tests** : supprimé par le layout `src/` + installation editable.
|
|
165
|
+
- **État global mutable** (`_SECRET_CACHE`, `_GUARDRAILS_APP`, `_PROVIDER_CALLS`) : encapsulé dans des instances injectables.
|
|
166
|
+
- **Imports Azure au niveau module** : déplacés en lazy import pour ne pas casser `import gateway_llm.secrets` si azure n'est pas installé.
|
|
167
|
+
- **Incohérence `success` booléen vs réponse partielle** : introduction du champ `status` explicite.
|
|
168
|
+
|
|
169
|
+
### Security
|
|
170
|
+
|
|
171
|
+
- Modèle de menace documenté (`docs/THREAT_MODEL.md`) avec 15 entrées T1–T15.
|
|
172
|
+
- Vérification `gitleaks` en CI (workflow hebdomadaire).
|
|
173
|
+
- `pip-audit --strict` en CI.
|
|
174
|
+
- `bandit -r src/` en CI.
|
|
175
|
+
- Pas de `shell=True` nulle part.
|
|
176
|
+
- Backends de secrets à choix explicite : aucune bascule silencieuse vers `.env`.
|
|
177
|
+
- `~/.gateway-llm/secrets.yaml` ne contient jamais de secret final, seulement la config du backend.
|
|
178
|
+
- Recommendation `chmod 600` documentée pour le fichier de config.
|
|
179
|
+
- Support `confidential` → `[ollama]` uniquement pour les données sensibles (y compris screenshots avec KPI).
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Notes de migration depuis le projet original
|
|
184
|
+
|
|
185
|
+
Si vous venez du projet `pipeline/` initial, voici les correspondances :
|
|
186
|
+
|
|
187
|
+
| Projet original | `gateway-llm` |
|
|
188
|
+
| :--- | :--- |
|
|
189
|
+
| `process_batch.py` (880 lignes) | 15+ modules sous `src/gateway_llm/` |
|
|
190
|
+
| `_get_secret()` | `PowerShellVaultBackend.get()` |
|
|
191
|
+
| `call_llm_with_fallback()` | `Router.route()` |
|
|
192
|
+
| `classify_and_route_task()` | `TaskClassifier.classify()` |
|
|
193
|
+
| `check_response_with_guardrails()` | `NemoGuardrail.check()` |
|
|
194
|
+
| `generate_summary_report()` | `BatchRunner._print_report()` + `ResultsTab._refresh()` |
|
|
195
|
+
| `tasks.json` | `tasks.jsonl` (une ligne par tâche) |
|
|
196
|
+
| `approved/`, `sent/` | `results.jsonl` (champ `status`) |
|
|
197
|
+
| `human_review/human_review_summary.*` | `ResultsTab` onglet « À revoir » |
|
|
198
|
+
| `history/tasks_*.json` | Non conservé (chaque sortie JSONL est un historique) |
|
|
199
|
+
| `scrape.py` / `auto_detect_selectors.py` | Non conservé (supprimé) |
|
|
200
|
+
|
|
201
|
+
[Unreleased]: https://github.com/Darki0n1/gateway-llm/compare/v0.1.0...HEAD
|
|
202
|
+
[0.1.0]: https://github.com/Darki0n1/gateway-llm/releases/tag/v0.1.0
|