POMA와 Qdrant: 구조를 보존하는 검색

POMA와 Qdrant: 구조를 보존하는 검색 (poma)

POMA는 문서 청킹 엔진이에요. 파일을 구조를 인식한 청크셋(chunkset)으로 바꿔서, 최소한의 보일러플레이트 코드로 Qdrant에 보내는 데 특화되어 있어요. Qdrant는 여기서 벡터 검색 엔진 역할을 하고요. 둘을 합치면 문서 처리부터 구조 보존 검색까지 하나의 흐름으로 이어져요.

출처: Qdrant 공식 문서 — poma

이 가이드에서는 POMA AI의 Qdrant SDK 흐름을 따라가 볼게요. 문서를 처리하고, 청크셋을 upsert 하고, 구조를 보존하는 cheatsheet를 검색하고, 마지막에 고급 제어 지점이 어디인지 짚어 볼게요.

준비물 (Prerequisites)

  • Python 3.10 이상
  • POMA API 키
  • Qdrant 클러스터 URL + API 키 (클라우드 사용 시)

1. API 키 얻기

POMA API 키

  1. https://app.poma-ai.com/에 접속해요.
  2. 회원가입 또는 로그인해요.
  3. 왼쪽 내비게이션에서 API Keys를 열어요.
  4. 키를 복사해서 POMA_API_KEY로 export 해요.

Qdrant 클러스터 API 키

클러스터 생성 시 또는 세분화된(fine-grained) API 키를 만들 때 확인할 수 있는데요, 자세한 내용은 인증 문서를 참고해요.

환경 변수 설정

POMA_API_KEY="your_poma_api_key"
QDRANT_URL="https://<cluster>.<region>.qdrant.io"
QDRANT_API_KEY="your_qdrant_api_key"

2. 의존성 설치

pip install "poma[qdrant]"

3. import

import os
from poma import Poma
from qdrant_client.http import models as qmodels
from poma.integrations.qdrant.qdrant_poma import PomaQdrant

다음 단계에서 로컬 문서 경로(예: "./docs/your_file.pdf")를 사용할 거예요. 링크된 Colab 노트북에 다운로드 가능한 샘플 파일이 포함되어 있어서 빠르게 테스트해 볼 수 있어요.

4. POMA로 파일 청킹하기

client = Poma(os.environ["POMA_API_KEY"])
job = client.start_chunk_file("./docs/your_file.pdf")
chunk_data = client.get_chunk_result(
    job["job_id"],
    show_progress=True,
    download_dir="./",
    filename="your_file.poma",
)

get_chunk_result(...)에서 쓰는 POMA 전용 옵션을 볼게요.

  • show_progress: 처리 중 작업 상태를 출력해요.
  • download_dir + filename: 반환된 아카이브를 .poma 파일로 저장하면서, 파싱된 chunk_data도 함께 돌려줘요.
  • 둘 다 생략하면 .poma 아카이브를 쓰지 않고 결과를 메모리에서만 받아요.

chunk_data는 구조화된 출력(chunkschunksets)을 담고 있고, 이게 다음 단계의 upsert_poma_points(...)에서 사용돼요.

이미 .poma 아카이브가 있다면 경로를 그대로 넘겨도 돼요.

chunk_data = "your_file.poma"

5. 청크셋을 Qdrant에 upsert 하기

QDRANT_COLLECTION_NAME = "cloud_hybrid"
DENSE_MODEL = "sentence-transformers/all-minilm-l6-v2"
SPARSE_MODEL = "Qdrant/bm25"
DENSE_OPTIONS = {"dimensions": 384}

poma_qdrant = PomaQdrant(
    url=os.environ["QDRANT_URL"],
    api_key=os.environ["QDRANT_API_KEY"],
    cloud_inference=True,
    timeout=120,
    collection_name=QDRANT_COLLECTION_NAME,
    dense_model=DENSE_MODEL,
    sparse_model=SPARSE_MODEL,
    dense_size=384,
    dense_options=DENSE_OPTIONS,
    auto_create_collection=True,
)
poma_qdrant.upsert_poma_points(chunk_data)

auto_create_collection=True일 때는 dense_size가 필수예요.

6. 구조 보존 cheatsheet 검색하기

cheatsheets = poma_qdrant.get_cheatsheets(
    query="Whats the positional embeddings frequency?",
    limit=10,
)
for i, cs in enumerate(cheatsheets, 1):
    print(f"\n=== Cheatsheet {i} ===")
    print(f"file_id: {cs['file_id']}")
    print("content:")
    print(cs["content"])

7. 고급 쿼리 제어 (선택)

Qdrant의 prefetch와 RRF(Reciprocal Rank Fusion) 융합을 명시적으로 쓰면서도 POMA cheatsheet를 그대로 반환받을 수 있어요.

query_text = "Whats the positional embeddings frequency?"
query_obj = qmodels.RrfQuery(rrf=qmodels.Rrf(k=60))
prefetch = [
    qmodels.Prefetch(
        query=qmodels.Document(
            text=query_text,
            model=DENSE_MODEL,
            options=DENSE_OPTIONS,
        ),
        using="dense",
        limit=100,
    ),
    qmodels.Prefetch(
        query=qmodels.Document(
            text=query_text,
            model=SPARSE_MODEL,
        ),
        using="sparse",
        limit=100,
    ),
]
cheatsheets = poma_qdrant.get_cheatsheets(
    query_obj=query_obj,
    prefetch=prefetch,
    collection_name=QDRANT_COLLECTION_NAME,
    limit=10,
    chunk_data=chunk_data,
)

더 알아보기 (Learn more)