Skip to content

Commit b95c264

Browse files
author
Elwardi
committed
docs: update implementation docs
1 parent e7f8621 commit b95c264

2 files changed

Lines changed: 52 additions & 64 deletions

File tree

docs/00-implementation.md

Lines changed: 49 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,68 @@
1-
# Code design style
1+
# Code design
22

3-
## Configuration validation and reporting of possible flags:
3+
foamBO = Ax + pydantic v2 + foamlib + FastAPI.
44

5-
## Motivation and Effects
5+
## Config tree
66

7-
We take a banana-trick-like approach for user convenience when creating configuration files.
8-
The goal is to make it easy for users and LLMs to reach a working configuration with trial-and-error.
7+
Root model: `FoamBOConfig` in `orchestrate.py`. Sub-models validated via `@field_validator`.
8+
All inherit `FoamBOBaseModel`. Field defaults + `examples=[...]` harvested by `default_config.py::get_default_config()`.
99

10-
To start, we get a missing top-level key error if it's not there yet. Let's take `orchestration_settings` as an example:
10+
## Subsystems
1111

12-
```shell
13-
omegaconf.errors.ConfigKeyError: Missing key orchestration_settings
14-
full_key: orchestration_settings
15-
object_type=dict
16-
```
12+
| File | Job |
13+
|---|---|
14+
| `orchestrate.py` | pydantic models (config tree) |
15+
| `optimize.py` | CLI entry, Ax client lifecycle |
16+
| `api.py` | `FoamBO` fluent builder |
17+
| `api_server.py` | FastAPI dashboard + REST + config builder |
18+
| `preflight.py` | static checks, dry-run |
19+
| `metrics.py` | `FoamJob`, `LocalJobMetric` |
20+
| `default_config.py` | defaults + `get_config_docs()` harvest |
21+
| `docs_concepts.py` | long-form concept entries |
22+
| `archive.py` | trial archival |
23+
| `analysis.py` | post-hoc analysis |
24+
| `config_upgrade.py` | version migration |
1725

18-
If we then assume users don't know what parameters to set in the `orchestration_settings` sub-dict,
19-
figuring it out is as easy as setting:
26+
## Orchestration
2027

21-
```yaml
22-
orchestration_settings: null
23-
```
28+
foamBO uses Ax's native `Orchestrator` (poll-based). Harvest latency is
29+
bounded by `init_seconds_between_polls` in the scheduler options.
2430

25-
```shell
26-
ValueError: Got an empty configuration for OrchestratorOptions.__init__, but expecting fields
27-
['max_trials', 'parallelism', 'global_stopping_strategy', 'tolerated_trial_failure_rate=0.5', 'initial_seconds_between_polls=0.1']
28-
```
31+
`FoamJobRunner.poll_trial` consumes a push queue at the top of each poll
32+
cycle so remote runners (SLURM, SSH) can notify completion via HTTP POST:
2933

30-
> Note that defaulted arguments are optional, but it's convenient to be able to see the active defaults.
34+
- `POST /api/v1/trials/{idx}/push/status` — writes `_state.trial_status_overrides[idx]`
35+
- `POST /api/v1/trials/{idx}/push/metrics` — appends to `_state.trial_pushed_metrics[idx]`
36+
- `POST /api/v1/trials/{idx}/push/heartbeat` — liveness only
37+
- `GET /api/v1/events` — dashboard-facing event log
3138

32-
This carries on recursively through the configuration tree. For example, the following configuration:
33-
```yaml
34-
# tolerated_trial_failure_rate and initial_seconds_between_polls are defaulted
35-
orchestration_settings:
36-
max_trials: 30
37-
parallelism: 4
38-
global_stopping_strategy: null
39-
```
40-
will result in the following error:
41-
```shell
42-
TypeError: OrchestratorOptions.create_global_stopping_strategy() got unexpected arguments from global_stopping_strategy sub-dict.
43-
Provided: empty configuration
44-
Expected: ['min_trials', 'window_size', 'improvement_bar']
45-
```
39+
Env vars injected into every trial subprocess:
40+
`FOAMBO_API_ENDPOINT`, `FOAMBO_TRIAL_INDEX`, `FOAMBO_SESSION_ID`.
4641

47-
`src/foambo/common.py` defines some utilities to create objects straight from dictionaries and
48-
ensure arguments are validated properly. Two usage patterns are common:
42+
Session-ID validation rejects pushes from stale jobs of prior crashed runs (HTTP 409).
4943

44+
## Key subsystems
5045

51-
### Validate dictionary entries as function arguments
46+
- **Trial dependencies**`TrialDependency` / `TrialSelector` / `TrialAction`. Phases: `immediate`, `pre_init`, `pre_mesh`, `pre_solve`, `post_solve`. Hook scripts exposed via `$FOAMBO_PRE_MESH` etc.
47+
- **Dimensionality reduction**`DimensionalityReductionOptions` inside `ConfigOrchestratorOptions`. Sobol-based param freezing after N trials.
48+
- **Parameter groups**`groups: [...]` tag on each param. Feeds group sensitivity, `matching_group` dep strategy, group-frozen sweeps, what-if in Predict tab.
49+
- **Config builder UI**`templates/config_builder.{html,js,css}`. Pico CSS + Alpine. Endpoints: `/config-builder`, `/api/v1/config/{schema,docs,validate,preflight}`.
5250

53-
```python
54-
# Will throw an exception if generation_config is missing required
55-
# keys for it to unpack to client.configure_generation_strategy arguments
56-
validate_args(client.configure_generation_strategy, generation_config)
57-
client.configure_generation_strategy(**generation_config)
58-
```
51+
## Docs pipeline
5952

60-
### Create objects with validation for nested fields creation
53+
`default_config.py::get_config_docs()` merges:
6154

62-
```python
63-
@dataclass
64-
class MyType():
65-
setting: int
66-
nested_field: AnotherType
55+
1. Pydantic Field descriptions (`harvest_docs` on `_get_doc_models()`)
56+
2. Manual YAML examples (`_examples` dict)
57+
3. `docs_concepts.py::CONCEPTS` — long-form markdown
58+
4. `load_tutorial_docs()``docs/*.md` summaries
6759

68-
__nested_fields__ : {
69-
"nested_field": "create_nested_field"
70-
}
60+
Served at `GET /api/v1/config/docs` for the config builder tooltips + Concepts modal. TUI browses same data via `foamBO --docs`.
7161

72-
@classmethod
73-
def create_nested_field(cls, arg1: int, arg2: float):
74-
return AnotherType(arg1=arg1, arg2=arg2)
62+
## Contributing
7563

76-
obj = instantiate_with_nested_fields(MyType, cfg['my_type'])
77-
```
78-
79-
This then can be helpful in creating documentation entities for each configuration entry.
64+
1. Add/modify pydantic model. Use `Field(description=..., examples=[...])` — both are harvested.
65+
2. If it's a new root section, add to `FoamBOConfig` + `_get_root_models()` + `_get_doc_models()`.
66+
3. For cross-cutting examples, drop an entry in `_examples` in `default_config.py`.
67+
4. For concept-level docs, add to `CONCEPTS` in `docs_concepts.py`.
68+
5. Run `foamBO --preflight <cfg>` on changed configs before commit.

docs/01-single-objective.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ The [single-objective](/examples/single-objective) folder provides a complete ex
4242

4343
The configuration file needs to contain a few sections:
4444
1. `experiment` to configure experiment meta-data and the parameter space
45-
1. `trial_generation` to configure the way "new trials are generated"
46-
1. `existing_trials` to load data for pre-existing trials if any
45+
1. `trial_generation` to configure the way "new trials are generated". To seed the
46+
experiment with pre-existing data (CSV or a saved foamBO JSON state), add a
47+
`SeedDataNode` to `trial_generation.generation_nodes` (see `method: custom`).
4748
1. `baseline` to promote a specific parameter set as a "baseline" for the analysis routines
4849
1. `optimization` to configure objectives, metrics, how there are computed, and how to handle
4950
the template case.
@@ -70,8 +71,6 @@ experiment:
7071
parameter_constraints: []
7172
trial_generation: # Automatic trial generation
7273
method: fast # Center-of-domain -> A few random ones -> BOtorch
73-
existing_trials:
74-
file_path: '' # No pre-existing trial data
7574
baseline:
7675
parameters: null # No baseline
7776
optimization:

0 commit comments

Comments
 (0)