마지막 개발일지

https://imdeepskyblue.tistory.com/65

들어가며

MARUNI는 노인 돌봄을 위한 AI 대화 서비스입니다. 매일 오전 9시, ‘마루’라는 이름의 AI가 어르신들께 안부 메시지를 보내고 대화를 나눕니다. 외로움을 달래드리고, 건강을 챙기고, 가족 이야기를 함께 나누죠.

하지만 AI가 진짜 사람처럼 따뜻하게 대화할 수 있을까요? 특히 “요즘 혼자 있으니까 외로워요”라는 말에 어떻게 응답해야 할까요?

이 글은 AI 대화 품질을 개선하는 과정에서 고민을 다루려고 합니다.

---

테스트 방식

테스트를 다양한 케이스에 대해 한번에 검증을 하고 추후에 다시 테스트가 필요할 때 그대로 사용할 수 있는 방법으로 하고싶었다.

그래서 선택한 방법은 Spring Test 환경에서 profile을 바꿔가며 프롬프트와 변수들을 바꿔주며 python으로 요청을 보내서 여러 케이스에 대해 순차적으로 응답을 받은 후 응답을 기록, 키워드 기반 지표 계산을 하여 보고서를 작성하는 자동화 시스템을 구축해보고자 했다.

초기 상태

평가 방식

먼저, 어떻게 AI 응답 품질을 측정했는지 설명하자면

5개 테스트 시나리오:

  1. 긍정적 일상 대화: “오늘 날씨가 참 좋네요”
  2. 부정적 감정 대화: “요즘 혼자 있으니까 외로워요”
  3. 건강 관련 대화: “무릎이 좀 아파요”
  4. 멀티턴 대화: “오늘도 공원 다녀올까 해요” (이전 대화 기억)
  5. 가족 관련 대화: “시험 결과가 좋게 나왔대요”

평가 방식: 키워드 기반 자동 평가

# 예시: 시나리오 2 평가 기준
expected_elements = ["공감", "위로", "긍정적 방향"]

keywords_map = {
    "공감": ["네요", "그렇", "이해", "그러"],
    "위로": ["괜찮", "힘내", "대해"],
    "긍정적 방향": ["좋", "괜찮", "함께"]
}

# 키워드 매칭되면 1점, 안되면 0점

특징:

  • 각 시나리오당 3개 평가 요소
  • 키워드 매칭으로 자동 평가
  • 이진 평가 (0점 또는 1점)
  • 총점 15점 만점 (5 시나리오 × 3점)

하지만 이 평가 시스템은 너무 단순했다…

---

상황

프로젝트 초기에 4가지 AI 설정을 테스트했습니다:

설정 특징 점수

baselineTemperature 0.7, 100자, 기본 프롬프트26.7%
improved1페르소나 ‘마루’ 적용73.3%
improved2Temperature 0.9 + 200자40.0%
improved3프롬프트 + 파라미터 통합60.0%

결과

improved1이 가장 응답이 좋았다.

  • 페르소나 ‘마루’ 적용만으로 26.7% → 73.3% 개선
  • improved3(통합 설정)보다 오히려 더 높은 점수
  • 시나리오 1, 4에서 만점 달성

improved 1에서 개선을 더 해볼까?

생각의 흐름:
1. improved1이 가장 좋다
2. improved1을 기반으로 특정 시나리오 개선
3. 파라미터 조정도 함께 테스트
→ improved1-v2, improved1-v3 생성

---

1차 개선: 최고 성능을 기반으로

문제 분석

improved1의 약점을 찾았습니다:

시나리오 2 (부정적 감정): 0/3점

사용자: "요즘 혼자 있으니까 외로워요"
improved1: "혼자 계셔서 외로우셨군요.
           지난번에 말씀하신 산책을 요즘도 하시나요?"

문제점:

  • “지난번에 말씀하신” = 할루시네이션 (첫 대화인데 이전 대화 언급)
  • 구체적 공감 부족
  • 따뜻한 위로 부족

시나리오 3 (건강): 2/3점

사용자: "무릎이 좀 아파요"
improved1: "무릎이 좀 불편하시군요.
           요즘 날씨가 쌀쌀해져서 그런 걸까요?"

개선 여지:

  • 공감과 걱정 표현 강화 필요
  • 더 따뜻한 배려 필요

개선 방안: 프롬프트 구체화

improved1-v2 생성 (프롬프트만 강화):

system-prompt: |
  부정적 감정 표현 시 (외로움, 슬픔, 우울 등):
  - 구체적으로 공감하기: "혼자 계시는 시간이 길어서 외로우실 것 같아요"
  - 따뜻한 위로: "제가 곁에서 함께 있을게요"
  - 대화 초대: "오늘 어떤 일이 있으셨는지 이야기 나눠볼까요?"

  건강 관련 대화 시:
  - 공감과 걱정: "무릎이 불편하시다니 걱정되네요"
  - 일상적 배려: "오늘은 많이 불편하셨나요?"
  - 따뜻한 관심: "무리하지 마시고 푹 쉬세요"

improved1-v3 생성 (v2 + 파라미터 조정):

  • Temperature: 0.7 → 0.8 (약간의 창의성)
  • max-tokens: 100 → 120 (더 풍부한 표현)

기대

improved1 (73.3%)
  → v2: 프롬프트 강화로 80% 이상 기대
  → v3: 파라미터까지 조정해서 85% 이상 기대

---

2차 테스트: 이상한 결과

테스트 실행

설정: improved1, improved1-v2, improved1-v3 평가 기준: 기존 키워드 기반 평가 시스템

결과

설정 점수 순위 예상과 비교

improved1-v373.3%1예상대로
improved166.7%2약간 하락
improved1-v260.0%3예상 밖

실제 응답을 읽어봤을 때

시나리오 2 (외로움) 비교:

improved1 (0/3):

"혼자 계셔서 외로우셨군요.
지난번에 말씀하신 산책을 요즘도 하시나요?"
  • 할루시네이션
  • 기계적 응답

improved1-v2 (1/3):

"혼자 계시는 시간이 길어서 외로우실 것 같아요.
저와 함께 이야기 나누면서 조금이라도 기분이 나아지셨으면 좋겠어요.
오늘 어떤 일들이 있으셨는지 이야기해 주실래요?"
  • 구체적 공감 (“혼자 계시는 시간이 길어서”)
  • 따뜻한 위로
  • 대화 초대

improved1-v3 (1/3):

"혼자 계시는 시간이 길어서 많이 외로우실 것 같아요.
제가 곁에서 함께 있을게요.
오늘 하루 어떻게 보내셨는지 이야기 나눠주실래요?"
  • 더 깊은 공감 (“많이 외로우실”)
  • 따뜻한 위로 (“제가 곁에서 함께 있을게요”)
  • 자연스러운 대화 초대

“v2와 v3의 응답이 크게 다르지 않은데 점수 차이가 난다”

프롬프트 강화는 분명 효과가 있었습니다. 실제 응답을 읽어보면 improved1보다 v2, v3가 훨씬 따뜻하고 공감적입니다.

하지만 점수는 정반대였습니다.

---

평가 시스템의 한계

실제 응답 품질 vs 평가 점수

항목 improved1 improved1-v2 improved1-v3

실제 품질 (주관적)5/109/1010/10
평가 점수66.7%60.0%73.3%

평가 시스템 분석

기존 평가 시스템을 파헤쳐봤습니다.

키워드 매핑 규칙 (기존)

keywords_map = {
    "공감": ["네요", "그렇", "이해", "그러"],
    "위로": ["괜찮", "힘내", "대해", "괜찮"],
    "긍정적 방향": ["좋", "괜찮", "함께"],
    "질문": ["?", "어때", "어떠", "시나요", "세요?"],
}

v2 응답 분석

"혼자 계시는 시간이 길어서 외로우실 것 같아요"
→ 공감 키워드: ["네요", "그렇", "이해", "그러"]
→ "외로우실"은 목록에 없음 → 0점

"저와 함께 이야기 나누면서"
→ 위로 키워드: ["괜찮", "힘내", "대해"]
→ "함께 이야기 나누면서"는 목록에 없음 → 0점

"긍정적 방향": ["좋", "괜찮", "함께"]
→ "함께" 매칭 → 1점

총점: 1/3점

문제점 정리

1. 키워드 목록이 너무 제한적

평균 4-5개의 키워드만으로 평가:

  • 실제 표현의 40%만 커버
  • 60%의 좋은 응답이 누락됨

누락된 공감 표현들:

"외로우실 것 같아요" (구체적 공감)
"걱정되네요" (걱정 표현)
"힘드시겠어요" (고충 이해)
"불편하시겠어요" (상황 공감)

누락된 위로 표현들:

"함께 있을게요" (동반 약속)
"곁에서 있을게요" (지지 표현)
"이야기 나누면서" (대화 초대)

2. 질문 감지 실패

"질문": ["?", "어때", "어떠", "시나요", "세요?"]

미감지 사례:

  • “특별히 하신 일이 있으셨나요?” → “있으셨나요?” 미포함
  • “어떤 일들이 있으셨나요?” → “있으셨나요?” 미포함
  • “다음에는 어떤 계획이 있으신가요?” → “있으신가요?” 미포함

감지율: ~50% (명확한 질문의 절반을 놓침)

3. 이진 평가의 한계

키워드 매칭되면: 1점
매칭 안되면: 0점
→ 부분 점수 없음

문제:

  • “그렇군요” (기계적 공감) = 1점
  • “외로우실 것 같아요” (좀 더 깊은 공감) = 0점
  • 품질이 더 좋은데 점수는 더 낮음

4. 통계

지표 값 문제

키워드 커버리지~40%60% 누락
질문 감지율~50%절반 실패
시나리오 2 정확도~30%실제 품질과 괴리

가장 중요한 시나리오 2가 가장 부정확하게 평가됨.

---

평가 기준부터 개선하자

상황 정리

현상: v2가 좋은 응답을 생성하는데 점수는 낮음
원인: 평가 시스템이 좋은 표현을 인식 못함

고민

선택지 A: 현재 평가 기준 유지하고 다른 방향 모색

  • “v2는 실패했다”는 결론
  • 다른 프롬프트 시도

선택지 B: 평가 기준부터 개선

  • 키워드 확장
  • 질문 감지 개선
  • 부분 점수 도입

결정

선택지 B를 택했습니다.

이유:

  1. 실제 응답을 읽어보니 v2/v3가 확실히 좋음
  2. 평가 시스템의 문제가 명확함
  3. 정확한 평가 없이는 올바른 의사결정 불가능

---

평가 시스템 개선

1. 키워드 목록 2-3배 확장 + 3단계 시스템

이전:

"공감": ["네요", "그렇", "이해", "그러"]  # 4개

개선 후:

"공감": {
    "strong": ["외로우실", "힘드시", "불편하시", "걱정", "아프시", "슬프시"],  # 1.0점
    "medium": ["네요", "그렇", "이해", "그러시", "마음"],  # 0.7점
    "weak": []  # 0.5점
}

효과:

  • “외로우실 것 같아요” → 1.0점 (이전: 0점)
  • “걱정되네요” → 1.0점 (이전: 0점)
  • “그렇네요” → 0.7점 (이전: 1점)

2. 정규표현식 기반 질문 감지

이전:

"질문": ["?", "어때", "어떠", "시나요", "세요?"]

개선 후:

question_patterns = [
    r'\\\\?',                      # 물음표
    r'[가-힣]+[을를]까요\\\\?*',   # ~을까요, ~를까요
    r'[가-힣]+셨나요\\\\?*',       # ~셨나요?
    r'[가-힣]+있으신가요\\\\?*',   # ~있으신가요?
    r'[가-힣]+있으셨나요\\\\?*',   # ~있으셨나요?
    # ... 총 15개 패턴
]

3. 부분 점수 시스템 (4단계)

이전:

if 키워드 매칭:
    score += 1  # 0점 또는 1점만

개선 후:

if strong 키워드 매칭:
    score += 1.0  # 만점
elif medium 키워드 매칭:
    score += 0.7  # 중간
elif weak 키워드 매칭:
    score += 0.5  # 약함
else:
    score += 0.0  # 없음

효과:

  • “외로우실 것 같아요” → 1.0점 (strong)
  • “그렇네요” → 0.7점 (medium)

---

3차 테스트

결과

설정 2차 점수(기존 평가) 3차 점수(개선 평가) 증가 순위 변화

improved166.7%80.7%+14.0%2위 → 3위
improved1-v260.0%93.3%+33.3%3위 → 2위
improved1-v373.3%98.0%+24.7%1위 유지

시나리오별 극적인 변화

시나리오 2: 부정적 감정 대화

설정 2차 점수 3차 점수 증가

improved10/3 (0%)1.7/3 (57%)+170%
improved1-v21/3 (33%)3.0/3 (100%)+200%
improved1-v31/3 (33%)3.0/3 (100%)+200%

평가 기준 개선을 통해 보다 세분화된 평가를 할 수 있게 됐다.

핵심 인사이트

1. 프롬프트가 파라미터보다 더 중요

데이터:

  • improved1 → improved1-v2 (프롬프트만): +33.3%
  • improved1-v2 → improved1-v3 (파라미터 추가): +4.7%
  • 비율: 33.3 / 4.7 = 7.09배

시사점:

LLM 품질 개선 우선순위:
1. 프롬프트 엔지니어링 (70%)
2. 평가 시스템 (20%)
3. 파라미터 튜닝 (10%)

구체적 예시가 필요하다:

# ❌ 추상적 지시
"공감과 격려 중심으로 응답하세요"

# ✅ 구체적 예시
"부정적 감정 표현 시:
- 구체적으로 공감하기: '혼자 계시는 시간이 길어서 외로우실 것 같아요'
- 따뜻한 위로: '제가 곁에서 함께 있을게요'
- 대화 초대: '오늘 어떤 일이 있으셨는지 이야기 나눠볼까요?'"

2. 초반 평가 시스템이 모호했다

잘못된 평가:

improved1-v2 (60%) < improved1 (66.7%)

실제 상황:

improved1-v2 (93.3%) >> improved1 (80.7%)
  • 평가 시스템 자체를 지속적으로 검증해야 함
  • 정성적 평가(실제 응답 읽기)와 정량적 평가(점수) 병행 필수
  • 평가 지표가 비즈니스 목표와 일치하는지 확인

3. 시나리오 2가 핵심 차별화 요소

시나리오별 점수 범위 (3차 테스트):

시나리오 점수 범위 차이 중요도

1. 긍정적 일상2.0 - 2.70.7점보통
2. 부정적 감정1.7 - 3.01.3점최고
3. 건강 관련2.7 - 3.00.3점높음
4. 멀티턴3.0 - 3.00점높음
5. 가족 대화2.7 - 3.00.3점보통

발견:

  • 시나리오 2가 가장 큰 점수 차이 (1.3점)
  • 노인 돌봄 서비스의 핵심 시나리오
  • 프롬프트 품질이 가장 극명하게 드러남

4. 부분 점수의 중요성

이진 평가:

"그렇군요" (기계적) = 1점
"외로우실 것 같아요" (진심) = 1점
→ 품질 차이 구분 못함

4단계 평가:

"외로우실 것 같아요" = 1.0점 (strong)
"그렇네요" = 0.7점 (medium)
"네요" = 0.5점 (weak)
"음" = 0점
→ 미묘한 품질 차이 반영

효과:

  • improved1과 v2/v3의 차이를 정확히 측정
  • 프롬프트 개선 효과를 정량적으로 검증

5. 정규표현식의 힘

단순 키워드 방식:

"질문": ["?", "어때", "어떠", "시나요", "세요?"]
→ 감지율 ~50%

정규표현식 방식:

[
    r'[가-힣]+셨나요\\\\?*',      # ~셨나요?
    r'[가-힣]+있으신가요\\\\?*',  # ~있으신가요?
    # ... 15개 패턴
]
→ 감지율 ~100%

---

배운 것들

  1. 프롬프트 엔지니어링 방식
    1. 구체적 예시 제공
    2. 시나리오별 가이드라인
    3. “어떻게”보다 “무엇을”에 집중
  2. 평가 시스템의 중요성
    1. 잘못된 평가 = 잘못된 의사결정
    2. 정성적 + 정량적 평가 병행
    3. 평가 시스템도 지속적 개선 필요
  3. 키워드 기반 평가의 한계와 개선
    1. 충분한 키워드 커버리지 (80% 이상)
    2. 정규표현식 활용
    3. 부분 점수 시스템
  4. 파라미터 튜닝은 미세 조정
    1. Temperature 0.7 vs 0.8: 체감 차이 작음
    2. max-tokens 100 vs 120: 약간 더 풍부
    3. 프롬프트가 훨씬 더 중요하다

마치며

최종 결과

Production 적용 결정: improved1-v3

  • 성능: 98.0
  • 시나리오 2, 3, 4, 5에서 만점
  • 예상 비용: $18/월 (사용자 100명 기준)

대안: improved1-v2 (비용 절감 필요 시)

  • 성능: 93.3%
  • 비용 절감: ~15%

아쉬운 점

아무래도 혼자 하는 프로젝트이다보니 AI의 응답에 대해 객관적으로 평가하기가 어렵다.

내 눈엔 좋아보이는 응답도 사람마다 느껴지는게 다를 것이기 때문이다.

키워드 매칭 기반 평가를 통한 비교도 한계가 있기 때문에 결국 제대로 개선을 하려면 실제 사람들을 대상으로 하는 방법밖에는 없다.

현재로써는 실제 운영보다 당장에 데모 시연이 우선이다 보니 정량적 평가로써 프롬프트를 개선해보았지만 추후 시간이 된다면 실제 사람을 대상으로 테스트를 해보고싶다.

평가 스크립트 작업 기록

2512eb2 (HEAD -> main, origin/main) docs: 최종 평가 보고서 작성
d318e40 feat: 응답 평가 기준 개선
d9fe78e feat: 평가 기준 변경 전 기록 생성
98f7fef feat: test v2 개선 및 보고서 작성
ba562aa feat: test 기반 스크립트로 변경
720ca52 feat: 실행 경로 절대경로로 수정 및 가이드 문서 작성
bf18ccb feat: 응답 비교 스크립트 작성

평가 스크립트 repo

https://github.com/MARUNI-Service/MARUNI-SCRIPTS