Kentlo commited on
Commit
56a2bc0
ยท
verified ยท
1 Parent(s): f8a0529

Sync from GitHub c6e463fa85688c6406b64ab1ad3a425506a9bacb

Browse files
README.md CHANGED
@@ -25,6 +25,7 @@ pinned: false
25
  - ํŒŒ์‹ฑ ํ’ˆ์งˆ ๊ฒ€์ฆ ๋ฐ ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ
26
  - ๋ฌธ์ œ, ์ •๋‹ต, ํ•ด์„ค, ํ’€์ด ๊ธฐ๋ก ์ €์žฅ
27
  - Streamlit ๊ธฐ๋ฐ˜ ๋ฌธ์ œํ’€์ด ํ™”๋ฉด
 
28
  - ์˜ค๋‹ต/๋ณต์Šต ํ™”๋ฉด
29
  - ๊ฐœ๋… ์ •๋ฆฌ ํ™”๋ฉด
30
  - Chroma ๊ธฐ๋ฐ˜ ์œ ์‚ฌ ๋ฌธ์ œ ๊ฒ€์ƒ‰ ๊ตฌ์กฐ
@@ -71,6 +72,31 @@ docker compose up --build
71
  - Airflow ์›น์„œ๋ฒ„: `http://localhost:8080`
72
  - PostgreSQL: `localhost:5432`
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  ## ํ™˜๊ฒฝ ๋ณ€์ˆ˜
75
 
76
  ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” PostgreSQL์ž…๋‹ˆ๋‹ค.
 
25
  - ํŒŒ์‹ฑ ํ’ˆ์งˆ ๊ฒ€์ฆ ๋ฐ ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ
26
  - ๋ฌธ์ œ, ์ •๋‹ต, ํ•ด์„ค, ํ’€์ด ๊ธฐ๋ก ์ €์žฅ
27
  - Streamlit ๊ธฐ๋ฐ˜ ๋ฌธ์ œํ’€์ด ํ™”๋ฉด
28
+ - ๊ณตํ†ต ์ง€๋ฌธ, ์›๋ฌธ ์ด๋ฏธ์ง€, Yes/No ์ง„์ˆ ํ˜• ๋ฌธ์ œํ’€์ด UI
29
  - ์˜ค๋‹ต/๋ณต์Šต ํ™”๋ฉด
30
  - ๊ฐœ๋… ์ •๋ฆฌ ํ™”๋ฉด
31
  - Chroma ๊ธฐ๋ฐ˜ ์œ ์‚ฌ ๋ฌธ์ œ ๊ฒ€์ƒ‰ ๊ตฌ์กฐ
 
72
  - Airflow ์›น์„œ๋ฒ„: `http://localhost:8080`
73
  - PostgreSQL: `localhost:5432`
74
 
75
+ ๋กœ์ปฌ์—์„œ Streamlit๋งŒ ๋น ๋ฅด๊ฒŒ ํ™•์ธํ•  ๋•Œ๋Š” ์ž„์‹œ SQLite DB๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
76
+
77
+ ```bash
78
+ DATABASE_URL=sqlite:////tmp/cert-study-local-check.db \
79
+ python -m streamlit run streamlit_app.py
80
+ ```
81
+
82
+ ## ๋ฐฐํฌ์šฉ ๋ฌธ์ œ ๋ฐ์ดํ„ฐ
83
+
84
+ Hugging Face Space์—๋Š” ๋กœ์ปฌ DB๋‚˜ PDF ์›๋ณธ์„ ์˜ฌ๋ฆฌ์ง€ ์•Š๊ณ , `cert_study_app/demo_data/questions_seed.json`๊ณผ `static/question_assets/`์˜ ์ฐธ์กฐ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
85
+
86
+ ํ˜„์žฌ ๋ฐฐํฌ์šฉ seed๋Š” 321๋ฌธํ•ญ, ๊ณตํ†ต ์ง€๋ฌธ ํฌํ•จ ๋ฌธํ•ญ, ์›๋ฌธ ์ด๋ฏธ์ง€, Yes/No ์ง„์ˆ ํ˜• ๋ฌธ์ œ UI์— ํ•„์š”ํ•œ ๊ตฌ์กฐ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. seed๋Š” ์•„๋ž˜ ๋ช…๋ น์œผ๋กœ ๋‹ค์‹œ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
87
+
88
+ ```bash
89
+ python scripts/export_hf_seed.py
90
+ ```
91
+
92
+ ## ๋ณ€๊ฒฝ ์ด๋ ฅ ํ™•์ธ
93
+
94
+ Git ์ปค๋ฐ‹์€ ๋‚ ์งœ์™€ ํ•จ๊ป˜ ๋‚จ๊ธฐ ๋•Œ๋ฌธ์— ์ผ์ž๋ณ„ ๋ณ€๊ฒฝ ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
95
+
96
+ ```bash
97
+ scripts/git_daily_changes.sh 2026-06-07
98
+ ```
99
+
100
  ## ํ™˜๊ฒฝ ๋ณ€์ˆ˜
101
 
102
  ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” PostgreSQL์ž…๋‹ˆ๋‹ค.
docs/01_overview.md CHANGED
@@ -50,6 +50,8 @@ PDF์—์„œ ์ถ”์ถœํ•œ ํ…์ŠคํŠธ๋ฅผ ๋ฌธ์ œ ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„๊ณ , ๋ฌธ์ œ ๋ณธ๋ฌธ, ๋ณด
50
 
51
  ์ €์žฅ๋œ ๋ฌธ์ œ๋ฅผ ์‹œํ—˜๋ณ„๋กœ ์„ ํƒํ•ด ํ’€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ์„ ํƒ๊ณผ ์ •๋‹ต ์—ฌ๋ถ€๋Š” ํ’€์ด ๊ธฐ๋ก์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
52
 
 
 
53
  ### ์˜ค๋‹ต/๋ณต์Šต
54
 
55
  ํ‹€๋ฆฐ ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•˜๊ณ , ๋ณต์Šต ํ๋ฆ„์œผ๋กœ ์ด์–ด๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
@@ -70,10 +72,14 @@ Chroma์— ๋ฌธ์ œ ์ž„๋ฒ ๋”ฉ์„ ์ €์žฅํ•ด, ํ˜„์žฌ ๋ฌธ์ œ์™€ ๋น„์Šทํ•œ ๋ฌธ์ œ๋ฅผ
70
 
71
  - PDF ํŒŒ์‹ฑ ๊ฒฐ๊ณผ๋ฅผ ๋” ์•ˆ์ •์ ์œผ๋กœ ๋งŒ๋“ค๊ธฐ
72
  - ํŒŒ์‹ฑ ํ’ˆ์งˆ์„ ์ž๋™์œผ๋กœ ๊ฒ€์ฆํ•˜๊ธฐ
 
 
73
  - PostgreSQL๊ณผ Chroma์˜ ์—ญํ• ์„ ๋ช…ํ™•ํžˆ ๋‚˜๋ˆ„๊ธฐ
74
  - Airflow๋กœ ๊ธด PDF ์ฒ˜๋ฆฌ ์ž‘์—…์„ ๊ด€๋ฆฌํ•˜๊ธฐ
75
  - Streamlit ํ™”๋ฉด์„ ์‹ค์ œ ๊ณต๋ถ€ํ•˜๊ธฐ ํŽธํ•œ ํ๋ฆ„์œผ๋กœ ๋‹ค๋“ฌ๊ธฐ
76
 
 
 
77
  ## ์•ž์œผ๋กœ ๊ฐœ์„ ํ•  ๊ธฐ๋Šฅ
78
 
79
  - ๋ถ๋งˆํฌ ๊ธฐ๋Šฅ
 
50
 
51
  ์ €์žฅ๋œ ๋ฌธ์ œ๋ฅผ ์‹œํ—˜๋ณ„๋กœ ์„ ํƒํ•ด ํ’€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ์„ ํƒ๊ณผ ์ •๋‹ต ์—ฌ๋ถ€๋Š” ํ’€์ด ๊ธฐ๋ก์œผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
52
 
53
+ ํ˜„์žฌ ๋ฌธ์ œํ’€์ด ํ™”๋ฉด์€ ์ผ๋ฐ˜ ๊ฐ๊ด€์‹๋ฟ ์•„๋‹ˆ๋ผ ๊ณตํ†ต ์ง€๋ฌธ ๋ฌธ์ œ, ์›๋ฌธ ์ด๋ฏธ์ง€ ๋ณด๊ธฐ, Yes/No ์ง„์ˆ ํ˜• ๋ฌธ์ œ, ํ•ญ๋ชฉ๋ณ„ ์„ ํƒ ๋ฌธ์ œ๋ฅผ ๊ตฌ๋ถ„ํ•ด์„œ ํ‘œ์‹œํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๊ฐœ์„ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
54
+
55
  ### ์˜ค๋‹ต/๋ณต์Šต
56
 
57
  ํ‹€๋ฆฐ ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•˜๊ณ , ๋ณต์Šต ํ๋ฆ„์œผ๋กœ ์ด์–ด๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
 
72
 
73
  - PDF ํŒŒ์‹ฑ ๊ฒฐ๊ณผ๋ฅผ ๋” ์•ˆ์ •์ ์œผ๋กœ ๋งŒ๋“ค๊ธฐ
74
  - ํŒŒ์‹ฑ ํ’ˆ์งˆ์„ ์ž๋™์œผ๋กœ ๊ฒ€์ฆํ•˜๊ธฐ
75
+ - ๊ณตํ†ต ์ง€๋ฌธ๊ณผ ์›๋ฌธ ์ด๋ฏธ์ง€๊ฐ€ ๋ฌธ์ œํ’€์ด ํ™”๋ฉด์—์„œ ๋ˆ„๋ฝ๋˜์ง€ ์•Š๊ฒŒ ํ•˜๊ธฐ
76
+ - Yes/No ์ง„์ˆ ํ˜• ๋ฌธ์ œ๋ฅผ ๊ฐ๊ด€์‹์ด ์•„๋‹ˆ๋ผ ์ง„์ˆ ๋ณ„ ์„ ํƒ UI๋กœ ์ œ๊ณตํ•˜๊ธฐ
77
  - PostgreSQL๊ณผ Chroma์˜ ์—ญํ• ์„ ๋ช…ํ™•ํžˆ ๋‚˜๋ˆ„๊ธฐ
78
  - Airflow๋กœ ๊ธด PDF ์ฒ˜๋ฆฌ ์ž‘์—…์„ ๊ด€๋ฆฌํ•˜๊ธฐ
79
  - Streamlit ํ™”๋ฉด์„ ์‹ค์ œ ๊ณต๋ถ€ํ•˜๊ธฐ ํŽธํ•œ ํ๋ฆ„์œผ๋กœ ๋‹ค๋“ฌ๊ธฐ
80
 
81
+ Hugging Face Space ๋ฐฐํฌ์šฉ์œผ๋กœ๋Š” ๋กœ์ปฌ DB๋‚˜ PDF ์›๋ณธ ๋Œ€์‹  `questions_seed.json`๊ณผ ํ•„์š”ํ•œ ์ •์  ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ seed์—๋Š” 321๋ฌธํ•ญ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
82
+
83
  ## ์•ž์œผ๋กœ ๊ฐœ์„ ํ•  ๊ธฐ๋Šฅ
84
 
85
  - ๋ถ๋งˆํฌ ๊ธฐ๋Šฅ
docs/03_data_pipeline.md CHANGED
@@ -129,6 +129,28 @@ LLM์€ ๋ชจ๋“  ๋‹จ๊ณ„์—์„œ ๋ฌด์กฐ๊ฑด ์“ฐ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๊ตฌ์กฐํ™”๊ฐ€ ์–ด
129
 
130
  ์ด๋•Œ PostgreSQL์˜ ๋ฌธ์ œ ID์™€ Chroma์˜ ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์•ผ ์œ ์‚ฌ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ์‹ค์ œ ๋ฌธ์ œ ํ™”๋ฉด์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  ## ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์ค‘์š”ํ•œ ์ 
133
 
134
  ### ์ €์žฅ ์ „์— ํ’ˆ์งˆ์„ ํ™•์ธํ•œ๋‹ค
 
129
 
130
  ์ด๋•Œ PostgreSQL์˜ ๋ฌธ์ œ ID์™€ Chroma์˜ ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์•ผ ์œ ์‚ฌ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ์‹ค์ œ ๋ฌธ์ œ ํ™”๋ฉด์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
131
 
132
+ ## ๋ฐฐํฌ์šฉ Seed ์ƒ์„ฑ
133
+
134
+ Hugging Face Space์—์„œ๋Š” ๋กœ์ปฌ PostgreSQL DB, Chroma ์ธ๋ฑ์Šค, PDF ์›๋ณธ์„ ์ง์ ‘ ์˜ฌ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ๋ฐฐํฌ ์‹œ ๋ฐ”๋กœ ๋ฌธ์ œํ’€์ด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก seed ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
135
+
136
+ ํ˜„์žฌ ๋ฐฐํฌ์šฉ seed ์ƒ์„ฑ ๋ช…๋ น์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
137
+
138
+ ```bash
139
+ python scripts/export_hf_seed.py
140
+ ```
141
+
142
+ ์ด ์Šคํฌ๋ฆฝํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์•„๋ž˜ ๋‘ ๋ฐ์ดํ„ฐ๋ฅผ ํ•ฉ์ณ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
143
+
144
+ - `data/Json/questions.json`: ๋ฌธ์ œ, ๋ณด๊ธฐ, ์ •๋‹ต, ํ•ด์„ค์ด ์ •๋ฆฌ๋œ ๊ธฐ์ค€ ๋ฐ์ดํ„ฐ
145
+ - `data/parsed_json/reparsed_multipage_images_20260601_205501.json`: ๊ณตํ†ต ์ง€๋ฌธ๊ณผ ๊ณตํ†ต ์ง€๋ฌธ ์›๋ฌธ ์ด๋ฏธ์ง€ ์ •๋ณด
146
+
147
+ ์ƒ์„ฑ ๊ฒฐ๊ณผ:
148
+
149
+ - `cert_study_app/demo_data/questions_seed.json`
150
+ - `static/question_assets/`
151
+
152
+ ํ˜„์žฌ seed์—๋Š” 321๋ฌธํ•ญ์ด ๋“ค์–ด ์žˆ์œผ๋ฉฐ, ๊ณตํ†ต ์ง€๋ฌธ์ด ์žˆ๋Š” ๋ฌธํ•ญ์€ ๊ธด ์ง€๋ฌธ๊ณผ ์›๋ฌธ ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ๊ฐ€ ํ•จ๊ป˜ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. Yes/No ์ง„์ˆ ํ˜• ๋ฌธ์ œ๋Š” ํ™”๋ฉด์—์„œ ์ง„์ˆ ๋ณ„ `์˜ˆ / ์•„๋‹ˆ์˜ค`๋กœ ํ’€ ์ˆ˜ ์žˆ๋„๋ก ์ •๋‹ต์ด `Y,N,Y` ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์ •๊ทœํ™”๋ฉ๋‹ˆ๋‹ค.
153
+
154
  ## ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์ค‘์š”ํ•œ ์ 
155
 
156
  ### ์ €์žฅ ์ „์— ํ’ˆ์งˆ์„ ํ™•์ธํ•œ๋‹ค
docs/05_deployment.md CHANGED
@@ -24,6 +24,15 @@ docker compose up --build
24
  - Airflow: `http://localhost:8080`
25
  - PostgreSQL: `localhost:5432`
26
 
 
 
 
 
 
 
 
 
 
27
  ## Docker๋ฅผ ์“ฐ๋Š” ์ด์œ 
28
 
29
  ์ด ํ”„๋กœ์ ํŠธ๋Š” Streamlit, PostgreSQL, Airflow, PDF ์ฒ˜๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, Chroma ๋“ฑ ์—ฌ๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
@@ -51,6 +60,21 @@ Docker๋ฅผ ์“ฐ๋Š” ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
51
 
52
  ์ด๋Ÿฐ ํŒŒ์ผ์€ ์‹คํ–‰ ์ค‘ ์ƒ์„ฑ๋˜๋Š” ๋ฐ์ดํ„ฐ์ด๋ฏ€๋กœ ๋ณดํ†ต Git์— ์˜ฌ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  ## ํ™˜๊ฒฝ ๋ณ€์ˆ˜
55
 
56
  ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์€ PostgreSQL์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
 
24
  - Airflow: `http://localhost:8080`
25
  - PostgreSQL: `localhost:5432`
26
 
27
+ Streamlit ํ™”๋ฉด๋งŒ ๋น ๋ฅด๊ฒŒ ํ™•์ธํ•  ๋•Œ๋Š” Docker ์—†์ด ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
28
+
29
+ ```bash
30
+ DATABASE_URL=sqlite:////tmp/cert-study-local-check.db \
31
+ python -m streamlit run streamlit_app.py
32
+ ```
33
+
34
+ ์ด ๋ฐฉ์‹์€ ์ž„์‹œ SQLite DB๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋กœ์ปฌ ํ™”๋ฉด ํ™•์ธ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด `data/questions.db` ํŒŒ์ผ ๊ถŒํ•œ์ด ๊ผฌ์˜€๊ฑฐ๋‚˜ ์ฝ๊ธฐ ์ „์šฉ ์ƒํƒœ์ผ ๋•Œ๋„ ์ƒˆ DB๋กœ ๋ฌธ์ œ seed ๋™์ž‘์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
35
+
36
  ## Docker๋ฅผ ์“ฐ๋Š” ์ด์œ 
37
 
38
  ์ด ํ”„๋กœ์ ํŠธ๋Š” Streamlit, PostgreSQL, Airflow, PDF ์ฒ˜๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, Chroma ๋“ฑ ์—ฌ๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
 
60
 
61
  ์ด๋Ÿฐ ํŒŒ์ผ์€ ์‹คํ–‰ ์ค‘ ์ƒ์„ฑ๋˜๋Š” ๋ฐ์ดํ„ฐ์ด๋ฏ€๋กœ ๋ณดํ†ต Git์— ์˜ฌ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
62
 
63
+ ## Hugging Face Space ๋ฐฐํฌ
64
+
65
+ Hugging Face Space๋Š” GitHub Actions๋ฅผ ํ†ตํ•ด ํ˜„์žฌ ํ”„๋กœ์ ํŠธ ์Šค๋ƒ…์ƒท์„ ๋™๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.
66
+
67
+ Space์—๋Š” ์•„๋ž˜ ๋Ÿฐํƒ€์ž„ ๋ฐ์ดํ„ฐ๋Š” ์˜ฌ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
68
+
69
+ - ์—…๋กœ๋“œ PDF ์›๋ณธ
70
+ - ๋กœ์ปฌ PostgreSQL/SQLite DB
71
+ - Chroma ์ธ๋ฑ์Šค
72
+ - Airflow ๋กœ๊ทธ์™€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
73
+
74
+ ๋Œ€์‹  `cert_study_app/demo_data/questions_seed.json`๊ณผ `static/question_assets/`๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์•ฑ ์‹œ์ž‘ ์‹œ DB๊ฐ€ ๋น„์–ด ์žˆ๊ฑฐ๋‚˜ ๊ธฐ์กด seed๊ฐ€ ์˜ค๋ž˜๋œ ๊ฒฝ์šฐ seed ๊ธฐ์ค€์œผ๋กœ ๋ฌธ์ œ๋ฅผ ์ถ”๊ฐ€/๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
75
+
76
+ ํ˜„์žฌ seed์—๋Š” 321๋ฌธํ•ญ, ๊ณตํ†ต ์ง€๋ฌธ, ์›๋ฌธ ์ด๋ฏธ์ง€, Yes/No ์ง„์ˆ ํ˜• ๋ฌธ์ œ ๊ตฌ์กฐ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
77
+
78
  ## ํ™˜๊ฒฝ ๋ณ€์ˆ˜
79
 
80
  ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์€ PostgreSQL์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
docs/07_troubleshooting.md CHANGED
@@ -48,6 +48,12 @@ docker compose logs cert-study-app
48
  - 8501 ํฌํŠธ๋ฅผ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ์ด ์‚ฌ์šฉ ์ค‘์ธ์ง€ ํ™•์ธํ•œ๋‹ค.
49
  - ํ•„์š”ํ•˜๋ฉด `http://127.0.0.1:8501`๋กœ๋„ ์ ‘์†ํ•ด ๋ณธ๋‹ค.
50
 
 
 
 
 
 
 
51
  ## PostgreSQL ์—ฐ๊ฒฐ ์˜ค๋ฅ˜
52
 
53
  ### ์ฆ์ƒ
@@ -100,6 +106,19 @@ CERT_STUDY_DB_FALLBACK=1
100
 
101
  ์šด์˜ ๋˜๋Š” ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ๋Š” PostgreSQL์„ ๊ธฐ์ค€์œผ๋กœ ๋งž์ถ”๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  ## Airflow ํ™”๋ฉด์— ์ ‘์†๋˜์ง€ ์•Š์„ ๋•Œ
104
 
105
  ### ์ฆ์ƒ
@@ -159,6 +178,40 @@ PDF ์—…๋กœ๋“œ ํ›„ ์ฒ˜๋ฆฌ ํ˜„ํ™ฉ์ด ์˜ค๋ž˜ ๋ฐ”๋€Œ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
159
  - ๋ฌธ์ œ ๋ฒˆํ˜ธ ํŒจํ„ด๊ณผ ๋ณด๊ธฐ ํŒจํ„ด์„ ๋” ๋ช…ํ™•ํžˆ ์ฒ˜๋ฆฌํ•œ๋‹ค.
160
  - ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ LLM์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ๋ณด๋‹ค, ์‹คํŒจ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์€ ๋ฌธ์ œ๋งŒ ๋ณด์ •ํ•˜๋Š” ๋ฐฉํ–ฅ์ด ์ข‹๋‹ค.
161
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  ## Chroma ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์ด์ƒํ•  ๋•Œ
163
 
164
  ### ์ฆ์ƒ
 
48
  - 8501 ํฌํŠธ๋ฅผ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ์ด ์‚ฌ์šฉ ์ค‘์ธ์ง€ ํ™•์ธํ•œ๋‹ค.
49
  - ํ•„์š”ํ•˜๋ฉด `http://127.0.0.1:8501`๋กœ๋„ ์ ‘์†ํ•ด ๋ณธ๋‹ค.
50
 
51
+ ๋กœ์ปฌ ๊ฐ€์ƒํ™˜๊ฒฝ์˜ `streamlit` ์‹คํ–‰ ํŒŒ์ผ์ด ์˜ˆ์ „ ๊ฒฝ๋กœ๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์•„๋ž˜์ฒ˜๋Ÿผ Python ๋ชจ๋“ˆ ๋ฐฉ์‹์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
52
+
53
+ ```bash
54
+ python -m streamlit run streamlit_app.py
55
+ ```
56
+
57
  ## PostgreSQL ์—ฐ๊ฒฐ ์˜ค๋ฅ˜
58
 
59
  ### ์ฆ์ƒ
 
106
 
107
  ์šด์˜ ๋˜๋Š” ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ๋Š” PostgreSQL์„ ๊ธฐ์ค€์œผ๋กœ ๋งž์ถ”๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
108
 
109
+ ### `attempt to write a readonly database` ์˜ค๋ฅ˜๊ฐ€ ๋‚  ๋•Œ
110
+
111
+ ๊ธฐ์กด SQLite ํŒŒ์ผ ๊ถŒํ•œ ๋•Œ๋ฌธ์— seed ๊ฐฑ์‹ ์ด ์‹คํŒจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
112
+
113
+ ๋น ๋ฅด๊ฒŒ ํ™”๋ฉด๋งŒ ํ™•์ธํ•˜๋ ค๋ฉด ์ƒˆ ์ž„์‹œ DB๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
114
+
115
+ ```bash
116
+ DATABASE_URL=sqlite:////tmp/cert-study-local-check.db \
117
+ python -m streamlit run streamlit_app.py
118
+ ```
119
+
120
+ ๊ธฐ์กด DB๋ฅผ ๊ณ„์† ์“ฐ๋ ค๋ฉด `data/questions.db` ํŒŒ์ผ ๊ถŒํ•œ๊ณผ ์†Œ์œ ์ž๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
121
+
122
  ## Airflow ํ™”๋ฉด์— ์ ‘์†๋˜์ง€ ์•Š์„ ๋•Œ
123
 
124
  ### ์ฆ์ƒ
 
178
  - ๋ฌธ์ œ ๋ฒˆํ˜ธ ํŒจํ„ด๊ณผ ๋ณด๊ธฐ ํŒจํ„ด์„ ๋” ๋ช…ํ™•ํžˆ ์ฒ˜๋ฆฌํ•œ๋‹ค.
179
  - ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ LLM์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ๋ณด๋‹ค, ์‹คํŒจ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์€ ๋ฌธ์ œ๋งŒ ๋ณด์ •ํ•˜๋Š” ๋ฐฉํ–ฅ์ด ์ข‹๋‹ค.
180
 
181
+ ## ๊ณตํ†ต ์ง€๋ฌธ์ด ๋ณด์ด์ง€ ์•Š์„ ๋•Œ
182
+
183
+ ### ์ฆ์ƒ
184
+
185
+ ์ผ€์ด์Šค ์Šคํ„ฐ๋”” ๋ฌธ์ œ์ธ๋ฐ `๊ณตํ†ต ์ง€๋ฌธ ๋ณด๊ธฐ`๊ฐ€ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
186
+
187
+ ### ํ™•์ธํ•  ๊ฒƒ
188
+
189
+ - `questions_seed.json`์— `parent_stem`์ด ๋“ค์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
190
+ - ์•ฑ์ด ์˜ค๋ž˜๋œ DB๋ฅผ ๋ณด๊ณ  ์žˆ์ง€ ์•Š์€์ง€ ํ™•์ธํ•œ๋‹ค.
191
+ - seed refresh๊ฐ€ DB์— ์“ธ ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ์ธ์ง€ ํ™•์ธํ•œ๋‹ค.
192
+
193
+ ### ํ•ด๊ฒฐ ๋ฐฉํ–ฅ
194
+
195
+ - Space ๋˜๋Š” ๋กœ์ปฌ ์•ฑ์„ ์žฌ์‹œ์ž‘ํ•œ๋‹ค.
196
+ - ๋กœ์ปฌ์—์„œ๋Š” ์ž„์‹œ SQLite DB๋กœ ๋‹ค์‹œ ์‹คํ–‰ํ•ด seed ์ž์ฒด๊ฐ€ ์ •์ƒ์ธ์ง€ ํ™•์ธํ•œ๋‹ค.
197
+ - ๊ธฐ์กด DB๊ฐ€ ์ฝ๊ธฐ ์ „์šฉ์ด๋ฉด ๊ถŒํ•œ์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์ƒˆ DB๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
198
+
199
+ ## Yes/No ๋ฌธ์ œ๊ฐ€ ๊ฐ๊ด€์‹์ฒ˜๋Ÿผ ๋ณด์ผ ๋•Œ
200
+
201
+ ### ์ฆ์ƒ
202
+
203
+ `๋‹ค์Œ ๊ฐ ์ง„์ˆ ์— ๋Œ€ํ•ด ์˜ˆ/์•„๋‹ˆ์˜ค๋ฅผ ์„ ํƒ`ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ A/B/C ๋ณด๊ธฐ์ฒ˜๋Ÿผ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
204
+
205
+ ### ์„ค๋ช…
206
+
207
+ Yes/No ์ง„์ˆ ํ˜• ๋ฌธ์ œ๋Š” ์ผ๋ฐ˜ ๊ฐ๊ด€์‹๊ณผ ๋‹ค๋ฅด๊ฒŒ ์ง„์ˆ ๋ณ„ `์˜ˆ / ์•„๋‹ˆ์˜ค` ์ž…๋ ฅ UI๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
208
+
209
+ ### ํ™•์ธํ•  ๊ฒƒ
210
+
211
+ - `question_type`์ด `Hotspot (True/False)` ๋˜๋Š” ์œ ์‚ฌํ•œ ๊ฐ’์ธ์ง€ ํ™•์ธํ•œ๋‹ค.
212
+ - ์ •๋‹ต์ด `Y,N,Y` ๋˜๋Š” `[{key, value}]` ํ˜•ํƒœ๋กœ ์ •๊ทœํ™”๋˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
213
+ - `1-A / 1-B / 2-A / 2-B` ํ˜•์‹์€ ํ•ญ๋ชฉ๋ณ„ ์„ ํƒ UI๋กœ ํ‘œ์‹œ๋˜์–ด์•ผ ํ•œ๋‹ค.
214
+
215
  ## Chroma ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์ด์ƒํ•  ๋•Œ
216
 
217
  ### ์ฆ์ƒ
docs/08_publish_automation.md CHANGED
@@ -66,7 +66,14 @@ Hugging Face Space์—๋Š” ๋กœ์ปฌ PostgreSQL ๋ฐ์ดํ„ฐ, Chroma ์ธ๋ฑ์Šค, ์—…๋กœ
66
  python scripts/export_hf_seed.py
67
  ```
68
 
69
- ์ด ์Šคํฌ๋ฆฝํŠธ๋Š” `data/Json/questions.json`์„ ์ฝ์–ด `questions_seed.json`์„ ๋งŒ๋“ค๊ณ , ๋ฌธ์ œ ์›๋ฌธ ๋ณด๊ธฐ์— ํ•„์š”ํ•œ ์ฐธ์กฐ ์ด๋ฏธ์ง€๋งŒ `static/question_assets/`๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. `dump.pdf` ์ „์ฒด๋‚˜ `data/images/` ์ „์ฒด๋ฅผ ์˜ฌ๋ฆฌ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์šฉ๋Ÿ‰๊ณผ ์ €์ž‘๊ถŒ ๋…ธ์ถœ ๋ฒ”์œ„๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
 
 
 
 
 
 
 
70
 
71
  ์‹ค์ œ ๊ธฐ์ถœ/๋คํ”„ ์„ฑ๊ฒฉ์˜ ๋ฌธ์ œ๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฒฝ์šฐ Hugging Face Space๋Š” private๋กœ ์šด์˜ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
72
 
@@ -158,6 +165,28 @@ git push origin main
158
 
159
  ๋กœ์ปฌ์—์„œ Hugging Face๊นŒ์ง€ ์ง์ ‘ pushํ•˜๋Š” ๋ฐฉ์‹์€ GitHub Actions ์„ค์ • ์ „ ํ…Œ์ŠคํŠธ์šฉ์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•ด๋„ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  ## ์ฃผ์˜์‚ฌํ•ญ
162
 
163
  - `HF_TOKEN`์€ ์ ˆ๋Œ€ Git์— ์ปค๋ฐ‹ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
 
66
  python scripts/export_hf_seed.py
67
  ```
68
 
69
+ ์ด ์Šคํฌ๋ฆฝํŠธ๋Š” `data/Json/questions.json`์„ ๊ธฐ์ค€ ๋ฌธ์ œ ๋ฐ์ดํ„ฐ๋กœ ์‚ฌ์šฉํ•˜๊ณ , `data/parsed_json/reparsed_multipage_images_20260601_205501.json`์—์„œ ๊ณตํ†ต ์ง€๋ฌธ๊ณผ ๊ณตํ†ต ์ง€๋ฌธ ์›๋ฌธ ์ด๋ฏธ์ง€ ์ •๋ณด๋ฅผ ๋ณด๊ฐ•ํ•ฉ๋‹ˆ๋‹ค.
70
+
71
+ ์ƒ์„ฑ ๊ฒฐ๊ณผ:
72
+
73
+ - `cert_study_app/demo_data/questions_seed.json`
74
+ - `static/question_assets/`
75
+
76
+ `dump.pdf` ์ „์ฒด๋‚˜ `data/images/` ์ „์ฒด๋ฅผ ์˜ฌ๋ฆฌ์ง€ ์•Š๊ณ , ๋ฌธ์ œํ’€์ด์™€ ์›๋ฌธ ํ™•์ธ์— ํ•„์š”ํ•œ ์ฐธ์กฐ ์ด๋ฏธ์ง€๋งŒ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ seed์—๋Š” 321๋ฌธํ•ญ, ๊ณตํ†ต ์ง€๋ฌธ, ์›๋ฌธ ์ด๋ฏธ์ง€, Yes/No ์ง„์ˆ ํ˜• ๋ฌธ์ œ ๊ตฌ์กฐ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
77
 
78
  ์‹ค์ œ ๊ธฐ์ถœ/๋คํ”„ ์„ฑ๊ฒฉ์˜ ๋ฌธ์ œ๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฒฝ์šฐ Hugging Face Space๋Š” private๋กœ ์šด์˜ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
79
 
 
165
 
166
  ๋กœ์ปฌ์—์„œ Hugging Face๊นŒ์ง€ ์ง์ ‘ pushํ•˜๋Š” ๋ฐฉ์‹์€ GitHub Actions ์„ค์ • ์ „ ํ…Œ์ŠคํŠธ์šฉ์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•ด๋„ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.
167
 
168
+ ## ์ผ์ž๋ณ„ ๋ณ€๊ฒฝ ํ™•์ธ
169
+
170
+ Git์€ ์ปค๋ฐ‹๋งˆ๋‹ค ๋‚ ์งœ์™€ ๋ณ€๊ฒฝ ํŒŒ์ผ์„ ๋‚จ๊น๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ผ์ž๋ณ„ ๋ณ€๊ฒฝ ๋‚ด์—ญ์€ ์–ธ์ œ๋“  ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
171
+
172
+ ์˜ค๋Š˜ ๋ณ€๊ฒฝ ๋‚ด์—ญ:
173
+
174
+ ```bash
175
+ git log --since=midnight --stat
176
+ ```
177
+
178
+ ํŠน์ • ๋‚ ์งœ ๋ณ€๊ฒฝ ๋‚ด์—ญ:
179
+
180
+ ```bash
181
+ scripts/git_daily_changes.sh 2026-06-07
182
+ ```
183
+
184
+ ๋” ์ž์„ธํžˆ ๋ณด๋ ค๋ฉด ํŠน์ • ์ปค๋ฐ‹์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
185
+
186
+ ```bash
187
+ git show <commit-hash>
188
+ ```
189
+
190
  ## ์ฃผ์˜์‚ฌํ•ญ
191
 
192
  - `HF_TOKEN`์€ ์ ˆ๋Œ€ Git์— ์ปค๋ฐ‹ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
docs/devlog/2026-06-07.md CHANGED
@@ -113,3 +113,19 @@ Chroma๋Š” ์œ ์‚ฌ ๋ฌธ์ œ ๊ฒ€์ƒ‰์„ ์œ„ํ•œ ๋ณด์กฐ ์ƒ‰์ธ์œผ๋กœ ์„ค๋ช…ํ–ˆ๋‹ค.
113
  - PDF ํŒŒ์‹ฑ ํ’ˆ์งˆ ๋ฆฌํฌํŠธ ํ™”๋ฉด ๊ฐœ์„ 
114
  - ๋ถ๋งˆํฌ ๊ธฐ๋Šฅ ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„
115
  - README์— ์Šคํฌ๋ฆฐ์ƒท ์ถ”๊ฐ€
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  - PDF ํŒŒ์‹ฑ ํ’ˆ์งˆ ๋ฆฌํฌํŠธ ํ™”๋ฉด ๊ฐœ์„ 
114
  - ๋ถ๋งˆํฌ ๊ธฐ๋Šฅ ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„
115
  - README์— ์Šคํฌ๋ฆฐ์ƒท ์ถ”๊ฐ€
116
+
117
+ ## ์ถ”๊ฐ€ ์ง„ํ–‰ ๋‚ด์šฉ
118
+
119
+ GitHub์™€ Hugging Face Space ๋ฐฐํฌ ์ž๋™ํ™”๋ฅผ ์ •๋ฆฌํ–ˆ๋‹ค. Hugging Face์—๋Š” ๋กœ์ปฌ DB๋‚˜ PDF ์›๋ณธ์„ ์ง์ ‘ ์˜ฌ๋ฆฌ์ง€ ์•Š๊ณ , ๋ฐฐํฌ์šฉ seed์™€ ํ•„์š”ํ•œ ์ •์  ์ด๋ฏธ์ง€๋งŒ ์˜ฌ๋ฆฌ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌ์„ฑํ–ˆ๋‹ค.
120
+
121
+ ๋ฐฐํฌ์šฉ seed๋Š” `scripts/export_hf_seed.py`๋กœ ์ƒ์„ฑํ•œ๋‹ค. ๊ธฐ์ค€ ๋ฌธ์ œ ๋ฐ์ดํ„ฐ๋Š” `data/Json/questions.json`์„ ์‚ฌ์šฉํ•˜๊ณ , ๊ณตํ†ต ์ง€๋ฌธ๊ณผ ๊ณตํ†ต ์ง€๋ฌธ ์›๋ฌธ ์ด๋ฏธ์ง€๋Š” `data/parsed_json/reparsed_multipage_images_20260601_205501.json`์—์„œ ๋ณด๊ฐ•ํ•œ๋‹ค.
122
+
123
+ ํ˜„์žฌ ๋ฐฐํฌ์šฉ seed์—๋Š” 321๋ฌธํ•ญ์ด ๋“ค์–ด ์žˆ๋‹ค. ๊ณตํ†ต ์ง€๋ฌธ์ด ์žˆ๋Š” ๋ฌธํ•ญ์€ `parent_stem`๊ณผ `parent_image_paths`๋ฅผ ํ•จ๊ป˜ ๊ฐ€์ง„๋‹ค.
124
+
125
+ ๋ฌธ์ œํ’€์ด UI์—์„œ๋Š” Yes/No ์ง„์ˆ ํ˜• ๋ฌธ์ œ๋ฅผ ์ผ๋ฐ˜ ๊ฐ๊ด€์‹์ด ์•„๋‹ˆ๋ผ ์ง„์ˆ ๋ณ„ `์˜ˆ / ์•„๋‹ˆ์˜ค` ๋งคํŠธ๋ฆญ์Šค๋กœ ํ‘œ์‹œํ•˜๋„๋ก ๊ฐœ์„ ํ–ˆ๋‹ค. `1-A / 1-B / 2-A / 2-B`์ฒ˜๋Ÿผ ํ•ญ๋ชฉ๋ณ„ ์„ ํƒ์ด ํ•„์š”ํ•œ ๋ฌธ์ œ๋Š” ํ•ญ๋ชฉ๋ณ„ select๋กœ ํ‘œ์‹œํ•œ๋‹ค.
126
+
127
+ ์ผ์ž๋ณ„ Git ๋ณ€๊ฒฝ ํ™•์ธ์„ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด `scripts/git_daily_changes.sh`๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค.
128
+
129
+ ```bash
130
+ scripts/git_daily_changes.sh 2026-06-07
131
+ ```
scripts/git_daily_changes.sh ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ DAY="${1:-$(date +%F)}"
5
+ NEXT_DAY="$(date -j -v+1d -f "%Y-%m-%d" "${DAY}" +%F 2>/dev/null || date -d "${DAY} +1 day" +%F)"
6
+
7
+ echo "Git changes for ${DAY}"
8
+ echo
9
+
10
+ git log \
11
+ --since="${DAY} 00:00" \
12
+ --until="${NEXT_DAY} 00:00" \
13
+ --date=short \
14
+ --pretty=format:'%h %ad %s' \
15
+ --stat
streamlit_app.py CHANGED
@@ -22,7 +22,7 @@ from cert_study_app.services.ingestion_job_service import IngestionJobService
22
  from cert_study_app.services.parse_quality_service import default_quality_report_path
23
  from cert_study_app.services.question_type_metadata_service import automation_summary, status_label, type_metadata
24
  from cert_study_app.services.question_concept_service import classify_question_batch, concept_label
25
- from cert_study_app.services.quiz_service import QuizService
26
  from cert_study_app.services.study_assistant_service import StudyAssistantService
27
  from cert_study_app.services.vector_service import QuestionVectorStore
28
 
@@ -680,36 +680,7 @@ def box_choice_labels(question, count: int) -> list[str]:
680
 
681
 
682
  def yes_no_answer_labels(value: str) -> list[str]:
683
- if isinstance(value, (list, dict)):
684
- raw_value = value
685
- else:
686
- raw_value = None
687
- try:
688
- raw_value = json.loads(value) if isinstance(value, str) else None
689
- except Exception:
690
- raw_value = None
691
-
692
- if isinstance(raw_value, list):
693
- values = [
694
- item.get("value") or item.get("answer") or item.get("selected_answer")
695
- for item in raw_value
696
- if isinstance(item, dict)
697
- ]
698
- labels = yes_no_answer_labels(",".join(str(item) for item in values if item))
699
- if labels:
700
- return labels
701
- elif isinstance(raw_value, dict):
702
- labels = yes_no_answer_labels(",".join(str(item) for item in raw_value.values()))
703
- if labels:
704
- return labels
705
-
706
- text = str(value or "")
707
- if re.fullmatch(r"\s*[YNyn](?:\s*,\s*[YNyn])+\s*", text):
708
- return [token.upper() for token in re.findall(r"[YNyn]", text)]
709
- tokens = re.findall(r"(?<![๊ฐ€-ํžฃ])์˜ˆ(?![๊ฐ€-ํžฃ])|์•„๋‹ˆ์˜ค|์•„๋‹ˆ์š”|\byes\b|\bno\b", text, re.I)
710
- if len(tokens) < 2:
711
- return []
712
- return ["Y" if token == "์˜ˆ" or token.lower() == "yes" else "N" for token in tokens]
713
 
714
 
715
  def is_yes_no_hotspot(question) -> bool:
 
22
  from cert_study_app.services.parse_quality_service import default_quality_report_path
23
  from cert_study_app.services.question_type_metadata_service import automation_summary, status_label, type_metadata
24
  from cert_study_app.services.question_concept_service import classify_question_batch, concept_label
25
+ from cert_study_app.services.quiz_service import QuizService, yes_no_labels
26
  from cert_study_app.services.study_assistant_service import StudyAssistantService
27
  from cert_study_app.services.vector_service import QuestionVectorStore
28
 
 
680
 
681
 
682
  def yes_no_answer_labels(value: str) -> list[str]:
683
+ return yes_no_labels(value)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
684
 
685
 
686
  def is_yes_no_hotspot(question) -> bool: