Инициализация постоянных данных 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 для добавления данных в коллекцию Chroma.

Добавьте данные напрямую, не указывая векторы документов:

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    metadatas: [{"глава": "3", "стих": "16"}, {"глава": "3", "стих": "5"}, {"глава": "29", "стих": "11"}, ...],
    documents: ["lorem ipsum...", "doc2", "doc3", ...],
})
// Пояснение к параметрам
// ids - обязательный
// embeddings - опциональный
// metadata - опциональный
// documents - опциональный

Если Chroma получает список документов, он автоматически использует функцию встраивания коллекции для вычисления векторов для документов (если функция встраивания не была предоставлена при создании коллекции, будет использовано значение по умолчанию). Также Chroma будет хранить сами документы. Если документ слишком велик для использования с выбранной функцией встраивания, произойдет исключение.

Каждый документ должен иметь уникальный идентификатор (ids). Добавление одного и того же идентификатора дважды приведет к хранению только исходного значения. Для каждого документа можно предоставить опциональный список словарей метаданных (metadatas), чтобы хранить дополнительную информацию для фильтрации данных во время запросов.

Кроме того, вы можете напрямую предоставить список векторных данных, связанных с документом, и Chroma будет использовать предоставленные вами векторные данные без автоматического вычисления вектора.

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: [{"глава": "3", "стих": "16"}, {"глава": "3", "стих": "5"}, {"глава": "29", "стих": "11"}, ...],
    documents: ["lorem ipsum...", "doc2", "doc3", ...],
})

Если предоставленные размерности векторных данных (длина) не соответствуют размерностям коллекции, произойдет исключение.

Также вы можете хранить документы в другом месте и просто предоставить векторные данные и список метаданных Chroma. Вы можете использовать идентификаторы для связи векторов с документами, хранящимися в другом месте.

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: [{"глава": "3", "стих": "16"}, {"глава": "3", "стих": "5"}, {"глава": "29", "стих": "11"}, ...],
})

Примечание: Основная функция векторной базы данных - это поиск семантической близости на основе векторных данных. Для уменьшения размера векторной базы данных и повышения эффективности мы можем выбрать хранение векторных данных и некоторых условий фильтрации в векторной базе данных. Другие данные, такие как содержание статьи, могут быть храниться в базах данных типа MYSQL, при условии их ассоциации через идентификаторы.

Запрос данных из коллекции

Метод .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 - необязательно

Запрос вернет топ n_results результатов для каждого вектора запроса (query_embedding) в порядке. Можно предоставить опциональный словарь where filter для фильтрации результатов на основе метаданных, связанных с каждым документом. Кроме того, можно предоставить опциональный словарь where_document filter для фильтрации результатов на основе содержания документа.

Если предоставленные query_embeddings не соответствуют размерам коллекции, возникнет исключение. Для обеспечения согласованности векторов рекомендуется использовать одну и ту же модель вложения текста для вычисления векторов.

Также можно осуществлять запросы, используя набор query_texts. Сначала Chroma вычислит вектор для каждого текста запроса с использованием функции встраивания коллекции, а затем выполнит запрос, используя сгенерированные текстовые векторы.

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

Также можно использовать .get для запроса данных из коллекции по идентификатору.

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

.get также поддерживает фильтры where и where_document. Если идентификатор не предоставлен, он вернет все данные из коллекции, которые соответствуют фильтрам where и where_document.

Указание возвращаемых полей

При использовании get или query можно использовать параметр include для указания полей данных, которые будут возвращены, включая векторные данные, документы и любые данные в метаданных. По умолчанию Chroma возвращает документы, метаданные и расстояния между векторами. Можно указать возвращаемые поля, передав массив имен полей в параметре includes для get или query.

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 filter. Словарь должен иметь следующую структуру:

{
    "metadata_field": {
        <Оператор>: <Значение>
    }
}

Для фильтрации метаданных поддерживаются следующие операторы:

  • $eq - Равно (строка, целое число, число с плавающей запятой)
  • $ne - Не равно (строка, целое число, число с плавающей запятой)
  • $gt - Больше чем (целое число, число с плавающей запятой)
  • $gte - Больше или равно (целое число, число с плавающей запятой)
  • $lt - Меньше чем (целое число, число с плавающей запятой)
  • $lte - Меньше или равно (целое число, число с плавающей запятой)

Использование оператора $eq эквивалентно использованию фильтра where.

{
    "metadata_field": "search_string"
}


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

Фильтрация содержания документа

Для фильтрации содержания документа в запросе должен быть предоставлен словарь where_document filter. Словарь должен иметь следующую структуру:

{
    "$contains": "search_string"
}

Использование логических операторов

Вы также можете использовать логические операторы $and и $or для объединения нескольких фильтров.

Оператор $and вернет результаты, которые соответствуют всем фильтрам в списке.

{
    "$and": [
        {
            "metadata_field": {
                <Оператор>: <Значение>
            }
        },
        {
            "metadata_field": {
                <Оператор>: <Значение>
            }
        }
    ]
}

Оператор $or вернет результаты, которые соответствуют любому условию фильтрации в списке.

{
    "$or": [
        {
            "metadata_field": {
                <Оператор>: <Значение>
            }
        },
        {
            "metadata_field": {
                <Оператор>: <Значение>
            }
        }
    ]
}

Обновление данных

Chroma также поддерживает операцию upsert, которая может обновлять существующие данные и вставлять новые данные, если данных не существует.

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 для удаления данных из коллекции по идентификатору.

await collection.delete({
    ids: ["id1", "id2", "id3",...], // идентификаторы
    where: {"chapter": "20"} // условие
})