Skip to content

Repository files navigation

All is Well - 임베딩 결합 적응형 자연어 패널 추출 시스템

LangGraph + RAG + BGE Reranker 기반 차세대 지능형 검색 플랫폼


📋 목차


📌 프로젝트 소개

All is Well은 방대한 패널 데이터베이스에서 사용자의 자연어 질의를 지능적으로 처리하여 최적의 패널을 추출하는 차세대 검색 시스템입니다. "캠핑을 좋아하는 30대 서울 거주 여성"과 같은 자연어 질의만으로 36,113명의 패널과 636,248건의 설문 응답 데이터를 검색하고, AI가 생성한 페르소나 및 통계 시각화를 통해 즉각적인 인사이트를 제공합니다.

🎯 핵심 가치기존 시스템의 한계:

  • 키워드 기반 검색으로 추상적 질의 처리 불가
  • 효율성과 정확성의 트레이드오프 문제
  • 검색 결과의 제한적 활용 (단순 목록만 제공)
  • 비연속적 검색 경험 (매번 새로 검색)
  • 새 데이터 추가 시 긴 전처리 시간

All is Well의 혁신:

  • 적응형 하이브리드 검색: 질의 난이도 자동 분류 (SQL/임베딩 동적 선택)
  • 지능형 그룹 분석: LLM 기반 페르소나 생성 및 AI 이미지 시각화
  • 대화형 연속 검색: LangGraph 세션 관리로 드릴다운 지원
  • 실시간 통계 시각화: Chart.js 인터랙티브 차트
  • BGE 기반 리랭킹: 전처리 없이 질문-응답 의미 유사성 계산

🔍 프리뷰

프리뷰

🏗 시스템 아키텍처

네얼간이 아키텍처

계층별 역할

Frontend (React + Vite)

  • 사용자 인터페이스
  • 검색, 히스토리, 라이브러리 관리
  • Chart.js 통계 시각화
  • TanStack Query 서버 상태 관리

Backend (FastAPI)

  • 사용자 인증 (JWT)
  • 검색 결과 캐시 관리
  • 히스토리 & 라이브러리 CRUD
  • CSV 다운로드 제공
  • 프록시 패턴으로 보안 강화

Data Pipeline (BGE + LangGraph)

  • LangGraph 3-Tier 검색 워크플로우
  • LLM 기반 쿼리 분석 & 결과 요약
  • ChromaDB 벡터 검색
  • BGE Reranker 재순위화
  • 페르소나 & 이미지 생성

Database (SQLite + ChromaDB)

  • SQLite: 구조화 데이터 (패널 정보, 정형 질의 응답 데이터)
  • ChromaDB: 벡터 검색 (비정형 질문 + 응답)

👥 팀원 및 역할

프로필 이름 역할 담당 업무 GitHub
이석우 Leader
AI·Data Engineer
Panel Search Pipeline Development
Data Structure Development
GitHub
양다원 Full-stack Developer UI Design & Frontend Development
Backend API Development (Login/Search)
GitHub
정수현 AI·Data Engineer AI Architecture Design
Data Embedding
GitHub
홍성환 Full-stack Developer UI Design & Frontend Development
Backend API Development (Library/History/Panel Details)
GitHub

🛠 기술 스택

Core Framework

  • FastAPI 0.115.x - 고성능 비동기 웹 프레임워크
  • Python 3.10+ - 프로그래밍 언어
  • Uvicorn - ASGI 서버

Database

  • SQLite 3 - 경량 로컬 데이터베이스
  • sqlite-vec - 벡터 유사도 검색 확장 (파이프라인)

Data & Validation

  • Pydantic 2.x - 데이터 검증 및 직렬화
  • httpx - 비동기 HTTP 클라이언트 (파이프라인 통신)

Authentication

  • python-jose - JWT 토큰 생성 및 검증
  • passlib - 비밀번호 해싱 (선택)

Utilities

  • python-multipart - 폼 데이터 처리
  • python-dotenv - 환경 변수 관리

📚 API 명세서

POST /api/auth/login

Description: 로그인 화면에서 기업명과 코드로 인증을 수행하고 JWT 토큰을 발급받습니다.

Request Body:

{
  "companyName": "한성대학교",
  "accessCode": "abcde1212"
}

Response (Success: 200 OK):

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoi...",
  "user": {
    "companyName": "한성대학교"
  }
}

POST /api/search

Description: 메인 검색 및 후속 질문(드릴다운)을 수행합니다. LangGraph의 메인 워크플로우를 실행합니다.

Request Body:

{
  "query": "캠핑 좋아하는 30대 남성",
  "session_id": "sid_12345abc" // (후속 질문 시에만 포함)
}

Response (Success: 200 OK):

{
  "session_id": "sid_12345def",
  "result_count": 63,
  "group_persona": {
    "text": "수도권에 거주하는 30대 남성으로, 캠핑과 자동차 여행을...",
    "image_url": "<https://s3.aws.com/all-is-well/images/persona_xyz.png>"
  },
  "group_analytics": [
    {
      "type": "bar",
      "title": "연령 분포",
      "data": { "30-34": 40, "35-39": 23 }
    },
    { "type": "pie", "title": "직업 분포", "data": { "IT": 0.5, "금융": 0.2 } }
  ],
  "results": [
    {
      "panel_id": "w13042835",
      "persona_summary": "서울 사는 현대 자동차 타는 활발한 성격의...",
      "similarity": 99.6
    },
    {
      "panel_id": "w13132443",
      "persona_summary": "수도권 사는 외제차 타며 캠핑을 좋아하는...",
      "similarity": 99.6
    }
  ]
}

GET /api/download

Description: 검색된 패널 그룹의 정보를 CSV 파일로 다운로드합니다.

Query Parameters:

파라미터명 타입 필수 설명
session_id string Y 다운로드할 검색 세션의 고유 ID

Request Example:

GET /api/download?session_id=sid_12345def

Response (Success: 200 OK):

  • Headers:
    • Content-Type: text/csv; charset=utf-8
    • Content-Disposition: attachment; filename="panel_results_2025-11-12_143215.csv"
  • Body: CSV 파일

CSV File Structure:

고유번호,한줄 페르소나,질문 유사도
w13042835,"서울 거주 35세 남성, 현대 자동차 소유, 주말마다 캠핑 다니는 활발한 성격의 IT 개발자",99.6
w13132443,"경기 거주 32세 남성, 수입차 소유, 캠핑 마니아로 아웃도어 용품 수집가",99.6

GET /api/panel/{panel_id}

Description: 개별 패널의 상세 정보를 조회합니다.

URL Parameter: panel_id (예: w13042835)

Response (Success: 200 OK):

{
  "headerData": {
    "persona": {
      "imageUrl": "/assets/images/panel-header-image.jpg",
      "id": "w13042835",
      "summary": "경기도에 거주하는 32세 남성..."
    },
    "profile": {
      "gender": "남자",
      "age": "32세",
      "job": "금융업",
      "location": "경기도 안산시",
      "maritalStatus": "미혼",
      "familySize": "4명",
      "children": "-",
      "education": "대학교 졸업",
      "personalIncome": "월 400만원~499만원",
      "householdIncome": "월 1300만원~1399만원"
    },
    "hashtags": ["남성", "32세", "경기도 거주", "자차 보유"]
  },
  "surveyData": {
    "title": "설문 내역",
    "categories": [
      {
        "id": "cat1",
        "categoryName": "개인정보",
        "questions": [{ "id": "q1", "q": "단말기 브랜드", "a": "삼성 갤럭시" }]
      },
      {
        "id": "cat2",
        "categoryName": "디지털/IT",
        "questions": [{ "id": "q3", "q": "사용 빈도가 높은 앱", "a": "SNS 앱" }]
      }
    ]
  }
}

GET /api/history

Description: "검색 기록" 페이지의 전체 목록을 조회합니다.

Query Parameters (Optional):

  • ?search=...: 기록 내역 검색
  • ?limit=5: (사이드바 '최근 항목'용) 최근 5개만 조회

Response (Success: 200 OK):

[
  {
    "id": "hist_001",
    "query": "수도권에 거주하는 자동차를 보유한 캠핑 좋아하는 30대 남성 100명을 찾아줘",
    "timestamp": "최근 조회 1일 전"
  },
  {
    "id": "hist_002",
    "query": "담배 피는 여성을 20대만 찾아줘",
    "timestamp": "최근 조회 3일 전"
  }
]

DELETE /api/history/{history_id}

Description: "검색 기록" 페이지에서 특정 기록 한 개를 삭제합니다.

URL Parameter: history_id (string, Required)

Response (Success):

  • Code: 204 No Content
  • Body: 없음

GET /api/library

Description: "패널 라이브러리" 페이지에 저장된 모든 검색 '세션'을 조회합니다.

Query Parameters (Optional):

  • ?search=...: 저장된 패널 찾기

Response (Success: 200 OK):

[
  {
    "id": "session_id_abc",
    "savedDate": "저장 일자 10월 25일",
    "queries": [
      {
        "id": "q1-1",
        "queryText": "수도권... 30대 남성 100명을 찾아줘",
        "resultCount": 100
      },
      {
        "id": "q1-2",
        "queryText": "서울에 거주하는 사람으로 추려줘",
        "resultCount": 68
      }
    ]
  }
]

POST /api/library/save

Description: 현재 검색(드릴다운) 중인 세션을 라이브러리에 저장합니다.

Request Body:

{
  "session_id": "sid_12345def"
}

Response (Success: 201 Created):

{
  "success": true,
  "saved_item": {
    "id": "session_id_def",
    "savedDate": "방금 전",
    "queries": [
      /* ... */
    ]
  }
}

DELETE /api/library/{session_id}

Description: 저장된 라이브러리 항목을 삭제합니다.

URL Parameter: session_id (예: session_id_abc)

Response (Success: 204 No Content): (반환값 없음)


Error Pages

  • 404 Not Found
    • title: "페이지를 찾을 수 없습니다"
    • message: "요청하신 페이지가 존재하지 않거나 삭제되었습니다."
    • action: "메인으로 돌아가기"
  • 401 Unauthorized
    • title: "로그인이 필요합니다"
    • message: "패널 검색 서비스를 이용하시려면 로그인해주세요."
    • action: "로그인하기"
  • 500 Internal Server Error
    • title: "일시적인 오류가 발생했습니다"
    • message: "잠시 후 다시 시도해주세요. 문제가 계속되면 관리자에게 문의하세요."
    • action: "다시 시도"
  • 400 Bad Request (검색어 없음)
    • title: "검색어를 입력해주세요"
    • message: "찾으시는 패널의 특성을 자연어로 입력해주세요."
    • action: "검색 페이지로"

📁 프로젝트 구조

AllIsWellBack/
├── databases/                    # 데이터베이스 파일
│   ├── chroma_db_answers/        # Chroma DB (설문 응답)
│   ├── chroma_db_questions/      # Chroma DB (질문)
│   └── main.db                   # SQLite 메인 DB
├── src/
│   └── app/
│       ├── db/                   # 데이터베이스 레이어
│       │   ├── database.py       # SQLite 연결 관리
│       │   └── migrations/       # DB 마이그레이션
│       ├── models/               # SQLAlchemy 모델 (향후 사용)
│       ├── routers/              # API 라우터
│       │   ├── auth.py           # 인증 API (로그인, JWT)
│       │   ├── history_api.py    # 검색 히스토리 API
│       │   ├── library_api.py    # 라이브러리 API
│       │   ├── panel_api.py      # 패널 상세 정보 API
│       │   └── search.py         # 검색 API (메인 검색, 드릴다운, 다운로드)
│       └── schemas/              # Pydantic 스키마
│           ├── history.py        # 히스토리 스키마
│           ├── library.py        # 라이브러리 스키마
│           ├── panel.py          # 패널 스키마
│           └── search.py         # 검색 요청/응답 스키마
├── static/                       # 정적 파일 (이미지 등)
├── venv/                         # Python 가상환경
├── .gitignore                    # Git 제외 파일
├── main.py                       # FastAPI 애플리케이션 진입점
├── requirements.txt              # Python 의존성
└── README.md                     # 프로젝트 문서

🚀 시작하기

필수 요구사항

Python 3.10 이상 pip 최신 버전

설치 및 실행

1. 저장소 클론
git clone https://github.com/fourEdiots/Backend.git
cd AllIsWellBack

2. 가상환경 생성 및 활성화
# Windows
python -m venv venv
venv\Scripts\activate

# macOS/Linux
python3 -m venv venv
source venv/bin/activate

3. 의존성 설치
pip install -r requirements.txt

4. 데이터베이스 초기화
# 데이터베이스 테이블 생성
python create_db_tables.py

5. 개발 서버 실행
# main.py 실행 (기본 포트 5001)
python main.py

# 또는 uvicorn 직접 실행
uvicorn main:app --host 127.0.0.1 --port 5001 --reload

💼 기대 효과

경제적 측면

1. 생산성 향상 & 비용 절감

  • 복잡한 SQL 작성 불필요 → 데이터 분석 인력 시간 절감
  • 신속한 인사이트 도출 → 시장 대응 속도 향상
  • 반복 작업 자동화 → IT 자원 소모 최소화

2. 비즈니스 성과 & 매출 증대

  • 타겟 마케팅 정확도 향상 → 마케팅 ROI 극대화
  • 개인화된 금융/의료 서비스 → 고객 만족도 & 객단가 상승
  • 고품질 의사결정 지원 → 사업 성공률 향상

사회적 측면

1. 연구 & 기술 혁신 가속화

  • 연구 생산성 제고 (논문, 특허, 임상 대상자 모집)
  • 범용 플랫폼 확장 (마케팅, 금융, 의료, 공공)

2. 공공 서비스 품질 개선

  • 정확한 정책 수립 지원
  • 시스템 신뢰도 & 사용자 만족도 향상

3. 데이터 리터러시 장벽 완화

  • SQL 지식 없이 자연어로 데이터 탐색
  • 조직 전반의 데이터 기반 문화 확산

📄 라이선스

  • 이 프로젝트는 한성대학교 기업연계 SW캡스톤디자인 수업에서 진행되었습니다. [GitHub]

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages