약 5분 만에 Ollama에 지속성 메모리(Persistent memory) 추가하기
요약
Ollama의 무상태(stateless) 특성을 보완하기 위해 Sieve 프록시를 사용하여 지속성 메모리를 추가하는 방법을 설명합니다. 클라이언트 코드 수정 없이 프록시 레이어에서 암호화된 메모리를 관리하여 컨텍스트 비용을 줄이고 모델의 환각을 방지합니다.
핵심 포인트
- Ollama의 세션 종료 시 데이터 휘발 문제 해결
- 프록시 방식을 통한 클라이언트 코드 변경 없는 메모리 구현
- 컨텍스트 페이로드 증가로 인한 성능 저하 및 비용 방지
- 암호화된 로컬 저장소를 통한 장기 기억 유지
Sieve 블로그에 처음 게시되었습니다. Sieve는 오픈 소스 (Apache 2.0) 컨텍스트 감소 (context-reduction) 프록시이며, 제가 개발하고 있습니다. 이것은 홍보가 아닌 가이드입니다. 이 단계들은 어떤 Ollama 설정에서도 작동합니다.
Ollama는 빠르고, 프라이빗하며, 완전히 상태가 없는 (stateless) 로컬 LLM 엔드포인트를 제공합니다. 채팅을 종료하면 모델에게 말한 모든 것이 사라집니다. 채팅을 계속 열어두면, 컨텍스트 윈도우 (context window)가 가득 찰 때까지 매 턴마다 점점 커지는 히스토리를 다시 전송하게 됩니다. 로컬 모델에게 한 번도 말한 적 없는 것에 대해 물어보면 — 모델에 따라 다르겠지만 — 단순히 이야기를 지어낼 수도 있습니다.
이 가이드는 단 하나의 URL 외에는 클라이언트 코드를 변경하지 않고도, Sieve를 사용하여 모든 Ollama 설정에 지속적이고 암호화된 메모리 (persistent, encrypted memory)를 추가합니다.
문제의 형태
로컬 모델을 대상으로 에이전트 (agents)나 장기적인 채팅을 실행할 때 세 가지 별개의 불편함이 나타나며, 이들은 공통된 근원을 가지고 있습니다.
세션이 종료되면 아무것도 남지 않습니다. 월요일에 어시스턴트에게 당신이 Python을 선호하고 배포 대상이 Raspberry Pi라고 말해도, 화요일이 되면 모델은 둘 다 알지 못합니다. 모델은 상태 (state)를 가지고 있지 않으며, 애플리케이션이 매번 모든 것을 전달해야 합니다.
페이로드 (payload)가 계속 커지기만 합니다. 표준적인 해결책은 히스토리를 다시 전송하는 것입니다: 시스템 프롬프트 (system prompt), 도구 스키마 (tool schemas), 이전의 모든 턴을 매 요청마다 보냅니다. 저는 The hidden cost of context에서 이 패턴의 결과를 측정했습니다. 요약하자면, 턴당 비용은 대화 길이에 따라 증가하며, 로컬 하드웨어에서는 이러한 증가가 초당 토큰 수 (tokens-per-second)의 감소로 이어집니다.
정보의 부재가 허구로 이어집니다. 질문이 당신이 보낸 컨텍스트 범위를 벗어나면, 특히 작은 모델들은 어떻게든 답변을 하려는 경향이 있습니다. 동료의 이름을 들어본 적이 없는 모델은 종종 이름을 지어내곤 합니다.
공통적인 근본 원인은 엔드포인트(endpoint)가 상태를 유지하지 않는 무상태(stateless) 방식이며, 메모리의 부담이 그 앞에 위치한 무엇인가에 전가된다는 점입니다. 대부분의 메모리 프레임워크는 SDK를 채택하고 사용자가 직접 add()/search()를 호출하도록 요구합니다. 여기서의 접근 방식은 다릅니다. 메모리를 트래픽 경로(traffic path) 안에 배치하여 클라이언트가 변경되지 않은 상태를 유지하도록 합니다. 제가 왜 프록시(proxy) 형태를 선호하는지에 대해서는 Why Sieve에 정리해 두었습니다.
완성된 결과물
사용자 클라이언트 ──► Sieve (127.0.0.1:11435) ──► Ollama (127.0.0.1:11434)
│
└── ~/.sieve/memory.db에 저장된 암호화된 저장소
Sieve는 Ollama의 네이티브 /api/chat뿐만 아니라 OpenAI 호환 /v1/chat/completions도 지원하므로, Ollama와 통신할 수 있는 것이라면 무엇이든 Sieve와 통신할 수 있습니다. 매 턴마다 Sieve는 나가는 페이로드(payload)에서 반복되는 지침, 도구 스키마(tool schemas), 오래된 기록을 제거합니다. 그리고 대화로부터 지속적인 사실을 학습하며, 이후의 턴에서 실제로 필요한 경우 관련 정보를 다시 주입합니다. 응답은 클라이언트에 변경 없이 그대로 전달됩니다.
1단계 — Sieve 설치
Python 3.11 이상 버전과 실행 중인 Ollama가 필요합니다. 권장되는 설치 도구는 pipx입니다.
pipx install llm-sieve
sieve --version # sieve, 버전 1.0.0 이상
그 다음 가이드 설치를 실행합니다:
sieve-install
Ollama가 127.0.0.1:11434에서 실행 중이라면, 설치 프로그램이 이를 자동으로 감지하여 이미 다운로드(pull)된 모델들을 보여줍니다. 약 50MB 크기의 임베딩 모델(embedding model)을 (최초 1회) 다운로드하고, 암호화된 저장소를 생성하며, 재부팅 시 자동 시작 옵션을 포함하여 프록시를 시작할지 제안합니다. 스크립트 방식의 무응답(no-prompts) 설치를 원한다면 다음과 같이 실행하세요:
sieve-install --no-input \
--provider http://127.0.0.1:11434 \
--model qwen3.5:9b
2단계 — URL 변경하기
Sieve는 Ollama의 11434 포트보다 의도적으로 하나 높은 11435 포트에서 대기합니다. 클라이언트가 Ollama를 가리키는 곳이 어디든, 대신 Sieve를 가리키도록 설정하세요.
Ollama 네이티브 클라이언트:
export OLLAMA_HOST=http://127.0.0.1:11435
OpenAI 호환 클라이언트:
client = OpenAI(
base_url="http://127.0.0.1:11435/v1", # 기존: http://127.0.0.1:11434/v1
api_key="not-used-by-sieve", # 여전히 상위 서버로 전달됨
...
또는 간단히 curl 사용:
curl http://127.0.0.1:11435/api/chat \
-H 'Content-Type: application/json' \
-d '{
...
모델 이름, 요청 형태(request shapes), 응답 형식(response formats), 스트리밍(streaming) — 이 모든 것이 변경되지 않았습니다. 클라이언트는 Sieve가 존재하는지조차 알지 못합니다.
3단계 — 작동 여부 확인하기
두 가지 내장 명령어가 있으며, 둘 다 샌드박스(sandboxed) 환경에서 실행됩니다 (실제 저장소에는 절대 영향을 주지 않습니다):
sieve demo
짧게 스크립트된 대화를 실행합니다: 정체성을 가진 개체가 자신을 소개하고, 사실(facts)을 공유하며, 이를 다시 물어본 뒤, 한 번도 언급되지 않은 인물에 대한 질문으로 대화를 마칩니다. 확인해야 할 사항은 다음과 같습니다: 입력된 사실에 대한 회상(recall) 성공 여부, 그리고 함정 질문에 대해 허구(fabrication)를 만들어내지 않고 거절(refusal) 하는지 여부입니다.
sieve benchmark
동일한 15개의 메시지를 모델에 직접 보내는 방식과 Sieve를 통해 보내는 방식 모두에 전송한 뒤, 차이(delta) 테이블을 출력합니다: 입력(in) 대 출력(out) 토큰 수, 학습된 사실, 응답 시간, 그리고 함정 질문에 대한 판결을 보여줍니다. 하드웨어 성능에 따라 5분에서 10분 정도 소요되며, 결과 수치는 제가 아닌 여러분의 환경에서 직접 확인하게 됩니다.
작동 과정 관찰하기
Sieve가 처리하는 모든 응답에는 진단 헤더(diagnostic headers)가 포함되어 있으므로, 프록시의 동작을 막연히 믿을 필요가 없습니다:
| 헤더 | 설명 |
|---|---|
X-Sieve-Inbound-Tokens | 트리밍(trim) 전의 페이로드(payload) 크기 |
| ... |
가장 먼저 살펴봐야 할 것은 인바운드(inbound)/아웃바운드(outbound) 쌍입니다. 이는
모든 데이터는 사용자의 기기에 머뭅니다. 사실(facts), 엔티티(entities), 에피소드(episodes)는 ~/.sieve/memory.db에 SQLCipher로 암호화된 SQLite 데이터베이스 형태로 저장되며, 키 파일(keyfile)도 그 옆에 함께 보관됩니다. 클라우드 구성 요소, 계정, 텔레메트리(telemetry)는 전혀 없습니다. 프록시(proxy)는 정확히 하나의 원격 파티와 통신하며, 이는 사용자가 설정한 LLM 엔드포인트(endpoint)뿐입니다. 만약 해당 엔드포인트가 localhost의 Ollama라면, 데이터는 기기 외부로 전혀 나가지 않습니다.
저장소는 패키지가 아닌 사용자의 소유입니다. pipx upgrade llm-sieve를 통한 업그레이드는 ~/.sieve/ 디렉토리에 전혀 영향을 주지 않으며, 사용자 데이터를 삭제하는 유일한 명령은 sieve uninstall --hard뿐인데, 이 명령은 실행 전 DELETE를 먼저 입력하도록 요구합니다.
솔직한 주의사항
소형 모델은 여전히 소형 모델의 문제를 가집니다. Sieve는 모델 앞에 올바른 사실을 배치하고, 게이트(gate) 역할을 하는 턴에서 정보의 부재가 허구의 생성(invention)으로 이어지는 것을 거부할 수 있지만, 모호한 상황에서의 13B 모델은 여전히 13B 모델일 뿐입니다. 데모의 함정 턴(trap turn)은 정직한 점검 도구입니다. 실제로 사용할 모델을 대상으로 직접 실행해 보세요. 부재 상황 처리(absence-handling) 능력이 빛을 발하는 곳은 8B 이상의 모델 클래스입니다.
콜드 스타트(Cold start)는 실재합니다. 아무것도 들어있지 않은 메모리 레이어는 아직 토큰을 절약해 주지 못합니다. 차이점(deltas)이 흥미로워지기 전까지는 몇 번의 턴(turns)을 위한 예산을 확보해 두세요.
포트 충돌(Port collisions)이 발생할 수 있습니다. 만약 11435 포트를 이미 다른 프로세스가 사용 중이라면, sieve start --port 11436을 실행하고 클라이언트를 해당 포트로 지정하세요.
5분 요약
pipx install llm-sieve
sieve-install # Ollama를 자동 감지하며, 이후 안내를 따릅니다
export OLLAMA_HOST=http://127.0.0.1:11435
...
URL 하나가 바뀌었을 뿐, SDK를 채택하거나 클라이언트 코드를 다시 작성할 필요도 없습니다. 이제 당신의 Ollama 모델은 세션 사이에서 당신이 누구인지 잊어버리지 않습니다.
Sieve는 Apache 2.0 라이선스 하에 오픈 소스로 제공됩니다: github.com/llmsieve/llm-sieve.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기