Spaces:
Sleeping
Sleeping
| # API ๋ช ์ธ์ (v1) | |
| Base URL | |
| ``` | |
| /api/v1 | |
| ``` | |
| ์์ฝ | |
| - ์ฃผ์ ๋ฆฌ์์ค: /posts, /predict, /uploads, /stats | |
| - ์๋ต ํฌ๋งท: JSON (HTML ํ์ด์ง๋ ์น ๋ผ์ฐํธ๋ก ๋ณ๋ ์ ๊ณต) | |
| - ํ๋ ๋ค์ด๋ฐ: snake_case | |
| - ๋ ์ง/์๊ฐ: ISO 8601 (์: 2026-04-28T12:34:56Z) | |
| ๊ณตํต ์๋ฌ ์๋ต (์์) | |
| ```json | |
| { | |
| "success": false, | |
| "error": { | |
| "code": 400, | |
| "message": "Bad Request", | |
| "details": null | |
| } | |
| } | |
| ``` | |
| ์ธ์ฆ / Rate limiting | |
| - ์ธ์ฆ: ์ ํ(์: JWT Authorization: Bearer <token>), ํ์ํ ์๋ํฌ์ธํธ์ ํ๊ธฐ | |
| - Rate limit: ์์ - 60 requests/min (๋ฌธ์ํ ๊ถ์ฅ) | |
| ๋ชจ๋ธ ๋ฉํ๋ฐ์ดํฐ(๊ถ์ฅ ์๋ต ํ๋) | |
| - model_name, model_version, inference_time_ms | |
| --- | |
| ## 1. ์น ํ์ด์ง ๋ผ์ฐํ (HTML) | |
| (์น ์๋ฒ ํ ํ๋ฆฟ์ฉ; API Base URL ์ ์ฉ ์์) | |
| - GET / โ 200 HTML (index.html) | |
| - GET /board โ 200 HTML (board.html) | |
| - GET /posts/{post_id} โ 200 HTML (post detail) | |
| --- | |
| ## 2. ์ด๋ฏธ์ง ๋ถ๋ฅ API (routers/predict.py) | |
| ### [POST] ์ด๋ฏธ์ง ๋ถ๋ฅ | |
| POST /api/v1/predict | |
| Headers: | |
| - Content-Type: multipart/form-data | |
| Request (form-data): | |
| - file: (required) image file, field name `file` (max 10MB, allowed: .jpg, .jpeg, .png) | |
| Response 200: | |
| ```json | |
| { | |
| "success": true, | |
| "filename": "cat.jpg", | |
| "predicted_class": "cat", | |
| "confidence": 0.9821, | |
| "top_k": [ | |
| {"label":"cat","score":0.9821}, | |
| {"label":"dog","score":0.0121} | |
| ], | |
| "model": { | |
| "name": "classifier", | |
| "version": "v1.0.0" | |
| }, | |
| "inference_time_ms": 123 | |
| } | |
| ``` | |
| Errors: | |
| - 400: missing file / invalid file type | |
| - 413: payload too large | |
| - 500: model inference failure | |
| --- | |
| ### [POST] ์ด๋ฏธ์ง ์ ๋ก๋ + ๋ถ๋ฅ + ๊ฒ์๊ธ ์๋ ์์ฑ | |
| POST /api/v1/predict/upload | |
| Headers: | |
| - Content-Type: multipart/form-data | |
| Request (form-data): | |
| - title: string (required) | |
| - content: string (optional) | |
| - image: file (required) field name `image` | |
| Response 201: | |
| ```json | |
| { | |
| "success": true, | |
| "post_id": 15, | |
| "prediction": "cat", | |
| "confidence": 0.98, | |
| "model": {"name":"classifier","version":"v1.0.0"} | |
| } | |
| ``` | |
| --- | |
| ### [GET] ๋ชจ๋ธ ๋ผ๋ฒจ ๋ชฉ๋ก | |
| GET /api/v1/predict/labels | |
| Response 200: | |
| ```json | |
| { | |
| "classes": ["cat","dog","car","person"] | |
| } | |
| ``` | |
| --- | |
| ## 3. ๊ฒ์๊ธ API (routers/post.py) | |
| ### [GET] ๊ฒ์๊ธ ๋ชฉ๋ก (ํ์ด์ง/ํํฐ) | |
| GET /api/v1/posts | |
| Query params: | |
| - page: int (default 1) | |
| - size: int (default 10) | |
| - category: string (optional) | |
| Response 200: | |
| ```json | |
| { | |
| "items": [ | |
| { | |
| "id": 1, | |
| "title": "๊ณ ์์ด ๋ถ๋ฅ ์ฑ๊ณต", | |
| "prediction": "cat", | |
| "confidence": 0.98, | |
| "created_at": "2026-04-28T12:00:00Z" | |
| } | |
| ], | |
| "page": 1, | |
| "size": 10, | |
| "total": 34 | |
| } | |
| ``` | |
| ### [GET] ๊ฒ์๊ธ ์์ธ | |
| GET /api/v1/posts/{id} | |
| Response 200: | |
| ```json | |
| { | |
| "id": 1, | |
| "title": "๊ณ ์์ด ๋ถ๋ฅ ์ฑ๊ณต", | |
| "content": "ํ ์คํธ ๊ธ", | |
| "image_url": "/uploads/cat.jpg", | |
| "prediction": "cat", | |
| "confidence": 0.98, | |
| "created_at": "2026-04-28T12:00:00Z" | |
| } | |
| ``` | |
| 404: post not found | |
| ### [POST] ๊ฒ์๊ธ ์์ฑ | |
| POST /api/v1/posts | |
| Headers: | |
| - Content-Type: application/json | |
| Request body: | |
| ```json | |
| { | |
| "title":"์ ๊ฒ์๊ธ", | |
| "content":"๋ด์ฉ", | |
| "image_url":"/uploads/sample.jpg", | |
| "prediction":"cat", | |
| "confidence":0.95 | |
| } | |
| ``` | |
| Response 201: | |
| ```json | |
| {"success": true, "id": 123} | |
| ``` | |
| Validation: title required, image_url optional, confidence 0.0-1.0 | |
| ### [PUT] ๊ฒ์๊ธ ์์ | |
| PUT /api/v1/posts/{id} | |
| Request body (partial ํ์ฉ): | |
| ```json | |
| {"title":"์์ ์ ๋ชฉ","content":"์์ ๋ด์ฉ"} | |
| ``` | |
| Response 200: {"success": true} | |
| ### [DELETE] ๊ฒ์๊ธ ์ญ์ | |
| DELETE /api/v1/posts/{id} | |
| Response 200: | |
| ```json | |
| {"success": true, "message": "์ญ์ ์๋ฃ"} | |
| ``` | |
| --- | |
| ## 4. ์ข์์ / ์ถ์ฒ | |
| POST /api/v1/posts/{id}/like | |
| Response 200: | |
| ```json | |
| {"success": true, "likes": 12} | |
| ``` | |
| --- | |
| ## 5. ํต๊ณ API (๋์๋ณด๋์ฉ) | |
| GET /api/v1/stats/classes | |
| Query params (optional): | |
| - start_date, end_date (ISO 8601) | |
| Response 200: | |
| ```json | |
| {"cat":34,"dog":20,"car":14} | |
| ``` | |
| --- | |
| ## ๋ฐ์ดํฐ/์๋ต ์คํค๋ง (schemas.py) | |
| PostCreate | |
| - title: string (required) | |
| - content: string (optional) | |
| - image_url: string (optional, ๊ฒฝ๋ก) | |
| - prediction: string (optional) | |
| - confidence: float (0.0 - 1.0, optional) | |
| PostResponse | |
| - id: int | |
| - title: string | |
| - content: string | |
| - image_url: string | |
| - prediction: string | |
| - confidence: float | |
| - created_at: datetime (ISO 8601) | |
| PredictResponse | |
| - success: bool | |
| - filename: string | |
| - predicted_class: string | |
| - confidence: float | |
| - top_k: [{label: string, score: float}] | |
| - model: {name:string, version:string} | |
| - inference_time_ms: int | |
| ErrorResponse | |
| - success: false | |
| - error: {code:int, message:string, details:object|null} | |
| --- | |
| ## ๊ตฌํ/์ด์ ๊ถ์ฅ์ฌํญ | |
| - ๋ชจ๋ API๋ /api/v1/ ์ ๋์ฌ๋ฅผ ์ฌ์ฉํด ๋ฒ์ ๊ด๋ฆฌ | |
| - ์์ฒญ/์๋ต ์์๋ OpenAPI(Swagger)๋ก ์์ฑํด ์๋ ๋ฌธ์ํ ๊ถ์ฅ | |
| - ํ์ผ ์ ๋ก๋๋ ์ ์ฅ์ ์ฉ๋, ํ์ฅ์ ๊ฒ์ฌ, ์ ์ฑ ํ์ผ ๊ฒ์ฌ ๊ตฌํ | |
| - ๋ฏผ๊ฐํ ํ์ผ ์ ๋ก๋๋ ์ธ์ฆ/ACL ์ ์ฉ | |
| - ๋ชจ๋ธ ๋ฒ์ ๊ด๋ฆฌ ๋ฐ A/B ํ ์คํธ ๋ก๊ทธ ๋จ๊ธฐ๊ธฐ | |
| - ์์ธํ ๋ก๊น (์์ฒญ id, inference time, model version)์ผ๋ก ๋ฌธ์ ์ถ์ | |
| --- |