모델은 상태가 없는 함수입니다. 방금 한 말도 서버에 남지 않습니다. 대화가 이어지는 것처럼 보이는 까닭은 우리 코드가 지난 대화를 모아 매번 통째로 다시 보내기 때문입니다. 리스트를 직접 들고 다니는 방식(multiturn_manual.py)과 세션별로 맡기는 방식(multiturn_history.py)을 차례로 따라가고, 5일차의 체크포인터로 이어지는 지점을 짚습니다. 모델의 답과 토큰 수는 실행마다 달라서 보라색 자리 표시로만 보여 줍니다.
왼쪽은 우리 코드가 들고 있는 대화 기록, 가운데는 상태가 없는 모델, 오른쪽은 세션 ID 별로 기록을 나눠 맡기는 RunnableWithMessageHistory 입니다. 어느 방식이든 모델에게 가는 것은 '지난 기록 + 새 질문' 전체입니다.
multiturn_manual.py 17줄이 없으면 기록에는 질문만 쌓이고, 모델은 자기가 앞서 무엇이라고 답했는지 모릅니다._store 는 프로세스 메모리입니다. 프로그램이 끝나면 모든 대화가 사라지고, 서버가 여러 대면 서로의 기록을 보지 못합니다. 16줄 주석처럼 실제 서비스에서는 Redis 나 DB 로 바꿉니다.session_id 를 빠뜨리면 실행되지 않습니다. with_memory.invoke("…") 처럼 config 없이 부르면 Missing keys ['session_id'] in config['configurable'] 라는 ValueError 가 납니다.multiturn_history.py 1줄은 '권장 방식'이라고 적었지만, 설치된 langchain-core 에서 RunnableWithMessageHistory 는 deprecated 입니다. 원리를 익히는 용도로 보고, 실제로는 5일차의 체크포인터를 씁니다.day1_practice/limits.py환각, 계산 오류, 상태 망각을 차례로 재현합니다. 이 자료는 마지막 상태 망각(19~21줄)만 다룹니다.day1_practice/messages_role.pysystem / user / assistant 역할을 바꿔 가며 같은 질문을 보냅니다. 세 번째 호출이 대화 기록을 함께 보내는 예입니다.day1_practice/multiturn_manual.pychat_history 리스트를 직접 관리하며 매 턴 기록 개수와 입력 토큰 수를 찍습니다.day1_practice/multiturn_history.pyRunnableWithMessageHistory 와 session_id 로 사용자별 기록을 나눠 관리합니다.day5_practice/checkpointer_basic.py(참고) 같은 원리를 thread_id 와 SQLite 체크포인터로 다시 만든 5일차 실습입니다.