κ³ κ°μ μν©μ λ°μν μλμ μ£Όλ¬Έ κ²°μ μλνλ₯Ό μ 곡νλ ν΄λ¨Όν°μΉ AI μ±μ€λ
- λ³Έ AI λ ν¬μ§ν 리λ κ³ κ° λνλ₯Ό μ΄ν΄νκ³ , μ£Όλ¬Έ λ° λ§€μ₯ μ 보 λ±μ μλ μλ΅νλ AI μ±μ€λ μλ²λ₯Ό ꡬνν μ½λμ λλ€.
- GPT-4o κΈ°λ° μμ°μ΄ μ²λ¦¬ λͺ¨λΈκ³Ό RAG ꡬ쑰λ₯Ό νμ©νμ¬ λ§€μ₯ μ 보λ₯Ό λ°μν μλλ₯Ό μ 곡νλ©°, Function CallingμΌλ‘ μ£Όλ¬Έ λ° μμ² μλνλ₯Ό μ²λ¦¬ν©λλ€.
- Redisλ₯Ό μ΄μ©ν μΈμ κ΄λ¦¬, MongoDB κΈ°λ° λ²‘ν° κ²μ, Flask κΈ°λ° REST API, EC2 + GitHub Actions κΈ°λ° CI/CD μλ λ°°ν¬ νκ²½μ ꡬμΆνμμ΅λλ€.
- Language: Python 3.10
- Framework: Flask
- LLM Model: OpenAI GPT-4o
- Embedding & RAG: LangChain + MongoDB
- Database: MongoDB, Redis
- Server ꡬμ±: Gunicorn + Nginx (HTTPS + 리λ²μ€ νλ‘μ)
- Deployment: AWS EC2 + GitHub Actions & AWS CodeDeploy κΈ°λ° CI/CD
π νλ‘μ νΈ κ΅¬μ‘°
Howkiki_AI/
βββ chatbot/ # GPT μ±μ€λ λ° RAG κ΄λ ¨ λ‘μ§
β βββ __init__.py
β βββ bot.py # μ¬μ©μ μ§λ¬Έμ μ²λ¦¬νκ³ GPT μλ΅ μμ± (Function Calling ν¬ν¨)
β βββ embedding.py # λ§€μ₯ μ 보 벑ν°ν λ° MongoDB μ μ₯
β βββ retriever.py # μ μ¬ λ¬Έμ₯ κ²μμ μν λ²‘ν° κ²μ λͺ¨λ (RAG)
βββ api/ # Flask API λΌμ°νΈ λ° μλ² κ΅¬μ±
β βββ __init__.py
β βββ routes.py # /chat λΌμ°νΈ: μ¬μ©μ μ§λ¬Έμ λ°μ GPT μλ΅ λ°ν
β βββ config.py # νκ²½ λ³μ λλ κ³ μ μ€μ μ 보 (Redis, OpenAI, MongoDB μ€μ λ±)
β βββ redis_client.py # Redis ν΄λΌμ΄μΈνΈ μ΄κΈ°ν λ° μΈμ
κΈ°λ° λν κΈ°λ‘ μ μ₯/μ‘°ν/μμ
βββ data/
β βββ housum.txt # λ§€μ₯ μ 보 ν
μ€νΈ (μν λ°μ΄ν°, μΆν κ΅μ²΄ κ°λ₯)
βββ scripts/ # μλ² μ€ν/μ€μ§/λ°°ν¬ μ€ν¬λ¦½νΈ
β βββ start.sh
β βββ stop.sh
β βββ deploy.sh
βββ app.py # Flask μ€ν μ§μ
μ
βββ requirements.txt # μμ‘΄μ± λͺ©λ‘
βββ .gitignore # git μΆμ μ μΈ νμΌ λͺ©λ‘
βββ appspec.yml
βββ README.mdπ μ£Όμ Source code μ€λͺ
| κ²½λ‘ | μ€λͺ |
|---|---|
app.py |
Flask μ ν리μΌμ΄μ μ μ€ννλ λ©μΈ μ§μ μ |
chatbot/bot.py |
μ¬μ©μμ μ§λ¬Έμ GPTμκ² μ λ¬νκ³ , νμ μ Function Callingμ ν΅ν΄ λμ μν (μ: μ£Όλ¬Έ μ²λ¦¬) |
chatbot/embedding.py |
housum.txt νμΌμμ μ€ λ¨μ λ¬Έμ₯μ μΆμΆνμ¬ OpenAI μλ² λ© ν MongoDBμ μ μ₯ (embedding, text, user_id, timestamp ν¬ν¨) |
chatbot/retriever.py |
쿼리 λ¬Έμ₯μ μλ² λ©νκ³ , MongoDBμμ λμΌν user_idλ₯Ό κ°λ λ¬Έμλ€κ³Ό μ½μ¬μΈ μ μ¬λλ₯Ό κ³μ°νμ¬ μμ top_k λ¬Έμλ₯Ό λ°ν |
api/routes.py |
/chat λΌμ°νΈλ₯Ό ν΅ν΄ μ¬μ©μμ μ§λ¬Έμ μμ νκ³ , GPT μλ΅μ μμ±νμ¬ JSONμΌλ‘ λ°ν (μ ν¨μ± κ²μ¬ λ° λ‘κ·Έ κΈ°λ‘ ν¬ν¨) |
api/redis_client.py |
Redis ν΄λΌμ΄μΈνΈλ₯Ό μ΄κΈ°ννλ©°, μ¬μ©μ ν ν° κΈ°λ°μ λν κΈ°λ‘ μ μ₯, μ‘°ν, μμ κΈ°λ₯μ μ 곡 (μΈμ μ μ§μ μ¬μ©) |
api/config.py |
Redis, MongoDB, OpenAI API ν€ λ±μ μ€μ μ 보λ₯Ό κ΄λ¦¬ |
data/housum.txt |
λ§€μ₯ μ λ³΄κ° ν¬ν¨λ ν μ€νΈ νμΌ, RAG κ²μμ μν λ²‘ν° μΈλ±μ± λμ |
git clone https://github.com/Clover-21/Howkiki_AI.git
cd Howkiki_AI # ν΄λ‘ ν ν΄λΉ νλ‘μ νΈλ‘ μ΄λpython -m venv venv
source venv/bin/activate # (Windowsμ κ²½μ°: venv\Scripts\activate)pip install -r requirements.txtνλ‘μ νΈ λ£¨νΈ λλ ν 리μ .env νμΌμ μμ±ν ν, μλμ κ°μ νμμΌλ‘ νκ²½ λ³μλ₯Ό μμ±ν©λλ€:
# OpenAI API Key
OPENAI_API_KEY=your_openai_api_key
# λ°±μλ API URL
api_url=your_backend_api_url
# Redis μ€μ
REDIS_HOST=your_redis_host
REDIS_PORT=your_redis_port
REDIS_DB=0
REDIS_PASSWORD=your_redis_password
# MongoDB μ€μ
MONGODB_URI=your_mongodb_url
β οΈ .env νμΌμ 보μμ GitHubμ ν¬ν¨λμ§ μμ΅λλ€.
νμν ν€ κ°μ κ΅μλκ» μ΄λ©μΌλ‘ λ³λ μ λ¬λλ Έμ΅λλ€.
β οΈ μ΄ μμ μ λ°μ΄ν° μ΄κΈ°νλ λ§€μ₯ μ 보 μμ μμλ§ νμν©λλ€.
data/housum.txt νμΌμ κΈ°λ°μΌλ‘ λ§€μ₯ μ 보λ₯Ό μλ² λ©νμ¬ MongoDB λ²‘ν° DBμ μ μ₯νλ €λ©΄ λ€μ λͺ
λ Ήμ΄λ₯Ό μ€ννμΈμ:
python chatbot/embedding.pyν΄λΉ λͺ λ Ήμ΄λ λ€μ μμ μ μνν©λλ€:
- data/housum.txtμ κ° μ€μ λ¬Έμλ‘ κ°μ£Όνκ³ μλ² λ© μμ±
- MongoDBμ howkiki.store 컬λ μ μ user_id, text, embedding, timestamp νλλ‘ μ μ₯
- κΈ°μ‘΄ λ°μ΄ν°λ μ΄κΈ°νλ¨ (drop() μ²λ¦¬)
μ±μ€λ AI μλ²λ λ κ°μ§ λ°©μμΌλ‘ ν μ€νΈν μ μμ΅λλ€:
- Postmanμ μ΄μ©ν HTTP μμ² ν μ€νΈ
- ν°λ―Έλμμ μΈν°λν°λΈ λͺ¨λ μ€ν
μ΄ μ€ μΈν°λν°λΈ λͺ¨λκ° λ λΉ λ₯΄κ³ νΈλ¦¬νκ² ν μ€νΈν μ μμ΅λλ€.
μλ²λ κΈ°λ³Έμ μΌλ‘ http://localhost:5000μμ μ€νλ©λλ€.
λ¨Όμ μλ²λ₯Ό μ€νν©λλ€:
# μλ μ€ νλλ₯Ό μ¬μ©νμΈμ
flask run
# λλ
python app.pyPostmanμμ λ€μκ³Ό κ°μ΄ μμ²μ 보λ λλ€:
- URL:
http://127.0.0.1:5000/api/chat - Method:
POST - Body (JSON):
{
"question": "μ¬κΈ°μ μ¬μ©μ μ
λ ₯ μμ±",
"storeId": "1",
"tableNum": "1",
"token": "123456789"
}μλ΅ μμ:
{
"function_call_result": "Assistant Response: ν¨μ νΈμΆμ΄ λμ§ μμ΅λλ€.",
"response": "건물 λ΄ μ£Όμ°¨μ₯μ 3μκ° κΈ°λ³Έ 무λ£λ‘ μ΄μ©ν μ μμ΄μ. π μΆκ°λ‘ κΆκΈνμ μ¬νμ΄ μλ€λ©΄ μΈμ λ μ§ λ§μν΄ μ£ΌμΈμ!",
"storeId": "1",
"tableNum": "1",
"token": "123456789"
}κ° νλ μ€λͺ :
function_call_result: ν¨μ νΈμΆμ΄ κ°μ§λμλμ§ μ¬λΆ (ν μ€νΈμ©)response: μ¬μ©μ μ§λ¬Έμ λν μλ΅storeId,tableNum,token: μμ²μμ μ λ ₯ν κ° κ·Έλλ‘ λ°νλ¨
ν°λ―Έλμμ μλ λͺ λ Ήμ΄λ₯Ό μ€ννμΈμ:
python chatbot/bot.pyμμ:
μλ
νμΈμ. νΈμ°μ¬μ
λλ€. λνλ₯Ό μ’
λ£νλ €λ©΄ 'μ’
λ£'λ₯Ό μ
λ ₯νμΈμ.
κ³ κ° > μλ
μ±μ€λ > μλ
νμΈμ! π 무μμ λμλ릴κΉμ? μ£Όλ¬Ένμκ±°λ κΆκΈν μ¬νμ΄ μλ€λ©΄ μΈμ λ μ§ λ§μν΄ μ£ΌμΈμ.
ν¨μ νΈμΆ κ²°κ³Ό: Assistant Response: ν¨μ νΈμΆμ΄ λμ§ μμ΅λλ€.- κ³ κ° >: μ¬μ©μκ° μ λ ₯νλ λΆλΆμ λλ€.
- λν μ’
λ£:
μ’ λ£μ λ ₯ λλCtrl + C - ν¨μ νΈμΆ κ²°κ³Όλ ν μ€νΈμ©μΌλ‘ ν¨κ» μΆλ ₯λ©λλ€.
*Postmanμ μ¬μ©νμ§ μμλ λλΆλΆμ κΈ°λ₯μ μΈν°λν°λΈ λͺ¨λμμ κ°νΈνκ² ν μ€νΈν μ μμ΅λλ€.
data/housum.txtνμΌμ κΈ°λ³Έ ν μ€νΈμ© μν λ§€μ₯ μ 보λ₯Ό ν¬ν¨ν©λλ€.- κ° μ€μ νλμ λ¬Έμλ‘ κ°μ£Όλλ©°, μλ² λ© μ²λ¦¬λμ΄ MongoDB(
howkiki.store컬λ μ )μ μ μ₯λ©λλ€. - μ΄ λ°μ΄ν°λ μ±μ€λκ° μ§μμ λ΅λ³ν μ μλλ‘ μ 보 κ²μ(RAG) κΈ°λ°μΌλ‘ μ¬μ©λ©λλ€.
μ€μ μλΉμ€ μ ν μ,
housum.txtνμΌμ μ€μ λ§€μ₯ μ λ³΄λ‘ κ΅μ²΄ν©λλ€.
-
MongoDB:
- μ¬μ© λͺ©μ : λ§€μ₯ μ 보μ λ²‘ν° μ μ₯ λ° μ μ¬λ κΈ°λ° κ²μ
- μ¬μ© 컬λ μ
:
howkiki.store - μ£Όμ νλ:
user_id: λ§€μ₯μ μλ³νλ IDtext: μλ³Έ ν μ€νΈembedding: OpenAI μλ² λ© λ²‘ν°timestamp: μμ± μκ°
-
Redis:
- μ¬μ© λͺ©μ : μ€μκ° μΈμ λ°μ΄ν°, μ£Όλ¬Έ μμ² κ²°κ³Ό μ μ₯ λ° κ³΅μ
- κΈ°λ³Έ DB: 0λ² (λ³κ²½ μ
REDIS_DBνκ²½ λ³μλ‘ μ€μ ) - μ μ₯ μμ: ν ν° κΈ°λ° λν κΈ°λ‘, μ£Όλ¬Έ μμ² κ²°κ³Ό λ±
λ³Έ νλ‘μ νΈλ λ€μ μ€νμμ€ λΌμ΄λΈλ¬λ¦¬λ₯Ό κΈ°λ°μΌλ‘ κ°λ°λμμ΅λλ€:
-
- λͺ©μ : λ¬Έμ μλ² λ©, Retriever ꡬμ±, LLM μΈν°νμ΄μ€ ν΅ν©μ μ¬μ©
-
- λͺ©μ : GPT-4o κΈ°λ° μλ΅ μμ±μ μν LLM μ°λμ μ¬μ©λλ©°, Function Calling κΈ°λ₯μ νμ©νμ¬ μ£Όλ¬Έ μ²λ¦¬ λ±μ μλνλ₯Ό μ§μ
-
- λͺ©μ : RESTful API μλ² κ΅¬νμ μ¬μ©λλ©°, λΌμ°ν λ° μμ²/μλ΅ μ²λ¦¬λ₯Ό λ΄λΉ
-
- λͺ©μ : MongoDBμμ λ°μ΄ν° μ μΆλ ₯ λ° μ°κ²° κ΄λ¦¬λ₯Ό μν΄ μ¬μ©
-
- λͺ©μ : Redis κΈ°λ°μ μΈμ κ΄λ¦¬ λ° μν μ 보 곡μ μ μ¬μ©
-
- λͺ©μ : λ²‘ν° μ°μ° λ° μ½μ¬μΈ μ μ¬λ κ³μ° λ±μ νμ©
