MAATRIX / Блог / Сколько RAM нужно для AnythingLLM

Сколько RAM нужно для AnythingLLM

Сколько RAM нужно для AnythingLLM

MAATRIX

AnythingLLM выглядит скромно: Node-приложение, чат и папка с документами. А потом контейнер тихо исчезает на середине загрузки первой партии PDF, в логе остаётся JavaScript heap out of memory, и вопрос «сколько RAM нужно» становится срочным. Ниже — куда уходит память, как померить свой расход и по какой формуле считать сервер.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Короткий ответ: сколько RAM нужно AnythingLLM

Запрос «anythingllm требования» приводит к строчке из документации разработчика: два ядра, 2 ГБ RAM, немного диска. Это правда про запуск, а не про работу. Приложение живёт в двух режимах: в покое — чат-интерфейс, ждущий ответа от чужого API; при загрузке документа — конвейер из парсера, эмбеддера и векторной базы, который на минуту-две становится самым прожорливым процессом машины.

Отсюда главная развилка: считается ли модель на этом же сервере. Если внешняя (OpenAI, Anthropic, OpenRouter, свой шлюз или Ollama на соседней машине) — речь про единицы гигабайт. Если локальная, память определяет уже не AnythingLLM, а веса.

КонфигурацияЧто реально работаетГде упрётесь
2 vCPU / 2 ГБЧат к внешнему API, пара десятков небольших документовПервый скан в PDF, скрапинг сайта, параллельная загрузка папки
2 vCPU / 4 ГБРабочий минимум: индексация, встроенный эмбеддер, LanceDBОдновременная переиндексация и активные чаты
4 vCPU / 8 ГБКоманда 10–15 человек, тысячи страниц, Qdrant в соседнем контейнереТолько локальная модель
8 vCPU / 16 ГБТо же плюс модель 7–8B в Q4 на CPUСкорость генерации, а не память

Дальше — откуда эти числа, чтобы пересчитать их под свою библиотеку.

Из чего складывается память: один контейнер, три процесса

Образ выглядит как одно приложение, но внутри работают минимум два процесса Node: сервер (/app/server/index.js) и коллектор (/app/collector/index.js). Фронтенд собран в статику и отдельной памяти почти не просит. Команда ниже выполняется на хосте, поэтому не зависит от содержимого образа:

docker top anythingllm -eo pid,rss,args

Вы увидите две строки с node и раздельными значениями RSS. Деталь важная: NODE_OPTIONS и лимиты применяются к обоим сразу, и бюджет памяти делится на двоих.

Что держит сервер. Express с маршрутами API, Prisma поверх SQLite (storage/anythingllm.db), нативный модуль LanceDB, веб-сокеты для агентов и — если эмбеддер встроенный — сессия ONNX Runtime с моделью. Ключевой момент, на котором путаются в замерах: бо́льшая часть этого лежит вне кучи V8, потому что Prisma, ORT и LanceDB — нативный код со своим аллокатором. heapUsed может показывать 200 МБ при полутора гигабайтах RSS, и это не ошибка.

Что держит коллектор. Парсеры по форматам (PDF, DOCX, XLSX, HTML), очередь разбора, Chromium для скрапинга ссылок и OCR-воркер для сканов. В покое он почти ничего не делает — потому средний расход и обманчив.

Цена входа каждого процесса — сотни мегабайт RSS ещё до первого запроса. Сверху ложатся две растущие строки:

  • Встроенный эмбеддер. Модель all-MiniLM-L6-v2 — 22,7 млн параметров: в fp32 около 91 МБ весов, в квантованной ONNX-сборке меньше. К весам добавляется арена тензоров и пул потоков ORT по числу видимых ядер: на 16-ядерной машине эта строка бюджета толще, чем на двухъядерной.
  • Векторный индекс. LanceDB работает файлами и отображает их в память. Вектор встроенного эмбеддера — 384 измерения по 4 байта, то есть 1,5 КБ; у text-embedding-3-small 1536 измерений — уже 6 КБ на чанк, и сто тысяч чанков дают 600 МБ индекса, который при поиске подтягивается страницами в кеш.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть AnythingLLM

Пики важнее покоя: индексация, Chromium и OCR

Сервер падает не оттого, что в чате сидят пять человек. Он падает на одной операции, которая длится полторы минуты.

Файл существует одновременно в нескольких видах. Конвейер такой: оригинал → коллектор разбирает его в текст → текст ложится как JSON в storage/documents/ → сервер читает этот JSON → режет на чанки → отправляет эмбеддеру → складывает векторы в vector-cache/ и LanceDB. На пике в памяти живут сразу буфер файла, распарсенный текст, массив чанков и тело запроса к эмбеддеру. Плюс поправка: строки в JavaScript — UTF-16, так что «текстовый мегабайт» превращается в два.

Сканы дороже текста на порядок. Страница A4 в 300 dpi — это 2480 × 3508 пикселей; растр в RGBA занимает около 33 МБ, и это один буфер, до всякого распознавания. OCR-воркер держит свои копии и языковые данные.

Chromium в коллекторе. «Загрузить сайт по ссылке» поднимает headless-браузер, а одна современная страница со скриптами — сотни мегабайт, сравнимо со всем остальным AnythingLLM. На машине с 2 ГБ скрапинг — самый быстрый способ увидеть перезапуск контейнера.

Переиндексация из кэша не бесплатна. Векторы кэшируются в storage/vector-cache/ в виде JSON, и при разборе такого файла в памяти одновременно лежат строка и массив чисел: 5 000 чанков по 384 измерения — это 1,9 млн чисел, около 15 МБ массивом JS плюс сама строка.

И отдельный предел, который памятью не лечится: у V8 жёсткий потолок длины строки — на 64-битной сборке 2^29−24 символа, чуть меньше 512 МБ. Гигабайтная выгрузка уронит разбор с RangeError: Invalid string length, сколько RAM вы бы ни добавили; такие дампы режьте на части до загрузки.

Как померить свой расход, а не гадать

Мерить надо не покой, а конкретную операцию. Самый честный способ — счётчик пика в cgroup v2: сбросить, загрузить тяжёлый документ через интерфейс, прочитать.

CID=$(docker inspect -f '{{.Id}}' anythingllm)
CG=/sys/fs/cgroup/system.slice/docker-$CID.scope
echo reset > $CG/memory.peak
# загрузите самый большой документ и дождитесь окончания Save and Embed
awk '{printf "%.0f MiB\n", 

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть AnythingLLM

Пики важнее покоя: индексация, Chromium и OCR

Сервер падает не оттого, что в чате сидят пять человек. Он падает на одной операции, которая длится полторы минуты.

Файл существует одновременно в нескольких видах. Конвейер такой: оригинал → коллектор разбирает его в текст → текст ложится как JSON в storage/documents/ → сервер читает этот JSON → режет на чанки → отправляет эмбеддеру → складывает векторы в vector-cache/ и LanceDB. На пике в памяти живут сразу буфер файла, распарсенный текст, массив чанков и тело запроса к эмбеддеру. Плюс поправка: строки в JavaScript — UTF-16, так что «текстовый мегабайт» превращается в два.

Сканы дороже текста на порядок. Страница A4 в 300 dpi — это 2480 × 3508 пикселей; растр в RGBA занимает около 33 МБ, и это один буфер, до всякого распознавания. OCR-воркер держит свои копии и языковые данные.

Chromium в коллекторе. «Загрузить сайт по ссылке» поднимает headless-браузер, а одна современная страница со скриптами — сотни мегабайт, сравнимо со всем остальным AnythingLLM. На машине с 2 ГБ скрапинг — самый быстрый способ увидеть перезапуск контейнера.

Переиндексация из кэша не бесплатна. Векторы кэшируются в storage/vector-cache/ в виде JSON, и при разборе такого файла в памяти одновременно лежат строка и массив чисел: 5 000 чанков по 384 измерения — это 1,9 млн чисел, около 15 МБ массивом JS плюс сама строка.

И отдельный предел, который памятью не лечится: у V8 жёсткий потолок длины строки — на 64-битной сборке 2^29−24 символа, чуть меньше 512 МБ. Гигабайтная выгрузка уронит разбор с RangeError: Invalid string length, сколько RAM вы бы ни добавили; такие дампы режьте на части до загрузки.

Как померить свой расход, а не гадать

Мерить надо не покой, а конкретную операцию. Самый честный способ — счётчик пика в cgroup v2: сбросить, загрузить тяжёлый документ через интерфейс, прочитать.

CID=$(docker inspect -f '{{.Id}}' anythingllm)
CG=/sys/fs/cgroup/system.slice/docker-$CID.scope
echo reset > $CG/memory.peak
# загрузите самый большой документ и дождитесь окончания Save and Embed
awk '{printf "%.0f MiB\n", $1/1048576}' $CG/memory.peak

Файл memory.peak появился в ядре 5.19 (Ubuntu 24.04 — 6.8, Debian 12 — 6.1), сброс записью reset работает с 6.8; на cgroup v1 аналог — memory.max_usage_in_bytes.

Разложить пик по процессам помогает docker top: снимок во время индексации показывает, кто вырос — сервер или коллектор.

watch -n 2 "docker top anythingllm -eo rss,args | sort -rn | head -4"

Про docker stats важная оговорка: на cgroup v2 в memory.current попадает страничный кеш, а LanceDB как раз работает через отображение файлов. Индекс на пару гигабайт «съест» память в отчёте, хотя ядро отдаст её обратно под давлением без всякого OOM. Планировать надо по анонимным страницам плюс запас на пик:

docker exec anythingllm grep -E '^(anon|file) ' /sys/fs/cgroup/memory.stat
docker exec anythingllm node -e "console.log((require('v8').getHeapStatistics().heap_size_limit/1048576).toFixed(0)+' MB')"

Вторая команда показывает потолок кучи V8 — но у нового процесса Node, а не у работающего сервера. Node подгоняет размер кучи под доступную память, поэтому на контейнере без лимита значение окажется заметно выше, чем при mem_limit: 2g. Именно на этом расхождении машины и ломаются.

Две разные смерти: `Reached heap limit` и `Exited (137)`

Диагноз ставится одной командой:

docker inspect anythingllm --format '{{.State.OOMKilled}} {{.State.ExitCode}}'

Вариант первый — упёрся сам V8. Код выхода 134, а в docker logs anythingllm --tail 60 перед смертью лежит характерный блок:

<--- Last few GCs --->
[42:0x6f2c1a0]   918273 ms: Mark-Compact 2020.4 (2083.9) -> 2019.1 (2084.2) MB,
                 1471.9 / 0.0 ms  (average mu = 0.121, current mu = 0.038)
                 allocation failure; scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

До системного лимита дело не дошло: процессу не хватило кучи. По пути в строках стека — /app/server или /app/collector — видно, какой из двух процессов умер. Смерть коллектора коварнее: чат продолжает работать, а документы просто перестают разбираться.

Вариант второй — пришло ядро. true 137, и подтверждение в журнале:

journalctl -k --since "6 hours ago" | grep -i "out of memory"
Memory cgroup out of memory: Killed process 3412 (node) total-vm:4218364kB,
anon-rss:1902104kB, file-rss:41216kB, shmem-rss:0kB, UID:0 oom_score_adj:0

anon-rss в момент смерти — ваш реальный пик, его удобно сравнить с бюджетом машины.

Теперь ловушка, специфичная именно для AnythingLLM: NODE_OPTIONS применяется ко всем процессам Node в контейнере. Ставите --max-old-space-size=3072 на машине с 4 ГБ — и разрешаете серверу и коллектору взять по 3 ГБ каждому. V8 при этом не начинает агрессивную сборку мусора вовремя, ядро приходит раньше, и вместо понятного FATAL ERROR вы получаете голый 137 без строчки диагностики. Разнести значения по процессам внутри одного контейнера штатно нельзя, поэтому правило простое: примерно треть лимита контейнера на процесс, для 4 ГБ — --max-old-space-size=1400.

Обратный перекос тоже бывает: куча меньше, чем нужно операции, — и вы стабильно ловите 134 при свободной памяти машины. Тогда потолок поднимают, но вместе с mem_limit:

docker update --memory 4g --memory-swap 4g anythingllm

Симптомы, не связанные с памятью, — обрыв стрима, откат настроек, EACCES в storage — разобраны в материале про частые ошибки AnythingLLM.

Формула под свою нагрузку и как ужать потребление

Считать удобнее слагаемыми, а не «по опыту»:

RAM ≈ 0,7 ГБ (два процесса Node в покое) + пик разбора (2–3 × размер самого тяжёлого документа, но не меньше 0,5 ГБ) + 0,3–0,6 ГБ на встроенный эмбеддер + векторный индекс + модель, если она на этой же машине.

Три сценария:

  • Один человек, внешний API, 200 офисных документов. 0,7 + 0,6 + 0,4 ≈ 1,7 ГБ на пике. 4 ГБ — с запасом, 2 ГБ — впритык и без сканов, скрапинга и параллельной загрузки папок.
  • Отдел 10–15 человек, тысячи страниц, Qdrant рядом. 0,7 + 1,2 + 0,5 + около гигабайта на векторную базу ≈ 3,5 ГБ пиково. 8 ГБ: формально проходит и 4, но переиндексация в рабочее время съест весь зазор.
  • AnythingLLM и Ollama на одной машине. Бюджет определяют веса: 7–8 миллиардов параметров в Q4_K_M — порядка 4,4–4,9 ГБ. Плюс KV-кэш, который считается точно: 2 (ключи и значения) × 32 слоя × 8 KV-голов × 128 на голову × 2 байта = 128 КБ на токен, то есть около 1 ГБ на контекст в 8k, а OLLAMA_NUM_PARALLEL эту величину множит. Итого ~6 ГБ под модель плюс 2 ГБ под AnythingLLM плюс система — 16 ГБ. Цифры по моделям — в таблице RAM для Ollama.

Что снимает нагрузку, от самого эффективного к косметике:

  1. Вынести эмбеддер. EMBEDDING_ENGINE=openai или Ollama на другой машине убирают из процесса и ONNX Runtime, и его пул потоков — сотни мегабайт запаса без потери функций.
  2. Грузить документы партиями. Пик определяется одновременностью, а не объёмом библиотеки: 30 файлов за раз вместо папки на 500 — и всплеск укладывается в бюджет. Почему часть файлов не доходит до векторов — в отдельном разборе.
  3. Не скрапить сайты с маленькой машины. Chromium дороже, чем всё приложение в покое.
  4. Поставить жёсткие лимиты. Тогда при всплеске умрёт контейнер, а не SSH-сессия и не база рядом.
services:
  anythingllm:
    image: mintplexlabs/anythingllm:latest
    container_name: anythingllm
    mem_limit: 4g
    memswap_limit: 4g
    environment:
      - STORAGE_DIR=/app/server/storage
      - NODE_OPTIONS=--max-old-space-size=1400
      - EMBEDDING_ENGINE=openai
      - VECTOR_DB=lancedb
    volumes:
      - ./storage:/app/server/storage
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"
    restart: unless-stopped
  1. Swap — страховка, а не решение. Двух гигабайт файла подкачки при vm.swappiness=10 хватает, чтобы пережить разовый пик индексации. Но если в своп уедет рабочий набор, интерфейс начнёт отвечать заметно медленнее — подробности в статье про то, что делать при нехватке RAM.

Какой сервер под AnythingLLM брать в MAATRIX

Честный минимум: 2 vCPU, 4 ГБ RAM, 40 ГБ NVMe. Вариант «AnythingLLM как интерфейс к внешней модели»: чат, документы, RAG. Два гигабайта из документации формально проходят — если вынести эмбеддер наружу, грузить файлы мелкими партиями и не трогать скрапинг сайтов. Но запаса там нет: первый скан в PDF или параллельная загрузка папки заканчиваются OOMKilled, а ваш вечер — чтением dmesg. Разница в цене между 2 и 4 ГБ несопоставима со стоимостью такого вечера.

Комфортный вариант: 4 vCPU, 8 ГБ RAM, 80–120 ГБ NVMe. Команда до полутора десятков человек, библиотека на тысячи страниц, место под Qdrant или Chroma в соседнем контейнере и переиндексация при смене эмбеддера в рабочее время, а не ночью. Четыре ядра здесь не про чат, а про скорость разбора документов. Если векторная база будет отдельным сервисом — как поднять её для RAG.

С локальной моделью: 8 vCPU, 16 ГБ RAM, 160 ГБ NVMe. Это про работоспособность, а не про скорость: генерация 7B на процессоре идёт темпом медленно печатающего человека. Нужны быстрые ответы — инференс дешевле вынести на GPU-сервер.

Локация — Лондон (UK). Довод прикладной: со встроенным эмбеддером приложение при первом запуске идёт за ONNX-моделью на huggingface.co, а образ тянется с Docker Hub — с российских адресов оба ресурса отвечают через раз. С британской площадки всё качается напрямую, OpenAI и Anthropic отвечают без региональных 403, пинг до Европы — десятки миллисекунд. США (Нью-Йорк) берут, когда нужен именно американский адрес; Россия — когда документы подпадают под 152-ФЗ, но тогда модель придётся держать локально, а это сразу строка с 16 ГБ. Сравнение площадок — в обзоре VPS в Великобритании для нейросетей.

Разворачивать руками не нужно: AnythingLLM есть в каталоге приложений apps.maatrix.io — приложение ставится автоматически при заказе сервера, работает на Ubuntu и Debian, а доступы (адрес панели и ключи) появляются в личном кабинете, в разделе «Доступ». Останется войти, подключить провайдера модели и загрузить первые документы; настройка по шагам — в статье про установку AnythingLLM на VPS. Оплата — картами российских банков, по СБП, криптовалютой или токеном MAAT. Сомневаетесь в конфигурации — опишите профиль: сколько человек, какие документы, где считается модель.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть AnythingLLM
/1048576}' $CG/memory.peak

Файл memory.peak появился в ядре 5.19 (Ubuntu 24.04 — 6.8, Debian 12 — 6.1), сброс записью reset работает с 6.8; на cgroup v1 аналог — memory.max_usage_in_bytes.

Разложить пик по процессам помогает docker top: снимок во время индексации показывает, кто вырос — сервер или коллектор.

watch -n 2 "docker top anythingllm -eo rss,args | sort -rn | head -4"

Про docker stats важная оговорка: на cgroup v2 в memory.current попадает страничный кеш, а LanceDB как раз работает через отображение файлов. Индекс на пару гигабайт «съест» память в отчёте, хотя ядро отдаст её обратно под давлением без всякого OOM. Планировать надо по анонимным страницам плюс запас на пик:

docker exec anythingllm grep -E '^(anon|file) ' /sys/fs/cgroup/memory.stat
docker exec anythingllm node -e "console.log((require('v8').getHeapStatistics().heap_size_limit/1048576).toFixed(0)+' MB')"

Вторая команда показывает потолок кучи V8 — но у нового процесса Node, а не у работающего сервера. Node подгоняет размер кучи под доступную память, поэтому на контейнере без лимита значение окажется заметно выше, чем при mem_limit: 2g. Именно на этом расхождении машины и ломаются.

Две разные смерти: `Reached heap limit` и `Exited (137)`

Диагноз ставится одной командой:

docker inspect anythingllm --format '{{.State.OOMKilled}} {{.State.ExitCode}}'

Вариант первый — упёрся сам V8. Код выхода 134, а в docker logs anythingllm --tail 60 перед смертью лежит характерный блок:

<--- Last few GCs --->
[42:0x6f2c1a0]   918273 ms: Mark-Compact 2020.4 (2083.9) -> 2019.1 (2084.2) MB,
                 1471.9 / 0.0 ms  (average mu = 0.121, current mu = 0.038)
                 allocation failure; scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

До системного лимита дело не дошло: процессу не хватило кучи. По пути в строках стека — /app/server или /app/collector — видно, какой из двух процессов умер. Смерть коллектора коварнее: чат продолжает работать, а документы просто перестают разбираться.

Вариант второй — пришло ядро. true 137, и подтверждение в журнале:

journalctl -k --since "6 hours ago" | grep -i "out of memory"
Memory cgroup out of memory: Killed process 3412 (node) total-vm:4218364kB,
anon-rss:1902104kB, file-rss:41216kB, shmem-rss:0kB, UID:0 oom_score_adj:0

anon-rss в момент смерти — ваш реальный пик, его удобно сравнить с бюджетом машины.

Теперь ловушка, специфичная именно для AnythingLLM: NODE_OPTIONS применяется ко всем процессам Node в контейнере. Ставите --max-old-space-size=3072 на машине с 4 ГБ — и разрешаете серверу и коллектору взять по 3 ГБ каждому. V8 при этом не начинает агрессивную сборку мусора вовремя, ядро приходит раньше, и вместо понятного FATAL ERROR вы получаете голый 137 без строчки диагностики. Разнести значения по процессам внутри одного контейнера штатно нельзя, поэтому правило простое: примерно треть лимита контейнера на процесс, для 4 ГБ — --max-old-space-size=1400.

Обратный перекос тоже бывает: куча меньше, чем нужно операции, — и вы стабильно ловите 134 при свободной памяти машины. Тогда потолок поднимают, но вместе с mem_limit:

docker update --memory 4g --memory-swap 4g anythingllm

Симптомы, не связанные с памятью, — обрыв стрима, откат настроек, EACCES в storage — разобраны в материале про частые ошибки AnythingLLM.

Формула под свою нагрузку и как ужать потребление

Считать удобнее слагаемыми, а не «по опыту»:

RAM ≈ 0,7 ГБ (два процесса Node в покое) + пик разбора (2–3 × размер самого тяжёлого документа, но не меньше 0,5 ГБ) + 0,3–0,6 ГБ на встроенный эмбеддер + векторный индекс + модель, если она на этой же машине.

Три сценария:

  • Один человек, внешний API, 200 офисных документов. 0,7 + 0,6 + 0,4 ≈ 1,7 ГБ на пике. 4 ГБ — с запасом, 2 ГБ — впритык и без сканов, скрапинга и параллельной загрузки папок.
  • Отдел 10–15 человек, тысячи страниц, Qdrant рядом. 0,7 + 1,2 + 0,5 + около гигабайта на векторную базу ≈ 3,5 ГБ пиково. 8 ГБ: формально проходит и 4, но переиндексация в рабочее время съест весь зазор.
  • AnythingLLM и Ollama на одной машине. Бюджет определяют веса: 7–8 миллиардов параметров в Q4_K_M — порядка 4,4–4,9 ГБ. Плюс KV-кэш, который считается точно: 2 (ключи и значения) × 32 слоя × 8 KV-голов × 128 на голову × 2 байта = 128 КБ на токен, то есть около 1 ГБ на контекст в 8k, а OLLAMA_NUM_PARALLEL эту величину множит. Итого ~6 ГБ под модель плюс 2 ГБ под AnythingLLM плюс система — 16 ГБ. Цифры по моделям — в таблице RAM для Ollama.

Что снимает нагрузку, от самого эффективного к косметике:

  1. Вынести эмбеддер. EMBEDDING_ENGINE=openai или Ollama на другой машине убирают из процесса и ONNX Runtime, и его пул потоков — сотни мегабайт запаса без потери функций.
  2. Грузить документы партиями. Пик определяется одновременностью, а не объёмом библиотеки: 30 файлов за раз вместо папки на 500 — и всплеск укладывается в бюджет. Почему часть файлов не доходит до векторов — в отдельном разборе.
  3. Не скрапить сайты с маленькой машины. Chromium дороже, чем всё приложение в покое.
  4. Поставить жёсткие лимиты. Тогда при всплеске умрёт контейнер, а не SSH-сессия и не база рядом.
services:
  anythingllm:
    image: mintplexlabs/anythingllm:latest
    container_name: anythingllm
    mem_limit: 4g
    memswap_limit: 4g
    environment:
      - STORAGE_DIR=/app/server/storage
      - NODE_OPTIONS=--max-old-space-size=1400
      - EMBEDDING_ENGINE=openai
      - VECTOR_DB=lancedb
    volumes:
      - ./storage:/app/server/storage
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"
    restart: unless-stopped
  1. Swap — страховка, а не решение. Двух гигабайт файла подкачки при vm.swappiness=10 хватает, чтобы пережить разовый пик индексации. Но если в своп уедет рабочий набор, интерфейс начнёт отвечать заметно медленнее — подробности в статье про то, что делать при нехватке RAM.

Какой сервер под AnythingLLM брать в MAATRIX

Честный минимум: 2 vCPU, 4 ГБ RAM, 40 ГБ NVMe. Вариант «AnythingLLM как интерфейс к внешней модели»: чат, документы, RAG. Два гигабайта из документации формально проходят — если вынести эмбеддер наружу, грузить файлы мелкими партиями и не трогать скрапинг сайтов. Но запаса там нет: первый скан в PDF или параллельная загрузка папки заканчиваются OOMKilled, а ваш вечер — чтением dmesg. Разница в цене между 2 и 4 ГБ несопоставима со стоимостью такого вечера.

Комфортный вариант: 4 vCPU, 8 ГБ RAM, 80–120 ГБ NVMe. Команда до полутора десятков человек, библиотека на тысячи страниц, место под Qdrant или Chroma в соседнем контейнере и переиндексация при смене эмбеддера в рабочее время, а не ночью. Четыре ядра здесь не про чат, а про скорость разбора документов. Если векторная база будет отдельным сервисом — как поднять её для RAG.

С локальной моделью: 8 vCPU, 16 ГБ RAM, 160 ГБ NVMe. Это про работоспособность, а не про скорость: генерация 7B на процессоре идёт темпом медленно печатающего человека. Нужны быстрые ответы — инференс дешевле вынести на GPU-сервер.

Локация — Лондон (UK). Довод прикладной: со встроенным эмбеддером приложение при первом запуске идёт за ONNX-моделью на huggingface.co, а образ тянется с Docker Hub — с российских адресов оба ресурса отвечают через раз. С британской площадки всё качается напрямую, OpenAI и Anthropic отвечают без региональных 403, пинг до Европы — десятки миллисекунд. США (Нью-Йорк) берут, когда нужен именно американский адрес; Россия — когда документы подпадают под 152-ФЗ, но тогда модель придётся держать локально, а это сразу строка с 16 ГБ. Сравнение площадок — в обзоре VPS в Великобритании для нейросетей.

Разворачивать руками не нужно: AnythingLLM есть в каталоге приложений apps.maatrix.io — приложение ставится автоматически при заказе сервера, работает на Ubuntu и Debian, а доступы (адрес панели и ключи) появляются в личном кабинете, в разделе «Доступ». Останется войти, подключить провайдера модели и загрузить первые документы; настройка по шагам — в статье про установку AnythingLLM на VPS. Оплата — картами российских банков, по СБП, криптовалютой или токеном MAAT. Сомневаетесь в конфигурации — опишите профиль: сколько человек, какие документы, где считается модель.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть AnythingLLM

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Хватит ли 2 ГБ, как написано в документации?

Для чата к внешнему API и пары десятков небольших документов — да. Первый же скан в PDF, загрузка сайта по ссылке или партия файлов разом кладут такую машину; проверка — docker inspect anythingllm --format '{{.State.OOMKilled}}'. Рабочий минимум без сюрпризов — 4 ГБ.

docker stats показывает 1,8 ГБ, а heapUsed — 200 МБ. Кто врёт?

Никто. Куча V8 — только часть расхода: ONNX Runtime, LanceDB и движок Prisma выделяют память мимо неё, а в memory.current на cgroup v2 попадает ещё и страничный кеш от файлов индекса. Реальные анонимные страницы — строка anon в /sys/fs/cgroup/memory.stat.

Снизит ли расход вынос векторной базы в Qdrant?

На той же машине — почти нет: LanceDB работает через отображение файлов и своей кучи не держит, а Qdrant добавит около гигабайта. Выигрыш появляется, только когда база переезжает на отдельный сервер. Больше даёт вынос эмбеддера: EMBEDDING_ENGINE=openai убирает из процесса ONNX Runtime вместе с пулом потоков.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.