fix(frontend): update ModelInfoResponse types to match backend structure
- Update TypeScript types to match flat backend response structure - Remove nested model_info and metrics objects - Remove label_config, use labels array and per_class_metrics array - Update all component references to use new structure - Generate default colors for prediction labels in CandleChart - Fix TypeScript type errors for nullable model_version - Remove accuracy/F1 metrics display (not in new response)
This commit is contained in:
parent
aa81d4f3d0
commit
5a7c901980
95 changed files with 326 additions and 63 deletions
2
next-env.d.ts
vendored
2
next-env.d.ts
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
import "./.next/dev/types/routes.d.ts";
|
import "./.next/types/routes.d.ts";
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
precision recall f1-score support
|
||||||
|
|
||||||
|
Bearish Engulfing 0.8065 1.0000 0.8929 25
|
||||||
|
Bullish Engulfing 1.0000 0.8125 0.8966 32
|
||||||
|
|
||||||
|
accuracy 0.8947 57
|
||||||
|
macro avg 0.9032 0.9062 0.8947 57
|
||||||
|
weighted avg 0.9151 0.8947 0.8949 57
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
|
|
@ -0,0 +1,97 @@
|
||||||
|
data:
|
||||||
|
annotations_path: data/annotations/export.json
|
||||||
|
enriched_path: data/enriched/features.csv
|
||||||
|
labeled_path: data/labeled/dataset.csv
|
||||||
|
raw_path: data/raw/OHLCV.csv
|
||||||
|
stages:
|
||||||
|
annotation_ingestion:
|
||||||
|
context_padding: 20
|
||||||
|
enabled: true
|
||||||
|
label_encoding: window
|
||||||
|
merge_strategy: human_priority
|
||||||
|
min_confidence: 1
|
||||||
|
programmatic_labels:
|
||||||
|
enabled: true
|
||||||
|
talib_patterns:
|
||||||
|
- CDLENGULFING
|
||||||
|
- CDLHAMMER
|
||||||
|
- CDLINVERTEDHAMMER
|
||||||
|
- CDLSHOOTINGSTAR
|
||||||
|
- CDLDOJI
|
||||||
|
- CDLDOJISTAR
|
||||||
|
- CDLMORNINGSTAR
|
||||||
|
- CDLEVENINGSTAR
|
||||||
|
- CDLHARAMI
|
||||||
|
- CDLPIERCING
|
||||||
|
- CDLDARKCLOUDCOVER
|
||||||
|
- CDL3WHITESOLDIERS
|
||||||
|
- CDL3BLACKCROWS
|
||||||
|
window_size: 30
|
||||||
|
feature_engineering:
|
||||||
|
candle_features: true
|
||||||
|
custom_features: []
|
||||||
|
enabled: true
|
||||||
|
talib_indicators:
|
||||||
|
- name: RSI
|
||||||
|
params:
|
||||||
|
timeperiod: 14
|
||||||
|
- name: EMA
|
||||||
|
params:
|
||||||
|
timeperiod: 20
|
||||||
|
- name: EMA
|
||||||
|
params:
|
||||||
|
timeperiod: 50
|
||||||
|
- name: MACD
|
||||||
|
params:
|
||||||
|
fastperiod: 12
|
||||||
|
signalperiod: 9
|
||||||
|
slowperiod: 26
|
||||||
|
- name: BBANDS
|
||||||
|
params:
|
||||||
|
nbdevdn: 2
|
||||||
|
nbdevup: 2
|
||||||
|
timeperiod: 20
|
||||||
|
- name: ATR
|
||||||
|
params:
|
||||||
|
timeperiod: 14
|
||||||
|
- name: ADX
|
||||||
|
params:
|
||||||
|
timeperiod: 14
|
||||||
|
- name: CCI
|
||||||
|
params:
|
||||||
|
timeperiod: 14
|
||||||
|
- name: MFI
|
||||||
|
params:
|
||||||
|
timeperiod: 14
|
||||||
|
- name: STOCH
|
||||||
|
params:
|
||||||
|
fastk_period: 14
|
||||||
|
slowd_period: 3
|
||||||
|
slowk_period: 3
|
||||||
|
inference:
|
||||||
|
batch_size: 1000
|
||||||
|
enabled: true
|
||||||
|
local_model_path: models/best_model.pkl
|
||||||
|
mlflow_model_name: candlestick_pattern_v1
|
||||||
|
mlflow_model_stage: Production
|
||||||
|
model_source: local
|
||||||
|
use_training_config: true
|
||||||
|
training:
|
||||||
|
class_weights: balanced
|
||||||
|
enabled: true
|
||||||
|
hyperparameters:
|
||||||
|
max_depth: 15
|
||||||
|
min_samples_leaf: 2
|
||||||
|
min_samples_split: 5
|
||||||
|
n_estimators: 200
|
||||||
|
n_jobs: -1
|
||||||
|
random_state: 42
|
||||||
|
mlflow:
|
||||||
|
experiment_name: candlestick_patterns
|
||||||
|
log_artifacts: true
|
||||||
|
register_model: false
|
||||||
|
tracking_uri: http://localhost:5000
|
||||||
|
model_type: random_forest
|
||||||
|
split_method: temporal
|
||||||
|
test_split: 0.2
|
||||||
|
validation_split: 0.1
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
artifact_uri: file:///home/homoludens/projekti/bitcon/candle_annotator/services/ml/mlruns/358560345319124639/509970efc3e0494ba3c2fbd7dd24d438/artifacts
|
||||||
|
end_time: 1771187605319
|
||||||
|
entry_point_name: ''
|
||||||
|
experiment_id: '358560345319124639'
|
||||||
|
lifecycle_stage: active
|
||||||
|
run_id: 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
run_name: painted-doe-188
|
||||||
|
source_name: ''
|
||||||
|
source_type: 4
|
||||||
|
source_version: ''
|
||||||
|
start_time: 1771187595858
|
||||||
|
status: 3
|
||||||
|
tags: []
|
||||||
|
user_id: homoludens
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597069 0.8947368421052632 0
|
||||||
|
1771187597069 0.8947368421052632 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597121 0.8928571428571429 0
|
||||||
|
1771187597121 0.8928571428571429 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597155 0.896551724137931 0
|
||||||
|
1771187597155 0.896551724137931 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597081 0.8947044334975369 0
|
||||||
|
1771187597081 0.8947044334975369 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597191 0.0 0
|
||||||
|
1771187597191 0.0 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597090 0.8949312937516204 0
|
||||||
|
1771187597090 0.8949312937516204 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597104 0.8064516129032258 0
|
||||||
|
1771187597104 0.8064516129032258 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597133 1.0 0
|
||||||
|
1771187597133 1.0 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597166 0.0 0
|
||||||
|
1771187597166 0.0 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597113 1.0 0
|
||||||
|
1771187597113 1.0 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597145 0.8125 0
|
||||||
|
1771187597145 0.8125 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187597176 0.0 0
|
||||||
|
1771187597176 0.0 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187596947 1.0 0
|
||||||
|
1771187596947 1.0 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187596958 1.0 0
|
||||||
|
1771187596958 1.0 0
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
1771187596967 1.0 0
|
||||||
|
1771187596967 1.0 0
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
destination_id: m-cf12ffc008e047e1a37f58efe209422c
|
||||||
|
destination_type: MODEL_OUTPUT
|
||||||
|
source_id: m-cf12ffc008e047e1a37f58efe209422c
|
||||||
|
source_type: RUN_OUTPUT
|
||||||
|
step: 0
|
||||||
|
tags: {}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
balanced
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
15
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
2
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
5
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
random_forest
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
3
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
200
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
2820
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
-1
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
57
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
207
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
22
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
42
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
temporal
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.2
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
121
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
84
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
2
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.1
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
painted-doe-188
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
aa81d4f3d0dcb9c58799d7bf63fd8fe61006bdce
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
pipeline.py
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
LOCAL
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
homoludens
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
artifact_path: file:///home/homoludens/projekti/bitcon/candle_annotator/services/ml/mlruns/358560345319124639/models/m-cf12ffc008e047e1a37f58efe209422c/artifacts
|
||||||
|
flavors:
|
||||||
|
python_function:
|
||||||
|
env:
|
||||||
|
conda: conda.yaml
|
||||||
|
virtualenv: python_env.yaml
|
||||||
|
loader_module: mlflow.sklearn
|
||||||
|
model_path: model.pkl
|
||||||
|
predict_fn: predict
|
||||||
|
python_version: 3.13.5
|
||||||
|
sklearn:
|
||||||
|
code: null
|
||||||
|
pickled_model: model.pkl
|
||||||
|
serialization_format: cloudpickle
|
||||||
|
sklearn_version: 1.8.0
|
||||||
|
skops_trusted_types: null
|
||||||
|
mlflow_version: 3.9.0
|
||||||
|
model_id: m-cf12ffc008e047e1a37f58efe209422c
|
||||||
|
model_size_bytes: 793682
|
||||||
|
model_uuid: m-cf12ffc008e047e1a37f58efe209422c
|
||||||
|
prompts: null
|
||||||
|
run_id: 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
utc_time_created: '2026-02-15 20:33:18.754593'
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
channels:
|
||||||
|
- conda-forge
|
||||||
|
dependencies:
|
||||||
|
- python=3.13.5
|
||||||
|
- pip
|
||||||
|
- pip:
|
||||||
|
- mlflow==3.9.0
|
||||||
|
- cloudpickle==3.1.2
|
||||||
|
- numpy==2.4.2
|
||||||
|
- pandas==2.3.3
|
||||||
|
- psutil==7.2.2
|
||||||
|
- pyarrow==22.0.0
|
||||||
|
- scikit-learn==1.8.0
|
||||||
|
- scipy==1.17.0
|
||||||
|
name: mlflow-env
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,7 @@
|
||||||
|
python: 3.13.5
|
||||||
|
build_dependencies:
|
||||||
|
- pip
|
||||||
|
- setuptools==82.0.0
|
||||||
|
- wheel
|
||||||
|
dependencies:
|
||||||
|
- -r requirements.txt
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
mlflow==3.9.0
|
||||||
|
cloudpickle==3.1.2
|
||||||
|
numpy==2.4.2
|
||||||
|
pandas==2.3.3
|
||||||
|
psutil==7.2.2
|
||||||
|
pyarrow==22.0.0
|
||||||
|
scikit-learn==1.8.0
|
||||||
|
scipy==1.17.0
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
artifact_location: file:///home/homoludens/projekti/bitcon/candle_annotator/services/ml/mlruns/358560345319124639/models/m-cf12ffc008e047e1a37f58efe209422c/artifacts
|
||||||
|
creation_timestamp: 1771187598541
|
||||||
|
experiment_id: '358560345319124639'
|
||||||
|
last_updated_timestamp: 1771187605161
|
||||||
|
model_id: m-cf12ffc008e047e1a37f58efe209422c
|
||||||
|
model_type: ''
|
||||||
|
name: model
|
||||||
|
source_run_id: 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
status: 2
|
||||||
|
status_message: null
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597069 0.8947368421052632 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597121 0.8928571428571429 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597155 0.896551724137931 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597081 0.8947044334975369 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597191 0.0 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597090 0.8949312937516204 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597104 0.8064516129032258 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597133 1.0 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597166 0.0 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597113 1.0 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597145 0.8125 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187597176 0.0 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187596947 1.0 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187596958 1.0 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1771187596967 1.0 0 509970efc3e0494ba3c2fbd7dd24d438
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
balanced
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
15
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
2
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
5
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
random_forest
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
3
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
200
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
2820
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
-1
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
57
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
207
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
22
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
42
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
temporal
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.2
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
121
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
84
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
2
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.1
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
aa81d4f3d0dcb9c58799d7bf63fd8fe61006bdce
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
pipeline.py
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
LOCAL
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
homoludens
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
custom_model_development
|
||||||
|
|
@ -365,7 +365,7 @@ export default function Home() {
|
||||||
setPredictionState((prev) => ({
|
setPredictionState((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
modelInfo: data,
|
modelInfo: data,
|
||||||
selectedLabels: new Set(data.label_config.map((l) => l.name)),
|
selectedLabels: new Set(data.labels),
|
||||||
error: null,
|
error: null,
|
||||||
}));
|
}));
|
||||||
return data;
|
return data;
|
||||||
|
|
@ -382,9 +382,9 @@ export default function Home() {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Generate cache key from chart, timerange, and model version
|
// Generate cache key from chart, timerange, and model version
|
||||||
const generateCacheKey = useCallback((chartId: number | null, modelVersion?: string) => {
|
const generateCacheKey = useCallback((chartId: number | null, modelVersion?: string | null) => {
|
||||||
if (!chartId) return null;
|
if (!chartId) return null;
|
||||||
const version = modelVersion || predictionState.modelInfo?.model_info.model_version || 'unknown';
|
const version = modelVersion || predictionState.modelInfo?.model_version || 'unknown';
|
||||||
return `${chartId}_${version}`;
|
return `${chartId}_${version}`;
|
||||||
}, [predictionState.modelInfo]);
|
}, [predictionState.modelInfo]);
|
||||||
|
|
||||||
|
|
@ -392,12 +392,12 @@ export default function Home() {
|
||||||
const fetchPredictions = useCallback(async (candles: any[]) => {
|
const fetchPredictions = useCallback(async (candles: any[]) => {
|
||||||
if (!activeChartId || candles.length === 0) return;
|
if (!activeChartId || candles.length === 0) return;
|
||||||
|
|
||||||
const cacheKey = generateCacheKey(activeChartId, predictionState.modelInfo?.model_info.model_version);
|
const cacheKey = generateCacheKey(activeChartId, predictionState.modelInfo?.model_version);
|
||||||
|
|
||||||
// Check cache first
|
// Check cache first
|
||||||
if (cacheKey && predictionCacheRef.current.has(cacheKey)) {
|
if (cacheKey && predictionCacheRef.current.has(cacheKey)) {
|
||||||
const cached = predictionCacheRef.current.get(cacheKey)!;
|
const cached = predictionCacheRef.current.get(cacheKey)!;
|
||||||
if (cached.modelVersion === predictionState.modelInfo?.model_info.model_version) {
|
if (cached.modelVersion === predictionState.modelInfo?.model_version) {
|
||||||
setPredictionState((prev) => ({
|
setPredictionState((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
spans: cached.spans,
|
spans: cached.spans,
|
||||||
|
|
@ -562,7 +562,7 @@ export default function Home() {
|
||||||
// Clear prediction cache when model version changes
|
// Clear prediction cache when model version changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (predictionState.modelInfo) {
|
if (predictionState.modelInfo) {
|
||||||
const currentVersion = predictionState.modelInfo.model_info.model_version;
|
const currentVersion = predictionState.modelInfo.model_version;
|
||||||
// Clear cache entries with different model versions
|
// Clear cache entries with different model versions
|
||||||
const newCache = new Map();
|
const newCache = new Map();
|
||||||
for (const [key, value] of predictionCacheRef.current.entries()) {
|
for (const [key, value] of predictionCacheRef.current.entries()) {
|
||||||
|
|
@ -572,7 +572,7 @@ export default function Home() {
|
||||||
}
|
}
|
||||||
predictionCacheRef.current = newCache;
|
predictionCacheRef.current = newCache;
|
||||||
}
|
}
|
||||||
}, [predictionState.modelInfo?.model_info.model_version]);
|
}, [predictionState.modelInfo?.model_version]);
|
||||||
|
|
||||||
// Health polling - check model status every 30 seconds when offline
|
// Health polling - check model status every 30 seconds when offline
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -374,10 +374,21 @@ const CandleChart = forwardRef<CandleChartHandle, CandleChartProps>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a label-to-color map from modelInfo
|
// Build a label-to-color map from modelInfo
|
||||||
|
// Generate colors for labels since backend no longer provides them
|
||||||
const labelColorMap: Record<string, string> = {};
|
const labelColorMap: Record<string, string> = {};
|
||||||
if (modelInfo?.label_config) {
|
if (modelInfo?.labels) {
|
||||||
modelInfo.label_config.forEach((lc) => {
|
const predefinedColors = [
|
||||||
labelColorMap[lc.name] = lc.color;
|
'#3b82f6', // blue
|
||||||
|
'#ef4444', // red
|
||||||
|
'#10b981', // green
|
||||||
|
'#f59e0b', // amber
|
||||||
|
'#8b5cf6', // violet
|
||||||
|
'#ec4899', // pink
|
||||||
|
'#06b6d4', // cyan
|
||||||
|
'#f97316', // orange
|
||||||
|
];
|
||||||
|
modelInfo.labels.forEach((label, index) => {
|
||||||
|
labelColorMap[label] = predefinedColors[index % predefinedColors.length];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ interface PredictionPanelProps {
|
||||||
onFetchBatchPredictions: () => void;
|
onFetchBatchPredictions: () => void;
|
||||||
onConfidenceChange: (threshold: number) => void;
|
onConfidenceChange: (threshold: number) => void;
|
||||||
onToggleLabelSelection: (label: string) => void;
|
onToggleLabelSelection: (label: string) => void;
|
||||||
predictionSummary?: PredictionSummary;
|
predictionSummary: PredictionSummary | null;
|
||||||
isModelOnline: boolean;
|
isModelOnline: boolean;
|
||||||
showOnlyDisagreements?: boolean;
|
showOnlyDisagreements?: boolean;
|
||||||
onToggleShowOnlyDisagreements?: () => void;
|
onToggleShowOnlyDisagreements?: () => void;
|
||||||
|
|
@ -77,23 +77,15 @@ export default function PredictionPanel({
|
||||||
<div className="mb-3 p-2 bg-muted/50 rounded text-xs">
|
<div className="mb-3 p-2 bg-muted/50 rounded text-xs">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-muted-foreground">Model:</span>
|
<span className="text-muted-foreground">Model:</span>
|
||||||
<span className="font-mono text-foreground">{modelInfo.model_info.model_name}</span>
|
<span className="font-mono text-foreground">{modelInfo.model_name}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-muted-foreground">Version:</span>
|
<span className="text-muted-foreground">Version:</span>
|
||||||
<span className="font-mono text-foreground">{modelInfo.model_info.model_version}</span>
|
<span className="font-mono text-foreground">{modelInfo.model_version || 'N/A'}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<span className="text-muted-foreground">Type:</span>
|
<span className="text-muted-foreground">Type:</span>
|
||||||
<span className="text-foreground">{modelInfo.model_info.model_type}</span>
|
<span className="text-foreground">{modelInfo.model_type}</span>
|
||||||
</div>
|
|
||||||
<div className="flex justify-between mt-1 pt-1 border-t border-border">
|
|
||||||
<span className="text-muted-foreground">Accuracy:</span>
|
|
||||||
<span className="text-foreground">{(modelInfo.metrics.accuracy * 100).toFixed(1)}%</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<span className="text-muted-foreground">F1 (macro):</span>
|
|
||||||
<span className="text-foreground">{(modelInfo.metrics.f1_macro * 100).toFixed(1)}%</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -144,26 +136,22 @@ export default function PredictionPanel({
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label className="text-xs text-muted-foreground mb-2 block">Filter by Label</label>
|
<label className="text-xs text-muted-foreground mb-2 block">Filter by Label</label>
|
||||||
<div className="space-y-1 max-h-32 overflow-y-auto">
|
<div className="space-y-1 max-h-32 overflow-y-auto">
|
||||||
{modelInfo.label_config.map((labelConfig) => {
|
{modelInfo.labels.map((label) => {
|
||||||
const metrics = modelInfo.metrics.per_class[labelConfig.name];
|
const metrics = modelInfo.per_class_metrics.find((m) => m.label === label);
|
||||||
const isSelected = selectedLabels.has(labelConfig.name);
|
const isSelected = selectedLabels.has(label);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
key={labelConfig.name}
|
key={label}
|
||||||
className="flex items-center gap-2 p-1 rounded hover:bg-muted/50 cursor-pointer"
|
className="flex items-center gap-2 p-1 rounded hover:bg-muted/50 cursor-pointer"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={isSelected}
|
checked={isSelected}
|
||||||
onChange={() => onToggleLabelSelection(labelConfig.name)}
|
onChange={() => onToggleLabelSelection(label)}
|
||||||
className="w-3 h-3"
|
className="w-3 h-3"
|
||||||
/>
|
/>
|
||||||
<div
|
<span className="text-xs text-foreground flex-1">{label}</span>
|
||||||
className="w-3 h-3 rounded"
|
|
||||||
style={{ backgroundColor: labelConfig.color }}
|
|
||||||
/>
|
|
||||||
<span className="text-xs text-foreground flex-1">{labelConfig.name}</span>
|
|
||||||
{metrics && (
|
{metrics && (
|
||||||
<span className="text-xs text-muted-foreground font-mono">
|
<span className="text-xs text-muted-foreground font-mono">
|
||||||
F1: {(metrics.f1_score * 100).toFixed(0)}%
|
F1: {(metrics.f1_score * 100).toFixed(0)}%
|
||||||
|
|
|
||||||
|
|
@ -16,40 +16,23 @@ export interface PerCandlePrediction {
|
||||||
confidence: number;
|
confidence: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModelInfo {
|
|
||||||
model_name: string;
|
|
||||||
model_version: string;
|
|
||||||
model_type: string;
|
|
||||||
experiment_name: string;
|
|
||||||
run_id: string;
|
|
||||||
trained_at: string;
|
|
||||||
feature_count: number;
|
|
||||||
label_names: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PerClassMetrics {
|
export interface PerClassMetrics {
|
||||||
[label: string]: {
|
label: string;
|
||||||
precision: number;
|
precision: number;
|
||||||
recall: number;
|
recall: number;
|
||||||
f1_score: number;
|
f1_score: number;
|
||||||
support: number;
|
support: number;
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ModelMetrics {
|
|
||||||
accuracy: number;
|
|
||||||
f1_macro: number;
|
|
||||||
f1_weighted: number;
|
|
||||||
per_class: PerClassMetrics;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModelInfoResponse {
|
export interface ModelInfoResponse {
|
||||||
model_info: ModelInfo;
|
model_name: string;
|
||||||
metrics: ModelMetrics;
|
model_version: string | null;
|
||||||
label_config: {
|
model_type: string;
|
||||||
name: string;
|
trained_at: string | null;
|
||||||
color: string;
|
dataset_version: string | null;
|
||||||
}[];
|
feature_engineering_enabled: boolean;
|
||||||
|
labels: string[];
|
||||||
|
per_class_metrics: PerClassMetrics[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PredictRequest {
|
export interface PredictRequest {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue