본문 바로가기
C.W.K.
Lesson 03 of 07 · published

피파의 기억 검색은 옆 맥에서 돌아

~13 min · fleet, embeddings, retrieval, omlx, provenance, measured

Level 0스펙 시트 훑는 사람
0 XP0/91 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete
"모든 메시지와 모든 금고 노트는 office의 저장소에 있는 숫자 1,024개고, server에서 계산됐어. 저장소 자체의 이름이 어느 모델이 어디서 만들었는지 말해."

색인, 세어 보기

피파의 기억 검색은 벡터 색인이야. 피파가 주고받은 모든 메시지와 금고의 모든 노트를 bge-m3 모델이 부동소수점 숫자 1,024개로 임베딩해서 office에 저장하고, 코사인 거리로 질의하고 리랭크해. 2026-09-15에 직접, 읽기 전용으로 읽으니 저장소는 컬렉션 둘에 메시지 임베딩 15,697개와 금고 임베딩 1,360개를 들고 있고, 그 이름이 출처 전체를 실어. messages__omlx__bge-m3-mlx-fp16__1024: 제공자, 모델, 정밀도, 차원. 다른 컬렉션 둘, 맨 이름 messages와 vault는 0행이야. Ollama 시절의 이름이고, 코드 리포지토리 밖에서 스크립트가 돌며 기본값을 요청할 때마다 비어 있는 채로 다시 나타나. 이 집은 한 번 지웠고 그것들은 돌아와. 읽기 전용 세기만이 드러내는 종류의 사실이야.

왜 옮겼나

검색은 처음엔 Ollama에서 돌았어. 이 퀘스트의 계획 관문에서 이 집이 밝힌 이동의 사연: Ollama의 변경이 임베딩 모델의 동작을 바꿨고, 검색은 모델을 따라가야 했고, 임베딩 제공자는 2026년 6월에 허브의 MLX 서버로 옮겼고 리랭킹이 뒤따랐어. MLX 서버는 그 뒤로 사고 없이 돌았고, 그 SSD 캐싱이 일부를 Ollama보다 빠르게 만들어. 이 퀘스트는 코드를 확인했어. 임베딩 서비스는 두 제공자를 지원하고, 리랭커는 MLX 것만 지원하고, 컬렉션 이름은 제공자, 모델, 차원으로 만들어져. 한 런타임이 임베딩한 저장소가 다른 런타임의 숫자로 질의되는 일이 절대 없도록 정확히 그러려고. Ollama 레슨의 경고를 오래가게 만든 거야. 밑에서 움직이는 런타임은 벡터의 의미를 움직일 수 있고, 자기 런타임을 기록하지 않는 색인은 그걸 알아챌 수 없어.

캐싱 주장의 어느 절반이 쓰이나

허브 레슨의 카운터가 이야기의 마지막 절반에 대한 증거야. 이 집이 말하는 MLX 서버의 이점은 MLX 쪽 SSD 캐싱이야. 반복되는 접두사의 KV 블록을 다시 계산하는 대신 디스크에서 다시 불러오는 것. 생성 기능이야. 긴 시스템 프롬프트나 공유 문서가 디코드 전에 거듭 프리필될 때 값을 해. 허브의 카운터는 143,626 요청에 완성 토큰 0과 0바이트의 SSD 캐시 디렉터리를 보여 줘. 가족이 거기 주는 부하는 순수 임베딩과 리랭킹이고, 재사용할 접두사가 없어. 그러니 양쪽 절반이 다 참이고 하나만 쓰이고 있어. 서버는 가족이 주는 워크로드에서 몇 달째 문제없이 돌았고, 대안보다 빠르게 만들 캐싱은 아직 싣지 않는 워크로드에 속해. 기억 검색은 집 서비스로서의 물리 트랙 프리필 단계야. 허브의 코어 80개에서 연산, 선 너머로 돌아오는 숫자 1,024개, 자기 제작자 이름을 붙인 컨트롤 플레인의 저장소.

Code

search_index.py — 읽기 전용으로 센 기억 저장소, 이름에 출처를 담아·python
#!/usr/bin/env python3
"""Pippa's memory search, counted: the vector store on the control plane, read-only.
Collection names carry provider, model and dimension, so the index states its own
provenance. Path from the environment; opened read-only with query_only."""
import os, sqlite3
db = os.environ["PIPPA_CHROMA"]                                     # the store's sqlite file
con = sqlite3.connect(f"file:{db}?mode=ro", uri=True)
con.execute("PRAGMA query_only=ON")
for name, n in con.execute("select c.name, count(e.id) from collections c left join segments s on s.collection=c.id "
                           "left join embeddings e on e.segment_id=s.id group by c.name"):
    print(f"{name:44} {n:7d}")
# office, 2026-09-15:
# messages                                           0     <- the Ollama-era bare name, recreated empty by a script run outside the repo
# messages__omlx__bge-m3-mlx-fp16__1024          15697     <- provider omlx, model bge-m3 fp16, 1024 dimensions
# vault                                              0
# vault__omlx__bge-m3-mlx-fp16__1024              1360

External links

Exercise

네가 의존하는 아무 검색 뒤의 벡터 저장소를 찾아 읽기 전용으로 열고 컬렉션을 세어. 각각을 만든 모델, 정밀도, 차원을 카드에 적어. 이름에 있으면 이름에서, 없으면 코드에서. 그리고 오늘 질의를 계산하는 런타임이 저장된 벡터를 계산한 그 런타임인지.
Hint
이름에 출처가 없으면 차원을 봐. 1,024는 bge-m3 것이고 다른 모델은 달라. 불일치는 자신 있게 헛소리를 돌려주는 검색이야. 저장소에 맨 이름의 빈 컬렉션이 있으면 뭔가가 기본값을 부르고 있는 거야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.