Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 88 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,99 +1,119 @@
# โœจProject Conventionโœจ
---
# ๐Ÿค– ์ž”๋ฐ˜ํ”Œ๋ŸฌํŒ… AI

<br>

## โœ‰๏ธ Commit Convention
FastAPI ๊ธฐ๋ฐ˜์˜ **AI ์ถ”์ฒœ ์„œ๋ฒ„**๋กœ, ์‹์•ฝ์ฒ˜ ์˜์–‘์„ฑ๋ถ„ํ‘œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ
**๋งž์ถคํ˜• ๋ฐ˜์ฐฌ ์ถ”์ฒœ**๊ณผ **์„ญ์ทจ ํŒ ์ œ๊ณต**์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๋Š” **Udacity ์Šคํƒ€์ผ**์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ์ž‘์„ฑ
### ๐Ÿ”น AI ๊ธฐ๋Šฅ

```
type: Subject (์ œ๋ชฉ)
* **๋ฉ”๋‰ด ์ถ”์ฒœ**

body (๋ณธ๋ฌธ) (๊ธด ์„ค๋ช…์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ์ž‘์„ฑ)
* 5๊ฐ€์ง€ ์ฝ˜์…‰ํŠธ ๊ธฐ๋ฐ˜:
`diet(๋‹ค์ด์–ดํŠธ)`, `keto(์ €ํƒ„๊ณ ์ง€)`, `low_sodium(์ €์—ผ)`, `glycemic(ํ˜ˆ๋‹น)`, `bulking(๋ฒŒํฌ์—…)`
* ์ž…๋ ฅ ๋ฉ”๋‰ด๋ช… -> ์œ ์‚ฌ๋„ ๋งค์นญ -> ์˜์–‘ ์„ฑ๋ถ„ ํ”ผ์ฒ˜ํ™” -> ์ฝ˜์…‰ํŠธ๋ณ„ ์ ์ˆ˜ํ™”(0\~100)

footer (๊ผฌ๋ฆฌ๋ง) (issue tracker ID๋ฅผ ๋ช…์‹œํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ์— ์ž‘์„ฑ)
```
<br>
* **Tip ์ƒ์„ฑ**

* OpenAI API ์—ฐ๋™์„ ํ†ตํ•œ **์‹์Šต๊ด€ ๊ฐ€์ด๋“œ / ๋ ˆ์‹œํ”ผ ์ œ์•ˆ**

---

## ๐Ÿš€ Tech Stack
<img width="1045" height="844" alt="struct-be" src="https://github.com/user-attachments/assets/a10dd991-3e69-46dc-8eb0-152d27e3c1e4" />

### ๐Ÿ›  **type**: ์ปค๋ฐ‹์˜ ์œ ํ˜•
### ๐Ÿ”น Framework & Language
- **Python 3.11**
- **FastAPI : ๊ฒฝ๋Ÿ‰ ์›น ํ”„๋ ˆ์ž„์›Œํฌ**
- **Uvicorn : ASGI ์„œ๋ฒ„**

| ํƒ€์ž… | ์„ค๋ช… |
|------------|------------------------------------------------|
| `feat` | โœจ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ์ถ”๊ฐ€ |
| `fix` | ๐Ÿ› ๋ฒ„๊ทธ ์ˆ˜์ • |
| `docs` | ๐Ÿ“ ๋ฌธ์„œ ์ˆ˜์ • (README, ์ฃผ์„ ๋“ฑ) |
| `style` | ๐Ÿ’„ ์ฝ”๋“œ ํฌ๋งทํŒ…, ์„ธ๋ฏธ์ฝœ๋ก  ๋ˆ„๋ฝ ๋“ฑ ๊ธฐ๋Šฅ ์˜ํ–ฅ ์—†๋Š” ๋ณ€๊ฒฝ |
| `refactor` | โ™ป๏ธ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง (๊ธฐ๋Šฅ ๋ณ€ํ™” ์—†์Œ) |
| `test` | โœ… ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ถ”๊ฐ€ ๋˜๋Š” ์ˆ˜์ • |
| `chore` | ๐Ÿ”ง ๋นŒ๋“œ ์„ค์ •, ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ € ์„ค์ • ๋“ฑ ๊ธฐํƒ€ ์ž‘์—… |
| `perf` | โšก ์„ฑ๋Šฅ ๊ฐœ์„  |
| `ci` | ๐Ÿ”„ CI ๊ด€๋ จ ์„ค์ • ๋ฐ ์Šคํฌ๋ฆฝํŠธ ์ˆ˜์ • |
| `revert` | โš™๏ธ ์ด์ „ ์ปค๋ฐ‹ ๋˜๋Œ๋ฆฌ๊ธฐ |
<img src="https://img.shields.io/badge/Python%203.11-3776AB?style=flat-square&logo=python&logoColor=white"/> <img src="https://img.shields.io/badge/FastAPI-009688?style=flat-square&logo=fastapi&logoColor=white"/> <img src="https://img.shields.io/badge/Uvicorn-499848?style=flat-square&logo=python&logoColor=white"/>

<br>

### ๐Ÿ–Š๏ธ **Subject**: ์ œ๋ชฉ

- 50์ž ์ด๋‚ด๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑ
- ๋งˆ์นจํ‘œ(`.`) ๊ธˆ์ง€
- ๊ณผ๊ฑฐ ์‹œ์ œ X, ๋ช…๋ น์–ด ์‚ฌ์šฉ
### ๐Ÿ”น Data / ML
- **scikit-learn : ๋ฒกํ„ฐํ™”, ์ฐจ์› ์ถ•์†Œ, ์Šค์ผ€์ผ๋ง, ๊ฒฐ์ธก์น˜ ๋ณด์ •**
- **hnswlib : ๊ทผ์ ‘ ํƒ์ƒ‰ (๋ฉ”๋‰ด๋ช… ์œ ์‚ฌ๋„ ๋งค์นญ)**
- **numpy / joblib : ์ˆ˜์น˜ ์—ฐ์‚ฐ ๋ฐ ๋ชจ๋ธ ์ง๋ ฌํ™”**
-**์‹์•ฝ์ฒ˜ ์˜์–‘์„ฑ๋ถ„ํ‘œ ๋ฐ์ดํ„ฐ (Excel/CSV) : ์˜์–‘ ์ •๋ณด ๊ธฐ๋ฐ˜ ํ•™์Šต/์ถ”์ฒœ**

<img src="https://img.shields.io/badge/scikit--learn-F7931E?style=flat-square&logo=scikitlearn&logoColor=white"/> <img src="https://img.shields.io/badge/hnswlib-333333?style=flat-square&logo=python&logoColor=white"/> <img src="https://img.shields.io/badge/numpy-013243?style=flat-square&logo=numpy&logoColor=white"/> <img src="https://img.shields.io/badge/joblib-333333?style=flat-square&logo=python&logoColor=white"/> <img src="https://img.shields.io/badge/%EC%8B%9D%EC%95%BD%EC%B2%98%20%EC%98%81%EC%96%91%EC%84%B1%EB%B6%84%ED%91%9C-0052CC?style=flat-square&logo=google-spreadsheet&logoColor=white"/>

<br>

### ๐Ÿ“ **Body**: ๋ณธ๋ฌธ
---

- **์„ ํƒ ์‚ฌํ•ญ**
- ์ œ๋ชฉ์—์„œ ์„ค๋ช…ํ•  ์ˆ˜ ์—†๋Š” ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ œ๊ณต
- "๋ฌด์—‡์„"๊ณผ "์™œ"๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์ƒ์„ธํžˆ ๊ธฐ์ˆ 
- ํ•œ ์ค„๋‹น 72์ž ์ด๋‚ด๋กœ ์ž‘์„ฑ
- ํ•„์š”์‹œ Markdown ์‚ฌ์šฉ ๊ฐ€๋Šฅ
## ๐Ÿ“‚ Project Structure

```text
๐Ÿ“ฆ menu-ai
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ main.py # FastAPI ์‹คํ–‰ ์—”ํŠธ๋ฆฌํฌ์ธํŠธ
โ”œโ”€โ”€ requirements.txt
โ”œโ”€โ”€ leftovers
โ”‚ โ”œโ”€โ”€ core # ์„ค์ •, ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ, ๊ณตํ†ต ์‘๋‹ต, ์™ธ๋ถ€ ํด๋ผ์ด์–ธํŠธ
โ”‚ โ””โ”€โ”€ domain
โ”‚ โ”œโ”€โ”€ recommend # ๋ฉ”๋‰ด ์ถ”์ฒœ ๋„๋ฉ”์ธ
โ”‚ โ”‚ โ”œโ”€โ”€ api/ # ์ถ”์ฒœ API
โ”‚ โ”‚ โ”œโ”€โ”€ data/ # ์›๋ณธ ์˜์–‘ ๋ฐ์ดํ„ฐ (์‹์•ฝ์ฒ˜ ์—‘์…€)
โ”‚ โ”‚ โ”œโ”€โ”€ model_store # ํ•™์Šต๋œ ๋ชจ๋ธ ๋ฐ ์ „์ฒ˜๋ฆฌ ์•„ํ‹ฐํŒฉํŠธ
โ”‚ โ”‚ โ”œโ”€โ”€ schemas/ # ์š”์ฒญ/์‘๋‹ต ์Šคํ‚ค๋งˆ
โ”‚ โ”‚ โ””โ”€โ”€ service/ # ์ถ”์ฒœ ๋กœ์ง (๋งค์นญ, ์Šค์ฝ”์–ด๋ง, ์ „์ฒ˜๋ฆฌ, ํ•™์Šต)
โ”‚ โ””โ”€โ”€ tip # ํŒ/๋ ˆ์‹œํ”ผ ๋„๋ฉ”์ธ
โ”‚ โ”œโ”€โ”€ api/ # Tip API
โ”‚ โ”œโ”€โ”€ schemas/ # ์š”์ฒญ/์‘๋‹ต ์Šคํ‚ค๋งˆ
โ”‚ โ””โ”€โ”€ service/ # ํ”„๋กฌํ”„ํŠธ/LLM ํ˜ธ์ถœ
```

---
<br>

## ๐Ÿ”ฌ ๋ฐ์ดํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ & ์•Œ๊ณ ๋ฆฌ์ฆ˜

## ๐ŸŒฟ Git Flow ๋ธŒ๋žœ์น˜ ์ „๋žต (with `main`) ๐ŸŒฟ
1. **๋ฐ์ดํ„ฐ ๋กœ๋”ฉ**

* ์‹์•ฝ์ฒ˜ ์˜์–‘ ๋ฐ์ดํ„ฐ(`.xlsx`) ๋กœ๋“œ -> ๊ฒฐ์ธก์น˜ ๋ณด์ •(Imputer) -> ์ •๊ทœํ™”(Scaler)

### ๐ŸŒด ๊ธฐ๋ณธ ๋ธŒ๋žœ์น˜
| ๋ธŒ๋žœ์น˜ | ์—ญํ•  |
|--------|------|
| `main` | ์ตœ์ข… ๋ฐฐํฌ์šฉ ๋ธŒ๋žœ์น˜ (stable) |
| `develop` | ๋‹ค์Œ ๋ฐฐํฌ๋ฅผ ์œ„ํ•œ ํ†ตํ•ฉ ๊ฐœ๋ฐœ ๋ธŒ๋žœ์น˜ |
2. **๋ฉ”๋‰ด๋ช… ๋งค์นญ**

<br>
* TF-IDF ๋ฒกํ„ฐํ™” -> TruncatedSVD ์ฐจ์› ์ถ•์†Œ -> hnswlib ๊ทผ์ ‘ ํƒ์ƒ‰์œผ๋กœ ์œ ์‚ฌ ๋ฉ”๋‰ด ๊ฒ€์ƒ‰

### ๐ŸŒฑ **์ž‘์—… ๋ธŒ๋žœ์น˜ ๋„ค์ด๋ฐ ๊ทœ์น™**
3. **์˜์–‘ ํ”ผ์ฒ˜ํ™”**

```
type/#issue๋ฒˆํ˜ธ (์ž‘์—… ๋‹จ์œ„๋Š” ๊ธฐ๋Šฅ/์ˆ˜์ •/๋ฆฌํŒฉํ† ๋ง ๋“ฑ์œผ๋กœ ๊ตฌ๋ถ„)
```
* `kcal, protein, fat, carbs, sugar, sodium` ๋“ฑ ์ฃผ์š” ์˜์–‘์†Œ๋ฅผ ๋ฒกํ„ฐํ™”

4. **์Šค์ฝ”์–ด๋ง (Concept Scoring)**

| prefix | ์„ค๋ช… | ์˜ˆ์‹œ |
|--------------|------------------------------|-----------------------------------|
| `feature/` | โœจ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ | `feature/#15` |
| `fix/` | ๐Ÿ› ๋ฒ„๊ทธ ์ˆ˜์ • | `fix/#42` |
| `refactor/` | โ™ป๏ธ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง | `refactor/#23` |
| `chore/` | ๐Ÿ”ง ์„ค์ • ๋ณ€๊ฒฝ, ์žก์ผ | `chore/#25` |
| `perf/` | โšก ์„ฑ๋Šฅ ๊ฐœ์„  | `perf/#94` |
| `hotfix/` | ๐Ÿš‘ ๊ธ‰ํ•œ ์ˆ˜์ • (main์—์„œ ๋ฐ”๋กœ ๋ถ„๊ธฐ) | `hotfix/#102` |
| `test/` | ๐Ÿงช ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ถ”๊ฐ€/์ˆ˜์ • | `test/#55` |
* ๋‹ค์ด์–ดํŠธ: ์—ด๋Ÿ‰ยท๋‹น๋ฅ˜ยทํƒ„์ˆ˜ํ™”๋ฌผ ์ œํ•œ
* ์ €์—ผ: ๋‚˜ํŠธ๋ฅจ ์—„๊ฒฉ ์ œํ•œ
* ํ˜ˆ๋‹น: ๋‹น๋ฅ˜ยทํƒ„์ˆ˜ํ™”๋ฌผ ๋™์‹œ ์ œํ•œ
* ์ €ํƒ„๊ณ ์ง€/๋ฒŒํฌ์—…: ๊ธฐ์กด ๋น„์œจ ์œ ์ง€

<br>
5. **์ถ”์ฒœ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜**

### ๐Ÿš€ ๋ธŒ๋žœ์น˜ ํ๋ฆ„ ์š”์•ฝ
* ์ ์ˆ˜(0\~100) ๊ธฐ๋ฐ˜ ๋žญํ‚น -> ์ƒ์œ„ N๊ฐœ ๋ฐ˜ํ™˜
* ์‘๋‹ต ๊ตฌ์กฐ: `isSuccess`, `httpStatus`, `data`, `timeStamp`

```text
1. main โ† ๋ฐฐํฌ
2. develop โ† ํ†ตํ•ฉ ๊ฐœ๋ฐœ (PR ๋Œ€์ƒ)
3. develop์—์„œ feature/fix/... ๋ธŒ๋žœ์น˜ ๋ถ„๊ธฐ
4. ๊ธฐ๋Šฅ ์™„๋ฃŒ ํ›„ develop์œผ๋กœ PR & ๋จธ์ง€
5. ๋ฐฐํฌ ์‹œ develop โ†’ main ๋จธ์ง€
6. ๊ธ‰ํ•œ ์ˆ˜์ •์€ hotfix์—์„œ main โ†’ develop ๋ณ‘ํ•ฉ
---

## โš™๏ธ ์‹คํ–‰ ๋ฐฉ๋ฒ•

### 1. ์˜์กด์„ฑ ์„ค์น˜

```bash
python3.11 -m venv .venv
source .venv/bin/activate
pip install --no-cache-dir -r requirements.txt
```

---
### 2. ํ•™์Šต (๋ชจ๋ธ ์ƒ์„ฑ)

์ตœ์ดˆ ์‹คํ–‰ ์‹œ, `model_store/`๊ฐ€ ๋น„์–ด ์žˆ๋‹ค๋ฉด ํ•™์Šต ๊ณผ์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

```bash
python -m leftovers.domain.recommend.service.train
```

โ†’ `nutrition_imputer.joblib`, `nutrition_scaler.joblib`, `concept_model_*.joblib` ๋“ฑ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

### 3. ์„œ๋ฒ„ ์‹คํ–‰

```bash
uvicorn main:app --host 0.0.0.0 --port 8000
```