feat: add FastAPI model/load endpoint and all Next.js proxy routes (tasks 2-4)
This commit is contained in:
parent
b8e649e333
commit
2a02669222
29 changed files with 1110 additions and 780 deletions
122
openspec/changes/ml-ui-connection/specs/backend-api/spec.md
Normal file
122
openspec/changes/ml-ui-connection/specs/backend-api/spec.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
## ADDED Requirements
|
||||
|
||||
### Requirement: Pattern detection endpoint
|
||||
The FastAPI service SHALL provide a `POST /patterns/detect` endpoint that accepts candle data and a list of CDL pattern names. The endpoint SHALL run the specified TA-Lib CDL functions on the candle data and return detected patterns as span annotation objects. Each returned annotation SHALL include start_time, end_time, label, confidence, and source ("talib").
|
||||
|
||||
#### Scenario: Detect specific patterns
|
||||
- **WHEN** `POST /patterns/detect` is called with `{candles: [...], patterns: ["CDLENGULFING", "CDLHAMMER"]}`
|
||||
- **THEN** the endpoint runs only Engulfing and Hammer detection and returns matching span annotations
|
||||
|
||||
#### Scenario: Detect all patterns
|
||||
- **WHEN** `POST /patterns/detect` is called with `{candles: [...], patterns: []}` (empty list)
|
||||
- **THEN** the endpoint runs all available CDL pattern functions
|
||||
|
||||
#### Scenario: No patterns found
|
||||
- **WHEN** detection runs but no patterns match
|
||||
- **THEN** the endpoint returns `{annotations: [], metadata: {count: 0}}`
|
||||
|
||||
#### Scenario: Invalid pattern name
|
||||
- **WHEN** a pattern name is not a valid TA-Lib CDL function
|
||||
- **THEN** the endpoint returns HTTP 400 with the invalid pattern name in the error message
|
||||
|
||||
### Requirement: Available patterns endpoint
|
||||
The FastAPI service SHALL provide a `GET /patterns/available` endpoint that returns the list of all supported CDL pattern names with their friendly display names.
|
||||
|
||||
#### Scenario: List available patterns
|
||||
- **WHEN** `GET /patterns/available` is called
|
||||
- **THEN** the endpoint returns a list of `{function_name, display_name}` for all supported CDL patterns
|
||||
|
||||
### Requirement: Training start endpoint
|
||||
The FastAPI service SHALL provide a `POST /training/start` endpoint that triggers a training run in a background thread. The endpoint SHALL accept `{model_type}` and return immediately with a run_id and status "running". Only one training run SHALL be allowed at a time.
|
||||
|
||||
#### Scenario: Start training
|
||||
- **WHEN** `POST /training/start` is called with `{model_type: "random_forest"}`
|
||||
- **THEN** the endpoint returns `{run_id, status: "running"}` and training begins in the background
|
||||
|
||||
#### Scenario: Training already in progress
|
||||
- **WHEN** `POST /training/start` is called while a training run is active
|
||||
- **THEN** the endpoint returns HTTP 409 with `{error: "Training already in progress", run_id: "<active_run_id>"}`
|
||||
|
||||
#### Scenario: Invalid model type
|
||||
- **WHEN** `POST /training/start` is called with an unsupported model type
|
||||
- **THEN** the endpoint returns HTTP 400 with `{error: "Unsupported model type. Available: random_forest, xgboost"}`
|
||||
|
||||
### Requirement: Training runs endpoint
|
||||
The FastAPI service SHALL provide a `GET /training/runs` endpoint that returns training run history from the database. Each entry SHALL include run_id, model_type, status, created_at, completed_at, and metrics_summary. Results SHALL be sorted by created_at descending.
|
||||
|
||||
#### Scenario: List training runs
|
||||
- **WHEN** `GET /training/runs` is called
|
||||
- **THEN** the endpoint returns training run records sorted by date descending
|
||||
|
||||
#### Scenario: No training runs
|
||||
- **WHEN** no training runs exist in the database
|
||||
- **THEN** the endpoint returns `{runs: []}`
|
||||
|
||||
### Requirement: Model load endpoint
|
||||
The FastAPI service SHALL provide a `POST /model/load` endpoint that loads a model by run_id. The endpoint SHALL look up the training run, find the model artifact (MLflow or local), and replace the currently loaded model. The endpoint SHALL return the new model's info.
|
||||
|
||||
#### Scenario: Load model by run_id
|
||||
- **WHEN** `POST /model/load` is called with `{run_id: "abc123"}`
|
||||
- **THEN** the endpoint loads the model associated with that run, updates the active model, and returns model info
|
||||
|
||||
#### Scenario: Run not found
|
||||
- **WHEN** `POST /model/load` is called with a non-existent run_id
|
||||
- **THEN** the endpoint returns HTTP 404 with `{error: "Training run not found"}`
|
||||
|
||||
#### Scenario: Model artifact missing
|
||||
- **WHEN** the training run exists but the model file is missing
|
||||
- **THEN** the endpoint returns HTTP 500 with `{error: "Model artifact not found for run"}`
|
||||
|
||||
### Requirement: Dataset info endpoint
|
||||
The FastAPI service SHALL provide a `GET /training/dataset-info` endpoint that returns information about the training dataset: file path, existence status, file size, and last modified date.
|
||||
|
||||
#### Scenario: Dataset exists
|
||||
- **WHEN** `GET /training/dataset-info` is called and the labeled dataset file exists
|
||||
- **THEN** the endpoint returns `{path, exists: true, size_bytes, last_modified, row_count}`
|
||||
|
||||
#### Scenario: Dataset missing
|
||||
- **WHEN** `GET /training/dataset-info` is called and the labeled dataset file does not exist
|
||||
- **THEN** the endpoint returns `{path, exists: false}`
|
||||
|
||||
### Requirement: Pattern detection proxy
|
||||
The Next.js API SHALL provide a `POST /api/patterns/detect` route that proxies to the FastAPI `/patterns/detect` endpoint.
|
||||
|
||||
#### Scenario: Proxy pattern detection
|
||||
- **WHEN** `POST /api/patterns/detect` is called
|
||||
- **THEN** the route forwards the request to the FastAPI service and returns the response
|
||||
|
||||
### Requirement: Available patterns proxy
|
||||
The Next.js API SHALL provide a `GET /api/patterns/available` route that proxies to the FastAPI `/patterns/available` endpoint.
|
||||
|
||||
#### Scenario: Proxy available patterns
|
||||
- **WHEN** `GET /api/patterns/available` is called
|
||||
- **THEN** the route forwards to the FastAPI service and returns the pattern list
|
||||
|
||||
### Requirement: Training proxy endpoints
|
||||
The Next.js API SHALL provide proxy routes for training operations: `POST /api/training/start`, `GET /api/training/runs`, and `GET /api/training/dataset-info`.
|
||||
|
||||
#### Scenario: Proxy training start
|
||||
- **WHEN** `POST /api/training/start` is called
|
||||
- **THEN** the route forwards to the FastAPI service and returns the response
|
||||
|
||||
#### Scenario: Proxy training runs
|
||||
- **WHEN** `GET /api/training/runs` is called
|
||||
- **THEN** the route forwards to the FastAPI service and returns the run list
|
||||
|
||||
### Requirement: Model load proxy
|
||||
The Next.js API SHALL provide a `POST /api/model/load` route that proxies to the FastAPI `/model/load` endpoint.
|
||||
|
||||
#### Scenario: Proxy model load
|
||||
- **WHEN** `POST /api/model/load` is called with a run_id
|
||||
- **THEN** the route forwards to the FastAPI service and returns the response
|
||||
|
||||
### Requirement: Bulk delete by source
|
||||
The Next.js API `DELETE /api/span-annotations` endpoint SHALL support a `source` query parameter for bulk deletion. When `source` is provided, all span annotations matching that source (and optionally `label` filter) for the current chart SHALL be deleted.
|
||||
|
||||
#### Scenario: Bulk delete TA-Lib annotations
|
||||
- **WHEN** `DELETE /api/span-annotations?chartId=1&source=talib` is called
|
||||
- **THEN** all span annotations with `source: "talib"` for chart 1 are deleted
|
||||
|
||||
#### Scenario: Bulk delete by source and label
|
||||
- **WHEN** `DELETE /api/span-annotations?chartId=1&source=talib&label=Engulfing` is called
|
||||
- **THEN** only TA-Lib annotations containing "Engulfing" in the label for chart 1 are deleted
|
||||
Loading…
Add table
Add a link
Reference in a new issue