ํ๊ตญ ๋์ ์ธ์ ์ํ ๋์ฅ ์ด์ ๊ด๋ฆฌ + ์ง๊ฑฐ๋ ์ผํ๋ชฐ ํตํฉ ํ๋ซํผ์ ๋๋ค. ์ทจ์ ํฌํธํด๋ฆฌ์ค ๋ชฉ์ ์ผ๋ก ์ค๊ณ๋์์ผ๋ฉฐ, ํ์ ์์ค์ ์ํคํ ์ฒ ์ค๊ณ์ AI ๊ธฐ๋ฅ ๊ตฌํ์ ์ด์ ์ ๋ง์ถฅ๋๋ค.
- ํ๋ก์ ํธ ๊ตฌ์กฐ
- ๊ธฐ์ ์คํ
- ์ฃผ์ ๊ธฐ๋ฅ
- CS ์ฑ๋ด ์ํคํ ์ฒ
- FAQ ์ง์๋ฒ ์ด์ค ์์คํ
- ์ค์น ๋ฐ ์คํ
- API ๋ฌธ์
- ์ํคํ ์ฒ ๊ฒฐ์ ๊ธฐ๋ก
FarmOS/
โโโ frontend/ React 19 + TypeScript + Vite ํฌํธ 5173
โ โโโ src/
โ โโโ modules/ ๊ธฐ๋ฅ๋ณ ๋ชจ๋ (farm, harvest, revenue, ...)
โ โโโ components/ ๊ณตํต ์ปดํฌ๋ํธ
โ
โโโ backend/ FastAPI + PostgreSQL ํฌํธ 8000
โ โโโ app/
โ โ โโโ api/ ๋ผ์ฐํฐ
โ โ โโโ models/ SQLAlchemy ORM ๋ชจ๋ธ
โ โ โโโ schemas/ Pydantic ์คํค๋ง
โ โโโ ai/ AI/ML ์๋น์ค
โ
โโโ shopping_mall/
โโโ frontend/ React 19 + TypeScript + Vite ํฌํธ 5173 (๋ณ๋)
โ โโโ src/
โ โโโ admin/ ์ด๋๋ฏผ ๋์๋ณด๋
โ โโโ components/ ์ผํ๋ชฐ ๊ณตํต ์ปดํฌ๋ํธ
โ
โโโ backend/ FastAPI + PostgreSQL + ChromaDB ํฌํธ 4000
โโโ app/
โ โโโ routers/ API ๋ผ์ฐํฐ (chatbot, knowledge, faq_categories, ...)
โ โโโ models/ SQLAlchemy ORM ๋ชจ๋ธ
โ โโโ services/ ๋น์ฆ๋์ค ๋ก์ง (์ฑ๋ด, ์ง์๋ฒ ์ด์ค ๋๊ธฐํ, ...)
โโโ ai/
โโโ agent/ ๋ฉํฐ์์ด์ ํธ ์ฑ๋ด (LangChain + LangGraph)
โโโ rag.py BM25 + Dense ํ์ด๋ธ๋ฆฌ๋ RAG
| ๋ถ๋ฅ | ๊ธฐ์ |
|---|---|
| ํ๋ ์์ํฌ | React 19 + TypeScript |
| ๋น๋ ๋๊ตฌ | Vite |
| ์๋ฒ ์ํ | TanStack Query v5 |
| ์คํ์ผ | Tailwind CSS |
| ์์ด์ฝ | Material Symbols |
| HTTP | Axios (credential: include) |
| ์๋ฆผ | react-hot-toast |
| ๋ถ๋ฅ | ๊ธฐ์ |
|---|---|
| ํ๋ ์์ํฌ | FastAPI |
| ORM | SQLAlchemy (๋๊ธฐ Session) |
| DB | PostgreSQL |
| ํจํค์ง ๋งค๋์ | uv |
| ์ค์ผ์ค๋ฌ | APScheduler |
| ๋ถ๋ฅ | ๊ธฐ์ |
|---|---|
| ์์ด์ ํธ | LangChain StructuredTool + LangGraph |
| LLM (Primary) | OpenAI ํธํ (OpenRouter/Ollama ์ ํ ๊ฐ๋ฅ) |
| LLM (Fallback) | Anthropic Claude Haiku |
| ์ฒดํฌํฌ์ธํฐ | LangGraph + AsyncPostgresSaver |
| ๋ฒกํฐ DB | ChromaDB (persistent) |
| ๊ฒ์ ๋ฐฉ์ | BM25 + Dense ํ์ด๋ธ๋ฆฌ๋ (RRF ๋ญํน) |
| Reranker | sentence-transformers (์ ํ์ ) |
| ์๋ฒ ๋ฉ | sentence-transformers / OpenAI embeddings |
- ์๋ฌผ ์ฌ๋ฐฐ ์ผ์ : ํ์ข ~์ํ ์ฌ์ดํด ๊ด๋ฆฌ ๋ฐ ์บ๋ฆฐ๋ ๋ทฐ
- ์ํ๋ ์ถ์ : ํ๋ชฉ๋ณ ์ํ๋ ์ ๋ ฅ ๋ฐ ํต๊ณ
- ์์ต/์ง์ถ ๊ด๋ฆฌ: ๋์ฅ ์์ต ๊ณ์ฐ์ ์๋ ์์ฑ
- ์ฃผ๊ฐ ๋ฆฌํฌํธ: LLM ๊ธฐ๋ฐ ๋์ฅ ์ด์ ์์ฝ ์๋ ์์ฑ
- ๊ณ ๊ฐ ์ธ๊ทธ๋จผํธ ๋ถ์: RFM ๊ธฐ๋ฐ ๊ตฌ๋งค ํจํด ๋ถ์
- ์ํ/์นดํ ๊ณ ๋ฆฌ ๊ด๋ฆฌ: ์ฌ๊ณ ์ค์๊ฐ ์ถ์
- ์ฃผ๋ฌธ/๋ฐฐ์ก ๊ด๋ฆฌ: ์ํ ๊ธฐ๋ฐ ์ํฌํ๋ก์ฐ
- ๊ตํ/๋ฐํ ์ฒ๋ฆฌ: Human-in-the-Loop ๊ตํ ์ ์ฒญ ์์คํ
- CS AI ์ฑ๋ด: ๋ฉํฐ์์ด์ ํธ ์๋ ์๋ (์๋ ์์ธ ์ค๋ช )
- FAQ ์ง์๋ฒ ์ด์ค: ๊ด๋ฆฌ์ ํธ์ง ๊ฐ๋ฅํ ์ฑ๋ด ํ์ต ๋ฐ์ดํฐ + ์ ๋๋ฆฌํฑ์ค
๊ณ ๊ฐ ๋ฌธ์๋ฅผ ์๋ ์ฒ๋ฆฌํ๋ ๋ฉํฐ์์ด์ ํธ ์์คํ ์ ๋๋ค. LangGraph ๊ธฐ๋ฐ ๊ทธ๋ํ๋ก ๋ณตํฉ ์ง๋ฌธ, ๋ฉํฐ์คํ ์ถ๋ก , Human-in-the-Loop ๊ตํ ์ ์ฒญ์ ์ง์ํฉ๋๋ค.
๊ณ ๊ฐ ์ง๋ฌธ
โ
POST /api/chatbot/ask
โ
MultiAgentChatbotService
โ
SupervisorExecutor (LangGraph)
โโโ CS ์ผ๋ฐ ์ง๋ฌธ โ AgentExecutor (LangChain tool_use)
โ โโโ search_faq (FAQ ํตํฉ RAG)
โ โโโ search_policy (์ ์ฑ
๋ฌธ์ RAG)
โ โโโ get_order_status (DB ์กฐํ)
โ โโโ search_products (DB ์กฐํ)
โ โโโ get_product_detail
โ โโโ escalate_to_agent
โ
โโโ ๊ตํ/๋ฐํ โ OrderGraph (LangGraph StateGraph)
โโโ create_exchange_request (pending ์ ์ฅ)
โโโ confirm_pending_action (์ต์ข
์คํ)
โโโ cancel_pending_action (์ทจ์)
Primary LLM ์ฅ์ ์ ์๋์ผ๋ก Fallback์ผ๋ก ์ ํํฉ๋๋ค.
primary = build_primary_llm() # OpenAI ํธํ โ .env์ PRIMARY_MODEL
fallback = build_fallback_llm() # Claude Haiku โ .env์ FALLBACK_MODELBM25(ํค์๋) + Dense(์๋ฏธ๋ก ) ํ์ด๋ธ๋ฆฌ๋ ๊ฒ์ ํ RRF๋ก ํตํฉ ๋ญํน:
์ง๋ฌธ
โ
normalize_query() โ ์กฐ์ฌ ์ ๊ฑฐ, ์๋ฌธ์ํ
โ
โโโ BM25 ๊ฒ์ (json ์ธ๋ฑ์ค)
โโโ Dense ๊ฒ์ (ChromaDB ์ฝ์ฌ์ธ)
โ
RRF ํตํฉ
โ
[์ ํ] Reranker (cross-encoder)
โ
๊ฑฐ๋ฆฌ ์๊ณ๊ฐ ํํฐ (distance_threshold=0.5)
โ
์ธ์ฉ ๋ฌธ์ ID ์์ง (CSToolContext.cited_faq_ids)
- JWT in HttpOnly ์ฟ ํค
- ๋น๋ก๊ทธ์ธ ์ฌ์ฉ์๋ ์ฑ๋ด ์ฌ์ฉ ๊ฐ๋ฅ (user_id=None)
- ๊ตํ ์ ์ฒญ, ์ฃผ๋ฌธ ์กฐํ๋ ๋ก๊ทธ์ธ ํ์
v2์์ ๊ธฐ์กด 4๊ฐ ๋ถ๋ฆฌ ์นดํ ๊ณ ๋ฆฌ(faq / storage_guide / season_info / farm_info)๋ฅผ ๋จ์ผ FAQ ์์คํ ์ผ๋ก ํตํฉํ์ต๋๋ค.
FaqCategory (์ด๋๋ฏผ ๊ด๋ฆฌ)
id, name, slug, color, icon, sort_order, is_active
โโโ KnowledgeDoc (FAQ ๋ฌธ์)
id, title, content, faq_category_id, chroma_doc_id
is_active, extra_metadata
โโโ FaqCitation (์ฑ๋ด ์ธ์ฉ ์ด๋ ฅ)
FaqFeedback (์ฌ์ฉ์ ํผ๋๋ฐฑ ๐/๐)
[๊ด๋ฆฌ์] KnowledgePage ์ด๋๋ฏผ์์ FAQ ๋ฑ๋ก/์์
โ
PostgreSQL ์ ์ฅ + ChromaDB ๋ฐฑ๊ทธ๋ผ์ด๋ ๋๊ธฐํ (KnowledgeSync)
โ
[์ฑ๋ด] search_faq ๋๊ตฌ ํธ์ถ ์ ChromaDB ๊ฒ์
โ metadata.db_id โ CSToolContext.cited_faq_ids์ ๋์
โ
[์๋น์ค] MultiAgentChatbotService.answer() ์๋ฃ ํ
โ cited_faq_ids โ shop_faq_citations ํ
์ด๋ธ ๊ธฐ๋ก
โ
[๊ณ ๊ฐ] ์ฑ๋ด ์๋ต ํ๋จ ๐/๐ ๋ฒํผ ํด๋ฆญ
โ POST /api/chatbot/faq-feedback
โ
[์ด๋๋ฏผ] KnowledgePage ์ ๋๋ฆฌํฑ์ค ์ปฌ๋ผ
โโโ ์ธ์ฉ ์ ยท ๋์๋จ % ยท ๊ฐ์ ํ์ ํ์
- ์ข์ธก ์ฌ์ด๋๋ฐ: ์นดํ ๊ณ ๋ฆฌ ๋ชฉ๋ก (์ถ๊ฐ/์์ /์ญ์ hover ๋ฒํผ)
- ์นดํ ๊ณ ๋ฆฌ ๊ด๋ฆฌ: ์ด๋ฆ, ์ฌ๋ฌ๊ทธ, ์์, ์์ด์ฝ ์ปค์คํฐ๋ง์ด์ง
- FAQ ํ ์ด๋ธ: ์ง๋ฌธ ์ ๋ชฉ, ์นดํ ๊ณ ๋ฆฌ ์นฉ, ์ธ์ฉ ์, ๋์๋จ % ๋ฏธ๋ ๋ฐ
- ์ ๋ ฌ ์ต์ : ์ต๊ทผ ๋ฑ๋ก์ / ๋ง์ด ์ธ์ฉ๋ ์ / ๋์๋จ ๋์ ์ / ๊ฐ์ ํ์ ์
- ๊ฐ์ ํ์ ํ์: ์ธ์ฉ์ ๋์ง๋ง ๐ > ๐ ์ธ ๋ฌธ์์
โ ๏ธ ์์ด์ฝ
# FAQ ์นดํ
๊ณ ๋ฆฌ
GET /api/admin/faq-categories ๋ชฉ๋ก (include_inactive ์ต์
)
POST /api/admin/faq-categories ์นดํ
๊ณ ๋ฆฌ ์์ฑ
PUT /api/admin/faq-categories/{id} ์์
DELETE /api/admin/faq-categories/{id} ์ญ์ (force=true ์ ๋ฌธ์ ๋ฏธ๋ถ๋ฅ ์ด๋)
# FAQ ๋ฌธ์
GET /api/admin/knowledge ๋ชฉ๋ก (์นดํ
๊ณ ๋ฆฌ ํํฐ, ์ ๋๋ฆฌํฑ์ค ํฌํจ)
POST /api/admin/knowledge ๋ฌธ์ ์์ฑ + ChromaDB ๋๊ธฐํ
GET /api/admin/knowledge/{id} ๋จ๊ฑด ์กฐํ
PUT /api/admin/knowledge/{id} ์์ + ChromaDB ๋๊ธฐํ
DELETE /api/admin/knowledge/{id} ์ํํธ ์ญ์
# ์ฑ๋ด ํผ๋๋ฐฑ
POST /api/chatbot/faq-feedback ๐/๐ ํผ๋๋ฐฑ ์ ์ถ (chat_log_id ๊ธฐ์ค upsert)
| ์ปฌ๋ ์ ๋ช | ๋ด์ฉ | ๋ฉํ๋ฐ์ดํฐ |
|---|---|---|
faq |
๋ชจ๋ FAQ ๋ฌธ์ (ํตํฉ) | db_id, subcategory_slug, subcategory_name, tags |
return_policy |
๋ฐํยท๊ตํยทํ๋ถ ์ ์ฑ | โ |
payment_policy |
๊ฒฐ์ ยท์ ๋ฆฝ๊ธ ์ ์ฑ | โ |
delivery_policy |
๋ฐฐ์ก ์ ์ฑ | โ |
quality_policy |
์ํ ํ์ง ๋ณด์ฆ ์ ์ฑ | โ |
service_policy |
๊ณ ๊ฐ์๋น์ค ์ด์ ์ ์ฑ | โ |
membership_policy |
๊ฐ์ธ์ ๋ณดยทํ์ ์ ์ฑ | โ |
- Python 3.11+, Node.js 20+
- PostgreSQL 15+
uvํจํค์ง ๋งค๋์
# shopping_mall/backend/.env
DATABASE_URL=postgresql://...
LANGGRAPH_POSTGRES_URL=postgresql://...
PRIMARY_MODEL=openai/gpt-4o-mini # OpenRouter ํ์ ๋๋ ๋ชจ๋ธ๋ช
FALLBACK_MODEL=claude-haiku-4-5-20251001
OPENROUTER_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
RERANKER_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2 # ์ ํํ์์ฉ ๋น ๋ฅธ ์คํ์ ๋ฃจํธ์ Web_Starter.exe๋ฅผ ๊ถ์ฅํฉ๋๋ค.
1. PostgreSQL ์คํ ๋ฐ .env ํ์ธ
2. Web_Starter.exe ์คํ
3. ์๋ฒ ์์ ๋ฒํผ ํด๋ฆญ
Web_Starter.exe๋ ์๋ฒ๋ฅผ ๋์ฐ๊ธฐ ์ ์ automation/run.mjs๋ฅผ ์คํํด DB ํ
์ด๋ธ/row ์๋ฅผ ํ์ธํ๊ณ , ํ์ํ ๊ฒฝ์ฐ ์๋ ํ๋ฆ์ ํธ์ถํฉ๋๋ค. ์ผํ๋ชฐ ํํธ๋ ์ถ๊ฐ๋ก shop_tickets.flags ๊ฐ์ ์์ ํ ๋๋ฝ ์ปฌ๋ผ์ ๋ณด๊ฐํ๊ณ , ์ํ ์ด๋ฏธ์ง URL์ ์ต์ ๋งคํ์ผ๋ก ๋ง์ถฅ๋๋ค.
์๋ ์คํ์ด ํ์ํ ๋๋ ์๋ ๋ช ๋ น์ ์ฌ์ฉํฉ๋๋ค.
# FarmOS ๋ฐฑ์๋
cd backend && uv run uvicorn main:app --reload
# FarmOS ํ๋ก ํธ์๋
cd frontend && npm install && npm run dev
# ์ผํ๋ชฐ ๋ฐฑ์๋
cd shopping_mall/backend && uv run uvicorn main:app --reload --port 4000
# ์ผํ๋ชฐ ํ๋ก ํธ์๋
cd shopping_mall/frontend && npm install && npm run dev# ์ ์ฑ
๋ฌธ์(PDF/DOCX)๋ฅผ ai/docs/์ ๋ฐฐ์น ํ ์คํ
cd shopping_mall/backend
uv run python scripts/seed_and_verify.pyWeb_Starter.exe ์คํ ์ ํ๋ก ์ผํ๋ชฐ ๋ฐ์ดํฐ๋ง ๋ค์ ๋ง์ถ๊ณ ์ถ๋ค๋ฉด ๋ฃจํธ์์ ์๋ ๋ช
๋ น์ ์คํํฉ๋๋ค.
python bootstrap/apply_shop_updates.pyํ์ฌ ์ด ์คํฌ๋ฆฝํธ๋ ์ํ ๋๋ฏธ ์ด๋ฏธ์ง URL์ ํ๋ชฉ๋ณ ์ธ๋ถ ์ด๋ฏธ์ง URL๋ก ๋ณด์ ํฉ๋๋ค. DB๊ฐ ๋น์ด ์๊ฑฐ๋ FAQ/RAG ๋ฐ์ดํฐ๊ฐ ๋ถ์กฑํ ๊ฒฝ์ฐ์๋ Web_Starter.exe์ ์๋ํ๊ฐ bootstrap/insert_data.py๋ฅผ ํตํด FAQ DB ์๋ฉ๊ณผ RAG ์ธ๋ฑ์ฑ๊น์ง ์ฒ๋ฆฌํฉ๋๋ค.
์๋ฒ ์คํ ํ ์๋ ์์ฑ Swagger UI์์ ํ์ธ:
- FarmOS: http://localhost:8000/docs
- ์ผํ๋ชฐ: http://localhost:4000/docs
๋ฐฐ๊ฒฝ: ๊ธฐ์กด if/elif ์ธํ
ํธ ๋ผ์ฐํฐ๋ ๋ณตํฉ ์ง๋ฌธ("๋ธ๊ธฐ ์ฌ๊ณ ์์ด? ๋ณด๊ด๋ฒ๋ ์๋ ค์ค")์ ์ธํ
ํธ ํ๋๋ก๋ง ์ฒ๋ฆฌ.
๊ฒฐ์ : LangChain tool_use ๊ธฐ๋ฐ AgentExecutor + LangGraph SupervisorExecutor๋ก ์ ํ.
๊ฒฐ๊ณผ: ๋ฉํฐ์คํ ์ถ๋ก , ๋ณตํฉ ์ง๋ฌธ ์ฒ๋ฆฌ, Human-in-the-Loop ๊ตํ ์ ์ฒญ ๊ตฌํ.
๋ฐฐ๊ฒฝ: faq / storage_guide / season_info / farm_info 4๊ฐ ChromaDB ์ปฌ๋ ์
์ด ๋ณ๋ RAG ๋๊ตฌ๋ก ๋ถ๋ฆฌ๋์ด ์ ์ง๋ณด์ ๋ณต์ก๋ ์ฆ๊ฐ. ์นดํ
๊ณ ๋ฆฌ ์ถ๊ฐ/๋ณ๊ฒฝ์ด ์ฝ๋ ๋ฐฐํฌ๋ฅผ ์๊ตฌ.
๊ฒฐ์ : ๋จ์ผ faq ChromaDB ์ปฌ๋ ์
+ PostgreSQL FaqCategory ํ
์ด๋ธ๋ก ํตํฉ. ์ด๋๋ฏผ์ด ์นดํ
๊ณ ๋ฆฌ๋ฅผ ์ฝ๋ ์์ด ๊ด๋ฆฌ.
๊ฒฐ๊ณผ: ๋๊ตฌ ์ 12 โ 9๊ฐ๋ก ๊ฐ์. ์นดํ ๊ณ ๋ฆฌ ์ถ๊ฐ/๋ณ๊ฒฝ์ด ์ด๋๋ฏผ UI์์ ์ฆ์ ๋ฐ์.
๋ฐฐ๊ฒฝ: RAG ๋๊ตฌ๊ฐ ์ด๋ค ๋ฌธ์๋ฅผ ์ธ์ฉํ๋์ง ์ถ์ ํ๋ ค๋ฉด ๋๊ตฌ ์คํ ์ค side-effect๊ฐ ํ์.
๊ฒฐ์ : CSToolContext dataclass๋ฅผ ํด๋ก์ ๋ก ์บก์ฒํด cited_faq_ids ๋์ . AgentResult๋ก ์์ ์๋น์ค์ ์ ๋ฌ ํ shop_faq_citations์ ์ผ๊ด ๊ธฐ๋ก.
๊ฒฐ๊ณผ: ๋๊ตฌ ํจ์๊ฐ ์์ ํจ์์ ๊ฐ๊น๊ฒ ์ ์ง๋๋ฉด์ ์ธ์ฉ ์ถ์ ๊ฐ๋ฅ.
๋ฐฐ๊ฒฝ: Dense ๋จ๋ ๊ฒ์์ ์ ํํ ์ํ๋ช ยท์ ์ฑ ๋ฒํธ ๋งค์นญ์ ์ทจ์ฝ.
๊ฒฐ์ : BM25(ํค์๋ ์ ํ๋) + Dense(์๋ฏธ๋ก ์ ์ ์ฌ๋)๋ฅผ RRF๋ก ํตํฉ ๋ญํน. ์ ํ์ Reranker(cross-encoder) ์ถ๊ฐ ์ง์.
๊ฒฐ๊ณผ: ์ํ๋ช ๊ฒ์ ์ ํ๋ ํฅ์, ๋ชจํธํ ์ง๋ฌธ์ ์๋ฏธ๋ก ์ ๋งค์นญ ์ ์ง.
ํฌํธํด๋ฆฌ์ค ํ๋ก์ ํธ โ Jiwon (onegeewon@gmail.com)