PGVectorStorepostgres를 백엔드로 사용하는 LangChain vectorstore의 구현입니다. 이 노트북에서는 PGVectorStore API 사용 방법을 다룹니다. 코드는 langchain-postgres라는 integration 패키지에 있습니다.

설정

이 패키지는 pgvector 확장이 포함된 PostgreSQL 데이터베이스가 필요합니다. 다음 명령을 실행하여 pgvector가 활성화된 Postgres 인스턴스용 컨테이너를 실행할 수 있습니다:
docker run --name pgvector-container -e POSTGRES_USER=langchain -e POSTGRES_PASSWORD=langchain -e POSTGRES_DB=langchain -p 6024:5432 -d pgvector/pgvector:pg16

설치

integration 라이브러리 langchain-postgres를 설치하세요.
pip install -qU  langchain-postgres
# This notebook also requires the following dependencies
pip install -qU  langchain-core langchain-cohere sqlalchemy

Postgres 값 설정

이 노트북에서 Postgres 인스턴스를 대상으로 기능을 테스트할 수 있도록 Postgres 값을 설정하세요.
# @title Set your values or use the defaults to connect to Docker { display-mode: "form" }
POSTGRES_USER = "langchain"  # @param {type: "string"}
POSTGRES_PASSWORD = "langchain"  # @param {type: "string"}
POSTGRES_HOST = "localhost"  # @param {type: "string"}
POSTGRES_PORT = "6024"  # @param {type: "string"}
POSTGRES_DB = "langchain"  # @param {type: "string"}
TABLE_NAME = "vectorstore"  # @param {type: "string"}
VECTOR_SIZE = 1024  # @param {type: "int"}

초기화

PGEngine 연결 풀

PostgreSQL을 vector store로 설정하기 위한 요구 사항 및 인자 중 하나는 PGEngine 객체입니다. PGEngine은 Postgres 데이터베이스에 대한 공유 connection pool을 구성합니다. 이는 연결 수를 관리하고 캐시된 데이터베이스 연결을 통해 대기 시간을 줄이기 위한 업계 모범 사례입니다. PGVectorStoreasyncpgpsycopg3 드라이버와 함께 사용할 수 있습니다. PGEngine.from_connection_string()을 사용하여 PGEngine을 생성하려면 다음이 필요합니다:
  1. url : postgresql+asyncpg 드라이버를 사용하는 connection string.
주의: 이 튜토리얼은 async 인터페이스를 보여줍니다. 모든 async 메서드에는 해당하는 sync 메서드가 있습니다.
# See docker command above to launch a Postgres instance with pgvector enabled.
CONNECTION_STRING = (
    f"postgresql+asyncpg://{POSTGRES_USER}:{POSTGRES_PASSWORD}@{POSTGRES_HOST}"
    f":{POSTGRES_PORT}/{POSTGRES_DB}"
)
# To use psycopg3 driver, set your connection string to `postgresql+psycopg://`
from langchain_postgres import PGEngine

pg_engine = PGEngine.from_connection_string(url=CONNECTION_STRING)
PGEngine.from_engine()을 사용하여 PGEngine을 생성하려면 다음이 필요합니다:
  1. engine : AsyncEngine 객체
from sqlalchemy.ext.asyncio import create_async_engine

# Create an SQLAlchemy Async Engine
engine = create_async_engine(
    CONNECTION_STRING,
)

pg_engine = PGEngine.from_engine(engine=engine)

테이블 초기화

PGVectorStore 클래스는 데이터베이스 테이블을 필요로 합니다. PGEngine 엔진에는 올바른 스키마로 테이블을 생성하는 데 사용할 수 있는 ainit_vectorstore_table() 헬퍼 메서드가 있습니다. 스키마를 사용자 지정하려면 Create a custom Vector Store 또는 Create a Vector Store using existing table를 참고하세요.
await pg_engine.ainit_vectorstore_table(
    table_name=TABLE_NAME,
    vector_size=VECTOR_SIZE,
)

선택 사항 팁: 💡

table_name을 전달하는 모든 곳에서 schema_name을 전달하여 스키마 이름도 지정할 수 있습니다. 예:
SCHEMA_NAME="my_schema"

await pg_engine.ainit_vectorstore_table(
    table_name=TABLE_NAME,
    vector_size=768,
    schema_name=SCHEMA_NAME,    # Default: "public"
)

Embedding 클래스 인스턴스 생성

원하는 LangChain embeddings model을 사용할 수 있습니다.
from langchain_cohere import CohereEmbeddings

embedding = CohereEmbeddings(model="embed-english-v3.0")

기본 PGVectorStore 초기화

기본 테이블 스키마를 사용하여 vectorstore에 연결합니다. 스키마를 사용자 지정하려면 Create a custom Vector Store 또는 Create a Vector Store using existing table를 참고하세요.
from langchain_postgres import PGVectorStore

store = await PGVectorStore.create(
    engine=pg_engine,
    table_name=TABLE_NAME,
    # schema_name=SCHEMA_NAME,
    embedding_service=embedding,
)

벡터 저장소 관리

문서 추가

벡터 저장소에 문서를 추가합니다. Metadata는 JSON 컬럼에 저장됩니다. 필터에 사용할 metadata를 저장하려면 “Create a custom Vector Store”를 참고하세요.
import uuid

from langchain_core.documents import Document

docs = [
    Document(
        id=str(uuid.uuid4()),
        page_content="Red Apple",
        metadata={"description": "red", "content": "1", "category": "fruit"},
    ),
    Document(
        id=str(uuid.uuid4()),
        page_content="Banana Cavendish",
        metadata={"description": "yellow", "content": "2", "category": "fruit"},
    ),
    Document(
        id=str(uuid.uuid4()),
        page_content="Orange Navel",
        metadata={"description": "orange", "content": "3", "category": "fruit"},
    ),
]

await store.aadd_documents(docs)

텍스트 추가

문서로 구조화되지 않은 경우 텍스트를 vectorstore에 직접 추가하세요.
import uuid

all_texts = ["Apples and oranges", "Cars and airplanes", "Pineapple", "Train", "Banana"]
metadatas = [{"len": len(t)} for t in all_texts]
ids = [str(uuid.uuid4()) for _ in all_texts]

await store.aadd_texts(all_texts, metadatas=metadatas, ids=ids)

문서 삭제

문서는 id를 사용하여 삭제할 수 있습니다.
await store.adelete([ids[1]])

벡터 저장소 질의

문서 검색

자연어 쿼리를 사용하여 유사한 문서를 검색합니다.
query = "I'd like a fruit."
docs = await store.asimilarity_search(query)
print(docs)

벡터로 문서 검색

벡터 embedding을 사용하여 유사한 문서를 검색합니다.
query_vector = embedding.embed_query(query)
docs = await store.asimilarity_search_by_vector(query_vector, k=2)
print(docs)

인덱스 추가

vector indexes를 적용하여 벡터 검색 쿼리를 빠르게 합니다. 인덱스 이름을 제공하지 않으면 기본 인덱스 이름이 사용됩니다. 여러 인덱스를 추가하려면 서로 다른 인덱스 이름이 필요합니다.
from langchain_postgres.v2.indexes import HNSWIndex, IVFFlatIndex

index = IVFFlatIndex()
await store.aapply_vector_index(index)

index = HNSWIndex(name="my-hnsw-index")
await store.aapply_vector_index(index)
인덱스 파라미터를 설정하여 recall과 QPS 간 최적의 균형을 위해 인덱스를 튜닝하세요.
index = IVFFlatIndex(name="my-ivfflat", lists=120)
await store.aapply_vector_index(index)

재인덱싱

인덱스의 테이블에 저장된 데이터를 사용하여 인덱스를 다시 빌드하고 오래된 사본을 교체합니다. 일부 인덱스 유형은 상당한 양의 새로운 데이터가 추가된 후 재인덱싱이 필요할 수 있습니다.
await store.areindex()  # Re-index using the default index name
await store.areindex("my-hnsw-index")  # Re-index using the index name

인덱스 삭제

벡터 인덱스를 제거합니다.
await store.adrop_vector_index()  # Delete index using the default name
await store.adrop_vector_index("my-hnsw-index")  # Delete index using the index name

사용자 지정 Vector Store 만들기

특별한 컬럼 이름이나 사용자 지정 metadata 컬럼으로 vectorstore를 사용자 지정합니다. ainit_vectorstore_table
  • content_column, embedding_column,metadata_columns, metadata_json_column, id_column 필드를 사용하여 컬럼 이름을 변경합니다.
  • 사용자 지정 id 또는 metadata 컬럼을 만들려면 Column 클래스를 사용합니다. Column은 이름과 데이터 타입으로 정의됩니다. 모든 Postgres data type을 사용할 수 있습니다.
  • 추가 metadata를 저장하기 위해 store_metadata를 사용하여 JSON 컬럼을 생성합니다.

선택 사항 팁: 💡

uuid가 아닌 id를 사용하려면 id 컬럼을 사용자 지정해야 합니다:
await pg_engine.ainit_vectorstore_table(
    ...,
    id_column=Column(name="langchain_id", data_type="INTEGER")
)
PGVectorStore
  • content_column, embedding_column,metadata_columns, metadata_json_column, id_column 필드를 사용하여 컬럼 이름을 변경합니다.
  • ignore_metadata_columns를 사용하여 Document metadata에 사용되지 않아야 하는 컬럼을 무시합니다. 이는 기존 테이블을 사용할 때 모든 데이터 컬럼이 필요하지 않은 경우에 유용합니다.
  • 벡터 검색 중 유사도 계산에 대해 다른 distance_strategy를 사용합니다.
  • 벡터 검색 중 로컬 인덱스 파라미터를 튜닝하려면 index_query_options를 사용합니다.
from langchain_postgres import Column

# Set table name
TABLE_NAME = "vectorstore_custom"
# SCHEMA_NAME = "my_schema"

await pg_engine.ainit_vectorstore_table(
    table_name=TABLE_NAME,
    # schema_name=SCHEMA_NAME,
    vector_size=VECTOR_SIZE,
    metadata_columns=[Column("len", "INTEGER")],
)


# Initialize PGVectorStore
custom_store = await PGVectorStore.create(
    engine=pg_engine,
    table_name=TABLE_NAME,
    # schema_name=SCHEMA_NAME,
    embedding_service=embedding,
    metadata_columns=["len"],
)

메타데이터 필터로 문서 검색

Vector Store는 관계형 데이터를 활용하여 유사도 검색을 필터링할 수 있습니다. vectorstore는 문서의 metadata 필드에 적용할 수 있는 일련의 필터를 지원합니다. metadata 컬럼을 사용하도록 마이그레이션하는 방법에 대한 자세한 내용은 migration guide를 참고하세요. PGVectorStore는 현재 다음 연산자와 모든 Postgres 데이터 타입을 지원합니다.
연산자의미/범주
$eq동등 (==)
$ne비동등 (!=)
$lt미만 (<)
$lte이하 (<=)
$gt초과 (>)
$gte이상 (>=)
$in특수 처리 (in)
$nin특수 처리 (not in)
$between특수 처리 (between)
$exists특수 처리 (is null)
$like텍스트 (like)
$ilike텍스트 (대소문자 무시 like)
$and논리 (and)
$or논리 (or)
import uuid

docs = [
    Document(
        id=str(uuid.uuid4()),
        page_content="Red Apple",
        metadata={"description": "red", "content": "1", "category": "fruit"},
    ),
    Document(
        id=str(uuid.uuid4()),
        page_content="Banana Cavendish",
        metadata={"description": "yellow", "content": "2", "category": "fruit"},
    ),
    Document(
        id=str(uuid.uuid4()),
        page_content="Orange Navel",
        metadata={"description": "orange", "content": "3", "category": "fruit"},
    ),
]

await custom_store.aadd_documents(docs)

# Use a dictionary filter on search
docs = await custom_store.asimilarity_search(query, filter={"content": {"$gte": 1}})

print(docs)

기존 테이블을 사용하여 Vector Store 만들기

기존 테이블 위에 Vector Store를 구축할 수 있습니다. PG DB에 미리 존재하는 테이블 products가 있고, eComm 벤처를 위한 제품 상세 정보를 저장한다고 가정합니다. 이 테이블을 PGVectorStore에 매핑하는 방법은 다음과 같습니다:
  • id_column="product_id": ID 컬럼은 products 테이블의 각 행을 고유하게 식별합니다.
  • content_column="description": description 컬럼에는 각 제품의 텍스트 설명이 들어 있습니다. 이 텍스트는 embedding_service에 의해 벡터로 생성되어 embedding_column에 저장되고, 각 설명의 의미를 표현합니다.
  • embedding_column="embed": embed 컬럼은 제품 설명에서 생성된 벡터를 저장합니다. 이 벡터는 유사한 설명을 가진 제품을 찾는 데 사용됩니다.
  • metadata_columns=["name", "category", "price_usd", "quantity", "sku", "image_url"]: 이 컬럼들은 각 제품의 metadata로 취급됩니다. Metadata는 제품 이름, 카테고리, 가격, 재고 수량, SKU(Stock Keeping Unit), 이미지 URL 등 추가 정보를 제공합니다. 이 정보는 검색 결과에 제품 세부 정보를 표시하거나 필터링 및 분류에 유용합니다.
  • metadata_json_column="metadata": metadata 컬럼은 제품에 대한 추가 정보를 유연한 JSON 형식으로 저장할 수 있습니다. 표준 컬럼에 맞지 않는 다양한 복잡한 데이터를 저장하는 데 유용합니다.
# Set an existing table name
TABLE_NAME = "products"
# SCHEMA_NAME = "my_schema"

# Initialize PGVectorStore
custom_store = await PGVectorStore.create(
    engine=pg_engine,
    table_name=TABLE_NAME,
    # schema_name=SCHEMA_NAME,
    embedding_service=embedding,
    # Connect to existing VectorStore by customizing below column names
    id_column="product_id",
    content_column="description",
    embedding_column="embed",
    metadata_columns=["name", "category", "price_usd", "quantity", "sku", "image_url"],
    metadata_json_column="metadata",
)
참고:
  1. 선택 사항: embed 컬럼이 새로 생성되었거나 embedding 모델이 지원하는 차원과 다른 경우, 기존 레코드에 대해 임시로 embedding을 추가해야 합니다. 예: ALTER TABLE products ADD COLUMN embed vector(768) DEFAULT NULL
  2. 새 레코드는 VectorStore를 통해 추가되면 embedding이 자동으로 생성됩니다.

정리

⚠️ 경고: 이 작업은 되돌릴 수 없습니다 vector store 테이블을 드롭합니다.
await pg_engine.adrop_table(TABLE_NAME)

검색 증강 생성(RAG) 사용법

이 vector store를 검색 증강 생성(RAG)에 사용하는 방법에 대한 가이드는 다음 섹션을 참고하세요:

API 참고 문서

모든 VectorStore 기능 및 구성에 대한 자세한 문서는 API 참고 문서를 확인하세요: python.langchain.com/api_reference/postgres/v2/langchain_postgres.v2.vectorstores.PGVectorStore.html
Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
I