File size: 6,234 Bytes
7d46a91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# ์นด๋ฅด๋ฐ€๋ผ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ๋…ธ๋ฒจ โ€” MVP ๊ตฌํ˜„ ๊ณ„ํš

> ์Šน์ธ์ผ: 2026-07-03 ยท ์ƒํƒœ: **M0~M6 ์ „์ฒด ์™„๋ฃŒ = MVP ์™„์„ฑ** (2026-07-03, feature/mvp-m1-m4)
> ์‹คํ–‰: `.venv/bin/uvicorn engine.router:app --port 8777` โ†’ http://localhost:8777 (์›น ๋ฆฌ๋”)
>       `.venv/bin/python scripts/play.py` (CLI) ยท `adk web .` โ†’ engine (ํฌ์ผ“ ๋‹จ๋…)
> LLM: ๋ฃจํŠธ `.env`์˜ OPENAI_API_KEY ์ž๋™ ๋กœ๋”ฉ. ์‹ค LLM์œผ๋กœ ํšŒํ”ผ์‚ฌ๋‹ค๋ฆฌยท์‹ฌ์ธตํ•ด๊ธˆยท์ˆ˜๋ ด E2E ๊ฒ€์ฆ ์™„๋ฃŒ
> follow-up: SequentialAgent โ†’ google.adk.workflow ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฒ€ํ†  ยท E06-09 ์œ ๋ณด(์ค‘๋ฆฝ) 3์•ˆ
> ์„ ํƒ์ง€ ๋ฏธ๋…ธ์ถœ ยท R-์•ฝ์ ๋ฐ˜์‘ ๊ตฌ์กฐํ™”(ํ˜„์žฌ raw ์ฃผ์ž…) ยท ํƒ€ ํ™”์ž(์•„๋ฒ„์ง€ ๋“ฑ) ์ฑ„ํŒ… ํฌ์ผ“ ยท ์„ธ์…˜ ์˜์†ํ™”
> ์›์น™: CLAUDE.md ์ค€์ˆ˜ (google-adk ๊ณต์‹ ํŒจํ„ด, ์„œ์‚ฌ ์ง„ํ–‰์€ ์ฝ”๋“œ๊ฐ€ยท๋Œ€์‚ฌ๋Š” LLM์ด, ์Šคํฌ์ผ๋Ÿฌ ํ•„ํ„ฐ ๊ฐ•์ œ)

## MVP ์ •์˜

**E01~E06(์ฑ•ํ„ฐ1)์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ํ”Œ๋ ˆ์ด ๊ฐ€๋Šฅํ•œ ์ˆ˜์ง ์Šฌ๋ผ์ด์Šค.**

- ์นด๋“œ ๋‹จ์œ„ ์ฝ๊ธฐ(L0, ์บ๋…ผ ๊ณ ์ •) โ†’ ์„ ํƒ์ง€/์ž์œ ์ฑ„ํŒ… ๊ฐœ์ž… ํฌ์ผ“(L1) โ†’ ์ˆจ์€ ์ƒํƒœ ๋ˆ„์  โ†’ ์—”๋”ฉ 3์ข… ์ˆ˜๋ ด(L2)
- ์—”์ง„: google-adk. ์‹คํ–‰: CLI + `adk web`. ๋ฆฌ๋”ฉ UI๋Š” MVP ์ดํ›„(M5)
- GraphRAG/Neo4j๋Š” MVP ์ œ์™ธ โ€” `kb_query`๋Š” pre_kb ์œ ์ง€, repository ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์ค€๋น„
- `reference/`๋Š” ๊ฐœ๋… ๊ฒ€์ฆ ํ”„๋กœํ† ํƒ€์ž…. **์ฐธ๊ณ ๋งŒ ํ•˜๊ณ  ์ฝ”๋“œ๋Š” ADK๋กœ ์ƒˆ๋กœ ๊ตฌ์ถ•** (์œ ์ € ํ™•์ •)

## ๋ฐ์ดํ„ฐ ๋ชจ๋ธ (A์•ˆ ์•„ํ‚คํ…์ฒ˜ โ€” reference v10์—์„œ ๊ฒ€์ฆ๋œ ๊ฐœ๋…)

| ๋ ˆ์ด์–ด | ํŒŒ์ผ | ๋‚ด์šฉ |
|---|---|---|
| ์ •์ฒด์„ฑ (๋ถˆ๋ณ€) | `content/characters.yaml` | ์ธ๋ฌผ ์‹œํŠธ(ENOS), player=laura, ์ง€์‹๊ฒฝ๊ณ„, kb_query ํ›… |
| ์ฑ•ํ„ฐ ๋ฉ”ํƒ€ | `content/chapters/*.yaml` | entry/exit beats, beat_range, ์—”๋”ฉ 3์ข… ๊ทœ์น™, R์นด๋“œ ๋“ฑ๋ก |
| ๋‚ด๋Ÿฌํ‹ฐ๋ธŒ | `content/beatcards/E0*/*.yaml` | ์นด๋“œ: narration ๋ธ”๋ก/choices/next/canon/๋ณต์„  ํƒœ๊ทธ/์—ฐ์ถœ |

- **์ฝ˜ํ…์ธ  ์›์ฒœ(๊ถŒ์œ„)**: `์นด๋ฅด๋ฐ€๋ผ/0701_์นด๋ฅด๋ฐ€๋ผ/๋น„ํŠธ์นด๋“œ/` MD (๋Œ€ํ‘œ๋‹˜ ์†Œ์œ )
- ๋ณ€ํ™˜ YAML์€ ํŒŒ์ƒ๋ฌผ: `scripts/beatcard_convert.py`(๊ฐœ๋ฐœํŒ€ ์†Œ์œ )๋กœ ์ƒ์„ฑ
- ์ˆจ์€ ์ƒํƒœ 3๊ฐ’ (P0 4์ข… ์—”์ง„ ๋ช…์„ธ): **์‹ ๋ขฐ์ถ•**(์‹œ์†Œ) ยท **์‡ ์•ฝ๋„**(๋‹จ์กฐ ์ฆ๊ฐ€, ์‹ ๋ขฐ์™€ ๋…๋ฆฝ) ยท **์•Ž**(์œ ์ €, ๋„์ž… 1ํšŒ ํ™•๋ฆฝ ํ›„ ๋ถˆ๋ณ€). ์ˆซ์ž/๊ฒŒ์ด์ง€ ์œ ์ € ๋น„๋…ธ์ถœ
- ์—”๋”ฉ ๊ทœ์น™: `doubtโ‰ฅ30โ†’์ฒ˜๋‹จ(์บ๋…ผ)` / `trustโ‰ฅ60โˆงdoubt<20โ†’์˜์›` / `defaultโ†’๊ตฌ์›`

## ์ฝ”๋“œ vs LLM ๊ฒฝ๊ณ„

| ๊ฐœ๋… | ๊ตฌํ˜„ | ํƒ€์ž… |
|---|---|---|
| ์นด๋“œ ์ง„ํ–‰(next ๋งํฌ, canon ์ฝ๊ธฐ) | `services/story.py` ์ƒํƒœ๋จธ์‹  | ๊ฒฐ์ •์  ์ฝ”๋“œ |
| ์„ ํƒ์ง€ โ†’ ์‹ ๋ขฐ์ถ• ๋ฐ˜์˜ | ์„ ํƒ ๋งคํ•‘ + state ์ปค๋ฐ‹ | ๊ฒฐ์ •์  ์ฝ”๋“œ |
| ์ž์œ ์ฑ„ํŒ… ๊ฐœ์ž… ํฌ์ผ“ | guard โ†’ character โ†’ director | ADK ํŒŒ์ดํ”„๋ผ์ธ |
| R-ํšŒํ”ผ์‚ฌ๋‹ค๋ฆฌ/์•ฝ์ ๋ฐ˜์‘ | guard ๊ทœ์น™ + character instruction ์ฃผ์ž… | BaseAgent + instruction |
| ์ˆจ์€ ์ƒํƒœ | session.state + FunctionTool โ†’ ํฌ์ผ“ ์ข…๋ฃŒ ์‹œ ์ปค๋ฐ‹ | ADK state |
| ์ˆ˜๋ ด ํŒ์ • | director ๊ตฌ์กฐํ™” ์ถœ๋ ฅ + `services/pocket.py` ์ฝ”๋“œ ์žฌ๊ฒ€์ฆ | LlmAgent + ์ฝ”๋“œ |
| ์—”๋”ฉ ๋ถ„๊ธฐ | ending_rules ์กฐ๊ฑด์‹ ํ‰๊ฐ€ | ๊ฒฐ์ •์  ์ฝ”๋“œ |
| ์Šคํฌ์ผ๋Ÿฌ ๋ฐฉ์–ด | `beat_id โ‰ค ํ˜„์žฌ` ํ•„ํ„ฐ + before_model ์ฝœ๋ฐฑ | ์ฝœ๋ฐฑ |

## ๊ฐœ์ž… ํฌ์ผ“ ํŒŒ์ดํ”„๋ผ์ธ (escalate ๊ฒฉ๋ฆฌ ๊ทœ์น™ ์ ์šฉ)

```
pocket_session (SequentialAgent)
โ”œโ”€โ”€ pocket_context_loader                  โ† BaseAgent: ์นด๋“œ ๋ธŒ๋ฆฌํ”„ + ์‹ ๋ขฐ ๋ ˆ๋ฒจ ๊ฒฐ ๋กœ๋“œ
โ”œโ”€โ”€ turn_loop (LoopAgent max=์นด๋“œ๋ณ„ ์ƒํ•œ)
โ”‚   โ”œโ”€โ”€ input_guard                        โ† BaseAgent: ์„ธ๊ณ„๊ด€ ์ดํƒˆ/์ •์ฒด์ง๊ฒฉ/์•ฝ์  ๊ฐ์ง€
โ”‚   โ”œโ”€โ”€ character                          โ† LlmAgent: ์นด๋ฅด๋ฐ€๋ผ (์‹œํŠธ+ํ™”๋ฒ•6๊ทœ์น™+R์นด๋“œ+์‹ ๋ขฐ๋ณ„ ๊ฒฐ)
โ”‚   โ””โ”€โ”€ director                           โ† LlmAgent: ๋น„ํŠธ ๋‹ฌ์„ฑ/์ดํƒˆ/์‹ ๋ขฐ๋ฐ˜์˜/์ˆ˜๋ ด โ†’ escalate
โ””โ”€โ”€ pocket_closer (LoopAgent max=1)        โ† ๊ฐ•์ œ ์ˆ˜๋ ด ๋‚ด๋ ˆ์ด์…˜ + ์ƒํƒœ ์ปค๋ฐ‹ โ†’ ๋‹ค์Œ ์นด๋“œ ๋ณต๊ท€
```

## ๋งˆ์ผ์Šคํ†ค

- **M0 โ€” ์Šค์บํด๋“œ** (0.5์ผ): git init(๋กœ์ปฌ๋งŒ, ์›๊ฒฉ ํ‘ธ์‹œ๋Š” ์ถ”ํ›„) ยท engine/ ๋ผˆ๋Œ€ ยท ์˜์กด์„ฑ ยท CLAUDE.md ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ์„น์…˜ ๊ฐฑ์‹  ยท ๋ณธ ๋ฌธ์„œ
- **M1 โ€” ์ฝ˜ํ…์ธ  ๊ณ„์•ฝ** (1์ผ): ๋น„ํŠธ์นด๋“œ/์ฑ•ํ„ฐ/์บ๋ฆญํ„ฐ Pydantic ์Šคํ‚ค๋งˆ + `python -m engine.schemas.validate content/` ยท ๋ณ€ํ™˜ ์Šคํฌ๋ฆฝํŠธ ยท next ๋งํฌ ๋ฌด๊ฒฐ์„ฑ ๊ฒ€์‚ฌ(๊ณ ์•„/๋Š๊ธด ์ฒด์ธ). ๊ฒ€์ฆ ๊ธฐ์ค€: ๊ธฐ์กด 61์นด๋“œ ํ†ต๊ณผ
- **M2 โ€” ๊ฒฐ์ •์  ๋ฆฌ๋”ฉ ๋ฃจํ”„** (1์ผ): entry_beat๋ถ€ํ„ฐ canon ํŽ˜์ด์ง• ยท ์„ ํƒ์ง€ ์‹ ๋ขฐ์ถ• ๋ฐ˜์˜ ยท ์‡ ์•ฝ๋„ ๋‹จ์กฐ ์ฆ๊ฐ€ ยท **LLM ์—†์ด** CLI๋กœ E01~E06 ํ†ต๋… + ์—”๋”ฉ 3์ข… ๋„๋‹ฌ ํ™•์ธ
- **M3 โ€” ADK ๊ฐœ์ž… ํฌ์ผ“** (2~3์ผ, ํ•ต์‹ฌ): ํ„ด ํŒŒ์ดํ”„๋ผ์ธ ยท ์นด๋ฅด๋ฐ€๋ผ instruction ยท director ๊ตฌ์กฐํ™” ํŒ์ •(FunctionToolโ†’state) ยท guard ยท `adk web`์œผ๋กœ ํฌ์ผ“ 1๊ฐœ(E06-09 ๊ถŒ์žฅ) ์ง‘์ค‘ ๊ฒ€์ฆ
- **M4 โ€” ์ „์ฒด ๊ด€ํ†ต** (1~2์ผ): ๋ฆฌ๋”ฉ ๋ฃจํ”„ โ†” ํฌ์ผ“ ์—ฐ๊ฒฐ ยท E01โ†’์—”๋”ฉ ์ „์ฒด ํ”Œ๋ ˆ์ด ยท ํ„ด ๋กœ๊น… ํ”Œ๋Ÿฌ๊ทธ์ธ ยท ์‹œ์—ฐ(CLI + adk web)
- **M5 โ€” MVP ์ดํ›„**: FastAPI router + ๋ฆฌ๋”ฉ UI ยท GraphRAG(kb_query ํ™œ์„ฑํ™”) ยท ํ‰๊ฐ€ ํ•˜๋„ค์Šค ยท style_critic ๋ฃจํ”„

## ํด๋” ๊ตฌ์กฐ

```
sorac/
โ”œโ”€โ”€ engine/
โ”‚   โ”œโ”€โ”€ agent.py / app.py / model.py / router.py
โ”‚   โ”œโ”€โ”€ schemas/        beatcard.py ยท chapter.py ยท character.py ยท validate.py
โ”‚   โ”œโ”€โ”€ services/       story.py ยท pocket.py ยท state.py ยท retrieval.py(2๋‹จ๊ณ„ ์Šคํ…)
โ”‚   โ”œโ”€โ”€ repositories/   content.py ยท playlog.py
โ”‚   โ”œโ”€โ”€ agents/         input_guard.py ยท pocket_context_loader.py
โ”‚   โ”œโ”€โ”€ sub_agents/     character/ ยท director/
โ”‚   โ”œโ”€โ”€ tools/          state/ (update_trust.py, mark_beat.py) ยท retrieval/(์Šคํ…)
โ”‚   โ”œโ”€โ”€ callbacks/ ยท plugins/logging.py ยท instructions/
โ”œโ”€โ”€ content/            beatcards/ ยท chapters/ ยท characters.yaml (M1์—์„œ ์ ์žฌ)
โ”œโ”€โ”€ scripts/            beatcard_convert.py
โ”œโ”€โ”€ tests/
โ””โ”€โ”€ docs/plans/mvp.md   (๋ณธ ๋ฌธ์„œ)
```

## ๊ฒฐ์ • ๋กœ๊ทธ

- ๋ฐ๋ชจ ํ”„๋ก ํŠธ: ์—”์ง„ ์šฐ์„ , UI ์ตœ์†Œ (์œ ์ € ํ™•์ •)
- E01_๊ตฌํ˜„๊ณ„ํš.drawio ๋ฌด์‹œ (์œ ์ € ์ง€์‹œ) โ€” ์”ฌ ์„ค๊ณ„ ๊ทผ๊ฑฐ๋กœ ์“ฐ์ง€ ์•Š์Œ
- ๋น„ํŠธ์นด๋“œ MD๊ฐ€ ์ฝ˜ํ…์ธ  ๊ถŒ์œ„, reference ๋‚ด YAML์€ ํŒŒ์ƒ๋ฌผ (์Šน์ธ)
- CLAUDE.md "YAML 4์ข…" ์„น์…˜ โ†’ A์•ˆ 3๋ ˆ์ด์–ด๋กœ ๊ฐฑ์‹  (์Šน์ธ)
- E07~E15: MD๋งŒ ์กด์žฌ, MVP ๋ฒ”์œ„ ๋ฐ–