feat: add license, compliance utilities, plot script, and UI layout restoration
Browse files- .gitignore +82 -81
- AGENTS.md +9 -0
- LICENSE +21 -0
- app.py +5 -8
- delete_zero_rel_articles.py +52 -0
- plot_keywords.py +34 -7
- stitch_screen.html +0 -0
.gitignore
CHANGED
|
@@ -1,81 +1,82 @@
|
|
| 1 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 2 |
-
# ํ๊ฒฝ๋ณ์ / ์ํฌ๋ฆฟ
|
| 3 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 4 |
-
.env
|
| 5 |
-
.env.*
|
| 6 |
-
!.env.example
|
| 7 |
-
|
| 8 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 9 |
-
# Python ๊ฐ์ํ๊ฒฝ
|
| 10 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 11 |
-
.venv/
|
| 12 |
-
venv/
|
| 13 |
-
env/
|
| 14 |
-
__pycache__/
|
| 15 |
-
*.py[cod]
|
| 16 |
-
*.pyo
|
| 17 |
-
*.pyd
|
| 18 |
-
*.egg-info/
|
| 19 |
-
dist/
|
| 20 |
-
build/
|
| 21 |
-
|
| 22 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 23 |
-
# Jupyter Notebook ์ฒดํฌํฌ์ธํธ
|
| 24 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 25 |
-
.ipynb_checkpoints/
|
| 26 |
-
*/.ipynb_checkpoints/
|
| 27 |
-
|
| 28 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 29 |
-
# ์์ง ๊ฒฐ๊ณผ ๋ฐ์ดํฐ (์์
, CSV)
|
| 30 |
-
# ํฌ๋กค๋ง ๊ฒฐ๊ณผ๋ git์ผ๋ก ๊ด๋ฆฌํ์ง ์์
|
| 31 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 32 |
-
Articles_*.xlsx
|
| 33 |
-
Articles_*.csv
|
| 34 |
-
*.xlsx
|
| 35 |
-
*.csv
|
| 36 |
-
|
| 37 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 38 |
-
# macOS ์์คํ
ํ์ผ
|
| 39 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 40 |
-
.DS_Store
|
| 41 |
-
.AppleDouble
|
| 42 |
-
.LSOverride
|
| 43 |
-
|
| 44 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 45 |
-
# IDE / ์๋ํฐ ์ค์
|
| 46 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 47 |
-
.vscode/
|
| 48 |
-
.idea/
|
| 49 |
-
.*_cache/
|
| 50 |
-
*.swp
|
| 51 |
-
*.swo
|
| 52 |
-
|
| 53 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 54 |
-
# ๋ก๊ทธ / ์์ ํ์ผ
|
| 55 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 56 |
-
*.log
|
| 57 |
-
*.tmp
|
| 58 |
-
*.bak
|
| 59 |
-
*.pyc
|
| 60 |
-
|
| 61 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 62 |
-
# ์์ ํจ์น ์คํฌ๋ฆฝํธ (์์
ํ ์ญ์ ํด์ผ ํ ํ์ผ๋ค)
|
| 63 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 64 |
-
patch_*.py
|
| 65 |
-
add_viz_cell.py
|
| 66 |
-
create_fingraph.py
|
| 67 |
-
rebuild_*.py
|
| 68 |
-
sync_*.py
|
| 69 |
-
modify_*.py
|
| 70 |
-
force_write_*.py
|
| 71 |
-
|
| 72 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 73 |
-
# ์ฐธ๊ณ ์๋ฃ
|
| 74 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 75 |
-
references
|
| 76 |
-
|
| 77 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 78 |
-
# ๋ก์ปฌ ๊ทธ๋ํ ๋ฐฑ์
๋ฐ์ดํฐ (๋ณด์/์ฉ๋ ์ฌ์ ๋ก ์ ์ธ)
|
| 79 |
-
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 80 |
-
graph_backup.json
|
| 81 |
-
artifacts/
|
|
|
|
|
|
| 1 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 2 |
+
# ํ๊ฒฝ๋ณ์ / ์ํฌ๋ฆฟ
|
| 3 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 4 |
+
.env
|
| 5 |
+
.env.*
|
| 6 |
+
!.env.example
|
| 7 |
+
|
| 8 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 9 |
+
# Python ๊ฐ์ํ๊ฒฝ
|
| 10 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 11 |
+
.venv/
|
| 12 |
+
venv/
|
| 13 |
+
env/
|
| 14 |
+
__pycache__/
|
| 15 |
+
*.py[cod]
|
| 16 |
+
*.pyo
|
| 17 |
+
*.pyd
|
| 18 |
+
*.egg-info/
|
| 19 |
+
dist/
|
| 20 |
+
build/
|
| 21 |
+
|
| 22 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 23 |
+
# Jupyter Notebook ์ฒดํฌํฌ์ธํธ
|
| 24 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 25 |
+
.ipynb_checkpoints/
|
| 26 |
+
*/.ipynb_checkpoints/
|
| 27 |
+
|
| 28 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 29 |
+
# ์์ง ๊ฒฐ๊ณผ ๋ฐ์ดํฐ (์์
, CSV)
|
| 30 |
+
# ํฌ๋กค๋ง ๊ฒฐ๊ณผ๋ git์ผ๋ก ๊ด๋ฆฌํ์ง ์์
|
| 31 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 32 |
+
Articles_*.xlsx
|
| 33 |
+
Articles_*.csv
|
| 34 |
+
*.xlsx
|
| 35 |
+
*.csv
|
| 36 |
+
|
| 37 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ๏ฟฝ๏ฟฝ๏ฟฝโโโโโโโโโ
|
| 38 |
+
# macOS ์์คํ
ํ์ผ
|
| 39 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 40 |
+
.DS_Store
|
| 41 |
+
.AppleDouble
|
| 42 |
+
.LSOverride
|
| 43 |
+
|
| 44 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 45 |
+
# IDE / ์๋ํฐ ์ค์
|
| 46 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 47 |
+
.vscode/
|
| 48 |
+
.idea/
|
| 49 |
+
.*_cache/
|
| 50 |
+
*.swp
|
| 51 |
+
*.swo
|
| 52 |
+
|
| 53 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 54 |
+
# ๋ก๊ทธ / ์์ ํ์ผ
|
| 55 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 56 |
+
*.log
|
| 57 |
+
*.tmp
|
| 58 |
+
*.bak
|
| 59 |
+
*.pyc
|
| 60 |
+
|
| 61 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 62 |
+
# ์์ ํจ์น ์คํฌ๋ฆฝํธ (์์
ํ ์ญ์ ํด์ผ ํ ํ์ผ๋ค)
|
| 63 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 64 |
+
patch_*.py
|
| 65 |
+
add_viz_cell.py
|
| 66 |
+
create_fingraph.py
|
| 67 |
+
rebuild_*.py
|
| 68 |
+
sync_*.py
|
| 69 |
+
modify_*.py
|
| 70 |
+
force_write_*.py
|
| 71 |
+
|
| 72 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 73 |
+
# ์ฐธ๊ณ ์๋ฃ
|
| 74 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 75 |
+
references
|
| 76 |
+
|
| 77 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 78 |
+
# ๋ก์ปฌ ๊ทธ๋ํ ๋ฐฑ์
๋ฐ์ดํฐ (๋ณด์/์ฉ๋ ์ฌ์ ๋ก ์ ์ธ)
|
| 79 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 80 |
+
graph_backup.json
|
| 81 |
+
artifacts/
|
| 82 |
+
keyword_frequencies.png
|
AGENTS.md
CHANGED
|
@@ -184,3 +184,12 @@ def test_4_core_scenarios():
|
|
| 184 |
5. **์ ์ฌ ๋ก๊ทธ์ ๊ด๊ณ ์ ๋ฐ ๊ฒฝ๊ณ ํ์**: ๊ธฐ์ฌ๋น ์ํฐํฐ ์/๊ด๊ณ ์๋ฅผ ๋ช
์ ์ถ๋ ฅ, ๊ด๊ณ 0๊ฐ์ธ ๊ฒฝ์ฐ โ ๏ธ ๊ฒฝ๊ณ ๋
ธ์ถ.
|
| 185 |
6. **`smoke_test_rag.py` ๊ด๊ณ ์ฐ๊ฒฐ์ฑ ์ฌ์ธต ๊ฒ์ฆ ์ถ๊ฐ**: 6์ข
๊ด๊ณ ์ ํ๋ณ ์นด์ดํธ, ๊ณ ๋ฆฝ ๋
ธ๋ ๋น์จ, ๊ธฐ์ฌ๋น ํ๊ท ๊ด๊ณ ์ ์๋ ์ ๊ฒ ๋ฐ ์๊ณ๊ฐ(3.0๊ฐ) ํ์ .
|
| 186 |
- **๊ฒ์ฆ**: `ruff`, `mypy` ๋ฌด๊ฒฐ์ ํต๊ณผ. ํ์ฌ ๊ทธ๋ํ ์ํ: DEVELOPS 69๊ฐ/APPLIES 102๊ฐ/์ ์ฒด ์ํฐํฐ ๊ด๊ณ 401๊ฐ(๊ธฐ์ฌ๋น 5.6๊ฐ). ๊ด๊ณ ์ฌ์ ์ฌ ํ์ดํ๋ผ์ธ ์ฌ์คํ ์์ .
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
5. **์ ์ฌ ๋ก๊ทธ์ ๊ด๊ณ ์ ๋ฐ ๊ฒฝ๊ณ ํ์**: ๊ธฐ์ฌ๋น ์ํฐํฐ ์/๊ด๊ณ ์๋ฅผ ๋ช
์ ์ถ๋ ฅ, ๊ด๊ณ 0๊ฐ์ธ ๊ฒฝ์ฐ โ ๏ธ ๊ฒฝ๊ณ ๋
ธ์ถ.
|
| 185 |
6. **`smoke_test_rag.py` ๊ด๊ณ ์ฐ๊ฒฐ์ฑ ์ฌ์ธต ๊ฒ์ฆ ์ถ๊ฐ**: 6์ข
๊ด๊ณ ์ ํ๋ณ ์นด์ดํธ, ๊ณ ๋ฆฝ ๋
ธ๋ ๋น์จ, ๊ธฐ์ฌ๋น ํ๊ท ๊ด๊ณ ์ ์๋ ์ ๊ฒ ๋ฐ ์๊ณ๊ฐ(3.0๊ฐ) ํ์ .
|
| 186 |
- **๊ฒ์ฆ**: `ruff`, `mypy` ๋ฌด๊ฒฐ์ ํต๊ณผ. ํ์ฌ ๊ทธ๋ํ ์ํ: DEVELOPS 69๊ฐ/APPLIES 102๊ฐ/์ ์ฒด ์ํฐํฐ ๊ด๊ณ 401๊ฐ(๊ธฐ์ฌ๋น 5.6๊ฐ). ๊ด๊ณ ์ฌ์ ์ฌ ํ์ดํ๋ผ์ธ ์ฌ์คํ ์์ .
|
| 187 |
+
|
| 188 |
+
- [x] **๋ฌด๊ฒฐ์ฑ, ๋ณด์ ๋ฐ ์ ์๊ถ ์ฌ์ธต ๊ฒ์ฌ ํต๊ณผ ๋ฐ Git ์๊ฒฉ ๋ฐฐํฌ ์๋ฃ (2026-05-20)**:
|
| 189 |
+
- **ํ์**: ์๊ฒฉ ๋ฐฐํฌ ์ ์ฝ๋์ ์ ๋ฐ์ ์ธ ๊ตฌ๋ ์์ ์ฑ(๋ฌด๊ฒฐ์ฑ), ์ํฌ๋ฆฟ ๋
ธ์ถ ์ํ(๋ณด์), ๋ผ์ด์ ์ค ์ถฉ๋ ๋ฐ ๊ถ๋ฆฌ ์ฃผ์ฒด(์ ์๊ถ)์ ๋ํ ๊ณต์ธ ๊ฒ์ฆ ์ํ ํ์.
|
| 190 |
+
- **์กฐ์น**:
|
| 191 |
+
1. **๋ฌด๊ฒฐ์ฑ ๊ฒ์ฌ(Integrity)**: `ruff check`์ `mypy` ์ ์ ํ์
๊ฒ์ฌ๋ฅผ ์คํํ์ฌ ์ ๊ท ์คํฌ๋ฆฝํธ ์คํ์ผ ์ค๋ฅ ๋ฐ ๊ฒฝ๊ณ 0๊ฑด์ผ๋ก ํต๊ณผํจ. `pytest tests/` ๋จ์ ํ
์คํธ(2/2 Passed) ๋ฐ `tests/smoke_test_rag.py` 4๋ ๊ณจ๋ ์๋๋ฆฌ์ค ํตํฉ ํ
์คํธ(4/4 Passed)๋ฅผ ์์ ํต๊ณผํจ์ผ๋ก์จ RAG ์ฟผ๋ฆฌ ์ ํ์ฑ๊ณผ ๊ทธ๋ํ ๋ฐ๋๋ฅผ ์๋ฒฝํ ๊ฒ์ฆํจ. `python -c "import app"`์ผ๋ก Gradio ๋น๋ ๋ฐ ์๊ฐ ์ง๋จ ํต๊ณผ ํ์ธ.
|
| 192 |
+
2. **๋ณด์ ๊ฒ์ฌ(Security)**: `bandit` ๋ณด์ ์ทจ์ฝ์ ๋ถ์๊ธฐ๋ฅผ ์ด์ฉํด ์์ค ์ฝ๋ ์ ๋ฐ์ ๋ณด์ ์ํ์ ํ์ํ์ฌ High/Medium ๋ฑ๊ธ ์ทจ์ฝ์ 0๊ฑด ๊ฒ์ฆ ์๋ฃ. `.gitignore`์ `.env`, `Articles_*.xlsx`๋ฅผ ์์ ์ฐจ๋จํ์ฌ ์ํฌ๋ฆฟ ํค ๋ฐ ๊ธฐ์ฌ ๋ฐ์ดํฐ ์ ์ถ ๊ฐ๋ฅ์ฑ์ ์์ฒ ์ ๊ฑฐํจ.
|
| 193 |
+
3. **์ ์๊ถ ๊ฒ์ฌ(Copyright)**: ์์กด์ฑ ํจํค์ง๋ค์ ๋ผ์ด์ ์ค๋ฅผ ์ ์ ๋ถ์ํ์ฌ ๋ชจ๋ Apache 2.0, MIT, BSD ๋ฑ ํ์ฉ์ ๋ผ์ด์ ์ค์์ ํ์ธํ์ฌ ๋ฒ์ ์ํ 0% ๋ณด์ฅ. ๋ฃจํธ์ MIT `LICENSE` ํ์ผ์ ์ ์ ๋ฐฐํฌํ๊ณ , `delete_zero_rel_articles.py`, `plot_keywords.py` ๋ฑ ์ ๊ท ์ ํธ๋ฆฌํฐ ํ์ผ์ ํ๊ธ ์ค๋ช
์ฃผ์ ๋ฐ ์ ์๊ถ ๋ช
์ ํค๋๋ฅผ ์๋ฒฝ ์ ์ฉํจ.
|
| 194 |
+
4. **Git ์
๋ก๋**: ๋ชจ๋ ์๊ฑด์ ๊ฐ์ถ ์ฝ๋๋ฅผ ์ต์ข
์คํ
์ด์งํ๊ณ ์์ด ์งง์ ์ปค๋ฐ ๋ฉ์์ง ๊ท์น ์ค์ ํ `origin/main`์ผ๋ก ์ต์ข
Push ์๋ฃ.
|
| 195 |
+
5. **UI ๋์์ธ ํผ๋๋ฐฑ ๋ฐ์**: ์ธ๋ถ๋ก ๋์ถ๋์ด ์ฑํ
์ฐฝ ์์ญ์ ์นจ๋ฒํ๋ ์ฐ์ธก ์ค๋ช
HTML์ ์ ๊ฑฐํ๊ณ ์ฑ๋ด ๋ด๋ถ์ placeholder ์์ญ์ผ๋ก ์๋ณตํ์์ผ๋ฉฐ, ๋์๋ณด๋์ ์ฑํ
์ฐฝ์ ๊ณจ๋ ํ๋ฉด ๋น์จ(3:7 split)์ ์๋ฒฝํ๊ฒ ๋ณต๊ตฌํจ.
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2026 yujetak / FinGraph Contributors
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
app.py
CHANGED
|
@@ -326,7 +326,7 @@ CHATBOT_DESCRIPTION = """
|
|
| 326 |
|
| 327 |
interface_kwargs = {
|
| 328 |
"fn": chat,
|
| 329 |
-
"chatbot": gr.Chatbot(height=
|
| 330 |
"textbox": gr.Textbox(
|
| 331 |
placeholder="๋ถ์ํ๊ณ ์ถ์ ๋ด์ฉ์ ์์ฐ์ด๋ก ์
๋ ฅํด์ฃผ์ธ์...",
|
| 332 |
container=False,
|
|
@@ -374,17 +374,14 @@ with gr.Blocks(**blocks_kwargs) as demo:
|
|
| 374 |
""")
|
| 375 |
|
| 376 |
with gr.Row():
|
| 377 |
-
# 2. ์ผ์ชฝ ์ปฌ๋ผ: ์ฌ์ด๋๋ฐ (๋์๋ณด๋ ๋ฐ ํ๋จ ๋ฉ๋ด) -
|
| 378 |
-
with gr.Column(scale=
|
| 379 |
stats_data = get_db_stats()
|
| 380 |
stats_html = build_stats_html(stats_data)
|
| 381 |
gr.HTML(stats_html)
|
| 382 |
|
| 383 |
-
# 3. ์ค๋ฅธ์ชฝ ์ปฌ๋ผ: ๋ฉ์ธ ์ฑ๋ด ์์ด๋ฆฌ์ด -
|
| 384 |
-
with gr.Column(scale=
|
| 385 |
-
# ์ฐ์ธก ์ค๋ช
์์ญ ๋ณต๊ตฌ (Chatbot placeholder ๋์ HTML๋ก ์ง์ ๋ ๋๋ง)
|
| 386 |
-
gr.HTML(CHATBOT_DESCRIPTION)
|
| 387 |
-
|
| 388 |
# ChatInterface without redundant titles/descriptions
|
| 389 |
chatbot_interface_kwargs = interface_kwargs.copy()
|
| 390 |
chatbot_interface_kwargs.pop("title", None)
|
|
|
|
| 326 |
|
| 327 |
interface_kwargs = {
|
| 328 |
"fn": chat,
|
| 329 |
+
"chatbot": gr.Chatbot(height=700, placeholder=CHATBOT_DESCRIPTION),
|
| 330 |
"textbox": gr.Textbox(
|
| 331 |
placeholder="๋ถ์ํ๊ณ ์ถ์ ๋ด์ฉ์ ์์ฐ์ด๋ก ์
๋ ฅํด์ฃผ์ธ์...",
|
| 332 |
container=False,
|
|
|
|
| 374 |
""")
|
| 375 |
|
| 376 |
with gr.Row():
|
| 377 |
+
# 2. ์ผ์ชฝ ์ปฌ๋ผ: ์ฌ์ด๋๋ฐ (๋์๋ณด๋ ๋ฐ ํ๋จ ๋ฉ๋ด) - 3:7 split์ ์ํด scale=3 ์ค์
|
| 378 |
+
with gr.Column(scale=3, min_width=320):
|
| 379 |
stats_data = get_db_stats()
|
| 380 |
stats_html = build_stats_html(stats_data)
|
| 381 |
gr.HTML(stats_html)
|
| 382 |
|
| 383 |
+
# 3. ์ค๋ฅธ์ชฝ ์ปฌ๋ผ: ๋ฉ์ธ ์ฑ๋ด ์์ด๋ฆฌ์ด - 3:7 split์ ์ํด scale=7 ์ค์
|
| 384 |
+
with gr.Column(scale=7, min_width=500):
|
|
|
|
|
|
|
|
|
|
| 385 |
# ChatInterface without redundant titles/descriptions
|
| 386 |
chatbot_interface_kwargs = interface_kwargs.copy()
|
| 387 |
chatbot_interface_kwargs.pop("title", None)
|
delete_zero_rel_articles.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""
|
| 3 |
+
FinGraph ์ง์ ๊ทธ๋ํ ๋ฌด๊ฒฐ์ฑ ๊ด๋ฆฌ ์ ํธ๋ฆฌํฐ
|
| 4 |
+
- ์ ์๊ถ: (c) 2026 yujetak / FinGraph Contributors (MIT License)
|
| 5 |
+
- ์ญํ : ์ง์ ์ ์ธ ์ํฐํฐ ๊ฐ ๊ด๊ณ์ (DEVELOPS, APPLIES ๋ฑ)์ด 0๊ฐ์ธ ๊ณ ๋ฆฝ ๊ธฐ์ฌ ๋
ธ๋๋ฅผ ํ์ํ๊ณ ์ ๊ฑฐํ์ฌ
|
| 6 |
+
๊ทธ๋ํ์ ์ฐ๊ฒฐ ๋ฐ๋์ RAG ๊ฒ์ ๋ฌด๊ฒฐ์ฑ์ ๋์
๋๋ค.
|
| 7 |
+
"""
|
| 8 |
+
import os
|
| 9 |
+
|
| 10 |
+
import dotenv
|
| 11 |
+
import neo4j
|
| 12 |
+
|
| 13 |
+
dotenv.load_dotenv()
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def get_neo4j_driver() -> neo4j.Driver:
|
| 17 |
+
uri = os.getenv("NEO4J_URI", "neo4j://localhost:7687")
|
| 18 |
+
client_id = os.getenv("NEO4J_CLIENT_ID")
|
| 19 |
+
client_secret = os.getenv("NEO4J_CLIENT_SECRET")
|
| 20 |
+
|
| 21 |
+
if client_id and client_secret:
|
| 22 |
+
try:
|
| 23 |
+
d = neo4j.GraphDatabase.driver(uri, auth=(client_id, client_secret))
|
| 24 |
+
d.verify_connectivity()
|
| 25 |
+
return d
|
| 26 |
+
except Exception:
|
| 27 |
+
pass
|
| 28 |
+
|
| 29 |
+
username = os.getenv("NEO4J_USERNAME", "neo4j")
|
| 30 |
+
password = os.getenv("NEO4J_PASSWORD", "password")
|
| 31 |
+
d = neo4j.GraphDatabase.driver(uri, auth=(username, password))
|
| 32 |
+
d.verify_connectivity()
|
| 33 |
+
return d
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
if __name__ == "__main__":
|
| 37 |
+
driver = get_neo4j_driver()
|
| 38 |
+
with driver.session() as s:
|
| 39 |
+
res = s.run('''
|
| 40 |
+
MATCH (a:Article)
|
| 41 |
+
OPTIONAL MATCH (a)-[:MENTIONS]->(n)
|
| 42 |
+
OPTIONAL MATCH (n)-[r:DEVELOPS|INVESTS_IN|PARTNERS_WITH|APPLIES|USED_IN|RELATED_TO]-()
|
| 43 |
+
WITH a, count(r) as rel_cnt
|
| 44 |
+
WHERE rel_cnt = 0
|
| 45 |
+
DETACH DELETE a
|
| 46 |
+
RETURN count(a) as deleted_count
|
| 47 |
+
''')
|
| 48 |
+
record = res.single()
|
| 49 |
+
if record:
|
| 50 |
+
print(f'Deleted articles with 0 relations: {record["deleted_count"]}')
|
| 51 |
+
driver.close()
|
| 52 |
+
|
plot_keywords.py
CHANGED
|
@@ -1,21 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import os
|
|
|
|
| 2 |
import dotenv
|
|
|
|
| 3 |
import neo4j
|
| 4 |
import pandas as pd
|
| 5 |
-
import matplotlib.pyplot as plt
|
| 6 |
-
import matplotlib.font_manager as fm
|
| 7 |
|
| 8 |
dotenv.load_dotenv()
|
| 9 |
|
|
|
|
| 10 |
# Windows ํ๊ฒฝ ํ๊ธ ํฐํธ ์ค์
|
| 11 |
plt.rc('font', family='Malgun Gothic')
|
| 12 |
plt.rcParams['axes.unicode_minus'] = False
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
def create_keyword_plot():
|
| 15 |
-
driver =
|
| 16 |
-
os.getenv('NEO4J_URI'),
|
| 17 |
-
auth=(os.getenv('NEO4J_USERNAME'), os.getenv('NEO4J_PASSWORD'))
|
| 18 |
-
)
|
| 19 |
|
| 20 |
query = """
|
| 21 |
MATCH (a:Article)-[:MENTIONS]->(n)
|
|
@@ -48,7 +74,7 @@ def create_keyword_plot():
|
|
| 48 |
# ๋ง๋ ์์ ์์น ํ
์คํธ ํ์
|
| 49 |
for bar in bars:
|
| 50 |
width = bar.get_width()
|
| 51 |
-
plt.text(width + 0.1, bar.get_y() + bar.get_height()/2, f'{int(width)}',
|
| 52 |
ha='left', va='center', fontsize=10)
|
| 53 |
|
| 54 |
plt.tight_layout()
|
|
@@ -56,5 +82,6 @@ def create_keyword_plot():
|
|
| 56 |
plt.savefig(output_path, dpi=300, bbox_inches='tight')
|
| 57 |
print(f"Graph successfully saved to {output_path}")
|
| 58 |
|
|
|
|
| 59 |
if __name__ == "__main__":
|
| 60 |
create_keyword_plot()
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""
|
| 3 |
+
FinGraph ํค์๋ ์๊ฐํ ์ ํธ๋ฆฌํฐ
|
| 4 |
+
- ์ ์๊ถ: (c) 2026 yujetak / FinGraph Contributors (MIT License)
|
| 5 |
+
- ์ญํ : ์์ง๋ ์ ์ฒด ๋ด์ค ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ด AI ๊ด๋ จ ์ฃผ์ ํค์๋(๊ธฐ์
/๊ธฐ์ /์๋น์ค)์ ์ถํ ๋น๋๋ฅผ ๋ถ์ํ์ฌ
|
| 6 |
+
์ข์ธก ๋์๋ณด๋ ํ๋ฉด์ ์ ์ฌํ ๊ณ ํ์ง ๋ง๋๊ทธ๋ํ ์ด๋ฏธ์ง(keyword_frequencies.png)๋ฅผ ์์ฑํฉ๋๋ค.
|
| 7 |
+
"""
|
| 8 |
import os
|
| 9 |
+
|
| 10 |
import dotenv
|
| 11 |
+
import matplotlib.pyplot as plt
|
| 12 |
import neo4j
|
| 13 |
import pandas as pd
|
|
|
|
|
|
|
| 14 |
|
| 15 |
dotenv.load_dotenv()
|
| 16 |
|
| 17 |
+
|
| 18 |
# Windows ํ๊ฒฝ ํ๊ธ ํฐํธ ์ค์
|
| 19 |
plt.rc('font', family='Malgun Gothic')
|
| 20 |
plt.rcParams['axes.unicode_minus'] = False
|
| 21 |
|
| 22 |
+
|
| 23 |
+
def get_neo4j_driver() -> neo4j.Driver:
|
| 24 |
+
uri = os.getenv("NEO4J_URI", "neo4j://localhost:7687")
|
| 25 |
+
client_id = os.getenv("NEO4J_CLIENT_ID")
|
| 26 |
+
client_secret = os.getenv("NEO4J_CLIENT_SECRET")
|
| 27 |
+
|
| 28 |
+
if client_id and client_secret:
|
| 29 |
+
try:
|
| 30 |
+
d = neo4j.GraphDatabase.driver(uri, auth=(client_id, client_secret))
|
| 31 |
+
d.verify_connectivity()
|
| 32 |
+
return d
|
| 33 |
+
except Exception:
|
| 34 |
+
pass
|
| 35 |
+
|
| 36 |
+
username = os.getenv("NEO4J_USERNAME", "neo4j")
|
| 37 |
+
password = os.getenv("NEO4J_PASSWORD", "password")
|
| 38 |
+
d = neo4j.GraphDatabase.driver(uri, auth=(username, password))
|
| 39 |
+
d.verify_connectivity()
|
| 40 |
+
return d
|
| 41 |
+
|
| 42 |
+
|
| 43 |
def create_keyword_plot():
|
| 44 |
+
driver = get_neo4j_driver()
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
query = """
|
| 47 |
MATCH (a:Article)-[:MENTIONS]->(n)
|
|
|
|
| 74 |
# ๋ง๋ ์์ ์์น ํ
์คํธ ํ์
|
| 75 |
for bar in bars:
|
| 76 |
width = bar.get_width()
|
| 77 |
+
plt.text(width + 0.1, bar.get_y() + bar.get_height() / 2, f'{int(width)}',
|
| 78 |
ha='left', va='center', fontsize=10)
|
| 79 |
|
| 80 |
plt.tight_layout()
|
|
|
|
| 82 |
plt.savefig(output_path, dpi=300, bbox_inches='tight')
|
| 83 |
print(f"Graph successfully saved to {output_path}")
|
| 84 |
|
| 85 |
+
|
| 86 |
if __name__ == "__main__":
|
| 87 |
create_keyword_plot()
|
stitch_screen.html
DELETED
|
File without changes
|