# π MarketSync (λ§μΌμ±ν¬)
### Agentic RAG κΈ°λ° μμκ³΅μΈ λ§μΆ€ν μ§μ μΆμ μΆμ² & λ§μΌν
AI 컨μ€ν΄νΈ
μ νμΉ΄λ λΉ
λ°μ΄ν°μ μ κ΅ μΆμ μ 보λ₯Ό ν΅ν© λΆμνμ¬, **AI μμ΄μ νΈ**κ° κ°κ²λ³λ‘ μ°Έμ¬ν λ§ν μ§μ μΆμ λ₯Ό μΆμ²νκ³ μ΅μ μ λ§μΌν
μ λ΅ λ³΄κ³ μλ₯Ό μλ μμ±ν©λλ€. π€
---
## π§ νλ‘μ νΈ κ°μ
MarketSyncλ **Streamlit μΉ μΈν°νμ΄μ€, FastAPI λ°μ΄ν° μλ², LangChain μμ΄μ νΈ**λ₯Ό κ²°ν©νμ¬ μμ곡μΈμ μν AI 컨μ€ν
μλΉμ€λ₯Ό μ 곡ν©λλ€. μ¬μ©μλ μμ μ κ°κ²λ₯Ό μ ννμ¬ μμΈ νλ‘νκ³Ό λΆμ κ·Έλνλ₯Ό νμΈν λ€, "10μμ μ΄λ¦¬λ μΆμ μΆμ²ν΄μ€", "μΆμ²λ μΆμ λ€μ λ§μΌν
μ λ΅ μλ €μ€" μ κ°μ μμ°μ΄ μ§λ¬Έμ ν΅ν΄ λ§μΆ€ν 컨μ€ν
μ λ°μ μ μμ΅λλ€.
**ν΅μ¬ μν€ν
μ²λ Agentic RAG**μ
λλ€. AI μμ΄μ νΈ(`Orchestrator`)λ μ¬μ©μμ μ§λ¬Έκ³Ό κ°κ²μ μμΈ νλ‘ν(JSON)μ λ°νμΌλ‘ μν©μ λ§λ **λꡬ(Tool)**λ₯Ό μμ¨μ μΌλ‘ μ ννκ³ , μ¬μ©μμ μ§λ¬Έμ λ°λΌ νμνλ€λ©΄ μ¬λ¬ λꡬλ₯Ό μμ°¨μ μΌλ‘ νΈμΆνμ¬ μ΅μ’
컨μ€ν
λ³΄κ³ μλ₯Ό μμ±ν©λλ€.
---
## π οΈ ν΅μ¬ λꡬ λ° μλ λ°©μ
AI μμ΄μ νΈκ° μ¬μ©νλ μ£Όμ λꡬμ λ΄λΆ μ²λ¦¬ κ³Όμ μ λ€μκ³Ό κ°μ΅λλ€.
| κΈ°λ₯ λΆλ₯ | λꡬ ν¨μλͺ
(`tools/`) | μ£Όμ μ²λ¦¬ κ³Όμ (`modules/`) |
| :--------------- | :------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **μΆμ μΆμ²** | `recommend_festivals` (festival\_recommender.py) | **νμ΄λΈλ¦¬λ 5λ¨κ³ νμ΄νλΌμΈ (`filtering.py`)**:
1. LLM 쿼리 μ¬μμ±
2. FAISS λ²‘ν° κ²μ (μ μ¬ μΆμ ν보 μ μ )
3. LLM λμ μμ± νκ° (κ°κ² λ§μΆ€μ±)
4. νμ΄λΈλ¦¬λ μ μ κ³μ°
5. μ΅μ’
Top3 κ²°κ³Ό ν¬λ§·ν
(2026 μμΈ‘ ν¬ν¨) |
| **λ§μΌν
(RAG)** | `search_contextual_marketing_strategy` (marketing\_strategy.py) | **컨ν
μ€νΈ κΈ°λ° RAG (`knowledge_base.py`)**:
1. κ°κ² νλ‘ν + μ§λ¬Έ β LLM κ²μ 쿼리 μμ±
2. FAISS λ²‘ν° κ²μ (κ΄λ ¨ μ λ΅ λ¬Έμ μΆμΆ)
3. LLM λ΅λ³ μμ± (μΆμΆλ λ΄μ©μ λ°νμΌλ‘ μμ°μ€λ¬μ΄ μ λ΅ μ μ) |
| **λ§μΌν
(μμ±)** | `create_festival_specific_marketing_strategy` (marketing\_strategy.py) | **LLM κΈ°λ° μ λ΅ μμ±**:
1. μΆμ νλ‘ν μ‘°ν (`profile_analyzer.py`)
2. κ°κ² νλ‘ν + μΆμ νλ‘ν + RAG κ²μ β LLM ν둬ννΈ κ΅¬μ±
3. LLMμ΄ νΉμ μΆμ λ§μΆ€ μ λ΅ μμ± |
| **λ§μΌν
(μμ±)** | `create_marketing_strategies_for_multiple_festivals` (marketing\_strategy.py) | **LLM κΈ°λ° μ λ΅ μμ± (λ€μ)**:
1. μ¬λ¬ μΆμ μ΄λ¦ μ
λ ₯λ°μ
2. κ° μΆμ λ³λ‘ `create_festival_specific_marketing_strategy` λ°λ³΅ νΈμΆ
3. λͺ¨λ μ λ΅μ νλμ λ³΄κ³ μλ‘ μ·¨ν© |
| **κ°κ² λΆμ** | `analyze_merchant_profile` (profile\_analyzer.py) | **LLM κΈ°λ° λΆμ**:
κ°κ² νλ‘ν(JSON) μ
λ ₯ β LLMμ΄ SWOT λΆμ λ° ν΅μ¬ κ³ κ° νΉμ± μμ½ λ³΄κ³ μ μμ± |
| **μΆμ λΆμ** | `analyze_festival_profile` (profile\_analyzer.py) | **LLM κΈ°λ° λΆμ**:
μΆμ νλ‘ν(JSON) μ
λ ₯ β LLMμ΄ μΆμ μ ν΅μ¬ νΉμ§ λ° μ£Όμ λ°©λ¬Έκ° νΉμ± μμ½ λ³΄κ³ μ μμ± |
| **μΆμ μ‘°ν** | `get_festival_profile_by_name` (profile\_analyzer.py) | **λ¨μ λ°μ΄ν° μ‘°ν**: μΆμ μ΄λ¦ μ
λ ₯ β `festival_df.csv`μμ ν΄λΉ μΆμ μ 보(JSON) λ°ν (μΊμ± νμ©) |
---
## π νλ‘μ νΈ κ΅¬μ‘° λ° μ½λ μ€λͺ
```plaintext
MarketSync/
βββ streamlit_app.py # Streamlit μΉ μΈν°νμ΄μ€ (UI)
βββ orchestrator.py # AI μμ΄μ νΈ: LangChain AgentExecutor, λꡬ λΌμ°ν
, μ΅μ’
λ΅λ³ μμ± λ‘μ§
βββ config.py # μ€μ μ€μν: κ²½λ‘, API ν€, λͺ¨λΈλͺ
, λ‘κΉ
μ€μ λ±
β
βββ api/ # λ°μ΄ν° μ 곡 λ° μ μ²λ¦¬ μλ²
β βββ server.py # FastAPI μλ²: /profile, /merchants μλν¬μΈνΈ μ 곡
β βββ data_loader.py # λ°μ΄ν° λ‘λ© λ° μ μ²λ¦¬ (final_df.csv, festival_df.csv)
β
βββ tools/ # LangChain @tool λꡬ μ μ λ μ΄μ΄
β βββ festival_recommender.py # [Tool] recommend_festivals λꡬ μ μ (filtering.py νΈμΆ)
β βββ marketing_strategy.py # [Tool] λ§μΌν
μ λ΅ κ΄λ ¨ λꡬ 3κ° μ μ (knowledge_base.py, profile_analyzer.py λ± νΈμΆ)
β βββ profile_analyzer.py # [Tool] κ°κ²/μΆμ λΆμ λ° μΆμ νλ‘ν μ‘°ν λꡬ 3κ° μ μ (LLM νΈμΆ, λ°μ΄ν° μ‘°ν)
β βββ tool_loader.py # λͺ¨λ λꡬ(@tool)λ₯Ό 리μ€νΈλ‘ λ¬Άμ΄ Orchestratorμ μ 곡
β
βββ modules/ # ν΅μ¬ λ‘μ§ κ΅¬ν λͺ¨λ
β βββ filtering.py # [μΆμ μΆμ²] FestivalRecommender ν΄λμ€ (5λ¨κ³ νμ΄νλΌμΈ ꡬν)
β βββ knowledge_base.py # [RAG] FAISS λ²‘ν° μ€ν μ΄ λ‘λ© (μΆμ , λ§μΌν
), μλ² λ© λͺ¨λΈ κ΄λ¦¬
β βββ llm_provider.py # LLM μΈμ€ν΄μ€ κ΄λ¦¬ (μ μ 곡μ λ° Temperature μ‘°μ )
β βββ profile_utils.py # κ°κ² νλ‘ν JSON κ°κ³΅ μ νΈλ¦¬ν° (μ±ν
μ©/λΆμμ©)
β βββ visualization.py # Streamlit μκ°ν: Matplotlib κ·Έλν μμ± ν¨μ
β
βββ utils/ # κ³΅ν΅ μ νΈλ¦¬ν°
β βββ parser_utils.py # LLM μλ΅μμ JSON μΆμΆ νμ
β
βββ data/ # μλ³Έ λ°μ΄ν°
β βββ final_df.csv # μ νμΉ΄λ κ°λ§Ήμ λ°μ΄ν°
β βββ festival_df.csv # μ κ΅ μΆμ μ 보 λ°μ΄ν°
β
βββ vectorstore/ # FAISS λ²‘ν° λ°μ΄ν°λ² μ΄μ€ μ μ₯ ν΄λ
βββ faiss_festival # μΆμ μ 보 λ²‘ν° DB
βββ faiss_marketing # λ§μΌν
μ λ΅ λ²‘ν° DB
```
------------------------------------------------------------------------
## π μν€ν
μ² λ° λ°μ΄ν° νλ¦
μ΄ μμ€ν
μ **μμ΄μ νΈ μ€μ¬μ λꡬ νΈμΆ (Tool-Calling)** μν€ν
μ²λ₯Ό κΈ°λ°μΌλ‘ μλν©λλ€. μ¬μ©μμ μμ°μ΄ μ§λ¬Έμ `Orchestrator`λΌλ AI μμ΄μ νΈμ μν΄ ν΄μλλ©°, μμ΄μ νΈλ μ 곡λ `[κ°κ² νλ‘ν]` 컨ν
μ€νΈμ **μμ€ν
ν둬ννΈ**μ μ§μΉ¨μ λ°λΌ κ°μ₯ μ μ ν λꡬλ₯Ό μ ννκ³ μ€νν©λλ€. νμνλ€λ©΄ μ¬λ¬ λꡬλ₯Ό μμ°¨μ μΌλ‘ νΈμΆνμ¬ μ»μ μ 보λ₯Ό μ’
ν©ν λ€, μ΅μ’
컨μ€ν
λ΅λ³μ μμ±ν©λλ€.
---
## π§© μμ€ν
ꡬμ±λ
### (1) μ 체 κ°μ: UI - μμ΄μ νΈ - API μνΈμμ©
μ¬μ©μκ° UIλ₯Ό ν΅ν΄ μ§λ¬Ένλ©΄, **μμ΄μ νΈ(Orchestrator)** κ° μλνκ³ , νμ μ FastAPI μλ²λ **μ¬λ¬ λꡬ(Tool)** μ μνΈμμ©ν©λλ€.
```mermaid
graph TD
%% ========================
%% AI 컨μ€ν
μμ§ (μ΅μλ¨)
%% ========================
subgraph SG_Engine ["π§ AI 컨μ€ν
μμ§"]
direction TB
C["π€ Orchestrator (ν΅μ¬ μμ΄μ νΈ)\n(orchestrator.py)\nAgentExecutor (LangChain)"]
D{"π¦ Tool Routing\nLLM μλ λΆμ & λꡬ μ ν"}
subgraph SG_Tools ["π§ λ±λ‘λ λꡬ λͺ©λ‘ (tools/)"]
T1["recommend_festivals\n(μΆμ μΆμ²)"]
T2["search_contextual_marketing_strategy\n(RAG λ§μΌν
μ λ΅)"]
T3["create_festival_specific_marketing_strategy\n(λ¨μΌ μΆμ μ λ΅)"]
T3_multi["create_marketing_strategies_for_multiple_festivals\n(λ€μ μΆμ μ λ΅)"]
T4["analyze_merchant_profile\n(κ°κ² λΆμ)"]
T5["analyze_festival_profile\n(μΆμ λΆμ)"]
T6["get_festival_profile_by_name\n(μΆμ νλ‘ν μ‘°ν)"]
end
LLM_Final["πͺ LLM (Final Report Generation)\nμ΅μ’
λ³΄κ³ μ μμ±"]
end
%% ========================
%% μ¬μ©μ μΈν°νμ΄μ€ & λ°μ΄ν° μλ² (νλ¨)
%% ========================
subgraph SG_UserServer ["π» μ¬μ©μ μΈν°νμ΄μ€ & λ°μ΄ν° μλ²"]
direction LR
A["π₯οΈ Streamlit UI\n(streamlit_app.py)\nμ¬μ©μ μνΈμμ©"] <--> B["π FastAPI Server\n(api/server.py)\nπ κ°κ² νλ‘ν / λͺ©λ‘ μ‘°ν"]
end
%% ========================
%% μ°κ²° κ΄κ³ (μμ )
%% ========================
A -- "μμ°μ΄ μ§λ¬Έ μ
λ ₯" --> C
C -- "μλ λΆμ μμ²" --> D
D -- "μ ν© λꡬ μ ν/μ€ν" --> SG_Tools
SG_Tools -- "λꡬ μ€ν κ²°κ³Ό" --> C
C -- "μ΅μ’
λ³΄κ³ μ μμ± μμ²" --> LLM_Final
LLM_Final -- "μ΅μ’
κ²°κ³Ό μ λ¬" --> A
%% ========================
%% μ€νμΌ μ§μ (GitHub νΈν)
%% ========================
style A fill:#4CAF50,color:#fff,stroke:#388E3C,stroke-width:2px
style B fill:#FF9800,color:#fff,stroke:#EF6C00,stroke-width:2px
style C fill:#E91E63,color:#fff,stroke:#C2185B,stroke-width:2px
style D fill:#9C27B0,color:#fff,stroke:#7B1FA2,stroke-width:2px,shape:diamond
style SG_Tools fill:#E1F5FE, stroke:#0277BD,color:#000
style T1,T2,T3,T3_multi,T4,T5,T6 fill:#03A9F4,color:#fff,stroke:#0288D1,stroke-width:2px,shape:hexagon
style LLM_Final fill:#BA68C8,color:#fff,stroke:#8E24AA,stroke-width:2px
```
---
### (2) μΆμ μΆμ² λꡬ μμΈ β `recommend_festivals`
LLM κΈ°λ° **νμ΄λΈλ¦¬λ 5λ¨κ³ νμ΄νλΌμΈ**μ ν΅ν΄,
κ°κ² λ§μΆ€ν μΆμ λ₯Ό μΆμ²ν©λλ€.
```mermaid
graph TD
%% ========================
%% Orchestrator μμ²
%% ========================
subgraph SG_Orchestrator_Req ["π§ Orchestrator μμ²"]
Agent["π€ AgentExecutor"] -- "μΆμ μΆμ² μμ²" --> Tool_Rec["π§© Tool: recommend_festivals"]
end
%% ========================
%% μ§μ λ² μ΄μ€ (μμ )
%% ========================
subgraph SG_KnowledgeBase ["π μ§μ λ² μ΄μ€ (modules/knowledge_base.py)"]
direction LR
EM["𧬠Embedding Model\n(HuggingFace)"]
VSF["π FAISS (μΆμ DB)"]
EM -- "μλ² λ© μμ± (Offline)" --> VSF
end
%% ========================
%% Filtering Pipeline
%% ========================
subgraph SG_Filtering_Pipeline ["π Filtering Pipeline (modules/filtering.py)"]
Tool_Rec --> Step1["1οΈβ£ LLM 쿼리 μ¬μμ±"]
Step1 --> Step2["2οΈβ£ FAISS λ²‘ν° κ²μ\n(μ μ¬ μΆμ ν보 νμ)"]
%% RAG νλ¦ λͺ
νν (μμ )
Step2 -- "쿼리 μλ² λ©" --> EM
Step2 -- "μ μ¬λ κ²μ" --> VSF
Step2 --> Step3["3οΈβ£ LLM λμ μμ± νκ°\n(κ°κ² λ§μΆ€μ± νλ¨)"]
Step3 --> LLM1["π€ LLM (Dynamic Evaluation)"]
Step3 --> Step4["4οΈβ£ νμ΄λΈλ¦¬λ μ μ κ³μ°\n(μ μ¬λ + λ§μΆ€μ±)"]
Step4 --> Step5["5οΈβ£ μ΅μ’
κ²°κ³Ό ν¬λ§·ν
\n(Top3 + 2026 μμΈ‘ ν¬ν¨)"]
end
%% ========================
%% κ²°κ³Ό λ°ν
%% ========================
subgraph SG_Result_Return ["π¦ κ²°κ³Ό λ°ν"]
Step5 -- "Top3 μΆμ μΆμ² κ²°κ³Ό" --> Agent
end
%% ========================
%% μ€νμΌ
%% ========================
style Agent fill:#E91E63,color:#fff
style Tool_Rec fill:#03A9F4,color:#fff
style Step1,Step2,Step3,Step4,Step5 fill:#81D4FA,color:#000
style VSF fill:#FFC107,color:#000
style EM fill:#4DD0E1,color:#000
style LLM1 fill:#BA68C8,color:#fff
style SG_KnowledgeBase fill:#F5F5F5,stroke:#9E9E9E
```
---
### (3) λ§μΌν
μ λ΅ (RAG) λꡬ μμΈ β `search_contextual_marketing_strategy`
**RAG** κΈ°λ°μΌλ‘ **κ°κ² νλ‘ν + μ§λ¬Έ 컨ν
μ€νΈ**λ₯Ό μ΄μ©ν΄
κ°μ₯ κ΄λ ¨μ± λμ λ§μΌν
μ λ΅ λ¬Έμλ₯Ό κ²μνκ³ , LLMμ΄ μμ°μ€λ½κ² μμ½/μ μν©λλ€.
```mermaid
graph TD
%% ========================
%% Orchestrator μμ²
%% ========================
subgraph SG_Orchestrator_Req_RAG ["π§ Orchestrator μμ²"]
Agent["π€ AgentExecutor"] -- "λ§μΌν
μ λ΅ (RAG) μμ²" --> Tool_RAG["π§© Tool: search_contextual_marketing_strategy"]
end
%% ========================
%% μ§μ λ² μ΄μ€ (μμ )
%% ========================
subgraph SG_KnowledgeBase_RAG ["π μ§μ λ² μ΄μ€ (modules/knowledge_base.py)"]
direction LR
EM["𧬠Embedding Model\n(HuggingFace)"]
VSM["π FAISS (λ§μΌν
DB)"]
EM -- "μλ² λ© μμ± (Offline)" --> VSM
end
%% ========================
%% RAG Logic
%% ========================
subgraph SG_RAG_Logic ["βοΈ RAG Logic (tools/marketing_strategy.py)"]
Tool_RAG --> Step1["1οΈβ£ LLM κ²μ 쿼리 μμ±\n(κ°κ² νλ‘ν + μ§λ¬Έ κΈ°λ°)"]
Step1 --> Step2["2οΈβ£ FAISS λ²‘ν° κ²μ\n(λ§μΌν
DB νμ)"]
%% RAG νλ¦ λͺ
νν (μμ )
Step2 -- "쿼리 μλ² λ©" --> EM
Step2 -- "μ μ¬λ κ²μ" --> VSM
Step2 --> Step3["3οΈβ£ LLM λ΅λ³ μμ±\n(κ²μλ 컨ν
μ€νΈ κΈ°λ°)"]
Step3 --> LLM2["π€ LLM (Answer Synthesis)"]
end
%% ========================
%% κ²°κ³Ό λ°ν
%% ========================
subgraph SG_Result_Return_RAG ["π¦ κ²°κ³Ό λ°ν"]
Step3 -- "μμ±λ λ§μΌν
μ λ΅ ν
μ€νΈ" --> Agent
end
%% ========================
%% μ€νμΌ
%% ========================
style Agent fill:#E91E63,color:#fff
style Tool_RAG fill:#03A9F4,color:#fff
style Step1,Step2,Step3 fill:#81D4FA,color:#000
style VSM fill:#FFC107,color:#000
style EM fill:#4DD0E1,color:#000
style LLM2 fill:#BA68C8,color:#fff
style SG_KnowledgeBase_RAG fill:#F5F5F5,stroke:#9E9E9E
```
---
### (4) LLM κΈ°λ° λΆμ λꡬ μμΈ β `analyze_merchant_profile` / `analyze_festival_profile`
κ°κ² λλ μΆμ μ νλ‘ν(JSON)μ μ
λ ₯λ°μ
LLMμ΄ **SWOT λΆμ / μ£Όμ νΉμ§ μμ½**μ μνν©λλ€.
```mermaid
graph TD
%% ========================
%% Orchestrator μμ²
%% ========================
subgraph SG_Orchestrator_Req_Analyze ["π§ Orchestrator μμ²"]
Agent["π€ AgentExecutor"] -- "κ°κ²/μΆμ λΆμ μμ²" --> Tool_Analyze["π§© Tool: analyze_merchant_profile / analyze_festival_profile"]
end
%% ========================
%% LLM λΆμ
%% ========================
subgraph SG_LLM_Analysis ["π LLM λΆμ (tools/profile_analyzer.py)"]
Tool_Analyze -- "νλ‘ν(JSON) μ λ¬" --> LLM_Analyze["π€ LLM (SWOT / μμ½ λΆμ)"]
end
%% ========================
%% κ²°κ³Ό λ°ν
%% ========================
subgraph SG_Result_Return_Analyze ["π¦ κ²°κ³Ό λ°ν"]
LLM_Analyze -- "λΆμ λ³΄κ³ μ ν
μ€νΈ" --> Agent
end
%% ========================
%% μ€νμΌ
%% ========================
style Agent fill:#E91E63,color:#fff
style Tool_Analyze fill:#03A9F4,color:#fff
style LLM_Analyze fill:#BA68C8,color:#fff
```
------------------------------------------------------------------------
## π λ°μ΄ν° νλ¦ μμΈ
1. **μ΄κΈ° μ€μ (UI β API β UI)**
* `streamlit_app.py` μ€ν μ `load_data()` ν¨μκ° FastAPI μλ²(`api/server.py`)μ `/merchants` μλν¬μΈνΈλ₯Ό νΈμΆνμ¬ μ 체 κ°λ§Ήμ λͺ©λ‘(ID, μ΄λ¦)μ λ°μμ΅λλ€.
* μ¬μ©μκ° Streamlit λλ‘λ€μ΄ λ©λ΄μμ μμ μ κ°κ²λ₯Ό μ νν©λλ€.
* μ νλ κ°κ² IDλ‘ FastAPI μλ²μ `/profile` μλν¬μΈνΈλ₯Ό νΈμΆνμ¬ ν΄λΉ κ°κ²μ μμΈ νλ‘ν(JSON)κ³Ό μκΆ/μ
μ’
νκ· λ°μ΄ν°λ₯Ό λ°μμ΅λλ€.
* λ°μμ¨ νλ‘ν λ°μ΄ν°λ `modules/visualization.py`λ₯Ό ν΅ν΄ κ·Έλνμ νλ‘ μκ°νλμ΄ μ¬μ©μμκ² λ³΄μ¬μ§κ³ , `st.session_state.profile_data`μ μ μ₯λ©λλ€.
2. **컨μ€ν
μμ² (UI β Orchestrator)**
* μ¬μ©μκ° Streamlit μ±ν
μ
λ ₯μ°½μ μ§λ¬Έμ μ
λ ₯ν©λλ€.
* `streamlit_app.py`λ `orchestrator.invoke_agent()` ν¨μλ₯Ό νΈμΆν©λλ€.
* μ΄λ **μ¬μ©μ μ§λ¬Έ(Query)**, **μ±ν
μ©μΌλ‘ κ°κ³΅λ κ°κ² νλ‘ν(JSON λ¬Έμμ΄)**, **μ΄μ λν κΈ°λ‘(History)**, **λ§μ§λ§ μΆμ² μΆμ λͺ©λ‘(μ νμ )**μ΄ `Orchestrator`λ‘ μ λ¬λ©λλ€.
3. **μλ λΆμ λ° λꡬ λΌμ°ν
(Orchestrator β LLM β Tool)**
* `orchestrator.py`μ `AgentExecutor`λ μμ€ν
ν둬ννΈμ μ λ¬λ 컨ν
μ€νΈ(κ°κ² νλ‘ν, μ§λ¬Έ λ±)λ₯Ό μ‘°ν©νμ¬ **첫 λ²μ§Έ LLM(λꡬ μ νμ©)**μ νΈμΆν©λλ€.
* LLMμ μ§λ¬Έμ μλλ₯Ό λΆμνκ³ , μμ€ν
ν둬ννΈμ κ°μ΄λλΌμΈμ λ°λΌ `tools/tool_loader.py`μ μ μλ **λꡬ λͺ©λ‘ μ€ κ°μ₯ μ ν©ν λꡬλ₯Ό μ ν**νκ³ νμν μ
λ ₯κ°(Arguments)μ κ²°μ ν©λλ€.
4. **λꡬ μ€ν (Tool β Modules/API/VectorDB/LLM)**
* μ νλ λꡬ ν¨μ(`tools/*.py`)κ° μ€νλ©λλ€.
* λꡬλ νμμ λ°λΌ `modules/*.py`μ ν΅μ¬ λ‘μ§(μ: `FestivalRecommender`), μΈλΆ API(λ μ¨ λ±), VectorDB(`modules/knowledge_base.py` κ²½μ ), λλ λ³λμ LLM(`modules/llm_provider.py` κ²½μ )μ νΈμΆνμ¬ μμ
μ μνν©λλ€.
5. **κ²°κ³Ό μ·¨ν© λ° λ°λ³΅ (Tool β Orchestrator β LLM β Tool ...)**
* λꡬ μ€ν κ²°κ³Ό(Observation)λ λ€μ `AgentExecutor`λ‘ λ°νλ©λλ€.
* μμ΄μ νΈλ μ΄ κ²°κ³Όλ₯Ό λ°νμΌλ‘ **λ€μ νλμ κ²°μ **ν©λλ€. (μ: μΆκ° μ λ³΄κ° νμνλ©΄ λ€λ₯Έ λꡬλ₯Ό νΈμΆνκ±°λ, λͺ¨λ μ λ³΄κ° λͺ¨μλ€κ³ νλ¨λλ©΄ μ΅μ’
λ΅λ³ μμ±μ μ€λΉ)
* μ΄ "LLM νλ¨ β λꡬ νΈμΆ β κ²°κ³Ό νμΈ" κ³Όμ μ μ¬μ©μμ μμ²μ΄ μμ ν ν΄κ²°λ λκΉμ§ **μ¬λ¬ λ² λ°λ³΅**λ μ μμ΅λλ€ (Agentic νΉμ±).
6. **μ΅μ’
λ΅λ³ μμ± λ° μΆλ ₯ (Orchestrator β LLM β UI)**
* `AgentExecutor`κ° μ΅μ’
μ μΌλ‘ λμΆν κ²°κ³Ό(`response['output']`) λλ νμ μ `orchestrator.py`κ° μ§μ **λ λ²μ§Έ LLM(λ΅λ³ μμ±μ©)**μ νΈμΆνμ¬, λͺ¨λ μ€κ° κ²°κ³Όμ 컨ν
μ€νΈλ₯Ό μ’
ν©ν **μ΅μ’
컨μ€ν
λ³΄κ³ μ(μμ°μ΄)**λ₯Ό μμ±ν©λλ€.
* μμ±λ λ³΄κ³ μλ `streamlit_app.py`λ‘ λ°νλμ΄ μ¬μ©μ νλ©΄μ μΆλ ₯λ©λλ€.
---
## βοΈ μ£Όμ νΉμ§ μμ½
| κΈ°λ₯ | μ€λͺ
|
| :--------------------- | :------------------------------------------------------------------------------------------- |
| **Agentic RAG** | LLM μμ΄μ νΈκ° κ°κ² νλ‘ν 컨ν
μ€νΈλ₯Ό λ°νμΌλ‘ μ€μ€λ‘ λꡬλ₯Ό μ ννκ³ , λμ μΌλ‘ RAG κ²μ 쿼리λ₯Ό μμ±νμ¬ μ€ν |
| **Tool Calling Agent** | LangChainμ `create_tool_calling_agent`λ₯Ό μ¬μ©νμ¬ μ¬λ¬ λꡬλ₯Ό μμ¨μ μΌλ‘ νΈμΆ λ° μ°κ³ |
| **νμ΄λΈλ¦¬λ μΆμ²** | FAISS λ²‘ν° κ²μ(μ μ¬λ) + LLM λμ νκ°(λ§μΆ€μ±) μ μλ₯Ό κ²°ν©νμ¬ μΆμ μΆμ² μ νλ ν₯μ |
| **컨ν
μ€νΈ κΈ°λ° λΆμ** | λͺ¨λ λꡬ νΈμΆ λ° μ΅μ’
λ΅λ³ μμ± μ, νμ¬ λΆμ μ€μΈ κ°κ²μ νλ‘ν(JSON)μ ν΅μ¬ 컨ν
μ€νΈλ‘ νμ© |
| **λͺ¨λνλ ꡬ쑰** | κΈ°λ₯λ³(UI, API, Orchestrator, Modules, Tools)λ‘ μ½λλ₯Ό λΆλ¦¬νμ¬ μ μ§λ³΄μμ± λ° νμ₯μ± μ¦λ |
| **λ°μ΄ν° μΊμ±** | Streamlitμ `@st.cache_data` / `@st.cache_resource`λ₯Ό νμ©νμ¬ λ°μ΄ν° λ° λͺ¨λΈ λ‘λ© μλ μ΅μ ν |
---
## π‘ κΈ°μ μ€ν
* **Frontend:** Streamlit
* **Backend (Data API):** FastAPI
* **LLM:** Google Gemini 2.5 Flash (`gemini-2.5-flash`)
* **AI Framework:** LangChain (Agents, Tool Calling, Prompts)
* **VectorStore:** FAISS (Facebook AI Similarity Search)
* **Embedding model:** HuggingFace `dragonkue/BGE-m3-ko` (νκ΅μ΄ νΉν λͺ¨λΈ)
* **Data Handling:** Pandas, NumPy
* **Visualization:** Matplotlib
---
## π μ€ν λ°©λ²
### 1οΈβ£ μ¬μ μ€λΉ
* Python 3.11 μ΄μ μ€μΉ
* `uv` (Python ν¨ν€μ§ μ€μΉ λꡬ) μ€μΉ (`pip install uv`)
* Google API Key λ°κΈ (Gemini λͺ¨λΈ μ¬μ©)
### 2οΈβ£ FastAPI μλ² μ€ν
FastAPI μλ²λ κ°λ§Ήμ λ°μ΄ν°(`final_df.csv`)λ₯Ό λ‘λνκ³ , `/profile` (κ°κ² μμΈ μ 보), `/merchants` (κ°κ² λͺ©λ‘) μλν¬μΈνΈλ₯Ό μ 곡ν©λλ€.
```bash
# 1. νλ‘μ νΈ λ£¨νΈ ν΄λλ‘ μ΄λ
cd C:(λ€μ΄λ°μ ν΄λ μμΉ)
# 2. κ°μνκ²½ μμ± λ° νμ±ν (μ΅μ΄ 1ν)
uv venv
# 3. κ°μνκ²½ νμ±ν (Windows)
.\.venv\Scripts\activate.bat
# (macOS/Linux: source .venv/bin/activate)
# 4. νμν λΌμ΄λΈλ¬λ¦¬ μ€μΉ
uv pip install -r requirements.txt
# 5. FastAPI μλ² μ€ν (api ν΄λμ server.pyλ₯Ό λͺ¨λλ‘ μ€ν)
python -m api.server
### 3οΈβ£ Streamlit μ± μ€ν
Streamlit μ±μ μ¬μ©μ μΈν°νμ΄μ€λ₯Ό μ 곡νκ³ , FastAPI μλ²μμ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ©°, `Orchestrator`λ₯Ό ν΅ν΄ AI 컨μ€ν
μ μνν©λλ€.
```bash
# 1. (FastAPI μλ²μ λ€λ₯Έ ν°λ―Έλμμ) νλ‘μ νΈ λ£¨νΈ ν΄λλ‘ μ΄λ
cd C:\(λ€μ΄λ°μ ν΄λ μμΉ)
# 2. κ°μνκ²½ νμ±ν (Windows)
.\.venv\Scripts\activate.bat
# (macOS/Linux: source .venv/bin/activate)
# 3. Streamlit secrets νμΌ μμ± (μ΅μ΄ 1ν)
# - .streamlit ν΄λλ₯Ό μμ±ν©λλ€.
mkdir .streamlit
# μλ λͺ
λ Ήμ΄μ "(λ°κΈλ°μ gemini API key)" λΆλΆμ μ€μ ν€λ‘ λ체νμΈμ.
echo GOOGLE_API_KEY="(λ°κΈλ°μ gemini API key)" > .streamlit\secrets.toml
# 4. Streamlit μ± μ€ν
uv run streamlit run streamlit_app.py
```
μ΄μ μΉ λΈλΌμ°μ μμ Streamlit μ± μ£Όμ(λ³΄ν΅ http://localhost:8501)λ‘ μ μνμ¬ MarketSyncλ₯Ό μ¬μ©ν μ μμ΅λλ€.
------------------------------------------------------------------------
## π μμ μλ리μ€
| μ¬μ©μ μ
λ ₯ | μ£Όμ μ€ν λꡬ | μμ κ²°κ³Ό |
| :---------------------------------- | :------------------------------------------------------ | :-------------------------------------- |
| "μ°λ¦¬ κ°κ² λΆμν΄μ€" | `analyze_merchant_profile` | κ°κ² SWOT λΆμ λ° ν΅μ¬ κ³ κ° λ¦¬ν¬νΈ |
| "μ£Όλ§ λ°©λ¬Έκ° λ릴 λ§ν μΆμ μΆμ²ν΄μ€" | `recommend_festivals` | Top 3 λ§μΆ€ μΆμ μΆμ² 리μ€νΈ |
| "`μμΈλμ νΈνμ΄` λ§μΌν
μ λ΅ μλ €μ€" | `create_festival_specific_marketing_strategy` | ν΄λΉ μΆμ λ§μΆ€ν λ§μΌν
μ λ΅ μ μ |
| "μΆμ²λ μΆμ λ€ λ§μΌν
λ°©λ² μλ €μ€" | `create_marketing_strategies_for_multiple_festivals` | μ¬λ¬ μΆμ μ λν ν΅ν© λ§μΌν
μ λ΅ μ μ |
| "μμ¦ λ¨λ ν보 λ°©λ² μλ €μ€" | `search_contextual_marketing_strategy` (RAG) | κ°κ² νΉμ± κΈ°λ° μ΅μ λ§μΌν
νΈλ λ/ν |
---
## π§ ν΅μ¬ μμ΄λμ΄
> "LLMμ΄ μ€μ€λ‘ λꡬλ₯Ό μ ννκ³ μ€ννλ **Agentic RAG**"
* **LangChainμ Tool-Calling Agent ꡬ쑰**: LLMμ΄ μ¬μ©μμ 볡μ‘ν μμ²μ μ΄ν΄νκ³ , νμν κΈ°λ₯(λꡬ)μ μμ¨μ μΌλ‘ νΈμΆνλ©° μμ
μ μνν©λλ€.
* **컨ν
μ€νΈ κΈ°λ° μμ¬κ²°μ **: κ°κ² νλ‘ν(JSON) λ°μ΄ν°λ₯Ό ν΅μ¬ 컨ν
μ€νΈλ‘ νμ©νμ¬, λͺ¨λ λΆμκ³Ό μΆμ²μ΄ νμ¬ λΆμ μ€μΈ κ°κ²μ λ§μΆ° μ΄λ£¨μ΄μ§λλ€.
* **νμ΄λΈλ¦¬λ μΆμ² μμ§**: FAISS λ²‘ν° κ²μ(μ μ¬λ κΈ°λ°)κ³Ό LLM μ¬νκ°(κ°κ² λ§μΆ€μ± κΈ°λ°)λ₯Ό κ²°ν©νμ¬ μΆμ²μ μ νμ±κ³Ό κ΄λ ¨μ±μ κ·Ήλνν©λλ€.
"# MarketSync"