Подробное руководство по разработке Python Chromadb
Установка
pip install chromadb
Сохранение данных Chromadb
import chromadb
Вы можете указать путь для сохранения файла базы данных Chroma. Если данные существуют, файл базы данных будет автоматически загружен при запуске программы.
client = chromadb.PersistentClient(path="/data/tizi365.db")
Параметр path
- это путь к файлу базы данных Chroma.
Примечание: Для базы данных Chroma достаточно создать объект клиента один раз. Загрузка и сохранение нескольких клиентов в один и тот же путь может вызвать непредвиденное поведение, включая удаление данных. Как правило, в приложении должен быть создан только один клиент Chroma.
Некоторые часто используемые функции объекта клиента:
client.reset() # Очищает и полностью сбрасывает базу данных
Операции с коллекциями
Chromadb использует примитив collection
для управления коллекциями векторных данных, которые можно сравнить с таблицами в MYSQL.
Создание, Просмотр и Удаление коллекций
Chroma использует имя коллекции в URL, поэтому у него есть некоторые ограничения на именование:
- Длина имени должна быть от 3 до 63 символов.
- Имя должно начинаться и заканчиваться строчной буквой или цифрой, и может содержать точки, дефисы и подчеркивания.
- Имя не может содержать две подряд идущие точки.
- Имя не может быть действительным IP-адресом.
Для создания коллекции необходимо указать имя коллекции и необязательную функцию вычисления вектора (также известную как функция встраивания). Если функция встраивания предоставляется, она должна быть предоставлена каждый раз при доступе к коллекции.
Примечание: Цель функции вычисления вектора (функции встраивания) - вычислить текстовый вектор.
collection = client.create_collection(name="my_collection", embedding_function=emb_fn)
collection = client.get_collection(name="my_collection", embedding_function=emb_fn)
Функция встраивания принимает текст в качестве входных данных и возвращает вычисленный вектор.
Примечание: Новички могут узнать о руководствах по модели встраивания текста.
Вы можете получить ссылку на существующую коллекцию с помощью функции .get_collection
и использовать .delete_collection
для удаления коллекции. Вы также можете использовать .get_or_create_collection
для ссылки на коллекцию (если она существует) или создания ее, если она не существует.
collection = client.get_collection(name="tizi365")
collection = client.get_or_create_collection(name="tizi365")
client.delete_collection(name="tizi365")
Другие часто используемые операции с коллекциями:
collection.peek() # Возвращает список первых 10 данных в коллекции
collection.count() # Возвращает общее количество данных в коллекции
collection.modify(name="new_name") # Переименовывает коллекцию
Указание метода расчета расстояния вектора
Функция create_collection
также включает параметр метаданных. Путем установки значения hnsw:space
можно настроить метод расчета расстояния векторного пространства.
Примечание: Векторные данные представляют собой сходство между векторами путем вычисления пространственного расстояния между ними. Чем ближе расстояние, тем выше сходство, и наоборот.
collection = client.create_collection(
name="collection_name",
metadata={"hnsw:space": "cosine"} # l2 - метод по умолчанию
)
Допустимые варианты для hnsw:space
- "l2", "ip" или "cosine". По умолчанию используется "l2".
Добавление данных в коллекцию
Используйте метод .add
для добавления данных в Chroma.
Добавление данных напрямую без указания векторов документов:
collection.add(
documents=["lorem ipsum...", "doc2", "doc3", ...],
metadatas=[{"глава": "3", "стих": "16"}, {"глава": "3", "стих": "5"}, {"глава": "29", "стих": "11"}, ...],
ids=["id1", "id2", "id3", ...]
)
Если Chroma получает список документов, она автоматически использует функцию встраивания коллекции для вычисления векторов документов (если функция встраивания не была предоставлена при создании коллекции, будет использовано значение по умолчанию). Также Chroma будет хранить сами документы. Если документ слишком велик для вычисления с использованием выбранной функции встраивания, произойдет исключение.
Каждый документ должен иметь уникальный идентификатор (ids). Добавление одного и того же идентификатора дважды приведет к хранению только первоначального значения. Дополнительно вы можете предоставить список словарей метаданных (metadatas) для каждого документа, чтобы хранить дополнительную информацию, которая может быть использована для фильтрации данных во время запросов.
В альтернативном варианте вы можете напрямую предоставить список связанных с документом векторных данных, и Chroma будет использовать предоставленные вами векторные данные без автоматического вычисления векторов.
collection.add(
documents=["doc1", "doc2", "doc3", ...],
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"}, ...],
ids=["id1", "id2", "id3", ...]
)
Если размерности предоставленных векторных данных не соответствуют размерностям коллекции, произойдет исключение.
Вы также можете хранить документы в другом месте и предоставить Chroma векторные данные и список метаданных. Вы можете использовать идентификаторы для связи векторов с документами, хранящимися в другом месте.
collection.add(
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"}, ...],
ids=["id1", "id2", "id3", ...]
)
Примечание: Основная функция векторной базы данных - поиск семантической схожести на основе векторных данных. Чтобы уменьшить размер векторной базы данных и улучшить эффективность, мы можем выбрать хранение векторных данных и некоторых необходимых атрибутов фильтрации в векторной базе данных. Другие данные, такие как содержание статьи, могут храниться в базах данных типа MYSQL, при условии их связи через идентификаторы.
Запрос данных из коллекции
Метод .query может быть использован для запроса наборов данных Chroma различными способами.
Вы можете выполнять запрос с использованием набора query_embeddings (векторных данных).
Совет: В реальных сценариях разработки, query_embeddings обычно получаются сначала путем вычисления вектора запроса пользователя с использованием модели векторного вложения текста, а затем используется этот вектор для запроса подобного контента.
collection.query(
query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
n_results=10,
where={"metadata_field": "is_equal_to_this"},
where_document={"$contains":"search_string"}
)
Запрос вернет n_results результатов, лучше всего соответствующих каждому вектору запроса (query_embedding) по порядку. Можно предоставить необязательный словарь фильтра where для фильтрации результатов на основе метаданных, связанных с каждым документом. Кроме того, можно предоставить необязательный словарь where_document для фильтрации результатов на основе содержания документа.
Если предоставленные query_embeddings не соответствуют размерностям коллекции, возникнет исключение. Чтобы обеспечить согласованные размерности векторов, используйте одну и ту же модель вложения текста для вычисления векторов.
Также можно выполнять запрос с использованием набора текстов запросов. Chroma сначала вычислит вектор для каждого текста запроса, используя функцию вложения коллекции, а затем выполнит запрос, используя сгенерированные векторы текста.
collection.query(
query_texts=["doc10", "thus spake zarathustra", ...],
n_results=10,
where={"metadata_field": "is_equal_to_this"},
where_document={"$contains":"search_string"}
)
Также можно использовать .get для запроса данных из коллекции по идентификатору.
collection.get(
ids=["id1", "id2", "id3", ...],
where={"style": "style1"}
)
.get также поддерживает фильтры where и where_document. Если идентификатор не предоставляется, будут возвращены все элементы в коллекции, соответствующие фильтрам where и where_document.
Указание возвращаемых полей
При использовании get или query, можно использовать параметр include для указания возвращаемых данных - вложения
, документы
или метаданные
, а для запросов также необходимо возвращать данные о расстоянии. По умолчанию Chroma возвращает документы и метаданные, и возвращает данные о расстоянии для запросов, в то время как "идентификаторы" всегда возвращаются. Можно указать возвращаемые поля, передав массив имен полей в параметр includes метода query или get.
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": {
<Оператор>: <Значение>
}
}
]
}
Обновление данных в коллекции
Используя .update
, вы можете обновить любые свойства данных в коллекции.
collection.update(
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=["doc1", "doc2", "doc3", ...],
)
Если идентификатор не найден в коллекции, будет записана ошибка, и обновление будет проигнорировано. Если у предоставленного документа нет соответствующего вектора, будет использована функция встраивания коллекции для расчета вектора.
Если предоставленные данные вектора имеют другое измерение, чем у коллекции, произойдет исключение.
Chroma также поддерживает операцию upsert, которая позволяет обновлять существующие данные и вставлять новые данные, если они не существуют.
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=[{"глава": "3", "стих": "16"}, {"глава": "3", "стих": "5"}, {"глава": "29", "стих": "11"}, ...],
documents=["doc1", "doc2", "doc3", ...],
)
Удаление данных из коллекции
Chroma поддерживает использование .delete
для удаления данных из коллекции по id
. Векторы, документы и метаданные, связанные с каждым элементом данных, также будут удалены.
collection.delete(
ids=["id1", "id2", "id3",...],
where={"глава": "20"}
)
.delete
также поддерживает фильтр where
. Если идентификатор не предоставлен, будут удалены все элементы в коллекции, соответствующие фильтру where
.