View on GitHub

2026-capstone-22

2026-capstone-template created by GitHub Classroom

πŸŽ“ μ‚°ν•™ μΊ‘μŠ€ν†€ 22μ‘° : ReadyTalk for Academy

β€» λ³Έ ν”„λ‘œμ νŠΈλŠ” μ‚°ν•™ν˜‘λ ₯으둜 μ§„ν–‰λ˜μ–΄ κΈ°μ—…κ³Όμ˜ ν˜‘μ•½μ— 따라 ν˜„μž¬ λ ˆν¬μ§€ν† λ¦¬ 및 μ†ŒμŠ€ μ½”λ“œλŠ” 외뢀에 κ³΅κ°œν•˜κΈ° μ–΄λ €μš΄ 점 μ–‘ν•΄ λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.

1. ν”„λ‘œμ νŠΈ μ†Œκ°œ

ReadyTalk for AcademyλŠ” 학원 μš΄μ˜μ„ νš¨μœ¨ν™”ν•˜κ³  μ‚¬μš©μž λ§žμΆ€ν˜• 상담을 μ œκ³΅ν•˜κΈ° μœ„ν•œ AI 기반 μ—μ΄μ „νŠΈ μ‹œμŠ€ν…œμž…λ‹ˆλ‹€. 비인증 μ‚¬μš©μžμ—κ²ŒλŠ” 상담 맀뉴얼 기반 μ•ˆλ‚΄μ™€ 행동 μœ λ„λ₯Ό μ œκ³΅ν•˜κ³ , 인증된 μ‚¬μš©μžμ—κ²ŒλŠ” 좜결 관리, μˆ˜μ—… 일정, 리포트 λ“± κ°œμΈν™”λœ μ„œλΉ„μŠ€λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€. λ˜ν•œ 기좜 문제 μœ ν˜• λΆ„λ₯˜ 및 μœ μ‚¬ 문제 생성을 톡해 ν•™μŠ΅μ„ μ§€μ›ν•˜λ©°, κ΄€λ¦¬μžλŠ” 상담 λ‚΄μš©μ„ μ €μž₯Β·μš”μ•½ν•˜μ—¬ 운영 νš¨μœ¨μ„ 높일 수 μžˆμŠ΅λ‹ˆλ‹€.

2. μ†Œκ°œ μ˜μƒ

[![ReadyTalk KMU μ†Œκ°œ μ˜μƒ]]

3. νŒ€ μ†Œκ°œ


μ–‘μ§€μ›…

νŒ€μž₯, λ°±μ—”λ“œ

μ •μœ λ―Έ

AI Agent 개발
ν”„λ‘ νŠΈμ—”λ“œ

μ΄μœ€μ„œ

AI Agent 개발

μ–‘μŠΉμΌ

λ¬Έμ„œ 정리
개발 보쑰

μœ ν˜œμ„±

AI Agent QA

ReadyTalk for Academy

Vertex AI 기반 λ©€ν‹°ν…Œλ„ŒνŠΈ AI 챗봇 ν”Œλž«νΌ

Architecture Overview

graph TB
    subgraph NGINX["Nginx :80"]
        direction LR
        RL[Rate Limiting]
        RP[Reverse Proxy]
    end

    subgraph FE["Frontend - React :3000"]
        SA_UI[Superadmin Pages]
        ADMIN_UI[Admin Pages]
        CHAT_UI[Chat Pages]
        CAL_UI[Calendar Pages]
    end

    subgraph BE["Backend - FastAPI :8000"]
        R1["/api/superadmin"]
        R2["/api/auth"]
        R3["/api/chat"]
        R4["/api/corpus"]
        R5["/api/models"]
        R6["/api/kakao"]
        R7["/api/calendar"]
    end

    subgraph DB["PostgreSQL :5432"]
        TENANT_DATA["tenant_id FK isolation"]
    end

    subgraph GCP["Google Cloud Platform"]
        subgraph RAG["Vertex AI RAG Engine"]
            RAG_CORPUS["RAG Corpus + Weaviate"]
        end
        subgraph VAS["Vertex AI Search"]
            DS["DataStore + Engine"]
        end
        subgraph GCS["GCS Β· techready_readytalk_kmu"]
            BUCKET["tenants/{slug}/{corpus}/files"]
        end
        GEMINI["Gemini API"]
        GCAL["Google Calendar API"]
    end

    WEAVIATE["Weaviate :8080"]

    KAKAO["KakaoTalk"] --> R6

    NGINX --> FE
    NGINX --> BE
    BE --> DB
    BE --> RAG
    BE --> VAS
    BE --> GCS
    BE --> GEMINI
    BE --> GCAL
    RAG --> WEAVIATE

Tech Stack

Layer Technology
Frontend React 18 Β· MUI Β· React Router v6 Β· Axios
Backend FastAPI Β· SQLAlchemy Β· Alembic Β· Gunicorn + Uvicorn
Database PostgreSQL 15
AI/Search Vertex AI RAG Engine Β· Vertex AI Search Β· Gemini API
Vector DB Weaviate (RAG Engine λ°±μ—”λ“œ)
Storage Google Cloud Storage
Calendar Google Calendar API (OAuth 2.0)
Infra Docker Compose Β· Nginx Β· GCP Compute Engine
Auth JWT (python-jose)
Messaging KakaoTalk Open Builder

검색 μ—”μ§„ 이쀑 지원

ν…Œλ„ŒνŠΈλ³„λ‘œ 검색 엔진을 선택할 수 μžˆμŠ΅λ‹ˆλ‹€:

μ—”μ§„ μ„œλΉ„μŠ€ λ¦¬μ†ŒμŠ€ ꡬ쑰 μš©λ„
RAG Engine (κΈ°λ³Έ) rag_service.py ragCorpora β†’ ragFiles Weaviate ν•˜μ΄λΈŒλ¦¬λ“œ 검색
Vertex AI Search search_service.py dataStores β†’ engines Google κ΄€λ¦¬ν˜• 검색
# tenant.search_backend ν•„λ“œλ‘œ 선택
"rag_engine"       # Vertex AI RAG + Weaviate
"vertex_ai_search" # Vertex AI Search (DataStore + Engine)

Multi-Tenant Architecture

ν…Œλ„ŒνŠΈ 격리 방식

λͺ¨λ“  ν…Œμ΄λΈ”μ— tenant_id FKλ₯Ό λΆ€μ—¬ν•˜μ—¬ λ°μ΄ν„°λ² μ΄μŠ€ λ ˆλ²¨μ—μ„œ κ²©λ¦¬ν•©λ‹ˆλ‹€.

tenants
  β”œβ”€β”€ users (tenant_id FK)
  β”œβ”€β”€ groups (tenant_id FK)
  β”œβ”€β”€ corpora (tenant_id FK)
  β”‚     └── documents (tenant_id FK)
  β”œβ”€β”€ chat_sessions (tenant_id FK)
  β”‚     └── messages (tenant_id FK)
  β”œβ”€β”€ tenant_gcp_configs (1:1)
  β”œβ”€β”€ tenant_kakao_configs (1:1)
  β”œβ”€β”€ tenant_calendar_configs (1:1)
  └── chatbot_settings (1:1)

GCP λ¦¬μ†ŒμŠ€ ꡬ쑰

1 GCP ν”„λ‘œμ νŠΈ, 1 GCS 버킷, N ν…Œλ„ŒνŠΈ ꡬ쑰:

GCP Project: techready-readytalk-kmu
β”‚
β”œβ”€β”€ Vertex AI RAG (asia-northeast3)
β”‚   β”œβ”€β”€ ragCorpora/xxx  ← ν…Œλ„ŒνŠΈA (RAG Engine)
β”‚   └── ragCorpora/yyy  ← ν…Œλ„ŒνŠΈB (RAG Engine)
β”‚
β”œβ”€β”€ Vertex AI Search (global)
β”‚   β”œβ”€β”€ dataStores/aaa + engines/aaa  ← ν…Œλ„ŒνŠΈC (Vertex AI Search)
β”‚   └── dataStores/bbb + engines/bbb  ← ν…Œλ„ŒνŠΈD (Vertex AI Search)
β”‚
β”œβ”€β”€ Weaviate (Docker, weaviate-kmu.ready.talk)
β”‚   └── Collection per RAG Corpus
β”‚
└── GCS Bucket: techready_readytalk_kmu
    └── tenants/
        β”œβ”€β”€ tenant-a/
        β”‚   └── corpus-name/
        β”‚       └── files...
        └── tenant-b/
            └── corpus-name/
                └── files...

User Hierarchy

Superadmin (tenant_id=NULL, is_superadmin=True)
β”‚  ν”Œλž«νΌ 전체 관리: ν…Œλ„ŒνŠΈ CRUD, GCP μ„€μ •, κΈ°λ³Έ λͺ¨λΈ μ„€μ •
β”‚
β”œβ”€β”€ Tenant Admin (is_admin=True)
β”‚   β”‚  ν…Œλ„ŒνŠΈ λ‚΄ 관리: λ¬Έμ„œμ €μž₯μ†Œ, λ¬Έμ„œ μ—…λ‘œλ“œ/μ‚­μ œ, μ‚¬μš©μž 관리
β”‚   β”‚
β”‚   β”œβ”€β”€ Regular User (κ·Έλ£Ή: κ΄€λ¦¬μž/일반)
β”‚   β”‚     μ±„νŒ…, 파일 μ—…λ‘œλ“œ, μ„Έμ…˜ 관리
β”‚   β”‚
β”‚   └── Guest User (auth_provider=guest)
β”‚         μ±„νŒ…λ§Œ κ°€λŠ₯, 파일 μ—…λ‘œλ“œ λΆˆκ°€
β”‚
└── KakaoTalk User (auth_provider=kakao)
      μΉ΄μΉ΄μ˜€ν†‘ 채널 톡해 μžλ™ 생성, μ±„νŒ…λ§Œ κ°€λŠ₯

Chat Flow (Function Calling 기반)

μ‚¬μš©μž 질문
    β”‚
    β–Ό
λͺ¨λΈ κ²°μ • (user.preferred_model > DEFAULT_MODEL)
    β”‚
    β–Ό
query_smart() β€” Gemini Function Calling
    β”‚
    β”œβ”€β”€ search_documents() β†’ RAG Corpus 검색 (top_k=5)
    β”œβ”€β”€ search_web()       β†’ Google Search (web_search_enabled μ‹œ)
    β”œβ”€β”€ list/create/update/delete_calendar_events() β†’ Google Calendar
    └── (none)             β†’ 일반 λŒ€ν™”
    β”‚
    β–Ό
응닡 생성 + 좜처 μΆ”μΆœ
    β”‚  - cited_sourcesμ—μ„œ 파일λͺ… μΆ”μΆœ
    β”‚  - DBμ—μ„œ display_name 쑰회 (UUID→원본λͺ…)
    β”‚  - GCS Signed URL 생성 (좜처 링크)
    β”‚
    β–Ό
DB μ €μž₯ (messages ν…Œμ΄λΈ”) β†’ 응닡 λ°˜ν™˜

Google Calendar 연동

ν…Œλ„ŒνŠΈλ³„ Google Calendar OAuth 연동:

  1. ν…Œλ„ŒνŠΈ μ–΄λ“œλ―Όμ΄ μΊ˜λ¦°λ” 연동 (OAuth 2.0)
  2. μ±—λ΄‡μ—μ„œ μžμ—°μ–΄λ‘œ 일정 관리 (Function Calling)
    • β€œμ΄λ²ˆ μ£Ό 일정 μ•Œλ €μ€˜β€ β†’ list_calendar_events
    • β€œλ‚΄μΌ 3μ‹œμ— λ―ΈνŒ… μž‘μ•„μ€˜β€ β†’ create_calendar_event
    • β€œνšŒμ˜ μ‹œκ°„ λ³€κ²½ν•΄μ€˜β€ β†’ update_calendar_event
    • β€œλ―ΈνŒ… μ·¨μ†Œν•΄μ€˜β€ β†’ delete_calendar_event

KakaoTalk Integration

μΉ΄μΉ΄μ˜€ν†‘ μ‚¬μš©μž β†’ 카카였 μ„œλ²„ β†’ /api/kakao/skill (webhook)
                                    β”‚
                                    β”œβ”€β”€ μ‚¬μš©μž μžλ™ 생성/쑰회
                                    β”œβ”€β”€ Function Calling 기반 슀마트 쿼리
                                    β”œβ”€β”€ 응닡 λΆ„ν•  (1000자 Γ— μ΅œλŒ€ 3개 말풍선)
                                    └── Callback URL둜 비동기 응닡

Superadmin 관리

Platform Settings

ν‚€ μ„€λͺ…
VERTEX_AI_PROJECT_ID GCP ν”„λ‘œμ νŠΈ ID
VERTEX_AI_LOCATION Vertex AI 리전
GCP_CREDENTIALS_PATH μ„œλΉ„μŠ€ 계정 JSON 경둜
GCS_BUCKET_NAME GCS 버킷λͺ…
GEMINI_API_KEY Gemini API ν‚€
DEFAULT_MODEL κΈ°λ³Έ AI λͺ¨λΈ
WEAVIATE_HTTP_ENDPOINT Weaviate μ—”λ“œν¬μΈνŠΈ
WEAVIATE_COLLECTION_NAME Weaviate μ»¬λ ‰μ…˜λͺ…
WEAVIATE_API_KEY_SECRET Secret Manager μ‹œν¬λ¦Ώ 경둜

Tenant Lifecycle

생성 μ‹œ μžλ™ ν”„λ‘œλΉ„μ €λ‹:

  1. Tenant λ ˆμ½”λ“œ 생성 (name, slug, search_backend)
  2. GCP Config 생성 (곡용 ν”„λ‘œμ νŠΈ/버킷 μ—°κ²°)
  3. κΈ°λ³Έ κ·Έλ£Ή 생성 (κ΄€λ¦¬μž, 일반)
  4. κ΄€λ¦¬μž 계정 μžλ™ 생성
  5. GCS에 ν…Œλ„ŒνŠΈ 폴더 생성

μ‚­μ œ μ‹œ Cascade Cleanup:

  1. Vertex AI RAG Corpus λ˜λŠ” Search DataStore/Engine μ‚­μ œ
  2. GCS ν…Œλ„ŒνŠΈ 폴더 및 ν•˜μœ„ 파일 μ‚­μ œ
  3. DB Cascade μ‚­μ œ

Project Structure

readytalk-kmu/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ main.py
β”‚   β”‚   β”œβ”€β”€ config.py
β”‚   β”‚   β”œβ”€β”€ database.py
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   β”œβ”€β”€ tenant.py              # Tenant, GcpConfig, KakaoConfig, CalendarConfig
β”‚   β”‚   β”‚   β”œβ”€β”€ user.py
β”‚   β”‚   β”‚   β”œβ”€β”€ group.py
β”‚   β”‚   β”‚   β”œβ”€β”€ chat.py
β”‚   β”‚   β”‚   β”œβ”€β”€ corpus.py
β”‚   β”‚   β”‚   β”œβ”€β”€ chatbot_settings.py
β”‚   β”‚   β”‚   β”œβ”€β”€ prompt_template.py
β”‚   β”‚   β”‚   β”œβ”€β”€ platform_setting.py
β”‚   β”‚   β”‚   └── store_permission.py
β”‚   β”‚   β”œβ”€β”€ routers/
β”‚   β”‚   β”‚   β”œβ”€β”€ superadmin.py          # ν…Œλ„ŒνŠΈ CRUD, ν”Œλž«νΌ μ„€μ •
β”‚   β”‚   β”‚   β”œβ”€β”€ auth.py                # 둜그인, νšŒμ›κ°€μž…, JWT
β”‚   β”‚   β”‚   β”œβ”€β”€ chat.py                # 슀마트 쿼리 (Function Calling)
β”‚   β”‚   β”‚   β”œβ”€β”€ corpus.py              # λ¬Έμ„œμ €μž₯μ†Œ CRUD (검색엔진 λΆ„κΈ°)
β”‚   β”‚   β”‚   β”œβ”€β”€ calendar.py            # Google Calendar OAuth
β”‚   β”‚   β”‚   β”œβ”€β”€ kakao.py               # μΉ΄μΉ΄μ˜€ν†‘ webhook
β”‚   β”‚   β”‚   β”œβ”€β”€ chatbot_settings.py    # 챗봇 μ„€μ •
β”‚   β”‚   β”‚   β”œβ”€β”€ prompt_templates.py    # ν”„λ‘¬ν”„νŠΈ ν…œν”Œλ¦Ώ
β”‚   β”‚   β”‚   β”œβ”€β”€ models.py             # Gemini λͺ¨λΈ λͺ©λ‘
β”‚   β”‚   β”‚   └── admin.py              # ν…Œλ„ŒνŠΈ μ–΄λ“œλ―Ό
β”‚   β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”‚   β”œβ”€β”€ rag_service.py         # Vertex AI RAG + Weaviate
β”‚   β”‚   β”‚   β”œβ”€β”€ search_service.py      # Vertex AI Search
β”‚   β”‚   β”‚   β”œβ”€β”€ chat_service.py        # 슀마트 쿼리 μ—”μ§„
β”‚   β”‚   β”‚   β”œβ”€β”€ gemini_client.py       # Gemini API ν΄λΌμ΄μ–ΈνŠΈ
β”‚   β”‚   β”‚   β”œβ”€β”€ gcs_service.py         # GCS 파일 관리
β”‚   β”‚   β”‚   β”œβ”€β”€ calendar_service.py    # Google Calendar 연동
β”‚   β”‚   β”‚   β”œβ”€β”€ tenant_provisioning.py # ν…Œλ„ŒνŠΈ ν”„λ‘œλΉ„μ €λ‹
β”‚   β”‚   β”‚   └── usage_service.py       # μ‚¬μš©λŸ‰ 좔적
β”‚   β”‚   β”œβ”€β”€ schemas/
β”‚   β”‚   └── utils/
β”‚   β”‚       β”œβ”€β”€ dependencies.py        # 인증 미듀웨어
β”‚   β”‚       β”œβ”€β”€ security.py            # JWT, λΉ„λ°€λ²ˆν˜Έ ν•΄μ‹±
β”‚   β”‚       β”œβ”€β”€ init_data.py           # 초기 데이터 (superadmin)
β”‚   β”‚       └── store_access.py        # λ¬Έμ„œμ €μž₯μ†Œ μ ‘κ·Ό κΆŒν•œ
β”‚   β”œβ”€β”€ credentials/                   # GCP μ„œλΉ„μŠ€ 계정 JSON (gitignore)
β”‚   β”œβ”€β”€ migrations/                    # Alembic DB λ§ˆμ΄κ·Έλ ˆμ΄μ…˜
β”‚   └── Dockerfile
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ App.js                     # λΌμš°νŒ… (slug 기반 ν…Œλ„ŒνŠΈ λΆ„κΈ°)
β”‚   β”‚   β”œβ”€β”€ pages/
β”‚   β”‚   β”‚   β”œβ”€β”€ ChatPage.js            # μ±„νŒ… UI
β”‚   β”‚   β”‚   β”œβ”€β”€ AdminPage.js           # ν…Œλ„ŒνŠΈ μ–΄λ“œλ―Ό
β”‚   β”‚   β”‚   β”œβ”€β”€ CalendarPage.js        # μΊ˜λ¦°λ” UI
β”‚   β”‚   β”‚   └── superadmin/            # μŠˆνΌμ–΄λ“œλ―Ό νŽ˜μ΄μ§€λ“€
β”‚   β”‚   β”œβ”€β”€ services/api.js            # Axios API ν΄λΌμ΄μ–ΈνŠΈ
β”‚   β”‚   └── context/
β”‚   β”‚       β”œβ”€β”€ AuthContext.js
β”‚   β”‚       └── TenantContext.js
β”‚   └── Dockerfile
β”œβ”€β”€ nginx/
β”‚   └── backend.conf                   # Nginx μ„€μ •
β”œβ”€β”€ docker-compose.yml                 # 둜컬 개발용
β”œβ”€β”€ docker-compose.dev.yml             # κ°œλ°œκ³„ (GCP VM)
β”œβ”€β”€ docker-compose.prod.yml            # μš΄μ˜κ³„
β”œβ”€β”€ .env                               # 둜컬 ν™˜κ²½λ³€μˆ˜ (gitignore)
└── .env.production                    # 운영 ν™˜κ²½λ³€μˆ˜ (gitignore)

Getting Started

Prerequisites

1. ν™˜κ²½ μ„€μ •

cp .env.example .env
# .env 파일 νŽΈμ§‘

2. GCP μ„œλΉ„μŠ€ 계정

mkdir -p backend/credentials
cp your-service-account.json backend/credentials/readytalk-kmu-credentials.json

3. μ‹€ν–‰

docker-compose up -d --build

4. 접속

URL μ„€λͺ…
http://localhost:8888 메인
http://localhost:8888/superadmin μŠˆνΌμ–΄λ“œλ―Ό
http://localhost:8888/{slug}/chat ν…Œλ„ŒνŠΈλ³„ μ±„νŒ…
http://localhost:8888/{slug}/admin ν…Œλ„ŒνŠΈλ³„ μ–΄λ“œλ―Ό

5. 초기 μ„€μ • μˆœμ„œ

  1. μŠˆνΌμ–΄λ“œλ―Ό 둜그인 (admin@academy.ready.talk)
  2. μ„€μ • > GCP μ„€μ • μž…λ ₯
  3. μ„€μ • > κΈ°λ³Έ λͺ¨λΈ 선택
  4. ν…Œλ„ŒνŠΈ 생성 (검색 μ—”μ§„ 선택: RAG Engine λ˜λŠ” Vertex AI Search)
  5. ν…Œλ„ŒνŠΈ μ–΄λ“œλ―Ό β†’ λ¬Έμ„œμ €μž₯μ†Œ 생성 β†’ 파일 μ—…λ‘œλ“œ