Persistent Chroma 데이터 초기화

import { ChromaClient } from 'chromadb'

클라이언트 초기화

const client = new ChromaClient();

일반 클라이언트 작업

await client.reset() // 데이터베이스 지우기

컬렉션 작업

Chromadb는 벡터 데이터 집합을 관리하기 위해 컬렉션 개념을 사용하며, 이는 MySQL의 테이블과 유사합니다.

컬렉션 생성, 조회, 삭제

Chroma는 URL에서 컬렉션 이름을 사용하므로 몇 가지 이름 지정 제한 사항이 있습니다:

  • 이름 길이는 3에서 63자여야합니다.
  • 이름은 소문자나 숫자로 시작하고 끝나야 하며, 중간에 점, 하이픈 및 밑줄을 포함할 수 있습니다.
  • 이름은 두 개 이상의 연속된 점을 포함할 수 없습니다.
  • 이름은 유효한 IP 주소가 될 수 없습니다.

컬렉션을 생성하려면 컬렉션 이름과 선택적으로 벡터 계산 함수(임베딩 함수로도 알려짐)를 지정해야 합니다. 만약 임베딩 함수를 제공한다면, 이 함수는 컬렉션에 접근할 때마다 제공되어야 합니다.

참고: 임베딩 함수는 텍스트 벡터를 계산하는 데 사용됩니다.

import { ChromaClient } from 'chromadb'

아래와 같이 컬렉션을 만들고 참조합니다:

let collection = await client.createCollection({name: "my_collection", embeddingFunction: emb_fn})

let collection2 = await client.getCollection({name: "my_collection", embeddingFunction: emb_fn})

임베딩 함수는 텍스트를 입력으로 받아 계산된 벡터 데이터를 반환합니다.

참고: 초보자들은 이 튜토리얼에서 텍스트 임베딩 모델에 대해 배울 수 있습니다.

기존의 컬렉션은 이름으로 .getCollection을 사용하여 참조할 수 있으며, .deleteCollection을 사용하여 삭제할 수도 있습니다.

const collection = await client.getCollection({name: "tizi365"}) // 컬렉션 tizi365 참조
await client.deleteCollection({name: "my_collection"}) // 컬렉션 삭제

일반 컬렉션 함수

await collection.peek() // 컬렉션 내의 처음 10개 데이터 레코드 반환
await collection.count() // 컬렉션 내의 총 데이터 레코드 수 반환

벡터 거리 계산 방법 조정

createCollection에는 metadata 매개변수를 포함하여, 벡터 공간의 거리 계산 방법을 사용자 정의할 수 있는 hnsw:space 값을 설정할 수 있는 선택적 매개변수가 포함되어 있습니다.

참고: 벡터 데이터는 벡터 간의 공간적 거리를 계산하여 벡터 간의 유사성을 나타내며, 거리가 가까울수록 높은 유사성을, 그 반대의 경우 낮은 유사성을 나타냅니다.

let collection = client.createCollection("collection_name", undefined, metadata={ "hnsw:space": "cosine" })

hnsw:space에 대한 유효한 옵션은 "l2", "ip", 또는 "cosine"입니다. 기본값은 "l2"입니다.

콜렉션에 데이터 추가하기

**.add**를 사용하여 크로마 콜렉션에 데이터를 추가합니다.

문서 벡터를 명시하지 않고 데이터를 직접 추가합니다:

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    metadatas: [{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
    documents: ["lorem ipsum...", "doc2", "doc3", ...],
})
// 매개변수 설명
// ids - 필수
// embeddings - 선택 사항
// metadata - 선택 사항
// documents - 선택 사항

만약 크로마가 문서 목록을 받으면, 콜렉션의 임베딩 기능을 자동으로 사용하여 문서에 대한 벡터를 계산합니다 (콜렉션을 생성할 때 임베딩 기능이 제공되지 않은 경우 기본값이 사용됩니다). 크로마는 또한 문서 자체를 저장합니다. 선택한 임베딩 기능과 함께 사용하기에 문서가 너무 크면 예외가 발생합니다.

각 문서는 고유한 ID (ids)를 가져야 합니다. 같은 ID를 두 번 추가하면 초기 값만 저장됩니다. 쿼리 중에 데이터를 필터링하기 위해 각 문서에 대해 추가 정보를 저장하는 선택적 메타데이터 사전 목록 (metadatas)을 제공할 수 있습니다.

또한, 문서 관련 벡터 데이터 목록을 직접 제공할 수 있고, 크로마는 자동으로 벡터를 계산하지 않고 제공한 벡터 데이터를 사용합니다.

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    embeddings: [[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
    metadatas: [{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
    documents: ["lorem ipsum...", "doc2", "doc3", ...],
})

만약 제공된 벡터 데이터의 차원 (길이)이 콜렉션의 차원과 일치하지 않는다면, 예외가 발생합니다.

문서를 다른 곳에 저장하고 단순히 크로마에 벡터 데이터와 메타데이터 목록을 제공할 수도 있습니다. IDs를 사용하여 다른 곳에 저장된 문서와 벡터를 연결할 수 있습니다.

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    embeddings: [[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
    metadatas: [{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
})

참고: 벡터 데이터베이스의 핵심 기능은 벡터 데이터를 기반으로 한 의미론적 유사성 검색입니다. 벡터 데이터베이스의 크기를 줄이고 효율성을 향상시키기 위해 벡터 데이터와 일부 필터링 가능한 속성 조건을 벡터 데이터베이스에 저장할지 선택할 수 있습니다. 기타 데이터는 MYSQL과 같은 데이터베이스에 저장할 수 있습니다. 단, ID를 통해 연관시켜야 합니다.

컬렉션 데이터 쿼리

.query 메서드를 사용하여 Chroma 데이터셋을 여러 가지 방법으로 쿼리할 수 있습니다.

쿼리는 query_embeddings(벡터 데이터)를 사용하여 할 수 있습니다.

팁: 실제 개발 시나리오에서 query_embeddings를 얻으려면 사용자의 쿼리는 일반적으로 텍스트 임베딩 모델을 통해 먼저 쿼리 벡터로 계산되고, 그런 다음이 벡터를 사용하여 유사한 콘텐츠를 쿼리합니다.

const result = await collection.query({
    queryEmbeddings: [[11.1, 12.1, 13.1], [1.1, 2.3, 3.2], ...],
    nResults: 10,
    where: {"metadata_field": "is_equal_to_this"},
})
// 입력 순서
// query_embeddings - 선택 사항
// n_results - 필수
// where - 선택 사항
// query_texts - 선택 사항

쿼리는 각 쿼리 벡터(query_embedding)에 대해 상위 n_results 결과를 순서대로 반환합니다. 선택적으로 where 필터 딕셔너리를 제공하여 각 문서와 관련된 메타데이터를 기반으로 결과를 필터링할 수 있습니다. 또한 선택적으로 where_document 필터 딕셔너리를 제공하여 문서 내용을 기반으로 결과를 필터링할 수 있습니다.

제공된 query_embeddings가 컬렉션의 차원과 일치하지 않는 경우 예외가 발생합니다. 벡터의 일관성을 보장하려면 같은 텍스트 임베딩 모델을 사용하는 것이 좋습니다.

또한 쿼리 텍스트 집합을 사용하여 쿼리할 수도 있습니다. Chroma는 먼저 각 쿼리 텍스트에 대한 벡터를 계산하고, 그런 다음 생성된 텍스트 벡터를 사용하여 쿼리를 실행합니다.

await collection.query({
    nResults: 10, // n_results
    where: {"metadata_field": "is_equal_to_this"}, // where
    queryTexts: ["doc10", "thus spake zarathustra", ...], // query_text
})

또한 .get을 사용하여 컬렉션에서 id별로 데이터를 쿼리할 수도 있습니다.

await collection.get({
    ids: ["id1", "id2", "id3", ...], //ids
    where: {"style": "style1"} // where
})

.get은 또한 wherewhere_document 필터를 지원합니다. id가 제공되지 않으면 wherewhere_document 필터와 일치하는 컬렉션 내의 모든 데이터가 반환됩니다.

반환 필드 지정

get 또는 query를 사용할 때 include 매개변수를 사용하여 반환할 데이터 필드를 지정할 수 있습니다. 기본적으로 Chroma는 문서, 메타데이터 및 벡터 거리를 반환합니다. get 또는 query의 includes 매개변수에 필드 이름의 배열을 전달하여 반환할 필드를 지정할 수 있습니다.

collection.get(
    include=["documents"]
)

collection.query(
    query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
    include=["documents"]
)

Where 필터 사용

Chroma는 메타데이터 및 문서 내용을 기반으로 쿼리를 필터링하는 기능을 지원합니다. where 필터는 메타데이터를 필터링하는 데 사용되고, where_document 필터는 문서 내용을 필터링하는 데 사용됩니다. 아래에서 필터 조건 표현을 작성하는 방법에 대해 설명합니다.

메타데이터로 필터링

메타데이터를 필터링하려면 쿼리에 대해 where 필터 딕셔너리를 제공해야 합니다. 딕셔너리는 다음 구조를 가져야 합니다.

{
    "metadata_field": {
        <연산자>: <값>
    }
}

메타데이터 필터링은 다음 연산자를 지원합니다:

  • $eq - 동일함 (문자열, 정수, 부동 소수점)
  • $ne - 동일하지 않음 (문자열, 정수, 부동 소수점)
  • $gt - 초과 (정수, 부동 소수점)
  • $gte - 이상 (정수, 부동 소수점)
  • $lt - 미만 (정수, 부동 소수점)
  • $lte - 이하 (정수, 부동 소수점)

$eq 연산자를 사용하는 것은 where 필터를 사용하는 것과 동일합니다.

{
    "metadata_field": "search_string"
}


{
    "metadata_field": {
        "$eq": "search_string"
    }
}

문서 내용으로 필터링

문서 내용을 필터링하려면 쿼리에 대해 where_document 필터 딕셔너리를 제공해야 합니다. 딕셔너리는 다음 구조를 가져야 합니다.

{
    "$contains": "search_string"
}

논리 연산자 사용하기

여러 필터를 결합하기 위해 $and$or 논리 연산자를 사용할 수 있습니다.

$and 연산자는 목록에 있는 모든 필터와 일치하는 결과를 반환합니다.

{
    "$and": [
        {
            "metadata_field": {
                <연산자>: <값>
            }
        },
        {
            "metadata_field": {
                <연산자>: <값>
            }
        }
    ]
}

$or 연산자는 목록에 있는 어떤 필터 조건이든 일치하는 결과를 반환합니다.

{
    "$or": [
        {
            "metadata_field": {
                <연산자>: <값>
            }
        },
        {
            "metadata_field": {
                <연산자>: <값>
            }
        }
    ]
}

데이터 업데이트하기

Chroma는 기존 데이터를 업데이트하고, 데이터가 존재하지 않는 경우 새 데이터를 삽입하는 업설트 작업을 지원합니다.

await collection.upsert({
    ids: ["id1", "id2", "id3"],
    embeddings: [[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2]],
    metadatas: [{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}],
    documents: ["doc1", "doc2", "doc3"]
})

데이터 삭제하기

Chroma는 컬렉션에서 .delete를 사용하여 id에 따라 데이터를 삭제하는 것을 지원합니다.

await collection.delete({
    ids: ["id1", "id2", "id3",...], //ids
    where: {"chapter": "20"} //where
})