Skip to content

alstjs1207/flo-ai

Repository files navigation

Flo AI - Course-based RAG Chatbot

강의(Course)별로 자료를 분석하고 정보를 제공하는 AI 챗봇 API 서버입니다. RAG (Retrieval-Augmented Generation) 패턴을 사용하여 업로드된 PDF/텍스트 파일에서 관련 정보를 검색하고 AI 기반 답변을 생성합니다.

주요 기능

  • 강의별 문서 관리: 각 강의(courseId)별로 독립적인 문서 저장 및 관리
  • PDF 및 텍스트 파일 업로드: 한 강의에 여러 파일 업로드 가능
  • 자동 문서 파싱 및 청킹: PDF/텍스트 자동 분석 및 chunk 단위 저장
  • 벡터 임베딩: Cohere API를 통한 고품질 임베딩 생성
  • 강의 범위 내 검색: courseId 기반 필터링으로 해당 강의 자료에서만 검색
  • 범위 제한 답변: LLM이 강의 범위를 벗어나는 질문을 판단하여 거부
  • OpenAI GPT 활용: 자연어 기반 답변 생성
  • Docker 컨테이너 지원: 배포 간편화

기술 스택

  • Framework: NestJS (TypeScript)
  • Database: MongoDB Atlas (Vector Search)
  • File Storage: Google Cloud Storage (개발 환경에서는 로컬 저장)
  • Embedding: Cohere API
  • LLM: OpenAI GPT API
  • Containerization: Docker

시스템 아키텍처

데이터 저장 파이프라인

Client → Upload API → GCS Storage (or Local) → PDF Parser → Text Chunker
  → Cohere Embedding → MongoDB Vector Store

데이터 조회 파이프라인

Client → Chat API → Query Embedding (Cohere) → Vector Search (MongoDB)
  → Top-K Retrieval → Context Assembly → OpenAI LLM → Response

프로젝트 구조

flo-ai/
├── src/
│   ├── modules/
│   │   ├── upload/          # 파일 업로드 (GCS/로컬)
│   │   ├── document/        # 문서 파싱 & chunking
│   │   ├── embedding/       # Cohere 임베딩
│   │   ├── vector-store/    # MongoDB 벡터 저장/조회
│   │   └── chat/            # RAG 검색 & OpenAI 응답
│   ├── config/              # 환경 설정
│   ├── app.module.ts
│   └── main.ts
├── uploads/                 # 로컬 개발 환경 업로드 폴더
├── Dockerfile
├── docker-compose.yml
└── package.json

설치 및 실행

1. 환경 변수 설정

.env.example 파일을 .env로 복사하고 필요한 값을 입력하세요:

cp .env.example .env

필수 환경 변수:

  • MONGODB_URI: MongoDB Atlas 연결 URI
  • COHERE_API_KEY: Cohere API 키
  • OPENAI_API_KEY: OpenAI API 키

개발 환경 설정:

  • ENABLE_REMOTE_STORAGE=false: 로컬 파일시스템 사용
  • LOCAL_UPLOAD_PATH=./uploads: 로컬 업로드 경로

프로덕션 환경 설정 (GCS 사용):

  • ENABLE_REMOTE_STORAGE=true: Google Cloud Storage 사용
  • GCS_PROJECT_ID: GCP 프로젝트 ID
  • GCS_KEY_FILENAME: 서비스 계정 키 파일 경로
  • GCS_BUCKET_NAME: GCS 버킷 이름

2. MongoDB Atlas Vector Index 생성

MongoDB Atlas에서 coursedocumentchunks 컬렉션에 vector_index라는 이름으로 Vector Search Index를 생성해야 합니다:

{
  "mappings": {
    "dynamic": true,
    "fields": {
      "courseId": {
        "type": "token"
      },
      "embedding": {
        "type": "knnVector",
        "dimensions": 1024,
        "similarity": "cosine"
      }
    }
  }
}

중요: courseId 필드를 token 타입으로 추가하여 강의별 필터링이 가능하도록 설정해야 합니다.

3. 로컬 실행

# 의존성 설치
npm install

# 개발 모드 실행
npm run start:dev

# 프로덕션 빌드
npm run build
npm run start:prod

4. Docker로 실행

# Docker Compose로 실행
docker-compose up -d

# 또는 Docker 단독 실행
docker build -t flo-ai .
docker run -p 3000:3000 --env-file .env flo-ai

API 엔드포인트

서버가 실행되면 http://localhost:3000/api에서 API에 접근할 수 있습니다.

Swagger 문서: http://localhost:3000/api/docs

주요 엔드포인트

모든 API는 강의(courseId)를 기준으로 동작합니다.

1. 강의에 파일 업로드

POST /api/courses/:courseId/documents/upload
Content-Type: multipart/form-data

file: [PDF or TXT file]

예시:

POST /api/courses/PYTHON-101/documents/upload

응답:

{
  "courseId": "PYTHON-101",
  "documentId": "507f1f77bcf86cd799439011",
  "fileName": "lecture.pdf",
  "fileUrl": "file:///path/to/uploads/documents/abc123.pdf",
  "status": "processing",
  "message": "File uploaded successfully. Processing in background."
}

2. 강의 문서 목록 조회

GET /api/courses/:courseId/documents

예시:

GET /api/courses/PYTHON-101/documents

3. 강의 문서 상세 조회

GET /api/courses/:courseId/documents/:id

4. 강의 문서 삭제

DELETE /api/courses/:courseId/documents/:id

5. 강의 통계 조회

GET /api/courses/:courseId/stats

응답:

{
  "totalDocuments": 5,
  "totalChunks": 150,
  "completedDocuments": 4,
  "processingDocuments": 1,
  "failedDocuments": 0
}

6. 강의 자료 기반 질문 (Chat)

POST /api/courses/:courseId/chat
Content-Type: application/json

{
  "query": "파이썬에서 리스트란 무엇인가요?",
  "topK": 5
}

예시:

POST /api/courses/PYTHON-101/chat

응답:

{
  "answer": "파이썬에서 리스트는 여러 값을 순서대로 저장할 수 있는 자료구조입니다...",
  "sources": [
    {
      "content": "리스트의 정의는...",
      "fileName": "lecture.pdf",
      "score": 0.95
    }
  ]
}

범위 밖 질문 시:

{
  "answer": "죄송합니다. 이 질문은 현재 강의 자료의 범위를 벗어납니다.",
  "sources": [...]
}

7. Health Check

GET /api/health

개발

테스트

# 단위 테스트
npm run test

# E2E 테스트
npm run test:e2e

# 테스트 커버리지
npm run test:cov

Linting & Formatting

# ESLint
npm run lint

# Prettier
npm run format

사용 예시

시나리오: 파이썬 강좌 (PYTHON-101)

1. 강의 자료 업로드

# 첫 번째 파일 업로드
curl -X POST http://localhost:3000/api/courses/PYTHON-101/documents/upload \
  -F "file=@python-basics.pdf"

# 두 번째 파일 업로드 (같은 강의에 여러 파일 가능)
curl -X POST http://localhost:3000/api/courses/PYTHON-101/documents/upload \
  -F "file=@python-advanced.pdf"

2. 업로드된 문서 확인

curl -X GET http://localhost:3000/api/courses/PYTHON-101/documents

3. 강의 통계 확인

curl -X GET http://localhost:3000/api/courses/PYTHON-101/stats

4. 질문하기 (강의 범위 내)

curl -X POST http://localhost:3000/api/courses/PYTHON-101/chat \
  -H "Content-Type: application/json" \
  -d '{
    "query": "파이썬에서 리스트와 튜플의 차이점은 무엇인가요?",
    "topK": 5
  }'

응답: 파이썬 강의 자료 기반으로 답변 제공

5. 질문하기 (강의 범위 밖)

curl -X POST http://localhost:3000/api/courses/PYTHON-101/chat \
  -H "Content-Type: application/json" \
  -d '{
    "query": "자바스크립트의 클로저란 무엇인가요?",
    "topK": 5
  }'

응답: "죄송합니다. 이 질문은 현재 강의 자료의 범위를 벗어납니다."

시나리오: 다른 강의 (JAVASCRIPT-101)

# 자바스크립트 강의에 파일 업로드
curl -X POST http://localhost:3000/api/courses/JAVASCRIPT-101/documents/upload \
  -F "file=@javascript-basics.pdf"

# 자바스크립트 강의에 질문
curl -X POST http://localhost:3000/api/courses/JAVASCRIPT-101/chat \
  -H "Content-Type: application/json" \
  -d '{
    "query": "자바스크립트의 클로저란 무엇인가요?",
    "topK": 5
  }'

응답: 자바스크립트 강의 자료 기반으로 답변 제공

주의사항

  1. MongoDB Atlas Vector Index:

    • 반드시 Atlas에서 Vector Search Index를 먼저 생성해야 합니다
    • coursedocumentchunks 컬렉션에 courseId 필드를 token 타입으로 추가
  2. courseId 설계:

    • courseId는 문자열 식별자입니다 (예: "PYTHON-101", "JAVASCRIPT-101")
    • 각 강의는 독립적으로 관리되며, 검색 시 강의 범위를 벗어나지 않습니다
    • 한 강의에 여러 파일을 업로드할 수 있습니다
  3. API Keys: 모든 API 키 (.env 파일)는 절대 git에 커밋하지 마세요.

  4. 개발 환경:

    • ENABLE_REMOTE_STORAGE=false로 설정하면 로컬 파일시스템 사용
    • GCS 설정 없이도 개발 가능
  5. 프로덕션 환경:

    • GCS 버킷과 서비스 계정이 미리 생성되어 있어야 합니다
    • ENABLE_REMOTE_STORAGE=true로 설정
  6. 파일 크기: 현재 최대 파일 크기는 10MB로 제한되어 있습니다.

  7. 범위 제한 답변:

    • LLM이 검색 결과의 유사도 점수를 분석하여 범위 밖 질문을 판단합니다
    • 평균 점수가 0.3 미만이면 범위 밖으로 간주됩니다

라이선스

MIT

문의

문제가 발생하거나 질문이 있으시면 이슈를 등록해주세요.

About

AI chat bot

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors