AISmarteasy – 시맨틱 커널 포크로 개발하기 5d – Worker – Memory – MemoryStore
llm의 태생적 한계로, llm 연동 애플리케이션이 llm이 가지고 있지 않은 데이터를 기억해 준다면 llm 입장에서는 큰 도움이다. Memory.
기억은 유지해야 되는 시간에 따라 단기 기억과 장기 기억으로 나뉜다. 기억해야 하는 데이터는 어딘가에 저장해야 한다. 시맨틱 커널은 기억해야 할 데이터는 MemoryRecord라도 하고, 저장소는 MemoryStore 라고 한다.
단기 기억은 필요할 때만 기억하고 잊어버리면 된다. 휘발성(volatile)이다. 단기 기억을 위한 메모리 저장소가 필요하다. 시맨틱 커널에서는 휘발성 저장소를 VolatileMemoryStore라고 한다.
llm 연동 ai 애플리케이션 데이터는 구조화될 필요 없이 자연어이면 된다. llm이 자연어를 임베딩 한 벡터를 사용하기 때문에 자연어이면 되는 게 아니고 더 정확 하게 는 자연어 벡터여야 한다.
장기 기억 데이터는 파일이나 데이터베이스로 저장된다. 장기 기억 저장소를 무엇으로 할지는 일반 데이터를 처리할 때처럼 해 볼 수 밖에 없다. 관계형 데이터베이스 등장 때와 같이, 대용량이면 데이터베이스를 사용하는 것으로 하자. llm 연동을 위해 벡터를 다루는 데이터베이스가 등장한다. 벡터 데이터베이스. 이미 벡터 데이터베이스는 여럿 등장했고, 우리는 파인콘을 권한다.
MemoryRecord는 text를 임베딩 한 vector가 관리되어야 할 값(vlaues)이다. llm 연동을 위해 기억해야 할 데이터는 벡터 값이다.
MemoryRecord
- vector, 시맨틱 커널에서는 values
임베딩 된 자연어 텍스트(text)를 알고 싶을 수 있다. 추가적으로 알고 싶은 데이터들이 있을 때 이들을 metadata로 묶자. 시맨틱 커널에서는 MemoryRecordMetadata라 한다.
MemoryRecordMetadata
-
- text
MemoryRecord
- vector
- metadata – MemoryRecordMetadata 타입
추가적으로 더 알고 싶은 것?
llm의 한계로 자주 지목되는 것이 환각이니, 데이터의 출처(source)를 알면 도움이 된다. 출처에 대한 설명(description)이 있으면 도움이 되겠다.
MemoryRecordMetadata
- source, 시맨틱 커널에서는 external source name
- description
데이터 생성 시점을 알면 도움이 더 될 수도 있다.
MemoryRecord
- id
- vector
- createdAt
- metadata
데이터 변경(갱신) 시점을 알면 더 더 도움이 되겠지. 실제 데이터를 삭제 하지 않고, 삭제 시점만 관리하기를 원할 수 도 있다. 여기서 부터는 임베딩 레코드 설계로 분리해서 다루자.
MemoryRecord와 MemoryRecordMetadata는 1:1이고, id를 키로 관리하기로 했으니 MemoryRecordMetadata도 id가 있어야 하고 MemoryRecord.id의 값과 같아야 한다.
임베딩 되지 않는 데이터와 관련된 텍스트(text)가 있을 수 있다. description은 메타 데이터가 무엇인지 간략한 설명이고 텍스트는 실제 메타 데이터 내용이라고 보면 되겠다.
MemoryRecordMetadata
- id,
- source
- description
- text
추가적으로 더 알고 싶은 것이 있을 수 있다. 메타 데이터를 설계를 거쳐야 한다. 그 정도가 아니라면 더 많은 것들은 추가적인 메타 데이터(additional metadata)로 묶어 한 번에 다루자.
MemoryRecordMetadata
- id,
- source
- description
- text
- additional metadata – string
프롬프트에 프롬프트 엔지니어링이 등장했던 것처럼, 임베딩에도 임베딩 엔지니어링이 등장 해, 임베딩 분석 설계 부분이 전문화 될 수 있어 보인다. 물론 자연어가 비구조가 특징이니 설계가 있더라도 그리 커지지는 않을 것 같다.
VolatileMemoryStore 구현
단기 기억할 수 있도록 해야 한다 .
데이터 베이스 시스템에서 여러 데이터 베이스를 관리하는 것처럼 데이트들을 그룹 별 관리할 수 있도록 하자.
컬렉션들을 관리하고, 컬렉션 별 데이터들을 관리해야 한다. 키가 될 수 있는 id가 있으니 dictionary를 사용하자.
데이터들을 갖는 컬렉션을 생성, 삭제할 수 있어야 한다. 컬렉션 별 데이터들을 구할 수 있어야 한다.
컬렉션에 데이터 생성, 갱신, 삭제 가능하도록 해야 한다.
컬렉션에서 다루는 데이터는 벡터이고, 쿼리 결과는 쿼리와 가장 유사한 벡터다. 가장 유사한 벡터를 찾는 방법 중, 지금 가장 괜찮은 것은 cosine similarity다. .NET에서 System.Numerics.Tensors.TensorPrimitives클래스의 CosineSimilarity 메소드를 제공한다. 시맨틱 커널은 이것을 사용한다.