예제
Chroma — 벡터 유사도 검색 (서버·키 불필요)

실제로 실행 가능한 미니 프로젝트입니다. 받아서 Docker로 실행해 보세요.

2026년 6월 28일

Chroma — 벡터 유사도 검색 (서버·키 불필요)

아주 작은 Chroma 데모입니다. 문서 몇 개를 저장하면 Chroma가 내장 모델로 임베딩하고, 최근접 이웃 질의를 실행합니다. 장난감 문서를 직접 바꾸면 RAG 검색기가 됩니다. API 키가 필요 없습니다.

Docker로 실행

cd samples/chroma_1
docker build -t aas-chroma .
docker run --rm aas-chroma "tell me about young cats"

첫 질의 때 Chroma의 내장 임베딩 모델(all-MiniLM-L6-v2, 약 80 MB)을 받으므로 한 번은 인터넷이 필요합니다.

Docker로 실행 (DooD를 쓰는 devcontainer에서)

호스트 Docker 데몬과 통신하는 dev container(Docker-outside-of-Docker)에서는 attach된 docker run이 실제로 실행했는데도 출력을 안 보여줄 수 있습니다. 실시간 attach 스트림이 VM 경계에서 출력을 흘려버리기 때문이니, detached로 실행하고 로그로 확인하세요:

cd samples/chroma_1
docker build -t aas-chroma .
docker logs -f "$(docker run -d aas-chroma "tell me about young cats")"

로컬에서 실행

cd samples/chroma_1
pip install -r requirements.txt
python app.py "tell me about young cats"

실행 결과

임베딩은 고정 모델 + 입력이라 결정적입니다. 그래서 순위는 매번 같고, 첫 실행에서만 모델을 내려받습니다.

nearest to 'tell me about young cats' by distance:
  kitten     0.8413
  cat        1.0233
  rocket     1.8533

파일

app.py
"""Chroma: vector similarity search with no server and no API key.

Stores a few documents in an in-memory Chroma collection (Chroma embeds them
with a built-in model), then runs a nearest-neighbour query. Swap the toy docs
for your own and it is a RAG retriever.

Run:
    docker build -t aas-chroma .
    docker run --rm aas-chroma "tell me about young cats"
"""

import sys

import chromadb

DOCS = {
    "cat": "Cats are independent pets that purr and chase laser pointers.",
    "kitten": "A kitten is a young cat that loves to play and nap.",
    "airplane": "An airplane is a powered flying vehicle with fixed wings.",
    "rocket": "A rocket is propelled by ejecting exhaust gas at high speed.",
}


def main() -> None:
    query = " ".join(sys.argv[1:]) or "tell me about young cats"

    client = chromadb.Client()  # in-memory; built-in embedding model
    col = client.create_collection("docs")
    col.add(ids=list(DOCS), documents=list(DOCS.values()))

    res = col.query(query_texts=[query], n_results=3)

    print(f"nearest to {query!r} by distance:")
    for label, dist in zip(res["ids"][0], res["distances"][0]):
        print(f"  {label:10s} {dist:.4f}")


if __name__ == "__main__":
    main()