ilangs/AI_Math_Tutor_HF
π° AI Math Tutor β 루미μ ν¨κ»νλ μ΄λ± μν
AI Agent κ³Όμ ν νλ‘μ νΈ | 4ν μ΄λ±νκ΅ 3νλ νμμ μν AI κΈ°λ° 1:1 μν νν°λ§ μλΉμ€ LangChain Β· LangGraph Β· FastAPI Β· ChromaDB Β· OpenAI
π νλ‘μ νΈ κ°μ
μλΉμ€ μκ°
루미(Lumi)λ μ΄λ±νκ΅ 3νλ νμμ μν νμ΅μ λλ AI νν° μΊλ¦ν°μ λλ€. λ¨μ λ¬Έμ νμ΄λ₯Ό λμ΄ κ°λ μ€λͺ β μ΄ν΄λ νμΈ β λ¬Έμ νκΈ° β AI μ±μ μ μμ ν νμ΅ μ¬μ΄ν΄μ μ 곡νλ©°, RAG(Retrieval-Augmented Generation) κΈ°λ° μμ μ§λ¬Έκ³Ό μν κΈ°λ₯, μ±μ λμ보λκΉμ§ κ°μΆ μ’ ν© νμ΅ νλ«νΌμ λλ€.
β¨ μ£Όμ κΈ°λ₯
1. μ€λμ νμ΅ (λ¨κ³λ³ νμ΅ μ¬μ΄ν΄)
λ¨μ μ ν β AI κ°λ
μ€λͺ
β μ΄ν΄λ νκ° β λ¬Έμ νκΈ° β AI μ±μ - λ¨μ μ ν: CSV λ°μ΄ν°μ μμ μΆμΆν μ€μ 3νλ μν λ¨μ λͺ©λ‘ μ 곡
- AI κ°λ μ€λͺ : OpenAIκ° λ£¨λ―Έ μΊλ¦ν°λ‘ ν΄λΉ λ¨μ κ°λ μ μ΄λ±νμ λλμ΄μ λ§κ² μ€λͺ
- 보좩 μ€λͺ : "λ€μ μ€λͺ ν΄μ€" λ²νΌμΌλ‘ λ μ¬μ΄ μΆκ° μ€λͺ μμ² κ°λ₯
- μ΄ν΄λ νκ°: νμμ΄ μμ μ λ§λ‘ κ°λ μ μ€λͺ νλ©΄ AIκ° [PASS] / [FAIL] νμ + κ²©λ € νΌλλ°± μ 곡
- λ¬Έμ νκΈ°: μ ν λ¨μμμ 무μμ λ¬Έμ 1κ° μΆμ
- AI μ±μ : νμ λ΅λ³μ OpenAIκ° μ±μ νκ³ [μ λ΅] / [μ€λ΅] + μμΈ νμ΄ νΌλλ°± μ 곡
- TTS μμ±: OpenAI TTS(nova λͺ©μ리)λ‘ κ°λ μ€λͺ κ³Ό νΌλλ°±μ μμ±μΌλ‘ μ¬μ
2. AI μμ νμ΅ μ±ν (RAG + LLM)
νμ μ§λ¬Έ μ
λ ₯ β μν μ§λ¬Έ λΆλ₯ β ChromaDB RAG κ²μ β OpenAI λ§μΆ€ λ΅λ³- μ ν΄μ§ λ¨μ μμ΄ μμ λ‘κ² μν κ΄λ ¨ μ§λ¬Έ κ°λ₯
- μν μ§λ¬Έ νν°λ§: LLMμ΄ λ¨Όμ μν κ΄λ ¨ μ§λ¬ΈμΈμ§ λΆλ₯ (λΉκ΄λ ¨ μ§λ¬Έ μ°¨λ¨)
- RAG κΈ°λ° λ΅λ³: ChromaDBμμ μλ―Έμ μΌλ‘ μ μ¬ν κΈ°μΆ λ¬Έμ Β·νμ΄λ₯Ό κ²μνμ¬ λ§₯λ½ μλ ννΈ μ 곡
- λν κΈ°λ‘ μ μ§: μ΄μ λν 컨ν μ€νΈλ₯Ό ν¬ν¨νμ¬ μ°μ μ§λ¬Έ κ°λ₯
- μ±ν κΈ°λ‘ μ μ₯: λν λ΄μ©μ΄ DBμ μ μ₯λμ΄ μ¬μ μ μ μ΄μ λν 볡μ
3. λ¨μ μν (μλ μΆμ β μ±μ β κ²°κ³Ό μ μ₯)
λ¨μ μ ν β 10λ¬Έμ μλ μΆμ β μΌκ΄ μ μΆ β AI λ³λ ¬ μ±μ β κ²°κ³Ό μ μ₯- μλ μΆμ : μ ν λ¨μμμ 10λ¬Έμ λ₯Ό 무μμλ‘ μΆμΆ (CSV μ§μ μ‘°ν)
- μΌκ΄ μ±μ :
asyncio.gather()λ‘ 10λ¬Έμ λ₯Ό λ³λ ¬ μ²λ¦¬νμ¬ μ±μ μλ μ΅μ ν - κ²°κ³Ό μ μ₯: μ μ, μ€λ΅ λ²νΈ, AI νΌλλ°±μ DBμ μ μ₯
- μν μ΄λ ₯ μ‘°ν: μ±μ λμ보λμμ κ³Όκ±° μν μ΄λ ₯ νμΈ κ°λ₯
4. μ±μ λμ보λ (νμ΅ μ΄λ ₯ Β· μ λ΅λ₯ )
- νμ΅ μ΄λ ₯: μ€λμ νμ΅μμ νΌ λ¬Έμ κΈ°λ‘ (λ¨μ, μ μ€λ΅, μΌμ)
- μ λ΅λ₯ ν΅κ³: μ 체 νμ΅ κΈ°λ‘ κΈ°λ° μ λ΅λ₯ (%) κ³μ° λ° μκ°ν
- μν μ΄λ ₯: λ¨μλ³ μν μ μ μΆμ΄ λ° κ³Όκ±° μν κ²°κ³Ό λͺ©λ‘
5. ν ν° μ¬μ© λ‘κ·Έ (LLM API λΉμ© μΆμ )
- μ€μκ° κΈ°λ‘: LLM νΈμΆλ§λ€
get_openai_callback()μΌλ‘ ν ν° μΒ·λΉμ©μ μΊ‘μ² - λ‘컬 DB μ μ₯: LangSmith μμ‘΄ μμ΄ λ‘컬 SQLite(
token_logsν μ΄λΈ)μ μ μ₯ - κΈ°λ₯λ³ λΆλ₯: κ°λ μ€λͺ / μ΄ν΄λνκ° / μ±μ / Q&A / AIμμ νμ΅ / μνμ±μ λ± actionλ³ μ§κ³
- λΉμ© νμ°: ν둬ννΈΒ·μ»΄ν리μ ν ν°μ λ¬λ¬($) λ° μν(β©)λ‘ νμ°νμ¬ νμ
ποΈ μμ€ν μν€ν μ²
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Frontend (HTML / JS) β
β login.html Β· app.html Β· section1~5.js β
β - λ‘κ·ΈμΈ/νμκ°μ
UI β
β - μΉμ
λ³ κΈ°λ₯ νλ©΄ (νμ΅/μ±ν
/μν/λμ보λ/ν ν°λ‘κ·Έ) β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β HTTP fetch (JWT Bearer Token)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FastAPI Server (server.py) β
β β
β /auth/* β routers/auth.py (λ‘κ·ΈμΈΒ·νμκ°μ
Β·JWT λ°κΈ) β
β /api/* β routers/tutor.py (AI νν° κΈ°λ₯ μ 체) β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Service Layer (app/services/tutor_service.py) β
β λΉμ¦λμ€ λ‘μ§ μ²λ¦¬ β
ββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LangChain Integration (app/tutor/integration.py) β
β β
β explain_chain Β· reexplain_chain Β· concept_chain β
β answer_chain Β· rag_chain Β· classify_chain β
β generate_speech_with_cache (TTS + MD5 μΊμ±) β
ββββββββββ¬ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββ ββββββββββββββββββββββββββββββββββββββ
β OpenAI OpenAI β β Two-Track λ°μ΄ν° μ‘°ν β
β (LLM + TTS) β β β
β β β Track 1: CSV / SQLite μ§μ μ‘°ν β
β text-embedding β β - μ€λμ νμ΅ (μ νν λ¨μ νν°λ§) β
β -3-small β β - λ¨μ μν (무μμ 10λ¬Έμ μΆμΆ) β
β (RAG Embed) β β β
βββββββββββββββββββ β Track 2: ChromaDB RAG κ²μ β
β - AI μμ νμ΅ μ±ν
β
β - μ맨ν±(μλ―Έ) μ μ¬λ κ²μ β
ββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Data Layer β
β database/user_db.sqlite - μ¬μ©μΒ·νμ΅Β·μνΒ·μ±ν
Β·ν ν° λ‘κ·Έ β
β database/vector_store/ - ChromaDB λ²‘ν° μΈλ±μ€ β
β data/processed/*.csv - μν λ¬Έμ λ°μ΄ν°μ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββTwo-Track λ°μ΄ν° μ‘°ν ꡬ쑰
μ€μ AI κ΅μ‘ μλΉμ€μμλ μ¬μ©νλ μμ μ μΈ νμ΄λΈλ¦¬λ μν€ν μ²μ λλ€.
π οΈ κΈ°μ μ€ν
π λ°μ΄ν° νμ΄νλΌμΈ (RAG κ΅¬μΆ 4λ¨κ³)
μλ³Έ ZIP (JSON νμΌλ€)
β
βΌ
[1λ¨κ³] collect_data_tutor.py
- ZIP λ΄λΆ JSON μν β OCR ν
μ€νΈ μΆμΆ
- λ¬Έμ (question) : μ λ΅(answer) 1:1 λ§€μΉ
- μΆλ ₯: μ΄κΈ° ν΅ν© CSV (νμ΄λ°μ λ΅ μ»¬λΌ)
β
βΌ
[2λ¨κ³] csv_refiner.py
- OpenAIλ‘ λ°μ΄ν° μ μ
- 'νμ΄λ°μ λ΅' β 'μ λ΅' + 'μΉμ ν νμ΄' μ»¬λΌ λΆλ¦¬
- μ΄λ±νμ λλμ΄ μΈμ΄λ‘ λ³ν
- μΆλ ₯: μ΅μ’
νμ΅μ© CSV (math_tutor_dataset.csv)
β
βΌ
[3λ¨κ³] rag_helper.py
- μλ² λ© λͺ¨λΈ μ€μ (text-embedding-3-small)
- ChromaDB μ°κ²° λ° λ°°μΉ(Batch) μ μ₯ λꡬ μ μ
- RAG κ²μ ν¨μ μ μ
β
βΌ
[4λ¨κ³] build_vector_db.py β μ€ν μ§μ
μ
- python build_vector_db.py λͺ
λ ΉμΌλ‘ μ€ν
- CSV μ½κΈ° β rag_helper νΈμΆ β ChromaDB λ²‘ν° μ μ₯
- μΆλ ₯: database/vector_store/ (ChromaDB μΈλ±μ€)
β
βΌ
ChromaDB λ²‘ν° DB μμ±
(AI μμ νμ΅ μ±ν
μμ RAG κ²μμ μ¬μ©)π νλ‘μ νΈ κ΅¬μ‘°
AI_Math_Tutor_4team/
β
βββ server.py # FastAPI μ± μ§μ
μ , λ―Έλ€μ¨μ΄Β·λΌμ°ν° λ±λ‘
βββ requirements.txt # Python ν¨ν€μ§ μμ‘΄μ± λͺ©λ‘
βββ .env # νκ²½λ³μ (API ν€, JWT μν¬λ¦Ώ λ±)
β
βββ app/ # λ°±μλ μ ν리μΌμ΄μ
μ½μ΄
β βββ routers/
β β βββ auth.py # λ‘κ·ΈμΈΒ·νμκ°μ
Β·JWT λ°κΈ API (/auth/*)
β β βββ tutor.py # AI νν° κΈ°λ₯ μ 체 API (/api/*)
β βββ services/
β β βββ tutor_service.py # λΉμ¦λμ€ λ‘μ§ (LLM νΈμΆ μ‘°μ¨)
β βββ tutor/
β β βββ integration.py # LangChain μ²΄μΈ μ μ, TTS μΊμ±
β βββ utils/
β βββ db_manager.py # SQLite CRUD, bcrypt λΉλ°λ²νΈ κ΄λ¦¬
β
βββ frontend/ # νλ‘ νΈμλ μ μ νμΌ
β βββ login.html # λ‘κ·ΈμΈΒ·νμκ°μ
νλ©΄
β βββ app.html # λ©μΈ μ± νλ©΄ (λ‘κ·ΈμΈ ν)
β βββ js/
β β βββ app.js # κ³΅ν΅ JS (μΈμ¦, API fetch μ νΈ)
β β βββ section1.js # μ€λμ νμ΅ νλ©΄ (νμ΅ νλ¦ UI)
β β βββ section2.js # AI μμ νμ΅ μ±ν
β β βββ section3.js # μν νλ©΄ + μν κ²°κ³Ό λͺ¨λ¬ UI
β β βββ section4.js # μ±μ λ‘κ·Έ λμ보λ (κ·Έλν + μν κΈ°λ‘ UI)
β β βββ section5.js # ν ν° μ¬μ© λ‘κ·Έ
β βββ css/ # μ€νμΌμνΈ
β βββ assets/ # μ΄λ―Έμ§Β·μμ΄μ½ λ± λ―Έλμ΄ νμΌ
β
βββ RAG_sys/ # RAG λ°μ΄ν° νμ΄νλΌμΈ
β βββ collect_data_tutor.py # [1λ¨κ³] μλ³Έ λ°μ΄ν° μμ§Β·λ³ν©
β βββ csv_refiner.py # [2λ¨κ³] AI κΈ°λ° λ°μ΄ν° μ μ
β βββ rag_helper.py # [3λ¨κ³] ChromaDB μ μ₯ λͺ¨λ μ μ
β βββ build_vector_db.py # [4λ¨κ³] λ²‘ν° DB κ΅¬μΆ μ€ν μ€ν¬λ¦½νΈ
β
βββ data/
β βββ processed/
β βββ math_dataset.csv # ZIP λ΄λΆ JSON μν OCR ν
μ€νΈ μΆμΆ
β βββ math_tutor_dataset.csv # μ μ λ μ΅μ’
μν λ¬Έμ λ°μ΄ν°μ
β
βββ database/
βββ user_db.sqlite # SQLite DB (μ¬μ©μΒ·νμ΅Β·μνΒ·μ±ν
Β·ν ν°)
βββ vector_store/
βββ chroma.sqlite3 # ChromaDB λ²‘ν° μΈλ±μ€π μ£Όμ API μλν¬μΈνΈ
μΈμ¦ (Authentication)
μ€λμ νμ΅
AI μμ νμ΅ μ±ν
λ¨μ μν
κΈ°ν
λͺ¨λ/api/*μλν¬μΈνΈλAuthorization: Bearer <JWT>ν€λ νμ Swagger λ¬Έμ:http://localhost:8000/docs
π μ€ν λ°©λ²
1. μ μ₯μ ν΄λ‘
git clone https://github.com/ilangs/AI_Math_Tutor_4team2. κ°μνκ²½ μμ± λ° νμ±ν
# κ°μνκ²½ μμ±
py -3.10 -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate3. ν¨ν€μ§ μ€μΉ
pip install -r requirements.txt4. νκ²½λ³μ μ€μ
νλ‘μ νΈ λ£¨νΈμ .env νμΌμ μμ±νκ³ μλ κ°μ μ±μμ£ΌμΈμ. (μλ [νκ²½λ³μ μ€μ ] μΉμ
μ°Έκ³ )
5. μλ² μ€ν
uvicorn server:app --reload --port 80006. λΈλΌμ°μ μ μ
http://127.0.0.1:8000/βοΈ νκ²½λ³μ μ€μ
νλ‘μ νΈ λ£¨νΈμ .env νμΌμ μμ±ν©λλ€:
# ββ OpenAI API βββββββββββββββββββββββββββββββββββββββββββ
OPENAI_API_KEY="sk-..." # OpenAI API ν€ (νμ)
# ββ JWT μΈμ¦ βββββββββββββββββββββββββββββββββββββββββββββ
# μλ λͺ
λ ΉμΌλ‘ μμ±:
# python -c "import secrets; print(secrets.token_hex(32))"
JWT_SECRET_KEY="μ¬κΈ°μ_λ°κΈλ_μν¬λ¦Ώ_ν€_μ
λ ₯"μ£Όμ:.envνμΌμ μ λ gitμ 컀λ°νμ§ λ§μΈμ..gitignoreμ μΆκ°νμ¬ κ΄λ¦¬ν©λλ€.
π ν ν° μ¬μ©λ μΆμ λ°©μ
LangSmith μμ΄λ LLM API λΉμ©μ μ ννκ² μΆμ νλ λ‘컬 κΈ°λ° λ°©μμ μ±ννμ΅λλ€.
μλ μ리
# routers/tutor.py μμ LLM νΈμΆλ§λ€ μ μ©
from langchain_community.callbacks import get_openai_callback
with get_openai_callback() as cb:
result = await some_llm_function(...) # LLM νΈμΆ
# with λΈλ‘ μ’
λ£ ν cbμ ν ν° μ λ³΄κ° μλ μ§κ³λ¨
save_token_usage(
username=current_user["username"],
action="κ°λ
μ€λͺ
", # κΈ°λ₯λͺ
λΆλ₯
prompt=cb.prompt_tokens, # μ
λ ₯ ν ν° μ
completion=cb.completion_tokens, # μΆλ ₯ ν ν° μ
total=cb.total_tokens, # ν©κ³ ν ν° μ
cost=cb.total_cost, # λ¬λ¬ λΉμ©
)DB ν
μ΄λΈ ꡬ쑰 (token_logs)
λΉμ© νμ° κΈ°μ€ (OpenAI)
κΈ°μ‘΄ λ°©μ λλΉ κ°μ : LangSmith API ν λΉλ μ΄κ³Ό μ νμ 0μ΄ λ°νλλ λ¬Έμ λ₯Ό λ‘컬 SQLite μ§μ μ μ₯ λ°©μμΌλ‘ μ ννμ¬ νμ μ νν ν ν° λ°μ΄ν°λ₯Ό 보μ₯ν©λλ€.
π₯ ν ꡬμ±
π κ°λ° νκ²½
- Python 3.10
- OS Windows 11
- IDE VS Code
- API λ¬Έμ
http://localhost:8000/docs(Swagger UI μλ μμ±)
π λΌμ΄μ μ€
λ³Έ νλ‘μ νΈλ κ΅μ‘ λͺ©μ μΌλ‘ μ μλμμ΅λλ€. 3μ£Ό AI Agent κ³Όμ μ€κ° νλ‘μ νΈ κ²°κ³Όλ¬Όμ λλ€.
Hugging Face λ°°ν¬
https://huggingface.co/spaces/ilangs/AIMathTutor_HF
