Серверы и 1С
Свой ИИ в закрытом контуре: когда облако под запретом
ИИ-помощник по внутренним документам без облака: собрали стенд на своих серверах — видеокарты в ESXi, Ollama и поиск по базе знаний на PostgreSQL.
Клиенты всё чаще спрашивают одно и то же: можно ли сделать ИИ-помощника, который знает внутренние регламенты, инструкции и документы компании? Сотрудник спрашивает «как оформить возврат поставщику?» и получает ответ со ссылкой на нужный пункт регламента, а не на статью из интернета.
Прежде чем обещать такое клиентам, мы решили собрать это сами. Не на слайдах, а на собственном стенде, на своём железе и своих документах: инструкциях, шаблонах договоров, заметках инженеров. Эта статья — о том, что получилось и обо что мы спотыкались.
Технически проще всего было бы подключить ChatGPT или Claude через API. Но мы сразу поставили себе то же условие, которое ставят службы безопасности наших клиентов: ни один документ не покидает периметр. Ни в облако, ни в чужой дата-центр, ни «только для обработки». Значит, всё — от модели до базы знаний — должно работать на своём железе, в закрытом контуре, без выхода в интернет.
Главное, что нужно понять про локальные модели
Когда говорят «запустить нейросеть у себя», обычно думают о мощности: процессоры, ядра, гигагерцы. На самом деле главное ограничение — объём видеопамяти. Модель должна целиком поместиться в память видеокарты, иначе её части начнут ездить через шину, и скорость упадёт в десятки раз.
Прикинуть можно на пальцах. Модель с 35 миллиардами параметров в сжатом формате (квантизация 4 бита) занимает около 20 ГБ. Плюс память на контекст — тот самый текст документов, который модель держит «в голове», пока отвечает. Поэтому карта на 24 ГБ — это минимум, с которого начинается разговор о серьёзных моделях, а карта на 10 ГБ подходит для моделей поменьше и вспомогательных задач.
Железо
Стенд мы собирали из того, что реально доступно небольшой компании. Основа — серверы Huawei 2288H V5 с быстрыми NVMe-массивами. Вычисления — видеокарты NVIDIA: RTX 3090 Ti на 24 ГБ под тяжёлые модели и RTX 3080 на 10 ГБ под вспомогательные задачи. Это потребительские карты, а не серверные ускорители за миллионы, и в этом весь смысл: при разумном бюджете получить достаточно памяти для моделей уровня 30+ миллиардов параметров.
Цена этого решения — инженерная работа. Потребительская видеокарта в сервере — это вопросы питания, охлаждения и, главное, виртуализации.
Самое трудное: пробросить видеокарту в виртуальную машину
На серверах стоит гипервизор VMware ESXi 8.0.3, а модели работают в виртуальных машинах на Ubuntu. Чтобы виртуальная машина получила видеокарту целиком и без потерь в скорости, используется проброс устройства (PCI passthrough). На серверных картах это работает из коробки. На потребительских — после нескольких настроек, о которых нигде не написано в одном месте.
На стороне сервера: в BIOS включаем поддержку 64-битного адресного пространства для устройств (Above 4G Decoding). Без неё карта с 24 ГБ памяти просто не помещается в адресное пространство, которое отводится устройствам.
На стороне ESXi: Host → Manage → Hardware → PCI Devices, отмечаем видеокарту для проброса и перезагружаем хост. Пробрасывать нужно обе функции карты — сам графический процессор и встроенный в него аудиоконтроллер HDMI.
На стороне виртуальной машины: загрузка через EFI, полное резервирование оперативной памяти (Reserve all guest memory — без этого проброс не включится) и несколько расширенных параметров:
pciPassthru.use64bitMMIO = "TRUE"
pciPassthru.64bitMMIOSizeGB = "64"
hypervisor.cpuid.v0 = "FALSE"
Размер окна MMIO считается от суммарной видеопамяти проброшенных карт, округлённой вверх до степени двойки. Параметр hypervisor.cpuid.v0 скрывает от драйвера, что он работает в виртуальной машине: старые драйверы NVIDIA для потребительских карт отказывались работать в виртуалке с ошибкой Code 43. Современные драйверы к этому относятся спокойно, но параметр не мешает.
Внутри виртуальной машины
Драйвер NVIDIA, Docker и NVIDIA Container Toolkit, который позволяет контейнерам видеть видеокарту:
sudo ubuntu-drivers install
# репозиторий NVIDIA Container Toolkit подключается по официальной инструкции
sudo apt install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
# проверка: контейнер должен увидеть карту
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
Если последняя команда показала табличку с вашей видеокартой, всё остальное — дело техники.
Мотор: Ollama
Модели запускает Ollama — сервер, который загружает модель в видеопамять и отвечает на запросы по HTTP. Две карты с разным объёмом памяти мы не объединяем в одну: на каждой своя копия Ollama со своим набором моделей. Тяжёлая модель живёт на 24 ГБ, распознавание и вспомогательные задачи — на 10 ГБ:
services:
ollama-main:
image: ollama/ollama:<версия> # фиксированная версия, не latest
container_name: ollama-main
restart: unless-stopped
environment:
- OLLAMA_KEEP_ALIVE=30m # не выгружать модель сразу после ответа
- OLLAMA_NUM_PARALLEL=2 # сколько запросов обрабатывать одновременно
- OLLAMA_FLASH_ATTENTION=1 # экономия памяти на длинном контексте
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ["0"] # RTX 3090 Ti
capabilities: [gpu]
volumes:
- ./ollama-main:/root/.ollama
ports:
- "127.0.0.1:11434:11434" # только локально!
ollama-aux:
image: ollama/ollama:<версия>
container_name: ollama-aux
restart: unless-stopped
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ["1"] # RTX 3080
capabilities: [gpu]
volumes:
- ./ollama-aux:/root/.ollama
ports:
- "127.0.0.1:11435:11434"
Обратите внимание на 127.0.0.1 в портах. В примерах из интернета почти всегда пишут просто "11434:11434", и это открывает Ollama на всю сеть. А у Ollama нет никакой авторизации: любой, кто дотянулся до порта, может задавать вопросы модели, загружать и удалять модели. В закрытом контуре, который строился ради безопасности, это была бы дыра посреди периметра. Доступ к моделям получают только наши сервисы на той же машине.
Фиксированная версия образа вместо latest — по той же логике: обновление должно быть решением, а не сюрпризом после перезапуска контейнера.
Память компании: RAG на PostgreSQL
Сама модель ничего не знает о регламентах компании. Чтобы она отвечала по документам, используется подход RAG: перед ответом система находит в базе знаний несколько подходящих фрагментов и подкладывает их модели вместе с вопросом. Модель отвечает уже не «из головы», а по найденному тексту.
Базой знаний служит PostgreSQL с расширением pgvector. Документы режутся на фрагменты по смысловым границам — разделам и пунктам, а не по количеству символов, — и для каждого фрагмента считается вектор, числовой «отпечаток смысла»:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE chunks (
id bigserial PRIMARY KEY,
doc text NOT NULL, -- название документа
section text, -- раздел или пункт
body text NOT NULL, -- сам фрагмент
embedding vector(1024) NOT NULL
);
CREATE INDEX ON chunks USING hnsw (embedding vector_cosine_ops);
Поиск — это запрос «найди фрагменты, ближайшие по смыслу к вопросу»:
import requests, psycopg
OLLAMA = "http://127.0.0.1:11435"
def embed(text: str) -> list[float]:
r = requests.post(f"{OLLAMA}/api/embed", json={"model": "bge-m3", "input": text})
return r.json()["embeddings"][0]
def find_context(question: str, k: int = 5):
vec = str(embed(question))
with psycopg.connect("dbname=kb") as db:
return db.execute(
"SELECT doc, section, body FROM chunks "
"ORDER BY embedding <=> %s::vector LIMIT %s",
(vec, k),
).fetchall()
Поля doc и section здесь не для красоты. В ответе модель обязана указать, из какого документа и пункта она взяла информацию. Это главная защита от «галлюцинаций»: если ответ нельзя подтвердить ссылкой на регламент, сотрудник это видит сразу.
Глаза и уши
Часть знаний компании хранится не в тексте, а в схемах и сканах. Для них мы подключили визуальную модель MiniCPM-V 2.6: она разбирает схемы и изображения и превращает их в текст, который потом попадает в ту же базу знаний.
А чтобы вопрос можно было наговорить голосом, добавили локальное распознавание речи на Faster-Whisper — тоже без единого обращения во внешний мир:
from faster_whisper import WhisperModel
model = WhisperModel("large-v3", device="cuda", compute_type="float16")
segments, _ = model.transcribe("vopros.ogg", language="ru", vad_filter=True)
question = " ".join(s.text.strip() for s in segments)
Параметр vad_filter отрезает тишину и шум, и распознавание коротких голосовых сообщений заметно ускоряется.
Дирижёр
Над всем этим работает оркестратор Hermes Agent. Он решает, какую модель позвать для какой задачи, ходит в базу знаний, собирает ответ и следит за очередью. Когда стенд перестал справляться с нагрузкой, мы обновили его до версии v0.20.6 и подключили второй рабочий сервер с двумя дополнительными видеокартами. Оркестратор раздаёт задачи между серверами сам, и добавление мощности не требует перестраивать систему.
Основную работу с базой знаний выполняют модели Qwen 35B и Gemma 26B, визуальные задачи — MiniCPM-V.
Честно о границах
Локальные модели не заменяют лучшие облачные модели во всём. В сложных рассуждениях, длинных цепочках логики и творческих задачах облако пока сильнее. Но для задачи «найди в наших документах и ответь со ссылкой» локальная модель с хорошей базой знаний справляется уверенно, отвечает за секунды и не отправляет за периметр ни одного байта. А для компаний с коммерческой тайной или персональными данными это часто единственный допустимый вариант.
Что из этого вынести
Свой ИИ в закрытом контуре — это реально и без бюджета дата-центра. Но это не «скачать программу», а инфраструктурный проект: подбор железа под объём видеопамяти, виртуализация с пробросом карт, безопасная публикация моделей, база знаний с поиском по смыслу и честная проверка ответов. Все грабли из этой статьи мы собрали на своём стенде, чтобы клиенты на них не наступали. Если вы думаете о собственном ИИ в закрытом контуре, поможем оценить, какое железо нужно под ваши задачи, и собрать систему — от выбора серверов до интерфейса для сотрудников.
Ещё проекты
Похожие объекты
Серверы и 1С
Zabbix тревожит сервер 1С: ложная тревога и настоящая настройка памяти SQL
Серверы клиентов у нас под мониторингом Zabbix: он пишет в Telegram, когда что-то идёт не так. Один из серверов 1С стал регулярно присылать предупреждение «Memory Pages/sec is too high (over 1000 for 5m)» со значениями около 4000.
Серверы и 1С
Медицинская система только по секретной ссылке: обратный прокси с ежемесячной ротацией токена
Медицинская организация пользуется облачной медицинской информационной системой (МИС). Вендор системы умеет ограничивать доступ по IP-адресу, но у клиники несколько площадок, сотрудники работают и из дома, и с мобильных устройств, а провайдеры меняют адреса.
Серверы и 1С
Секретная ссылка вместо белого списка IP
Медицинская организация работает в облачной медицинской информационной системе. Страница входа в систему открыта в интернет, как у любого сайта.