Junhoee commited on
Commit
f56c599
Β·
verified Β·
1 Parent(s): 1670941

Update docs/agent-architecture.md

Browse files
Files changed (1) hide show
  1. docs/agent-architecture.md +53 -98
docs/agent-architecture.md CHANGED
@@ -1,129 +1,84 @@
1
- # Agent Architecture
2
 
3
  ## κ°œμš”
4
 
5
- ν˜„μž¬ 메ꡬ밍 챗봇은 μ•„λž˜ νλ¦„μœΌλ‘œ λ™μž‘ν•©λ‹ˆλ‹€.
6
 
7
- 1. `bootstrap.py`μ—μ„œ ν™˜κ²½λ³€μˆ˜μ™€ λŸ°νƒ€μž„ 데이터 경둜λ₯Ό μ€€λΉ„
8
- 2. `retrieval.py`μ—μ„œ FAISS μΈλ±μŠ€μ™€ 메타데이터λ₯Ό λ‘œλ“œ
9
- 3. `agent.py`μ—μ„œ Google ADK `LlmAgent`와 retrieval tool ꡬ성
10
- 4. `chat.py`μ—μ„œ μ„Έμ…˜ μ‹€ν–‰, 슀트리밍 응닡, λŒ€ν™” μš”μ•½ 관리
11
- 5. `app_gradio.py`μ—μ„œ PC/λͺ¨λ°”일 λ°˜μ‘ν˜• μ±„νŒ… UI 제곡
12
 
13
- ## νŒŒμΌλ³„ μ—­ν• 
14
 
15
- ### `megumin_agent/bootstrap.py`
16
-
17
- - `.env` λ‘œλ“œ
18
- - 둜컬 `adk-python/src` 경둜 등둝
19
- - Hugging Face dataset repoμ—μ„œ 데이터 파일 λ‹€μš΄λ‘œλ“œ
20
- - λ‹€μš΄λ‘œλ“œ μ‹€νŒ¨ μ‹œ 둜컬 `data/processed`λ₯Ό fallback으둜 μ‚¬μš©
21
 
22
- λ‹€μš΄λ‘œλ“œ λŒ€μƒ:
 
 
 
 
23
 
24
- - `megumin_qa_dataset.json`
25
- - `megumin_questions.faiss`
26
- - `megumin_question_answer.faiss`
27
- - `megumin_questions_meta.json`
28
- - `namuwiki_qa.json`
29
- - `namuwiki_questions.faiss`
30
- - `namuwiki_question_answer.faiss`
31
- - `namuwiki_questions_meta.json`
32
 
33
- ### `megumin_agent/retrieval.py`
34
 
35
- - QA JSON λ ˆμ½”λ“œ λ‘œλ“œ
36
- - Gemini μž„λ² λ”© 기반 FAISS 검색
37
- - question-only μΈλ±μŠ€μ™€ question+answer 인덱슀λ₯Ό λ‘˜ λ‹€ 쑰회
38
- - 두 검색 κ²°κ³Όλ₯Ό 합쳐 μ μˆ˜κ°€ 높은 후보 top-kλ₯Ό λ°˜ν™˜
39
 
40
- 데이터 계측:
41
 
42
- - 페λ₯΄μ†Œλ‚˜ 계측: `megumin_qa_dataset.json`
43
- - 사싀 계측: `namuwiki_qa.json`
 
44
 
45
  ### `megumin_agent/agent.py`
46
 
47
- - 메ꡬ밍 페λ₯΄μ†Œλ‚˜ ν”„λ‘¬ν”„νŠΈ μ •μ˜
48
- - `retrieve_megumin_examples` tool μ •μ˜
49
- - 페λ₯΄μ†Œλ‚˜μš© top-2, μ‚¬μ‹€μš© top-2λ₯Ό 각각 μˆ˜μ§‘
50
- - ADK callback으둜 λŒ€ν™” μš”μ•½, 졜근 질의, RAG 흔적을 state에 기둝
51
-
52
- tool λ°˜ν™˜ 핡심:
53
-
54
- - `persona_matches`
55
- - `fact_matches`
56
- - `style_notes`
57
- - `fact_notes`
58
 
59
  ### `megumin_agent/chat.py`
60
 
61
- - `Runner`와 `InMemorySessionService` 생성
62
- - `stream_chat()`으둜 ADK SSE 슀트리밍 응닡 생성
63
- - `chat_once()`λŠ” 슀트리밍 κ²°κ³Όλ₯Ό λͺ¨μ•„ μ΅œμ’… λ¬Έμžμ—΄λ§Œ ν•„μš”ν•  λ•Œ μ‚¬μš©ν•˜λŠ” 래퍼
64
- - 졜근 6턴을 남기고, κ·Έ 이전 λŒ€ν™”λŠ” `conversation_summary_map` key-value ꡬ쑰둜 μ••μΆ•
65
- - μ••μΆ•λœ μš”μ•½μ€ 짧은 λ¬Έμžμ—΄ ν˜•νƒœμ˜ `conversation_summary`λ‘œλ„ ν•¨κ»˜ λ Œλ”λ§
66
-
67
- μš”μ•½ ꡬ쑰:
68
-
69
- - `user_topics`
70
- - `assistant_points`
71
 
72
  ### `app_gradio.py`
73
 
74
- - PC용 3νŒ¨λ„ λ ˆμ΄μ•„μ›ƒ 제곡
75
- - μ™Όμͺ½: 메ꡬ밍 ν”„λ‘œν•„κ³Ό μ˜ˆμ‹œ 질문
76
- - κ°€μš΄λ°: μ±„νŒ… νŒ¨λ„
77
- - 였λ₯Έμͺ½: 메ꡬ밍 λΉ„μ£Όμ–Ό νŒ¨λ„
78
- - 첫 접속 μ‹œ κΈ°λ³Έ 인삿말을 assistant λ©”μ‹œμ§€λ‘œ 미리 ν‘œμ‹œ
79
- - `create_chat_services()`λŠ” import μ‹œμ μ΄ μ•„λ‹ˆλΌ 첫 질문 μ‹œμ μ— lazy init
80
- - 첫 질문 μ „μ—λŠ” `μ„œλΉ„μŠ€ μ€€λΉ„ 쀑...`, 이후 응닡 생성 μ€‘μ—λŠ” `λ‹΅λ³€ 생성 쀑...` μƒνƒœ ν‘œμ‹œ
81
- - μž‘μ€ κ·œμΉ™ 기반 μƒνƒœ λ°°μ§€λ₯Ό μΆ”κ°€ν•΄ λ©”κ΅¬λ°μ˜ ν˜„μž¬ λΆ„μœ„κΈ°λ₯Ό ν‘œμ‹œ
82
- - ADK의 SSE partial eventλ₯Ό λ°›μ•„ 닡변을 μ μ§„μ μœΌλ‘œ 슀트리밍 ν‘œμ‹œ
83
- - `launch(..., ssr_mode=False)`둜 μ„œλ²„ μ‚¬μ΄λ“œ λ Œλ”λ§μ„ 끄고 초기 기동 뢀담을 μ€„μž„
84
- - λͺ¨λ°”μΌμ—μ„œλŠ” 쒌우 glass panel을 숨기고, 제λͺ©, μ΅œμ†Œ μ„€λͺ…, 이미지, μ±„νŒ…μ°½λ§Œ 보이도둝 λ‹¨μˆœν™”
85
 
86
  ### `app_gradio_messenger.py`
87
 
88
- - κΈ°μ‘΄ agent/chat λ‘œμ§μ„ κ·ΈλŒ€λ‘œ μž¬μ‚¬μš©ν•˜λŠ” λ©”μ‹ μ €ν˜• UI
89
- - 쒌츑 3, 우츑 7 λΉ„μœ¨μ˜ 2μ„Ήν„° λ ˆμ΄μ•„μ›ƒ
90
- - 쒌츑: 캐릭터 ν”„λ‘œν•„ λͺ©λ‘κ³Ό 졜근 λŒ€ν™” 미리보기
91
- - 우츑: 캐릭터 쒌츑 말풍선, μ‚¬μš©μž 우츑 말풍선 ꡬ쑰의 λŒ€ν™”μ°½
 
 
 
 
 
 
92
 
93
  ### `app.py`
94
 
95
- - Hugging Face Spaces μ§„μž…μ 
96
- - `MEGUMIN_UI` ν™˜κ²½λ³€μˆ˜λ‘œ κΈ°λ³Έ UI와 λ©”μ‹ μ € UI 쀑 ν•˜λ‚˜λ₯Ό 선택해 λ‘œλ“œ
97
-
98
- ## λŒ€ν™” 흐름
99
-
100
- μ‚¬μš©μž μž…λ ₯이 λ“€μ–΄μ˜€λ©΄:
101
-
102
- 1. `app_gradio.py`κ°€ μƒνƒœ 문ꡬλ₯Ό λ¨Όμ € κ°±μ‹ 
103
- 2. 첫 질문이면 `get_services()`κ°€ lazy init으둜 μ„œλΉ„μŠ€ μ€€λΉ„
104
- 3. `chat.py`의 `stream_chat()`이 ADK `run_async(..., RunConfig(streaming_mode=SSE))`둜 μ‹€ν–‰
105
- 4. `agent.py`의 tool이 retrieval μˆ˜ν–‰
106
- 5. `retrieval.py`κ°€
107
- - 페λ₯΄μ†Œλ‚˜ 데이터 top-2
108
- - 사싀 데이터 top-2
109
- λ₯Ό 각각 검색
110
- 6. ADK partial eventκ°€ λ“€μ–΄μ˜¬ λ•Œλ§ˆλ‹€ UIκ°€ assistant 닡변을 μ μ§„μ μœΌλ‘œ κ°±μ‹ 
111
- 7. μ„Έμ…˜ μ’…λ£Œ ν›„ 였래된 이벀트λ₯Ό key-value summary둜 μ••μΆ•
112
-
113
- ## μ„Έμ…˜κ³Ό λ©”λͺ¨λ¦¬
114
-
115
- ν˜„μž¬ μ €μž₯ 방식은 `InMemorySessionService`μž…λ‹ˆλ‹€.
116
 
117
- - μ„œλ²„ ν”„λ‘œμ„ΈμŠ€κ°€ μ‚΄μ•„ μžˆλŠ” λ™μ•ˆλ§Œ μœ μ§€
118
- - μž¬μ‹œμž‘ μ‹œ μ΄ˆκΈ°ν™”
119
- - 졜근 6ν„΄λ§Œ μœ μ§€
120
- - 였래된 λ‚΄μš©μ€ `user_topics`, `assistant_points` μ€‘μ‹¬μ˜ key-value summary둜 state에 남김
121
 
122
- ## UI λͺ©μ 
 
 
123
 
124
- ν˜„μž¬ UIλŠ” μ²΄ν—˜ν˜• 캐릭터 챗봇 화면을 λͺ©ν‘œλ‘œ ν•©λ‹ˆλ‹€.
125
 
126
- - 캐릭터와 μ‹€μ œλ‘œ 마주 보고 λŒ€ν™”ν•˜λŠ” λŠλ‚Œ
127
- - 반투λͺ… 유리 νŒ¨λ„ 쀑심 ꡬ성
128
- - λ©”κ΅¬λ°μ˜ κΈ°λ³Έ μ†Œκ°œμ™€ μ‚¬μš© μ˜ˆμ‹œ 제곡
129
- - 슀트리밍 λ‹΅λ³€κ³Ό μž‘μ€ μƒνƒœ λ°°μ§€λ‘œ 생동감 보강
 
1
+ # μ—μ΄μ „νŠΈ μ•„ν‚€ν…μ²˜
2
 
3
  ## κ°œμš”
4
 
5
+ ν”„λ‘œμ νŠΈλŠ” μ„Έ 개의 UI μ§„μž…μ κ³Ό ν•˜λ‚˜μ˜ 곡용 μ±„νŒ… λŸ°νƒ€μž„μœΌλ‘œ κ΅¬μ„±λ©λ‹ˆλ‹€.
6
 
7
+ 1. `app.py`
8
+ 2. `app_gradio.py`
9
+ 3. `app_gradio_messenger.py`
10
+ 4. `megumin_agent/`
 
11
 
12
+ 각 UI 계측은 같은 μ±„νŒ… μ„œλΉ„μŠ€ 헬퍼λ₯Ό ν˜ΈμΆœν•˜κ³ , μ±„νŒ… μ„œλΉ„μŠ€λŠ” 검색, μ—μ΄μ „νŠΈ μ‹€ν–‰, 슀트리밍, μ„Έμ…˜ μƒνƒœ 관리λ₯Ό λ‹΄λ‹Ήν•©λ‹ˆλ‹€.
13
 
14
+ ## λŸ°νƒ€μž„ 흐름
 
 
 
 
 
15
 
16
+ 1. `megumin_agent/bootstrap.py`κ°€ ν™˜κ²½ λ³€μˆ˜λ₯Ό 뢈러였고 둜컬 λ˜λŠ” 원격 데이터 νŒŒμΌμ„ μ€€λΉ„ν•©λ‹ˆλ‹€.
17
+ 2. `megumin_agent/retrieval.py`κ°€ 페λ₯΄μ†Œλ‚˜/사싀 검색에 ν•„μš”ν•œ FAISS μΈλ±μŠ€μ™€ 메타데이터λ₯Ό λ‘œλ“œν•©λ‹ˆλ‹€.
18
+ 3. `megumin_agent/agent.py`κ°€ ADK μ—μ΄μ „νŠΈλ₯Ό κ΅¬μ„±ν•˜κ³  검색 기반 도ꡬλ₯Ό μ—°κ²°ν•©λ‹ˆλ‹€.
19
+ 4. `megumin_agent/chat.py`κ°€ μ±„νŒ… μ„œλΉ„μŠ€λ₯Ό λ§Œλ“€κ³  λΆ€λΆ„ 응닡 슀트리밍과 μ„Έμ…˜ λ©”λͺ¨λ¦¬λ₯Ό κ΄€λ¦¬ν•©λ‹ˆλ‹€.
20
+ 5. UI λͺ¨λ“ˆμ΄ 화면을 λ Œλ”λ§ν•˜κ³  μ‚¬μš©μž λ©”μ‹œμ§€λ₯Ό `stream_chat()`으둜 μ „λ‹¬ν•©λ‹ˆλ‹€.
21
 
22
+ ## λͺ¨λ“ˆλ³„ μ„€λͺ…
 
 
 
 
 
 
 
23
 
24
+ ### `megumin_agent/bootstrap.py`
25
 
26
+ - `.env`λ₯Ό λ‘œλ“œν•©λ‹ˆλ‹€.
27
+ - ν•„μš” μ‹œ 둜컬 `adk-python/src` 경둜λ₯Ό μ€€λΉ„ν•©λ‹ˆλ‹€.
28
+ - κ°€λŠ₯ν•˜λ©΄ Hugging Faceμ—μ„œ 데이터셋 μžμ‚°μ„ λ‚΄λ €λ°›μŠ΅λ‹ˆλ‹€.
29
+ - 원격 μžμ‚°μ„ μ‚¬μš©ν•  수 μ—†μœΌλ©΄ 둜컬 처리 λ°μ΄ν„°λ‘œ ν΄λ°±ν•©λ‹ˆλ‹€.
30
 
31
+ ### `megumin_agent/retrieval.py`
32
 
33
+ - QA JSON μ†ŒμŠ€μ™€ FAISS 인덱슀λ₯Ό λ‘œλ“œν•©λ‹ˆλ‹€.
34
+ - 페λ₯΄μ†Œλ‚˜ν˜• 데이터와 μ‚¬μ‹€ν˜• 데이터에 λŒ€ν•΄ 검색을 μˆ˜ν–‰ν•©λ‹ˆλ‹€.
35
+ - ν”„λ‘¬ν”„νŠΈ ꡬ성에 μ‚¬μš©ν•  κ°„κ²°ν•œ 검색 κ²°κ³Όλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
36
 
37
  ### `megumin_agent/agent.py`
38
 
39
+ - 메ꡬ밍 페λ₯΄μ†Œλ‚˜ ν”„λ‘¬ν”„νŠΈμ™€ 검색 도ꡬλ₯Ό μ •μ˜ν•©λ‹ˆλ‹€.
40
+ - 페λ₯΄μ†Œλ‚˜ 검색과 사싀 검색을 ν•˜λ‚˜μ˜ μ—μ΄μ „νŠΈ νλ¦„μœΌλ‘œ ν•©μΉ©λ‹ˆλ‹€.
41
+ - λ©€ν‹°ν„΄ λŒ€ν™”μ— ν•„μš”ν•œ μš”μ•½ μƒνƒœλ₯Ό κ΄€λ¦¬ν•©λ‹ˆλ‹€.
 
 
 
 
 
 
 
 
42
 
43
  ### `megumin_agent/chat.py`
44
 
45
+ - 곡용 λŸ¬λ„ˆμ™€ λ©”λͺ¨λ¦¬ 기반 μ„Έμ…˜ μ„œλΉ„μŠ€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.
46
+ - `stream_chat()`으둜 SSE μŠ€νƒ€μΌμ˜ λΆ€λΆ„ 응닡을 μ œκ³΅ν•©λ‹ˆλ‹€.
47
+ - 졜근 ν„΄ μƒνƒœμ™€ μš”μ•½ 정보λ₯Ό μœ μ§€ν•΄ 후속 λŒ€ν™”λ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
 
 
 
 
 
 
 
48
 
49
  ### `app_gradio.py`
50
 
51
+ - κΈ°μ‘΄ 닀쀑 νŒ¨λ„ κ΅¬μ„±μ˜ 메인 μ±„νŒ… UIμž…λ‹ˆλ‹€.
52
+ - 첫 μš”μ²­ μ‹œμ μ— μ±„νŒ… μ„œλΉ„μŠ€λ₯Ό μ§€μ—° μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.
53
+ - μ–΄μ‹œμŠ€ν„΄νŠΈμ˜ λΆ€λΆ„ 응닡을 ν™”λ©΄μ˜ μ±„νŒ… μ˜μ—­μ— μŠ€νŠΈλ¦¬λ°ν•©λ‹ˆλ‹€.
 
 
 
 
 
 
 
 
54
 
55
  ### `app_gradio_messenger.py`
56
 
57
+ - λ™μΌν•œ 곡용 μ±„νŒ… μ„œλΉ„μŠ€ 계측 μœ„μ— λ©”μ‹ μ €ν˜• UIλ₯Ό 올린 νŒŒμΌμž…λ‹ˆλ‹€.
58
+ - 쒌츑과 우츑 μ„Ήν„°λŠ” Gradio `Column(scale=3)`κ³Ό `Column(scale=7)`으둜 `3:7` λΉ„μœ¨μ„ μœ μ§€ν•©λ‹ˆλ‹€.
59
+ - λ°μŠ€ν¬ν†± λ©”μ‹ μ € λ ˆμ΄μ•„μ›ƒμ€ μ˜λ„μ μœΌλ‘œ κ³ μ • 높이λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
60
+ - 우츑 μ„Ήν„°λŠ” `상단 헀더`, `λ©”μ‹œμ§€ ν‘œμ‹œ μ˜μ—­`, `μž…λ ₯ μ˜μ—­`의 μ„Έ 파트둜 λ‚˜λ‰˜λ©°, κ³ μ • 3ν–‰ grid둜 λ°°μΉ˜λ©λ‹ˆλ‹€.
61
+ - `상단 헀더`와 `μž…λ ₯ μ˜μ—­`은 λͺ…μ‹œμ μΈ ν”½μ…€ 높이λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
62
+ - λ©”μ‹œμ§€ λ·°ν¬νŠΈλŠ” `calc(...)`둜 λ‚¨λŠ” λ†’μ΄λ§Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
63
+ - 아바타 μ΄λ―Έμ§€λŠ” μ™ΈλΆ€ μ €μž₯μ†Œ λŒ€μ‹  ν”„λ‘œμ νŠΈ λ‚΄λΆ€ `source_file` ν΄λ”μ˜ 둜컬 이미지 νŒŒμΌμ„ Gradio 파일 라우트둜 μ„œλΉ™ν•©λ‹ˆλ‹€.
64
+ - μš°μ„ μ μœΌλ‘œ `megumin_profile` μ΄λ¦„μ˜ `png`, `jpg`, `jpeg`, `webp` νŒŒμΌμ„ μ°Ύκ³ , μ—†μœΌλ©΄ 같은 ν΄λ”μ˜ 첫 번째 이미지 νŒŒμΌμ„ μ‚¬μš©ν•©λ‹ˆλ‹€.
65
+ - fallback SVGλŠ” 둜컬 이미지 λ‘œλ“œ μ‹€νŒ¨ μ‹œμ—λ§Œ ν‘œμ‹œλ˜λ©°, `source_file` ν΄λ”λŠ” λ©”μ‹ μ € 단독 μ‹€ν–‰κ³Ό `app.py` 경유 μ‹€ν–‰ λͺ¨λ‘μ—μ„œ `allowed_paths`둜 λͺ…μ‹œμ μœΌλ‘œ λ…ΈμΆœν•©λ‹ˆλ‹€.
66
+ - Gradio μžλ™ stretch λž˜νΌκ°€ μ„Έλ‘œ ν™•μž₯을 λ‹€μ‹œ μœ λ°œν•  수 μžˆμœΌλ―€λ‘œ 이 νŒŒμΌμ—μ„œλŠ” `gr.Blocks(fill_height=True)`λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
67
 
68
  ### `app.py`
69
 
70
+ - Hugging Face Spaces μ§„μž…μ μž…λ‹ˆλ‹€.
71
+ - `MEGUMIN_UI` 값에 따라 κΈ°λ³Έ UI와 λ©”μ‹ μ € UI 쀑 ν•˜λ‚˜λ₯Ό μ„ νƒν•©λ‹ˆλ‹€.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
+ ## μ„Έμ…˜ λͺ¨λΈ
 
 
 
74
 
75
+ - ν˜„μž¬ μ„Έμ…˜ μ €μž₯μ†ŒλŠ” λ©”λͺ¨λ¦¬ κΈ°λ°˜μž…λ‹ˆλ‹€.
76
+ - μ•± ν”„λ‘œμ„ΈμŠ€κ°€ μ‚΄μ•„ μžˆλŠ” λ™μ•ˆ λŒ€ν™” 연속성이 μœ μ§€λ©λ‹ˆλ‹€.
77
+ - 졜근 λ©”μ‹œμ§€λŠ” 직접 λ³΄μ‘΄ν•˜κ³ , 였래된 λ§₯락은 μš”μ•½ μƒνƒœλ‘œ μΆ•μ•½ν•©λ‹ˆλ‹€.
78
 
79
+ ## λ©”μ‹ μ € λ ˆμ΄μ•„μ›ƒ μœ μ§€λ³΄μˆ˜ κ·œμΉ™
80
 
81
+ - `app_gradio_messenger.py`λŠ” 뷰포트λ₯Ό 꽉 μ±„μš°λŠ” flex μ‹€ν—˜μ΄ μ•„λ‹ˆλΌ κ³ μ • 높이 λ ˆμ΄μ•„μ›ƒμœΌλ‘œ λ‹€λ£Ήλ‹ˆλ‹€.
82
+ - λ©”μ‹ μ € νŒ¨λ„ 높이가 λ°”λ€Œλ©΄ CSS λ³€μˆ˜μ™€ 이 λ¬Έμ„œλ₯Ό ν•¨κ»˜ μˆ˜μ •ν•©λ‹ˆλ‹€.
83
+ - 쒌우 λΉ„μœ¨μ΄ λ°”λ€Œλ©΄ Gradio `scale` κ°’κ³Ό README λ©”λͺ¨λ₯Ό ν•¨κ»˜ μˆ˜μ •ν•©λ‹ˆλ‹€.
84
+ - νŠΉλ³„ν•œ μ΄μœ μ™€ λΈŒλΌμš°μ € 검증 없이 λ‚΄λΆ€ λž˜νΌμ— μ€‘μ²©λœ κ³ μ • `min-height` 체인을 λ‹€μ‹œ λ„μž…ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.