Сколько RAM нужно для AnythingLLM
AnythingLLM выглядит скромно: Node-приложение, чат и папка с документами. А потом контейнер тихо исчезает на середине загрузки первой партии PDF, в логе остаётся JavaScript heap out of memory, и вопрос «сколько RAM нужно» становится срочным. Ниже — куда уходит память, как померить свой расход и по какой формуле считать сервер.
Содержание
- Короткий ответ: сколько RAM нужно AnythingLLM
- Из чего складывается память: один контейнер, три процесса
- Пики важнее покоя: индексация, Chromium и OCR
- Как померить свой расход, а не гадать
- Две разные смерти: `Reached heap limit` и `Exited (137)`
- Формула под свою нагрузку и как ужать потребление
- Какой сервер под AnythingLLM брать в MAATRIX
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество 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-small1536 измерений — уже 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.
Что снимает нагрузку, от самого эффективного к косметике:
- Вынести эмбеддер.
EMBEDDING_ENGINE=openai или Ollama на другой машине убирают из процесса и ONNX Runtime, и его пул потоков — сотни мегабайт запаса без потери функций. - Грузить документы партиями. Пик определяется одновременностью, а не объёмом библиотеки: 30 файлов за раз вместо папки на 500 — и всплеск укладывается в бюджет. Почему часть файлов не доходит до векторов — в отдельном разборе.
- Не скрапить сайты с маленькой машины. Chromium дороже, чем всё приложение в покое.
- Поставить жёсткие лимиты. Тогда при всплеске умрёт контейнер, а не 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
- 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.
Что снимает нагрузку, от самого эффективного к косметике:
- Вынести эмбеддер.
EMBEDDING_ENGINE=openaiили Ollama на другой машине убирают из процесса и ONNX Runtime, и его пул потоков — сотни мегабайт запаса без потери функций. - Грузить документы партиями. Пик определяется одновременностью, а не объёмом библиотеки: 30 файлов за раз вместо папки на 500 — и всплеск укладывается в бюджет. Почему часть файлов не доходит до векторов — в отдельном разборе.
- Не скрапить сайты с маленькой машины. Chromium дороже, чем всё приложение в покое.
- Поставить жёсткие лимиты. Тогда при всплеске умрёт контейнер, а не 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
- 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 — десятки моделей в одном окне. Оплата картой РФ и по СБП.