MarketSync / README.md
hyeonjoo's picture
Update README.md
5644fda verified
---
title: MarketSync
emoji: ๐ŸŽ‰
colorFrom: blue
colorTo: green
sdk: streamlit
app_file: streamlit_app.py
pinned: false
---
# ๐ŸŽ‰ MarketSync (๋งˆ์ผ“์‹ฑํฌ)
... (๊ธฐ์กด README ๋‚ด์šฉ์€ ๊ทธ๋Œ€๋กœ ๋‘ ) ...
# ๐ŸŽ‰ 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`)**: <br> 1. LLM ์ฟผ๋ฆฌ ์žฌ์ž‘์„ฑ <br> 2. FAISS ๋ฒกํ„ฐ ๊ฒ€์ƒ‰ (์œ ์‚ฌ ์ถ•์ œ ํ›„๋ณด ์„ ์ •) <br> 3. LLM ๋™์  ์†์„ฑ ํ‰๊ฐ€ (๊ฐ€๊ฒŒ ๋งž์ถค์„ฑ) <br> 4. ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ ์ˆ˜ ๊ณ„์‚ฐ <br> 5. ์ตœ์ข… Top3 ๊ฒฐ๊ณผ ํฌ๋งทํŒ… (2026 ์˜ˆ์ธก ํฌํ•จ) |
| **๋งˆ์ผ€ํŒ… (RAG)** | `search_contextual_marketing_strategy` (marketing\_strategy.py) | **์ปจํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ RAG (`knowledge_base.py`)**: <br> 1. ๊ฐ€๊ฒŒ ํ”„๋กœํ•„ + ์งˆ๋ฌธ โ†’ LLM ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ ์ƒ์„ฑ <br> 2. FAISS ๋ฒกํ„ฐ ๊ฒ€์ƒ‰ (๊ด€๋ จ ์ „๋žต ๋ฌธ์„œ ์ถ”์ถœ) <br> 3. LLM ๋‹ต๋ณ€ ์ƒ์„ฑ (์ถ”์ถœ๋œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฌ์šด ์ „๋žต ์ œ์•ˆ) |
| **๋งˆ์ผ€ํŒ… (์ƒ์„ฑ)** | `create_festival_specific_marketing_strategy` (marketing\_strategy.py) | **LLM ๊ธฐ๋ฐ˜ ์ „๋žต ์ƒ์„ฑ**: <br> 1. ์ถ•์ œ ํ”„๋กœํ•„ ์กฐํšŒ (`profile_analyzer.py`) <br> 2. ๊ฐ€๊ฒŒ ํ”„๋กœํ•„ + ์ถ•์ œ ํ”„๋กœํ•„ + RAG ๊ฒ€์ƒ‰ โ†’ LLM ํ”„๋กฌํ”„ํŠธ ๊ตฌ์„ฑ <br> 3. LLM์ด ํŠน์ • ์ถ•์ œ ๋งž์ถค ์ „๋žต ์ƒ์„ฑ |
| **๋งˆ์ผ€ํŒ… (์ƒ์„ฑ)** | `create_marketing_strategies_for_multiple_festivals` (marketing\_strategy.py) | **LLM ๊ธฐ๋ฐ˜ ์ „๋žต ์ƒ์„ฑ (๋‹ค์ˆ˜)**: <br> 1. ์—ฌ๋Ÿฌ ์ถ•์ œ ์ด๋ฆ„ ์ž…๋ ฅ๋ฐ›์Œ <br> 2. ๊ฐ ์ถ•์ œ๋ณ„๋กœ `create_festival_specific_marketing_strategy` ๋ฐ˜๋ณต ํ˜ธ์ถœ <br> 3. ๋ชจ๋“  ์ „๋žต์„ ํ•˜๋‚˜์˜ ๋ณด๊ณ ์„œ๋กœ ์ทจํ•ฉ |
| **๊ฐ€๊ฒŒ ๋ถ„์„** | `analyze_merchant_profile` (profile\_analyzer.py) | **LLM ๊ธฐ๋ฐ˜ ๋ถ„์„**: <br> ๊ฐ€๊ฒŒ ํ”„๋กœํ•„(JSON) ์ž…๋ ฅ โ†’ LLM์ด SWOT ๋ถ„์„ ๋ฐ ํ•ต์‹ฌ ๊ณ ๊ฐ ํŠน์„ฑ ์š”์•ฝ ๋ณด๊ณ ์„œ ์ƒ์„ฑ |
| **์ถ•์ œ ๋ถ„์„** | `analyze_festival_profile` (profile\_analyzer.py) | **LLM ๊ธฐ๋ฐ˜ ๋ถ„์„**: <br> ์ถ•์ œ ํ”„๋กœํ•„(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)**
* `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"