์ผ์ ์ ์ดํดํ๊ณ ๋งฅ๋ฝ์ ์ฐ๊ฒฐํด ํ์ํ ์ค๋นยท์คํ ํญ๋ชฉ์ ์ถ์ฒํ๋ FastAPI ๊ธฐ๋ฐ ๋ถ์ ์๋ฒ
tryna brain์ tryna ์๋น์ค์ ์ผ์ ํ์ฑ ๋ฐ ์ถ์ฒ ์ ์ฉ ์๋ฒ์ ๋๋ค. Spring ์๋ฒ์ ์ญํ ์ ๋ถ๋ฆฌํ์ฌ ์์ฐ์ด ์ผ์ ํ์ฑ, Neo4j ๊ธฐ๋ฐ ์๋ฏธ ๋งคํ๊ณผ ํ๋ณด ์กฐํ, Upstage ๊ธฐ๋ฐ ์๋ฒ ๋ฉ ๋ฐ ์ถ์ฒ ๋ฌธ๊ตฌ ์ ์ ๋ฅผ ๋ด๋นํฉ๋๋ค.
tryna๋ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ์งง์ ์ผ์ ์ ๋งฅ๋ฝ์ ์ดํดํ๊ณ , ์ผ์ ์ ํ์ ํ์ํ ํ ์ผ์ ์ ์ํ๋ ์ผ์ ์๋น์ค์ ๋๋ค.
tryna brain์ ๋ค์ ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- ์์ฐ์ด ์ผ์ ์์ ๋ ์ง, ์๊ฐ, ์ฅ์ ๋ฑ ์ผ์ ํ๋ณด ์ ๋ณด ์ถ์ถ
- ์ผ์ ์ ํยท๋งฅ๋ฝยท์ฅ์๋ฅผ ๋ถ์ํ์ฌ ์ค๋น ๋ฐ ์คํ ํญ๋ชฉ ์ถ์ฒ
์๋ฅผ ๋ค์ด ์ฌ์ฉ์๊ฐ ๋ค์๊ณผ ๊ฐ์ด ์ ๋ ฅํ๋ฉด:
๊ธ์์ผ 3์ ํํ ํ์
ํ์ฑ API๋ ๋ค์๊ณผ ๊ฐ์ด ์ผ์ ํ๋ณด ์ ๋ณด๋ฅผ ๋ฐํํฉ๋๋ค.
{
"tempEventId": "tmp_f7258568-0374-4710-8473-329576255448",
"eventTitle": "๊ธ์์ผ 3์ ํํ ํ์",
"draftRevision": 1,
"startDate": "2026-08-14",
"dateSource": "RELATIVE_EXPRESSION",
"startTime": "15:00:00",
"placeCandidate": null,
"toEmbedding": ["ํํ", "ํ์"],
"isAllDayCandidate": false,
"needsConfirmation": false,
"warnings": []
}์ดํ ์ถ์ฒ API๋ Neo4j ๊ด๊ณยท๋ฒกํฐ ํ๋ณด์ Upstage LLM์ ํ์ฉํ์ฌ ํ์ ์๊ฐ ํ์ธ, ์๊ธฐํ ๋ด์ฉ ์ ๋ฆฌ์ ๊ฐ์ ์ค๋นยท์คํ ํญ๋ชฉ์ ์ต๋ 3๊ฐ๊น์ง ์ ์ํฉ๋๋ค.
tryna ๋ฐฑ์๋๋ ์ญํ ์ ๋ฐ๋ผ Spring ์๋ฒ์ FastAPI brain ์๋ฒ๋ก ๋ถ๋ฆฌํฉ๋๋ค.
Spring ์๋ฒ๋ ์๋น์ค ์ด์์ ํ์ํ ํต์ฌ ๋ฐฑ์๋ ๊ธฐ๋ฅ์ ๋ด๋นํฉ๋๋ค.
- ํ์/๋นํ์ ์ธ์ฆ ๋ฐ ์ฌ์ฉ์ ๊ณ์ ๊ด๋ฆฌ
- ์ผ์ CRUD ๋ฐ ์บ๋ฆฐ๋ ์กฐํ
- ์ถ์ฒ ์์ฒญ ์ค ์ต์
draftRevision๋ฑ๋ก - ์ถ์ฒ ๊ฒฐ๊ณผ ์ ์ฅ
- ์๋ฆผ ๋ฐ ์ธ๋ถ ์บ๋ฆฐ๋ ์ฐ๋
- DB ํธ๋์ญ์ ๋ฐ ๊ถํ ๊ฒ์ฆ
FastAPI brain ์๋ฒ๋ ์ผ์ ๋ฌธ์ฅ์ ์ดํดํ๊ณ ์ถ์ฒ ํ๋ณด๋ฅผ ์์ฑยท์ ์ ํ๋ ๋ถ์ ์์ง ์ญํ ์ ๋ด๋นํฉ๋๋ค.
- Rule Based Parser์ Kiwi ๊ธฐ๋ฐ ์์ฐ์ด ์ผ์ ํ์ฑ
- Upstage ์๋ฒ ๋ฉ ๊ธฐ๋ฐ ์ผ์ ์ ํยท๋งฅ๋ฝยท์ฅ์ ์๋ฏธ ๋งคํ
- Neo4j ๊ด๊ณ ๋ฐ ๋ฒกํฐ ๊ธฐ๋ฐ ์ถ์ฒ ํ๋ณด ์กฐํ
- Upstage LLM ๊ธฐ๋ฐ ์ถ์ฒ ํญ๋ชฉ ์ ํ ๋ฐ
displayText์ ์ - ์๊ฐ ๋งฅ๋ฝ ๊ฒ์ฆ๊ณผ
TIMED_ACTIONยทUNTIMED_PREP๋ถ๋ฅ - Redis ๊ธฐ๋ฐ ์ต์
draftRevision๊ฒ์ฆ - Spring ์๋ฒ์ ํ์ฑ ๋ฐ ์ถ์ฒ ๊ฒฐ๊ณผ ๋ฐํ
| Type | Tool |
|---|---|
| Language | |
| Framework | |
| ASGI Server | |
| Database | |
| Cache | |
| LLM | |
| NLP | |
| Configuration | |
| Package Manager | |
| Version Control | |
| Collaboration |
Client
โ
โผ
Spring Server
โ
โ ๋ด๋ถ API ์ธ์ฆ ๋ฐ ์ผ์ ํ์ฑ/์ถ์ฒ ์์ฒญ
โผ
FastAPI Brain Server
โ
โโโ Rule Based Parser + Kiwi
โ ๋ ์ง, ์๊ฐ, ์ฅ์ ๋ฑ ์ผ์ ํ๋ณด ์ถ์ถ
โ
โโโ Upstage Embedding + Neo4j
โ ์๋ฏธ ๋งคํ ๋ฐ ๊ด๊ณยท๋ฒกํฐ ์ถ์ฒ ํ๋ณด ์กฐํ
โ
โโโ Upstage LLM
โ ์ถ์ฒ ํญ๋ชฉ ์ ํ ๋ฐ displayText ์ ์
โ
โโโ Redis/Valkey
์ต์ draftRevision ๊ฒ์ฆ
โ
โผ
Spring Server
โ
โ ์ถ์ฒ ๊ฒฐ๊ณผ ์ ์ฅ/์๋ต
โผ
Client
| Step | Component | Responsibility |
|---|---|---|
| D101 | Schedule Context + Upstage Embedding | ์ผ์ ์ ๋ณด๋ฅผ ์๋ฒ ๋ฉ ์ ๋ ฅ์ผ๋ก ๊ตฌ์ฑํ๊ณ ์ฟผ๋ฆฌ ๋ฒกํฐ ์์ฑ |
| D102 | Neo4j | EventType, Context, PlaceType ์๋ฏธ ๋งคํ ๋ฐ ๊ด๊ณยท๋ฒกํฐ ์ถ์ฒ ํ๋ณด ๊ฒฐํฉ |
| D103 | Upstage LLM | ํ๋ณด ์ค ์ต๋ 3๊ฐ๋ฅผ ์ ํํ๊ณ ์์ฐ์ค๋ฌ์ด displayText๋ก ์ ์ |
| D104 | Temporal Validator | ๋ ์ง ๋งฅ๋ฝ ๊ฒ์ฆ ๋ฐ TIMED_ACTIONยทUNTIMED_PREP ํ์ |
| D105 | Suggestion Composer | ์์์ ๋ถ๋ชจ ์์ ์ผ์ ID๋ฅผ ๊ฒ์ฆํ๊ณ ์ต์ข ์๋ต ๊ตฌ์ฑ |
Spring ์๋ฒ๋ tempEventId๋ณ ์ต์ draftRevision์ Redis์ ๋ฑ๋กํฉ๋๋ค. FastAPI๋ D101~D105 ๋จ๊ณ ์ฌ์ด์์ recommendation:latest-revision:{tempEventId}๋ฅผ ์กฐํํ๊ณ , ์ค๋๋ ์์ฒญ์ด๋ฉด 409 STALE_DRAFT_REVISION_409๋ก ํ์ ์ฒ๋ฆฌ๋ฅผ ์ค๋จํฉ๋๋ค. Redis๋ฅผ ์ฌ์ฉํ ์ ์์ ๋์๋ ์ถ์ฒ ํ์ดํ๋ผ์ธ์ ๊ณ์ ์คํํ๋ fail-open ์ ์ฑ
์ ์ ์ฉํฉ๋๋ค.
Upstage์๋ ๋ถ์๊ณผ ์ถ์ฒ ์ ์ ์ ํ์ํ ์ผ์ ์ ๋ณด ๋ฐ Neo4j ํ๋ณด๋ง ์ ๋ฌํฉ๋๋ค. ๊ฐ์ธ์ ๋ณด๋ ๋ถํ์ํ ๋ฏผ๊ฐ ์ ๋ณด๋ ์ ๋ฌํ์ง ์๋ ๊ฒ์ ์์น์ผ๋ก ํฉ๋๋ค.
brain/
โโ app/
โ โโ main.py
โ โโ api/
โ โ โโ v1/
โ โ โโ router.py
โ โ โโ routes/
โ โ โโ event_previews.py
โ โ โโ health.py
โ โ โโ recommendations.py
โ โโ core/
โ โ โโ config.py
โ โ โโ deps.py
โ โ โโ error_code.py
โ โ โโ handlers.py
โ โ โโ internal_auth.py
โ โ โโ responses.py
โ โ โโ valkey_client.py
โ โโ graph/
โ โ โโ neo4j_client.py
โ โ โโ models/
โ โ โโ repositories/
โ โโ schemas/
โ โ โโ recommendation/
โ โ โโ event_preview.py
โ โ โโ health.py
โ โโ services/
โ โโ event_preview_service.py
โ โโ parser_service.py
โ โโ recommendation/
โ โโ schedule_context_service.py
โ โโ candidate_search_service.py
โ โโ refinement_service.py
โ โโ temporal_validation_service.py
โ โโ suggestion_compose_service.py
โ โโ revision_guard_service.py
โโ tests/
โโ nginx/
โโ Dockerfile
โโ requirements.txt
โโ .env.example
โโ README.md
| Package | Responsibility |
|---|---|
app.main |
FastAPI ์ฑ ์ง์ ์ ๊ณผ Neo4jยทRedis ์๋ช ์ฃผ๊ธฐ ๊ด๋ฆฌ |
app.core |
ํ๊ฒฝ๋ณ์, ์์กด์ฑ, ๋ด๋ถ ์ธ์ฆ, ๊ณตํต ์๋ตยท์์ธ ๋ฐ Redis ์ฐ๊ฒฐ ๊ด๋ฆฌ |
app.api |
ํฌ์ค์ฒดํฌ, ์ผ์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ, ์ถ์ฒ API ์๋ํฌ์ธํธ ์ ์ |
app.graph |
Neo4j ์ฐ๊ฒฐ๊ณผ ์ผ์ ์๋ฏธ ๋งคํยท์ถ์ฒ ํ๋ณด ์กฐํ |
app.schemas |
ํ์ฑยท์ถ์ฒ ํ์ดํ๋ผ์ธ์ ์์ฒญ/์๋ต ๋ชจ๋ธ ์ ์ |
app.services |
์์ฐ์ด ํ์ฑ ๋ฐ D101~D105 ์ถ์ฒ ๋น์ฆ๋์ค ๋ก์ง ์ํ |
Python 3.13 ํ๊ฒฝ์ ๊ถ์ฅํฉ๋๋ค.
python3.13 -m venv .venv.venv/bin/python -m pip install -r requirements.txtWindows PowerShell์์๋ .venv/bin/python ๋์ .\.venv\Scripts\python.exe๋ฅผ ์ฌ์ฉํฉ๋๋ค.
cp .env.example .env๋ก์ปฌ Neo4j, Redis/Valkey ๋ฐ Upstage API ์ ๋ณด๋ฅผ .env์ ์ค์ ํฉ๋๋ค. VALKEY_HOST๋ฅผ ๋น์๋๋ฉด Redis ๊ธฐ๋ฐ ๊ธฐ๋ฅ์ ๋นํ์ฑํ๋๋ฉฐ ์๋ฒ๋ ๊ณ์ ์คํ๋ฉ๋๋ค.
.venv/bin/python -m uvicorn app.main:app --reload --host 127.0.0.1 --port 8000ํ ์คํธ๋ ๋ค์ ๋ช ๋ น์ด๋ก ์คํํฉ๋๋ค.
PYTHONPATH=. .venv/bin/python -m pytestFastAPI brain ์๋ฒ๋ FastAPI ๊ธฐ๋ณธ Swagger UI๋ฅผ ์ฌ์ฉํฉ๋๋ค.
http://127.0.0.1:8000/docs
๋น์ฆ๋์ค API๋ X-Internal-Api-Key ํค๋๋ก Spring ์๋ฒ์์ ๋ด๋ถ ํต์ ์ ์ธ์ฆํฉ๋๋ค. ํฌ์ค์ฒดํฌ๋ ์ธ์ฆ ๋์์์ ์ ์ธ๋ฉ๋๋ค.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/health |
Neo4j ๋ฐ Redis ์ฐ๊ฒฐ ์ํ ํ์ธ |
POST |
/api/v1/event-previews |
์์ฐ์ด ์ผ์ ํ์ฑ ๋ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์์ฑ |
POST |
/api/v1/recommendations |
D101~D105 ์ถ์ฒ ํ์ดํ๋ผ์ธ ์คํ |
์ถ์ฒ API์ stop_after_step ์ฟผ๋ฆฌ๋ ๊ฐ๋ฐ ํ๊ฒฝ์์ ์ค๊ฐ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ๋๋ง ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ์ด์ ํ๊ฒฝ์์๋ 403์ ๋ฐํํฉ๋๋ค.
ํด๋ผ์ด์ธํธ๋ brain API๋ฅผ ์ง์ ํธ์ถํ์ง ์์ต๋๋ค. Spring ์๋ฒ๊ฐ ์ฌ์ฉ์ ์ธ์ฆ๊ณผ ์์ฒญ ๊ฒ์ฆ์ ์ํํ ๋ค X-Internal-Api-Key๋ฅผ ํฌํจํด brain API๋ฅผ ํธ์ถํฉ๋๋ค.
์๋ก์ด ์ผ์ ์์ฑ์ ์์ํ ๋ tempEventId๋ JSON null๋ก ์ ๋ฌํ๊ฑฐ๋ ํ๋๋ฅผ ์๋ตํฉ๋๋ค. ๋ฌธ์์ด "null"์ ์ ๋ฌํ๋ฉด ์ค์ ์์ ์ผ์ ID๋ก ์ทจ๊ธ๋๋ฏ๋ก ์ฌ์ฉํ์ง ์์ต๋๋ค.
{
"tempEventId": null,
"eventTitle": "๋ค์์ฃผ ๊ธ์์ผ 3์๋ถํฐ 4์๊น์ง ํ์",
"draftRevision": 0,
"selectedDate": "2026-08-13"
}brain์ ์ต์ด ์์ฒญ์ ์๋ก์ด tempEventId๋ฅผ ์์ฑํ๊ณ ์์ฒญ์ draftRevision์ ๊ทธ๋๋ก ๋ฐํํฉ๋๋ค.
{
"tempEventId": "tmp_f7258568-0374-4710-8473-329576255448",
"eventTitle": "๋ค์์ฃผ ๊ธ์์ผ 3์๋ถํฐ 4์๊น์ง ํ์",
"draftRevision": 0,
"startDate": "2026-08-21",
"dateSource": "RELATIVE_EXPRESSION",
"endDate": null,
"startTime": "15:00:00",
"endTime": "16:00:00",
"placeCandidate": null,
"toEmbedding": ["ํ์"],
"isAllDayCandidate": false,
"needsConfirmation": false,
"warnings": []
}๊ฐ์ ์ผ์ ์ ์์ฑํ๋ ๋์์๋ ์ด์ ์๋ต์ tempEventId๋ฅผ ๊ทธ๋๋ก ์ ๋ฌํ๊ณ , ํธ์ถํ๋ ์ชฝ์์ draftRevision์ ์ฆ๊ฐ์ํต๋๋ค. brain์ draftRevision์ ์๋์ผ๋ก ์ฆ๊ฐ์ํค์ง ์์ต๋๋ค.
{
"tempEventId": "tmp_f7258568-0374-4710-8473-329576255448",
"eventTitle": "๋ค์์ฃผ ๊ธ์์ผ 4์๋ถํฐ 5์๊น์ง ํ์",
"draftRevision": 1,
"selectedDate": "2026-08-13"
}- ๋์ผํ ์ผ์ ์์ฑ ๊ณผ์ ์์๋ ๊ฐ์
tempEventId๋ฅผ ์ ์งํฉ๋๋ค. - ์ผ์ ์ ์ฅ, ์์ฑ ์ทจ์ ๋๋ ์๋ก์ด ์ผ์ ์์ฑ์ ์์ํ๋ฉด ํธ์ถํ๋ ์ชฝ์์ ๊ธฐ์กด
tempEventId๋ฅผ ์ด๊ธฐํํฉ๋๋ค. - brain์ ์์ ์ผ์ ์ ์ ์ฅยท์ทจ์ ์ํ๋ฅผ ๋ณด๊ดํ์ง ์์ต๋๋ค.
- ์ถ์ฒ ํ์ดํ๋ผ์ธ์
tempEventId๋ณ ์ต์draftRevision์ ๊ธฐ์ค์ผ๋ก ์ค๋๋ ์์ฒญ์ ํ์ ๋จ๊ณ๋ฅผ ์ค๋จํฉ๋๋ค.
์ผ์ ์์ ๋ ์ง๋ ๋ค์ ์์๋ก ๊ฒฐ์ ํฉ๋๋ค.
- ์ผ์ ์๋ฌธ์์ ํ์ฑํ ๋ ์ง
- ์์ฒญ์ผ๋ก ์ ๋ฌ๋
selectedDate - Asia/Seoul ๊ธฐ์ค ์ค๋
dateSource๋ ๋ ์ง๊ฐ ๊ฒฐ์ ๋ ์ถ์ฒ๋ฅผ ๋ํ๋
๋๋ค.
| Value | Description |
|---|---|
EXPLICIT |
์ฌ์ฉ์๊ฐ ์ ๋ ๋ ์ง๋ฅผ ์ง์ ์ ๋ ฅ |
RELATIVE_EXPRESSION |
๋ด์ผ, ๋ค์ ์ฃผ ๊ธ์์ผ ๋ฑ์ ์๋ ๋ ์ง ํํ์ ํ์ฑ |
SELECTED_DATE |
์๋ฌธ์ ๋ ์ง๊ฐ ์์ด ์์ฒญ์ selectedDate ์ฌ์ฉ |
DEFAULT_TODAY |
์๋ฌธ๊ณผ ์์ฒญ์ ๋ ์ง๊ฐ ์์ด Asia/Seoul ๊ธฐ์ค ์ค๋ ์ฌ์ฉ |
์ผ์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์๋ต๊ณผ ์ถ์ฒ ์์ฒญ์ ํ๋ ์ด๋ฆ์ด ์ผ๋ถ ๋ค๋ฅด๋ฏ๋ก Spring ์๋ฒ์์ ๋ค์๊ณผ ๊ฐ์ด ๋ณํํฉ๋๋ค.
| Event Preview Response | Recommendation Request |
|---|---|
startDate |
startDateCandidate |
startTime |
startTimeCandidate |
endDate |
endDateCandidate |
endTime |
endTimeCandidate |
dateSource |
startDateSource |
toEmbedding |
embeddingWords |
์ถ์ฒ ์์ฒญ์๋ ์ผ์ ์
๋ ฅ ์ถ์ฒ๋ฅผ ๋ํ๋ด๋ sourceType๋ ํฌํจํด์ผ ํฉ๋๋ค.
{
"tempEventId": "tmp_f7258568-0374-4710-8473-329576255448",
"draftRevision": 1,
"eventTitle": "๋ค์์ฃผ ๊ธ์์ผ 4์๋ถํฐ 5์๊น์ง ํ์",
"sourceType": "USER_NATURAL_LANGUAGE",
"startDateCandidate": "2026-08-21",
"startTimeCandidate": "16:00:00",
"endDateCandidate": null,
"endTimeCandidate": "17:00:00",
"startDateSource": "RELATIVE_EXPRESSION",
"placeCandidate": null,
"description": null,
"embeddingWords": ["ํ์"]
}sourceType |
Description |
|---|---|
USER_NATURAL_LANGUAGE |
์ฌ์ฉ์๊ฐ ์์ฐ์ด๋ก ์ ๋ ฅํ ์ผ์ |
USER_MANUAL_EDIT |
์ฌ์ฉ์๊ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ ๋ณด๋ฅผ ์ง์ ์์ ํ ์ผ์ |
GET /api/v1/healthResponse:
{
"status": "UP",
"timestamp": "2026-08-13T09:00:00Z",
"components": {
"neo4j": {
"status": "UP",
"detail": null
},
"redis": {
"status": "UP",
"detail": null
}
}
}Redis/Valkey๊ฐ ์ค์ ๋์ง ์์ ๋ก์ปฌ ํ๊ฒฝ์์๋ components.redis.status๊ฐ DISABLED๋ก ํ์๋ฉ๋๋ค. ํ์ฌ ์ ์ฒด ์ํ์ HTTP ์ํ ์ฝ๋๋ Neo4j ์ฐ๊ฒฐ ์ํ๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฒฐ์ ํฉ๋๋ค.
๋น์ฆ๋์ค ์์ธ์ ์์ฒญ๊ฐ ๊ฒ์ฆ ์ค๋ฅ๋ ๊ณตํต ์๋ต ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํฉ๋๋ค.
Error:
{
"success": false,
"code": "COMMON_400",
"message": "์๋ชป๋ ์์ฒญ์
๋๋ค.",
"data": null
}์ผ์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ, ์ถ์ฒ ์ฑ๊ณต ์๋ต ๋ฐ ํฌ์ค์ฒดํฌ ์๋ต์ ๊ฐ API์ ์๋ต ์คํค๋ง๋ฅผ ์ง์ ๋ฐํํฉ๋๋ค. ๋ฐ๋ผ์ ๋ชจ๋ ์ฑ๊ณต ์๋ต์ด success, code, message, data ํ์์ผ๋ก ๊ฐ์ธ์ง์ง๋ ์์ต๋๋ค.
๊ณตํต ์์ธ ์ฒ๋ฆฌ๋ app/core์์ ๊ด๋ฆฌํฉ๋๋ค.
ํ์ฌ ์ฃผ์ ์๋ฌ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
| Code | HTTP Status | Description |
|---|---|---|
COMMON_400 |
400 | ์๋ชป๋ ์์ฒญ |
INTERNAL_AUTH_401 |
401 | ์๋ฒ ๊ฐ ์ธ์ฆ ์คํจ |
COMMON_403 |
403 | ํ์ฌ ํ๊ฒฝ์์ ์ฌ์ฉํ ์ ์๋ ๊ธฐ๋ฅ |
COMMON_404 |
404 | ๋ฆฌ์์ค ์์ |
STALE_DRAFT_REVISION_409 |
409 | ์ต์ ์ ๋ ฅ์ด ์กด์ฌํ๋ ์ด์ ์ถ์ฒ ์์ฒญ ์ค๋จ |
COMMON_422 |
422 | ์์ฒญ๊ฐ ๊ฒ์ฆ ์คํจ |
COMMON_500 |
500 | ์๋ฒ ๋ด๋ถ ์ค๋ฅ |
INTERNAL_AUTH_500 |
500 | ๋ด๋ถ API ์ธ์ฆ ์ค์ ๋๋ฝ |
EMBEDDING_400 |
400 | ์๋ฒ ๋ฉ ์ ๋ ฅ๊ฐ ๋๋ฝ |
EMBEDDING_503 |
503 | ์๋ฒ ๋ฉ ๋ชจ๋ธ ์ฐ๋ ๋ถ๊ฐ |
NEO4J_503 |
503 | Neo4j ์ฐ๊ฒฐ ๋ถ๊ฐ |
LLM_503 |
503 | LLM ์ฐ๋ ๋ถ๊ฐ |
brain ์๋ฒ๋ .env ๊ธฐ๋ฐ์ผ๋ก ํ๊ฒฝ๋ณ์๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
APP_NAME=tryna brain
APP_ENV=local
API_V1_PREFIX=/api/v1
ROOT_PATH=
INTERNAL_API_KEY=local-internal-api-key
VALKEY_HOST=localhost
VALKEY_PORT=6379
VALKEY_PASSWORD=
NEO4J_URI=neo4j://localhost:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=password
NEO4J_DATABASE=neo4j
UPSTAGE_API_KEY=
UPSTAGE_API_KEY_MULTI=
UPSTAGE_QUERY_EMBEDDING_MODEL=solar-embedding-1-large-query
UPSTAGE_PASSAGE_EMBEDDING_MODEL=solar-embedding-1-large-passage
UPSTAGE_EMBEDDING_TIMEOUT_SECONDS=10
UPSTAGE_CHAT_MODEL=solar-pro3
UPSTAGE_CHAT_TIMEOUT_SECONDS=20
D102_EMBEDDING_DIMENSION=4096
D102_EVENT_TYPE_MIN_SCORE=0.61
D102_CONTEXT_MIN_SCORE=0.63
D102_PLACE_TYPE_MIN_SCORE=0.63
D102_RECOMMENDATION_MIN_SCORE=0.62์ด์ ํ๊ฒฝ(APP_ENV=prod)์์๋ Redis/Valkey ์ฐ๊ฒฐ์ TLS์ ์์คํ
CA ์ธ์ฆ์ ๊ฒ์ฆ์ ์ ์ฉํฉ๋๋ค. .env๋ Git์ ์ปค๋ฐํ์ง ์๊ณ .env.example๋ง ๊ณต์ ํฉ๋๋ค.
๋ฏผ๊ฐ ์ ๋ณด๋ ์ ์ฅ์์ ์ปค๋ฐํ์ง ์์ต๋๋ค.
๋ค์ ๊ฐ์ ๋ก์ปฌ .env ๋๋ ๋ฐฐํฌ ํ๊ฒฝ์ secret์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค.
INTERNAL_API_KEYNEO4J_PASSWORDVALKEY_PASSWORDUPSTAGE_API_KEYUPSTAGE_API_KEY_MULTI
.gitignore์ ๋ค์ ํ์ผ๊ณผ ๋๋ ํฐ๋ฆฌ๋ฅผ ์ ์ธํ๋๋ก ์ค์ ํฉ๋๋ค.
.env
.env.local
.env.*.local
.venv
__pycache__/- ์์ฐ์ด ์ผ์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ API ๊ตฌํ
- D101~D105 ์ถ์ฒ ํ์ดํ๋ผ์ธ ๊ตฌํ
- Neo4j ์ฐ๊ฒฐ ๋ฐ ๊ด๊ณยท๋ฒกํฐ ์ถ์ฒ ํ๋ณด ์กฐํ
- Upstage ์๋ฒ ๋ฉ ๋ฐ ์ถ์ฒ ๋ฌธ๊ตฌ ์ ์
- Redis/Valkey ์ฐ๊ฒฐ ๋ฐ ์ต์ revision ๊ฒ์ฆ
- ๋ด๋ถ API ํค ์ธ์ฆ
- ๊ณตํต ์์ธ ์ฒ๋ฆฌ์ Health Check API
- Docker ๋ฐ GitHub Actions CI/CD ๊ตฌ์ฑ
- pytest ํ ์คํธ ๊ตฌ์ฑ
- Python ๋ฐ FastAPI ์คํ ํ๊ฒฝ ๊ตฌ์ถ
- ์์ฐ์ด ์ผ์ 1์ฐจ ํ์ฑ๊ณผ Kiwi ์ฐ๋
- Neo4j ์ฐ๊ฒฐ ๋ฐ ์ง์๋ฒ ์ด์ค ๊ตฌ์ถ
- Neo4j ์๋ฏธ ๋งคํ๊ณผ ์ถ์ฒ ํ๋ณด ์กฐํ ๊ตฌํ
- ๊ด๊ณยท๋ฒกํฐ ์ถ์ฒ ํ๋ณด ๊ฒฐํฉ
- Upstage ์๋ฒ ๋ฉ ๋ฐ LLM ์ฐ๋
- ์ถ์ฒ ํญ๋ชฉ ์๊ฐ ๋งฅ๋ฝ ๊ฒ์ฆ๊ณผ ์ต์ข ์๋ต ๊ตฌ์ฑ
- Redis ๊ธฐ๋ฐ ์ค๋๋ ์ถ์ฒ ์์ฒญ ํ์ ์ฒ๋ฆฌ ์ฐจ๋จ
- Spring ์๋ฒ ๋ด๋ถ API ์ฐ๋