|
|
|
Professor Seleznov
|
У меня на столе стоит небольшая золотистая коробочка размером чуть больше Mac mini. Внутри — приватный AI-сервер: чат с локальной 26B-моделью, поисковая индексация моих документов с GPU-парсингом, конструктор агентов в Dify, RAGFlow для тяжёлого парсинга PDF, мониторинг, бэкапы, опциональный кластер из двух машин по QSFP 200G. Тридцать контейнеров, пять минут на установку черезsudo bashinstall.sh, ноль обращений к внешним API. Я делал это не как pet-project, а под себя — мне нужна была машина для работы с корпоративными документами, договорами и регламентами, которые ни при каких условиях нельзя отдавать в облачные ассистенты. Сборка получилась самостоятельным дистрибутивом — назвал его AGmind, выложил на GitHub под Apache 2.0. В статье разберу: — из чего собран стек и зачем там каждый компонент; — почему RAGFlow пришлось пересобрать с нуля и что я туда добавил; — как устроен кластер из двух Spark'ов; — пять конкретных грабель GB10, которые я ловил вечерами; — почему Claude Code за месяц превратил один из этих компонентов в работающий продукт, но при этом не заменил собственно программиста. Зачем мне понадобился свой AI-сервер Облачные ассистенты — OpenAI, Anthropic, Gemini — прекрасно работают с тем, что не страшно отдавать наружу. Как только речь заходит про корпоративные документы, юридические договоры, медкарты, внутренние регламенты — каждый второй compliance-офицер заворачивает SaaS, и совершенно справедливо. Это не вопрос того, насколько хорош TLS у вендора. Это вопрос того, что данные физически уходят на чужие серверы, и дальше доверять можно только бумажкам. Self-hosted-альтернатив я перебрал руками. Open WebUI — нормальный чат, но с документами работает плохо. Dify — мощный workflow-конструктор и приличный фронт, но встроенный парсер PDF слабый: таблицы плывут, картинки пропадают, многоколоночные тексты разваливаются. RAGFlow — наоборот, сильный парсер, но UI и оркестрация уступают Dify. AnythingLLM, FlowiseAI, LangFlow — у каждого своя специализация и свой набор пропусков. Мне нужно было одно: чтобы я мог положить в папку 200 PDF-документов, задавать по ним вопросы, ходить в это через нормальный чат, собирать агентов через drag-n-drop, и чтобы всё это поднималось одной командой и так же одной командой бэкапилось. Кубики для этого в open-source есть, дистрибутива — нет. Так появился AGmind. Железо: что такое DGX Spark в двух словах DGX Spark — это компактный AI-десктоп от NVIDIA на чипе GB10 Grace Blackwell. Анонсировали в марте 2025 как Project DIGITS, продавать начали 15 октября 2025. Стартовая цена $3999, в феврале 2026 из-за дефицита LPDDR5x подняли до $4699. Внутри одного SoC сидят: — 20-ядерный ARM-процессор (10 высокопроизводительных Cortex-X925 + 10 энергоэффективных Cortex-A725, спроектированы NVIDIA совместно с MediaTek); — Blackwell GPU c compute capability sm_121: 48 SM, 6144 CUDA-ядра, 192 тензорных ядра пятого поколения; — 128 ГБ памяти LPDDR5x с пропускной способностью 273 ГБ/с — единый когерентный пул, который видят и CPU, и GPU без всякого PCIe-копирования; — два QSFP-порта на 200 Гбит каждый (NVIDIA ConnectX-7), через которые два Spark'а склеиваются в кластер. По чистой GPU-производительности это что-то между RTX 5070 и 5070 Ti. Сенсация не в FLOPs, а именно в 128 ГБ unified memory: на одной коробке за $4 тысячи я могу инферить 70B-модель в FP4 без всякого шардирования, чего на потребительском железе обычно не сделать. Что у этой коробки болит — драйверы. Spark официально живёт на ветке 580.x; на 590+ NVIDIA словила три независимые регрессии, специфичные для unified memory GB10: — vLLM зависает на CUDAGraph capture при первом инференсе. Воспроизведено независимо в репозитории eugr/spark-vllm-docker, там в README прямо стоит требование «driver 580.x, на 590.x deadlock»; — утечка памяти в драйвере 590.48.01: после нормального завершения CUDA-процесса в системе пропадает порядка 80 ГБ, которых не видно ни в AnonPages, ни в Slab, ни в PageTables; лечится только перезагрузкой; — TMA-баг в драйвере 595.58.03 валит NVFP4-квантизацию с illegal memory access. В моём install.sh поэтому стоит apt-mark hold nvidia-driver-580-open — это не паранойя, а защита от unattended-upgrades, которые рано или поздно подтянут 590, и человек, поставивший систему вечером, утром получит мёртвую vLLM. Архитектура: что входит в стек и зачем Стек у меня живёт в докере и состоит примерно из тридцати контейнеров. Dify — фронтенд и оркестратор workflow Dify (langgenius/dify-api:1.13.3) — основной интерфейс, через который я живу. Это open-source-аналог LangChain Studio плюс ChatGPT-like чат, плюс drag-n-drop конструктор агентов. У них есть workflow-редактор, в котором можно нодами собрать что-нибудь типа «получи документ → распарси через RAGFlow → суммаризируй gemma-4 → отправь в Telegram», и это собирается за пять минут без кода. Я использую Dify как primary frontend (agmind-dify.local), а внутри он умеет ходить в локальную vLLM, в RAGFlow через плагин из marketplace и в любой OpenAI-compatible endpoint. Сам Dify — это пять контейнеров: api, worker, web, sandbox, plugin_daemon. RAGFlow — пересобранный с нуля под Spark Здесь надо отдельно. Upstream-RAGFlow в коробке не работает на DGX Spark — там и x86-only зависимости, и устаревшие ONNX-рантаймы, и куча мелочей. Готового образа под arm64 + sm_121 + CUDA 13 в природе нет. Поэтому я взял базу из патчей HendrikSchoettle/ragflow-dgx-spark (там сделана работа по переезду на ARM), накатил поверх свои cherry-pick'и из upstream main и собрал собственный образ ar2r223/ragflow-spark:v0.24.1-spark, запиннил по SHA256, выложил в DockerHub. В сборке: — Базовая ветка v0.24.0 + патчи Hendrik: cascade-OCR на Latin / Cyrillic / Chinese (важно — в upstream был только английский), file metadata в ES-чанках, поддержка AVIF, фиксы IMAP и WebDAV mtime, ONNX Runtime GPU 1.25.0 под aarch64 + CUDA 13 + sm_121; — Cherry-pick из upstream main (от 27 апреля): TokenChunker (атомарные таблицы + image_context), TitleChunker (5 уровней regex-иерархии для книг, законов, мануалов), pdf_chunk_metadata.py, extract_pdf_outlines, 7 ingestion-шаблонов (book / general / laws / manual / one / paper / resume); — Мои runtime-патчи: русский prompt для image describe в cv_model.py (когда у KB language=Russian, vision-модель получает русскоязычный prompt вместо захардкоженного английского), русские заголовки и описания в 10 ingestion-шаблонах, плюс лечение бага Pipeline.globals в Hendrik fork v0.24, где Pipeline не наследовал от Canvas и валился с AttributeError на первом же чанке. В результате RAGFlow умеет на моём железе разбирать русскоязычные PDF с таблицами, схемами и иллюстрациями, описывать картинки русским текстом через vision-модель и индексировать всё это в Elasticsearch 9.x. Образ ~13.3 ГБ, тянется один раз. Apropos — тэг :latest в моём versions.env запрещён, все образы пинятся либо по версии, либо по digest. Это правило в CI: галлюцинирующие LLM любят предлагать «правдоподобные» теги, которых не существует в registry. Об этом подробнее в разделе про Claude Code. vLLM — три инстанса под разные задачи На GB10 у меня крутится три инстанса vLLM: — vLLM (LLM) — vllm/vllm-openai:gemma4-cu130, запускает google/gemma-4-26B-A4B-it. Это NVIDIA playbook-сборка под arm64 и sm_121, единственная, на которой gemma-4 нормально живёт на Spark. По умолчанию gpu_memory_utilization=0.60 — оставляю запас для docling-serve, у которого пиковое потребление до 16 ГБ; — vLLM (embeddings) — nvcr.io/nvidia/vllm:26.02-py3, поднимает deepvk/USER-bge-m3. Это, кстати, не стандартный bge-m3, а файнтюненная под русский вариант от deepvk, на наших корпоративных текстах работает заметно лучше; — vLLM (reranker) — то же базовое NGC-изображение, поднимает BAAI/bge-reranker-v2-m3 для финальной сортировки кандидатов. Почему 26.02-py3, а не 26.03? Потому что 26.03 требует драйвер 595.45+, а у нас 580.142, и поднимать драйвер мы не можем (см. выше). Маленький пример того, как один gotcha тянет за собой выбор всех остальных версий. Атеншн-бэкенд я фиксирую VLLM_ATTENTION_BACKEND=TRITON_ATTN, потому что FlashInfer FP8 на sm_121 валится с kernel only supports sm120 — это известный баг под новый compute capability. Docling — парсер документов с GPU OCR Docling-serve (docling-serve-cu130:v1.16.1) — это GPU-ускоренный конвертер документов от IBM. Принимает PDF / DOCX / PPTX / XLSX, отдаёт Markdown с сохранённой структурой таблиц, заголовками и описаниями картинок. В стеке у меня три preset'а под разные типы документов: — FAST — для текстовых PDF с готовым text layer (Word/LaTeX export). Отключает OCR и table-structure recognition, на 5-страничной arxiv-статье даёт 4.05 секунды против 6.01 в default; — BALANCED (default) — полный pipeline, OCR включается автоматически если text layer неполный, TableFormer работает в accurate-режиме; — SCAN — для отсканированных страниц без text layer. Принудительный easyocr с lang=[ru, en] и picture_description через vLLM gemma-4 vision с concurrency=8, по моим замерам у каждого значимого изображения получается осмысленное русскоязычное описание, которое попадает в индекс. Docling делит GPU с vLLM, отсюда и gpu_memory_utilization=0.60 у LLM-инстанса. Базы и хранение Тут без сюрпризов: — PostgreSQL 16-alpine — метаданные Dify, состояние плагинов; — Redis 7.4 — task queue, кэш плагинов, pub/sub для celery; — Weaviate 1.37 — векторное хранилище под эмбеддинги (есть toggle на Qdrant, но дефолт Weaviate); — MinIO — S3-совместимое объектное хранилище под загруженные документы (agmind-storage.local); — Elasticsearch 9.x — нужен RAGFlow, в нём чанки + полнотекстовый индекс. RAGFlow жёстко завязан на ES, Postgres он не умеет; — MySQL 8.0 — тоже под RAGFlow, у них в схеме MySQL захардкожен. Мониторинг и операционка Без мониторинга стек из тридцати контейнеров — это слепая лошадь. У меня: — Prometheus + Grafana 3001 с десятью собственными дашбордами (общий обзор, контейнеры, GPU master, GPU worker, peer-worker, логи, алерты, аудит, RAG-метрики, RAGFlow). Отдельная боль: на GB10 unified memory dcgm-exporter не работает совсем, а NVML возвращает N/A на половину запросов. Пришлось писать свой textfile collector, который парсит nvidia-smi и отдаёт agmind_gpu_* метрики через node-exporter; — Loki + Grafana Alloy — логи всех контейнеров, в апреле перевёл с Promtail на Alloy (это уже официально рекомендуемый агент); — Alertmanager — каналы в Telegram и webhook; — Portainer 2.39 — визуальное управление контейнерами на master + автодеплой агента на peer Spark с одним и тем же PORTAINER_AGENT_SECRET (чтобы переустановки не ломали привязку); — fail2ban + UFW — firewall LAN-only по умолчанию, защита от bruteforce. Безопасность Из коробки: — все секреты лежат в /opt/agmind/credentials.txt с правами 600, root-only; — у каждого контейнера в compose сдропано 30+ Linux-capabilities; — Dify Sandbox изолирован в отдельной Docker-сети ssrf-network, наружу ходит через Squid-прокси (защита от SSRF в плагинах); — опциональная Authelia с TOTP/WebAuthn на Grafana и Portainer; — agmind rotate-secrets перегенерирует все пароли и ключи одной командой. Кластер из двух Spark'ов Если у вас две Spark-машины, AGmind их склеивает в кластер по QSFP 200G DAC. Это не просто «увеличить память» — это разнесение нагрузок: vLLM получает выделенный GPU без оглядки на парсер.
┌─────────────────────┐ ┌─────────────────────┐ │ spark-master │ QSFP 200G DAC │ spark-peer │ │ (frontend + БД + │ ◄──── direct link ────►│ (только vLLM, │ │ Dify + RAGFlow + │ 192.168.100.0/24 │ выделенный GPU, │ │ monitoring) │ │ 128K context) │ │ WAN: ethernet │ │ WAN: NAT через │ │ iptables MASQUERADE│ ─────── default gw ───►│ master по QSFP │ └─────────────────────┘ └─────────────────────┘
Что важно понимать: — На single-Spark vLLM делит GPU с docling, поэтому в визарде задаётся вопрос про контекст (32K / 64K / 128K) — на 128K при активном парсинге уже впритык; — На dual-Spark этот вопрос пропускается: peer крутит только vLLM, GPU выделен полностью, 128K контекст по умолчанию без компромиссов; — NAT-on-demand — peer выходит в WAN через QSFP master'а только когда нужно (тянет образы или модели), потом командой agmind nat off WAN отрезается, и intent air-gap сохраняется. Полезно, если железо стоит в защищённой сети, а интернет нужен раз в неделю на апдейт; — Симметричная установка — sudo bashinstall.sh на обеих нодах, визард сам определяет роль через LLDP, при отсутствии — fallback на ping. Для CI можно задать --mode=master или --mode=worker явно; — Passwordless SSH между нодами визард настраивает сам, мониторинг показывает обе машины в Grafana отдельными дашбордами gpu-master и gpu-worker. Что я с этим всем делаю в реальной жизни Открываю agmind-dify.local в браузере — и: Чат с локальной 26B-моделью. TTFT 183 миллисекунды, генерация 23–24 токена в секунду на одиночном запросе, до 50 токенов агрегированно на трёх параллельных. Контекст 65K с FP8 KV-кэшем, до 45 параллельных запросов на одной коробке. Никаких лимитов, ничего не уходит наружу. Загружаю папку с PDF — задаю по ним вопросы. Под капотом RAGFlow парсит каждый документ, выдирает таблицы и картинки, прогоняет картинки через vision-модель (gemma-4 vision описывает каждое изображение русским текстом), нарезает на чанки, эмбеддинги в Weaviate. Когда я спрашиваю — bge-m3 ищет похожие чанки, bge-reranker сортирует, gemma-26B пишет ответ со ссылками на источник. Конструктор агентов. Нужен агент, который раз в день забирает определённые письма из Gmail, классифицирует их, важные складывает в Notion, остальные суммаризирует в дайджест и отправляет в Telegram, — собирается в Dify за десять минут на drag-n-drop, без единой строчки кода. Бэкап. sudo agmind backup — снимок Postgres, Redis, всех volume'ов и конфигов. Опционально шифрование age, опционально upload по SSH на peer-машину. Производительность на честных бенчмарках Без чисел разговор про self-hosted AI бессмысленный.
| Метрика |
gemma-4-26B-A4B-it (MoE) |
| TTFT (streaming) |
183 мс |
| TPS (1 запрос) |
23–24 ток/с |
| TPS (3 параллельных) |
~50 ток/с агрегированно |
| Контекст |
65K (FP8 KV-cache) |
| Max concurrency @ 65K |
45 запросов |
| Память: веса |
48.5 GiB (bfloat16) |
| Память: KV-cache |
41.7 GiB (FP8) |
| Total footprint |
~95 GiB |
| Docling (5-page arxiv PDF) |
Время |
| Cold start |
6.04 с |
| Warm |
1.6 с |
| Per-page (warm) |
0.32 с |
| 284-page PDF, без VLM |
88 с |
| Тот же PDF, с VLM concurrency=8 |
191 с |
| Прочее |
|
| Полный install.sh на чистой системе |
~30 минут (включая 52 ГБ весов) |
Установка bash
git clone https://github.com/botAGI/AGmind.git cd AGmind sudo bash install.sh
Визард задаёт 10–15 вопросов: single-Spark или dual-Spark, какую LLM (по умолчанию gemma-4, либо curated-список Qwen / Llama / Mistral / phi-4, либо custom HuggingFace), какой контекст, какие опциональные сервисы (RAGFlow, Open WebUI, LiteLLM, SearXNG, DB-GPT, Crawl4AI, Authelia 2FA), куда бэкапиться. Через ~25 минут стек живой, все credentials лежат в /opt/agmind/credentials.txt с правами 600. Day-2-операции: bash
agmind status # сервисы, GPU, модели, эндпоинты agmind doctor # системная диагностика agmind logs # тейл логов agmind ragflow status # три ragflow-контейнера + ES health agmind docling bench # cold/warm/per-page тайминг agmind upgrade --diff # что устарело относительно pinned-версий agmind backup # Postgres + Redis + volumes agmind rotate-secrets # перегенерировать пароли и ключи
Пять грабель GB10, на которые я наступил Часы потерь честные. Каждая история — это вечер, который вместо «допилить фичу» превратился в «понять, почему это вообще не работает». 1. 502 на каждый запрос после force-recreate (потерял два дня) Я писал nginx-конфиг по привычке нулевых: upstream agmind_api { server api:5001; } плюс proxy_passhttp://agmind_api. Через неделю мне понадобилось рестартнуть Dify api с обновлённым .env через docker compose up -d --force-recreate api. Получил 502 на каждый запрос. Логи api здоровы, сам api отвечает на curl по новому IP, nginx — 502. Оказалось, новый api получил новый IP (был .5, стал .7), а nginx upstream-блок закешировал старый IP при старте. Добавил resolver 127.0.0.11 valid=10s; (Docker embedded DNS) — не помогло. Ещё час дебага: resolver влияет только на proxy_pass $variable, а на upstream-блоки и на статический proxy_passhttp://name — нет. Это в документации nginx написано, но мелким шрифтом. Решение — переписать всё через variable form: nginx
location /api { set $u_dify_api http://api:5001; proxy_pass $u_dify_api; }
И полностью убрать upstream {}-блоки. Сейчас в templates/nginx.conf.template действует жёсткое правило при ревью: ни одного proxy_pass http:// без $. Регрессионный тест проверяет, что после force-recreate api сервис отвечает 200 без ручного рестарта nginx. 2. Зомби-задачи в Redis после force-recreate (потерял два часа) Запустил большой PDF на 280 страниц через docling, висит в processing десять минут. Подумал — worker завис, сделал docker compose up -d --force-recreate worker. Вернулся через час — задача всё ещё processing. Перезапустил весь стек. Та же история. Любая новая загрузка стабильно висит в waiting, GPU idle. Реальная причина оказалась в моих же force-recreate'ах, которые оставили в Redis stale-state: ключи generate_task_belong: (TTL 1800), pub/sub-каналы /1.celeryev привязаны к hostname celery@OLDID, новый worker их не читает. Recreate = новый контейнер с новым hostname. Redis ничего об этом не знает. Лечится так: bash
redis-cli -a $PW -n 0 --scan --pattern 'generate_task_belong:*' | \ xargs redis-cli -a $PW -n 0 DEL redis-cli -a $PW -n 1 --scan --pattern 'celery-task-meta-*' | \ xargs redis-cli -a $PW -n 1 DEL
FLUSHDB блокируется ACL даже для default user — это security hardening, разрешён только DEL by key. Правильный путь дальше — менять env через docker restart api worker, а не через recreate. 3. mDNS self-collision (потерял час) Хотел, чтобы agmind-dify.local, agmind-rag.local, agmind-storage.local резолвились в одну машину. Положил три алиаса в /etc/avahi/hosts на один и тот же IP. Avahi пишет в журнал: Local name collision. С другого хоста алиасы не резолвятся. Час дебага. Оказалось, это self-collision внутри avahi: демон при старте регистрирует $(hostname).local → 192.168.1.42 как primary address record, и когда я добавляю alias на тот же IP, avahi видит конфликт между двумя record'ами для одного IP — и даже не отправляет probe в сеть. Фикс — использовать avahi-publish-address -R name.local IP через systemd-обёртку, по одному юниту на алиас. /etc/avahi/hosts оставить только для имён с другим IP. Бонус-баг к этой истории: второй mDNS-respond'ер на UDP/5353 ломает avahi молча. NoMachine с EnableLocalNetworkBroadcast 1, iTunes/Bonjour и прочие занимают порт. Проверяется через sudo ss -ulnp | grep 5353 — там должен быть только avahi. 4. Distroless-контейнеры без shell (потерял полчаса) Loki, redis_exporter, nginx-prometheus-exporter — distroless-образы. У них нет /bin/sh. Healthcheck через CMD-SHELL wget ... выдаёт stat /bin/sh: no such file or directory, и контейнер навечно висит unhealthy, хотя метрики отдаются нормально. Если у вас в compose depends_on: { redis_exporter: { condition: service_healthy } } — стек никогда не поднимется. Правило простое: для distroless-образов здоровье проверяется через Prometheus up{job=...}, а не через docker healthcheck. 5. APT и truncated downloads (потерял вечер) Это уже не про AGmind, а про инфраструктуру. Но без этой истории картина неполная. apt-get install -y linux-firmware (это 603-мегабайтный deb для arm64) — dpkg -i падает с «неожиданный конец файла или потока». SHA256 не совпадает. --reinstall не помогает, apt-get clean не помогает. stat показывает 632 МБ, curl -sI возвращает Content-Length 634 МБ. Файл обрезается на ~2 МБ до конца. Curl по HTTP принимает truncated body как успех — HTTP 200, Connection closed до конца Content-Length, для curl это валидный финал. Где-то между моим хостом и upstream-зеркалом сидит прозрачный прокси или CDN, который режет соединение. Решение — везде HTTPS. TLS требует close_notify alert при завершении, и если он не пришёл, клиент знает, что body неполный. После замены http://ports.ubuntu.com на https:// всё стало качаться чисто. Я узнал это случайно, когда уже хотел переустанавливать систему. Сидел и думал — это что, я железо при распаковке покалечил? Месяц с Claude Code: что это на самом деле Самое интересное в этой истории — не какой стек я собрал, а как я его собирал. Я не писал код руками. Точнее, писал, но в объёме одной-двух строк, чтобы что-то быстро поправить. Все 88 КБ install.sh, все 16 lib-модулей, все nginx-шаблоны, все Python-скрипты для генерации манифестов сгенерировал Claude Code. Это не «ChatGPT, дай сниппет». Claude Code — это CLI-агент, который читает файлы в репозитории, делает правки, гоняет тесты, открывает PR. Он сам видит мой проект, сам помнит, что в каком модуле. Я формулирую задачу человеческим языком, он её делает. О себе для контекста: учился на программиста, лет 12–15 назад писал в продакшене, потом ушёл в бизнес и десять лет руки до кода почти не доходили. Архитектурное мышление осталось, диффы я читать не разучился, но сесть и накатать тысячу строк bash с идемпотентным wizard'ом — давно не садился. Тем интереснее было собрать что-то целиком, имея AI-агента в роли младшего разработчика на рутине. Что у меня работало хорошо: bash-скрипты с edge-case'ами (в install.sh сейчас покрыто около тридцати возможных состояний хоста — частичная установка после прерывания, существующие credentials, сломанный peer, занятый порт 5353, битый apt-cache); регрессионные тесты под mock'и для cluster-mode; документация (этот пост — я диктую содержание, Claude формулирует, я вычитываю). Что работало плохо. LLM врут, и это не лечится. Самый болезненный случай — Claude как-то предложил minio/minio:RELEASE.2026-02-01T00-00-00Z как стабильный пин MinIO. Тэг выглядит правдоподобно: timestamp в правильном формате, паттерн совпадает с реальными релизами. docker compose config принимает его как валидный. При docker compose up падает с manifest unknown, и установка валится на 9-й фазе из 11. После этого случая я в CLAUDE.md (это файл с правилами проекта, его Claude автоматически читает в начале каждой сессии) написал жирно: «LLM не знает, какие тэги существуют в registry. Никаких "выглядит правдоподобно". Только docker manifest inspect перед commit». И добавил автотест tests/compose/test_image_tags_exist.sh, который проверяет каждый image:tag в registry. Теперь галлюцинации ловятся в CI. Контекст забывается между сессиями. Каждая новая сессия — чистый лист. Если я не зафиксирую правило «не делай force-recreate во время RAG-индексации, это ломает Redis-state, я уже терял два часа», он через неделю это снова предложит. Без CLAUDE.md ничего не работает. Сейчас у меня там 200 с лишним строк правил, и каждое — выстраданное факапом. Раздел называется «Learned the hard way». Иногда не понимает приоритеты. Говоришь «поправь баг в OCR» — попутно отрефакторит три соседних модуля, потому что заметил code smell. Иногда полезно, иногда я просто хочу патч, а не PR на восемьсот строк. Лечится через тот же CLAUDE.md: «не правь то, о чём тебя не просили». Что я вынес про AI-разработку Главное наблюдение, которое стоит написать прямым текстом: AI-агент не делает тебя умнее. Он делает тебя быстрее в том, в чём ты уже хоть как-то разбираешься. Если я не понимаю, почему proxy_passhttp://name ломается на force-recreate, а proxy_pass $variable — нет, никакой Claude мне это сам не объяснит. Он сгенерирует код, я его поставлю, оно сломается, и я не пойму, почему. Если же я понимаю — Claude напишет nginx-конфиг с правильным паттерном за минуту вместо часа. То же самое со всем остальным. Без общего понимания, как устроен Docker, что такое systemd-юнит, как работает HTTP, я бы не отличил рабочий код от рабочего-с-виду. Claude — не замена программиста. Это сильно ускоренный младший разработчик, на которого можно скинуть рутину, при условии, что архитектор у тебя есть. И если этого архитектора нет — никакая модель его не заменит, хоть она и пишет код в десять раз быстрее тебя. Где это реально меняет уравнение: в задачах, где у тебя есть видение, опыт читать чужой код, понимание предметной области — но нет команды и нет физического времени. Раньше один человек с такими исходными мог сделать MVP за пару месяцев. Сейчас — production-grade продукт за 30 дней. У меня в репозитории 86 коммитов, 32 тысячи строк, 30 контейнеров, и это не маркетинговая фраза, а git log. Дисциплина простая: — чёткое видение продукта (не «дай мне умную систему», а «wizard на 10 вопросов, идемпотентность, откат при ошибке, конкретные SLO»); — CLAUDE.md с правилами проекта, который пополняется после каждого факапа; — железо под рукой для проверки на живом стенде — эмуляция врёт, форумы устаревают, документация по умолчанию отстаёт от реальности. Если у вас есть DGX Spark — забирайте install.sh, гоняйте на чистой системе, в issue-tracker'е расскажите, что сломалось. Если Spark'а нет, но интересно, как устроен private RAG end-to-end — lib/ и templates/docker-compose.yml читаются как самодокументация: я писал их так, чтобы через год самому помнить, почему именно gpu_memory_utilization=0.60, а не 0.70. Во второй части расскажу про мониторинг unified memory без NVML — там пришлось довольно изобретательно костылить — и про supply-chain hardening для Dify-плагинов в air-gap-сценариях. Подписывайтесь, если интересно. github.com/botAGI/AGmind-Источник
|
|
|
|