SafeHome은 한국의 전세사기 피해자를 돕기 위한 AI 챗봇 서비스의 백엔드입니다.
이 프로젝트는 RAG (Retrieval-Augmented Generation) 아키텍처를 기반으로 하며, 현재는 Mock AI 모듈을 사용하여 즉시 실행 및 테스트가 가능합니다. AI 팀이 실제 모델을 개발하면 쉽게 교체할 수 있도록 설계되었습니다.
- 챗봇 API: 사용자 메시지 처리 및 응답 생성
- 의도 분류 (Intent Classification): 사용자 메시지의 의도 파악
- 감정 분석 (Emotion Analysis): 사용자의 감정 상태 감지
- 피해자 상태 분류 (Victim Status): 5단계 피해 수준 판정 (Level 0-4)
- RAG 시스템: 지식 베이스 검색 및 응답 생성
- 세션 관리: 대화 히스토리 저장 및 관리
- 위기 감지: 위기 상황 자동 감지 및 긴급 응답
- 지식 베이스: 전세사기 관련 5개 카테고리 정보
- MongoDB 연동: 사용자 및 채팅 로그 영구 저장 (선택적)
- 카카오 로그인: 사용자 인증 API (Mock)
현재는 키워드 기반 Mock 모듈을 사용:
- Intent Classifier: 키워드 매칭으로 의도 분류
- Emotion Analyzer: 키워드 매칭으로 감정 감지
- Victim Classifier: 키워드 기반 피해 수준 판정
- RAG Engine: 단순 텍스트 검색 및 템플릿 기반 응답
① SessionManager.load_history() → 세션 이력 로드
② IntentClassifier.classify() → 의도 분류
③ EmotionAnalyzer.analyze() → 감정 분석
④ Crisis Check → 위기 상황 즉시 대응
⑤ Classifier.determine_victim_status() → 피해자 상태 판정
⑥ RAGEngine.search() → 관련 문서 검색
⑦ RAGEngine.generate_response() → LLM 응답 생성
⑧ SessionManager.save_history() → 세션 저장
⑨ ChatLogService.save_to_db() → DB 영구 저장
safehome-backend/
├── main.py # 🚀 FastAPI 애플리케이션 진입점
├── requirements.txt # Python 의존성
├── README.md # 프로젝트 문서
├── INTEGRATION_GUIDE.md # AI 팀 통합 가이드
├── .gitignore # Git 무시 파일
├── .env.example # 환경 변수 템플릿
│
├── api/ # 🎯 API 레이어
│ ├── __init__.py
│ ├── routes.py # API 라우트: /chat, /history, /auth
│ └── schemas.py # Pydantic 스키마
│
├── core/ # 🌐 핵심 설정
│ ├── __init__.py
│ ├── config.py # 환경변수, DB URI, AI 모드
│ └── interfaces.py # AI 모듈 공통 인터페이스
│
├── db/ # 💾 데이터베이스
│ ├── __init__.py
│ └── mongodb.py # MongoDB 연결 (선택적)
│
├── models/ # 📦 데이터 모델
│ ├── __init__.py
│ ├── user.py # 사용자 스키마 (Kakao)
│ └── chat_log.py # 채팅 로그 스키마
│
├── services/ # 💡 비즈니스 로직
│ ├── __init__.py
│ ├── chatbot_service.py # 메인 오케스트레이터 (9단계 파이프라인)
│ ├── session_manager.py # 세션/대화 메모리 관리
│ ├── chat_log_service.py # MongoDB 로그 저장
│ └── auth_service.py # 카카오 로그인 처리
│
├── ai_modules/ # 🧠 AI 모듈
│ ├── __init__.py # 모듈 팩토리
│ │
│ ├── intent/ # Intent 분류
│ │ ├── __init__.py
│ │ ├── base.py # 베이스 클래스
│ │ ├── mock.py # ✅ Mock 구현
│ │ └── classifier.py # (AI2) Production 구현
│ │
│ ├── emotion/ # Emotion 분석
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── mock.py # ✅ Mock 구현
│ │ └── analyzer.py # (AI2) Production 구현
│ │
│ ├── classifier/ # 🎯 AI2: Victim Status Classifier
│ │ ├── __init__.py
│ │ ├── classifier_logic.py # 피해자 상태 판정 로직
│ │ └── prompt_templates.py # 대화 템플릿
│ │
│ ├── rag/ # RAG 엔진 (Mock)
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── mock.py # ✅ Mock 구현
│ │ └── engine.py # Production 구현
│ │
│ └── rag_engine/ # 🧠 AI1: Production RAG Engine
│ ├── __init__.py
│ ├── create_db.py # A/B 단계: 문서 로딩 & 벡터 생성
│ ├── define_prompt.py # D 단계: LLM 프롬프트 정의
│ ├── run_chain.py # C/E 단계: RAG 체인 실행
│ ├── requirements.txt # AI1 의존성
│ ├── index/ # 💾 FAISS 벡터 인덱스
│ └── knowledge_base/ # 📚 RAG 소스 문서
│
├── knowledge_base/ # 📚 지식 베이스 (Mock용)
│ ├── 1_victim_criteria.md
│ ├── 2_financial_support.md
│ ├── 3_housing_support.md
│ ├── 4_legal_support.md
│ └── 5_psychological_support.md
│
└── tests/ # 🧪 테스트
├── __init__.py
└── test_chatbot.py
# 프로젝트 디렉토리로 이동
cd safehome-backend
# 가상환경 생성 (권장)
python -m venv venv
# 가상환경 활성화
# macOS/Linux:
source venv/bin/activate
# Windows:
venv\Scripts\activate
# 의존성 설치
pip install -r requirements.txt# 서버 시작
python main.py서버가 시작되면 다음 URL에 접속:
- API 문서: http://localhost:8000/docs
- Health Check: http://localhost:8000/health
- http://localhost:8000/docs 접속
POST /api/chat엔드포인트 선택- "Try it out" 클릭
- 요청 본문 입력:
{ "message": "경매 통지서를 받았어요", "session_id": null } - "Execute" 클릭
curl -X POST "http://localhost:8000/api/chat" \
-H "Content-Type: application/json" \
-d '{"message": "경매 통지서를 받았어요"}'import requests
response = requests.post(
"http://localhost:8000/api/chat",
json={"message": "경매 통지서를 받았어요"}
)
print(response.json())채팅 메시지를 처리하고 응답을 반환합니다.
요청:
{
"message": "경매 통지서를 받았어요",
"session_id": "optional-session-id"
}응답:
{
"response": "경매 통지 관련 상황입니다. 관련 정보: ...",
"intent": "auction",
"emotion": "shock",
"victim_status": "Level 3 - 심각한 피해 - 긴급지원 필요 (주거/법률/재정)",
"session_id": "abc-123-def",
"confidence": 0.85
}세션의 대화 히스토리를 조회합니다.
응답:
{
"session_id": "abc-123-def",
"messages": [
{
"role": "user",
"content": "경매 통지서를 받았어요",
"timestamp": "2025-10-10T10:30:00",
"metadata": { "intent": "auction", "emotion": "shock" }
},
{
"role": "assistant",
"content": "경매 통지 관련 상황입니다...",
"timestamp": "2025-10-10T10:30:01",
"metadata": { "intent": "auction", "emotion": "shock" }
}
],
"found": true,
"created_at": "2025-10-10T10:30:00",
"updated_at": "2025-10-10T10:30:01"
}세션을 삭제합니다.
응답:
{
"success": true,
"message": "Session abc-123-def deleted successfully",
"session_id": "abc-123-def"
}카카오 로그인을 처리합니다 (Mock).
요청:
{
"kakao_id": "1234567890",
"nickname": "홍길동",
"profile_image": "https://example.com/profile.jpg"
}응답:
{
"user_id": "user_abc123",
"kakao_id": "1234567890",
"nickname": "홍길동",
"message": "로그인 성공"
}서버 상태를 확인합니다.
응답:
{
"status": "ok",
"service": "SafeHome Backend",
"version": "1.0.0",
"ai_backend": {
"intent": "mock",
"emotion": "mock",
"rag": "mock"
}
}모든 AI 모듈은 core/interfaces.py에 정의된 인터페이스를 따릅니다:
# Intent Classifier Interface
class IntentClassifierInterface(ABC):
def classify(self, text: str) -> Tuple[str, float]:
"""Returns (intent, confidence)"""
pass
# Emotion Analyzer Interface
class EmotionAnalyzerInterface(ABC):
def analyze(self, text: str) -> str:
"""Returns emotion label"""
pass
# RAG Engine Interface
class RAGEngineInterface(ABC):
def search(self, query: str) -> List[str]:
"""Returns relevant snippets"""
pass
def generate_response(self, question: str, context: str) -> str:
"""Returns generated response"""
pass# ai_modules/intent/mock.py
class MockIntentClassifier(BaseIntentClassifier):
def classify(self, text: str) -> Tuple[str, float]:
# 키워드 기반 분류
if "경매" in text or "통지" in text:
return ("auction", 0.85)
# ... 기타 키워드 검사
return ("general", 0.60)-
.env.example을.env로 복사:cp .env.example .env
-
.env파일 수정:# AI Backend Mode INTENT_BACKEND=production EMOTION_BACKEND=production RAG_BACKEND=production # MongoDB (선택적) MONGODB_URI=mongodb://localhost:27017 DATABASE_NAME=safehome_db # API Keys (필요시) OPENAI_API_KEY=your-key-here ANTHROPIC_API_KEY=your-key-here
core/config.py는 환경 변수에서 자동으로 설정을 로드:
class Settings:
AI_BACKEND = {
"intent": os.getenv("INTENT_BACKEND", "mock"),
"emotion": os.getenv("EMOTION_BACKEND", "mock"),
"rag": os.getenv("RAG_BACKEND", "mock")
}
MONGODB_URI = os.getenv("MONGODB_URI", None)
# ...ai_modules/__init__.py의 팩토리 함수가 자동으로 올바른 구현을 로드:
def get_intent_classifier() -> IntentClassifierInterface:
backend = settings.AI_BACKEND.get("intent", "mock")
if backend == "mock":
from ai_modules.intent.mock import MockIntentClassifier
return MockIntentClassifier()
elif backend == "production":
from ai_modules.intent.classifier import ProductionIntentClassifier
return ProductionIntentClassifier()파일: ai_modules/intent/classifier.py
from typing import Tuple
from .base import BaseIntentClassifier
class ProductionIntentClassifier(BaseIntentClassifier):
def __init__(self):
super().__init__()
# 모델 로드
self.model = load_your_model("path/to/model")
def classify(self, text: str) -> Tuple[str, float]:
# 실제 모델로 분류
prediction = self.model.predict(text)
intent = prediction['label']
confidence = prediction['score']
return (intent, confidence)파일: ai_modules/emotion/analyzer.py
from .base import BaseEmotionAnalyzer
class ProductionEmotionAnalyzer(BaseEmotionAnalyzer):
def __init__(self):
super().__init__()
# 모델 로드
self.model = load_your_model("path/to/emotion_model")
def analyze(self, text: str) -> str:
# 실제 모델로 분석
emotion = self.model.predict(text)['label']
return emotion파일: ai_modules/rag/engine.py
from typing import List
from .base import BaseRAGEngine
class ProductionRAGEngine(BaseRAGEngine):
def __init__(self):
super().__init__()
# Vector DB 및 LLM 초기화
self.vector_db = connect_to_pinecone() # 예시
self.embeddings = load_embeddings_model()
self.llm = load_llm("gpt-4") # 예시
def search(self, query: str) -> List[str]:
# 벡터 검색
query_embedding = self.embeddings.encode(query)
results = self.vector_db.search(query_embedding, top_k=3)
return [r['text'] for r in results]
def generate_response(self, question: str, context: str) -> str:
# LLM으로 응답 생성
prompt = f"Context: {context}\n\nQuestion: {question}\n\nAnswer:"
response = self.llm.generate(prompt)
return responseAI 모듈 구현 후 core/config.py 수정:
AI_BACKEND = {
"intent": "production",
"emotion": "production",
"rag": "production"
}requirements.txt에 필요한 라이브러리 추가:
# AI/ML 라이브러리 예시
torch==2.0.0
transformers==4.30.0
pinecone-client==2.2.0
openai==1.0.0
sentence-transformers==2.2.0# pytest 설치 (필요시)
pip install pytest
# 테스트 실행
pytest tests/
# 또는 직접 실행
python tests/test_chatbot.py- ✅ Intent Classifier 테스트
- ✅ Emotion Analyzer 테스트
- ✅ RAG Engine 테스트
- ✅ 챗봇 서비스 통합 테스트
- ✅ 세션 관리 테스트
- ✅ 위기 감지 테스트
def test_chatbot_service_auction():
bot = ChatbotService()
result = bot.process_message("경매 통지서 받았어요")
assert result["intent"] == "auction"
assert "response" in result
assert "session_id" in result문제: Address already in use 에러
해결:
# 다른 포트로 실행
python main.py --port 8001
# 또는 main.py 수정
uvicorn.run("main:app", host="0.0.0.0", port=8001)문제: ModuleNotFoundError
해결:
# PYTHONPATH 설정
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
python main.py문제: RAG가 파일을 찾지 못함
해결:
knowledge_base/폴더가 존재하는지 확인- 파일 권한 확인
- 로그에서 파일 로드 상태 확인
문제: 프론트엔드 연결 시 CORS 에러
해결: main.py에서 CORS 설정 수정
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"], # 프론트엔드 URL
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)현재 5개 카테고리의 전세사기 지원 정보를 포함:
-
피해자 인정 기준 (
1_victim_criteria.md)- 피해자 인정 요건
- 신청 절차
- 필요 서류
-
금융 지원 (
2_financial_support.md)- 보증금 반환 보증
- 긴급생활 안정자금
- 주거안정 지원금
- 세금 감면
-
주거 지원 (
3_housing_support.md)- 긴급 임시주거
- 공공임대주택
- 이사 비용 지원
-
법률 지원 (
4_legal_support.md)- 무료 법률 상담
- 경매/배당 절차
- 형사 고소 지원
-
심리 지원 (
5_psychological_support.md)- 위기 상담
- 심리 치료
- 자조 모임
Built with ❤️ for SafeHome Hackathon