~/ / AI 기사 / VPS에서 로컬 LLM / Ollama로 임베딩 만들기: 검색과 RAG의 기본

Ollama로 임베딩 만들기: 검색과 RAG의 기본

의미로 문장을 찾는 검색도, 채팅 모델이 내 문서를 바탕으로 답하는 RAG도 임베딩에서 시작합니다. Ollama는 채팅 모델을 돌리는 서버에서 그대로 임베딩을 만들 수 있습니다. 이 글에서는 요청 방법, Ollama 라이브러리에 올라와 있는 모델, 결과를 바꾸는 설정, 벡터를 비교하는 방법을 Ollama 문서와 라이브러리 페이지에 적힌 내용만으로 다룹니다. 이 페이지의 도구 두 개로 각 단계를 브라우저에서 직접 해 볼 수 있습니다.

게시: · 읽는 데 약 6분 · Ollama 문서와 라이브러리 페이지를 2026-11-04에 확인한 내용입니다. 모델과 필드는 바뀔 수 있으니, 의존하기 전에 최신 페이지를 확인하세요.

임베딩이란

Ollama의 embeddings 페이지에 따르면, 임베딩은 텍스트를 숫자 벡터로 바꾼 것이며, 벡터 데이터베이스에 저장하거나 코사인 유사도로 검색하거나 RAG 파이프라인에서 쓸 수 있습니다. 벡터의 길이는 모델에 따라 달라지며, 이 페이지는 보통 384~1024차원이라고 합니다.

검색할 때는 질문을 같은 모델로 임베딩한 뒤, 저장된 벡터 중에서 질문과 가장 비슷한 것을 찾습니다.

/api/embed로 임베딩 만들기

엔드포인트는 POST /api/embed입니다. 요청에는 model과 input이 필요하고, input은 문자열 하나일 수도 있고 문자열 배열일 수도 있습니다. 배열을 보내면 응답의 embeddings 필드에 문자열마다 벡터가 하나씩 같은 순서로 담겨 오므로, 여러 문단도 요청 한 번이면 됩니다.

문서에는 명령줄 예시도 있습니다. ollama run embeddinggemma "Hello world"를 실행하면 벡터가 JSON 배열로 출력되고, echo로 텍스트를 파이프로 넘길 수도 있습니다.

필드API 레퍼런스의 설명
model필수. 모델 이름.
input필수. 텍스트 하나 또는 텍스트 배열.
truncate기본값은 true이며, 컨텍스트 윈도우를 넘는 입력은 잘립니다. false이면 오류가 반환됩니다.
dimensions임베딩을 생성할 차원 수.
keep_alive모델을 로드된 상태로 유지하는 시간.
options컨텍스트 길이를 정하는 num_ctx 같은 실행 옵션.

Ollama에는 OpenAI 호환 엔드포인트인 /v1/embeddings도 있습니다. 문서에는 model, 문자열 또는 문자열 배열인 input, encoding format, dimensions는 지원하고, 토큰 배열과 user는 지원하지 않는다고 나와 있습니다.

Ollama 라이브러리의 임베딩 모델

Ollama 라이브러리에는 embedding 카테고리가 있습니다. 아래 표는 거기에 올라와 있는 모델 중 여섯 개를 골라, 각 모델의 태그 페이지가 latest 태그에 대해 알려 주는 크기와 컨텍스트 윈도우를 정리한 것입니다. 여섯 개 중 네 개는 1GB 미만입니다.

모델latest 태그의 크기컨텍스트 윈도우
all-minilm46MB512
nomic-embed-text274MB2K
embeddinggemma622MB2K
mxbai-embed-large670MB512
bge-m31.2GB8K
qwen3-embedding4.7GB40K

다른 태그는 크기가 다릅니다. 예를 들어 라이브러리에는 qwen3-embedding:0.6b가 639MB에 컨텍스트 윈도우 32K로, embeddinggemma:300m-qat-q4_0이 239MB로 올라와 있습니다. 이 모델들의 품질은 비교하지 않았으며, 라이브러리 페이지에도 순위는 없습니다. Ollama 0.40.11에서 all-minilm을 시험해 보니 ollama show에는 컨텍스트 길이 512와 파라미터 num_ctx 256이 표시되었고, 긴 입력은 256 토큰에서 잘렸습니다. 사용하는 모델을 ollama show로 확인하세요.

긴 입력은 오류 없이 잘립니다

컨텍스트 윈도우는 토큰 단위로 셉니다. truncate의 기본값이 true이기 때문에, 모델의 컨텍스트 윈도우보다 긴 텍스트는 짧게 잘린 채로 오류 없이 벡터가 반환됩니다. 긴 문서를 입력 하나로 보내면 이렇게 끝부분을 잃을 수 있습니다.

도움이 되는 방법은 두 가지입니다. 하나는 긴 문서를 더 작은 청크로 나누어 청크마다 임베딩하는 것으로, 검색이 질문에 답이 되는 부분만 돌려줄 수 있게 되는 효과도 있습니다. 다른 하나는 truncate를 false로 해서 보내는 것입니다. 그러면 청크가 여전히 너무 길 때 Ollama가 잘라 버리는 대신 오류를 반환합니다.

아래의 청크 분할 도구는 텍스트를 문단, 줄, 문장, 공백 순서로 나누고 겹침(오버랩)을 두어, 모든 청크를 담은 /api/embed 요청을 하나 만들어 줍니다. 모델마다 토크나이저가 다르기 때문에 토큰이 아니라 글자 수로 셉니다. 컨텍스트 윈도우보다 여유를 두세요.

직접 해 보기: RAG Text Chunker

길이는 글자 수입니다. 모델의 컨텍스트 윈도우는 토큰 단위이고 텍스트가 몇 토큰이 되는지는 모델에 따라 다르므로, 여유를 두세요.

curl 명령

Ollama에 접근할 수 있는 컴퓨터에서 실행하세요. 응답에는 청크마다 벡터가 하나씩 이 순서로 들어 있습니다.

curl http://localhost:11434/api/embed -d '{
  "model": "embeddinggemma",
  "input": [
    "Embeddings turn text into numeric vectors. You can store them in a vector database and search them with cosine similarity, or use them in a RAG pipeline.\n\nThe length of each vector depends on the embedding model. Use the same model when you index your documents and when you embed a question.\n\n",
    "Ollama'\''s /api/embed endpoint takes a single string or an array of strings. By default, input that is longer than the model'\''s context window is truncated. Set truncate to false to get an error instead.\n\n",
    "Split long documents into smaller chunks before you embed them, so that each chunk fits in the context window and a search can return the part that answers the question."
  ],
  "truncate": false
}'

청크

청크 3개. 가장 긴 청크는 294자입니다.

  1. #0 · 294자 · 오프셋 0에서 시작

    Embeddings turn text into numeric vectors. You can store them in a vector database and search them with cosine similarity, or use them in a RAG pipeline. The length of each vector depends on the embedding model. Use the same model when you index your documents and when you embed a question.

  2. #1 · 202자 · 오프셋 294에서 시작

    Ollama's /api/embed endpoint takes a single string or an array of strings. By default, input that is longer than the model's context window is truncated. Set truncate to false to get an error instead.

  3. #2 · 169자 · 오프셋 496에서 시작

    Split long documents into smaller chunks before you embed them, so that each chunk fits in the context window and a search can return the part that answers the question.

/api/embed용 JSON 본문

{
  "model": "embeddinggemma",
  "input": [
    "Embeddings turn text into numeric vectors. You can store them in a vector database and search them with cosine similarity, or use them in a RAG pipeline.\n\nThe length of each vector depends on the embedding model. Use the same model when you index your documents and when you embed a question.\n\n",
    "Ollama's /api/embed endpoint takes a single string or an array of strings. By default, input that is longer than the model's context window is truncated. Set truncate to false to get an error instead.\n\n",
    "Split long documents into smaller chunks before you embed them, so that each chunk fits in the context window and a search can return the part that answers the question."
  ],
  "truncate": false
}

/api/embed의 요청 필드는 Ollama API 레퍼런스에 나온 대로이며, 2026-11-04에 확인했습니다. Ollama API: Generate embeddings

모든 작업은 브라우저에서 이루어집니다. 도구는 명령만 작성하며 아무것도 전송하지 않습니다.

인덱싱과 검색에는 같은 모델을 쓰세요

embeddings 페이지는 인덱싱할 때와 질의할 때 같은 임베딩 모델을 쓰라고 합니다. 벡터의 길이는 모델에 따라 달라지므로, 서로 다른 모델의 벡터는 차원 수조차 같지 않을 수 있습니다.

dimensions도 마찬가지입니다. 문서를 인덱싱할 때 지정했다면, 질문을 임베딩할 때도 같은 값을 지정하세요. 모델이나 이 설정을 바꾸면 저장해 둔 문서를 다시 임베딩해야 합니다.

벡터 비교하기

문서는 대부분의 시맨틱 검색에 코사인 유사도를 권하며, /api/embed가 L2 정규화된 단위 길이 벡터를 반환한다고 설명합니다. 단위 길이 벡터에서는 코사인 유사도와 내적이 같은 숫자이므로, 벡터 데이터베이스를 둘 중 어느 쪽으로 설정해도 결과 순위는 같습니다.

무언가를 만들기 전에 내 텍스트로 모델을 확인하려면, 질문을 맨 앞에 두고 질문과 문단 몇 개를 요청 하나로 임베딩하세요. 그 응답을 아래에 붙여 넣으면 질문과의 코사인 유사도로 문단 순위가 매겨지고, 모든 벡터가 단위 길이인지, 차원 수가 같은지도 표시됩니다.

직접 해 보기: Embedding Similarity Calculator

예시는 읽기 쉽도록 4차원의 가상 단위 길이 벡터를 사용합니다. 실제 임베딩은 수백~수천 차원입니다.

Ollama /api/embed 응답(으)로 읽었습니다: 4차원 벡터 4개. 모든 벡터의 길이가 1이므로 코사인 유사도와 내적이 같습니다.

코사인 유사도 순위

#0 How do I keep a model loaded in Ollama?와(과) 비교한 결과입니다. 값이 클수록 더 비슷합니다.

순위텍스트코사인내적거리
1#1 keep_alive controls how long the model stays in memory0.99620.99620.0876
2#2 Protect Ollama with nginx and a password0.40370.40371.0921
3#3 Tomorrow's weather forecast0.01000.01001.4071

코사인 유사도 행렬

각 칸은 행의 벡터와 열의 벡터를 비교한 값입니다.

#0#1#2#3
#01.0000.9960.4040.010
#10.9961.0000.475-0.005
#20.4040.4751.000-0.377
#30.010-0.005-0.3771.000

벡터

텍스트차원길이(L2 노름)단위 길이
#0 How do I keep a model loaded in Ollama?41.000000예
#1 keep_alive controls how long the model stays in memory41.000000예
#2 Protect Ollama with nginx and a password41.000001예
#3 Tomorrow's weather forecast41.000000예

Ollama의 embeddings 문서와 API 레퍼런스를 바탕으로 2026-11-04에 확인했습니다. Ollama: Embeddings / Ollama API: Generate embeddings

모든 계산은 브라우저에서 이루어집니다. 어디로도 전송되지 않습니다.

작은 서버의 메모리

임베딩 모델도 다른 모델과 똑같이 로드됩니다. Ollama FAQ에 따르면, 메모리에 들어갈 경우 동시에 로드할 수 있는 모델 수인 OLLAMA_MAX_LOADED_MODELS의 기본값은 GPU 수의 3배이고, CPU 추론이면 3입니다. 그래서 메모리가 허락하면 채팅 모델과 임베딩 모델을 함께 로드해 둘 수 있습니다.

Ollama 메모리 감시에 관한 글에서 ollama ps, keep_alive 등 무엇이 메모리에 남을지 정하는 설정을 설명합니다.

출처

다음에 읽기