# 프롬프트 동적 관리 시스템 계획 **날짜**: 2025-12-25 **최종 보강**: 2026-03-03 **작성자**: happybell80, Claude **상태**: 완료 (2026-03-10 기준) **원칙 참조**: - `book/300_architecture/311_backend_coding_principles.md` (계층 분리, DB state 경유) - `book/300_architecture/312_writing-principles.md` - `book/300_architecture/315_테스트_원칙.md` (TDD) - `book/300_architecture/313_Gemini_프롬프트_설계_원칙.md` **관련 문서**: - [자기개선루프 프롬프트DB 23로컬24 통합실행기록](./260304_자기개선루프_프롬프트DB_23로컬24_통합실행기록.md) - [프롬프트DB 응답생성 폐루프 미연결](../troubleshooting/260310_프롬프트DB_응답생성_폐루프_미연결.md) --- ## 1. 목표 하드코딩 프롬프트를 DB 정책으로 전환해 다음을 달성한다. - 무중단 프롬프트 수정 - 사용자/로빙/작업별 개인화 - A/B 실험 기반 자동 개선 - 안전한 자동 승격 + 즉시 롤백 --- ## 2. 현재 상태 요약 (2026-03-03 기준) - rb8001 코드 하드코딩 프롬프트 템플릿: 약 40개 - 사용자 핵심 UX 경로 프롬프트 유형: 약 8~10종 - chat(감정 반영), summarize, analyze, extract, calendar_confirm 등 - 현재 문제: - 프롬프트 수정 시 코드 배포 필요 - 버전/실험/성과 추적이 일관되지 않음 - 회귀 시 신속 롤백이 어려움 --- ## 3. 범위 ### 포함 - `rb8001` LLM 경로의 시스템/작업별 프롬프트 - 감정 기반 동적 규칙(톤/길이/금지 규칙) - A/B 실험, 메트릭 수집, 자동 승격 정책 ### 제외 - 모델 자체 교체/튜닝 - 감정 분류기 모델 재학습 - 인프라 토폴로지 변경 ## 3-1) 로컬 개발자 실행 경계 (필수) ### 로컬 개발자가 할 수 있는 것 - 프롬프트 DB 스키마/Repository/Service/API 구현 - `/api/message` 경로의 프롬프트 버전 선택/이벤트 자동 기록 코드 구현 - 단위 테스트/로컬 통합 테스트 작성 및 실행 - 실험 게이트/승격 조건 로직 문서화 및 코드 반영 ### 로컬 개발자가 할 수 없는 것 (운영 확인 필요) - 23 게이트웨이 프록시 경로/메서드 운영 반영 확정 - 운영 DB 실적재/지표 집계 기반 자동 승격 최종 판정 - 실사용 트래픽 기준 품질/안전/비용 게이트 충족 판정 - 운영 경유 폐루프 E2E 최종 승인 ### 완료 판정 규칙 - 로컬 완료: 코드/테스트/문서 기준 충족 - 운영 완료: 서버 반영 + 운영 경유 E2E + 지표 검증 완료 - 운영 증거 없이는 "프롬프트 DB화 완료"로 보고하지 않는다 ## 3-2. 자기개선 루프 계획과의 운영 원칙 (설계 병행, 실행 분리) - 설계는 병행: - 프롬프트 DB화와 자기개선 루프 DB를 `run_id` 기준으로 함께 설계한다. - 실행은 분리: - 1차 릴리스는 루프 수집/판정 골격을 우선 적용한다. - 프롬프트 자동 승격/롤백은 기준선 데이터 확보 후 2차로 적용한다. - 운영 모드: - 초기 기본값은 `자동 제안 + 사람 승인`으로 고정한다. - RAG 적용 원칙: - RAG는 필수 선행조건이 아니다. - 1차는 반성/정책 업데이트 보조 용도로만 제한 적용한다. - 프롬프트 승격/롤백의 최종 판정은 기존 정량 지표와 게이트 규칙을 우선한다. - 연결 문서: - [자기개선 루프 DB/서비스 구현 실행계획](./260303_자기개선루프_DB_구현_실행계획.md) --- ## 4. 데이터 모델 (최소 스키마) ### 4.1 `prompt_templates` - purpose: 프롬프트 논리 단위(식별자) - columns: - `id`, `template_key` (unique) - `prompt_type` (`system`, `chat`, `extract`, `calendar_confirm`, ...) - `scope_level` (`global`, `robeing`, `task`, `user`) - `scope_id` (nullable) - `is_enabled` - `created_at`, `updated_at` ### 4.2 `prompt_versions` - purpose: 템플릿 버전 이력 - columns: - `id`, `template_id`, `version` - `content` (TEXT/JSONB) - `variables_schema` (JSONB) - `status` (`draft`, `candidate`, `active`, `retired`) - `created_by`, `change_reason`, `created_at` ### 4.3 `prompt_experiments` - purpose: 실험 라우팅 - columns: - `id`, `experiment_key`, `template_key` - `control_version_id`, `treatment_version_id` - `traffic_ratio` (예: 90:10) - `guardrail_config` (JSONB) - `status` (`running`, `paused`, `completed`) - `started_at`, `ended_at` ### 4.4 `prompt_events` - purpose: 요청 단위 결과 로그 - columns: - `id`, `request_id`, `template_key`, `version_id`, `variant` - `execution_mode` (`safe_prod`, `strict_observe`) - `user_id`, `robeing_id`, `task_type` - `latency_ms`, `tokens_in`, `tokens_out` - `feedback_signal` (up/down/reask/abandon) - `created_at` ### 4.5 `prompt_metrics_daily` - purpose: 일별 집계 - columns: - `date`, `template_key`, `version_id`, `variant` - `success_rate`, `reask_rate`, `fallback_rate` - `avg_latency_ms`, `avg_tokens`, `feedback_score` --- ## 5. 런타임 병합 규칙 ### 5.1 해석 순서 (낮음 → 높음 우선순위) 1. Global 2. Robeing 3. Task 4. User 5. Runtime modifier(감정/리스크 규칙) ### 5.2 병합 원칙 - 문자열 덮어쓰기 금지, 섹션 단위 병합(`role`, `constraints`, `output_format`) - 금지 규칙(예: 민감 라벨 직접 노출 금지)은 항상 최종 승자 - 해석 실패 시 처리 규칙: - `safe_prod`: 즉시 fallback (최근 stable active 버전) - `strict_observe`: fallback 금지, 오류 노출 + 구조화 로그 기록 --- ## 6. 자동 개선 정책 ### 6.1 실험 지표 - 1차 품질 지표: - `reask_rate` (낮을수록 좋음) - `negative_feedback_rate` (낮을수록 좋음) - `task_success_rate` (높을수록 좋음) - 2차 비용/성능 지표: - `avg_latency_ms` - `avg_tokens` - `fallback_rate` ### 6.2 자동 승격 조건(예시) - 최소 샘플 수 충족 (예: n >= 500) - treatment가 control 대비: - `reask_rate` 10% 이상 개선 - `negative_feedback_rate` 악화 없음 - `latency_ms` 15% 이상 악화 없음 - guardrail 위반 0건 ### 6.3 자동 롤백 조건 - 15분 윈도우 기준 `fallback_rate` 급증 - `negative_feedback_rate` 임계치 초과 - 5xx/파싱 실패 연쇄 발생 ### 6.4 운영 모드 - 기본: **자동 제안 + 사람 승인 후 승격** - 완전 자동 승격은 초기 1개월 관찰 후 제한 적용 --- ## 7. 구현 단계 ### Phase 1: 인벤토리/스키마/TDD - 하드코딩 프롬프트 인벤토리 확정(파일/함수/용도) - `prompt_templates`, `prompt_versions` 생성 - Repository + Service 뼈대 구현 - 테스트: - 스키마 생성/마이그레이션 - 버전 조회/활성 버전 선택 ### Phase 2: 읽기 경로 전환 (safe fallback) - `llm_service.py`, `gemini_handler.py`에 DB 조회 연결 - 기존 하드코딩은 fallback로 유지 - 테스트: - DB 성공 시 DB 프롬프트 사용 - DB 실패 시 하드코딩 fallback - `strict_observe`에서 DB 실패 시 fallback 없이 오류/로그 노출 검증 ### Phase 3: 병합/개인화/감정 modifier - scope 병합 및 변수 치환 - 감정/리스크 modifier를 DB 규칙으로 부분 이관 - 테스트: - 병합 우선순위 - 금지 규칙 우선 적용 ### Phase 4: 실험/메트릭/자동 승격 - `prompt_experiments`, `prompt_events`, `prompt_metrics_daily` 구현 - 실험 라우터 + 승격/롤백 워커 구현 - 테스트: - 라우팅 결정 일관성 - guardrail 위반 시 자동 중단/롤백 --- ## 8. 수용 기준 (Definition of Done) - 하드코딩 의존 프롬프트 80% 이상 DB 전환 - 핵심 UX 경로(chat/summarize/extract/calendar_confirm) DB 관리 - 실험 대시보드에서 버전별 지표 확인 가능 - 자동 롤백 시나리오 리허설 1회 이상 통과 - 장애 시 서비스 무중단 fallback 확인 - `strict_observe` 경로에서 의도적 실패가 로그/메트릭으로 누락 없이 수집되는지 검증 --- ## 9. 위험과 대응 - 위험: 잘못된 프롬프트 배포로 UX 악화 - 대응: candidate → canary → full 단계적 승격 - 위험: 과도한 개인화로 톤 불안정 - 대응: immutable safety constraints 최종 적용 - 위험: 지표 왜곡/샘플 편향 - 대응: 최소 샘플 수 + 시간/사용자 분산 조건 --- ## 10. 운영 권고안 (초기 4주) ### 10.1 운영 모드 - 기본 모드: `자동 제안 + 사람 승인 후 승격` - 완전 자동 승격은 안정화 4주 후, low-risk 템플릿부터 제한 허용 ### 10.2 배포/승격 절차 - 단계 고정: `draft -> candidate -> canary(10%) -> full` - canary 승격 최소 조건: - 최소 샘플 수 `n >= 500` - 최소 관찰 시간 `>= 24h` - guardrail 위반 0건 ### 10.3 실시간 가드레일 (권장 임계치) - `reask_rate`가 control 대비 10%p 이상 악화 시 즉시 중단 - `negative_feedback_rate`가 control 대비 5%p 이상 악화 시 롤백 - `fallback_rate`가 15분 윈도우에서 2배 이상 급증 시 롤백 - 5xx/파싱 실패 연쇄 발생 시 즉시 kill-switch ### 10.4 DB 운영 권장 - `prompt_events`는 일 단위 파티셔닝 권장 - 보관 주기: 원천 이벤트 30~90일, 집계 메트릭 장기 보관 - 필수 인덱스: - `(template_key, version_id, created_at)` - `(experiment_key, status)` - `(date, template_key, version_id)` on daily metrics - 권한 분리: - 편집 권한(템플릿 수정)과 승격 권한(활성화/롤백) 분리 ### 10.5 관측/알람 - 대시보드 3축: - 품질: reask, feedback, task_success - 성능: latency, tokens - 안정성: fallback, parse_fail, 5xx - 알람 윈도우 이중화: - 15분 단기(즉시 대응) - 1시간 중기(추세 확인) ### 10.6 복구/감사 - 승격마다 `change_reason`, `approver`, `experiment_key` 필수 기록 - 월 1회 롤백 드릴 수행 및 결과 문서화 ### 10.7 폴백 규율 (핵심) - 원칙: 폴백은 사용자 보호용 최후 수단이며, 개선 신호를 가리는 기본 경로가 되어서는 안 된다. - 이중 운영 모드: - `safe_prod`: 일반 사용자 트래픽, 제한적 폴백 허용 - `strict_observe`: 카나리/내부 검증 트래픽, 폴백 금지(오류를 노출해 개선 포인트 확보) - 필수 로그 스키마(폴백/실패 공통): - `request_id`, `template_key`, `version_id`, `variant` - `route`, `fallback_reason`, `upstream_error_code`, `upstream_error_message` - `latency_ms`, `created_at` - 운영 규칙: - `strict_observe` 비율은 최소 5~10% 유지 - 폴백 비율이 기준치 초과 시 실험 승격 금지 - 로그 없는 폴백 경로는 배포 금지 --- ## 11. 체크리스트 (누락 방지) ### 설계 - [ ] 실제 하드코딩 인벤토리 목록화 완료 - [ ] scope 우선순위 충돌 규칙 정의 - [ ] 안전 제약(금지 규칙) 최종 우선순위 명시 ### 구현 - [ ] Repository/DDL/Service 동시 반영 - [ ] fallback 경로(코드/DB) 모두 테스트 - [ ] 실험 라우팅 deterministic 보장 - [ ] `safe_prod` vs `strict_observe` 모드별 실패 처리 테스트 - [ ] 실패 이벤트의 구조화 로그 스키마(`execution_mode` 포함) 검증 ### 운영 - [ ] 승격/롤백 가드레일 임계값 합의 - [ ] 대시보드/알람 연결 - [ ] 장애 훈련(롤백 drill) 수행 - [ ] `strict_observe` 트래픽 비율(최소 5~10%) 운영 중인지 확인 - [ ] 폴백 이벤트 필수 로그 스키마 누락 없는지 점검 - [ ] 로그 없는 폴백 경로가 없는지 배포 전 검증 --- ## 12. 2회 점검 기록 (2026-03-03) ### 1차 점검에서 추가한 누락 항목 - 자동 승격 조건(샘플 수/가드레일) - 자동 롤백 조건 - 이벤트/메트릭 테이블 분리 - 현재 하드코딩 인벤토리 규모 반영 ### 2차 점검에서 확정한 항목 - scope 병합 우선순위 명시 - immutable safety constraints 최종 우선 적용 명시 - DoD/운영 체크리스트/리허설 항목 추가 --- ## 13. 운영 기본값 표 (초기값) | 항목 | 기본값 | 비고 | |---|---:|---| | canary 비율 | 10% | high-risk 템플릿은 5% | | 최소 샘플 수 | 500 | 승격 전 필수 | | 최소 관찰 시간 | 24h | 승격 전 필수 | | reask_rate 가드레일 | +10%p | control 대비 악화 시 중단 | | negative_feedback_rate 가드레일 | +5%p | control 대비 악화 시 롤백 | | fallback_rate 가드레일 | 2x | 15분 윈도우 급증 시 롤백 | | 오류 가드레일 | 5xx/파싱 실패 연쇄 | 즉시 kill-switch | --- ## 14. DDL/롤백 SQL 예시 ### 14.1 생성 DDL (요약) ```sql CREATE TABLE IF NOT EXISTS prompt_templates ( id BIGSERIAL PRIMARY KEY, template_key TEXT NOT NULL UNIQUE, prompt_type TEXT NOT NULL, scope_level TEXT NOT NULL, scope_id TEXT, is_enabled BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS prompt_versions ( id BIGSERIAL PRIMARY KEY, template_id BIGINT NOT NULL REFERENCES prompt_templates(id), version INT NOT NULL, content JSONB NOT NULL, variables_schema JSONB, status TEXT NOT NULL, created_by TEXT, change_reason TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE(template_id, version) ); CREATE TABLE IF NOT EXISTS prompt_experiments ( id BIGSERIAL PRIMARY KEY, experiment_key TEXT NOT NULL UNIQUE, template_key TEXT NOT NULL, control_version_id BIGINT NOT NULL REFERENCES prompt_versions(id), treatment_version_id BIGINT NOT NULL REFERENCES prompt_versions(id), traffic_ratio JSONB NOT NULL, guardrail_config JSONB NOT NULL, status TEXT NOT NULL, started_at TIMESTAMPTZ, ended_at TIMESTAMPTZ ); CREATE TABLE IF NOT EXISTS prompt_events ( id BIGSERIAL PRIMARY KEY, request_id TEXT NOT NULL, template_key TEXT NOT NULL, version_id BIGINT NOT NULL REFERENCES prompt_versions(id), variant TEXT NOT NULL, user_id TEXT, robeing_id TEXT, task_type TEXT, latency_ms INT, tokens_in INT, tokens_out INT, feedback_signal TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS prompt_metrics_daily ( date DATE NOT NULL, template_key TEXT NOT NULL, version_id BIGINT NOT NULL REFERENCES prompt_versions(id), variant TEXT NOT NULL, success_rate DOUBLE PRECISION, reask_rate DOUBLE PRECISION, fallback_rate DOUBLE PRECISION, avg_latency_ms DOUBLE PRECISION, avg_tokens DOUBLE PRECISION, feedback_score DOUBLE PRECISION, PRIMARY KEY (date, template_key, version_id, variant) ); CREATE INDEX IF NOT EXISTS idx_prompt_events_template_ver_time ON prompt_events(template_key, version_id, created_at); CREATE INDEX IF NOT EXISTS idx_prompt_experiments_key_status ON prompt_experiments(experiment_key, status); CREATE INDEX IF NOT EXISTS idx_prompt_metrics_daily_lookup ON prompt_metrics_daily(date, template_key, version_id); ``` ### 14.2 롤백 SQL (요약) ```sql -- 1) active 버전 되돌리기(예: status 전환 정책 사용 시) -- UPDATE prompt_versions SET status='active' WHERE id=:stable_version_id; -- UPDATE prompt_versions SET status='retired' WHERE id=:bad_version_id; -- 2) 실험 즉시 중단 -- UPDATE prompt_experiments SET status='paused', ended_at=NOW() WHERE experiment_key=:exp_key; -- 3) 필요 시 인덱스/테이블 제거 (개발환경 한정) -- DROP INDEX IF EXISTS idx_prompt_events_template_ver_time; -- DROP TABLE IF EXISTS prompt_metrics_daily, prompt_events, prompt_experiments, prompt_versions, prompt_templates; ``` --- ## 15. RACI (책임 체계) | 역할 | 책임 | |---|---| | Author | 프롬프트 초안 작성, 변경 사유 기록 | | Reviewer | 품질/톤/안전 제약 검토 | | Approver | canary/full 승격 승인 | | Operator | 알람 대응, kill-switch, 롤백 실행 | 운영 원칙: - 편집 권한과 승격 권한은 분리한다. - 야간/주말 온콜 Operator를 지정한다. --- ## 16. 운영 캘린더 - 일일: - 15분/1시간 알람 리뷰 - 전일 대비 품질/성능/안정성 지표 점검 - 주간: - 실험 결과 리뷰 - candidate -> canary -> full 승격 회의 - 월간: - 롤백 드릴 1회 - 가드레일 임계값 재평가 --- ## 17. 변경 이력 템플릿 ```text change_id: template_key: from_version: to_version: experiment_key: change_reason: expected_impact: approver: applied_at: rollback_target_version: post_check_result: ``` --- ## 18. 장애 런북 (요약) 1. 알람 감지: 가드레일 위반 확인(15분/1시간 동시 확인) 2. 즉시 차단: experiment `paused` + kill-switch 적용 3. 안정화: stable active 버전 강제 전환 4. 검증: 핵심 API smoke + 주요 UX 시나리오 3건 확인 5. 사후 분석: 원인/영향/재발 방지 항목 기록 운영 목표: - 장애 감지 후 15분 내 안정 버전 복귀 --- ## 19. 일정 추정 (체크용) ### 19.1 빠른 현실 기준 - 30분: 설계/문서 확정, 작업 분할, 체크리스트 고정 (구현 완료 불가) - 4~6시간: MVP 골격 구현 - 스키마/Repository/기본 조회·병합 - `safe_prod`/`strict_observe` 분기 연결 - 핵심 단위 테스트 일부 - 1~2일: 기능 완료 + 테스트 통과 - LLM 경로 연동(`llm_service`, `gemini_handler`) - fallback/strict_observe 동작 검증 - TDD + 핵심 E2E - 4~5일: 운영 안정화 포함 - canary(5~10%) 관측 - 가드레일 임계치 보정 - 롤백 드릴 수행 ### 19.2 마일스톤 - M1 (반나절): DB 스키마 + Repository 초안 - M2 (1일): 런타임 병합 + 모드 분기 동작 - M3 (2일): 테스트/검증 완료, canary 시작 준비 - M4 (4~5일): canary 관측 + 운영 기준 확정 --- ## 참고 문서 - `book/300_architecture/311_backend_coding_principles.md` - `book/300_architecture/312_writing-principles.md` - `book/300_architecture/315_테스트_원칙.md` - `book/300_architecture/313_Gemini_프롬프트_설계_원칙.md` - `journey/troubleshooting/250806_happybell80_동적프롬프트구현.md`