261001

u·2일 전

TIL

목록 보기
29/30

  • Store의 장기 기억 VS 체크포인터 (thread_id기준) - 대화세션
    • Store의 장기 기억 : 사용자 ID별 사용자 맞춤 장기 기억 저장소 (대화내용XXX)

장기 메모리

LangGraph Store

Store : 장기기억 저장소

  1. Store 기본 구조

    • namespace : 기억을 모아두는 공간

      • 문자열 튜플
      • (”용도”, ”사용자”, “기억종류”) ← 예시
    • key : namespace 안에서 기억을 구분하는 이름

    • value : 실제 저장할 내용 {딕셔너리}

      • {’text’:’내용’}
      • {’text’:~, ‘kind’:~, ‘speaker’:~}
        → kind, speaker 넣는 이유: 메타데이터 필터링용
    • put : 저장

      • store.put(namespace, key, value)
      • index=False → 임베딩 저장 X
      • index=[’text’] → text 키 값 임베딩 저장 → 의미 검색 가능
    • get : key로 정확히 불러오기

      • item = store.get(namespace, key)
    • delete : 삭제

      • store.delete(namespace, key)
    • search(query=) : 의미 검색

      • store.search(namespace, query=의미검색, filter=메타데이터 조건, limit=가져올개수)
  2. Node에서 Store 사용

@dataclass
class UserContext:
    user_id: str  # 실행 코드가 전달하는 사용자 ID. 기억의 조회 범위를 결정

from langgraph.runtime import Runtime

def recall_memories(state: CounselingState, runtime: Runtime[UserContext]):
		
		# runtime : 노드가 실행될 때 필요한 사용자 정보 및 저장소 같은 자원에 접근하기 위한 변수
    # runtime.context : langchain 정해진 부분
    # user_id : 우리가 정의한 정보
    
    user_id = runtime.context.user_id

    profile_namespace = ("counseling", user_id, "profile")
    episode_namespace = ("counseling", user_id, "episodes")

    memories = []

    # key로 정확히 조회
    for key in ["work_context", "counseling_goal", "support_preference"]:
        item = runtime.store.get(profile_namespace, key)

        if item:
            memories.append(item.value["text"])

    # 현재 질문과 관련된 기억 검색
    hits = runtime.store.search(
        episode_namespace,
        query=state["messages"][-1].text,
        filter={"speaker": "user"},
        limit=2,
    )

    memories += [item.value["text"] for item in hits]

    return {"recalled_memories": memories}
  • runtime.context : 실행할 때 전달한 사용자 정보
  • runtime.context.user_id : 사용자별 기억 구분
  • runtime.store : Store 접근
  • get() : 정확한 기억 조회
  • search() : 관련 기억 검색
  1. Edge 연결
    • 기억 조회 Node → 답변 Node
    • 조회한 기억을 State에 넣고 다음 Node에서 사용
  2. 답변

Mem0

Mem0 : 대화에서 장기기억을 LLM으로 추출 → 저장 → 검색하는 라이브러리

  1. Memory 설정

memory = Memory.from_config(mem0_config)

  • add : 기억 추출 + 저장

memory.add(message, user_id=user_id, prompt=profile_policy, metadata={"memory_space": "profile"})

  • get_all / search : 기억 조회
    • profile → 항상 조회
      memory.get_all(filters={"user_id": user_id, "memory_space": "profile"}, top_k=50)
    • episodes → 현재 질문과 관련된 기억 검색
      memory.search(question, filters={"user_id": user_id, "memory_space": "episodes"}, top_k=3)
    • get_all() → 조건에 맞는 기억 전체 조회
    • search() → 질문과 의미적으로 관련된 기억 검색
    • filters → 사용자와 기억 공간 제한
  1. Node 생성
    1. profile = memory.get_all(...) # 항상 필요한 정보 found = memory.search(...) # 관련 과거 경험
  2. Edge 연결
  • 기억 수정 / 삭제
    • get_all() / search() → 여러 기억 조회·검색
    • memory.get(memory_id) → ID로 정확히 하나 조회
    • memory.update(memory_id=memory_id, text="수정된 기억") → 기존 기억 수정
    • memory.delete(memory_id) → 기존 기억 삭제
    • memory.history(memory_id) → 변경 이력 확인

infer=False→ LLM 추출 없이 이미 확정한 문장을 그대로 저장할 수 있다.


Store vs Mem0

LangGraph StoreMem0
기억을 직접 정리해서 저장LLM이 대화에서 기억 추출
put()add()
namespace / key / value 직접 지정user_id / metadata / id 사용
get() 정확 조회get(), get_all() 조회
search() 의미 검색search() 의미 검색
갱신 로직 직접 설계update/delete 제공

장기 기억 관리 방식

  1. Store
  2. Mem0 (실무)
  3. LLM Wiki (실무)
    1. 사용자별 장기기억을 저장하기 위한 용도 X
      개인 1명, 팀별 작업을 잘 수행하기위한 장기기억 방식

컨텍스트 엔지니어링(대화 요약·메시지 트리밍·토큰 예산)

Context : LLM에게 넣어주는 정보

→ 시스템 프롬프트 + 대화내역 + 장기기억 + Tool 정보 + 출력 스키마 등

Context Engineering

: LLM에게 무엇을, 얼마나 넣을지 설계해서 답변 품질을 높이는 것

  1. 필요한 정보 선택
    • 현재 질문, 시스템 지시, 장기 기억, 대화 요약, 최근 대화
    • 많이 넣는다고 무조건 좋은 것 X
  2. 검색 (Search)
    • 현재 질문과 관련된 장기기억 선택
    • 핵심 기억 → get()
    • 관련 경험 → search()
  3. 트리밍 (Trimming)
    • trim_messages
    • 입력 한도에 맞게 메시지 일부 선택
    • strategy="last" → 최근 대화 우선
    • State 원본은 유지, 이번 모델 입력만 줄임
  4. 요약 (Summarization)
    • 대화가 길어지면 오래된 대화를 요약
    • 최근 메시지는 원문 유지
    • 기존 요약 + 오래된 대화 → 새로운 요약
    • 최신 변경사항·기존 합의·제외 조건 등을 유지
  5. 토큰 예산 (Token Budget)
    • 모델 입력에 사용할 분량을 정함
    • 전체 입력 예산 - 지시/기억/요약 = 최근 대화에 쓸 예산
    • count_tokens_approximately() → 근사 토큰 계산

전체 흐름:
사용자 질문 → 필요한 장기기억 조회 → 대화가 길면 오래된 내용 요약 → 입력 예산 계산 → 최근 대화 trim → 지시 + 기억 + 요약 + 최근 대화 → LLM 답변

0개의 댓글