# ChromaDB

ChromaDB это **ведущая открытая векторная база данных с открытым исходным кодом** созданная специально для AI-приложений. Она предоставляет простой, интуитивно понятный API для хранения, запросов и управления высокоразмерными эмбеддингами — основой современных RAG-систем, семантического поиска, рекомендательных движков и памяти LLM.

ChromaDB скрывает сложность поиска по векторному сходству, позволяя вам сосредоточиться на создании AI-приложений. Она поддерживает режим в памяти для разработки и режим постоянного сервера для продакшн-развертываний, с поддержкой Docker для лёгкого развёртывания на GPU-серверах Clore.ai.

Ключевые особенности:

* 🚀 **Простой API для Python/JavaScript** — начните за несколько минут
* 💾 **Постоянное хранилище** — данные сохраняются при перезапуске контейнера
* 🔍 **Несколько метрик расстояния** — косинус, L2, скалярное произведение
* 📦 **Интегрированные эмбеддинги** — встроенная поддержка OpenAI, Cohere, sentence-transformers
* 🏗️ **Многопользовательская (multi-tenant)** — коллекции для организации разных наборов данных
* 🔌 **REST API** — язык-независимый HTTP-интерфейс
* ⚡ **Быстро** — индекс HNSW для приближённого поиска ближайших соседей
* 🔗 **Родная интеграция с LangChain/LlamaIndex** — первоклассная интеграция

{% hint style="success" %}
Все примеры можно запускать на GPU-серверах, арендуемых через [CLORE.AI Маркетплейс](https://clore.ai/marketplace).
{% endhint %}

***

## Требования к серверу

| Параметр | Минимум                        | Рекомендуется                               |
| -------- | ------------------------------ | ------------------------------------------- |
| GPU      | Любая NVIDIA GPU (опционально) | NVIDIA RTX 3080+ (для эмбеддингов)          |
| VRAM     | Не требуется для ChromaDB      | 8–16 ГБ (для локальных моделей эмбеддингов) |
| ОЗУ      | 4 ГБ                           | 16–32 ГБ                                    |
| CPU      | 2 ядра                         | 8 ядер                                      |
| Диск     | 10 ГБ                          | 50–200 ГБ (для больших наборов данных)      |
| ОС       | Ubuntu 20.04+                  | Ubuntu 22.04                                |
| Docker   | Требуется                      | Docker + Docker Compose                     |
| Порты    | 22, 8000                       | 22, 8000                                    |

{% hint style="info" %}
Самому ChromaDB GPU не требуется — оно эффективно работает на CPU. Однако **генерация эмбеддингов** (преобразование текста в векторы) сильно выигрывает от ускорения на GPU. Если вы планируете использовать локальные модели эмбеддингов (sentence-transformers и т.д.), выбирайте сервер с GPU.
{% endhint %}

***

## Быстрое развертывание на CLORE.AI

### 1. Найдите подходящий сервер

Перейдите на [CLORE.AI Маркетплейс](https://clore.ai/marketplace) и выберите:

* **Только CPU** для сервера ChromaDB + API (храните предварительно вычисленные эмбеддинги)
* **GPU-сервер** если вы также хотите генерировать эмбеддинги локально

### 2. Настройте ваше развёртывание

**Docker-образ:**

```
chromadb/chroma:latest
```

**Проброс портов:**

```
22   → доступ по SSH
8000 → HTTP API ChromaDB
```

**Переменные окружения:**

```
IS_PERSISTENT=TRUE
ANONYMIZED_TELEMETRY=FALSE
CHROMA_SERVER_AUTH_CREDENTIALS_FILE=/chroma/auth.txt
```

**Команда запуска:**

```bash
uvicorn chromadb.app:app --host 0.0.0.0 --port 8000
```

### 3. Тестирование развертывания

```bash
curl http://<server-ip>:8000/api/v1/heartbeat
# Ожидаемый ответ: {"nanosecond heartbeat": <timestamp>}
```

***

## Пошаговая настройка

### Шаг 1: Подключитесь по SSH к вашему серверу

```bash
ssh root@<ip-вашего-clore-сервера> -p <ssh-порт>
```

### Шаг 2: Создайте директорию для данных

```bash
mkdir -p /workspace/chromadb/data
mkdir -p /workspace/chromadb/config
```

### Шаг 3: Запустите контейнер ChromaDB

```bash
docker run -d \
  --name chromadb \
  -p 8000:8000 \
  -v /workspace/chromadb/data:/chroma/chroma \
  -e IS_PERSISTENT=TRUE \
  -e ANONYMIZED_TELEMETRY=FALSE \
  -e CHROMA_SERVER_LOG_LEVEL=INFO \
  chromadb/chroma:latest
```

### Шаг 4: Проверьте, что он работает

```bash
# Проверить состояние
curl http://localhost:8000/api/v1/heartbeat

# Проверить версию
curl http://localhost:8000/api/v1/version

# Список коллекций
curl http://localhost:8000/api/v1/collections
```

### Шаг 5: Установите Python-клиент

```bash
pip install chromadb
pip install sentence-transformers  # Для локальных эмбеддингов на GPU
pip install openai                  # Для эмбеддингов OpenAI
```

### Шаг 6: Проверьте подключение из Python

```python
import chromadb

client = chromadb.HttpClient(host="<server-ip>", port=8000)
print(f"Версия ChromaDB: {client.get_version()}")
print(f"Heartbeat: {client.heartbeat()}")
```

### Шаг 7: (Опционально) Включите аутентификацию

```bash
# Создайте учётные данные для аутентификации
echo "admin:$2y$12$$(openssl rand -hex 16)" > /workspace/chromadb/auth.txt

# Запуск с включённой аутентификацией
docker run -d \
  --name chromadb-auth \
  -p 8000:8000 \
  -v /workspace/chromadb/data:/chroma/chroma \
  -v /workspace/chromadb/auth.txt:/chroma/auth.txt \
  -e IS_PERSISTENT=TRUE \
  -e CHROMA_SERVER_AUTH_CREDENTIALS_FILE=/chroma/auth.txt \
  -e CHROMA_SERVER_AUTH_CREDENTIALS_PROVIDER=chromadb.auth.providers.HtpasswdFileServerAuthCredentialsProvider \
  -e CHROMA_SERVER_AUTH_PROVIDER=chromadb.auth.basic.BasicAuthServerProvider \
  chromadb/chroma:latest
```

***

## Примеры использования

### Пример 1: Базовые операции с векторным хранилищем

```python
import chromadb
from chromadb.utils import embedding_functions

# Подключение к ChromaDB на сервере Clore.ai
client = chromadb.HttpClient(
    host="<your-clore-server-ip>",
    port=8000
)

# Используйте sentence-transformers для эмбеддингов (запускается на GPU, если доступно)
embedding_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
    model_name="all-MiniLM-L6-v2"
)

# Создайте коллекцию
collection = client.get_or_create_collection(
    name="clore_ai_docs",
    embedding_function=embedding_fn,
    metadata={"hnsw:space": "cosine"}  # Метрика расстояния
)

# Добавьте документы
documents = [
    "Clore.ai — это децентрализованный маркетплейс GPU-облаков для AI-нагрузок.",
    "Вы можете арендовать NVIDIA RTX 4090, A100 и H100 GPU на Clore.ai.",
    "Clore.ai поддерживает развёртывания на базе Docker для любых AI-фреймворков.",
    "Цены на Clore.ai конкурентоспособны по сравнению с AWS и GCP.",
    "Маркетплейс Clore.ai имеет тысячи GPU-серверов по всему миру.",
    "Вы можете развёртывать PyTorch, TensorFlow, JAX и другие ML-фреймворки.",
    "Clore.ai предлагает спотовые цены для экономичной работы с GPU.",
]

ids = [f"doc_{i}" for i in range(len(documents))]

collection.add(
    documents=documents,
    ids=ids,
    metadatas=[{"source": "docs", "index": i} for i in range(len(documents))]
)

print(f"Добавлено {len(documents)} документов в коллекцию")
print(f"Размер коллекции: {collection.count()} документов")
```

***

### Пример 2: Семантический поиск

```python
import chromadb
from chromadb.utils import embedding_functions

client = chromadb.HttpClient(host="<server-ip>", port=8000)
embedding_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
    model_name="all-MiniLM-L6-v2"
)

collection = client.get_collection(
    name="clore_ai_docs",
    embedding_function=embedding_fn
)

# Запросы для семантического поиска
queries = [
    "Сколько стоит аренда GPU?",
    "Какие инструменты машинного обучения доступны?",
    "Расскажите о вариантах аппаратного обеспечения GPU",
]

for query in queries:
    results = collection.query(
        query_texts=[query],
        n_results=3,
        include=["documents", "distances", "metadatas"]
    )

    print(f"\n🔍 Запрос: {query}")
    for i, (doc, dist) in enumerate(zip(
        results["documents"][0],
        results["distances"][0]
    )):
        similarity = 1 - dist  # Преобразовать расстояние в меру сходства
        print(f"  {i+1}. [{similarity:.3f}] {doc[:100]}...")
```

***

### Пример 3: RAG-пайплайн с ChromaDB + OpenAI

```python
import chromadb
from chromadb.utils import embedding_functions
from openai import OpenAI

# Инициализировать клиентов
chroma_client = chromadb.HttpClient(host="<server-ip>", port=8000)
openai_client = OpenAI(api_key="your-openai-api-key")

# Используйте эмбеддинги OpenAI
openai_ef = embedding_functions.OpenAIEmbeddingFunction(
    api_key="your-openai-api-key",
    model_name="text-embedding-3-small"
)

# Получение коллекции
collection = chroma_client.get_or_create_collection(
    name="knowledge_base",
    embedding_function=openai_ef
)

def add_to_knowledge_base(texts, ids=None, metadatas=None):
    """Добавить документы в базу знаний ChromaDB."""
    if ids is None:
        ids = [f"doc_{i}" for i in range(len(texts))]
    collection.add(documents=texts, ids=ids, metadatas=metadatas or [{}]*len(texts))
    print(f"✓ Добавлено {len(texts)} документов. Всего: {collection.count()}")

def rag_query(question, n_context=5):
    """Извлечь релевантный контекст и сгенерировать ответ с помощью GPT-4."""
    # 1. Извлечь релевантные документы
    results = collection.query(
        query_texts=[question],
        n_results=n_context,
        include=["documents", "distances"]
    )

    context_docs = results["documents"][0]
    distances = results["distances"][0]

    # 2. Построить строку контекста
    context = "\n\n".join([
        f"[Источник {i+1} (релевантность: {1-d:.2f})]: {doc}"
        for i, (doc, d) in enumerate(zip(context_docs, distances))
    ])

    # 3. Сгенерировать ответ с LLM
    messages = [
        {
            "role": "system",
            "content": "Вы полезный помощник. Отвечайте на вопросы на основе предоставленного контекста. Если ответа нет в контексте, признайте это."
        },
        {
            "role": "user",
            "content": f"Context:\n{context}\n\nQuestion: {question}"
        }
    ]

    response = openai_client.chat.completions.create(
        model="gpt-4-turbo",
        messages=messages,
        temperature=0.1
    )

    answer = response.choices[0].message.content

    return {
        "question": question,
        "answer": answer,
        "sources": context_docs,
        "relevance_scores": [1 - d for d in distances]
    }

# Пример использования
knowledge = [
    "Clore.ai — это маркетплейс GPU-облака с более чем 45 000 пользователями.",
    "Clore.ai поддерживает развёртывание рабочих нагрузок на базе Docker.",
    "GPU-серверы на Clore.ai варьируются от GTX 1080 до H100.",
    "Вы можете развёртывать AI-приложения с доступом по SSH и кастомными портами.",
]
add_to_knowledge_base(knowledge)

result = rag_query("Сколько пользователей у Clore.ai?")
print(f"Q: {result['question']}")
print(f"A: {result['answer']}")
```

***

### Пример 4: Управление документами в нескольких коллекциях

```python
import chromadb
from chromadb.utils import embedding_functions

client = chromadb.HttpClient(host="<server-ip>", port=8000)
embedding_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
    model_name="all-mpnet-base-v2"  # Эмбеддинги более высокого качества
)

# Создайте отдельные коллекции для разных типов документов
collections = {
    "technical_docs": client.get_or_create_collection("technical_docs", embedding_function=embedding_fn),
    "faq": client.get_or_create_collection("faq", embedding_function=embedding_fn),
    "blog_posts": client.get_or_create_collection("blog_posts", embedding_function=embedding_fn),
}

# Добавьте документы в соответствующие коллекции
collections["technical_docs"].add(
    documents=["Руководство по развёртыванию Docker для Clore.ai", "Конфигурация SSH для GPU-серверов"],
    ids=["tech_001", "tech_002"],
    metadatas=[{"type": "guide", "version": "v2"}, {"type": "config"}]
)

collections["faq"].add(
    documents=["Q: Как оплатить? A: Через криптовалюту.", "Q: Какие GPU? A: От RTX до H100."],
    ids=["faq_001", "faq_002"],
    metadatas=[{"category": "payment"}, {"category": "hardware"}]
)

# Поиск по всем коллекциям
def search_all_collections(query, n_results=2):
    all_results = []
    for name, col in collections.items():
        results = col.query(query_texts=[query], n_results=n_results)
        for doc, dist in zip(results["documents"][0], results["distances"][0]):
            all_results.append({
                "collection": name,
                "document": doc,
                "similarity": 1 - dist
            })

    # Сортировать по релевантности
    all_results.sort(key=lambda x: x["similarity"], reverse=True)
    return all_results[:n_results * 2]

results = search_all_collections("Как развернуть с помощью Docker?")
for r in results:
    print(f"[{r['collection']}] ({r['similarity']:.3f}) {r['document'][:80]}...")
```

***

### Пример 5: Фильтрация и запросы по метаданным

```python
import chromadb

client = chromadb.HttpClient(host="<server-ip>", port=8000)
collection = client.get_collection("technical_docs")

# Добавьте документы с подробными метаданными
collection.add(
    documents=[
        "Руководство: Запуск PyTorch на кластерах с NVIDIA A100",
        "Руководство: Распределённое обучение TensorFlow на RTX 4090",
        "Учебник: Дообучение LLM с LoRA на GPU",
        "Справочник: Матрица совместимости CUDA 12.1",
        "Руководство: Сетевые настройки Docker для мульти-GPU систем",
    ],
    ids=["d1", "d2", "d3", "d4", "d5"],
    metadatas=[
        {"type": "guide", "gpu": "A100", "framework": "pytorch", "year": 2024},
        {"type": "guide", "gpu": "RTX4090", "framework": "tensorflow", "year": 2024},
        {"type": "tutorial", "gpu": "any", "framework": "transformers", "year": 2024},
        {"type": "reference", "gpu": "any", "framework": "cuda", "year": 2023},
        {"type": "guide", "gpu": "multi", "framework": "docker", "year": 2024},
    ]
)

# Запрос с фильтром по метаданным
results = collection.query(
    query_texts=["Руководство по обучению на GPU"],
    n_results=3,
    where={"type": "guide"},  # Возвращать только руководства
    include=["documents", "metadatas", "distances"]
)

print("Отфильтрованные результаты (type=guide):")
for doc, meta, dist in zip(
    results["documents"][0],
    results["metadatas"][0],
    results["distances"][0]
):
    print(f"  [{1-dist:.3f}] {doc}")
    print(f"    Метаданные: {meta}")
```

***

## Конфигурация

### Docker Compose (Продакшн)

```yaml
version: '3.8'

services:
  chromadb:
    image: chromadb/chroma:latest
    container_name: chromadb
    ports:
      - "8000:8000"
    volumes:
      - chromadb_data:/chroma/chroma
    environment:
      - IS_PERSISTENT=TRUE
      - ANONYMIZED_TELEMETRY=FALSE
      - CHROMA_SERVER_LOG_LEVEL=INFO
      - ALLOW_RESET=FALSE
      - CHROMA_SEGMENT_CACHE_POLICY=LRU
      - CHROMA_MEMORY_LIMIT_BYTES=2147483648  # Кэш 2 ГБ
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/heartbeat"]
      interval: 30s
      timeout: 10s
      retries: 3

volumes:
  chromadb_data:
    driver: local
```

### Справочник переменных окружения

| Переменная                    | По умолчанию | Описание                                |
| ----------------------------- | ------------ | --------------------------------------- |
| `IS_PERSISTENT`               | `FALSE`      | Включить постоянное хранение            |
| `ANONYMIZED_TELEMETRY`        | `TRUE`       | Отключить сбор статистики использования |
| `CHROMA_SERVER_LOG_LEVEL`     | `INFO`       | Уровень подробности логов               |
| `CHROMA_MEMORY_LIMIT_BYTES`   | Нет          | Максимальная память для кэша сегментов  |
| `ALLOW_RESET`                 | `FALSE`      | Разрешить сброс всех данных через API   |
| `CHROMA_SERVER_AUTH_PROVIDER` | Нет          | Класс провайдера аутентификации         |

***

## Советы по производительности

### 1. Выберите подходящую модель эмбеддинга

| Модель                   | Размерность | Скорость | Качество     | Требуется GPU    |
| ------------------------ | ----------- | -------- | ------------ | ---------------- |
| `all-MiniLM-L6-v2`       | 384         | Быстро   | Хорошо       | Нет              |
| `all-mpnet-base-v2`      | 768         | Средняя  | Лучше        | Опционально      |
| `text-embedding-3-small` | 1536        | Быстро   | Отлично      | Только через API |
| `BAAI/bge-large-en-v1.5` | 1024        | Средняя  | Лучший выбор | Да               |

### 2. Пакетные upsert-операции для скорости

```python
# Добавляйте пакетами по 100-1000 для наилучшей производительности
BATCH_SIZE = 500

for i in range(0, len(all_documents), BATCH_SIZE):
    batch = all_documents[i:i+BATCH_SIZE]
    collection.add(
        documents=[d["text"] for d in batch],
        ids=[d["id"] for d in batch],
        metadatas=[d["meta"] for d in batch]
    )
    print(f"Пакет {i//BATCH_SIZE + 1} готов")
```

### 3. Настройка индекса HNSW

```python
collection = client.create_collection(
    name="optimized",
    metadata={
        "hnsw:space": "cosine",
        "hnsw:construction_ef": 200,  # Больше = лучшее качество индекса (медленнее сборка)
        "hnsw:search_ef": 100,        # Больше = лучшая полнота (медленнее поиск)
        "hnsw:M": 32,                 # Больше = лучшая полнота (больше памяти)
    }
)
```

### 4. Постоянный клиент для локального использования

```python
# Для разработки прямо на сервере Clore.ai
import chromadb

client = chromadb.PersistentClient(path="/workspace/chromadb/data")
# Сервер не требуется, быстрее для однопроцессного использования
```

***

## Устранение неполадок

### Проблема: Не удаётся подключиться к ChromaDB

```bash
# Проверьте, что контейнер запущен
docker ps | grep chromadb

# Проверьте логи
docker logs chromadb --tail 20

# Проверьте изнутри контейнера
docker exec chromadb curl http://localhost:8000/api/v1/heartbeat
```

### Проблема: Данные потеряны после перезапуска контейнера

```bash
# Убедитесь, что том смонтирован
docker inspect chromadb | grep Mounts -A 10

# Запустите снова с явным томом
docker run -d -p 8000:8000 \
  -v /workspace/chromadb/data:/chroma/chroma \
  -e IS_PERSISTENT=TRUE \
  chromadb/chroma:latest
```

### Проблема: Ошибки Out of memory

```bash
# Ограничьте кэш памяти
docker run -d -p 8000:8000 \
  -e CHROMA_MEMORY_LIMIT_BYTES=1073741824 \
  -v /workspace/chromadb/data:/chroma/chroma \
  chromadb/chroma:latest
```

### Проблема: Медленная генерация эмбеддингов

```bash
# Проверьте, используется ли GPU для эмбеддингов
python3 -c "
import torch
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2', device='cuda')
print(f'Модель эмбеддинга на: {model.device}')
"
```

### Проблема: Коллекция не найдена после перезапуска

```bash
# Проверьте, включена ли персистентность
curl http://localhost:8000/api/v1/collections
# Если пусто, IS_PERSISTENT не был установлен или том не был смонтирован
```

***

## Ссылки

* **GitHub**: <https://github.com/chroma-core/chroma>
* **Официальная документация**: <https://docs.trychroma.com>
* **Docker Hub**: <https://hub.docker.com/r/chromadb/chroma>
* **PyPI**: <https://pypi.org/project/chromadb>
* **Discord**: <https://discord.gg/MMeYNTmh3x>
* **CLORE.AI Маркетплейс**: <https://clore.ai/marketplace>

***

## Рекомендации Clore.ai по GPU

| Сценарий использования                   | Рекомендуемый GPU | Примерная стоимость на Clore.ai |
| ---------------------------------------- | ----------------- | ------------------------------- |
| Разработка/Тестирование                  | RTX 3090 (24GB)   | \~$0.12/gpu/hr                  |
| Production RAG                           | RTX 3090 (24GB)   | \~$0.12/gpu/hr                  |
| Высокопропускная способность эмбеддингов | RTX 4090 (24GB)   | \~$0.70/gpu/hr                  |

> 💡 Все примеры в этом руководстве можно развернуть на [Clore.ai](https://clore.ai/marketplace) GPU-серверах. Просматривайте доступные GPU и арендуйте по часам — без обязательств, с полным root-доступом.
