μ°¨μΈλ AI λ©ν°μμ΄μ νΈ νμ μ°κ΅¬ νλ«νΌ
AutoGen STORM Researchλ Microsoft AutoGen νλ μμν¬λ₯Ό κΈ°λ°μΌλ‘ ꡬμΆλ μ§λ₯ν μ°κ΅¬ μ΄μμ€ν΄νΈμ λλ€. μ¬λ¬ AI μμ΄μ νΈκ° νμ νμ¬ μ λ¬Έκ° μμ€μ μ¬μΈ΅ μ°κ΅¬λ₯Ό μννκ³ , μ¬μ©μμ μΈν°λν°λΈνκ² μν΅νλ©° κ³ νμ§ λ³΄κ³ μλ₯Ό μμ±ν©λλ€.
- μ§λ₯ν λΆμκ° μμ±: μ°κ΅¬ μ£Όμ μ λ§λ λ€μν μ λ¬Έ λΆμΌ AI λΆμκ°λ€μ μλ μμ±
- λ³λ ¬ μΈν°λ·° μμ€ν : μ¬λ¬ λΆμκ°κ° λμμ μ λ¬Έκ°μ μ¬μΈ΅ μΈν°λ·° μ§ν
- νμ λ³΄κ³ μ μμ±: κ° λΆμΌ μ λ¬Έκ°λ€μ μΈμ¬μ΄νΈλ₯Ό μ’ ν©ν νμ μμ€μ λ³΄κ³ μ μμ±
- λ©ν°μμ€ κ²μ: 5κ°μ§ κ²μ λꡬλ₯Ό νμ©ν μ’
ν©μ μ 보 μμ§
- π Tavily Search: μ΅μ μΉ μ 보 λ° μ€μκ° λν₯
- ποΈ DuckDuckGo: νλΌμ΄λ²μ μ€μ κ²μ
- π° Naver News: νκ΅ κ΄λ ¨ μ΅μ λ΄μ€ λ° μ¬ν λν₯
- π Wikipedia: κΈ°λ³Έ κ°λ , μ μ, μμ¬μ λ°°κ²½
- π ArXiv: νμ λ Όλ¬Έ λ° μ΅μ μ°κ΅¬ μλ£
- μ€μκ° μ§ν μΆμ : WebSocket/SSE κΈ°λ° μ€μκ° μ°κ΅¬ κ³Όμ λͺ¨λν°λ§
- μ¬μ©μ νΌλλ°± λ°μ: μ°κ΅¬ κ²°κ³Όμ λν νΌλλ°±μ λ°μ μΆκ° λΆμκ° μμ± λ° μ¬μ°κ΅¬
- λ²μ κ΄λ¦¬: μλ³Έ μ°κ΅¬ β νΌλλ°± κ°μ λ²μ μΆμ λ° κ΄λ¦¬
- Azure OpenAI: GPT-4, GPT-4o (κΈ°λ³Έ κΆμ₯)
- OpenAI: GPT-4o, GPT-4o-mini
- Anthropic: Claude 3.5 Sonnet
- λμ λͺ¨λΈ μ ν: API ν€ μνμ λ°λ₯Έ μλ λ°±μ λͺ¨λΈ μ¬μ©
graph TB
subgraph "Frontend Layer"
A[Next.js 15 UI<br/>ν¬νΈ 3001]
end
subgraph "Backend Layer"
B[FastAPI Server<br/>ν¬νΈ 8002]
C[μ€μκ° ν΅μ <br/>WebSocket + SSE]
end
subgraph "AI Agent Layer"
D[λΆμκ° μμ±κΈ°]
E[μΈν°λ·°μ΄ μμ΄μ νΈ]
F[μ λ¬Έκ° μμ΄μ νΈ]
G[λ³΄κ³ μ μμ±μ]
end
subgraph "Data Sources"
H[Tavily Search]
I[DuckDuckGo]
J[Naver News]
K[Wikipedia]
L[ArXiv]
end
subgraph "AI Models"
M[Azure OpenAI]
N[OpenAI]
O[Anthropic]
end
A <--> B
B <--> C
B <--> D
D <--> E
E <--> F
F <--> G
F <--> H
F <--> I
F <--> J
F <--> K
F <--> L
D <--> M
E <--> N
F <--> O
- Python 3.11+
- Node.js 18+
- uv (Python ν¨ν€μ§ λ§€λμ )
- npm λλ yarn
-
μ μ₯μ ν΄λ‘
git clone https://github.com/jh941213/autogen_storm_research.git cd autogen_storm_research -
νκ²½ λ³μ μ€μ
cd storm-research cp .env.example .env # .env νμΌμ νΈμ§νμ¬ API ν€λ€μ μ€μ νμΈμ
-
νμ API ν€ μ€μ (
.envνμΌ)# Azure OpenAI (κΆμ₯ - κ°μ₯ μμ μ ) AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/ AZURE_OPENAI_API_KEY=your_azure_openai_key AZURE_OPENAI_DEPLOYMENT=gpt-4o AZURE_OPENAI_API_VERSION=2024-12-01-preview # κ²μ API (νμ) TAVILY_API_KEY=your_tavily_api_key # μΆκ° κ²μ API (μ νμ¬ν) NAVER_CLIENT_ID=your_naver_client_id NAVER_CLIENT_SECRET=your_naver_client_secret # λμ AI λͺ¨λΈ (μ νμ¬ν) OPENAI_API_KEY=your_openai_key ANTHROPIC_API_KEY=your_anthropic_key # μΆμ /λͺ¨λν°λ§ (μ νμ¬ν) LANGFUSE_SECRET_KEY=your_langfuse_secret LANGFUSE_PUBLIC_KEY=your_langfuse_public LANGFUSE_HOST=https://us.cloud.langfuse.com
-
μ 체 μμ€ν μ€ν
# λ°±μλ + νλ‘ νΈμλ λμ μ€ν ./run-all.shλλ κ°λ³ μ€ν:
# λ°±μλλ§ μ€ν (ν¬νΈ 8002) ./start.sh # νλ‘ νΈμλλ§ μ€ν (ν¬νΈ 3001) cd frontend ./start.sh
-
μΉ λΈλΌμ°μ μμ μ μ
http://localhost:3001
- μ°κ΅¬ μ£Όμ μ λ ₯: κ΄μ¬ μλ μ£Όμ λ₯Ό μμ°μ΄λ‘ μ λ ₯
- AI λͺ¨λΈ μ ν: Azure OpenAI, OpenAI, λλ Anthropic μ€ μ ν
- μ€μ μ‘°μ :
- λΆμκ° μ (1-10λͺ )
- μΈν°λ·° ν΄ μ (1-10ν΄)
- λ³λ ¬/μμ°¨ μΈν°λ·° λͺ¨λ
- μ°κ΅¬ μμ: μ€μκ°μΌλ‘ μ§ν μν© λͺ¨λν°λ§
- κ²°κ³Ό νμΈ: μμ±λ μ’ ν© λ³΄κ³ μ κ²ν
- μ΄κΈ° μ°κ΅¬ μλ£ ν κ²°κ³Ό νμ΄μ§μμ "νΌλλ°± μ μΆ" ν΄λ¦
- κ°μ μμ²μ¬ν μ λ ₯ (μ: "κ²½μ μ μΈ‘λ©΄μ λ μμΈν λ€λ€μ£ΌμΈμ")
- μλ κ³ κΈ μ²λ¦¬:
- νΌλλ°± λΆμ
- μΆκ° μ λ¬Έ λΆμκ° 1λͺ μμ±
- κΈ°μ‘΄ + μΆκ° λΆμκ°λ‘ μ 체 μ¬μ°κ΅¬
- νΌλλ°± μ€μ¬μ μλ‘μ΄ λ³΄κ³ μ μμ±
- κ°μ λ λ²μ νμΈ λ° νμ€ν 리 κ΄λ¦¬
μ°κ΅¬ μ§ν μ€ λ€μ λ¨κ³λ€μ μ€μκ°μΌλ‘ νμΈν μ μμ΅λλ€:
- π§ μ€μ (0-10%): μ°κ΅¬ νκ²½ μ€λΉ
- π₯ λΆμκ° μμ± (10-30%): μ λ¬Έ λΆμΌλ³ AI λΆμκ° μμ±
- π€ μΈν°λ·° μ§ν (30-80%): κ° λΆμκ°μ μ λ¬Έκ° κ° μ¬μΈ΅ μΈν°λ·°
- π λ³΄κ³ μ μμ± (80-100%): μ’ ν© λΆμ λ° λ³΄κ³ μ μμ±
- SSE (Server-Sent Events): μ°μ μ¬μ©λλ μ€μκ° μ€νΈλ¦¬λ°
- WebSocket: μλ°©ν₯ ν΅μ μ΄ νμν κ²½μ°
- HTTP ν΄λ§: λ€νΈμν¬ λ¬Έμ μ λ°±μ λ°©μ
- workflow.py: μ 체 μ°κ΅¬ μν¬νλ‘μ° μ€μΌμ€νΈλ μ΄μ
- agents.py: κ°μ’ AI μμ΄μ νΈ μ μ λ° κ΄λ¦¬
- tools.py: κ²μ λꡬ ν΅ν© λ° κ΄λ¦¬
- tracing.py: μ±λ₯ λͺ¨λν°λ§ λ° μΆμ
- Aurora ν μ€νΈ ν¨κ³Ό: νμ΄ν μ λλ©μ΄μ
- μ€μκ° μ§νλ₯ : μμΈν νλ λ‘κ·Έμ ν¨κ»
- λ°μν λμμΈ: λͺ¨λ λλ°μ΄μ€μμ μ΅μ ν
- λ€ν¬λͺ¨λ μ§μ: λμ νΈν ν λ§
| μλν¬μΈνΈ | λ©μλ | μ€λͺ |
|---|---|---|
/research/start |
POST | μλ‘μ΄ μ°κ΅¬ μμ |
/research/progress/{session_id} |
GET | μ°κ΅¬ μ§ν μν© μ‘°ν |
/research/progress/{session_id}/stream |
GET | SSE μ€μκ° μ€νΈλ¦Ό |
/research/result/{session_id} |
GET | μ°κ΅¬ κ²°κ³Ό μ‘°ν |
/research/feedback/{session_id} |
POST | νΌλλ°± μ μΆ λ° μ¬μ°κ΅¬ |
/research/history/{session_id} |
GET | μ°κ΅¬ νμ€ν 리 μ‘°ν |
| μλν¬μΈνΈ | λ©μλ | μ€λͺ |
|---|---|---|
/research/tasks |
GET | λͺ¨λ μ°κ΅¬ μμ λͺ©λ‘ |
/research/task/{session_id} |
GET | νΉμ μ°κ΅¬ μμ μ‘°ν |
/research/task/{session_id} |
DELETE | μ°κ΅¬ μμ μμ |
/health |
GET | μλ² μν νμΈ |
# μ°κ΅¬ μμ
curl -X POST "http://localhost:8002/research/start" \
-H "Content-Type: application/json" \
-d '{
"topic": "μΈκ³΅μ§λ₯μ λ―Έλμ μ¬νμ μν₯",
"max_analysts": 3,
"max_interview_turns": 3,
"parallel_interviews": true,
"model_provider": "azure_openai"
}'
# μ§ν μν© νμΈ
curl "http://localhost:8002/research/progress/{session_id}"
# SSE μ€νΈλ¦Ό μ°κ²°
curl -N "http://localhost:8002/research/progress/{session_id}/stream"# Docker μ΄λ―Έμ§ λΉλ
docker build -t autogen-storm-research .
# 컨ν
μ΄λ μ€ν
docker run -p 8002:8002 -p 3001:3001 \
-e AZURE_OPENAI_API_KEY=your_key \
-e TAVILY_API_KEY=your_key \
autogen-storm-research# Cloud Build μ¬μ©
gcloud builds submit --config cloudbuild.yaml# Railway CLI μ¬μ©
railway uprender.yamlμ€μ νμΌμ ν΅ν μλ λ°°ν¬
cd frontend
vercel --prod# λ°±μλ κ°λ° λͺ¨λ
cd storm-research
uv venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
uv pip install -r requirements.txt
python app_interactive.py
# νλ‘ νΈμλ κ°λ° λͺ¨λ
cd frontend
npm install
npm run devstorm-research/
βββ autogen_storm/ # ν΅μ¬ AI μμ΄μ νΈ λͺ¨λ
β βββ workflow.py # μ°κ΅¬ μν¬νλ‘μ° μ€μΌμ€νΈλ μ΄μ
β βββ agents.py # AI μμ΄μ νΈ μ μ
β βββ tools.py # κ²μ λꡬ ν΅ν©
β βββ models.py # λ°μ΄ν° λͺ¨λΈ μ μ
β βββ config.py # μ€μ κ΄λ¦¬
β βββ tracing.py # μ±λ₯ μΆμ
βββ app_interactive.py # FastAPI λ©μΈ μ ν리μΌμ΄μ
βββ requirements.txt # Python μμ‘΄μ±
βββ frontend/ # Next.js νλ‘ νΈμλ
βββ src/
β βββ app/ # Next.js App Router νμ΄μ§
β βββ components/ # React μ»΄ν¬λνΈ
β βββ lib/ # μ νΈλ¦¬ν° ν¨μ
β βββ store/ # Zustand μν κ΄λ¦¬
βββ package.json # Node.js μμ‘΄μ±
# λ°±μλ ν
μ€νΈ
cd storm-research
python test_imports.py # λͺ¨λ μν¬νΈ ν
μ€νΈ
python test_websocket.py # WebSocket ν
μ€νΈ
python test_api_request.py # API μμ² ν
μ€νΈ
# νλ‘ νΈμλ ν
μ€νΈ
cd frontend
npm run test # Jest ν
μ€νΈ μ€ν
npm run build # λΉλ ν
μ€νΈ# .env νμΌμ μ¬λ°λ₯Έ API ν€κ° μ€μ λμ΄ μλμ§ νμΈ
cat .env | grep API_KEY
# Tavily API ν€ ν
μ€νΈ
curl -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{"api_key": "your_tavily_key", "query": "test"}'# ν¬νΈ μ¬μ© μ€μΈ νλ‘μΈμ€ νμΈ
lsof -i :8002 # λ°±μλ ν¬νΈ
lsof -i :3001 # νλ‘ νΈμλ ν¬νΈ
# νλ‘μΈμ€ μ’
λ£
kill -9 <PID># Python μμ‘΄μ± μ¬μ€μΉ
cd storm-research
uv pip install -r requirements.txt --force-reinstall
# Node.js μμ‘΄μ± μ¬μ€μΉ
cd frontend
rm -rf node_modules package-lock.json
npm install- λ°©νλ²½μ΄λ νλ‘μκ° WebSocketμ μ°¨λ¨νλ κ²½μ°
- HTTP ν΄λ§ λͺ¨λλ‘ μλ λ°±μ λλ―λ‘ κΈ°λ₯μ μ μ μλ
# λ°±μλ λ‘κ·Έ
tail -f storm-research/server.log
# νλ‘ νΈμλ κ°λ° μλ² λ‘κ·Έ
cd frontend
npm run dev # ν°λ―Έλμμ μ§μ λ‘κ·Έ νμΈ- ν¬ν¬: μ΄ μ μ₯μλ₯Ό ν¬ν¬νμΈμ
- λΈλμΉ: μλ‘μ΄ κΈ°λ₯ λΈλμΉλ₯Ό μμ±νμΈμ
git checkout -b feature/amazing-feature
- 컀λ°: λ³κ²½μ¬νμ 컀λ°νμΈμ
git commit -m "Add amazing feature" - νΈμ: λΈλμΉμ νΈμνμΈμ
git push origin feature/amazing-feature
- ν 리νμ€νΈ: Pull Requestλ₯Ό μμ±νμΈμ
- μ½λ μ€νμΌ: Pythonμ Black, TypeScriptλ ESLint/Prettier μ¬μ©
- μ»€λ° λ©μμ§: Conventional Commits νμ μ€μ
- ν μ€νΈ: μλ‘μ΄ κΈ°λ₯μλ λ°λμ ν μ€νΈ μΆκ°
- λ¬Έμν: READMEμ API λ¬Έμ μ λ°μ΄νΈ
μ΄ νλ‘μ νΈλ MIT Licenseμ λ°λΌ λΌμ΄μ μ€κ° λΆμ¬λ©λλ€.
- Microsoft AutoGen: κ°λ ₯ν λ©ν°μμ΄μ νΈ νλ μμν¬ μ 곡
- FastAPI: νλμ μ΄κ³ λΉ λ₯Έ μΉ νλ μμν¬
- Next.js: μ΅κ³ μ React κΈ°λ° νλ‘ νΈμλ νλ μμν¬
- Tavily: κ³ νμ§ κ²μ API μλΉμ€
- OpenAI, Anthropic, Microsoft: νμ μ μΈ AI λͺ¨λΈ μ 곡
β¨ AutoGen STORM Research Assistantλ‘ AI νμ μ°κ΅¬μ μλ‘μ΄ κ²½νμ μμνμΈμ! β¨
π μμνκΈ° β’ π λ¬Έμ β’ π μ΄μ 리ν¬νΈ β’ π¬ ν λ‘