131 lines
4.5 KiB
Python
131 lines
4.5 KiB
Python
"""
|
||
FastAPI 메인 애플리케이션
|
||
"""
|
||
import uvicorn
|
||
from fastapi import FastAPI
|
||
from fastapi.middleware.cors import CORSMiddleware
|
||
from fastapi.responses import HTMLResponse
|
||
|
||
from app.core.config import settings
|
||
from app.api.endpoints import router
|
||
|
||
# FastAPI 앱 생성
|
||
app = FastAPI(
|
||
title="Q-Table 협상 전략 데모 API",
|
||
description="기업 간 협상 시뮬레이션을 위한 강화학습 Q-Table 데모 API",
|
||
version="1.0.0",
|
||
docs_url="/docs",
|
||
redoc_url="/redoc"
|
||
)
|
||
|
||
# CORS 설정
|
||
app.add_middleware(
|
||
CORSMiddleware,
|
||
allow_origins=settings.allowed_origins,
|
||
allow_credentials=True,
|
||
allow_methods=["*"],
|
||
allow_headers=["*"],
|
||
)
|
||
|
||
# API 라우터 등록
|
||
app.include_router(router, prefix="/api/v1")
|
||
|
||
|
||
@app.get("/", response_class=HTMLResponse)
|
||
async def root():
|
||
"""루트 페이지"""
|
||
html_content = """
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>Q-Table 협상 전략 데모 API</title>
|
||
<style>
|
||
body { font-family: Arial, sans-serif; margin: 40px; }
|
||
.header { color: #2c3e50; }
|
||
.section { margin: 20px 0; }
|
||
.link { color: #3498db; text-decoration: none; }
|
||
.link:hover { text-decoration: underline; }
|
||
.code { background-color: #f8f9fa; padding: 2px 4px; border-radius: 3px; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1 class="header">🎯 Q-Table 협상 전략 데모 API</h1>
|
||
|
||
<div class="section">
|
||
<h2>📋 API 문서</h2>
|
||
<ul>
|
||
<li><a href="/docs" class="link">Swagger UI</a> - 대화형 API 문서</li>
|
||
<li><a href="/redoc" class="link">ReDoc</a> - 깔끔한 API 문서</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>🚀 주요 기능</h2>
|
||
<ul>
|
||
<li><strong>보상 계산:</strong> <span class="code">POST /api/v1/reward/calculate</span></li>
|
||
<li><strong>에피소드 생성:</strong> <span class="code">POST /api/v1/episodes/generate</span></li>
|
||
<li><strong>Q-Learning 업데이트:</strong> <span class="code">POST /api/v1/learning/q-learning</span></li>
|
||
<li><strong>FQI+CQL 학습:</strong> <span class="code">POST /api/v1/learning/fqi-cql</span></li>
|
||
<li><strong>행동 추천:</strong> <span class="code">POST /api/v1/action/recommend</span></li>
|
||
<li><strong>시스템 상태:</strong> <span class="code">GET /api/v1/status</span></li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>📊 데이터 조회</h2>
|
||
<ul>
|
||
<li><strong>Q-Table:</strong> <span class="code">GET /api/v1/qtable</span></li>
|
||
<li><strong>경험 데이터:</strong> <span class="code">GET /api/v1/experiences</span></li>
|
||
<li><strong>FQI+CQL 결과:</strong> <span class="code">GET /api/v1/fqi-cql</span></li>
|
||
<li><strong>정책 비교:</strong> <span class="code">GET /api/v1/compare/{state}</span></li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>🔧 유틸리티</h2>
|
||
<ul>
|
||
<li><strong>헬스 체크:</strong> <span class="code">GET /api/v1/health</span></li>
|
||
<li><strong>시스템 초기화:</strong> <span class="code">POST /api/v1/reset</span></li>
|
||
<li><strong>설정 조회:</strong> <span class="code">GET /api/v1/config</span></li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>🎮 프론트엔드</h2>
|
||
<p>Streamlit 기반 대화형 인터페이스: <a href="http://localhost:8501" class="link">http://localhost:8501</a></p>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>📝 보상함수</h2>
|
||
<p><strong>R(s,a) = W × (A/P) + (1-W) × End</strong></p>
|
||
<ul>
|
||
<li><strong>W:</strong> 가중치 = (S_n + PZ_n) / 2</li>
|
||
<li><strong>A:</strong> 앵커링 목표가</li>
|
||
<li><strong>P:</strong> 상대방 제안가</li>
|
||
<li><strong>End:</strong> 협상 종료 여부</li>
|
||
</ul>
|
||
</div>
|
||
</body>
|
||
</html>
|
||
"""
|
||
return html_content
|
||
|
||
|
||
def start_api():
|
||
"""API 서버 시작 (Poetry 스크립트용)"""
|
||
uvicorn.run(
|
||
"app.main:app",
|
||
host=settings.api_host,
|
||
port=settings.api_port,
|
||
reload=True
|
||
)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
uvicorn.run(
|
||
"app.main:app",
|
||
host=settings.api_host,
|
||
port=settings.api_port,
|
||
reload=True
|
||
)
|