Skip to content
Merged
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,37 @@ All notable changes to ForgeLM are documented here.

### Fixed

- Stop saying that Microsoft Teams and Discord accept the webhook payload directly. The user manual (English and Turkish) and the
`webhook` field descriptions said all three ingest it; the body is a Slack-style `attachments` block with no top-level `text`,
`content` or `embeds`. Discord needs `content` or `embeds` and answers HTTP 400; Teams retired Office 365 Connectors in May 2026 and
its Workflows webhooks expect an Adaptive Card. Both need a relay. The page now shows the real payload, and the access-control SOP
no longer claims that a payload carries `FORGELM_OPERATOR` (it does not) or lists five events (there are eight). The `url_env`
description said it overrides `url`; it is read only when `url` is empty, so `url` wins. A formatter for Teams and Discord is a
separate, larger change and stays open on the issue (#112).
- Say that the DeepSpeed preset names (`zero2`, `zero3`, `zero3_offload`) work only from a source checkout. They resolve to
`configs/deepspeed/<name>.json` beside the package or in the current directory, and neither the wheel nor the Docker image ships
that folder, so on a `pip install` the names fail with a configuration error (and the unset-`deepspeed_config` default is
`zero2`). The configuration and distributed-training references, the troubleshooting entry (its sample error is now the real
message), the enterprise guide, the user manuals, `config_template.yaml` and the field description now say so and point at a
JSON path; the template's `torchrun … forgelm` launch line is `-m forgelm`, the only form that runs the checkout. The
unverified "`zero3_offload` fits 70B on 8×24 GB" sentence is gone, and the `zero2` preset's own start-up failure is noted
(#410). Shipping the presets in the package, and a test that resolves one from an installed wheel, are code changes and stay
open on the issues (#110, #111, #115).
- Show the real output directory on the first-run, project-layout and human-oversight pages (English and Turkish). They described a
`checkpoints/<name>/artifacts/` bundle with a `manifest.json` that hashes "every file inside … for tamper-evidence", a
`config_snapshot.yaml`, a `safety_report.json` and a `data_audit_report.json`. None of those exist: a run writes `audit_log.jsonl` with its
`.manifest.json` genesis pin, a `compliance/` directory (`compliance_report.json`, `training_manifest.yaml`, `data_provenance.json`,
`data_governance_report.json`, and `annex_iv_metadata.json` only when the YAML names a provider, system or purpose), `safety/` and
`benchmark/` only when enabled, and `final_model/` with the weights, model card, `deployer_instructions.md` and `model_integrity.json`.
Only the audit log and `final_model/` are tamper-checked; nothing hashes `compliance/`, and the pages now say so. The invented training log
(a DPO pass in an SFT-only template, `Llama Guard S1-S14: clean`) is replaced by a description of the real stages, the approval-gate
sample shows the two log lines the trainer prints, and the `forgelm doctor` sample uses the real renderer's format (ASCII header and
`[+ pass]` markers, "discoverable" wording, an abridged row list) (#96, #534).
- Describe `--offline` / `model.offline` as what it does. It sets `HF_HUB_OFFLINE`, `TRANSFORMERS_OFFLINE` and `HF_DATASETS_OFFLINE`; it does not
stop webhooks, the LLM-judge and synthetic-data API clients, or W&B / MLflow. The `--offline` help text, the `model.offline` field
description, the configuration and CLI references (English and Turkish) and the enterprise deployment guide said "Air-gapped mode" and
"prevents any network calls"; the air-gap page no longer lists Comet, which `training.report_to` does not accept. Gating those clients
behind the flag is a code change and stays open (#74, #100, #893).
- `training.rope_scaling` works on transformers 5 again. The setting was passed to `from_pretrained(rope_scaling=...)`,
which no longer works: the documented `{type: linear, factor: 4}` raised `KeyError: 'rope_type'` while the model was
built, and `{rope_type: ..., factor: ...}` replaced the whole parameter dict so `rope_theta` was lost (`TypeError`).
Expand Down
4 changes: 2 additions & 2 deletions config_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@ data:
# dare_seed: 42 # DARE: RNG seed for the random drop mask

# Distributed training (multi-GPU). Requires: pip install forgelm[distributed]
# Launch with: torchrun --nproc_per_node=N forgelm --config my_config.yaml
# Launch with: torchrun --nproc_per_node=N -m forgelm --config my_config.yaml
# distributed:
# strategy: "deepspeed" # "deepspeed" or "fsdp"
# deepspeed_config: "zero2" # preset: "zero2", "zero3", "zero3_offload" or path to JSON
# deepspeed_config: "ds.json" # path to a DeepSpeed JSON (the presets "zero2", "zero3", "zero3_offload" need a source checkout)
# # --- FSDP options (when strategy: "fsdp") ---
# # fsdp_strategy: "full_shard" # "full_shard" or "shard_grad_op" (FSDP2 supports no other)
# # fsdp_auto_wrap: true
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/enterprise_deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ ForgeLM sets `HF_HUB_OFFLINE=1`, `TRANSFORMERS_OFFLINE=1`, `HF_DATASETS_OFFLINE=
```yaml
distributed:
strategy: "deepspeed"
deepspeed_config: "zero2" # or "zero3", "zero3_offload"
deepspeed_config: "/etc/forgelm/ds_zero2.json" # your own DeepSpeed JSON; the zero2/zero3/zero3_offload preset names need a source checkout
```

```bash
Expand Down Expand Up @@ -152,7 +152,7 @@ See the [Distributed Training Guide](../reference/distributed_training.md) for d
| `trust_remote_code` | `false` | Prevents arbitrary code execution from model repos |
| `auth.hf_token` | Use `HUGGINGFACE_TOKEN` env var | Don't hardcode tokens in YAML |
| `webhook.url` | Always use `url_env` with environment variable | Webhook tokens excluded from model cards (v0.3.1rc1+), but avoid direct URLs for credential hygiene |
| `offline` | `true` for air-gapped | Prevents any network calls |
| `offline` | `true` for air-gapped | Blocks Hugging Face Hub, transformers and datasets network calls (it sets `HF_HUB_OFFLINE`, `TRANSFORMERS_OFFLINE`, `HF_DATASETS_OFFLINE`). It does **not** stop webhooks, judge or synthetic-data API clients, or W&B / MLflow: disable those (omit `webhook:`, use local judge and teacher models, set `report_to: none`) for a true air gap |

---

Expand Down
7 changes: 4 additions & 3 deletions docs/guides/troubleshooting-tr.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,12 @@ nvidia-smi
### DeepSpeed Config bulunamadı

```text
FileNotFoundError: DeepSpeed preset 'zero2' not found
DeepSpeed preset 'zero2' not found at <path>/configs/deepspeed/zero2.json
```

ForgeLM proje kökünden çalıştırdığınızdan emin olun ya da mutlak yol
kullanın:
Ön ayar adları yalnızca bir kaynak checkout'unda çözülür (paketin yanındaki ya da geçerli dizindeki bir
`configs/deepspeed/` dizini); `pip install` veya Docker imajı bunları içermez. ForgeLM proje kökünden çalıştırın ya da
bir DeepSpeed JSON dosyasının yolunu kullanın:

```yaml
distributed:
Expand Down
6 changes: 4 additions & 2 deletions docs/guides/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,12 @@ nvidia-smi
### DeepSpeed Config Not Found

```text
FileNotFoundError: DeepSpeed preset 'zero2' not found
DeepSpeed preset 'zero2' not found at <path>/configs/deepspeed/zero2.json
```

Ensure you're running from the ForgeLM project root, or use an absolute path:
The preset names resolve only from a source checkout (a `configs/deepspeed/` directory beside the package or in the
current directory); a `pip install` or the Docker image does not contain them. Run from the ForgeLM project root, or
use the path of a DeepSpeed JSON file:

```yaml
distributed:
Expand Down
34 changes: 20 additions & 14 deletions docs/qms/access_control-tr.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,20 +230,26 @@ webhook:

ForgeLM webhook gövdelerini HMAC ile **imzalamaz** — `WebhookConfig`
üzerinde `webhook.secret_env` alanı yoktur (bkz.
`forgelm/config.py::WebhookConfig`). Hedef-tarafı atıf (a) HTTPS +
`webhook.url_env` üzerinden URL-gizliliğine, (b) curated payload
içinde taşınan `FORGELM_OPERATOR` kimliğine, ve (c) alıcı sistemin
kendi bearer-token / imzalı-istek kontrollerine (Slack signing
secret, Teams connector token) düşer.

Webhook wire-format olay sözlüğü (5 olay): `training.start`,
`training.success`, `training.failure`, `training.reverted`,
`approval.required` — Phase 8. In-process notifier metot adları
`notify_*` öneki kullanır (`notify_start`, `notify_success`,
`notify_failure`, `notify_reverted`, `notify_awaiting_approval`)
ve bu beş wire olayına dispatch eder. Her payload `FORGELM_OPERATOR`
kimliğini taşır böylece alıcı sistem (Slack, Teams, custom
incident-management) bildirimi attribute edebilir.
`forgelm/config.py::WebhookConfig`). Hedef-tarafı özgünlük (a) HTTPS +
`webhook.url_env` üzerinden URL-gizliliğine ve (b) alıcı tarafın kendi
uyguladığı kimlik doğrulamaya düşer. Bir Slack incoming webhook'unun gizli
URL'sinden başka bir doğrulaması yoktur (Slack'in signing secret'ı Slack'ten
*gelen* istekleri doğrular, bir webhook URL'sine gelenleri değil); bu yüzden
özel bir relay kendi kimlik doğrulamasını istemelidir, çünkü ForgeLM imza
göndermez. Webhook payload'u `FORGELM_OPERATOR`
kimliğini **taşımaz**; bir modeli kimin çalıştırdığı veya onayladığı
bildirimden değil, audit log'dan okunur.

Webhook wire-format olay sözlüğü sekiz olaydır: beş tek-aşamalı
yaşam-döngüsü olayı `training.start`, `training.success`,
`training.failure`, `training.reverted` ve `approval.required`, ayrıca
çok-aşamalı bir koşunun bunlarla birlikte yaydığı üç `pipeline.*`
olayı (`pipeline.started`, `pipeline.completed`,
`pipeline.stage_reverted`). In-process notifier metotları `notify_*`
öneki kullanır (`notify_start`, `notify_success`, `notify_failure`,
`notify_reverted`, `notify_awaiting_approval`,
`notify_pipeline_started`, `notify_pipeline_completed`,
`notify_pipeline_reverted`) ve bu wire olaylarına dispatch eder.

## 8. Doğrulama checklist'i

Expand Down
35 changes: 20 additions & 15 deletions docs/qms/access_control.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,21 +228,26 @@ webhook:

ForgeLM does **not** HMAC-sign webhook bodies — there is no
`webhook.secret_env` field on `WebhookConfig` (see
`forgelm/config.py::WebhookConfig`). Destination-side attribution falls to (a)
HTTPS + URL-secrecy via `webhook.url_env`, (b) the
`FORGELM_OPERATOR` identity carried inside the curated payload, and
(c) the receiving system's own bearer-token / signed-request
controls (Slack signing secret, Teams connector token).

The webhook wire-format event vocabulary (5 events) is
`training.start`, `training.success`, `training.failure`,
`training.reverted`, and `approval.required` — Phase 8. The
in-process notifier method names use the `notify_*` prefix
(`notify_start`, `notify_success`, `notify_failure`,
`notify_reverted`, `notify_awaiting_approval`) and dispatch to those
five wire events. Every payload carries the `FORGELM_OPERATOR`
identity so the receiving system (Slack, Teams, custom
incident-management) can attribute the notification.
`forgelm/config.py::WebhookConfig`). Destination-side authenticity falls to
(a) HTTPS + URL-secrecy via `webhook.url_env` and (b) authentication
the receiving side applies itself. A Slack incoming webhook has none
beyond its secret URL (Slack's signing secret verifies requests *from*
Slack, not requests to a webhook URL), so a custom relay should require
its own authentication, because ForgeLM sends no signature. A webhook
payload does **not** carry the
`FORGELM_OPERATOR` identity; attribution of who ran or approved a model
comes from the audit log, not from the notification.

The webhook wire-format event vocabulary has eight events: the five
single-stage lifecycle events `training.start`, `training.success`,
`training.failure`, `training.reverted` and `approval.required`, plus the
three `pipeline.*` events (`pipeline.started`, `pipeline.completed`,
`pipeline.stage_reverted`) that a multi-stage run emits alongside them. The
in-process notifier methods use the `notify_*` prefix (`notify_start`,
`notify_success`, `notify_failure`, `notify_reverted`,
`notify_awaiting_approval`, `notify_pipeline_started`,
`notify_pipeline_completed`, `notify_pipeline_reverted`) and dispatch to
those wire events.

## 8. Verification checklist

Expand Down
10 changes: 5 additions & 5 deletions docs/reference/configuration-tr.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Tam açıklamalı örnek için `config_template.yaml` dosyasına bakın.
| `load_in_4bit` | bool | `true` | QLoRA 4-bit NF4 kuantizasyon |
| `backend` | string | `"transformers"` | `"transformers"` veya `"unsloth"` (desteklenen mimarilerde daha hızlı, Linux) |
| `trust_remote_code` | bool | `false` | Model depolarından özel kod çalıştırma. **Güvenlik riski** |
| `offline` | bool | `false` | İzole mod: HF Hub çağrısı yok. Modeller/veri setleri yerel olmalı |
| `offline` | bool | `false` | HF offline değişkenlerini ayarlar; Hub, transformers ve datasets ağ çağrısı yapmaz. Modeller/veri setleri yerel olmalı. Webhook'ları, judge veya sentetik-veri API istemcilerini ve W&B / MLflow'u durdurmaz |
| `revision` | string | `null` | Temel modeli + tokenizer'ı bir HF Hub commit SHA'sına (40-hex) veya branch/tag'e sabitle. **Bugün uygulanıyor.** Bkz. [Hub revision pinleme](#hub-revision-pinleme) |
| `bnb_4bit_use_double_quant` | bool | `true` | Ekstra VRAM tasarrufu için çift kuantizasyon |
| `bnb_4bit_quant_type` | string | `"nf4"` | Kuantizasyon tipi (`"nf4"` veya `"fp4"`) |
Expand Down Expand Up @@ -397,7 +397,7 @@ kaynağı kaydedilmemiştir.
| Alan | Tip | Varsayılan | Açıklama |
|------|-----|-----------|----------|
| `strategy` | string | `null` | `"deepspeed"` veya `"fsdp"` (null = tek GPU) |
| `deepspeed_config` | string | `null` | Ön ayar (`"zero2"`, `"zero3"`, `"zero3_offload"`) veya JSON yolu |
| `deepspeed_config` | string | `null` | JSON yolu ya da yalnızca kaynak checkout'unda çözülen (pip veya Docker kurulumunda çözülmeyen) bir ön ayar adı (`"zero2"`, `"zero3"`, `"zero3_offload"`) |
| `fsdp_strategy` | string | `"full_shard"` | `"full_shard"` veya `"shard_grad_op"` (`"hybrid_shard"` ve `"no_shard"` reddedilir: FSDP2 bunları desteklemez) |
| `fsdp_auto_wrap` | bool | `true` | Transformer katmanlarını otomatik sar (transformers 5.10+'ta yok sayılır, katmanlar hep sarılır) |
| `fsdp_offload` | bool | `false` | Parametreleri CPU'ya taşı |
Expand Down Expand Up @@ -433,11 +433,11 @@ kaynağı kaydedilmemiştir.

| Alan | Tip | Varsayılan | Açıklama |
|------|-----|-----------|----------|
| `url` | string | `null` | Webhook hedef URL |
| `url_env` | string | `null` | URL'yi içeren ortam değişkeni adı |
| `url` | string | `null` | Webhook hedef URL'si: bir Slack incoming webhook'u ya da bir relay (Teams ve Discord payload'u doğrudan reddeder) |
| `url_env` | string | `null` | URL'yi içeren ortam değişkeni adı; yalnızca `url` boşken okunur |
| `notify_on_start` | bool | `true` | Eğitim başlangıcında bildir |
| `notify_on_success` | bool | `true` | Başarıda bildir |
| `notify_on_failure` | bool | `true` | Hata durumunda bildir |
| `notify_on_failure` | bool | `true` | Eğitim hata verdiğinde ya da eğitim sonrası bir kapı modeli geri aldığında bildir |
| `timeout` | int | `10` | HTTP istek zaman aşımı (saniye). Notifier ≥ 1s'ye clamp'ler. v0.5.5'te varsayılan 10s'ye çıkarıldı (önceden 5s'di) — Slack/Teams gateway gecikme atışları production'da düzenli olarak 5s'yi aşıyor ve bir webhook zaman aşımı audit chain'i sessizce zayıflatıyor (webhook arızası best-effort). |
| `allow_private_destinations` | bool | `false` | RFC1918 / loopback / link-local hedeflere webhook gönderimine izin verir (cluster içi Slack proxy, on-prem Teams gateway gibi). Varsayılan yalnızca genel internet — SSRF koruması |
| `require_https` | bool | `false` | TLS-only zorlama. `true`, plaintext bir `http://` URL'ini reddeder (SSRF chokepoint raise eder; POST atlanır), warn-and-send yerine. Varsayılan `false`, warn-then-send davranışını korur |
Expand Down
10 changes: 5 additions & 5 deletions docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ See `config_template.yaml` for a complete annotated example.
| `load_in_4bit` | bool | `true` | Enable QLoRA 4-bit NF4 quantization |
| `backend` | string | `"transformers"` | `"transformers"` or `"unsloth"` (faster on supported architectures, Linux only) |
| `trust_remote_code` | bool | `false` | Allow custom code from model repos. **Security risk** — only enable for models that require it |
| `offline` | bool | `false` | Air-gapped mode: no HF Hub calls. Models/datasets must be local |
| `offline` | bool | `false` | Sets the HF offline variables, so Hub, transformers and datasets make no network calls. Models/datasets must be local. Does not stop webhooks, judge or synthetic-data API clients, or W&B / MLflow |
| `revision` | string | `null` | Pin the base model + tokenizer to an HF Hub commit SHA (40-hex) or a branch/tag. **Honoured today.** See [Hub revision pinning](#hub-revision-pinning) |
| `bnb_4bit_use_double_quant` | bool | `true` | Double quantization for extra VRAM savings |
| `bnb_4bit_quant_type` | string | `"nf4"` | Quantization type (`"nf4"` or `"fp4"`) |
Expand Down Expand Up @@ -293,11 +293,11 @@ exits 0, and nothing is deleted, blocked or scheduled automatically. The

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `url` | string | `null` | Webhook destination URL |
| `url_env` | string | `null` | Env var name containing URL |
| `url` | string | `null` | Webhook destination URL: a Slack incoming webhook, or a relay (Teams and Discord reject the payload directly) |
| `url_env` | string | `null` | Env var name containing the URL; read only when `url` is empty |
| `notify_on_start` | bool | `true` | Notify on training start |
| `notify_on_success` | bool | `true` | Notify on success |
| `notify_on_failure` | bool | `true` | Notify on failure |
| `notify_on_failure` | bool | `true` | Notify when training raises or a post-training gate reverts the model |
| `timeout` | int | `10` | HTTP request timeout (seconds). Clamped to ≥ 1s by the notifier. Default raised to 10s in v0.5.5 (was 5s) — Slack/Teams gateway latency spikes regularly cross 5s in production, and a webhook timeout silently degrades the audit chain (webhook failure is best-effort). |
| `allow_private_destinations` | bool | `false` | Opt in to webhooks pointing at RFC1918 / loopback / link-local hosts (in-cluster Slack proxy, on-prem Teams gateway). Defaults to public-internet only — SSRF guard |
| `require_https` | bool | `false` | TLS-only enforcement. `true` refuses a plaintext `http://` URL (the SSRF chokepoint raises; the POST is skipped) instead of warn-and-send. Default `false` preserves warn-then-send |
Expand All @@ -310,7 +310,7 @@ exits 0, and nothing is deleted, blocked or scheduled automatically. The
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `strategy` | string | `null` | `"deepspeed"` or `"fsdp"` (null = single GPU) |
| `deepspeed_config` | string | `null` | Preset (`"zero2"`, `"zero3"`, `"zero3_offload"`) or JSON path |
| `deepspeed_config` | string | `null` | JSON path, or a preset name (`"zero2"`, `"zero3"`, `"zero3_offload"`) that resolves only from a source checkout, not from a pip or Docker install |
| `fsdp_strategy` | string | `"full_shard"` | `"full_shard"` or `"shard_grad_op"` (`"hybrid_shard"` and `"no_shard"` are rejected: FSDP2 does not support them) |
| `fsdp_auto_wrap` | bool | `true` | Auto-wrap transformer layers (ignored on transformers 5.10+, which always wraps them) |
| `fsdp_offload` | bool | `false` | Offload parameters to CPU |
Expand Down
Loading
Loading