Hun-Bot's Devlog

JLPT & Buiness 회화 연습용 일본어 회화 앱 개발기 1편

jlpt business japanese app devlog

JLPT & Business 회화 연습용 일본어 회화 앱 개발기 1편

지난 6월부터 약 7개월간 일본어 공부를 하고 있는데, 시중에 나와 있는 일본어 회화 연습 어플이나 유튜브 광고에 나오는 앱들은 마음에 들지 않아서, 직접 만들어보면서 어떤 기술적 한계가 있길래 좋은 공부 어플을 못 만드는지 알아보고 싶었습니다.

좋은 일본어 회화 연습 앱이라고 생각하는 조건은

  1. 일상 회화부터 비즈니스 회화까지 다양한 상황에 맞는 대화를 연습할 수 있어야 하고, 경어, 존경어, 겸양어 또한 자연스럽게 사용할 수 있어야 한다. [JLPT N1이상 수준을 목표]
  2. 사용자는 음성 기반으로 AI와 대화를 주고 받으며 실시간 소통을 통해 회화 능력을 향상시킬 수 있어야 한다.
  3. 사용자가 대화한 내용을 바탕으로 피드백을 제공하여, 잘못한 부분을 개선할 수 있도록 도와주어야 한다.
  4. 면접 연습을 할 수 있도록 사용자의 전공 및 포트폴리오, 이력서에 대한 다양한 질문을 제공하고 평가해야 한다. 항상 최악의 상황을 가정해야하며, 매 질문마다 꼬리질문을 통해 심층적인 답변을 유도해야 한다.
  5. 사용자의 개인 정보나 대화 내용이 외부로 유출되지 않도록 철저한 보안이 보장되어야 한다.

이렇게 생각을 해두고, Gemini Deep Research의 도움을 받아서 필요한 기술들과 어떻게 개발해야 할지를 정리해봤습니다.


초기 기술 스택 선정

구분기술명선정 이유
언어 (Language)Python 3.11+AI/ML 라이브러리 생태계가 가장 풍부함.
오케스트레이션LangGraph순환(Cycle)과 상태(State) 관리가 필수적인 에이전트 워크플로우에 최적화됨. (단순 Chain이 아닌 복잡한 대화 흐름 제어)
LLM (Text)CyberAgentLM3-22B-Chat (GGUF) 또는 Llama-3-Elyza-JP-8B일본어 특화 성능이 뛰어나며 로컬 구동 또는 저비용 API 활용 가능.
TTS (Audio)Style-Bert-VITS2일본어 특유의 억양과 감정(기쁨, 분노, 당황 등)을 가장 자연스럽게 표현하는 오픈소스 모델.
RAG & 검색Qdrant (Vector DB) + SudachiPy (Tokenizer)하이브리드 검색 지원 및 일본어 형태소 분석에 최적화된 토크나이저 활용.
UI/UXChainlit대화형 AI 프로토타이핑에 가장 빠르고 효율적이며, ‘생각의 과정(Chain of Thought)‘을 시각화하기 좋음.

가장 중요한 부분인 실시간 대화를 위해서는 Chainlit으로는 부족하다고 생각되어 추가적으로 어떤 실시간 통신 프레임워크를 사용할지 고민을 했습니다.

특성ChainlitGradioLiveKit
주요 용도채팅형 LLM 앱ML 모델 데모/서빙실시간 A/V 인프라
통신 프로토콜WebSocketWebSocket / HTTPWebRTC (UDP/TCP)
지연 시간 (Latency)중간 (500ms~1s)중간 (500ms~1s)매우 낮음 (<200ms)
오디오 처리 방식파일/청크 전송스트림 제너레이터RTP 미디어 스트림
Barge-in (끼어들기)어려움 (커스텀 필요)가능하나 복잡함기본 지원 (Native)
상태 관리영구 채팅 세션상태 객체 전달실시간 룸(Room) 상태
확장성수직적 확장 용이컨테이너화 용이클라우드/엣지 분산 처리

위 표를 참고하여, 실시간 오디오 통신 및 끼어들기(Barge-in) 기능이 필수적이므로, LiveKit을 메인 통신 프레임워크로 선정하였습니다. LiveKit + [ ] 조합으로 프론트엔드와 백엔드를 구성할 예정입니다.

실시간 음성 대화 (Real-Time Voice)

제가 원하는 느낌의 동작을 하려면 음성 인식(STT), 거대언어모델(LLM), 음성 합성(TTS)으로 이어지는 파이프라인 전체가 ‘스트리밍(Streaming)’ 구조로 최적화되어야 할텐데, Streaming이라는게 구현하기 상당히 어려운 영역이라고 알고 있고, 아마, 조금씩 만들어보면서 방향을 잡아나가야 할 것 같습니다.

일반적인 음성 대화의 흐름 (Non-Streaming)

단계구성요소설명
1VAD Delay사용자의 말이 끝났는지 판단하기 위해 침묵을 기다리는 시간
2Audio Upload오디오 데이터를 클라우드로 전송
3ASR Processing전체 오디오를 텍스트로 변환
4LLM Inference전체 답변 텍스트 생성 완료 대기
5TTS Synthesis전체 텍스트를 오디오로 변환
6Audio Download & Buffering재생 준비

문제점: 각 단계를 순차적으로 처리하므로 전체 지연 시간이 누적되어 실시간 대화에 부적합합니다.

Streaming 방식의 구조 (Real-Time)

단계기술설명
1Transport (WebRTC)오디오가 20ms 단위의 프레임으로 쪼개져 실시간으로 서버(LiveKit Agent)에 도착
2Server-side VAD (Silero VAD)오디오 프레임 스트림을 실시간으로 분석하여 발화 시작/종료 감지
3Streaming STT (ReazonSpeech v2)발화 감지 즉시 오디오 프레임을 STT 엔진에 밀어 넣기. 중간 결과(Interim Results) 텍스트 생성
4Speculative LLM Processing(고급 최적화) STT의 중간 결과만으로 LLM이 문맥 파악 후 답변 생성 준비 또는 즉시 토큰 생성 시작
5Streaming LLMLLM이 완성된 문장을 한꺼번에 내뱉지 않고 토큰(Token) 단위로 스트리밍
6Streaming TTS (Style-Bert-VITS2)문장 부호나 의미 단위로 텍스트가 모이면 즉시 오디오 합성 시작
7Playback합성된 첫 번째 오디오 청크가 즉시 WebRTC 트랙을 통해 사용자에게 전송

장점: 병렬 처리와 점진적 결과 전달로 지연 시간을 최소화하여 자연스러운 실시간 대화 구현 가능

데이터 수집

당연하겠지만, 우선 비즈니스 회화에 대한 데이터 및 경어, 존경어와 같은 일본의 특수한 언어에 대한 데이터를 수집해야 했고, 수집할 데이터는 아래와 같습니다.

BSD (Business Scene Dialogue) 데이터셋: ryo0634/bsd_ja_en

  • Hugging Face에서 다운로드
  • JSON 형식의 대화 데이터
  • 상황(전화, 회의, 사과) & 화자 관계(상사-부하, 거래처) 별 분류
  • 비즈니스 매너 문서: business-mail.jp 등에서 수집
  • 경어/문법 교정 데이터: TMU Evaluation Corpus나 KeiCO 코퍼스

KeiCO 코퍼스

출처: GitHub - Liumx2020/KeiCO-corpus
논문: Liu et al. (2022) - “Construction and Validation of a Japanese Honorific Corpus”

규모: 10,007개 문장 (5개 어노테이션 per 문장)
어노테이션:
   - 경어 레벨 (4단계)
   - 존경어(尊敬語/sonkeigo) 분류
   - 겸양어(謙譲語/kenjougo) 분류
   - 정중어(丁寧語/teineigo) 분류
   - 활동 분야(field)

경어 레벨 체계 (Level 1-4)

레벨이름사용 상황마커 예시
1최고 존경 (最高敬意)공식 연설, 정중한 비즈니스ございます, 申し上げます, いたします
2일반 존경 (一般敬意)비즈니스 대화, 공식 문서ます, ございます
3중간 경어 (中程度敬意)일상 존경ます, です
4캐주얼 (カジュアル敬意)가까운 관계

경어 오류를 감지하고 피드백할 때:

아래와 같은 방식으로 텍스트 형태로 화면에 응답을 띄우려고 한다. 아니면, 음성으로도 피드백을 줄 수 있을 것이다.

# 사용자의 잘못된 표현
user_utterance = "すみません。"  # Level 4 (casual)

# KeiCO 데이터로부터 분류 학습
correct_level = 1  # 비즈니스는 최고 존경 필요
correct_form = "失礼いたします。"

# 피드백 생성
feedback = "귀하의 'すみません'은 Level 4입니다. " \
           "비즈니스 상황에서는 Level 1인 '失礼いたします'를 사용해야 합니다."

데이터 분류 및 구조화

BSD 데이터 분류 스키마

상황(Scenario)
├── 전화 (Telephone)
│   ├── 고객 서비스
│   ├── 주문 확인
│   └── 문제 해결
├── 회의 (Meeting)
│   ├── 사업 협상
│   ├── 프로젝트 검토
│   └── 결과 보고
├── 사과 (Apology)
│   ├── 실수 인정
│   ├── 보상 제시
│   └── 신뢰 회복
└── 기타 (Other)
    ├── 이메일 대화
    └── 명함 교환

화자 관계(Speaker Relationship)
├── 상사-부하 (Superior-Subordinate) → Level 2 이상 필수
├── 동료 (Peers) → Level 2-3
├── 거래처 (Business Partner) → Level 1-2
├── 신규 고객 (New Customer) → Level 1 권장
└── 기존 고객 (Existing Customer) → Level 2-3

전처리 및 형태소 분할

왜 형태소 분할이 필요한가?

일본어는 띄어쓰기가 없기 때문에, 의미 있는 단위로 분할해야 한다. 일본어에 특화되어서 형태소 분석 및 의미 단위로 텍스트를 나눌 수 있는 도구가 필요하다.

의미 단위로 분류해 줄 수 있는 도구는 SudachiPy라고 하는 꽤 규모가 큰 일본어 형태소 분석기이다.

SudachiPy: https://pypi.org/project/SudachiPy/

WAP Tokushima Laboratory of AI and NLP: https://nlp.worksap.co.jp/

임베딩 생성

조사한 내용에 따르면 아래 모델이 일본어 문장 임베딩에 가장 적합하다고 하는데, 우선 적용해보고 성능이 만족스럽지 않으면 다른 모델도 시도해볼 예정이다.

모델 선택: cl-nagoya/ruri-large (일본어 특화)

from sentence_transformers import SentenceTransformer

# 일본어 특화 모델
model = SentenceTransformer('cl-nagoya/ruri-large')

# 텍스트를 384차원 벡터로 변환
texts = [
    "会議でのビジネス敬語",
    "電話での丁寧な表現",
    "謝罪の文化"
]

embeddings = model.encode(texts)  # shape: (3, 384)

print(f"임베딩 생성 완료: {embeddings.shape}")

Qdrant 벡터 DB 구축

Qdrant는 벡터 검색에 최적화된 오픈소스 데이터베이스로, 대규모 임베딩 데이터를 효율적으로 저장하고 검색할 수 있다. 이 옵션 또한 마찬가지로 더 좋은 벡터 DB가 있으면 교체할 예정이다.

하이브리드 검색 구현(옵션)

벡터 검색 + BM25 키워드 검색의 조합을 사용할 예정인데, BM25란? https://www.geeksforgeeks.org/nlp/what-is-bm25-best-matching-25-algorithm/ 간단하게 얘기해서, 문서 내 단어 빈도와 역문서 빈도를 고려하여 키워드 기반 검색의 정확도를 높이는 알고리즘이다.

이게 정말로 필요할지는 모르겠다. 우선, BM25없이 벡터 검색만 구현해보고, 성능이 만족스럽지 않으면 BM25를 추가하는 방향으로 할 예정이다.

참고 자료

Japanese Speaking App 1 / 1
이전 편 없음
다음 편 없음

목차

댓글