vignette/docs/MASTERPLAN.md
Yun Chan 05aa7b312e 로컬 whisper STT 사이드카 디바이스 폴백과 deprecated audioop 제거
cuDNN 부재 환경에서 ctranslate2 는 Python 예외가 아니라 네이티브 크래시로 죽어
프로세스가 통째로 사라진다. 같은 프로세스의 try/except 로는 절대 잡을 수 없어
디바이스 확인을 버릴 수 있는 자식 프로세스(--self-check)로 분리했다.
auto 는 CUDA 프로브 실패 시 CPU(int8)로 폴백하고, 명시적 --device cuda 는 조용히
강등하지 않는다.

함께 고친 것:
- warmup PCM 생성의 연산자 우선순위 버그(b"\x00\x00" * N // 2 가 바이트열 정수
  나눗셈이 되어 TypeError). warmup_pcm() 으로 분리하고 테스트로 고정했다.
- audioop 은 Python 3.13 에서 제거되므로 array + 정수 연산으로 RMS 를 직접 구한다.

실측(저장소 무참조 synthetic seed 8.72초, CPU int8 small):
interim 9 · final 5 · word timestamp 12개 present, 전사는 원문과 한 글자 차이.
사이드카 회귀 37/37.
2026-08-08 01:39:58 +09:00

324 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 한신대학교 SW중심대학 산학협력 — 생성형 AI 심리상담 시뮬레이션 플랫폼 마스터플랜
> 통합 기준 문서 (SoT, Single Source of Truth) · 작성 2026-06-25 · 트웬티온스 산학협력
> 제약: **20주 / 매칭금 500만 / 기존 풀스택팀**
>
> **🔄 2026-06-25 업데이트 (윤찬 확인):** **IRB 정식 심의 불필요.** 수련생 대상 *교육 활용*이라 인간 대상 임상시험이 아니므로 IRB 면제. → 아래 "IRB 승인"이 걸려있던 의존성/리드타임은 모두 해소(Phase 3 게이트 제거, 즉시 착수 가능). 단 **미성년 원본 사례데이터(0615 등) 활용동의 + 개인정보 처리방침**은 별도로 한신대 공문 확인 유지(IRB와 무관한 데이터 거버넌스 사안).
> 본 문서는 9개 도메인 전문 설계서를 단일 마스터플랜으로 종합한다. 각 도메인 상세는 §부록 A의 설계서 원본 참조.
상담 수련생 훈련용 — **가상내담자 시뮬레이션 + AI 실시간 피드백 + 안전 가드레일**. 이 플랫폼은 진단·치료가 아니라 **수련생 연습용**(FDA General Wellness / 식약처 비의료기기 포지셔닝)이라는 점을 전 계층에서 고정한다.
---
## 0. 한 페이지 요약 (의사결정 고정값)
| 영역 | 확정 결정 | 핵심 근거 |
|---|---|---|
| **AI 엔진** | 기본=Anthropic Messages API(Opus 4.8/Sonnet 4.6) **엔진 어댑터** 뒤에 배치. `claude -p`(Max OAuth)는 옵션 플래그·개발 시연용 | `claude -p`+OAuth 과금 누수(이틀 $1,800 사례)·동시성 1프로세스 한계·rate limit 마비 리스크. 어댑터 한 줄로 전환 가능하게 흡수 |
| **3-AI 구조** | 상담사 AI(선택) / 내담자 AI / 백그라운드 평가 AI. **정보 비대칭을 DB `visible_to[]` 컬럼이 강제**(프롬프트 신뢰 X) | 상담사AI가 내담자 CCD를 보면 시뮬레이션 가치 0 |
| **상태머신** | 라포→탐색→개입→정리 전이는 **FastAPI 백엔드가 결정론적으로 소유**(LLM 아님) | 단계 흐릿하면 수련생 채점 신뢰도 붕괴 |
| **저항 엔진** | 내담자 저항을 프롬프트 형용사 아닌 **상태머신 수치**로 단계 주입 (핵심 차별기술) | CARE-Bench가 LLM positivity bias(과순응) 정량 확인 |
| **피드백** | 피드백 패널 = 1급 시민. **자유연습(피드백 OFF) 기본 차단** | Stanford CARE RCT: 연습만 d=-0.52 하락, 연습+피드백 집단격차 d=0.72 |
| **프론트** | React 19 + SSE, pnpm/Turborepo 모노레포(`packages/core` 100% 공유, 추후 RN) | 웹→네이티브 전환을 구조로 증명, 20주 과대약속 회피 |
| **백엔드** | FastAPI + SSE 스트리밍, 상태머신·가드레일·엔진 어댑터 | |
| **DB** | NAS PostgreSQL 16(+pgvector) 단일 SoR. Timescale은 확장 시 hypertable만 선택 | 20명 규모에 Timescale 과잉 |
| **배포** | Docker Compose 단일 호스트 모놀리식(5~6 컨테이너), Caddy 리버스프록시. K8s 금지 | 20주·인력 제약에 모놀리식이 최적 |
| **외부노출** | chanpaca.net = Cloudflare named tunnel(일반) **+ SSE 경로는 버퍼링 우회 분리**(Tailscale Funnel) | Cloudflare가 SSE를 ~100KB 버퍼링 + 100초 timeout → 50분 상담 스트림 충돌 |
| **음성** | 1차 캐스케이드(Deepgram STT → 로컬 엔진 → OpenAI gpt-4o-mini-tts). s2s 1차 탈락 | transcript가 평가·로깅·재귀학습·가드레일의 1급 자산. s2s는 transcript 손실 |
| **인증** | BFF + OAuth 2.1 Auth Code + PKCE(S256). 토큰은 서버(Redis)에만, 브라우저엔 HttpOnly 쿠키 | 미성년 사례데이터+상담 민감정보 → XSS 토큰탈취 원천 차단 |
| **안전** | MIND-SAFE식 다층 분리 + 한국어 자살콘텐츠 분류(Llama Guard 한국어 미지원 공백 보강) | 재현율=법적 책임 최우선 |
---
## 1. 시스템 아키텍처 개요
### 1.1 물리 토폴로지 (인바운드 포트 0)
```
[교수님 브라우저] https://chanpaca.net
┌─────────┴──────────┐
│ Cloudflare Edge │ ← named tunnel(영구 URL, TLS/DDoS)
│ (정적·일반 API) │ ⚠ SSE는 버퍼링 → 분리 경로
└─────────┬──────────┘
│ (outbound-only, 개방포트 0)
┌───────────────────────────┼────────────────────────────────────────┐
│ 로컬 PC / NAS (한국 내 · 데이터 주권) Docker Compose: counsel-net │
│ ┌────────────┐ │
│ │ cloudflared│──┐ ┌──────────┐ ┌──────────────────────────┐ │
│ │(named tun.)│ │ │ frontend │ │ backend (FastAPI) │ │
│ └────────────┘ │ │ React19 │ │ ┌────────────────────┐ │ │
│ ┌────────────┐ ├──►│ 정적빌드 │◄──►│ │ 상태머신(결정론) │ │ │
│ │ Caddy │◄─┘ └──────────┘ │ │ 가드레일/안전레일 │ │ │
│ │ SSE flush-1 │◄──── [SSE 직결경로] │ │ SSE 스트리머 │ │ │
│ └─────┬──────┘ (Tailscale Funnel) │ │ 엔진 어댑터(라우터)│ │ │
│ │ │ └────────┬───────────┘ │ │
│ ▼ └──────┬────┼──────────────┘ │
│ stream.chanpaca.net (SSE 전용) │ │ │
│ ┌─────▼─┐ ┌▼─────────┐ │
│ ┌────────────────┐ ┌──────────────┐ │engine │ │ voice-gw │ │
│ │ Postgres 16 │ │ pgvector(RAG)│ │adapter│ │ OpenAI │ │
│ │ (NAS 영구볼륨) │ │ 임베딩 1024d │ │ ①claude_api(기본) │ │
│ │ 학습로그·관계형 │ └──────────────┘ │ ②claude_cli(옵션) │ │
│ │ RLS 이중강제 │ │ ③openai/solar │ │
│ └────────────────┘ [Presidio PII 마스킹] ──► 외부 LLM(마스킹 후만) │
└──────────────────────────────────────────────────────────────────────┘
```
**원칙**: ① 인바운드 포트 0 (cloudflared outbound 터널) ② 데이터는 로컬(NAS)을 떠나지 않음, PII 마스킹 후에만 외부 LLM 호출 ③ 전송 계층 추상화(`VITE_SSE_BASE_URL`)로 SSE 경로 무중단 전환.
### 1.2 논리 레이어 (프롬프트 캐싱 친화)
```
[L0 역할+안전가드레일+도식노출금지] ┐
[L1 페르소나 카드(정적)] ├─ cache_control (입력비 90%↓, 실측 59~70% 절감)
[L2 RAG 임상청크] ┘
[L3 상태머신 주입(stage, openness)]
[L4 메모리 버퍼(사실 hard-pin)]
[L5 수련생 발화]
```
---
## 2. AI 3종 상호작용 모델
### 2.1 정보 비대칭 (DB가 강제)
| AI | system 프롬프트 | 볼 수 있는 것 | 절대 못 보는 것 |
|---|---|---|---|
| **① 상담사 AI** (선택/보조) | 마이크로스킬 시연용 | 대화 표면 | 내담자 CCD·DSM 차원·평가결과 |
| **② 가상내담자 AI** | 페르소나 카드+CCD+저항 | 자기 페르소나·대화 | 평가 점수·정답 라벨 |
| **③ 백그라운드 평가 AI** | 루브릭+골든 taxonomy | 전체 회기·CCD·정답 | (전부 봄, 학습자에 노출 X) |
3-AI는 서로 다른 system 프롬프트의 **독립 `claude -p`/API 호출**. "누가 무엇을 보는가"는 **DB `visible_to[]` 컬럼이 강제**하며 프롬프트를 신뢰하지 않는다.
### 2.2 턴 사이클 (결정론 상태머신 중심)
```
수련생 발화 U_t
→ [입력 가드레일] PII 마스킹 + 위기 분류(수련생 실제위기 vs 페르소나 연기 구분)
→ [상태머신] stage·effective_openness(t) 계산
effective_openness = clamp(stage.openness
+ rapport_credit(t)*unlock_rate
- resistance*decay(t), 0, 1)
→ [내담자 AI] 페르소나 응답 생성 (Structured Outputs, CCD 직접노출 금지)
→ [출력 가드레일] 자살수단 정보 차단, ideation_stage ≤ 3 상한
→ [평가 AI 2-tier]
· fast-loop(경량): U_t만 보고 4차원 태깅 (실시간 신호)
· deep-loop(Opus): 단계 전환·회기말, 0-5 채점 + 대안발화 (대시보드)
→ [로깅] TurnLog → Postgres (= 재귀학습 JSONL 원천)
```
**rapport_credit**: 수련생이 공감·반영·타당화·홀딩을 쓰면 +, 조언점프·평가적언어·유도질문이면 0/. → **좋은 상담을 하면 내담자가 열리고, 나쁜 상담을 하면 닫힌다.** 0615 실데이터의 "방어가 서서히 풀어지고 있음" 궤적 재현.
### 2.3 평가 AI 2-tier 루프 (핵심 레버)
- **fast-loop**: Haiku/Solar 경량, 발화별 4차원(공감·개방질문·검증·이론부합) 태깅 → 콜드스타트 지연·비용 통제
- **deep-loop**: Opus 4.8, 전체 회기 + 골든라벨 RAG로 0-5 채점(CTRS는 0-6 분리) + 대안발화 제시. **실시간 팝업보다 종료 후 대시보드가 SUS↑·인지부하↓**
- **LLM-judge 보정**: raw 직접사용 금지, 길이정규화, 이중코딩 vs LLM weighted-κ≥0.6 / ICC≥0.75 게이트 통과분만 골든셋 승격
### 2.4 가상내담자 페르소나 (DSM-5 = 내부 파라미터, 비노출)
- **차원적 프로파일**(RDoC 정신): negative_affect·hopelessness·suicide_risk{ideation_stage 1~5}·sleep_disturbance를 0~1 연속값 (단일 DSM 라벨 X)
- **CCD 8요소**(Patient-Ψ): core_belief(worthless 등)·automatic_thought·coping_strategy — **직접 발화 금지**, 행동으로만 드러내 상담자가 추론하게
- **시드 페르소나 3종(교수 검수 필수 게이트)**: P1=0615 청소년 우울·자퇴·자살사고(hard) / P2=성인 범불안·신체화(moderate, 자살0) / P3=인간중심 미혼모(PCT 훈련). 2차 백로그: ADHD품행·경계선특질·적응장애·위기4~5단계 전용
---
## 3. 데이터 모델 + Postgres 스키마 요약
### 3.1 원천 — 0615 파란색 라벨의 3종 혼재 (실측 확인)
`축어록_파란색라벨_0615.hwpx`를 직접 파싱(파랑 #3057B9, 라벨 89개·77종) → 한 셀에 **3종이 혼재**함을 확인. 학습 신호 오염 방지를 위해 **3개 분리 필드로 격상**이 스키마 설계의 출발점:
- **(A) 기법 태그**(복수): 공감/반영/탐색/홀딩/타당화/직면/해석/자기개방/안정화/희망고취/위험사정…
- **(B) 내담자 상태 태그**(복수): 비자발/방어/자살사고인정/부정적자기인식/갈등상태…
- **(C) 슈퍼바이저 논평** 2종: `rationale`(근거설명) vs `critique`(과도한 자기개방·비언어반영 부족 등)
### 3.2 스키마 요약 (PostgreSQL 16, 3 스키마: app / audit / ds)
```sql
-- ── app: 운영 ──────────────────────────────────────────────
sessions(id, learner_id, persona_id, theory_mode, started_at, ended_at, stage_path JSONB)
turns/utterances( -- 발화 = 최소 원자단위, 모든 라벨/평가/PII가 FK로 매달림
id, session_id FK, seq, speaker('counselor'|'client'),
stage('라포'|'탐색'|'개입'|'정리'),
text, -- 저장 전 Presidio PII 마스킹
text_masked, -- 외부 LLM 전송용
actor_kind, -- 3 AI + 인간(수련생/슈퍼바이저) 통합 출처
llm_provider, model, tokens_in, tokens_out, cost_usd, visible_to TEXT[])
-- 라벨은 버전드 코드테이블 + 다대다(복수 라벨)
technique_label_def / client_state_def / stage_def / scale_def(0-5, CTRS 0-6)
turn_technique(turn_id, label_id) / turn_client_state(turn_id, label_id)
feedback_scores(turn_id, dimension, score, rationale) -- 0-5, D3
supervisor_comment(turn_id, kind('rationale'|'critique'),
text, intent_deviation JSONB{expected, actual, severity, dimension}) -- 윤찬 "의도와 다른 부분" 1급 시민
safety_events(session_id, trigger_type, ko_risk_level, escalated, latency_ms, created_at)
rag_chunks(id, source, embedding vector(1024), text)
-- ── audit: append-only 법적 증거 ──────────────────────────
event_log / llm_call_log(cost·드리프트·inference_geo) / audit_log(열람추적)
-- ── ds: 재귀 학습 파이프라인 ──────────────────────────────
dataset / dataset_item / annotation_round / annotation / export_manifest
-- AI자동(1R) → 인간검수(2R) → IAA 게이트(κ≥0.6, ICC≥0.75) → 골든셋 → JSONL
```
### 3.3 거버넌스 (인프라 직결)
- **저장 전 PII 마스킹 하드 게이트**: backend→외부 LLM 경로에 Presidio(MedicalNERRecognizer). 마스킹 후 텍스트만 적재·전송
- **RBAC + Postgres RLS 이중강제**: 학습자=본인 / 교수자=담당 코호트 / 관리자=전부+교수활동(열람을 audit_log에 기록)
- **데이터 국내처리**: DB=NAS(국내), 민감구간은 국내 모델(Solar/HyperCLOVA) 라우팅 또는 `inference_geo:us` 명시
- **미성년 원본 4단계 격리**: 원본 축어록은 플랫폼 DB 절대 미적재, 사람이 가명처리·전문가 검수한 CCD 스펙만 진입 (Character.AI 판례 대응)
---
## 3.6 RAG 아키텍처 (2026-06 최신 기준 · 윤찬 요청 보강)
> RAG는 부가기능이 아니라 본 시스템 3개 축(페르소나 일관성 / 피드백 근거 / 지식)을 떠받치는 핵심. 2026.6 production RAG 합의 = **failure mode 기준으로 사다리 최소한만 오른다**(GraphRAG·Agentic 풀스택 처음부터 X).
### 용도별 매핑 (서로 다른 RAG)
1. **페르소나 메모리** (내담자 일관성) — 순수 RAG 아님 → **하이브리드 메모리**: 구조화 상태(상태머신 수치) + rolling summary + episodic 벡터 recall. 임상 비네트는 소규모 고정셋이라 검색난도 낮음.
2. **피드백 근거** (0615 발화-라벨 정답셋 + 슈퍼바이저 논평) — 오답비용 큼 → 하이브리드 + 리랭킹 (+확장 시 CRAG 그레이딩).
3. **지식** (DSM-5 진단기준 · 상담이론 인간중심/CBT) — 정적 KB → 하이브리드 + Contextual Retrieval.
### 확정 스택 (MVP = Phase 1)
- **임베딩 = BGE-M3**: 다국어(한국어 강함) + dense·sparse·ColBERT 멀티벡터를 **단일 모델**로 제공 → 하이브리드와 late-interaction을 한 모델로 흡수. *우리 rag-memory가 이미 BGE-M3 사용 중 → 재활용.*
- **저장/검색 = pgvector(HNSW)**: 기존 NAS Postgres에 인프라 추가 0, 수백만 벡터 sub-100ms.
- **하이브리드 검색**: dense(pgvector) + sparse BM25(PG full-text 또는 BGE-M3 sparse), top-50 회수.
- **Contextual Retrieval(Anthropic)**: 청크 임베딩 전 1문장 맥락 주입 → 검색실패 **49%↓**(+리랭킹 시 **67%↓**).
- **리랭커 = cross-encoder(BGE-reranker-v2-m3, 한국어)**: top-50 → top-5. 답변품질 **15~30%↑**.
### 확장 (Phase 2+)
- **Adaptive RAG 라우터**(2026 SOTA): 질의 복잡도 분류 → 단순=하이브리드 / 복잡=다단계 라우팅.
- **CRAG(Corrective RAG)**: 피드백 근거처럼 오답비용 큰 경로에 관련성 그레이딩 + 재질의.
- (선택) **GraphRAG**: 상담이론 교차개념(인간중심↔CBT 연결) 맵이 커질 때만 2차 — 단순 lookup엔 과잉이라 1차 제외.
- (선택) ColBERT 독립 late-interaction: BGE-M3 멀티벡터로 충분, 품질 부족 시에만.
> 근거 출처: [Anthropic Contextual Retrieval](https://www.anthropic.com/news/contextual-retrieval), [RAG Production Patterns 2026](https://ailearningguides.com/rag-production-patterns-2026/), [Jina ColBERT v2 다국어](https://jina.ai/news/jina-colbert-v2-multilingual-late-interaction-retriever-for-embedding-and-reranking/). Agentic+KG 환각 62%↓(2026.5 MLOps 벤치).
---
## 4. Phase별 구현 로드맵 (단일 로드맵, 산발 task 금지)
> 각 Phase에 **우선순위·의존성·완료기준(DoD)** 명시. Phase는 순차, 내부 트랙은 병렬(소유 파일 분리).
### Phase 0 — 기반 정렬 (1~2주차) · 우선순위 P0
- **목표**: 인프라 스캐폴드 + taxonomy 확정 + IRB 착수
- **작업**:
- docker-compose 6서비스 스캐폴드 + `secrets/` git-ignore + Caddyfile(`flush_interval -1`)
- Postgres 스키마 §3.2 적용 + RLS 정책 + pgvector
- 라벨 taxonomy v1.0 확정(3축 분리) → 0615 축어록 골든셋 라벨링 1차
- IRB 프로토콜 초안(Stanford CARE 차용: minimal risk·자살시나리오 1차 제외·전문가 검증 내담자)
- 엔진 어댑터 인터페이스 정의(provider 플래그: claude_api/claude_cli/openai/solar)
- **의존성**: 없음 (시작점). taxonomy ↔ DB 코드테이블 동기화 필요
- **완료기준**: `docker compose up`으로 6서비스 기동 + Postgres 스키마 마이그레이션 통과 + 골든셋 50발화 라벨링 + IRB 신청서 제출
### Phase 1 — MVP 코어 루프 (3~8주차) · 우선순위 P0
- **목표**: 텍스트 기반 1-페르소나 상담→피드백 1회 완주 (chanpaca.net 시연 가능)
- **트랙 A (백엔드/AI)**: 엔진 어댑터 Messages API 직결 + 캐싱 레이어 + 상태머신(라포→탐색→개입→정리) + 내담자 AI(P1 페르소나) + 평가 AI deep-loop + 입출력 가드레일
- **트랙 B (프론트)**: `/learn` 셸 + 상담 시뮬레이션 UI 3존(대화60%·피드백패널40%·숨김안전배너) + SSE 스트리밍(React19 `useActionState`/`use`) + 단계바
- **트랙 C (인프라)**: Cloudflare named tunnel → chanpaca.net + SSE 실측(50분 세션 끊김 테스트) → 끊기면 stream.chanpaca.net Funnel 분리
- **의존성**: Phase 0 전부. 트랙 A·B는 SSE 스키마·점수 Structured Output 스키마 합의 후 병렬
- **완료기준**: 교수님이 chanpaca.net에서 P1 내담자와 텍스트 상담 → 회기말 0-5 4차원 피드백+대안발화 수신 → 전 turn이 Postgres에 cost 텔레메트리 포함 적재. **저항 엔진 작동 검증**(공감 시 개방도↑, 조언점프 시↓)
### Phase 2 — 음성 + 3역할 + 페르소나 확장 (9~15주차) · 우선순위 P1
- **목표**: 멀티모달 + 3역할 페이지 + 페르소나 3종 + 안전 가드레일 완성
- **트랙 A (음성)**: 캐스케이드(Deepgram STT → 엔진 → OpenAI TTS), persona→voice 매핑 테이블, 턴테이킹(semantic EOT·침묵 임계 1.2~2.0s), barge-in 로깅
- **트랙 B (3역할)**: `/teach`(담당 학습자 전체 열람+검수 오버라이드) `/admin`(전부+교수활동 감사) + BFF OAuth 2.1 + RBAC×소유권 이중게이트
- **트랙 C (AI)**: 페르소나 P2·P3 추가(교수 검수), fast-loop 실시간 태깅, 한국어 자살콘텐츠 분류기(few-shot 5단계)
- **트랙 D (데이터)**: 재귀 학습 파이프라인(annotation_round + IAA 게이트), 교수자 검수 루프(AI vs 교수자 weighted-κ 누적)
- **의존성**: Phase 1 코어 루프. 음성은 transcript 입력레일 위기분류와 결합 필수
- **완료기준**: 음성 왕복 상담 round-trip ~1.1~2.0s + 3역할 권한 격리 실동작 검증(학습자가 타인 기록 접근 차단) + safety_events 트리거→교수자 자동알림 + 교수 검수 데이터 누적
### Phase 3 — IRB 파일럿 + 효과성 검증 (16~20주차) · 우선순위 P1
- **목표**: 수련생 20명 IRB 파일럿 + 사전사후 효과 측정 + 데이터셋 골든화
- **작업**: IRB 승인 하 20명 pre-post(자기효능감, 자살/자해 시나리오 1차 제외) + SUS·KPI 측정 + 골든셋 export_manifest → JSONL + 결과 리포트
- **의존성**: Phase 2 전부 + IRB 승인(Phase 0 신청)
- **완료기준**: 20명 세션 완주 + KPI 충족(임베딩 일관성≥0.79, 환각률≤5%, SUS≥80, κ≥0.6/ICC≥0.75) + 자기효능감 사전사후 유의 + 재귀학습 데이터셋 1차 산출
### 1차 명시 제외(2차 백로그)
6-에이전트 풀시스템 · 임상KG 자체구축 · 멀티벤더 A/B · 위기 4~5단계 자유시뮬 · RN 네이티브 앱(1차는 `apps/mobile` 스캐폴드+core import 검증만) · OpenAI Realtime s2s · K8s · Timescale 전면 도입 · 한신대 학내 SSO(1차 Google OIDC 단독)
---
## 5. 기술스택 확정
| 계층 | 확정 | 비고 |
|---|---|---|
| 프론트 | **React 19** + Vite 정적빌드, SSE(`useActionState`/`useOptimistic`/`use`), pnpm+Turborepo 모노레포 | `packages/core` 로직/타입/스키마 100% 공유, 추후 RN/Expo |
| 백엔드 | **FastAPI** + uvicorn(`--workers`, SSE 롱리브드 연결 산정) | 상태머신·가드레일·엔진 어댑터·SSE 스트리머 소유 |
| DB | **PostgreSQL 16** + pgvector(RAG 통합), NAS 영구볼륨, RLS | Timescale은 hypertable 선택 확장 |
| 컨테이너 | **Docker Compose** 단일 호스트 모놀리식(6 컨테이너), Caddy 리버스프록시(`flush_interval -1`) | 이식=compose+secrets, 클라우드 VM(국내 리전) `docker compose up` |
| AI 엔진 | **엔진 어댑터** → 기본 Anthropic Messages API(Opus 4.8/Sonnet 4.6), `claude -p`(Max OAuth)는 옵션 플래그 | 과금 누수·동시성·rate limit 흡수. tier: client=Sonnet/Solar, feedback=Opus, cheap=Haiku |
| 음성 | ~~OpenAI gpt-4o-mini-tts + Deepgram STT, 로컬은 폴백~~**2026-08-08 결정으로 로컬 우선**: STT는 노트북 상주 faster-whisper(`local_whisper`), TTS는 노트북 Higgs Audio v3. 근거·제약은 [`decisions/local-voice-stack.md`](./decisions/local-voice-stack.md) | s2s 1차 탈락(transcript 보존). Higgs 운영 사용은 라이선스 확인 전까지 dev 전용이라 운영 TTS는 OpenAI 유지 |
| 인증 | **OAuth 2.1 Auth Code + PKCE(S256)** BFF, Google OIDC 1차, Authlib | 토큰 Redis만, HttpOnly `__Host-` 쿠키, stateful 세션(IRB 철회 즉시 무효화) |
| 외부노출 | **Cloudflare named tunnel** + SSE는 Tailscale Funnel 분리 | 인바운드 포트 0 |
| 안전 | Presidio PII 마스킹 + NeMo rail + 한국어 자살분류 + 결정론 게이트 | Llama Guard 한국어 미지원 보강 |
---
## 6. 핵심 리스크 + 완화책
| # | 리스크 | 영향 | 완화책 |
|---|---|---|---|
| R1 | **`claude -p` OAuth 과금 누수** (이틀 $1,800 사례) | 매칭금 증발 | 기본=Messages API 직결, claude_cli는 옵션 플래그+비용캡 모니터. 어댑터로 무중단 전환 |
| R2 | **Cloudflare SSE 버퍼링·100초 timeout** | 시연 중 스트림 끊김 | named tunnel(일반)+Tailscale Funnel(SSE) 분리, 30초 heartbeat, 전송계층 추상화 |
| R3 | **positivity bias**(저항 내담자 재현 실패) | 시뮬레이션 가치 저하 | 저항을 백엔드 결정론 수치로, Big5 저항 파라미터, CARE-Bench 회귀 테스트 |
| R4 | **CCD 메타노출**("제 핵심신념은…") | 추론 훈련 무력화 | 직접노출 금지 + QA 체크리스트 + Structured Outputs |
| R5 | **자살수단 정보 누출** | 법적 책임·안전 | ideation_stage ≤ 3 상한, 출력 가드레일, 4~5단계는 안전종료 시나리오만 |
| R6 | **LLM-judge 편향**(길이·성별) | 채점 타당도 | raw 직접사용 금지, 길이정규화, 이중코딩 κ≥0.6/ICC≥0.75, 성별 균형 |
| R7 | **PII 외부 LLM 유출** | IRB·법적 책임 | Presidio 마스킹 미들웨어 강제, 마스킹 후만 적재·전송, safety_events 로깅 |
| R8 | **한국어 위기 분류 공백**(Llama Guard 미지원) | 위기 미탐지 | JMIR 2026 한국어 자살콘텐츠 벤치(few-shot 5단계), 재현율 우선 |
| R9 | **한국어 토큰 팽창(최대 35%)** | 비용 과소추정 | 실샘플 token counting, cost_usd 실측 적재 후 재추산, 캐싱 |
| R10 | **NAS 단일 호스트 SPOF** | 시연 중 다운 | 스냅샷 백업, pgdata 정기 덤프, 클라우드 VM 페일오버 리허설 |
| R11 | **한신대 SSO 미확인** | 2단계 일정 불확실 | 1차 Google OIDC 단독, SSO는 Authlib provider 추상화 뒤 2차, 공문 질의 |
| R12 | **20주 일정 압박** | 과대약속 실패 | 1차 범위 통제(2차 백로그 명시), MVP 코어 루프 우선, RN은 스캐폴드만 |
---
## 7. 학술 / IRB 체크리스트
**학술 엄밀성**
- [ ] DSM-5 차원 프로파일(RDoC) 반영, 진단명 외부 비노출 가드레일
- [ ] 가상내담자 충실도: Patient-Ψ(CCD 8요소) + Client101(비네트+메모리)
- [ ] 피드백 타당도: 검증 척도 이식(0-5, CTRS 0-6 분리), 4차원 채점, Structured Outputs
- [ ] 효과성 인과: Stanford CARE RCT(연습+피드백 d=0.72)로 피드백 필수성 입증 → 자유연습 비활성화
- [ ] LLM-judge 보정 프로토콜(이중코딩 vs LLM κ≥0.6/ICC≥0.75)
- [ ] 인용 논문 마스터 목록: PSI-Bench, PsychEval, TherapyGym/THERAPYJUDGE, Roleplay-doh, CARE-Bench, MIND-SAFE
**IRB / 윤리**
- [ ] "교육용·비치료용" intended use 고정(FDA General Wellness / 식약처 비의료기기)
- [ ] minimal risk 프로토콜, **자살 시나리오 1차 제외**, 전문가 검증 내담자
- [ ] 수련생 20명 사전 동의(로그인 직후 하드 게이트, 미동의=시뮬레이션 라우트 서버 차단)
- [ ] 미성년 원본 데이터 4단계 격리, 법정대리인 활용동의 범위 확인
- [ ] PIPC(2024.12) + 생명윤리법 + 가명처리, 데이터 국내처리/해외전송 명시
- [ ] D6 컴플라이언스 매트릭스(APA/PIPC/WHO/Character.AI 판례/FDA)
- [ ] **한신대 공문 질의 필요**: SSO 프로토콜/클레임, IRB 주관, 미성년 원본 활용동의, NAS 국내처리 보장
**KPI(M5 수용기준)**: 임베딩 일관성≥0.79 · 환각률≤5%(목표≤1%) · Top-1≥0.80 · SUS≥80 · κ≥0.6/ICC≥0.75 · 저항 재현 · 자기효능감 사전사후
---
## 8. 즉시 착수할 다음 액션 Top 5
1. **한신대 공문 질의서 발송** — SSO 프로토콜/클레임, IRB 주관 기관, 미성년 원본 사례데이터 법정대리인 활용동의 범위, NAS Postgres 국내처리 보장. (트웬티온스→한신대, 가장 긴 리드타임·블로킹 의존성)
2. **IRB 프로토콜 초안 작성·제출** — Stanford CARE 차용(minimal risk, 자살시나리오 1차 제외, 전문가 검증 내담자, 수련생 20명 사전동의). 승인 리드타임이 Phase 3 게이트.
3. **docker-compose 6서비스 스캐폴드 + Postgres 스키마 §3.2 + Caddyfile(`flush_interval -1`)** — 기존 풀스택팀에 인프라 베이스 인계. 이후 트랙 병렬화의 기반.
4. **0615 축어록 라벨 taxonomy v1.0 확정 + 골든셋 1차 라벨링** — 3축 분리(기법/내담자상태/슈퍼바이저논평) 코드테이블화. 평가 AI 정답셋 + 페르소나 상태전이 정답으로 이중 활용.
5. **엔진 어댑터 PoC(Messages API 기본 + 캐싱 레이어 + Presidio 마스킹 선행)**`claude -p` 과금 누수 회피 검증 + P1 페르소나 1턴 응답 + 비용 텔레메트리 실측. claude_cli는 옵션 플래그로 병존.
---
## 부록 A. 도메인 설계서 원본 (절대경로)
- 학술근거·평가: `Projects/영업/2026/한신대학교 산학협력 프로젝트/설계서/01_학술근거_평가프레임워크_설계서.md`
- DSM-5 페르소나(M1): `…/scratchpad/M1_persona_engine_design.md`
- taxonomy·annotation: `…/_analysis/상담기법-슈퍼비전-taxonomy-annotation-스키마-설계서.md`
- 3-AI 오케스트레이션: `…/설계/3AI_오케스트레이션_아키텍처_설계서.md`
- 데이터모델·NAS Postgres: `Projects/수업/2026/한신대 SW중심대학 산학협력 2026/설계/데이터모델_NAS_Postgres_스키마_설계서.md`
- 인증·RBAC·IRB: `…/설계/auth-rbac-설계서.md`
- 실시간 음성 채팅: `…/설계/[설계서] 실시간 음성 채팅 아키텍처.md`
- 프론트엔드·UX: `…/설계/프론트엔드-UX-설계서.md`
- 배포·인프라: 본 마스터플랜 §1·§4·§5에 통합 (별도 파일 미생성)
## 부록 B. 디자인 철칙 (윤찬, 전 화면 강제)
border-left 강조선 · 이모지(SVG 내부 포함) · AI 양산형 카드덤프 · 무지개 점수색 **전부 금지**. 에디토리얼 미니멀, 한 페이지 한 메시지, 강조는 weight/배경틴트/상단 kicker. 채도 낮은 그린-그레이 신뢰 톤. (린트 강제 권장)