chore: Vignette 모노레포 초기 스캐폴드 + 설계 문서 이관
- apps/web(React) · apps/api(FastAPI) · infra(Docker) · docs(설계 SoT) - 마스터플랜·적대검증·메모리설계·디자인컨셉 docs 이관 - 미성년 사례데이터는 .gitignore로 제외(개인정보 보호)
This commit is contained in:
commit
709baadd01
12 changed files with 3087 additions and 0 deletions
602
docs/MEMORY_KNOWLEDGE_PERSONA_DESIGN.md
Normal file
602
docs/MEMORY_KNOWLEDGE_PERSONA_DESIGN.md
Normal file
|
|
@ -0,0 +1,602 @@
|
|||
# 메모리·지식·페르소나 통합 아키텍처 설계서
|
||||
|
||||
> 한신대 AI 심리상담 시뮬레이션 훈련 플랫폼 · **단일 종합 설계서**
|
||||
> 작성 2026-06-25 · 트웬티온스 산학협력
|
||||
> 종합 대상 4개 영역: ① 회기 간 연속성 메모리(최우선 갭) · ② 지식 데이터베이스(KB) · ③ 페르소나 일관성 · ④ 3-AI 메모리 뷰/정보비대칭/종단평가
|
||||
> 상위 SoT: `HANSHIN_AI_PLATFORM_MASTERPLAN.md` + `MASTERPLAN_REVISIONS.md`(BLUE TEAM 패치). **본 문서는 두 상위 문서의 확정 전제를 깨지 않는 하위 통합 설계다.**
|
||||
|
||||
---
|
||||
|
||||
## 0. 확정 전제 (바꾸지 않음) + 설계 철학
|
||||
|
||||
### 0.1 변경 불가 기술 전제
|
||||
|
||||
| 항목 | 확정값 |
|
||||
|---|---|
|
||||
| 엔진 | 로컬 `claude -p` 상주 멀티턴 풀(`--input-format stream-json`), Messages API는 가용성 폴백 |
|
||||
| RAG | BGE-M3(dense+sparse+ColBERT 단일모델) + pgvector(HNSW) + 하이브리드 + Anthropic Contextual Retrieval + BGE-reranker-v2-m3 |
|
||||
| DB | NAS PostgreSQL 16 + pgvector, RLS 이중강제 |
|
||||
| 백엔드 | FastAPI(상태머신·가드레일·엔진 어댑터 소유) |
|
||||
| 3-AI | 상담사AI(보조/선택) · 내담자AI · 백그라운드 평가AI |
|
||||
| 정보비대칭 | DB `visible_to[]` 컬럼이 강제(프롬프트 신뢰 X), 인간 RBAC×cohort와 2-레이어 AND |
|
||||
|
||||
### 0.2 통합 설계 철학 — 람다 자신의 메모리 시스템에서 차용한 3대 원리
|
||||
|
||||
이 플랫폼의 메모리·지식·페르소나는 **람다(이 AI)의 실제 운영 메모리 구조**를 1차 레퍼런스로 삼는다. 검증된 운영 패턴이라 추측이 아니다.
|
||||
|
||||
| 람다 시스템 원리 | 통합 설계 적용 |
|
||||
|---|---|
|
||||
| **계층 압축** (daily 원본 → weekly 요약 → monthly 요약, 원본 archive 절대보존, 숫자 무손실) | 메모리 4계층(working/episodic/summary/semantic) + KB 3계층(청크/Contextual prefix/community 요약). 원본 append-only, 압축은 파생 테이블에만 |
|
||||
| **역할 분리** (rag-memory=BGE-M3 sqlite 시맨틱 ↔ graphify=GraphRAG 구조, "둘 다 유지, 충돌 X, 질문 유형에 맞게 선택") | 에피소드 메모리(내담자 일관성) ↔ 정적 지식 KB를 **물리적으로 다른 스키마·다른 검색정책**으로 분리. 충돌 시 우선순위 룰로 결정 |
|
||||
| **부트의 큰그림→세부 읽기** (monthly→weekly→daily, "본문 인용 필요할 때만 직접 Read") | 회기 시작 회상도 case_digest(큰그림)→직전 summary(중간)→episodic recall(세부) 순으로 토큰 예산 배분. 매 발화 전체 덤프 금지 |
|
||||
| **IDENTITY/SOUL 불변 + daily 가변** (정체성이 일지 압축에 오염 안 됨) | 페르소나 = 불변 카드(persona_card) + 가변 메모리(persona_session_memory)를 다른 테이블·다른 프롬프트 레이어·다른 권한으로 물리 분리 → drift 구조적 차단 |
|
||||
|
||||
### 0.3 4대 대원칙 (전 영역 관통)
|
||||
|
||||
- **P1. 원본은 절대 삭제 안 한다** — `turns`는 append-only(람다 archive). "망각"은 물리삭제가 아니라 회상 우선순위 배제(salience 하위 → 검색 랭킹 하위 → system 미주입).
|
||||
- **P2. 숫자(상태 수치)는 무손실로 넘긴다** — working state(저항·라포·openness)는 LLM 요약이 아니라 **결정론 상태머신이 DB 컬럼으로** 직접 carry-over. LLM에 수치를 맡기면 hallucination.
|
||||
- **P3. 큰 그림 → 세부 순서로 회상** — 토큰 예산을 case→summary→episodic 순으로 배분.
|
||||
- **P4. 압축은 LLM, carry-over는 결정론** — 서사(narrative)는 LLM 압축(손실 허용), 상태 수치·pinned fact는 코드가 직접 복사(무손실).
|
||||
|
||||
---
|
||||
|
||||
## 1. 통합 메모리 계층도 (working/episodic/semantic/summary + 지식KB)
|
||||
|
||||
```
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
통합 메모리·지식 아키텍처 — 5개 저장 계층 (메모리 4 + 지식 1), 물리 분리
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
계층 수명 저장소(스키마.테이블) 채우는 주체 람다 대응물
|
||||
─────────────────────────────────────────────────────────────────────────────────
|
||||
┌──── 에피소드 메모리 (내담자 연속성) ── app 스키마 ────────────────────────────┐
|
||||
│① WORKING 회기 내 app.session_state 상태머신(결정론) L3+L4 │
|
||||
│ 회기내상태 (체크포인트) +단기버퍼(JSONB) 매 턴 UPSERT 상태머신 │
|
||||
│ │
|
||||
│② EPISODIC 영구 app.turns + 발화 로깅(원자) daily │
|
||||
│ 회기별사건 (append-only) app.turn_embedding(HNSW) 회기 중 임베딩 (원본) │
|
||||
│ │
|
||||
│③ SUMMARY 영구 app.session_summary 회기종료 압축(LLM) weekly │
|
||||
│ 회기종료요약 (+digest 임베딩) 회기당 1행 │
|
||||
│ │
|
||||
│④ SEMANTIC 영구(evolving) app.case_profile 케이스누적 압축 monthly │
|
||||
│ 누적임상프로파일 + app.pinned_fact 회기마다 갱신/병합 +MEMORY │
|
||||
└───────────────────────────────────────────────────────────────────────────────┘
|
||||
┌──── 정적 지식 KB (DSM/이론/taxonomy) ── kb 스키마 (독립, FK 없이 read-only) ──┐
|
||||
│⑤ KNOWLEDGE 영구(버전드) kb.chunk(멀티벡터 HNSW) 오프라인 인덱싱 graphify │
|
||||
│ 정적임상지식 +kb.document +kb.source (배치, 런타임 아님) references│
|
||||
│ 3계층: 원본청크 → Contextual prefix → community 요약(예산초과 fallback) │
|
||||
└───────────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
─────────────────────────────────────────────────────────────────────────────────
|
||||
데이터 흐름:
|
||||
회기종료: ②turns ──압축(LLM)──► ③session_summary ──병합(LLM+rule)──► ④case_profile
|
||||
+ pinned_fact(rule)
|
||||
회기시작: ④case_profile+pinned ──┐
|
||||
③직전 summary ──┼─로드(큰그림→세부)──► 내담자AI system L2-EP
|
||||
②episodic recall(top-k)─┘ (BGE-M3 하이브리드+reranker, ~1.5~2K토큰)
|
||||
⑤KB 청크 ───────────────────로드(정책별 필터)──► system L2-KB (캐시친화)
|
||||
|
||||
모순 시 우선순위: pinned(L4) > 에피소드(이미 한 말) > 상태머신수치 > KB > LLM사전지식
|
||||
("KB는 사전이지 판사가 아니다" — 내담자는 에피소드를 따르고 KB는 보정용)
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
```
|
||||
|
||||
### 1.1 계층별 역할 한 줄 정의
|
||||
|
||||
- **① WORKING**: 상태머신 결정론 수치(stage·effective_openness·rapport_credit·resistance·ideation_stage) + 최근 K턴 버퍼. 매 턴 체크포인트 UPSERT(프로세스 죽어도 복원).
|
||||
- **② EPISODIC**: 발화=최소 원자단위, 저장 시 BGE-M3 임베딩 → 회기 시작 회상의 검색 대상. append-only(재귀학습·audit 원천).
|
||||
- **③ SUMMARY**: 회기당 1행. 구조화 수치 snapshot(무손실) + narrative(LLM 압축) 분리. 다음 회기 carry-over 1차 단위.
|
||||
- **④ SEMANTIC**: 케이스 전체 궤적 누적 압축(CCD 추정·호소문제·라포궤적·치료동맹). pinned_fact=절대 흘리면 안 되는 핵심(모순 처리 기준점).
|
||||
- **⑤ KNOWLEDGE**: DSM/이론/taxonomy/논평. 버전드, 거의 불변. 3-AI가 같은 물리 테이블을 다른 정책으로 검색.
|
||||
|
||||
---
|
||||
|
||||
## 2. 회기 라이프사이클 시퀀스
|
||||
|
||||
```
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
회기 라이프사이클: 회기시작 회상 → 진행(턴 사이클) → 회기종료 압축 → 다음 회기
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
【A. 회기 시작 — 회상 + 상태 복원】 (람다 부트 monthly→weekly→daily 차용)
|
||||
────────────────────────────────────────────────────────────────────────────
|
||||
학습자가 P1 내담자와 N번째 회기 시작
|
||||
│
|
||||
├─1. case_profile + pinned_fact 로드 (큰 그림, ~400+300토큰) [P3]
|
||||
│ load_pinned_facts(case_id, status IN stable/evolving/locked)
|
||||
│
|
||||
├─2. 직전 session_summary 로드 (중간, ~500토큰)
|
||||
│ {digest, open_threads, homework, end_state}
|
||||
│
|
||||
├─3. episodic recall (세부, top-5, ~600토큰)
|
||||
│ query = open_threads + homework (+학습자 첫 발화)
|
||||
│ → hybrid_search(case_id 스코프, dense+sparse RRF, top-50)
|
||||
│ → BGE-reranker-v2-m3 → top-5
|
||||
│
|
||||
├─4. 상태 복원 (carry-over, 결정론) [P2]
|
||||
│ init_session_state_from_history():
|
||||
│ stage = '라포' (매 회기 라포부터 재시작 — 상담 구조)
|
||||
│ rapport_credit = prev.rapport_credit × 0.7 (주1회 간격 일부 이월)
|
||||
│ resistance = inter_session_drift(prev, alliance)
|
||||
│ ideation_stage = prev (보수적 유지 — 안전 R5)
|
||||
│
|
||||
├─5. KB 정적 청크 로드 (페르소나 증상 단서, 정책 필터)
|
||||
│ visible_to='client' AND sensitivity<=1, 본문 비노출(행동단서만)
|
||||
│
|
||||
└─6. 상주 claude -p 프로세스 점유 + system 주입 (불변, cache_control)
|
||||
L0 가드레일 + L1 페르소나카드(불변) + L2-EP 회상 + L2-KB 지식
|
||||
→ session_state.recall_context에 캐시 (회기 내 재검색 0)
|
||||
|
||||
【B. 회기 진행 — 턴 사이클】 (마스터플랜 §2.2, 매 발화)
|
||||
────────────────────────────────────────────────────────────────────────────
|
||||
학습자 발화 U_t
|
||||
│
|
||||
├─ [입력 가드레일] Presidio PII 마스킹 + 위기분류(실제위기 vs 연기 분기)
|
||||
├─ [라우터] route_memory_vs_knowledge(turn, ai_role) [람다 "필요할때만 Read"]
|
||||
│ needs_episodic = 지시어("아까/저번에") OR role=client OR 단계전이
|
||||
│ needs_knowledge = role=evaluator OR 임상용어 OR role=counselor
|
||||
├─ [상태머신] effective_openness(t) 계산 (결정론, LLM 아님) [P2]
|
||||
│ = clamp(stage.openness + rapport_credit×unlock_rate - resistance×decay)
|
||||
├─ [모순 검사] handle_potential_contradiction(new_turn, pinned)
|
||||
│ locked 사실모순 → 차단·재생성 / clinical 변화 → 수용·갱신+이력
|
||||
├─ [내담자 AI] stdin JSON 주입 → 페르소나 응답 (CCD 직접노출 금지)
|
||||
│ L3 상태수치 + L4 fact hard-pin + L5 episodic recall + L6 최근N턴
|
||||
├─ [출력 가드레일] 자살수단 차단, ideation≤3, drift 감지(임베딩 일관성≥0.79)
|
||||
├─ [평가 AI 2-tier]
|
||||
│ fast-loop(로컬/Haiku): U_t만 4차원 태깅 (실시간)
|
||||
│ deep-loop(Opus 상주): 단계전환·회기말 0-5 채점 + 대안발화
|
||||
├─ [working 갱신] session_state UPSERT (체크포인트, 단기버퍼 append)
|
||||
└─ [로깅] turns → Postgres + 임베딩 (재귀학습 JSONL 원천)
|
||||
↑ K턴 반복 (recall_context는 회기 내 재사용, 재검색 안 함)
|
||||
|
||||
【C. 회기 종료 — 압축】 (람다 daily→weekly 컴프레션, 비동기 비블로킹)
|
||||
────────────────────────────────────────────────────────────────────────────
|
||||
stage='정리' 완료 OR 명시 종료
|
||||
│
|
||||
├─(A) 무손실 carry-over: end_state = working 종료 snapshot (코드 복사, LLM 미경유) [P4]
|
||||
├─(B) salience 산출 → 망각/유지 결정
|
||||
│ compute_salience(t): pinned/위기/최초개방/정서급변 ↑, 잡담 ↓
|
||||
│ salience ≥ 0.5 → episodic 영구유지(검색 우선), 미만 → digest 흡수
|
||||
├─(C) narrative 압축(LLM, 상주 claude -p 재사용): digest 6~10문장 + open_threads
|
||||
│ pinned 사실은 프롬프트 hard-pin → digest 보존 강제
|
||||
│ 입력 = turns.text_masked만 (F-03 마스킹 강제)
|
||||
├─(D) digest 임베딩 + session_summary UPSERT + episodic 임베딩 백필
|
||||
├─(E) case_profile 병합: rapport_trajectory append, CCD 추정 갱신,
|
||||
│ case_digest 재압축(N회기마다 or major shift), alliance EWMA
|
||||
├─(F) pinned_fact 모순/갱신 처리 + pinned_fact_history 이력화
|
||||
└─(G) RAG 동기화 (람다 storeDocument→embed): 다음 회기 회상 대비
|
||||
│
|
||||
├─ 상주 프로세스 회수 (누적 컨텍스트 리셋 → 말투표류 D-c 회기경계서 차단)
|
||||
└─ 종단 평가: learner_profile EWMA(현재수준)+slope(성장속도) 갱신
|
||||
|
||||
【D. 다음 회기】 → 【A】로 복귀 (case_profile·summary·pinned 누적된 상태로)
|
||||
토큰 ~4K 고정 (100회기여도 선형증가 X)
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 통합 Postgres 스키마 (메모리·지식·페르소나·평가, DDL 수준)
|
||||
|
||||
> 스키마 4분할: `app`(운영·메모리·페르소나) / `kb`(정적 지식, 독립) / `audit`(append-only 감사) / `ds`(재귀학습). **Phase 0에 전부 선반영(nullable), cross-session·KB 채우기는 Phase 2a**(MASTERPLAN_REVISIONS §3.5 재마이그레이션 폭탄 방지 원칙).
|
||||
|
||||
### 3.1 페르소나 — 불변 카드 (app.persona_card)
|
||||
|
||||
```sql
|
||||
-- ════ 불변 정체성 (람다 IDENTITY/SOUL, 버전드, 교수만 편집) ════
|
||||
CREATE TABLE app.persona_card (
|
||||
persona_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
code TEXT NOT NULL, -- 'P1','P2','P3'
|
||||
version INT NOT NULL DEFAULT 1, -- 편집 시 +1 (진행 세션은 옛 version 핀)
|
||||
status TEXT NOT NULL DEFAULT 'draft'
|
||||
CHECK (status IN ('draft','review','approved','archived')),
|
||||
display_name TEXT NOT NULL,
|
||||
difficulty TEXT NOT NULL CHECK (difficulty IN ('easy','moderate','hard')),
|
||||
theory_target TEXT[], -- {'humanistic','cbt'}
|
||||
demographics JSONB NOT NULL, -- 범주화(재식별 방지 F-25): age_band,sex,grade...
|
||||
presenting JSONB NOT NULL, -- 표층 호소(내담자가 입으로 말함)
|
||||
history JSONB NOT NULL, -- 과거사
|
||||
big5 JSONB NOT NULL, -- {O,C,E,A,N} 0~1 (말투·반응 수학적 앵커)
|
||||
resistance JSONB NOT NULL, -- {base_resistance,unlock_rate,decay_floor,silence_prob,deflection_prob}
|
||||
speech_style JSONB NOT NULL, -- {register,avg_sentence_len,fillers,honorific,verbal_tics}
|
||||
affect_baseline JSONB NOT NULL, -- {negative_affect,hopelessness,anhedonia,sleep,anxiety,suicide_ideation_stage} hard상한=3
|
||||
ccd JSONB NOT NULL, -- Patient-Ψ 8요소 (★직접발화 금지 R4, 행동으로만)
|
||||
dsm5_dimensional JSONB NOT NULL, -- criteria_behavior_matrix (진단명 비노출, 내부 엄밀성 F-22)
|
||||
source_provenance TEXT NOT NULL, -- '0615 합성변형' (원문 미적재 F-05)
|
||||
is_synthetic BOOL NOT NULL DEFAULT TRUE,
|
||||
created_by UUID, approved_by UUID, approved_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE (code, version)
|
||||
);
|
||||
CREATE INDEX idx_persona_card_status ON app.persona_card(status) WHERE status='approved';
|
||||
|
||||
-- 음성 매핑 (provider-agnostic, 카드 버전 정합)
|
||||
CREATE TABLE app.persona_voice_map (
|
||||
persona_id UUID NOT NULL REFERENCES app.persona_card(persona_id) ON DELETE CASCADE,
|
||||
version INT NOT NULL,
|
||||
voice_id TEXT NOT NULL, -- 'voice_p1_teen_m'
|
||||
provider TEXT NOT NULL CHECK (provider IN ('openai','higgs','melotts')),
|
||||
base_params JSONB NOT NULL,
|
||||
prosody_map JSONB NOT NULL, -- 상태(stage/affect/resistance)→prosody 함수
|
||||
PRIMARY KEY (persona_id, version)
|
||||
);
|
||||
|
||||
-- 상담사 AI 페르소나 (데모/self-play용, 이론 충실도 일관)
|
||||
CREATE TABLE app.counselor_profile (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), code TEXT,
|
||||
theory TEXT CHECK (theory IN ('humanistic','cbt','integrative')),
|
||||
skill_level TEXT, reasoning_chain JSONB, -- CoE: PCT/CBT 추론체인
|
||||
allowed_microskills TEXT[], speech_style JSONB
|
||||
);
|
||||
```
|
||||
|
||||
### 3.2 메모리 ① WORKING (app.session_state, 체크포인트)
|
||||
|
||||
```sql
|
||||
CREATE TABLE app.session_state (
|
||||
session_id UUID PRIMARY KEY REFERENCES app.sessions(id) ON DELETE CASCADE,
|
||||
stage TEXT NOT NULL DEFAULT '라포' CHECK (stage IN ('라포','탐색','개입','정리')),
|
||||
turn_seq INT NOT NULL DEFAULT 0,
|
||||
effective_openness REAL NOT NULL DEFAULT 0.15 CHECK (effective_openness BETWEEN 0 AND 1),
|
||||
rapport_credit REAL NOT NULL DEFAULT 0.0, -- 회기말 carry 대상 (0.7 이월)
|
||||
resistance REAL NOT NULL DEFAULT 0.65 CHECK (resistance BETWEEN 0 AND 1),
|
||||
ideation_stage SMALLINT NOT NULL DEFAULT 1 CHECK (ideation_stage BETWEEN 1 AND 5),
|
||||
affect_state JSONB NOT NULL DEFAULT '{}',
|
||||
short_buffer JSONB NOT NULL DEFAULT '[]', -- 최근 K턴 rolling window
|
||||
recall_context JSONB, -- 회기시작 1회 로드, 회기내 재사용 캐시
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
```
|
||||
|
||||
### 3.3 메모리 ② EPISODIC (app.turns 확장 + app.turn_embedding)
|
||||
|
||||
```sql
|
||||
-- 마스터플랜 §3.2 turns에 연속성 컬럼 추가
|
||||
ALTER TABLE app.turns
|
||||
ADD COLUMN IF NOT EXISTS salience REAL DEFAULT 0.0, -- 망각/우선순위
|
||||
ADD COLUMN IF NOT EXISTS is_pinned BOOL DEFAULT FALSE, -- pinned_fact 승격 발화
|
||||
ADD COLUMN IF NOT EXISTS contradicts UUID[] DEFAULT '{}', -- 모순추적: 뒤집은 과거 turn_id[]
|
||||
-- 음성 paralinguistic (MASTERPLAN_REVISIONS §3.5 선반영)
|
||||
ADD COLUMN IF NOT EXISTS audio_ref TEXT,
|
||||
ADD COLUMN IF NOT EXISTS silence_ms INT,
|
||||
ADD COLUMN IF NOT EXISTS speech_rate REAL,
|
||||
ADD COLUMN IF NOT EXISTS barge_in BOOL;
|
||||
|
||||
CREATE TABLE app.turn_embedding (
|
||||
turn_id UUID PRIMARY KEY REFERENCES app.turns(id) ON DELETE CASCADE,
|
||||
case_id UUID NOT NULL, -- denormalized: 케이스 스코프 회상
|
||||
session_id UUID NOT NULL, seq INT NOT NULL,
|
||||
dense vector(1024) NOT NULL, -- BGE-M3 dense
|
||||
sparse JSONB, -- BGE-M3 sparse {token_id:weight}
|
||||
context_prefix TEXT, -- Contextual Retrieval 1문장
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX idx_turn_emb_hnsw ON app.turn_embedding
|
||||
USING hnsw (dense vector_cosine_ops) WITH (m=16, ef_construction=64);
|
||||
CREATE INDEX idx_turn_emb_case ON app.turn_embedding (case_id, session_id);
|
||||
```
|
||||
|
||||
### 3.4 메모리 ③ SUMMARY (app.session_summary)
|
||||
|
||||
```sql
|
||||
CREATE TABLE app.session_summary (
|
||||
session_id UUID PRIMARY KEY REFERENCES app.sessions(id) ON DELETE CASCADE,
|
||||
case_id UUID NOT NULL, session_no INT NOT NULL,
|
||||
-- (A) 무손실 carry-over (상태 수치 snapshot, LLM 미경유) [P2]
|
||||
end_state JSONB NOT NULL, -- {stage,openness,rapport_credit,resistance,ideation_stage,affect}
|
||||
rapport_delta REAL,
|
||||
-- (B) narrative 압축 (LLM, 손실 허용)
|
||||
digest TEXT NOT NULL, -- 6~10문장, 다음 회기 system 주입
|
||||
open_threads JSONB NOT NULL DEFAULT '[]', -- 미해결 [{topic,last_stance,raised_session_no}]
|
||||
homework JSONB, emotional_arc TEXT,
|
||||
-- (C) 검색용
|
||||
digest_embedding vector(1024),
|
||||
token_count INT, compressed_by TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE (case_id, session_no)
|
||||
);
|
||||
CREATE INDEX idx_sess_sum_case ON app.session_summary (case_id, session_no DESC);
|
||||
CREATE INDEX idx_sess_sum_emb ON app.session_summary
|
||||
USING hnsw (digest_embedding vector_cosine_ops) WITH (m=16, ef_construction=64);
|
||||
```
|
||||
|
||||
### 3.5 메모리 ④ SEMANTIC (app.case_profile + app.pinned_fact)
|
||||
|
||||
```sql
|
||||
-- 케이스 = 한 가상내담자의 다회기 전체 (persona_id=템플릿, case=학습자별 인스턴스)
|
||||
CREATE TABLE app.case_profile (
|
||||
case_id UUID PRIMARY KEY,
|
||||
persona_id TEXT NOT NULL, -- 시드 페르소나
|
||||
learner_id UUID NOT NULL, -- ★ 학습자별 독립 연속체
|
||||
last_session_no INT NOT NULL DEFAULT 0,
|
||||
ccd_estimate JSONB NOT NULL DEFAULT '{}', -- CCD 8요소 현재추정 +confidence
|
||||
presenting_arc JSONB NOT NULL DEFAULT '[]', -- 호소문제 궤적
|
||||
rapport_trajectory JSONB NOT NULL DEFAULT '[]', -- [{session_no,end_rapport,end_openness}]
|
||||
alliance_level REAL DEFAULT 0.2, -- 치료동맹 누적
|
||||
case_digest TEXT NOT NULL DEFAULT '', -- 전체 궤적 8~12문장 (큰그림, 람다 monthly)
|
||||
digest_embedding vector(1024),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- pinned facts (람다 MEMORY.md, 절대 흘리면 안 되는 핵심, 모순 기준점)
|
||||
CREATE TABLE app.pinned_fact (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
case_id UUID NOT NULL REFERENCES app.case_profile(case_id) ON DELETE CASCADE,
|
||||
key TEXT NOT NULL, -- 'name','family','suicide_attempt_history'
|
||||
value TEXT NOT NULL, -- 가명처리/마스킹된
|
||||
fact_type TEXT NOT NULL CHECK (fact_type IN ('identity','history','relationship','clinical','agreement')),
|
||||
status TEXT NOT NULL DEFAULT 'stable' CHECK (status IN ('stable','evolving','contradicted','locked')),
|
||||
source_turn UUID, confidence REAL NOT NULL DEFAULT 1.0,
|
||||
version INT NOT NULL DEFAULT 1, updated_session_no INT,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE (case_id, key)
|
||||
);
|
||||
CREATE INDEX idx_pinned_case ON app.pinned_fact (case_id, status);
|
||||
|
||||
-- pinned 변경 이력 (append-only, 모순/갱신 audit + 평가AI 정답신호)
|
||||
CREATE TABLE app.pinned_fact_history (
|
||||
id BIGSERIAL PRIMARY KEY, fact_id UUID NOT NULL, case_id UUID NOT NULL,
|
||||
old_value TEXT, new_value TEXT,
|
||||
reason TEXT, -- 'contradiction','clarification','progression'
|
||||
session_no INT, turn_id UUID, created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
```
|
||||
|
||||
### 3.6 지식 ⑤ KB (kb 스키마, 독립)
|
||||
|
||||
```sql
|
||||
CREATE SCHEMA kb;
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
||||
|
||||
-- 출처 + 라이선스 (DSM-5 저작권 1차 통제)
|
||||
CREATE TABLE kb.source (
|
||||
source_id TEXT PRIMARY KEY, -- 'dsm5','theory','taxonomy_0615'
|
||||
title TEXT NOT NULL,
|
||||
kb_kind TEXT NOT NULL CHECK (kb_kind IN
|
||||
('diagnostic','theory','technique','taxonomy','supervisor_pattern','template','ko_context')),
|
||||
license_class CHAR(1) NOT NULL CHECK (license_class IN ('A','B','C','D')), -- C=저작권민감 D=미성년파생
|
||||
origin_path TEXT, citation TEXT,
|
||||
external_llm_ok BOOLEAN NOT NULL DEFAULT false, -- C/D면 false → 국내 라우팅
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
-- 문서 + 버전 (graphify content_hash 증분 인덱싱 차용)
|
||||
CREATE TABLE kb.document (
|
||||
doc_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
source_id TEXT NOT NULL REFERENCES kb.source(source_id),
|
||||
doc_uri TEXT NOT NULL, version INT NOT NULL DEFAULT 1,
|
||||
content_hash TEXT NOT NULL, -- SHA256 → 변경감지(증분)
|
||||
superseded_by BIGINT REFERENCES kb.document(doc_id),
|
||||
is_active BOOLEAN NOT NULL DEFAULT true, indexed_at TIMESTAMPTZ,
|
||||
UNIQUE (source_id, doc_uri, version)
|
||||
);
|
||||
|
||||
-- 청크 + 멀티벡터 (검색 본체)
|
||||
CREATE TABLE kb.chunk (
|
||||
chunk_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
doc_id BIGINT NOT NULL REFERENCES kb.document(doc_id) ON DELETE CASCADE,
|
||||
source_id TEXT NOT NULL, kb_kind TEXT NOT NULL, -- 비정규화(필터 가속)
|
||||
seq INT NOT NULL, heading_path TEXT,
|
||||
chunk_text TEXT NOT NULL, -- 표시·LLM 주입(prefix 미포함)
|
||||
context_prefix TEXT, -- Contextual Retrieval 주입문
|
||||
embedding vector(1024), -- BGE-M3 dense
|
||||
sparse_vec JSONB, colbert_vecs JSONB, -- 멀티벡터(단일 호출 산출)
|
||||
visible_to TEXT[] NOT NULL DEFAULT '{client,counselor,evaluator}', -- 정보비대칭
|
||||
sensitivity SMALLINT NOT NULL DEFAULT 0, -- 0공개 1비공개내부 2평가전용 3원천격리
|
||||
label_id BIGINT, -- taxonomy면 technique_label_def FK
|
||||
meta JSONB DEFAULT '{}', -- {dsm_category,theory,bias_weight...}
|
||||
token_count INT, created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
CREATE INDEX idx_chunk_hnsw ON kb.chunk USING hnsw (embedding vector_cosine_ops) WITH (m=16, ef_construction=64);
|
||||
CREATE INDEX idx_chunk_fts ON kb.chunk USING gin (to_tsvector('simple', chunk_text));
|
||||
CREATE INDEX idx_chunk_trgm ON kb.chunk USING gin (chunk_text gin_trgm_ops);
|
||||
CREATE INDEX idx_chunk_visible ON kb.chunk USING gin (visible_to);
|
||||
CREATE INDEX idx_chunk_route ON kb.chunk (kb_kind, sensitivity);
|
||||
```
|
||||
|
||||
### 3.7 평가 + 종단 추적 + 드리프트 감사 (app + audit)
|
||||
|
||||
```sql
|
||||
-- 발화별 평가 (마스터플랜 §3.2, visible_to로 학습자 비노출)
|
||||
CREATE TABLE app.feedback_scores (
|
||||
turn_id UUID NOT NULL, dimension TEXT NOT NULL, -- 공감/개방질문/검증/이론부합
|
||||
score REAL, -- 0-5 (CTRS 0-6)
|
||||
rationale TEXT, top1_score REAL, -- CRAG 게이트(임계미달→관찰프레이밍 F-06)
|
||||
visible_to TEXT[] NOT NULL DEFAULT '{evaluator}',
|
||||
PRIMARY KEY (turn_id, dimension)
|
||||
);
|
||||
|
||||
-- 종단 학습자 프로파일 (회기 거듭하며 나아지는지 — 윤찬 직접 답)
|
||||
CREATE TABLE app.learner_profile (
|
||||
learner_id UUID PRIMARY KEY,
|
||||
-- 4차원 EWMA(현재수준) + slope(성장속도) 동시
|
||||
dim_ewma JSONB NOT NULL DEFAULT '{}', -- {empathy:0.6, open_q:0.5, validation:..., theory:...}
|
||||
dim_slope JSONB NOT NULL DEFAULT '{}', -- 성장속도 (잘하는데정체 vs 못하지만급성장 구분)
|
||||
persistent_gaps JSONB DEFAULT '[]', -- deep-loop만 맥락화 코칭 (fast-loop 절대 미주입)
|
||||
session_count INT DEFAULT 0, updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
-- 페르소나 드리프트 감사 (KPI 임베딩일관성≥0.79 측정)
|
||||
CREATE TABLE audit.persona_drift_log (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
session_id UUID NOT NULL, turn_id UUID, persona_id UUID NOT NULL,
|
||||
drift_type TEXT NOT NULL, -- 'big5_violation'|'ccd_leak'|'fact_contradiction'|'style_drift'
|
||||
embedding_sim REAL, detail JSONB,
|
||||
severity TEXT CHECK (severity IN ('warn','block')),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- KB 검색 로그 (환각측정·캐시검증, 람다 cost.json 차용)
|
||||
CREATE TABLE kb.retrieval_log (
|
||||
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
session_id UUID, turn_id UUID, ai_role TEXT NOT NULL,
|
||||
query_text TEXT, policy TEXT NOT NULL, hit_chunk_ids BIGINT[],
|
||||
rerank_scores REAL[], top1_score REAL, used_in_answer BOOLEAN,
|
||||
latency_ms INT, created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
```
|
||||
|
||||
> **핵심 설계 결정 — `(persona_id, learner_id)` 복합키**: 한 페르소나(P1)를 20명이 각자 연습한다. 같은 카드(불변) + 다른 연속체(가변). `case_profile.learner_id`가 "이 학습자에게 이 내담자가 겪은 회기 히스토리"를 정의 → 학습자 간 기억 오염 차단.
|
||||
|
||||
---
|
||||
|
||||
## 4. 3-AI 정보비대칭이 메모리·KB 레이어에서 강제되는 방식
|
||||
|
||||
### 4.1 핵심 원리 — 위험한 건 turn 표면이 아니라 파생 메모리
|
||||
|
||||
turn 자체는 대화 표면이라 덜 위험하다. **위험한 건 CCD·정답라벨·점수·종단요약 같은 파생 메모리.** 여기에만 `visible_to[]`를 달고, **컨텍스트 조립기가 역할별로 물리적으로 다른 쿼리 분기**를 탄다.
|
||||
|
||||
```
|
||||
2-레이어 강제 (MASTERPLAN_REVISIONS §5.1 F-30):
|
||||
┌─ 레이어1: AI 정보비대칭 (current_ai_view enum) ── visible_to[] WHERE 강제
|
||||
│ CLIENT_AI 분기엔 load_ccd()·load_evaluator_answer() 함수 자체가 없음
|
||||
│ → "필터 누락"이 아니라 "코드 경로 부재"가 1차 방어
|
||||
└─ 레이어2: 인간 RBAC×cohort (current_role) ── RLS DB레벨 방어선
|
||||
인간이 turn 읽을 때 두 게이트 AND (단일 미들웨어 + RLS 이중강제)
|
||||
```
|
||||
|
||||
### 4.2 메모리 레이어 — 3-AI 뷰 격리 매트릭스
|
||||
|
||||
| 메모리/KB 항목 | ② 내담자 AI | ① 상담사 AI(보조) | ③ 평가 AI |
|
||||
|---|---|---|---|
|
||||
| ① working(상태수치) | 자기 stage·openness만 (수치 주입, 메타노출 X) | 표면 대화만 | 전체 (저항엔진 검증) |
|
||||
| ② episodic(자기 발화) | 자기 케이스 recall만 (case 스코프 강제) | 회상 없음(표면만) | 전체 (정답 대조) |
|
||||
| ③ session_summary | digest·pinned는 "자기기억"으로만 표현 | 미노출 | 전체 + open_threads |
|
||||
| ④ case_profile.ccd_estimate | **절대 비노출** (R4 메타노출 금지) | **절대 비노출** | 전체 (정답 CCD) |
|
||||
| ④ pinned_fact(clinical) | 자기 사실로만 | 미노출 | 전체 (변화 정답신호) |
|
||||
| ⑤ KB diagnostic(DSM) | 내부 파라미터 (본문 비노출, 행동단서만) | **차단** | 전체 |
|
||||
| ⑤ KB taxonomy 정답라벨 | 차단 (sensitivity≥2) | 차단 | 전체 (채점 기준) |
|
||||
| learner_profile | 차단 | 차단 | deep-loop만 (fast 미주입, 사전편향 차단) |
|
||||
|
||||
### 4.3 KB 레이어 — 같은 물리 테이블, 다른 retrieval 정책 4-튜플
|
||||
|
||||
검색 정책 = **사전필터(WHERE) + 회수 가중치 + 리랭킹 목표 + 주입 방식**.
|
||||
|
||||
| 차원 | ② 내담자 AI | ① 상담사 AI | ③ 평가 AI |
|
||||
|---|---|---|---|
|
||||
| 사전필터 | `kb_kind IN (diagnostic,theory,technique)` `AND 'client'=ANY(visible_to)` `AND sensitivity<=1` | `kb_kind IN (theory,technique,microskill,ko_context)` `AND 'counselor'=ANY(visible_to)` `AND sensitivity=0` | `'evaluator'=ANY(visible_to)` `AND sensitivity<=2` (taxonomy·supervisor 정답 포함) |
|
||||
| 회수 가중치 | dense 0.7 / sparse 0.3 (증상 의미) | dense 0.5 / sparse 0.5 (기법명) | sparse 0.6 / dense 0.4 (라벨명·논평) |
|
||||
| 주입 방식 | 본문 비노출, "행동단서 요약"만 | 본문+예시 | 본문+label_id+bias_weight |
|
||||
| 절대 차단 | sensitivity≥2, 타 페르소나 CCD | DSM diagnostic, 평가정답 | (전부 봄, 학습자 비노출은 응답 가공단) |
|
||||
|
||||
```sql
|
||||
-- 하이브리드 검색 SQL 계약 (정책별 파라미터화, visible_to DB 강제)
|
||||
WITH dense AS (
|
||||
SELECT chunk_id, 1-(embedding <=> :q_dense) AS s_dense FROM kb.chunk
|
||||
WHERE kb_kind=ANY(:kinds) AND :role=ANY(visible_to) AND sensitivity<=:sens_max
|
||||
ORDER BY embedding <=> :q_dense LIMIT 50),
|
||||
sparse AS (
|
||||
SELECT chunk_id, ts_rank_cd(to_tsvector('simple',chunk_text),:q_terms) AS s_sparse FROM kb.chunk
|
||||
WHERE kb_kind=ANY(:kinds) AND :role=ANY(visible_to) AND sensitivity<=:sens_max
|
||||
AND to_tsvector('simple',chunk_text) @@ :q_terms LIMIT 50)
|
||||
SELECT c.chunk_id, c.chunk_text, c.context_prefix, c.label_id,
|
||||
COALESCE(d.s_dense,0)*:w_dense + COALESCE(s.s_sparse,0)*:w_sparse AS fused
|
||||
FROM kb.chunk c LEFT JOIN dense d USING(chunk_id) LEFT JOIN sparse s USING(chunk_id)
|
||||
WHERE d.chunk_id IS NOT NULL OR s.chunk_id IS NOT NULL
|
||||
ORDER BY fused DESC LIMIT :k; -- → BGE-reranker-v2-m3 top-5
|
||||
```
|
||||
|
||||
### 4.4 누수 방지 자동 테스트 (F-17, 람다 직접검증)
|
||||
|
||||
- **T1 RLS 부정테스트**: 타 AI뷰 SET → 0행 반환 확인
|
||||
- **T2 조립기 화이트리스트**: CLIENT_AI 분기에 ccd/정답 로드 함수 부재 정적검증
|
||||
- **T3 CCD-메타 누설**: "제 핵심신념은…" 정규식 게이트 + 분류기
|
||||
- **T4 cross-trainee 누수**: 학습자A의 case가 B에 새지 않는지 (case_id 스코프)
|
||||
- **람다 직접**: IDOR 403 스크린샷, ai_view 위조 요청 차단 검증
|
||||
|
||||
---
|
||||
|
||||
## 5. 기존 마스터플랜 §3.6과의 정합/대체점
|
||||
|
||||
| 마스터플랜 §3.6 항목 | 본 설계 | 정합 / 대체 |
|
||||
|---|---|---|
|
||||
| 페르소나 메모리=하이브리드(상태수치+rolling summary+episodic 벡터) | 4계층(working/episodic/summary/semantic)으로 **구체화** | **정합·확장** (§3.6 추상을 테이블·압축 알고리즘으로 실체화) |
|
||||
| 피드백 근거=하이브리드+리랭킹(+CRAG) | KB ③평가 경로 = 하이브리드+Contextual+reranker, top1_score 게이트 | **정합** (CRAG를 ③경로에만 우선 도입) |
|
||||
| 지식=정적 KB+Contextual Retrieval | kb 스키마 + 3계층(청크/prefix/community) + license_class | **정합·확장** (DSM 저작권 통제 추가) |
|
||||
| 임베딩=BGE-M3 단일모델 멀티벡터 | episodic·summary·KB 전부 BGE-M3 | **정합** (동일 모델 재사용) |
|
||||
| pgvector(HNSW) | 모든 벡터 테이블 HNSW | **정합** |
|
||||
| 하이브리드 dense+sparse top-50 | episodic·KB 동일 RRF | **정합** |
|
||||
| GraphRAG=2차(이론 교차개념) | 본 설계도 graphify 2차 (theory KB 커질 때만) | **정합** |
|
||||
| (§3.6 미언급) 회기 간 연속성 | **본 설계가 신규 추가** (summary/case_profile/recall/모순처리) | **대체점=신규 보강** (§3.6은 단일회기 메모리만, 본 설계가 cross-session 채움) |
|
||||
| (§3.6 미언급) rag_chunks vs episodic 분리 | 에피소드(app)↔정적KB(kb) **물리 스키마 분리** | **대체점=명확화** (§3.6 rag_chunks를 KB 전용으로 좁히고 메모리는 별도) |
|
||||
|
||||
> **핵심 대체점**: 마스터플랜 §3.6은 "페르소나 메모리=하이브리드 메모리"라고만 했지 **회기 간 연속성(cross-session)을 다루지 않았다.** 본 설계가 summary→case_profile 계층 압축 + 회기 시작 회상 + 모순 처리를 신규로 채운다. §3.6의 RAG 스택 자체는 하나도 바꾸지 않는다(BGE-M3/pgvector/하이브리드/Contextual/reranker 그대로).
|
||||
|
||||
---
|
||||
|
||||
## 6. 20주·n=1 제약 하 MVP 메모리 범위
|
||||
|
||||
### 6.1 Phase 매핑 (단일 로드맵 정합, 산발 task 금지)
|
||||
|
||||
| 항목 | Phase | 소유(REVISIONS §6.1) | DoD 검증(람다 직접) |
|
||||
|---|---|---|---|
|
||||
| **스키마 전체 선반영** (§3 전부, nullable) | **Phase 0** | 람다 직접(인프라) | 마이그레이션 통과 + nullable 확인 |
|
||||
| 페르소나 카드 4테이블 + 음성맵 | Phase 0 | 람다 직접 | DDL 적용 |
|
||||
| ① working + 체크포인트 | Phase 1 | A2(상태머신) | 프로세스 kill 후 상태 복원 재현 |
|
||||
| ② episodic + 임베딩 | Phase 1 | A1(엔진)+데이터 | 발화 저장 시 임베딩 적재 DB쿼리 |
|
||||
| ⑤ KB (하이브리드+Contextual+reranker) | Phase 1 | A1+데이터 | ②/③ 다른 청크 회수 SQL 대조 |
|
||||
| ③ 회기종료 압축 | **Phase 2a** | A2+데이터 | 회기 완주→summary 생성, 토큰예산 실측 |
|
||||
| ④ case_profile+pinned+모순처리 | **Phase 2a** | A2+데이터 | 2회기→carry-over+모순처리 재현 |
|
||||
| 회기시작 회상 | **Phase 2a** | A1+B(UI카드) | N회기째 "지난번~" 정확 회상 + 정답대조 |
|
||||
| 종단 learner_profile EWMA+slope | Phase 2a~3 | D(데이터) | 다회기 성장곡선 대시보드 |
|
||||
|
||||
### 6.2 MVP 메모리 범위 결정 (정직한 단계화)
|
||||
|
||||
- **Phase 1 = 단일 회기 메모리만**: working(상태머신 carry-over 체크포인트) + episodic(발화 임베딩) + KB(정적 지식). **cross-session 없음.** 0615를 1회기 episodic 시드로.
|
||||
- **Phase 2a = cross-session 추가**: summary 압축 + case_profile 누적 + 회기 시작 회상 + 모순 처리. 다회기 진화는 데이터가 아니라 **결정론 상태머신 + 합성 시나리오**로 보장.
|
||||
- **스키마는 Phase 0에 전부 선반영** (재마이그레이션 폭탄 방지).
|
||||
|
||||
### 6.3 n=1 정직 표기 (절대 "검증됨" 보류)
|
||||
|
||||
- **0615은 사실상 단일 회기 사례** → 다회기 연속성 학습 코퍼스 없음. 압축 품질(정보보존율)·회상 정확도는 **0615로 검증 불가.**
|
||||
- Phase 1엔 **룰 기반으로 시작**(salience 룰, inter_session_drift 룰, EWMA α=0.4·FAST_WINDOW=6 전부 가정값).
|
||||
- 정량검증은 **Phase 3 파일럿(20명×다회기)에서 first measure** — "압축 전후 사실 보존율 / 다음회기 회상 정확도 / 성장곡선 타당도". 그 전엔 "검증됨" 표기 금지(`feedback_measure_before_report`).
|
||||
- **추가 축어록 수급이 전제** — n=1 해소는 한신대 공문(블로킹 의존성, F-04)에 달림.
|
||||
|
||||
---
|
||||
|
||||
## 7. 핵심 리스크 (통합)
|
||||
|
||||
| # | 리스크 | 영향 | 완화 |
|
||||
|---|---|---|---|
|
||||
| **M1** | 압축 정보손실로 페르소나 일관성 균열 | 페르소나 붕괴 | pinned 무손실+episodic 검색 백업, digest는 서사용. Phase3 보존율 측정 |
|
||||
| **M2** | 상태수치 LLM hallucination | 저항엔진 오작동 | end_state는 코드 복사(P4), LLM 미경유 |
|
||||
| **M3** | n=1로 압축/회상/성장곡선 품질 검증 불가 | 정량근거 부재 | 정직표기, 룰 시작, Phase3 first measure. α·window·TTFT 전부 "실측 필요" |
|
||||
| **M4** | 모순처리 오판 (정당변화↔버그 혼동) | 잘못 차단/오염 | fact_type별 분기(locked만 차단), 전건 이력화 사후교정 |
|
||||
| **M5** | 회상 검색 오류 (엉뚱한 과거발화) | "지난번~" 환각 | reranker top-5, open_threads 우선쿼리, case 스코프 강제 |
|
||||
| **M6** | CCD 메타노출 (회상·KB가 정답 누설) | 추론훈련 무력화 | visible_to 분리, 내담자="자기기억"만, KB 본문 비노출(단서만), 출력 가드레일 |
|
||||
| **M7** | 회기 경계 상태 리셋 버그 | 진화 손실 | carry-over 명시(0.7 이월), rapport_trajectory DB 회귀테스트 |
|
||||
| **M8** | 페르소나 drift (가변이 불변 덮음) | 페르소나 깨짐 | 불변 카드 압축 대상 제외, COMPRESS_SYSTEM hard rule+금칙어 정규식 이중방어 |
|
||||
| **M9** | DSM-5 verbatim 저작권 (license C) | 법적 책임 | 원문 미적재 환언본만, verbatim 검출기 게이트, 국내 라우팅 |
|
||||
| **M10** | 한국어 sparse/BM25 토크나이징 (PG simple 형태소 미분리) | 검색 품질 | pg_trgm+BGE sparse 병용, 부족 시 mecab-ko 2차. 실측 전 "해결됨" 금지 |
|
||||
| **M11** | 정보비대칭 누수 (내담자가 정답청크 봄) | 시뮬레이션 가치 0 | visible_to+sensitivity DB WHERE 강제, 코드경로 부재 1차방어, T1~T4 자동테스트 |
|
||||
| **M12** | 마스킹 게이트 우회 (claude -p stdin 직송) | IRB·법적 | C/D 청크 external_llm_ok=false, Presidio 선통과(F-03), KB는 인덱싱 시점 환언 |
|
||||
| **M13** | 압축/HNSW 재인덱싱 비용 누적 | 예산 | 정액 한계비용 0, content_hash 증분, case_digest 재압축 N회기마다, salience 입력축소 |
|
||||
| **M14** | 임베딩 일관성 0.79 임계가 임의값 | KPI 무근거 | self-play 회귀로 분포 측정 후 확정, 파일럿 전 "검증됨" 금지 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 통합 요약 (한 장)
|
||||
|
||||
- **5계층**: ①working(상태머신 수치+버퍼, 코드 carry-over·체크포인트) ②episodic(turns+BGE-M3, append-only) ③summary(회기종료 LLM 압축 ~600토큰) ④semantic(case_profile evolving+pinned_fact) ⑤knowledge(kb 스키마, 3-AI 다른 정책). 메모리(app)↔지식(kb) **물리 스키마 분리**.
|
||||
- **회기 라이프사이클**: 시작(case_digest→summary→episodic recall, 큰그림→세부, ~4K 고정) → 진행(턴 사이클, 상태머신 결정론, 모순검사) → 종료(수치 코드복사+서사 LLM압축+salience 망각/유지+case 병합) → 다음 회기(누적 상태).
|
||||
- **회기 간 연속성(최우선 갭)**: 상태 수치 carry-over(rapport 0.7 이월, ideation 보수적 유지), pinned hard-pin 무손실, 모순 처리(locked=차단·재생성 / clinical=수용·갱신+이력), 람다 daily→weekly→monthly 압축 직이식.
|
||||
- **페르소나 일관성**: 불변 카드 + 가변 메모리 물리 분리(L1 캐시 vs L3~L6 턴주입), drift=가변이 불변 덮을 때 → 구조적 차단. 음성 prosody=텍스트 말투와 같은 상태머신 입력 동기화.
|
||||
- **정보비대칭**: 파생 메모리(CCD·정답·점수·종단)에만 visible_to, 코드경로 부재 1차방어+RLS 2차, 인간 RBAC×cohort AND. KB는 같은 테이블 다른 4-튜플 정책.
|
||||
- **§3.6 정합**: BGE-M3/pgvector/하이브리드/Contextual/reranker 스택 그대로, 회기 간 연속성만 신규 보강.
|
||||
- **MVP·n=1**: Phase 0 스키마 전체 선반영, Phase 1 단일회기, Phase 2a cross-session. 0615 검증 불가→룰 시작+Phase3 first measure, 추가 축어록 수급(공문 블로킹) 전제. "검증됨" 표기 보류.
|
||||
|
||||
---
|
||||
|
||||
## 부록. 종합 근거 자료 (절대경로)
|
||||
|
||||
- 마스터플랜: `C:/Users/encep/Dropbox/Obsidian/Yun Chan Repository/Projects/영업/2026/한신대학교 산학협력 프로젝트/HANSHIN_AI_PLATFORM_MASTERPLAN.md` (§2 3-AI, §3 데이터모델, §3.6 RAG)
|
||||
- BLUE TEAM 패치: `…/적대검증_2026-06-25/MASTERPLAN_REVISIONS.md` (§1 stream-json 상주풀, §3 마스킹·스키마, §5 visible_to/RBAC 레이어분리, §6 RACI·DoD검증)
|
||||
- 데이터 원천: `…/데이터/README.md` (0615 n=1 시드, 파란색=발화별 기법라벨+슈퍼바이저논평 taxonomy)
|
||||
- 람다 메모리 시스템(1차 레퍼런스): `…/Lambda/BOOT.md`(부트 큰그림→세부), `…/Lambda/procedures/memory-compression.md`(daily→weekly→monthly 압축 알고리즘), `…/CLAUDE.md`(graphify=GraphRAG / rag-memory=BGE-M3 sqlite 역할분리)
|
||||
- KB 자료원: `…/Lambda/references/counseling/`(00~07 DSM·이론·마이크로스킬·위기·한국맥락, 출처인용·가드레일 완비 환언본)
|
||||
- 자매 설계서: `…/설계/연속성메모리_정보비대칭_종단평가_설계서.md`(3-AI 메모리뷰 상세)
|
||||
|
||||
**설계 차별점 4줄**: ① 같은 물리 KB(`kb.chunk`) 하나를 visible_to+sensitivity+정책 매트릭스로 3-AI가 다르게 검색(DB 강제, 코드경로 부재 1차방어). ② 람다 daily→weekly→monthly 계층압축을 메모리 4계층(working/episodic/summary/semantic) + KB 3계층(청크/prefix/community)으로 이식. ③ 람다 rag-memory↔graphify 역할분리를 에피소드 메모리↔정적 KB 물리분리로, 모순 시 "KB는 사전이지 판사가 아니다"(에피소드>KB) 우선순위로 페르소나 일관성 보호. ④ 회기 간 연속성=수치는 결정론 carry-over(무손실)+서사는 LLM 압축(손실허용)+pinned hard-pin, ideation은 보수적 유지(안전).
|
||||
Loading…
Add table
Add a link
Reference in a new issue