Spaces:
Running
Running
File size: 5,603 Bytes
2b83ee8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | ## `/model` API
λͺ¨λΈ λ€μ΄λ‘λ μλν¬μΈνΈλ μ΅μ λͺ¨λΈκ³Ό νΉμ λ²μ μ λͺ¨λΈμ λͺ¨λ μ 곡νλ©°, μλ΅ ν€λλ₯Ό ν΅ν΄ μ€μ λ²μ μ 보λ₯Ό νμΈν μ μμ΅λλ€.
### μμ² νμ
```
GET /model
GET /model?version={λ²νΈ}
GET /model?version={λ²νΈ}&filename={νμΌλͺ
}
```
| νλΌλ―Έν° | νμ
| μ€λͺ
|
| --- | --- | --- |
| `version` (μ ν) | int | μλ΅νκ±°λ λΉ κ°μ΄λ©΄ μ΅μ λͺ¨λΈ. μ§μ νλ©΄ ν΄λΉ λ²μ νμΈ ν λ€μ΄λ‘λ. |
| `filename` (μ ν) | string | λ΄λ €λ°μ νμΌλͺ
. κΈ°λ³Έκ°μ νκ²½ λ³μ `HF_E2E_MODEL_FILE` (κΈ°λ³Έ `cnn_gru_fatigue.tflite`). |
### μλ΅
- λ³Έλ¬Έ: μμ²ν λͺ¨λΈ λ°μ΄λ리 (μ: `.tflite`, `.keras`, λ©νλ°μ΄ν° λ±)
- ν€λ:
- `X-Model-Version`: μ€μ λ€μ΄λ‘λλ λͺ¨λΈ λ²μ
- `X-Model-Filename`: λ°νλ νμΌλͺ
- μλ¬:
- `404` β μμ²ν λ²μ μ΄ νμ¬ `model_version`λ³΄λ€ ν¬κ±°λ manifestμ μ‘΄μ¬νμ§ μμ λ
- `500` β Hugging Face Hub λ€μ΄λ‘λ μ€ν¨ λ± λ΄λΆ μ€λ₯
### λμ κ·μΉ
1. μλ²λ `training_state.json`μ `model_version` κ°μ μ½μ΄ νμ¬ νμ© κ°λ₯ν μ΅λ λ²μ μ νμΈν©λλ€.
2. `version`μ μ§μ νμ§ μμΌλ©΄ μ΅μ λͺ¨λΈ(νμ¬ λ²μ )μ λ€μ΄λ‘λν©λλ€.
3. `version`μ μ§μ νλ©΄ μλ²κ° νμ¬ `model_version` μ΄νμΈμ§ νμΈν λ€, λμΌν νμΌλͺ
μ λ΄λ €μ€λλ€(λ²μ λ³λ‘ νμΌλͺ
μ ꡬλΆνμ§ μμ΅λλ€).
4. μμ²ν λ²μ μ΄ νμ¬ λ²μ λ³΄λ€ ν¬κ±°λ νμΌμ΄ μ‘΄μ¬νμ§ μμΌλ©΄ `404`λ₯Ό λ°νν©λλ€.
### μ¬μ© μμ
#### μ΅μ λͺ¨λΈ λ€μ΄λ‘λ
```bash
curl -L -o cnn_gru_fatigue_latest.tflite \
"https://merry99-musclecare-train-ai.hf.space/model"
```
#### λ²μ 3 λͺ¨λΈ λ€μ΄λ‘λ
```bash
curl -L -o cnn_gru_fatigue_v3.tflite \
"https://merry99-musclecare-train-ai.hf.space/model?version=3"
```
#### λ²μ 3 λ©νλ°μ΄ν° λ€μ΄λ‘λ
```bash
curl -L -o metadata_v3.json \
"https://merry99-musclecare-train-ai.hf.space/model?version=3&filename=cnn_gru_fatigue_metadata.json"
```
#### ν€λ νμΈ
```bash
curl -I "https://merry99-musclecare-train-ai.hf.space/model?version=3"
```
μλ΅ ν€λ μμ:
```
X-Model-Version: 3
X-Model-Filename: cnn_gru_fatigue.tflite
```
### μ£Όμ μ¬ν
- `training_state.json`μ `model_version` κ°μ΄ κΈ°μ€μ΄ λλ©°, κ·Έλ³΄λ€ λμ λ²μ μ μμ²νλ©΄ 404κ° λ°νλ©λλ€.
- λ²μ λ³λ‘ λ€λ₯Έ νμΌμ μ μ§νμ§ μκ³ , κ°μ νμΌλͺ
μ λ΄λ €μ£Όλ ν€λ(`X-Model-Version`)λ‘ μ€μ λ²μ μ νμΈν©λλ€.
- μ€ν¨(μ: 404) μ JSON μλ΅μ΄ λ΄λ €μ€λ―λ‘, ν΄λΌμ΄μΈνΈλ μν μ½λλ₯Ό λ¨Όμ νμΈν λ€ **200μΌ λλ§** `body`λ₯Ό νμΌλ‘ μ μ₯νμΈμ.
Flutter μμ (Dio):
```dart
final response = await dio.get<List<int>>(
'https://merry99-musclecare-train-ai.hf.space/model',
options: Options(responseType: ResponseType.bytes),
);
if (response.statusCode == 200) {
final version = response.headers.value('X-Model-Version');
final filename = response.headers.value('X-Model-Filename') ?? 'model.tflite';
await File('/path/$filename').writeAsBytes(response.data!);
} else {
final errorText = utf8.decode(response.data ?? []);
// μλ¬ μ²λ¦¬
}
```
- Space νκ²½ λ³μ `HF_E2E_MODEL_TOKEN`, `HF_E2E_MODEL_REPO_ID`κ° μ¬λ°λ₯΄κ² μ€μ λΌ μμ΄μΌ `/model` λ° `/trigger`κ° μ μ λμν©λλ€.
## λͺ¨λΈ μ
λ ₯ μ¬μ (Flutter μ°Έκ³ )
- μ
λ ₯ νμ: `(batch_size, input_dim)`μ΄λ©° κΈ°λ³Έ `input_dim = 10 (FEATURE_COLUMNS) + embedding_dim`.
- `FEATURE_COLUMNS`: `rms_acc`, `rms_gyro`, `mean_freq_acc`, `mean_freq_gyro`, `entropy_acc`, `entropy_gyro`, `jerk_mean`, `jerk_std`, `stability_index`, `fatigue_prev`.
- `user_emb`: λ©νλ°μ΄ν°μ `embedding_dim`κ³Ό λμΌν κΈΈμ΄. λΆμ‘±νλ©΄ λ€λ₯Ό `0.0f`λ‘ ν¨λ©.
- λ©νλ°μ΄ν°(`cnn_gru_fatigue_metadata.json`)μ `scaler.mean`, `scaler.scale`λ‘ νμ€νν λ€ λͺ¨λΈμ μ λ¬.
### Flutterμμ μ€ν μμ
- **λ©νλ°μ΄ν° λ‘λ**: JSONμμ `feature_columns`, `scaler.mean`, `scaler.scale`, `embedding_dim`, `input_dim`μ μ½λλ€.
- **νΉμ§ μΆμΆ**: μΈ‘μ λ²νΌμ λλ¬ μ»μ μλμ°μμ 10κ° νΌμ² κ°μ κ³μ°νλ€.
- **νμ€ν**: `(value - mean) / scale`μ μννλ `scale`μ΄ 0μ΄λ©΄ 0μΌλ‘ λ체.
- **μ
λ ₯ λ²‘ν° κ΅¬μ±**: `[μ κ·νλ 10κ° νΌμ², user_emb(ν¨λ© ν¬ν¨)]`μ μ΄μ΄ λΆμ¬ `Float32List`λ‘ λ§λ λ€.
- **TFLite μ€ν**: μ
λ ₯μ `[1, input_dim]`μΌλ‘ reshape ν `interpreter.run(input, output)`μ νΈμΆνλ€.
```dart
final meta = await loadMetadata(); // JSON νμ±: scaler, embedding_dim λ±
final features = computeFeatureVector(); // κΈΈμ΄ 10, float
final userEmb = ensureEmbeddingLength(rawEmb, meta.embeddingDim); // ν¨λ©
final normalized = List<double>.generate(features.length, (i) {
final scale = meta.scalerScale[i] == 0 ? 1.0 : meta.scalerScale[i];
return (features[i] - meta.scalerMean[i]) / scale;
});
final inputVector = Float32List.fromList([
...normalized,
...userEmb.map((e) => e.toDouble()),
]);
final outputBuffer = Float32List(1);
interpreter.run(inputVector.reshape([1, inputVector.length]), outputBuffer);
final fatigueScore = outputBuffer[0];
```
### μ£Όμ
- μ΅μ΄ μΈ‘μ λΆν° λ°λ‘ μμΈ‘ κ°λ₯νλ©°, λ μ΄μ 5κ° μλμ° λμ μ΄ νμνμ§ μμ΅λλ€.
- `fatigue_prev`λ μ§μ μΈ‘μ μ νΌλ‘λ μ§νλ‘, κ°μ΄ μλ€λ©΄ `0` λλ μ§μ μμΈ‘μΉλ‘ μ΄κΈ°νν΄ μ£ΌμΈμ.
- νΌμ² μΆμΆ λ‘μ§κ³Ό μλ² λ© μ°¨μμ λ°±μλ νμ΅ νμ΄νλΌμΈκ³Ό λμΌν΄μΌ ν©λλ€.
|