-
이코에코(Eco²) Agent: Multi-turn 대화 E2E 검증 완료이코에코(Eco²)/Agent 2026. 1. 19. 11:29

검증 일시: 2026-01-19 03:05 UTC
검증 환경: k8s-master (13.209.44.249)
관련 PR: #434 (fix: use redis_streams for ProgressNotifier and DomainEventBus)
검증 결과: ✅ PASS
1. 검증 개요
1.1 검증 목적
LangGraph 체크포인터(PostgreSQL + Redis Cache-Aside)를 통한 멀티턴 대화 상태 영속화 및 맥락 유지 검증.
1.2 핵심 검증 항목
항목 설명 결과 세션 상태 영속화 동일 session_id로 여러 메시지 처리 시 상태 유지 ✅ Pass 체크포인트 누적 turn마다 step이 연속적으로 증가 ✅ Pass intent_history 누적 이전 대화의 intent가 히스토리에 누적 ✅ Pass 맥락 유지 이전 턴의 대화 내용을 참조하여 응답 ✅ Pass Redis Streams 이벤트 각 turn의 이벤트가 정상 발행 ✅ Pass
2. 데이터 검증 (3 Turns)
세션 ID: 6a87f182-9599-498a-a519-fab2002f3c6a
2.1 Turn별 체크포인트 분포
Turn job_id Shard min_step max_step Checkpoints 1 199887cb-...1 -1 6 8 2 fdcd9d16-...3 7 14 8 3 ff6dc3bd-...3 15 22 8 총 24개 체크포인트, step이 -1 → 22까지 연속 증가
2.2 intent_history Blob 크기 변화
Turn Version Blob Size 내용 1 3-4 7 bytes ["waste"]2 11-12 13 bytes ["waste", "waste"]3 19-20 19 bytes ["waste", "waste", "waste"]2.3 채널별 Blob 현황
channel blob_count total_size __pregel_tasks6 10,150 disposal_rules5 6,141 weather_context5 930 __start__3 629 decomposed_queries6 214 intent_history6 78 2.4 Redis Streams Shard 분포
Shard Events Turn Shard 1 20 Turn 1 Shard 3 40 Turn 2, 3
3. 맥락 유지 검증 (5 Turns)
세션 ID: 04d4c54c-74dd-4271-8c92-5ce781d00b6a
검증 목적: 맥락 의존적 대화에서 이전 턴의 컨텍스트가 유지되는지 검증3.1 테스트 시나리오
페트병 분리배출 주제로 맥락이 이어지는 5턴 대화:
Turn 메시지 맥락 의존성 1 "페트병 어떻게 버려?" 기본 질문 2 "라벨은 어떻게 해?" 페트병 맥락 필요 3 "뚜껑도 분리해야 해?" 페트병 맥락 유지 4 "유색 페트병은 다르게 버려?" 페트병+색상 확장 5 "지금까지 알려준 거 정리해줘" 전체 맥락 요약 3.2 Turn별 대화 내용
Turn 1: 페트병 어떻게 버려?
User: 페트병 어떻게 버려?
Assistant (intent:
waste):무색 **페트병(먹는샘물/음료/주스병)**이면 **투명 페트병 전용 수거함(무색페트)**에 버리면 돼! ♻️ 배출은 이렇게 해줘: - **라벨 떼기 → 내용물 비우기 → 물로 헹구기 → 납작하게 압착 → 뚜껑 닫아서** 배출 참고로 **유색 페트병**이나 **음료·생수병이 아닌 페트 용기(식품용기, 컵, 워셔액 용기 등)**는 **플라스틱류**로 버려야 해.Turn 2: 라벨은 어떻게 해?
User: 라벨은 어떻게 해?
Assistant (intent:
waste):라벨은 보통 **떼서 따로 버리는 게 정답**이야 ♻️ - **종이 라벨**이면: 잘 떼어서 **종이류**로 (찢어지면 일반쓰레기인 경우도 있어) - **비닐/플라스틱 라벨**이면: **비닐류**로 분리배출💡 맥락 유지 확인: "라벨"만 언급했지만 페트병 라벨로 이해하고 응답
Turn 3: 뚜껑도 분리해야 해?
User: 뚜껑도 분리해야 해?
Assistant (intent:
waste):응, **대부분은 뚜껑도 분리하는 게 좋아!** ♻️ 보통 병(페트/유리) 몸통이랑 뚜껑 재질이 달라서 **몸통은 해당 수거함**, **뚜껑은 플라스틱류로 따로** 배출해주면 더 좋아.💡 맥락 유지 확인: "뚜껑"만 언급했지만 페트병 뚜껑으로 이해
Turn 4: 유색 페트병은 다르게 버려?
User: 유색 페트병은 다르게 버려?
Assistant (intent:
waste):응, **유색 페트병(초록/갈색/파란색 등)**은 무색 투명페트병이랑 달라서 **"플라스틱류"로 배출**하면 돼! ♻️ 무색 투명페트병만 따로 모아서 전용 수거함(무색페트병)으로 배출해야 해.💡 맥락 유지 확인: Turn 1에서 언급한 유색 페트병 내용과 연결
Turn 5: 지금까지 알려준 거 정리해줘
User: 지금까지 알려준 거 정리해줘
Assistant (intent:
general):좋아, 지금까지 내용 **무색 페트병(먹는샘물·음료 페트병)** 기준으로 깔끔하게 정리해줄게 ♻️ - **대상:** 먹는샘물/음료/주스 같은 **무색 PET 페트병** - **배출 방법:** **라벨 제거 → 내용물 비우기 → 물로 헹구기 → 눌러서 압착 → 뚜껑 닫아 배출** - **주의(이건 무색페트병으로 X):** **유색 페트병**, 페트 재질의 다른 용기/식품용기/워셔액 용기/컵, 먹는샘물·음료 외 플라스틱 용기는 **"플라스틱류"로 배출**해야 해 원하면 사진이나 제품 이름 보내줘도 "이게 무색페트병 맞는지" 같이 확인해줄게!✅ 맥락 유지 검증 완료: 이전 4개 턴의 내용(배출 방법, 라벨, 뚜껑, 유색 페트병)을 모두 포함하여 정리
3.3 데이터 검증 (5 Turns)
Turn job_id Shard min_step max_step Intent 1 29fddf24-...0 -1 6 waste 2 dcf654da-...1 7 14 waste 3 345f4bb5-...0 15 22 waste 4 f9ec98c6-...0 23 30 waste 5 0e4d8084-...1 31 38 general 총 40개 체크포인트, step이 -1 → 38까지 연속 증가
3.4 intent_history Blob 크기 변화 (5 Turns)
Turn Blob Size 추정 내용 1 7 bytes ["waste"]2 13 bytes ["waste", "waste"]3 19 bytes ["waste", "waste", "waste"]4 25 bytes ["waste", "waste", "waste", "waste"]5 33 bytes ["waste", "waste", "waste", "waste", "general"]
4. 멀티턴 상태 흐름
┌─────────────────────────────────────────────────────────────────────────────┐ │ Multi-Turn Conversation State Flow │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ Turn 1: "페트병 어떻게 버려?" │ │ ├── intent: waste, steps: -1 → 6 │ │ └── PostgreSQL checkpoint saved ────────────┐ │ │ │ │ │ ▼ │ │ Turn 2: "라벨은 어떻게 해?" │ │ ├── intent: waste, steps: 7 → 14 │ │ ├── intent_history: ["waste", "waste"] │ │ └── 맥락: 페트병 라벨로 이해 ◄────────────────┤ │ │ │ │ │ ▼ │ │ Turn 3: "뚜껑도 분리해야 해?" │ │ ├── intent: waste, steps: 15 → 22 │ │ └── 맥락: 페트병 뚜껑으로 이해 ◄──────────────┤ │ │ │ │ │ ▼ │ │ Turn 4: "유색 페트병은 다르게 버려?" │ │ ├── intent: waste, steps: 23 → 30 │ │ └── 맥락: Turn 1 유색 페트병 언급과 연결 ◄────┤ │ │ │ │ │ ▼ │ │ Turn 5: "지금까지 알려준 거 정리해줘" │ │ ├── intent: general, steps: 31 → 38 │ │ └── 맥락: Turn 1-4 전체 내용 요약 ◄───────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
5. SSE Event Flow
5.1 Turn 5 이벤트 시퀀스
queued (started) → intent (general) → general → aggregator → answer → done ↑ ↑ 맥락 기반 분류 이전 대화 참조하여 응답 생성5.2 done 이벤트 상세 (Turn 5)
6. 결론
6.1 검증 완료 항목
항목 상태 근거 세션 상태 영속화 ✅ Pass 동일 thread_id로 40개 체크포인트 누적 체크포인트 연속성 ✅ Pass step이 -1 → 38까지 연속 증가 intent_history 누적 ✅ Pass blob 크기 7 → 13 → 19 → 25 → 33 bytes 증가 맥락 유지 ✅ Pass Turn 5에서 이전 4개 턴 내용 정확히 요약 Redis Streams 발행 ✅ Pass 5개 turn 모두 이벤트 발행 확인 6.2 주요 설정
설정 값 위치 CHAT_SHARD_COUNT4 configmap.yaml enable_dynamic_routingTrue dependencies.py cache_ttl86400 (24h) checkpointer.py PostgreSQL Checkpointer Cache-Aside Pattern checkpointer.py
부록: 테스트 환경
Cluster: k8s-master (13.209.44.249) Namespace: chat Deployment: chat-worker PostgreSQL: dev-postgresql-0 (postgres namespace) Redis Streams: rfr-streams-redis-0 (redis namespace) Redis Pub/Sub: rfr-pubsub-redis-0 (redis namespace)'이코에코(Eco²) > Agent' 카테고리의 다른 글
이코에코(Eco²) Agent: Multi-Intent 분류 E2E 검증 완료 (0) 2026.01.19 이코에코(Eco²) Agent: Token Streaming 트러블슈팅 (0) 2026.01.19 이코에코(Eco²) Agent: LangGraph + Event Bus E2E 검증 완료 (1) 2026.01.19 이코에코(Eco²) Agent Multi-Intent E2E Test Results (0) 2026.01.19 Code Review: Channel Separation + Priority Scheduling (0) 2026.01.19