Далучайцеся да нашага Тэлеграм-канала
Папулярныя тэмы
AI (15)
ШІ (13)
js (11)
сумоўе js beginner (7)
сумоўе (6)
fun (5)
MCP (3)
Youtube (3)
сумоўе js (3)
2024 (2)
AWS (2)
Angular (2)
Event (2)
JSONP (2)
JavaScript (2)
LLM (2)
Prompts (2)
agents (2)
beginner (2)
docker (2)
http (2)
javascript (2)
loop (2)
беларускаямова (2)
вынікі (2)
каналы (2)
мова (2)
пераклад (2)
ASO (1)
BF (1)
Bun (1)
CORS (1)
CSS (1)
CodeStars (1)
Copilot (1)
Deno (1)
EC2 (1)
ES6 (1)
Flux (1)
GitHub (1)
JS (1)
JSON (1)
JSONB (1)
JSONL (1)
LangChain (1)
LangGraph (1)
MVP (1)
NodeJS (1)
NodeJS Gmail backend beginners (1)
Nodejs (1)
PWA (1)
Polotsk (1)
Promptdesigne (1)
Prompting (1)
RSS (1)
Ragneda (1)
React (1)
ReactNative (1)
SOP (1)
SQL (1)
SSR CSR js сумоўе (1)
Search (1)
Signal (1)
SystemDesign (1)
Tailwind (1)
Telegram (1)
Threema (1)
VS (1)
Vector (1)
Vibe (1)
Windows (1)
angular (1)
architecture (1)
beginners (1)
belgeek (1)
cloudflare (1)
code (1)
context (1)
css (1)
engineering (1)
gamedev (1)
hdd (1)
history (1)
interview (1)
it (1)
job (1)
js ssg сумоўе (1)
lacinka (1)
localhost ngrok тунэль (1)
models (1)
multiagents (1)
network (1)
news (1)
other (1)
prompts (1)
react (1)
server (1)
telegram (1)
tools (1)
translations (1)
Абнаўленні (1)
Анімэ (1)
Артыкул (1)
БД (1)
Беларуская (1)
Беларусь (1)
Бяспека (1)
Вынікі (1)
Выявы (1)
Вядзьмар (1)
Каляндар (1)
Падарункі (1)
Токены (1)
бд (1)
дзень (1)
літаратура (1)
мадэлі (1)
маркетынг (1)
нараджэня (1)
праграмаванне парадыгмы (1)
практыка (1)
промпты (1)
раскладка (1)
рэпазіторыі (1)
селектары (1)
серыялы (1)
спам (1)
сумоўе js beginer (1)
сумоўе js beginner AJAX (1)
сумоўе практыка js (1)
сумоўе практыка js beginner (1)
тэлеграм (1)
цыклпадзей (1)

Bel-Geek - гэта адкрытая пляцоўка для публікацыі артыкулаў розных аўтараў на беларускай мове на свабодныя тэмы.

Перад тым як прыступіць да стварэння ўласнага артыкула, трэба аўтарызавацца. Калі ў вас няма акаунта, то трэба зарэгістравацца на сайце па спасылцы: https://bel-geek.com/register.

Далей трэба націснуць на тры кропкі ў шапцы сайта, каб з'явілася меню. Выбраць пункт "Стварыць артыкул", і перайсці на старонку рэдактара, ці скарыстацца спасылкай: https://bel-geek.com/editor/add

Пры стварэнні артыкула абавязкова трэба дадаць назву артыкула, імя аўтара ды тэгі ў адпаведныя палі формы, пажадана дадаць апісанне.

Напрыклад:

Як бачна на малюнку, з правага боку будзе панэль, на якой знаходзіцца прадагляд артыкула. З левага боку - рэдактар.

Важна!

Захоўвайце час ад часу свае артыкулы з дапамогай кнопкі "Захаваць" (працуем над аўтазахаваннем), каб выпадкова не згубіць напісанае. Таксама можна захаваць напісанае і адкласці работу з артыкулам на іншы дзень.

Калі вы ўжо вядзеце блогі ў іншых сацыяльных сетках, то дадавайце спасылкі на іх у сваіх артыкулах, каб чытачы маглі знайсці больш цікавай ім інфармацыі.

Калі артыкул будзе гатовы, трэба перавесці перамыкач над рэдактарам тэксту "Паказваць усім" у актыўнае становішча і націснуць кнопку "Захаваць".

PS. Калі вы ствараеце пераклад - то абавязкова пакідайце спасылкі на арыгінал.


Карысныя спасылкі, якімі можна карыстацца падчас напісання артыкулаў:

Мноства слоўнікаў: https://slounik.org/

Правапіс слоў у розных склонах і ліках: https://starnik.by/

Артыкул
LoveJS, 2023-08-06

cover

Уводзіны: Чаму мы зноў гаворым пра гэтых дыназаўраў?

Яшчэ пару гадоў таму здавалася, што дні старых добрых "вінчэстараў" палічаныя. SSD імкліва таннелі, ноўтбукі схуднелі, а гук паркоўкі галовак HDD стаў успрымацца як гук мадэма з 90-х. Здавалася, яшчэ крыху - і гэтыя грукатлівыя цэглы сыдуць у гісторыю следам за дыскетамі і DVD-плэерамі.

Але на двары 2026 год, і сюрпрыз! Месца на SSD каштуе як крыло ад Боінга.

Дзякуйце Штучнаму Інтэлекту. Сур'ёзна. Пакуль вы генеруеце карцінкі коцікаў у касмічных касцюмах, дата-цэнтры скупаюць Flash-памяць (NAND) такімі тэмпамі, што заводам проста няма калі рабіць танныя SSD для простых смяротных. Уся хуткая памяць сыходзіць на навучанне нейрасетак.

І тут на сцэну зноў выходзіць ён - Яго Вялікасць HDD. Павольны, цяжкі, шумны, але такі родны. І галоўнае - танны. HDD вярнуўся, але ўжо не як "сістэмны дыск" (запускаць з яго Windows у 2026-м - гэта вытанчаны від мазахізму), а як аснова вашага асабістага воблака. Гэта ідэальнае месца для сямейных архіваў, калекцыі фільмаў у 4K і ўсяго таго, што павінна ляжаць надзейна, але не займаць дарагое месца на хуткім дыску.


Што такое HDD (для тых, хто нарадзіўся з айфонам у руках)

Калі спрасціць, HDD - гэта высокатэхналагічны прайгравальнік вінілавых кружэлак, запакаваны ў герметычную металічную скрынку. Унутры знаходзяцца магнітныя "бліны", якія круцяцца з хуткасцю 7200 абаротаў у хвіліну (гэта як кола баліда Формулы-1). Над імі парыць счытвальная галоўка. Яна не кранаецца паверхні, а ляціць на вышыні менш за чалавечы волас.

Што гэта значыць для вас?

  1. Ён далікатны. Стукнуць па корпусе падчас працы - і галоўка "пацалуе" дыск. Гэта як драпіна на вініле - песня (вашы дадзеныя) скончыцца назаўжды.
  2. Ён павольны. Каб знайсці файл, галоўцы трэба фізічна даехаць да патрэбнага месца. У SSD усё адбываецца тэлепартацыяй (электрычным імпульсам).
  3. Ён танны. Вы можаце купіць вялізны HDD на 8 Тэрабайт па цане "хуткага" SSD на 2 ТБ.

Маркетынгавае пекла: Якога колеру ваш дыск?

Раней было проста: прыйшоў у краму, купіў "вінчэстар", уставіў. Сёння вытворцы выпускаюць дзясяткі мадэляў з рознымі колерамі на лэйбах. І іх рэальна важна адрозніваць, бо ўнутры стаіць розная прашыўка (firmware), якая вызначае, як дыск сябе паводзіць.

1. Desktop HDD ("Звычайныя", Blue/Green)

Самыя простыя і даступныя дыскі. Разлічаны на стандартны офісны ці хатні рэжым: камп'ютар уключаецца раніцай, працуе 8-10 гадзін і выключаецца на ноч. Вердыкт: Добрыя для захоўвання фільмаў і файлаў у звычайным ПК. Непрыдатныя для сервераў і рэжыму 24/7, бо маюць меншы рэсурс механікі і горш пераносяць вібрацыі.

2. Surveillance HDD ("Для відэаназірання", Purple/SkyHawk)

Спецыялізаваныя дыскі, распрацаваныя для кругласутачнага запісу відэапатокаў з камер. Іх галоўная асаблівасць - прыярытэт хуткасці запісу над цэласнасцю дадзеных. Калі пры запісе ўзнікне памылка, звычайны дыск спыніцца і паспрабуе прачытаць сектар зноў, што прывядзе да страты некалькіх секунд відэа. Surveillance-дыск памылку праігнаруе і працягне пісаць далей, каб відэашэраг не перарываўся. Чаму нельга браць у ПК? Для захоўвання файлаў такая логіка небяспечная. Калі дыск "прапусціць" памылку ў вашым Excel-файле або архіве з фота, файл будзе пашкоджаны назаўжды.

3. NAS HDD ("Сеткавыя", Red/IronWolf)

Аптымальны варыянт для захоўвання дадзеных. Калі вы яшчэ не ведаеце, NAS (Network Attached Storage) - гэта маленькая каробачка, у якую ўстаўляюцца дыскі. Яна падключаецца да вашага роўтара, і ўсе прылады ў доме - тэлефон, ноўтбук, тэлевізар - бачаць гэтыя дыскі як сваё асабістае воблака. Па сутнасці, гэта ваш хатні Dropbox, толькі без абаненцкай платы. Гэтыя дыскі сканструяваныя спецыяльна для працы ў рэжыме 24/7 у шматдыскавых сістэмах (RAID). Яны маюць абарону ад вібрацый (што важна, калі ў адным корпусе стаіць некалькі дыскаў), менш грэюцца і маюць пашыраны рэсурс працы. Вердыкт: Найлепшы выбар для хатняга сервера ці ПК, калі дадзеныя для вас важныя. Яны крыху даражэйшыя за звычайныя офісныя мадэлі, але значна больш жывучыя.

4. Enterprise HDD ("Серверныя", Gold/Ultrastar)

Эліта свету назапашвальнікаў. Гэтыя дыскі ставяць у дата-цэнтры Google і Amazon. Яны неверагодна надзейныя і самыя хуткія сярод HDD. Але ёсць нюанс: Яны трашчаць, як стары трактар "Беларус", і грэюцца, як патэльня. Інжынеры разлічвалі іх для глухіх серверных пакояў з магутнымі вентылятарамі, а не для вашай утульнай спальні. Калі вы не гатовыя спаць пад гукі будоўлі - не бярыце іх дадому, нават калі яны танныя на другасным рынку.


Самая вялікая падстава: CMR супраць SMR ("Чарапіца")

Увага! Тут вас спрабуюць падмануць. Каб упіхнуць больш дадзеных і зэканоміць, вытворцы прыдумалі SMR (Shingled Magnetic Recording) - "чарапічны" запіс.

  • CMR (Нармальны): Дарожкі ідуць побач, як палосы на шашы. Можна перазапісаць любую інфармацыю ў любы момант. Хутка і прадказальна.
  • SMR (Чарапічны): Дарожкі накладваюцца адна на адну, як дах. Каб змяніць адзін байт, дыску трэба падняць і перакласці ўсе "чарапіцы" побач.

У чым праблема SMR? Пакуль вы проста захоўваеце фільмы ("паклаў і забыў") - усё ОК. Але паспрабуйце запісаць на яго 100 Гб дробных файлаў або перазаліць бэкап... Хуткасць упадзе да ўзроўню флэшкі з 2005 года, а дыск пачне "тупіць" і выдаваць гукі памірання. Парада: Заўсёды гугліце мадэль. Калі там SMR - бярыце толькі для архіва "на чорны дзень". Для актыўнага карыстання шукайце толькі CMR.


Як не аблажацца з выбарам аб'ёму?

Тут важна знайсці баланс, бо гігантызм тут не заўсёды карысны.

  • 1-4 ТБ: Сэнсу няма але не дакладна. Каштуе (за ТБ) доражэй за астатнія але мо каму і дастаткова.
  • 6-8-10 ТБ: "Залатая сярэдзіна". Самыя адэкватныя кошты.
  • 12-20 ТБ: Гэта часта тыя самыя шумныя карпаратыўныя монстры. Ці гатовыя вы слухаць іх хрусценне?

Лайфхак: Два дыскі па 8 ТБ лепш, чым адзін на 16 ТБ. Калі памрэ адзін вялікі - вы страціце ўсё. Калі памрэ адзін з двух - хаця б палова коцікаў застанецца жывая.


Як не забіць дыск за год?

Дыскі паміраюць не ад старасці, а ад дрэннага жыцця.

  1. Не смажце іх. Тэмпература 30–45°C - гэта курорт. 50°C і вышэй - гэта пекла, дзе плавіцца змазка падшыпнікаў. Пастаўце вентылятар!
  2. Не трэсці! Працуючы HDD баіцца нават, калі вы моцна тупнеце нагой побач з сістэмнікам. Не стаўце ПК на сабвуфер.
  3. Купіце UPS (Бесперабойнік). Раптоўнае адключэнне святла падчас запісу - гэта інфаркт для дыска. Галоўка можа проста ўпасці на блін і зрабіць "скрэтч".

Як зразумець, што дыск памірае? (SMART)

Кожны HDD вядзе ўнутраны дзённік свайго здароўя - тэхналогія называецца S.M.A.R.T.. Вы можаце праверыць яго бясплатнымі праграмамі:

  • Windows: CrystalDiskInfo
  • macOS: DriveDx
  • Linux: GSmartControl (графічны) або smartctl з пакета smartmontools (каманда ў тэрмінале)

На што глядзець у першую чаргу:

  • Reallocated Sectors (пераразмеркаваныя сектары): Дыск знайшоў сапсаваныя ўчасткі і перанёс дадзеныя ў запасныя. Калі іх крыху - нічога страшнага. Калі іх колькасць расце - дыск дажывае свае апошнія месяцы.
  • Current Pending Sectors: Сектары, якія дыск не змог прачытаць, але яшчэ не перанёс. Гэта чырвоны сігнал - рабіце бэкап тэрмінова.
  • CRC Errors: Памылкі пры перадачы дадзеных па кабелі. Часта гэта проста дрэнны SATA-кабель, але ігнараваць не варта.

Правіла: Усталюйце маніторынг і правярайце дыскі хаця б раз на месяц. Лепш даведацца пра праблему загадзя, чым аднойчы ўбачыць "Disk not found" пры загрузцы.


Высновы: Ідэальная зборка ў 2026

Не спрабуйце знайсці "адзін дыск для ўсяго". Гэта як шукаць машыну, каб і бульбу вазіць, і ў гонках удзельнічаць.

Правільная схема разумнага чалавека:

  1. SSD (NVMe) 1 ТБ: Для Windows/macOS, праграм і гульняў, у якія гуляеце зараз. Каб усё адкрывалася імгненна.
  2. HDD (NAS, CMR) 8 ТБ: Ваша лічбавае сховішча. Сюды ляцяць фільмы, архівы фота, усталёўшчыкі гульняў (каб не пампаваць нанова) і бэкапы сістэмы.
  3. Знешні дыск / Воблака: Копія таго, што прымусіць вас плакаць у выпадку страты (сямейныя фота і дакументы).

HDD не памёр - ён проста змяніў прафесію. Раней быў галоўным, цяпер стаў архіварыусам. І пакуль нейрасеткі з'ядаюць усю хуткую памяць на планеце, менавіта HDD застаецца самым танным і практычным спосабам захоўваць тэрабайты вашых дадзеных на гады наперад.

У наступным артыкуле мы распавядзем пра NAS падрабязна: як выбраць, як наладзіць, што такое RAID і чаму ён не замяняе бэкап.

hdd
Admin, 2026-02-19

Гэта пераклад артыкула з LangChain Blog.

Арыгінал: https://blog.langchain.com/choosing-the-right-multi-agent-architecture/ Выбар правільнай мульты-агентнай архітэктуры

У гэтым артыкуле мы разгледзім, калі мульты-агентныя архітэктуры становяцца неабходнымі, чатыры асноўныя шаблоны, якія мы назіраем, і тое, як LangChain дазваляе эфектыўна будаваць мульты-агентныя сістэмы.

Шматлікія агенцкія задачы лепш за ўсё вырашаюцца адным агентам з добра распрацаванымі інструментамі. Варта пачаць з гэтага — адзіночныя агенты прасцей у стварэнні, разуменні і адладцы. Але па меры маштабавання прыкладанняў каманды сутыкаюцца з агульнай праблемай: у іх ёсць разрозненыя магчымасці агентаў, якія яны хочуць аб'яднаць у адзіны ўзгоднены інтэрфейс. Па меры росту колькасці функцый узнікаюць два асноўныя абмежаванні:

  1. Кіраванне кантэкстам: Спецыялізаваныя веды для кожнай здольнасці не могуць камфортна змясціцца ў адным промпце (падказцы). Калі б вокны кантэксту былі бясконцымі, а затрымка нулявой, вы маглі б уключыць усю адпаведную інфармацыю адразу. На практыцы патрэбныя стратэгіі для выбарачнага прадастаўлення інфармацыі па меры працы агентаў.
  2. Размеркаваная распрацоўка: Розныя каманды распрацоўваюць і падтрымліваюць кожную здольнасць незалежна, з выразнымі межамі і адказнасцю. Адзіны маналітны промпт агента становіцца цяжкім для кіравання рознымі камандамі.

Гэтыя абмежаванні становяцца крытычнымі, калі вы кіруеце шырокімі даменнымі ведамі, каардынуеце працу каманд або вырашаеце сапраўды складаныя задачы. У такіх выпадках мульты-агентныя архітэктуры могуць стаць правільным выбарам.

Мульты-агентныя архітэктуры

Чатыры архітэктурныя шаблоны складаюць аснову большасці мульты-агентных прыкладанняў: Subagents, Skills, Handoffs і Routers. Кожны з іх выкарыстоўвае розны падыход да каардынацыі задач, кіравання станам і паслядоўнага адкрыцця магчымасцей.

Subagents: Цэнтралізаваная аркестроўка

Subagents — Centralized orchestration

У шаблоне Subagents агент-назіральнік (supervisor) каардынуе спецыялізаваных субагентаў, выклікаючы іх як інструменты. Галоўны агент захоўвае кантэкст размовы, у той час як субагенты застаюцца без стана (stateless), забяспечваючы моцную ізаляцыю кантэксту.

  • Як гэта працуе: Галоўны агент вырашае, якіх субагентаў выклікаць, якія ўваходныя дадзеныя даць і як аб'яднаць вынікі. Субагенты не памятаюць мінулых узаемадзеянняў. Гэтая архітэктура забяспечвае цэнтралізаванае кіраванне, дзе ўся маршрутызацыя праходзіць праз галоўнага агента, які можа выклікаць некалькі субагентаў паралельна.
  • Лепш за ўсё падыходзіць для: Прыкладанняў з некалькімі рознымі даменамі, дзе неабходны цэнтралізаваны кантроль працоўнага працэсу, і субагенты не павінны размаўляць непасрэдна з карыстальнікамі. Прыклады ўключаюць персанальных асістэнтаў, якія каардынуюць каляндар, электронную пошту і CRM-аперацыі, або даследчыя сістэмы, якія дэлегуюць задачы спецыялізаваным даменным экспертам.
  • Асноўны кампраміс: Дадае адзін дадатковы выклік мадэлі на ўзаемадзеянне, таму што вынікі павінны праходзіць назад праз галоўнага агента. Гэтыя накладныя выдаткі забяспечваюць цэнтралізаваны кантроль і ізаляцыю кантэксту, але каштуюць затрымкі (latency) і токенаў.

Skills: Прагрэсіўнае раскрыццё

Skills — Progressive disclosure

У шаблоне Skills агент загружае спецыялізаваныя промпты і веды па запыце. Думайце пра гэта як пра прагрэсіўнае раскрыццё магчымасцей агента.

  • Як гэта працуе: Skills — гэта ў асноўным спецыялізацыі на аснове промптаў, спакаваныя ў каталогі, якія змяшчаюць інструкцыі, скрыпты і рэсурсы. Пры запуску агент ведае толькі назвы навыкаў і апісанні. Калі навык становіцца актуальным, агент загружае яго поўны кантэкст. Дадатковыя файлы ўнутры Skills забяспечваюць трэці ўзровень дэталізацыі, які агент выяўляе толькі па меры неабходнасці.
  • Лепш за ўсё падыходзіць для: Адзіночных агентаў з вялікай колькасцю магчымых спецыялізацый, сітуацый, дзе не трэба ўводзіць абмежаванні паміж магчымасцямі, або размеркавання каманд, дзе розныя каманды падтрымліваюць розныя Skills. Тыповыя прыклады ўключаюць агентаў для напісання кода або творчых асістэнтаў.
  • Асноўны кампраміс: Кантэкст назапашваецца ў гісторыі размоў па меры загрузкі навыкаў, што можа прывесці да раздзімання токенаў (token bloat) пры наступных выкліках. Аднак гэты шаблон забяспечвае прастату і прамое ўзаемадзеянне з карыстальнікам на працягу ўсяго часу.

Handoffs: Пераходы на аснове стана

Handoffs — State-driven transitions

У шаблоне Handoffs актыўны агент дынамічна змяняецца ў залежнасці ад кантэксту размовы. Кожны агент мае магчымасць перадаваць кіраванне іншым праз выклік інструментаў.

  • Як гэта працуе: Калі агент выклікае інструмент Handoff, ён абнаўляе стан, які вызначае наступнага агента для актывацыі. Гэта можа азначаць пераключэнне на іншага агента або змену сістэмнага промпта бягучага агента і даступных інструментаў. Стан захоўваецца паміж раўндамі размовы, што дазваляе ствараць паслядоўныя працоўныя працэсы (workflow).
  • Лепш за ўсё падыходзіць для: Патокаў падтрымкі кліентаў, якія збіраюць інфармацыю паэтапна, шматступенных размоўных досведаў, або любога сцэнара, які патрабуе паслядоўных абмежаванняў, дзе магчымасці адкрываюцца толькі пасля выканання папярэдніх умоў.
  • Асноўны кампраміс: Больш залежны ад стана, чым іншыя шаблоны, патрабуе ўважлівага кіравання станам. Аднак гэта дазваляе весці плыўныя шматкрокавыя (multi-turn) размовы, дзе кантэкст натуральна пераносіцца паміж этапамі.

Router: Паралельная адпраўка і сінтэз

Router — Parallel dispatch and synthesis

У шаблоне Router крок маршрутызацыі класіфікуе ўваходныя дадзеныя і накіроўвае іх спецыялізаваным агентам, выконваючы запыты раўналежна і сінтэзуючы вынікі.

  • Як гэта працуе: Router дэкампазіруе запыт, выклікае нуль або некалькі спецыялізаваных агентаў паралельна, і сінтэзуе вынікі ў звязны адказ. Routers звычайна не маюць стана (stateless), апрацоўваючы кожны запыт незалежна.
  • Лепш за ўсё падыходзіць для: Прыкладанняў з рознымі вертыкалямі (асобныя галіны ведаў), сцэнараў, якія патрабуюць запытаў да некалькіх крыніц адначасова, або сітуацый, дзе трэба сінтэзаваць вынікі ад некалькіх агентаў. Прыклады ўключаюць карпаратыўныя базы ведаў і шматвертыкальныя асістэнты падтрымкі кліентаў.
  • Асноўны кампраміс: Дызайн без стана азначае нязменную прадукцыйнасць на запыт, але паўтаральныя выдаткі на маршрутызацыю, калі вам патрэбна гісторыя размоў. Гэта можа быць змякчэна шляхам абгортвання Router як інструмента ўнутры размоўнага агента са станам.

Супастаўленне патрабаванняў з шаблонамі

ПатрабаваннеШаблон
Некалькі розных даменаў (каляндар, пошта, CRM), патрабуецца паралельнае выкананнеSubagents
Адзін агент з мноствам магчымых спецыялізацый, лёгкая кампазіцыяSkills
Паслядоўны працоўны працэс са зменай станаў, агент размаўляе з карыстальнікам ўвесь часHandoffs
Розныя вертыкалі, запыт да некалькіх крыніц паралельна і сінтэз вынікаўRouter

Характарыстыкі прадукцыйнасці

Выбар архітэктуры наўпрост уплывае на затрымку, кошт і карыстальніцкі досвед.

Scenario 1: One-shot request

Scenario 1 — One-shot request

Scenario 2: Repeat request

Scenario 2 — Repeat request

Scenario 3: Multi-domain query

Scenario 3 — Multi-domain query

  • Аднаразовы запыт: Handoffs, Skills і Router найбольш эфектыўныя.
  • Паўторны запыт: Шаблоны са станам (Handoffs, Skills) эканомяць 40-50% выклікаў на паўторных запытах, захоўваючы кантэкст.
  • Шматдаменны запыт: Шаблоны з паралельным выкананнем (Subagents, Router) найбольш эфектыўныя. Skills маюць менш выклікаў, але высокае выкарыстанне токенаў з-за назапашвання кантэксту.

З чаго пачаць

У многіх выпадках простыя архітэктуры часта дастатковыя. Пачніце з аднаго агента і добрай распрацоўкі промптаў (prompt engineering). Дадавайце інструменты перад даданнем агентаў. Пераходзьце да мульты-агентных шаблонаў толькі тады, калі вы сутыкнецеся з відавочнымі абмежаваннямі.

Крыніца: https://blog.langchain.com/choosing-the-right-multi-agent-architecture/

AI
agents
multiagents
Admin, 2026-02-05

покрыўка

Прывітанне! Мы ўжо разабралі Джэнтльменскі набор кантэйнераў, якія робяць жыццё прасцейшым. Але засталося галоўнае пытанне: "А дзе гэта ўсё запускаць?"

Купляць дарагі сервер? Арандаваць магутнасці ў воблаку? Не. Сёння мы пойдзем іншым шляхам. Мы возьмем тое, што ў вас, хутчэй за ўсё, ужо ёсць, і зробім з гэтага цукерку.

Частка 1. Бітва фарматаў: Што абраць?

Самае частае памылковае меркаванне: "Мне патрэбна спецыяльнае сервернае абсталяванне". Насамрэч, для хатніх задач (NextCloud, Jellyfin, Home Assistant) магутнасці звычайнага камп'ютара 5-7 гадовай даўніны хопіць з лішкам.

Давайце разгледзім тры асноўныя варыянты:

1. Стары ноўтбук (The King of Home Lab)

У многіх ляжыць без справы стары ноўтбук са зламаным экранам або проста "тармазны" для гульняў. Чаму гэта ідэальны варыянт:

  • Убудаваны UPS: Батарэя, нават калі яна трымае 10 хвілін, выратуе вашу файлавую сістэму пры раптоўным адключэнні святла. Гэта фіча, за якую ў дарослых серверах плацяць сотні даляраў.
  • Усё ў адным: Вам не трэба шукаць манітор і клавіятуру, каб наладзіць BIOS ці пераўстанавіць сістэму.
  • Бясплатна: Ён ужо ваш.

Нюансы: Трэба сачыць за ахалоджваннем (пачысціце яго ад пылу!) і цяжка дадаць другі жорсткі дыск.

2. Міні-ПК (USFF — Ultra Small Form Factor)

Гэта карпаратыўныя малышы кшталту Lenovo ThinkCentre Tiny, Dell OptiPlex Micro або HP EliteDesk Mini. Іх масава спісваюць офісы, і на барахолках іх поўна па $50-150. Чаму гэта крута:

  • Надзейнасць: Яны спраектаваны працаваць 24/7 гадамі.
  • Эстэтыка: Маленькая, ціхая скрыначка, якая прыгожа выглядае на паліцы.
  • Апгрэйд: Лёгка адкрыць крышку, дадаць RAM або замяніць SSD.

напрыклад bel-geek зараз размешчаны на ім.


Нюансы: Вам спатрэбіцца знешні манітор для першай наладкі і асобны UPS, калі ў вас скача напруга.

3. Чаму НЕ Raspberry Pi?

Яшчэ пару год таму "малінка" была каралём самаробак. Але сёння:

  • Кошт: Камплект Raspberry Pi 4/5 з корпусам, блокам сілкавання і добрай SD-карткай каштуе як б/у Міні-ПК на i5 працэсары.
  • SD-карткі: Яны паміраюць. Гэта факт. Для надзейнага сервера трэба мудраваць з SSD праз USB.
  • Архітэктура: ARM — гэта добра, але часам вы знойдзеце патрэбны Docker-кантэйнер, а ён сабраны толькі пад x86 (звычайныя працэсары). Гэта боль.

Вердыкт: Калі ёсць стары ноўтбук — пачынайце з яго. Калі хочаце прыгожа і ёсць $100 — бярыце Міні-ПК.

Частка 2. Выбар АС: Desktop ці Server?

Гэта месца, дзе ламаюцца дзіды на форумах. "Сапраўдныя адміны" скажуць вам ставіць Ubuntu Server (або Debian), дзе няма нічога, акрамя чорнага экрана з тэрміналам.

Я скажу іншае: Стаўце Ubuntu Desktop (звычайную версію).

Чаму? Таму што мы робім хатні сервер для сябе, а не для карпарацыі.

  • Камфорт: Калі ў вас адваліцца сетка, вы зможаце падысці да сервера, узяць мышку і паглядзець логі ў зручным акне, або проста адкрыць браўзер і пагугліць праблему прама на серверы.
  • Wi-Fi: Наладзіць Wi-Fi праз тэрмінальны Netplan — тое яшчэ задавальненне для пачаткоўца. У Desktop версіі вы проста клікаеце па значку Wi-Fi.
  • Кошт рэсурсаў: Так, графічны інтэрфейс з'есць лішні 1 ГБ аператыўнай памяці. Але калі ў вас 8 ГБ RAM (стандарт для старога ноўта), вы гэтага нават не заўважыце. Зручнасць важнейшая за гэты гігабайт.

Частка 3. Падрыхтоўка і BIOS

Перад тым як ставіць сістэму, трэба крыху "пашаманіць" у BIOS (націскайце F2, Del або F12 пры ўключэнні):

  1. Virtualization Technology (VT-x / AMD-V): ENABLE. Гэта крытычна важна для працы Docker. Без гэтага нічога не паляціць.
  2. Power on after power loss: (Для Міні-ПК) ON. Калі электрычнасць знікне і з'явіцца, сервер павінен сам уключыцца. У ноўтбукаў гэтай опцыі часта няма, але там ёсць батарэя.
  3. Wake on LAN: ON. Карысна, калі вы захочаце ўключыць сервер аддалена (не рабіў так ніколі).

Важна: Калі вы выкарыстоўваеце стары ноўтбук або ПК, не палянуйцеся разабраць яго, пачысціць ад пылу і замяніць тэрмапасту. Ён будзе працаваць 24/7, і перагрэў нам не патрэбен, але і перагрэць такое трэба яшчэ пастарацца.

Частка 4. Усталёўка і Старт

  1. Спампуйце Ubuntu LTS (Long Term Support) з афіцыйнага сайта. LTS версіі падтрымліваюцца 5 гадоў — гэта гарантыя стабільнасці.
  2. Запішыце вобраз на флэшку праз праграму BalenaEtcher (яна самая простая і прыгожая). Калі у вас ужо есць нешта з лінуксаў - то там існуе таксама простая праграма для стварэння бут-флэшак.
  3. Загрузіцеся з флэшкі і выберыце "Install Ubuntu".
  4. Пры ўсталёўцы выбірайце "Minimal Installation" (каб не ставіць лішні офісны пакет і плэеры), але пакіньце галачку "Install third-party software" (для драйвераў Wi-Fi і відэа).

Фінальны штрых: Ставім Docker

Калі сістэма ўсталявалася, віншую! У вас ёсць паўнавартасны Linux-камп'ютар. Засталося адкрыць тэрмінал (Ctrl+Alt+T) і ператварыць яго ў сервер.

Мы не будзем пакутаваць і ўводзіць 10 каманд. Скарыстаемся скрыптом, які ўсё зробіць прыгожа:

bash
1# Абнаўляем сістэму
2sudo apt update && sudo apt upgrade -y
3
4# Ставім Docker адным скрыптом
5curl -fsSL https://get.docker.com -o get-docker.sh
6sudo sh get-docker.sh
7
8# Дадаем сябе ў групу docker (каб не пісаць sudo кожны раз)
9sudo usermod -aG docker $USER
10newgrp docker

Праверыць, ці жывы пацыент:

bash
1docker run hello-world

Калі ён напісаў: "Hello from Docker!" — вы перамаглі, калі не - ну, тут чат ГПТ у дапамогу.

Частка 5. Лікбез: Як карыстацца Docker Compose?

Мы з вамі ўвесь час гаворым пра нейкія файлы docker-compose.yml. Але што з імі рабіць на практыцы?

Усё проста. Docker Compose — гэта рэцэпт. Вы пішаце ў файл, што хочаце запусціць (напрыклад, NextCloud і Базу Дадзеных), а Docker сам усё спампоўвае і звязвае.

Алгарытм дзеянняў:

  1. Ствараем папку пад сэрвіс: Лепш трымаць парадак. Хочаце паставіць Jellyfin? Стварыце папку.

    bash
    1mkdir jellyfin
    2cd jellyfin
  2. Ствараем файл рэцэпту:

    bash
    1nano docker-compose.yml

    (Nano — гэта просты тэкставы рэдактар. Калі вы ў Desktop-версіі Ubuntu, можаце проста стварыць тэкставы файл правай кнопкай мышы, але можна і Gedit).

  3. Устаўляем код: Бярэце код з майго мінулага артыкула, уклейваеце ў файл і захоўваеце (у nano: Ctrl+O, Enter, Ctrl+X).

  4. Запускаем:

    bash
    1docker compose up -d
    • up — падняць (запусціць).
    • -d — detached mode (запусціць у фоне, каб не вісела ў тэрмінале).
  5. Карысныя каманды:

    • docker compose logs -f — паглядзець, што піша праграма (калі нешта не працуе, глядзіце сюды).
    • docker compose down — спыніць і выдаліць кантэйнеры (дадзеныя ў папках застануцца, выдаліцца толькі сама "машына").
    • docker compose pull — абнавіць версію праграмы (калі выйшла новая).

Вось і ўся магія. Ніякіх складаных apt-get install і канфліктаў версій.

Частка 6. Тонкая наладка: Узровень "Бог"

Каб ваш сервер стаў сапраўды "паставіў і забыўся", трэба зрабіць яшчэ некалькі важных шаманскіх дзеянняў.

1. Ноўтбук і сіндром "Зачыненай крышкі"

Калі ў вас ноўтбук, то па змаўчанні пры закрыцці крышкі ён думае, што праца скончана, і пераходзіць у сон. Але сервер — гэта не пра сон, яму спаць нельга!

Растлумачым яму гэта на мове тэрмінала:

  1. Адкрыйце галоўны файл паводзін:
    bash
    1sudo nano /etc/systemd/logind.conf
  2. Знайдзіце радок, дзе напісана #HandleLidSwitch=suspend.
  3. Бязлітасна змяніце яго на:
    text
    1HandleLidSwitch=ignore
    (І прыбярыце рашотку # у пачатку, інакш магія не спрацуе!)
  4. Захавайце (Ctrl+O, Enter) і бяжыце адтуль (Ctrl+X).
  5. І перазагрузіце службу, каб прымяніць змены:
    bash
    1sudo systemctl restart systemd-logind

або проста перазагрузіце сістэму.

Цяпер можаце смела закрываць ноўтбук і хаваць яго ў шафу . Толькі пакіньце яму шчыліну для паветра.

2. Аўтазапуск: Лянота рухае прагрэс.

Святло міргнула, сервер перазагрузіўся... і што? І нічога. Цішыня. Каб не бегаць да яго кожны раз і не тыкаць пальцам у кнопку, наладзім аўтапілот.

А) Docker

Скажам яму: "Устань і ідзі" (разам з сістэмай):

bash
1sudo systemctl enable docker

І не забывайце ў сваіх docker-compose.yml пісаць магічнае заклінанне restart: unless-stopped. Гэта значыць: "Працуй, пакуль я сам цябе не выключу".

Б) Тэлепорт да хаты (WireGuard Clean)

Памятаеце, мы рабілі VPN-сервер? Цяпер зробім так, каб ваш хатні сервер сам залазіў у гэты VPN і сядзеў там як партызан. Тады вы знойдзеце яго па ўнутраным IP (напрыклад, 10.8.0.2), нават калі ваш правайдэр вырашыць змяніць вам адрас тры разы на дзень.

Крок 1. Ставім інструменты:

bash
1sudo apt install wireguard resolvconf -y

Крок 2. Дадаем канфіг:

  1. Зайдзіце ў свой WireGuard Easy (з мінулага гайда).
  2. Стварыце кліента HomeServer.
  3. Спампуйце яго файл.

Крок 3. Ужыўляем канфіг: Ствараем файл на серверы:

bash
1sudo nano /etc/wireguard/wg0.conf

Капіруем усё з таго файліка, што спампавалі, і ўстаўляем сюды. Захоўваем (Ctrl+O, Enter, Ctrl+X).

Крок 4. Запускаем магічны тунэль:

bash
1sudo systemctl enable wg-quick@wg0
2sudo systemctl start wg-quick@wg0

Крок 5. Момант ісціны:

bash
1sudo wg show

Бачыце зялёнае/белае і словы handshake? Віншую! Ваш сервер цяпер у "віртуальнай сетцы".

3. Парады бывалых

  • Хочаце адчуць сябе Неа? Усталюйце btop.
    bash
    1sudo snap install btop
    Запусціце і глядзіце на прыгожыя графікі. Карысці — нуль, затое выглядае крута.
  • Лянівае абнаўленне: Раз на месяц заходзьце ў папку з праектам і рабіце:
    bash
    1docker compose pull && docker compose up -d
    Гэта абновіць усё, што можна абнавіць, пакуль вы п'яце каву.

Што далей?

Цяпер у вас ёсць магутны падмурак - уласны сервер на Ubuntu. Прыйшоў час накатаць на яго софт. Вяртайцеся да майго мінулага артыкула Джэнтльменскі набор, бярыце адтуль docker-compose файлы і запускайце свае сэрвісы.

Цяпер яны будуць працаваць хутка, стабільна і цалкам пад вашым кантролем. Поспехаў у будаўніцтве лічбавага дома!

server
Admin, 2026-01-16

Я вялікі фанат сэра Тэры Пратчэта. Яго кнігі паўплывалі на маё пачуццё гумару і на тое, як я гляджу на свет ня толькі ў межах фэнтэзі-літаратуры. Некаторы час таму я дадаў на свой англамоўны блог невялікую, але значную дэталь — HTTP-загаловак X-Clacks-Overhead.

Гэты загаловак з’яўляецца спасылкай на раман «Going Postal» і сістэму сувязі Clacks. Коратка кажучы, гэта ціхі спосаб сказаць «GNU Terry Pratchett» — сігнал, які дазваляе трансляваць яго імя па сетцы і не быць яму забытым. Прасцей кажучы, велікоднае яйка для фанатаў :)

Мой блог працуе на Cloudflare Pages. Гэтая платформа падтрымлівае карыстальніцкія HTTP-загалоўкі адказу праз звычайны тэкставы файл _headers, размешчаны ў каранёвым каталогу сайта, і дадае загалоўкі згодна з вызначанымі вамі правіламі.

Вось адпаведны раздзел з майго файла _headers:

text
1/*
2  X-Clacks-Overhead: "GNU Terry Pratchett"

Вось і ўсё — кожны запыт да статычных рэсурсаў і HTML атрымлівае гэты загаловак у адказе.

Калі хочаце праверыць гэта самастойна, адкрыйце інструменты распрацоўшчыка ў браўзеры → укладку Network → праверце загалоўкі адказу, альбо запусціце ў кансолі гэтую каманду:

text
1curl -I https://hleb.dev

Ён не робіць нічога карыснага. Нічога не змяняе ні ў прадуктыўнасці, ні ў функцыянальнасці блога. Але часам менавіта такія маленькія, здавалася б непатрэбныя рэчы робяць інтэрнэт лепшым.

Гэта пераклад майго англамоўнага артыкула.

http
cloudflare
hleb, 2026-01-14

cover

Прывітанне спадарства!

Кожны паважаючы сябе джэнтльмен (і лэдзі, вядома) павінен мець тры рэчы: добры касцюм, чыстае сумленне і ўласны сервер. Ну добра, наконт касцюма можна паспрачацца, а вось сервер — рэч незаменная. Сёння я пакажу вам свой "залаты стандарт" — 6 сэрвісаў, якія ператвараюць звычайны камп'ютар у магутны цэнтр кіравання палётамі.

І ўсё гэта — па цане кубка кавы. Мы пабудуем экасістэму, дзе вы зможаце глядзець кіно, захоўваць сакрэтныя планы захопу свету коцікамі (ці проста іх фатаграфіі) і кіраваць усім гэтым праз бяспечны VPN-тунэль.

Заводзьце свае докеры, пагналі!

Архітэктура: Дзе запускаць усё гэта?

Каб усё працавала ідэальна, я рэкамендую наступную схему:

  1. Аддалены VPS-сервер:

    • Тут мы запускаем толькі VPN (WireGuard).
    • Чаму: Вам патрэбен статычны "белы" IP-адрас, каб да яго можна было падключыцца з любога месца. Самы танны VPS за $3-5 у месяц выдатна падыдзе. Ён будзе працаваць як "уваходныя вароты".
  2. Лакальны Хатні Сервер:

    • Тут мы запускаем усё астатняе (Portainer, NextCloud, Jellyfin, Excalidraw, Flatnotes).
    • Што гэта можа быць: Стары ноўтбук, які пыліцца на паліцы, міні-ПК (напрыклад Intel NUC) або ваш асноўны ПК.

      Заўвага пра Raspberry Pi: Хоць "малінка" вельмі папулярная, для поўнага спісу гэтых сэрвісаў яна можа быць слабаватай. Асабліва Jellyfin патрабуе магутнасці для апрацоўкі відэа, ды і NextCloud любіць паесці аператыўную памяць. Лепш глядзець у бок x86 жалеза (стары ноўт ці mini-PC).

    • Чаму:
      • Танна: Вам не трэба плаціць за дарагія гігабайты дыска ў воблаку. Ваш стары HDD на 1TB будзе бясплатным.
      • Хутка: Дома фільмы праз Jellyfin будуць лятаць па Wi-Fi на максімальнай хуткасці, не нагружаючы інтэрнэт.
      • Прыватна: Вашы асабістыя дадзеныя фізічна знаходзяцца ў вас дома.

Як гэта звязаць? Вы падключаеце свой лакальны сервер да VPN (як кліент). Цяпер вы з тэлефона падключаецеся да таго ж VPN, і вуаля — вы ў адной віртуальнай сетцы са сваім хатнім серверам, дзе б вы ні знаходзіліся.

1. WireGuard (wg-easy)

ws

Навошта гэта трэба? Каб вашы сэрвісы былі даступныя вам у любой кропцы свету, але пры гэтым схаваныя ад старонніх вачэй. Гэта ваш асабісты шыфраваны тунэль дадому.

Чаму менавіта WireGuard? Ён хуткі, сучасны і менш жарэ батарэю на тэлефоне ў параўнанні з OpenVPN. Я рэкамендую выкарыстоўваць wg-easy. Гэта WireGuard, які ставіцца за хвіліну і мае зручны вэб-інтэрфейс для стварэння канфігаў. Вам не трэба пісаць складаныя канфігурацыі ў тэрмінале — проста заходзіце ў браўзер, ствараеце карыстальніка "iPhone" і скануеце QR-код праграмай WireGuard на тэлефоне. Усё, вы ў хатняй сетцы!

docker-compose.yml:

yaml
1version: "3.8"
2services:
3  wg-easy:
4    image: ghcr.io/wg-easy/wg-easy
5    container_name: wg-easy
6    environment:
7      # Замяніце на ваш рэальны знешні IP або дамен
8      - WG_HOST=YOUR_SERVER_IP
9      # Пароль для доступу да вэб-інтэрфейсу
10      - PASSWORD=secret_password
11      - WG_PORT=51820
12      - WG_DEFAULT_ADDRESS=10.8.0.x
13      - WG_DEFAULT_DNS=1.1.1.1
14    volumes:
15      - ./wireguard:/etc/wireguard
16    ports:
17      - "51820:51820/udp"
18      - "51821:51821/tcp"
19    restart: unless-stopped
20    cap_add:
21      - NET_ADMIN
22      - SYS_MODULE
23    sysctls:
24      - net.ipv4.ip_forward=1
25      - net.ipv4.conf.all.src_valid_mark=1

Важна: Пасля запуску вэб-інтэрфейс будзе даступны па порце 51821. Наладзьце ў ім кліентаў, падключыцеся, і далей вы зможаце звяртацца да іншых сэрвісаў па іх лакальных IP (ці па ўнутраных IP Docker сеткі, калі наладзіць маршрутызацыю).

2. Portainer

port Навошта гэта трэба? Калі ў вас запушчана 5-10 кантэйнераў, сачыць за імі праз кансоль становіцца нязручна. Portainer — гэта візуальны пульт кіравання вашым серверам.

Што дае:

  • Зручнасць з тэлефона: Калі нешта зламалася, а вы не ля камп'ютара, можна зайсці з тэлефона ў вэб-інтэрфейс Portainer і перазапусціць кантэйнер адной кнопкай.
  • Логі і статыстыка: Адразу бачна, колькі памяці спажывае праграма і што яна піша ў лог, без неабходнасці ўводзіць docker logs -f ....
  • Рэдагаванне на ляту: Можна змяніць зменную асяроддзя і перастварыць кантэйнер прама ў браўзеры.

docker-compose.yml:

yaml
1version: "3.8"
2services:
3  portainer:
4    image: portainer/portainer-ce:latest
5    container_name: portainer
6    restart: always
7    volumes:
8      - /var/run/docker.sock:/var/run/docker.sock
9      - ./portainer_data:/data
10    ports:
11      - "9000:9000"

3. Excalidraw

excalidraw Навошта гэта трэба? Часам трэба хутка намаляваць схему, дыяграму ці проста візуалізаваць думкі. Існуюць анлайн-сэрвісы, але навошта аддаваць ім свае ідэі? Excalidraw — гэта open-source рашэнне.

Плюсы сэлф-хостынгу:

  • Прыватнасць: Вашы схемы захоўваюцца толькі ў вас. Ніякай перадачы дадзеных на чужыя серверы.
  • Доступ з планшэта: Excalidraw шыкоўна працуе на iPad ці Android-планшэтах. Стыль "ад рукі" робіць схемы жывымі і зразумелымі.
  • Аўтаномнасць: Працуе нават калі адключылі інтэрнэт.

docker-compose.yml:

yaml
1version: "3.8"
2services:
3  excalidraw:
4    image: excalidraw/excalidraw:latest
5    container_name: excalidraw
6    restart: unless-stopped
7    ports:
8      - "3001:80"

4. Flatnotes

Навошта гэта трэба? Notion і Obsidian — гэта крута, але часам яны занадта "цяжкія" або патрабуюць сінхранізацыі праз незразумелыя воблакі.

Чаму Flatnotes:

  • Чысты Markdown: Вашы нататкі — гэта проста тэкставыя файлы. Вы заўсёды зможаце іх прачытаць, нават калі сэрвіс знікне.
  • Маланкавы пошук: Імгненна знаходзіць патрэбнае.
  • Мінімалізм: Нічога лішняга, толькі вы і тэкст. Ідэальна пасуе для "вікі" па праекце ці асабістых запісаў.
  • Доступ адусюль: Пішыце з ноўтбука, чытайце з тэлефона. Інтэрфейс выдатна адаптуецца пад мабільныя прылады.

docker-compose.yml:

yaml
1version: "3.8"
2services:
3  flatnotes:
4    image: dullage/flatnotes:latest
5    container_name: flatnotes
6    environment:
7      - PUID=1000
8      - PGID=1000
9      - FLATNOTES_AUTH_TYPE=password
10      - FLATNOTES_USERNAME=user
11      - FLATNOTES_PASSWORD=change_me
12      - FLATNOTES_SECRET_KEY=a_long_random_string
13    volumes:
14      - ./notes:/data
15    ports:
16      - "8080:8080"
17    restart: unless-stopped

5. NextCloud

nextcloude Навошта гэта трэба? Гэта ўжо цяжкая артылерыя. Поўная замена Google Drive, Dropbox і iCloud. NextCloud дазваляе цалкам адмовіцца ад старонніх воблакаў.

Магчымасці:

  • Аўтазапампоўка фота: Ставіце праграму NextCloud на тэлефон, і ўсе вашы новыя фоткі аўтаматычна ляцяць на ваш хатні сервер. Тэлефону можно ламацца — фота ў бяспецы.
  • Воблака для ўсяго: Можна кінуць файлы з ноўтбука, а потым адкрыць іх на тэлефоне. Гэта як ваша персанальнае воблака, доступ да якога маеце толькі вы праз VPN.
  • Сінхранізацыя кантактаў і календароў: Калі вы хочаце сапраўды "De-Google" сваё жыццё, NextCloud можа стаць цэнтрам сінхранізацыі ўсіх вашых прылад.

Для простага запуску можна выкарыстаць SQLite (не рэкамендуецца для вялікай нагрузкі) або паўнавартасную базу дадзеных. Ніжэй варыянт з базай дадзеных MariaDB.

docker-compose.yml:

yaml
1version: "3.8"
2
3services:
4  db:
5    image: mariadb:10.6
6    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
7    restart: always
8    volumes:
9      - ./nextcloud_db:/var/lib/mysql
10    environment:
11      - MYSQL_ROOT_PASSWORD=root_password
12      - MYSQL_PASSWORD=nextcloud_user_password
13      - MYSQL_DATABASE=nextcloud
14      - MYSQL_USER=nextcloud
15
16  app:
17    image: nextcloud
18    restart: always
19    ports:
20      - "8081:80"
21    links:
22      - db
23    volumes:
24      - ./nextcloud_html:/var/www/html
25    environment:
26      - MYSQL_PASSWORD=nextcloud_user_password
27      - MYSQL_DATABASE=nextcloud
28      - MYSQL_USER=nextcloud
29      - MYSQL_HOST=db

6. Bonus - Jellyfin

jellyfin Навошта гэта трэба? Гэта не проста "відэа-плэер", гэта сапраўдны медыя-камбайн. Ваш уласны Netflix, Spotify і Audible у адным флаконе. Пампуем на сервер - глядзім паўсюль - на тэлефоне, тэлевізары і інш.

Што ён умее:

  • Кіно і Серыялы: Аўтаматычна распазнае файлы, падцягвае прыгожыя вокладкі, апісанні, рэйтынгі IMDB і фота акцёраў. Умее запамінаць, дзе вы спыніліся (resume playback).
  • Музыка: Выдатная замена Spotify для вашай асабістай калекцыі. Ёсць падтрымка плэйлістоў, "радыё" па жанрах і стрымінг на тэлефон у высокай якасці (FLAC).
  • Кнігі і Коміксы: Jellyfin выдатна разумее фарматы электронных кніг (ePub, PDF) і коміксаў (CBR/CBZ). Можна чытаць любімую мангу ці тэхнічную літаратуру з планшэта праз зручны інтэрфейс.
  • Аўдыёкнігі: Асобная бібліятэка для аўдыёкніг, якая памятае прагрэс для кожнай кнігі.
  • Live TV: Калі ў вас ёсць IPTV-плэйліст, яго можна дадаць у Jellyfin і атрымаць тэлебачанне з праграмай перадач і магчымасцю запісу эфіру (DVR).

Чаму Jellyfin:

  • Цалкам бясплатна: У адрозненне ад канкурэнтаў (Plex, Emby), тут няма ніякіх прэміум-падпісак. Усе функцыі адкрыты адразу.
  • Транскадзіраванне: Калі ваш тэлевізар не "цягне" цяжкі 4K-фільм, сервер сам на ляту пераробіць яго ў патрэбны фармат.
  • Кліенты пад усё: Android TV, Apple TV, iOS, Android, Web, Roku. Пачалі глядзець на тэлевізары — даглядзелі ў дарозе на тэлефоне.

docker-compose.yml:

yaml
1version: "3.8"
2services:
3  jellyfin:
4    image: jellyfin/jellyfin:latest
5    container_name: jellyfin
6    user: 1000:1000
7    network_mode: "host" # Рэкамендуецца для DLNA і адкрыцця партоў
8    volumes:
9      - ./jellyfin/config:/config
10      - ./jellyfin/cache:/cache
11      - /path/to/media:/media # Пакажыце шлях да вашых фільмаў
12    restart: "unless-stopped"

Як бачыце, разгарнуць уласныя сэрвісы сёння прасцей, чым здаецца. Вам не трэба быць гуру Linux ці DevOps-інжынерам. Дастаткова Docker, жадання крыху разабрацца і пары вечароў.

Гэты спіс — толькі вяршыня айсберга. Існуюць тысячы гатовых кантэйнераў: ад блакіроўшчыкаў рэкламы (Pi-hole) да сістэм разумнага дома (Home Assistant) і асабістых бібліятэк кніг. Галоўнае — пачаць. Вы атрымаеце не толькі зручныя інструменты, якія належаць толькі вам, але і кайф ад таго, што зрабілі гэта самі.

Спадзяюся, мой досвед будзе вам карысны. Калі ў вас ёсць пытанні, ці вы ведаеце іншыя класныя кантэйнеры, пра якія варта расказаць — пішыце ў каментарах, будзем разбірацца разам!

docker
Admin, 2026-01-09

cover

Каляды - адно з найстаражытнейшых свят на землях сучаснай Беларусі

На працягу тысячагоддзяў мяняліся дзяржавы, вераванні, але Каляды заставаліся. Разам з імі змяняўся і каляндар, а значыць - і сама дата святкавання. Каб зразумець, чаму сёння Каляды бываюць і 25 снежня, і 7 студзеня, трэба паглядзець на гісторыю паслядоўна.

Дахрысціянская эпоха

У дахрысціянскую эпоху Каляды былі звязаныя з зімовым сонцаваротам - найкароткім днём і самай доўгай ноччу года. Свята прыпадала прыкладна на 21–22 снежня па сучасным грыгарыянскім календары. Гэта быў момант нараджэння новага Сонца і пачатку новага гадавога кола.

Хрысціянізацыя (X–XI ст.) і Сярэднявечча

Пасля хрысціянізацыі ў X–XI стагоддзях Каляды былі злучаныя са святам Нараджэння Хрыста і замацаваныя за датай 25 снежня па юліянскім календары, што на той час супадала з 25 снежня па сучасным календары (розніца паміж сістэмамі з’явілася пазней). У сярэднявеччы і на працягу наступных стагоддзяў Каляды на землях сучаснай Беларусі святкаваліся менавіта ў гэты дзень.

Рэч Паспалітая (з 1582 г.)

Да 1582 года Еўропа жыла па юліянскім календары. Але ён быў недакладным: за 128 гадоў набягалі адны лішнія суткі памылкі. Да XVI стагоддзя набегла ўжо 10 лішніх дзён. Каб вярнуць каляндар у адпаведнасць з прыродай (раўнадзенствам), папа Рыгор XIII загадаў "выкрасліць" гэтыя 10 дзён. Як гэта выглядала: Людзі леглі спаць 4 кастрычніка 1582 года, а прачнуліся адразу 15 кастрычніка. Розніца: Адразу стала 10 дзён. У гэтым годзе Рэч Паспалітая прыняла грыгарыянскі каляндар. З гэтага моманту дата Калядаў на землях сучаснай Беларусі замацавалася як 25 снежня па грыгарыянскім календары, гэта значыць 25 снежня і паводле сённяшняга календара. У такім рытме гэтыя землі жылі з 1582 да 1772 года.

Чаму розніца павялічваецца?

Гэта самае цікавае. Грыгарыянскі каляндар больш хітры ў падліку высакосных гадоў (тых, дзе ёсць 29 лютага). У юліянскім (старым) календары кожны чацвёрты год — высакосны. У грыгарыянскім (новым) — гады, якія заканчваюцца на "00" (1700, 1800, 1900), не з'яўляюцца высакоснымі, калі яны не дзеляцца на 400. З-за гэтага юліянскі каляндар накідвае "лішні" дзень кожныя сто гадоў (апроч кратных 400).

Расійская імперыя (пасля 1772 г.)

Пасля падзелаў Рэчы Паспалітай землі сучаснай Беларусі апынуліся ў складзе Расійскай імперыі, дзе працягваў дзейнічаць юліянскі каляндар.

  • У XVIII стагоддзі розніца паміж календарамі складала 11 дзён.
  • У XIX стагоддзі - 12 дзён.
  • З XX стагоддзя - 13 дзён.

Таму традыцыйнае 25 снежня па юліянскім календары паступова пачало адпавядаць 7 студзеня па сучасным грыгарыянскім календары. З канца XVIII стагоддзя і да пачатку XX стагоддзя Каляды на землях сучаснай Беларусі фактычна святкаваліся 7 студзеня ў сучасным адліку часу.

Савецкі перыяд і Сучаснасць

У 1918 годзе савецкая ўлада ўвяла грыгарыянскі каляндар у грамадзянскім жыцці. Дзяржава з таго часу жыве па сучасным календары, але праваслаўная царква захавала юліянскі. Таму Каляды і сёння існуюць у дзвюх датах: 25 снежня і 7 студзеня (гэта 25 снежня па юліянскім календары).

Гістарычнае рэзюмэ

Такім чынам, у розныя гістарычныя перыяды Каляды на землях сучаснай Беларусі святкаваліся так:

  • У паганскую эпоху: каля 21–22 снежня.
  • У сярэднявеччы: 25 снежня.
  • У часы ВКЛ і Рэчы Паспалітай: 25 снежня.
  • У складзе Расійскай імперыі: 7 студзеня (у перакладзе на сучасны каляндар).
  • У савецкі перыяд: пераважна неафіцыйна.
  • У сучаснай Беларусі: і 25 снежня, і 7 студзеня.

Літаратура:

  1. Беларускі фальклор: Энцыклапедыя. У 2 т. Т. 1: А — К / Рэдкал.: Г. П. Пашкоў і інш. — Мінск: Беларуская Энцыклапедыя імя П. Броўкі, 2005.
  2. Крук Я., Катовіч, А. Залатыя правілы народнай культуры. — 2-е выд., дап. — Мінск: Адукацыя і выхаванне, 2010.
  3. Кухаронак Т. І. Каляндарныя звычаі і абрады беларусаў. — Мінск: Навука і тэхніка, 1993.
  4. Лобач У. А. Міф. Прастора. Чалавек: традыцыйны культурны ландшафт беларусаў. — Мінск: Тэхналогія, 2013.
  5. Энцыклапедыя гісторыі Беларусі. У 6 т. Т. 4: Кадэты — Ляшчэня / Беларус. Энцыкл.; Рэдкал.: Г. П. Пашкоў (галоўны рэд.) і інш. — Мінск: БелЭн, 1997.
Каляндар
Беларусь
Stanislava, 2025-12-25

cover

Вітанкі, спадарства!

Вось і амаль скончыўся 2025 год. Мы сталі старэйшымі, крыху разумнейшымі і, спадзяюся, усё яшчэ патрэбнымі гэтаму свету, нягледзячы на ўсе гэтыя вашыя нейрасеткі. Час падвесці рысу і паглядзець, чым мы тут увогуле займаліся цэлы год (Але спачатку віншаванне).

Віншуем вас з надыходзячым Новым 2026 годам!

Жадаем, каб у новым годзе ваш асабісты "прадакшн" працаваў стабільна, багі фіксіліся імгненна, а жыццё падкідвала толькі прыемныя апдэйты. Няхай розум застаецца светлым, а сэрца — гарачым.

Падымаем віртуальныя (і не толькі) келіхі за нашу супольнасць.

А цяпер давайце паглядзім, як мы дакаціліся да такога жыцця ў мінулым годзе.

Што вы шукалі ў нас?

Цікава назіраць, як змяняюцца інтарэсы. Але ёсць рэчы, якія застаюцца нязменнымі. Самым запатрабаваным матэрыялам нашага рэсурсу стаў артыкул пра наладжванне раскладкі — "Кастамная раскладка клавятуры Windows для беларускай лацінкі й ня толькі". Відаць, перад тым як пісаць код або раманы, трэба ўсё ж такі разабрацца, дзе якая літара знаходзіцца. Гэта база!

Таксама вас цікавіла наша гісторыя — таямнічая і велічная "Рагнеда - першая вядомая жанчына Полацкага княства". Мы разам разбіраліся ў аптычных ілюзіях, каб не даць вачам падмануць розум, і смяяліся разам з класікамі ў аглядзе кнігі "Купала і Колас жартуюць". Ну і, вядома, вечнае пытанне: "Што паглядзець ці пачытаць па-беларуску".

Што вы чыталі да дзірак?

Статыстыка праглядаў не хлусіць: вы сапраўдныя хардкоршчыкі. Ніякіх "топ-10 коцікаў", толькі суровы тэхнічны кантэнт (але ці быў іншы?). Безумоўным лідарам стаў наш гайд "Надзейны AI-workflow з GitHub Copilot". Зразумела, усе мы хочам, каб робат працаваў замест нас, а мы толькі пілі каву і атрымлівалі зарплату. Таксама вы актыўна чыталі пра тое, як прымусіць AI не хлусіць (так, гэта ўсё яшчэ праблема) і як навучыць яго чытаць вашыя дакументы. Тэмы Zero-Shot і Few-Shot таксама ў топе — відаць, вы ўсур'ёз вырашылі знайсці агульную мову з гэтымі жалязякамі.

Нашы праекты і надзеі

У 2025 годзе мы выкацілі ў прадакшн Zaspa.online і goman.live. Планы былі сціплыя: падпарадкаваць сусвет і абагнаць OpenAI. Пакуль што мы на стадыі "падпарадкаваць сэрцы першых карыстальнікаў", але рухаемся ў правільным кірунку! Сэрвісы працуюць, багі фіксяцца (часам), і мы верым у светлую будучыню.

А вось з новымі аўтарамі сітуацыя як у спартзале ў лютым — пуставата. Няўжо ўсе баяцца? Сябры, калі вы ўмееце выйсці з Vim, вы ўжо можаце пісаць тэхнічныя артыкулы! Пераставайце саромецца і прыходзьце да нас. Мы не крытыкуем, мы рэдагуем (з любоўю, але гэта не дакладна).

Утульны куток

І не забывайце пра наш Discord-сервер. Гэта месца, дзе можна зняць гальштук (і нават штаны,бо ніхто не пабачыць) і проста пагутарыць. Пра софт, пра тое, як "увайсці ў айці" і не выйсці ў вакно, ці проста пачытаць навіны. Там свая атмасфера, і без вас яна як код без каментароў — працуе, але нешта не тое.

Словы ўдзячнасці

Напрыканцы — хвілінка сентыментальнасці (абяцаю, плакаць не будзем). Дзякуй аўтарам, якія знаходзілі час паміж дэдлайнамі і выгараннем, каб пісаць гэтыя цудоўныя тэксты. Дзякуй нябачным героям — адмінам нашага Telegram-канала. Гэта яны фільтруюць спам пра крыпту і робяць так, каб ваша стужка была чыстай і прыгожай.

І, вядома, дзякуй вам, нашы чытачы. Вы ставіце лайкі, пішаце каменты (часам нават добрыя) і матывуеце нас не закідваць гэтую справу. Без вас мы б проста размаўлялі самі з сабой, а гэта ўжо дыягназ.

Заставайцеся з намі ў 2026-м. Будзе яшчэ весялей, ці хаця б не сумна!

З надыходзячым Новым годам, сябры! (і няхай прадакшн не падае, а то я закалупаўся сярод ночы выпраўляць тое што нарабіў)!

belgeek
Admin, 2025-12-21

head

Што вы даведаецеся: Як будаваць AI-агентныя сістэмы з LangGraph - ад базавых канцэпцый да працуючага кода. Мы створым пайплайн для напісання артыкулаў з некалькімі AI-агентамі, якія супрацоўнічаюць, правяраюць працу адзін аднаго і ітэруюць, пакуль вынік не будзе ідэальным.


ЧАСТКА 1: Базавыя канцэпцыі

Што такое граф?

Перш чым разбірацца з LangGraph, трэба зразумець, што такое граф у праграмаванні.

Граф - гэта структура даных

Уявіце карту метро:

  • Станцыі - гэта вузлы (nodes)
  • Лініі паміж станцыямі - гэта пераходы (edges)
text
1    Звычайны граф:              Карта метро (аналогія):
2
3        [A]                         [Плошча Перамогі]
4         │                                 │
5         ▼                                 ▼
6        [B]───────►[C]              [Кастрычніцкая]───►[Купалаўская]
7         │                                 │
8         ▼                                 ▼
9        [D]                         [Інстытут культуры]

У LangGraph:

  • Вузлы - гэта функцыі (агенты), якія нешта робяць.
  • Пераходы - гэта правілы, хто пасля каго працуе.

Навошта патрэбны LangGraph?

Праблема: Звычайныя AI-праграмы лінейныя

text
1Звычайны ланцужок (Chain):
2
3    Пытанне → LLM → Адказ
4
5    або
6
7    Пытанне → Інструмент 1 → LLM → Інструмент 2 → Адказ

Гэта працуе для простых задач, але што, калі:

  • Трэба вярнуцца назад і перарабіць?
  • Трэба праверыць вынік і, магчыма, паўтарыць?
  • Трэба некалькі агентаў з рознымі ролямі?

Рашэнне: LangGraph дазваляе ствараць цыклы

text
1LangGraph (Граф):
2
3                    ┌──────────────────────┐
4                    │                      │
5                    ▼                      │
6    Пытанне → [Даследчык] → [Пісьменнік] → [Рэцэнзент]
789                                          Добра? ───НЕ───► назад да Пісьменніка
1011                                              ТАК
121314                                           [Вынік]

Што такое "стан" (State)?

Стан - гэта памяць праграмы

Уявіце, што вы пішаце артыкул з камандай:

  • Даследчык сабраў матэрыялы → трэба некуды запісаць.
  • Пісьменнік напісаў чарнавік → трэба перадаць рэцэнзенту.
  • Рэцэнзент напісаў заўвагі → трэба вярнуць пісьменніку.

Стан - гэта "кошык", куды ўсе кладуць свае вынікі і адкуль бяруць даныя.

text
1┌─────────────────────────────────────────────────────────────┐
2│                         СТАН (State)                        │
3├─────────────────────────────────────────────────────────────┤
4│                                                             │
5│   topic: "Пра што пішам"                                    │
6│   research: "Матэрыялы ад даследчыка"                       │
7│   draft: "Чарнавік ад пісьменніка"                          │
8│   review: "Заўвагі ад рэцэнзента"                           │
9│   finalArticle: "Гатовы артыкул"                            │
10│   messages: [гісторыя ўсіх паведамленняў]                   │
11│                                                             │
12└─────────────────────────────────────────────────────────────┘
13         ▲                    ▲                    ▲
14         │                    │                    │
15    Даследчык            Пісьменнік           Рэцэнзент
16    (чытае і піша)       (чытае і піша)       (чытае і піша)

ЧАСТКА 2: Annotation - Як ствараецца стан

Што такое Annotation?

Annotation - гэта спосаб апісання структуры стану. Гэта як стварэнне формы з палямі.

Аналогія: Анкета

Уявіце, што вы ствараеце анкету:

text
1┌─────────────────────────────────────────┐
2│            АНКЕТА РАБОТНІКА             │
3├─────────────────────────────────────────┤
4│ Імя: ___________________                │
5│ Узрост: _____                           │
6│ Вопыт працы (гады): _____               │
7│ Спіс навыкаў: ___, ___, ___             │
8└─────────────────────────────────────────┘

У кодзе гэта выглядае так:

typescript
1// АНАЛОГІЯ: Стварэнне формы анкеты
2const Anketa = {
3    imya: '', // Тэкставае поле
4    uzrost: 0, // Лік
5    vopyt: 0, // Лік
6    navyki: [], // Спіс
7};

У LangGraph: Annotation.Root

У LangGraph стан ствараецца з дапамогай Annotation.Root(). Гэта спецыяльная функцыя, якая апісвае структуру вашых даных - якія палі існуюць і як яны павінны абнаўляцца.

typescript
1import { Annotation } from '@langchain/langgraph';
2
3const ResearchState = Annotation.Root({
4    // Кожнае поле апісваецца праз Annotation<Тып>
5    topic: Annotation<string>({...}),
6    research: Annotation<string>({...}),
7    draft: Annotation<string>({...}),
8    // і г.д.
9});

Кожнае поле ўнутры Annotation.Root мае дзве важныя ўласцівасці: reducer (як абнаўляць значэнне) і default (пачатковае значэнне). Мы разбяром іх далей.


Што такое Reducer?

Праблема: Як аб'ядноўваць даныя?

Калі некалькі агентаў пішуць у адно поле, што рабіць?

text
1Агент 1 піша: topic = "Тэма А"
2Агент 2 піша: topic = "Тэма Б"
3
4Што павінна быць у topic? "Тэма А"? "Тэма Б"? "Тэма А + Тэма Б"?

Рашэнне: Reducer - функцыя, якая вырашае

Reducer - гэта функцыя, якая атрымлівае:

  1. Бягучае значэнне (што ўжо ёсць)
  2. Новае значэнне (што прыйшло)

І вяртае: вынік (што захаваць)

typescript
1reducer: (current, update) => результат;
2//         ▲         ▲           ▲
3//         │         │           └── Што захаваецца
4//         │         └── Новае значэнне
5//         └── Бягучае значэнне

Прыклады Reducer-аў:

1. Reducer "ЗАМЯНІЦЬ" (replace)

Новае значэнне поўнасцю замяняе старое.

typescript
1// Код:
2reducer: (current, update) => update;
3
4// Прыклад:
5// Бягучае: "Тэма А"
6// Новае:   "Тэма Б"
7// Вынік:   "Тэма Б"  ← новае замяніла старое

Аналогія: Вы перазапісваеце файл - новы змест замяняе стары.

text
1файл.txt
2──────────────
3Было:   "Стары тэкст"
4        ▼ (перазапіс)
5Стала:  "Новы тэкст"
2. Reducer "ДАДАЦЬ" (append)

Новыя элементы дадаюцца да існуючых.

typescript
1// Код:
2reducer: (current, update) => [...current, ...update];
3
4// Прыклад:
5// Бягучае: ["Паведамленне 1", "Паведамленне 2"]
6// Новае:   ["Паведамленне 3"]
7// Вынік:   ["Паведамленне 1", "Паведамленне 2", "Паведамленне 3"]

Аналогія: Вы дадаеце новыя запісы ў дзённік - старыя застаюцца.

text
1дзённік.txt
2──────────────
3Было:   "Панядзелак: зрабіў А"
4        "Аўторак: зрабіў Б"
5        ▼ (дадаём)
6Стала:  "Панядзелак: зрабіў А"
7        "Аўторак: зрабіў Б"
8        "Серада: зрабіў В"  ← дадалося

Поўны прыклад стану:

typescript
1const ResearchState = Annotation.Root({
2    // ═══════════════════════════════════════════════════════
3    // ПОЛЕ: messages (паведамленні)
4    // ═══════════════════════════════════════════════════════
5    messages: Annotation<BaseMessage[]>({
6        // REDUCER: Дадаваць новыя паведамленні да існуючых
7        reducer: (current, update) => [...current, ...update],
8        // DEFAULT: Пачатковае значэнне - пусты масіў
9        default: () => [],
10    }),
11    //
12    // Як гэта працуе:
13    // 1. Пачатак:    messages = []
14    // 2. Даследчык:  messages = [] + [AIMessage] = [AIMessage]
15    // 3. Пісьменнік: messages = [AIMessage] + [AIMessage] = [AIMessage, AIMessage]
16    // 4. І г.д. - усе паведамленні захоўваюцца
17
18    // ═══════════════════════════════════════════════════════
19    // ПОЛЕ: topic (тэма)
20    // ═══════════════════════════════════════════════════════
21    topic: Annotation<string>({
22        // REDUCER: Замяняць старое значэнне новым
23        reducer: (_, update) => update, // "_" значыць "ігнаруем"
24        // DEFAULT: Пачатковае значэнне - пусты радок
25        default: () => '',
26    }),
27    //
28    // Як гэта працуе:
29    // 1. Пачатак:    topic = ""
30    // 2. Карыстач:   topic = "" → "LangChain"
31    // Калі хтось яшчэ напіша ў topic - старое значэнне знікне
32
33    // ═══════════════════════════════════════════════════════
34    // ПОЛЕ: iterationCount (лічыльнік ітэрацый)
35    // ═══════════════════════════════════════════════════════
36    iterationCount: Annotation<number>({
37        reducer: (_, update) => update, // Проста замяняем
38        default: () => 0, // Пачынаем з 0
39    }),
40    //
41    // Пісьменнік кожны раз піша: iterationCount: state.iterationCount + 1
42    // 1. Пачатак:         iterationCount = 0
43    // 2. Пісьменнік (1):  iterationCount = 0 + 1 = 1
44    // 3. Пісьменнік (2):  iterationCount = 1 + 1 = 2
45    // 4. Пісьменнік (3):  iterationCount = 2 + 1 = 3
46});

Візуалізацыя Reducer-аў:

text
1┌─────────────────────────────────────────────────────────────────┐
2│                    REDUCER: ЗАМЯНІЦЬ                            │
3├─────────────────────────────────────────────────────────────────┤
4│                                                                 │
5│   Бягучае:  █████████████  "Стары тэкст"                        │
6│                   ▼                                             │
7│   Новае:    ░░░░░░░░░░░░░  "Новы тэкст"                         │
8│                   ▼                                             │
9│   Вынік:    ░░░░░░░░░░░░░  "Новы тэкст"  ← толькі новае         │
10│                                                                 │
11└─────────────────────────────────────────────────────────────────┘
12
13┌─────────────────────────────────────────────────────────────────┐
14│                    REDUCER: ДАДАЦЬ                              │
15├─────────────────────────────────────────────────────────────────┤
16│                                                                 │
17│   Бягучае:  [█] [█] [█]         ← тры элементы                  │
18│                   +                                             │
19│   Новае:    [░] [░]             ← два новыя                     │
20│                   =                                             │
21│   Вынік:    [█] [█] [█] [░] [░] ← усе разам                     │
22│                                                                 │
23└─────────────────────────────────────────────────────────────────┘

Што такое default?

default - гэта функцыя, якая вяртае пачатковае значэнне поля.

typescript
1default: () => значэнне

Чаму функцыя, а не проста значэнне?

Гэта распаўсюджаная пастка JavaScript. Калі вы выкарыстоўваеце просты аб'ект або масіў як default, усе экзэмпляры будуць спасылацца на адну і тую ж спасылку - змены ў адным месцы паўплываюць на ўсе астатнія!

typescript
1// ДРЭННА: Калі гэта аб'ект або масіў
2default: []  // Усе экзэмпляры будуць спасылацца на адзін масіў!
3
4// ДОБРА: Функцыя стварае новы масіў кожны раз
5default: () => []  // Кожны экзэмпляр атрымае свой масіў

Прыклады:

typescript
1// Для радка
2default: () => ''        // Пусты радок
3
4// Для ліку
5default: () => 0         // Нуль
6
7// Для масіва
8default: () => []        // Пусты масіў
9
10// Для аб'екта
11default: () => ({})      // Пусты аб'ект
12
13// Для boolean
14default: () => false     // false

ЧАСТКА 3: Вузлы (Nodes) - Агенты

Што такое вузел?

Вузел (Node) - гэта функцыя, якая:

  1. Атрымлівае поўны стан
  2. Робіць нейкую працу (напрыклад, выклікае LLM)
  3. Вяртае частковае абнаўленне стану

Аналогія: Работнік на канвееры

text
1┌─────────────────────────────────────────────────────────────┐
2│                         КАНВЕЕР                             │
3├─────────────────────────────────────────────────────────────┤
4│                                                             │
5│   [Каробка] ──► [Работнік 1] ───────► [Работнік 2] ──────►  │
6│                    │                      │                 │
7│                    ▼                      ▼                 │
8│              Дадае дэталь А         Дадае дэталь Б          │
9│                                                             │
10└─────────────────────────────────────────────────────────────┘
11
12Кожны работнік:
131. Бачыць, што ўжо зроблена (стан)
142. Робіць сваю частку работы
153. Перадае далей з дапаўненнямі

Структура вузла ў кодзе:

typescript
1async function myNode(
2    state: ResearchStateType // ← УВАХОД: Поўны стан
3): Promise<Partial<ResearchStateType>> {
4    // ← ВЫХАД: Частковае абнаўленне
5    // 1. Чытаем даныя са стану
6    const data = state.someField;
7
8    // 2. Робім працу
9    const result = await doSomething(data);
10
11    // 3. Вяртаем абнаўленне (толькі тое, што змянілі)
12    return {
13        someField: result,
14    };
15}

Важна: Partial<State>

Вузел не абавязаны вяртаць увесь стан - толькі палі, якія змяніліся. LangGraph аб'яднае вашае частковае абнаўленне з існуючым станам з дапамогай reducer-аў, якія вы вызначылі.

typescript
1// Поўны стан мае 6 палёў:
2state = {
3    topic: "...",
4    research: "...",
5    draft: "...",
6    review: "...",
7    finalArticle: "...",
8    messages: [...],
9    iterationCount: 0
10}
11
12// Але вузел можа вярнуць толькі тое, што змяніў:
13return {
14    draft: "Новы чарнавік",           // Змянілі
15    messages: [new AIMessage("...")], // Дадалі
16    // Астатнія палі не згадваем - яны застануцца як былі
17}

Нашы вузлы падрабязна

Цяпер разгледзім чатыры вузлы ў нашай сістэме напісання артыкулаў. Кожны вузел мае канкрэтную ролю і перадае свае вынікі наступнаму праз агульны стан.

Вузел 1: Даследчык (researcherNode)

Даследчык - першы агент у нашым пайплайне. Ён бярэ тэму і генеруе даследчыя матэрыялы, якія будуць выкарыстоўвацца пісьменнікам.

typescript
1async function researcherNode(
2    state: ResearchStateType
3): Promise<Partial<ResearchStateType>> {
4    // ┌─────────────────────────────────────────────────────────────┐
5    // │ КРОК 1: Атрымліваем тэму для даследавання                  │
6    // └─────────────────────────────────────────────────────────────┘
7    const topic =
8        state.topic ||
9        String(state.messages[state.messages.length - 1]?.content) ||
10        '';
11    //            ▲               ▲
12    //            │               └── Альбо апошняе паведамленне
13    //            └── Спачатку спрабуем узяць topic
14
15    // ┌─────────────────────────────────────────────────────────────┐
16    // │ КРОК 2: Фармуем prompt для LLM                             │
17    // └─────────────────────────────────────────────────────────────┘
18    const prompt = `Ты эксперт-даследчык. Твая задача - сабраць ключавую інфармацыю.
19    Тэма: ${topic}
20    Правядзі кароткае даследаванне...`;
21
22    // ┌─────────────────────────────────────────────────────────────┐
23    // │ КРОК 3: Выклікаем LLM                                      │
24    // └─────────────────────────────────────────────────────────────┘
25    const response = await model.invoke([
26        { role: 'system', content: prompt }, // Інструкцыі для AI
27        { role: 'user', content: `Даследуй тэму: ${topic}` }, // Запыт
28    ]);
29
30    const research = String(response.content); // Вынік ад LLM
31
32    // ┌─────────────────────────────────────────────────────────────┐
33    // │ КРОК 4: Вяртаем абнаўленне стану                           │
34    // └─────────────────────────────────────────────────────────────┘
35    return {
36        research, // Запісваем вынік даследавання
37        messages: [
38            new AIMessage({ content: `[Даследаванне завершана]\n${research}` }),
39        ],
40        // ▲ Дадаем паведамленне ў гісторыю
41    };
42}

Што адбываецца:

text
1УВАХОД (state):                    ВЫХАД (абнаўленне):
2┌─────────────────────┐            ┌─────────────────────┐
3│ topic: "LangChain"  │            │ research: "LangCh.. │
4│ research: ""        │  ──────►   │ messages: [+1 msg]  │
5│ draft: ""           │            └─────────────────────┘
6│ messages: [1 msg]   │
7└─────────────────────┘
8
9                                    ▼ Пасля аб'яднання:
10                               ┌─────────────────────┐
11                               │ topic: "LangChain"  │
12                               │ research: "LangCh...│ ← абноўлена
13                               │ draft: ""           │
14                               │ messages: [2 msgs]  │ ← дадалося
15                               └─────────────────────┘

Вузел 2: Пісьменнік (writerNode)

Пісьменнік бярэ даследаванне і стварае чарнавік артыкула. Калі гэта перапрацоўка (пасля водгукаў рэцэнзента), ён таксама ўлічвае каментары да рэцэнзіі. Звярніце ўвагу, як iterationCount дапамагае адсочваць, колькі разоў артыкул быў перапісаны.

typescript
1async function writerNode(
2    state: ResearchStateType
3): Promise<Partial<ResearchStateType>> {
4    // ┌─────────────────────────────────────────────────────────────┐
5    // │ КРОК 1: Чытаем даследаванне і магчымую рэцэнзію            │
6    // └─────────────────────────────────────────────────────────────┘
7    const prompt = `Ты тэхнічны пісьменнік. На аснове даследавання напішы артыкул.
8
9Даследаванне:
10${state.research}
11
12${
13    state.review
14        ? `Папярэдняя рэцэнзія (улічы заўвагі):
15${state.review}`
16        : ''
17}
18`;
19
20    // ┌─────────────────────────────────────────────────────────────┐
21    // │ КРОК 2: Выклікаем LLM                                       │
22    // └─────────────────────────────────────────────────────────────┘
23    const response = await model.invoke([
24        { role: 'system', content: prompt },
25        { role: 'user', content: 'Напішы артыкул на аснове даследавання' },
26    ]);
27
28    const draft = String(response.content);
29
30    // ┌─────────────────────────────────────────────────────────────┐
31    // │ КРОК 3: Вяртаем абнаўленне                                  │
32    // └─────────────────────────────────────────────────────────────┘
33    return {
34        draft, // Чарнавік артыкула
35        iterationCount: state.iterationCount + 1, // Павялічваем лічыльнік
36        messages: [
37            new AIMessage({
38                content: `[Чарнавік ${state.iterationCount + 1}]`,
39            }),
40        ],
41    };
42}

Што адбываецца пры паўторным выкліку:

text
1ПЕРШЫ ВЫКЛІК:                      ДРУГІ ВЫКЛІК (пасля рэцэнзіі):
2┌─────────────────────┐            ┌─────────────────────┐
3│ research: "..."     │            │ research: "..."     │
4│ review: ""          │            │ review: "Дапрацуй...│ ← ёсць заўвагі!
5│ iterationCount: 0   │            │ iterationCount: 1   │
6└─────────────────────┘            └─────────────────────┘
7         │                                   │
8         ▼                                   ▼
9  Піша без заўваг                   Улічвае заўвагі
10         │                                   │
11         ▼                                   ▼
12┌─────────────────────┐            ┌─────────────────────┐
13│ draft: "Версія 1"   │            │ draft: "Версія 2"   │
14│ iterationCount: 1   │            │ iterationCount: 2   │
15└─────────────────────┘            └─────────────────────┘

Вузел 3: Рэцэнзент (reviewerNode)

Рэцэнзент ацэньвае чарнавік і вырашае, ці гатовы ён да публікацыі. Ключавы момант тут - вывад: калі рэцэнзія змяшчае "ЗАЦВЕРДЖАНА", артыкул ідзе на фіналізацыю. У адваротным выпадку ён вяртаецца да пісьменніка для паляпшэнняў. Менавіта гэта дазваляе ствараць цыкл у нашым графе.

typescript
1async function reviewerNode(state: ResearchStateType): Promise<Partial<ResearchStateType>> {
2
3    // ┌─────────────────────────────────────────────────────────────┐
4    // │ КРОК 1: Фармуем запыт на рэцэнзію                          │
5    // └─────────────────────────────────────────────────────────────┘
6    const prompt = `Ты строгі рэдактар. Ацані артыкул.
7
8Артыкул:
9${state.draft}
10
11Ацані па крытэрыях:
121. Дакладнасць інфармацыі
132. Структура і лагічнасць
143. Якасць мовы
154. Паўната раскрыцця тэмы
16
17Калі артыкул добры - скажы "ЗАЦВЕРДЖАНА".
18Калі трэба дапрацаваць - дай канкрэтныя рэкамендацыі.`;
19
20    // ┌─────────────────────────────────────────────────────────────┐
21    // │ КРОК 2: Атрымліваем рэцэнзію                                │
22    // └─────────────────────────────────────────────────────────────┘
23    const response = await model.invoke([...]);
24    const review = String(response.content);
25
26    // ┌─────────────────────────────────────────────────────────────┐
27    // │ КРОК 3: Вяртаем рэцэнзію                                    │
28    // └─────────────────────────────────────────────────────────────┘
29    return {
30        review,  // Рэцэнзія (або "ЗАЦВЕРДЖАНА" або заўвагі)
31        messages: [new AIMessage({ content: `[Рэцэнзія]\n${review}` })],
32    };
33}

Два магчымыя вынікі:

text
1ВАРЫЯНТ А: Артыкул добры           ВАРЫЯНТ Б: Трэба дапрацаваць
2┌─────────────────────────┐        ┌─────────────────────────┐
3│ review: "ЗАЦВЕРДЖАНА.   │        │ review: "Дапрацаваць:   │
4│ Артыкул выдатны!"       │        │ 1. Дадай прыклады       │
5│                         │        │ 2. Удакладні тэрміны"   │
6└─────────────────────────┘        └─────────────────────────┘
7         │                                   │
8         ▼                                   ▼
9    Ідзём да                           Вяртаемся да
10    finalizer                          writer

Вузел 4: Фіналізатар (finalizerNode)

Фіналізатар - найпрасцейшы вузел - ён проста капіюе зацверджаны чарнавік у поле finalArticle, пазначаючы канец нашага працоўнага працэсу. Ён выклікаецца, калі рэцэнзент зацвярджае артыкул.

typescript
1async function finalizerNode(
2    state: ResearchStateType
3): Promise<Partial<ResearchStateType>> {
4    // Просты вузел - капіюе чарнавік у фінальны артыкул
5    return {
6        finalArticle: state.draft, // Гатовы артыкул
7        messages: [new AIMessage({ content: `[ГАТОВА]\n\n${state.draft}` })],
8    };
9}

Што адбываецца:

text
1УВАХОД:                            ВЫХАД:
2┌─────────────────────┐            ┌─────────────────────┐
3│ draft: "Гатовы..."  │ ──────►    │ finalArticle:       │
4│ finalArticle: ""    │            │   "Гатовы..."       │
5└─────────────────────┘            └─────────────────────┘

ЧАСТКА 4: Пераходы (Edges)

Што такое пераход?

Пераход (Edge) - гэта правіла, якое кажа: "Пасля гэтага вузла выконваецца той вузел".

Аналогія: Стрэлкі на схеме

text
1Рэцэпт пічы:
2
3    [Зрабіць цеста] ─────► [Дадаць соус] ─────► [Дадаць сыр] ─────► [Выпекчы]
4           │                     │                    │                 │
5           ▼                     ▼                    ▼                 ▼
6       ПЕРАХОД              ПЕРАХОД              ПЕРАХОД           КАНЕЦ

Два тыпы пераходаў у LangGraph:

1. Простыя пераходы (addEdge)

Заўсёды ідзём у адзін і той жа вузел.

typescript
1workflow.addEdge('researcher', 'writer');
2//                    ▲            ▲
3//                    │            └── Куды ідзём
4//                    └── Адкуль ідзём
5
6// Значыць: Пасля researcher ЗАЎСЁДЫ ідзём да writer

Візуалізацыя:

text
1    [researcher] ───────────────► [writer]
2                   (заўсёды)
2. Умоўныя пераходы (addConditionalEdges)

Выбар наступнага вузла залежыць ад стану.

typescript
1workflow.addConditionalEdges(
2    'reviewer', // Адкуль ідзём
3    shouldContinue, // Функцыя, якая вырашае куды
4    {
5        writer: 'writer', // Калі функцыя верне 'writer' → ідзём у writer
6        finalizer: 'finalizer', // Калі функцыя верне 'finalizer' → ідзём у finalizer
7    }
8);

Візуалізацыя:

text
1                            ┌──────────► [writer]
23    [reviewer] ─────► [?] ──┤
45                            └──────────► [finalizer]
6
7    Функцыя shouldContinue вырашае, якую стрэлку абраць

Функцыя shouldContinue падрабязна

Гэта "мозг" нашага ўмоўнага пераходу. Ён аналізуе бягучы стан і вырашае, куды ісці далей. Функцыя павінна вярнуць радок, які адпавядае аднаму з ключоў у аб'екце супастаўлення, вызначаным у addConditionalEdges.

typescript
1function shouldContinue(state: ResearchStateType): 'writer' | 'finalizer' {
2    //                                              ▲
3    //                                              └── Вяртае адзін з гэтых радкоў
4
5    const review = state.review.toLowerCase();
6    const maxIterations = 3;
7
8    // ═══════════════════════════════════════════════════════════════
9    // УМОВА 1: Рэцэнзент сказаў "ЗАЦВЕРДЖАНА"
10    // ═══════════════════════════════════════════════════════════════
11    if (review.includes('зацверджана') || review.includes('approved')) {
12        console.log('Артыкул зацверджаны');
13        return 'finalizer'; // ← Ідзём завяршаць
14    }
15
16    // ═══════════════════════════════════════════════════════════════
17    // УМОВА 2: Занадта шмат спробаў (абарона ад бясконцага цыкла)
18    // ═══════════════════════════════════════════════════════════════
19    if (state.iterationCount >= maxIterations) {
20        console.log('Дасягнуты максімум ітэрацый');
21        return 'finalizer'; // ← Прымусова завяршаем
22    }
23
24    // ═══════════════════════════════════════════════════════════════
25    // ІНАКШ: Патрэбна дапрацоўка
26    // ═══════════════════════════════════════════════════════════════
27    console.log('Патрабуецца дапрацоўка');
28    return 'writer'; // ← Вяртаемся да пісьменніка
29}

Блок-схема рашэння:

text
1                         ┌───────────────────┐
2                         │  shouldContinue   │
3                         │    (функцыя)      │
4                         └─────────┬─────────┘
567                    ┌──────────────────────────────┐
8                    │ Ці ёсць "зацверджана"        │
9                    │ у рэцэнзіі?                  │
10                    └──────────────┬───────────────┘
1112                      ┌────────────┴────────────┐
13                      │                         │
14                     ТАК                       НЕ
15                      │                         │
16                      ▼                         ▼
17               ┌────────────┐      ┌──────────────────────────┐
18               │  return    │      │ Ці iterationCount >= 3?  │
19               │'finalizer' │      └──────────────┬───────────┘
20               │            │                     │
21               └────────────┘        ┌────────────┴────────────┐
22                                     │                         │
23                                    ТАК                       НЕ
24                                     │                         │
25                                     ▼                         ▼
26                              ┌────────────┐            ┌────────────┐
27                              │  return    │            │  return    │
28                              │'finalizer' │            │  'writer'  │
29                              │            │            │            │
30                              └────────────┘            └────────────┘

Як будуецца граф

Цяпер давайце злучым усё разам! Пабудова графа ў LangGraph ідзе па простым шаблоне: стварыць граф, дадаць вузлы, злучыць іх пераходамі і скампіляваць.

Паслядоўнасць стварэння:

typescript
1// ═══════════════════════════════════════════════════════════════
2// КРОК 1: Ствараем StateGraph з нашым станам
3// ═══════════════════════════════════════════════════════════════
4const workflow = new StateGraph(ResearchState)
5
6    // ═══════════════════════════════════════════════════════════
7    // КРОК 2: Дадаем вузлы (рэгіструем функцыі)
8    // ═══════════════════════════════════════════════════════════
9    .addNode('researcher', researcherNode) // Імя 'researcher' → функцыя
10    .addNode('writer', writerNode) // Імя 'writer' → функцыя
11    .addNode('reviewer', reviewerNode) // Імя 'reviewer' → функцыя
12    .addNode('finalizer', finalizerNode) // Імя 'finalizer' → функцыя
13
14    // ═══════════════════════════════════════════════════════════
15    // КРОК 3: Дадаем простыя пераходы
16    // ═══════════════════════════════════════════════════════════
17    .addEdge('__start__', 'researcher') // Пачатак → Даследчык
18    .addEdge('researcher', 'writer') // Даследчык → Пісьменнік
19    .addEdge('writer', 'reviewer') // Пісьменнік → Рэцэнзент
20
21    // ═══════════════════════════════════════════════════════════
22    // КРОК 4: Дадаем умоўны пераход
23    // ═══════════════════════════════════════════════════════════
24    .addConditionalEdges('reviewer', shouldContinue, {
25        writer: 'writer', // Калі 'writer' → назад да пісьменніка
26        finalizer: 'finalizer', // Калі 'finalizer' → да фіналізатара
27    })
28
29    // ═══════════════════════════════════════════════════════════
30    // КРОК 5: Дадаем канчатковы пераход
31    // ═══════════════════════════════════════════════════════════
32    .addEdge('finalizer', '__end__'); // Фіналізатар → Канец

Спецыяльныя вузлы:

text
1┌─────────────────────────────────────────────────────────────┐
2│  '__start__'  │  Віртуальны пачатковы вузел                │
3│               │  LangGraph аўтаматычна пачынае з яго        │
4├───────────────┼─────────────────────────────────────────────┤
5│  '__end__'    │  Віртуальны канчатковы вузел               │
6│               │  Калі дайшлі да яго - граф завяршыўся       │
7└─────────────────────────────────────────────────────────────┘

ЧАСТКА 5: Кампіляцыя і запуск

Мы вызначылі наш стан, вузлы і пераходы. Цяпер час ператварыць гэты чарцёж у працуючае прыкладанне!

Што такое compile()?

compile() - гэта працэс пераўтварэння апісання графа ў выканальную праграму. Пакуль вы не выклічаце compile(), у вас ёсць толькі апісанне таго, што вы хочаце пабудаваць - а не рэальна працуючая сістэма.

typescript
1// Апісанне графа (blueprint)
2const workflow = new StateGraph(ResearchState)
3    .addNode(...)
4    .addEdge(...);
5
6// Кампіляцыя ў выканальную праграму
7const app = workflow.compile();
8//    ▲
9//    └── Цяпер гэта можна запускаць!

Аналогія: Рэцэпт vs. Гатовая страва

text
1workflow (апісанне)              app (скампіляваная праграма)
2────────────────────            ──────────────────────────────
3Рэцэпт на паперы                 Гатовая піца
4   - Як рабіць цеста                (можна есці)
5   - Што дадаваць
6   - Як выпякаць
7
8Нельга есці!                     Можна есці!

Checkpointer (MemorySaver)

Што гэта такое?

Checkpointer - гэта механізм для захавання стану пасля кожнага кроку.

typescript
1import { MemorySaver } from '@langchain/langgraph';
2
3const checkpointer = new MemorySaver();
4
5const app = workflow.compile({
6    checkpointer, // ← Дадаем checkpointer
7});

Навошта гэта патрэбна?

text
1БЕЗ CHECKPOINTER:
2═══════════════════════════════════════════════════════════════
3
4    Запуск 1:   START → researcher → writer → ... → END
5
6    Запуск 2:   START → researcher → ...  (усё з пачатку!)
7
8    Немагчыма працягнуць з месца спынення
9    Немагчыма праглядзець гісторыю
10
11
12З CHECKPOINTER:
13═══════════════════════════════════════════════════════════════
14
15    Запуск 1:   START → researcher → [ЗАХАВАНА]
1617                                   thread_id: "chat-123"
18
19    Запуск 2:   [АДНАЎЛЕННЕ] → writer → reviewer → ...
2021                thread_id: "chat-123"
22
23    Можна працягнуць з месца спынення
24    Можна праглядзець гісторыю
25    Можна мець некалькі незалежных "размоў"

Thread ID - ідэнтыфікатар "трэда"

typescript
1const config = {
2    configurable: {
3        thread_id: 'article-1', // Унікальны ID для гэтай "размовы"
4    },
5};
6
7// Кожны thread_id - гэта асобная гісторыя
8// 'article-1' - пра адзін артыкул
9// 'article-2' - пра іншы артыкул
10// Яны не перасякаюцца!

Запуск графа

Нарэшце! Давайце запусцім наш граф. Функцыя invoke() прымае пачатковыя значэнні стану і канфігурацыю, а затым выконвае ўвесь граф ад пачатку да канца.

Функцыя invoke()

typescript
1const result = await app.invoke(
2    // Пачатковыя даныя для стану
3    {
4        topic: 'Перавагі LangChain',
5        messages: [new HumanMessage('Перавагі LangChain')],
6    },
7    // Канфігурацыя
8    {
9        configurable: {
10            thread_id: 'article-1',
11        },
12    }
13);

Што адбываецца пры invoke():

text
1┌─────────────────────────────────────────────────────────────────┐
2│                         invoke()                                 │
3└───────────────────────────────┬─────────────────────────────────┘
456┌─────────────────────────────────────────────────────────────────┐
7│ 1. ІНІЦЫЯЛІЗАЦЫЯ СТАНУ                                          │
8│    state = {                                                     │
9│        topic: "Перавагі LangChain",                             │
10│        messages: [HumanMessage],                                 │
11│        research: "",  ← default                                  │
12│        draft: "",     ← default                                  │
13│        review: "",    ← default                                  │
14│        finalArticle: "", ← default                               │
15│        iterationCount: 0, ← default                              │
16│    }                                                             │
17└───────────────────────────────┬─────────────────────────────────┘
181920┌─────────────────────────────────────────────────────────────────┐
21│ 2. ПАЧАТАК: __start__ → researcher                              │
22│    Выконваем researcherNode(state)                              │
23│    → Атрымліваем абнаўленне {research: "...", messages: [...]}  │
24│    → Аб'ядноўваем са станам праз reducers                       │
25│    Захоўваем checkpoint                                          │
26└───────────────────────────────┬─────────────────────────────────┘
272829┌─────────────────────────────────────────────────────────────────┐
30│ 3. ПЕРАХОД: researcher → writer                                 │
31│    Выконваем writerNode(state)                                  │
32│    → Атрымліваем абнаўленне {draft: "...", iterationCount: 1}   │
33│    → Аб'ядноўваем са станам                                     │
34│    Захоўваем checkpoint                                         │
35└───────────────────────────────┬─────────────────────────────────┘
363738┌─────────────────────────────────────────────────────────────────┐
39│ 4. ПЕРАХОД: writer → reviewer                                   │
40│    Выконваем reviewerNode(state)                                │
41│    → Атрымліваем абнаўленне {review: "..."}                     │
42│    → Аб'ядноўваем са станам                                     │
43│    Захоўваем checkpoint                                         │
44└───────────────────────────────┬─────────────────────────────────┘
454647┌─────────────────────────────────────────────────────────────────┐
48│ 5. УМОЎНЫ ПЕРАХОД: shouldContinue(state)                        │
49│    → Вяртае 'writer' або 'finalizer'                            │
50│    → Калі 'writer' - вяртаемся да кроку 3                       │
51│    → Калі 'finalizer' - ідзём далей                             │
52└───────────────────────────────┬─────────────────────────────────┘
53                                │ (калі 'finalizer')
5455┌─────────────────────────────────────────────────────────────────┐
56│ 6. ПЕРАХОД: reviewer → finalizer                                │
57│    Выконваем finalizerNode(state)                               │
58│    → Атрымліваем абнаўленне {finalArticle: "..."}               │
59│    → Аб'ядноўваем са станам                                     │
60│    Захоўваем checkpoint                                         │
61└───────────────────────────────┬─────────────────────────────────┘
626364┌─────────────────────────────────────────────────────────────────┐
65│ 7. КАНЕЦ: finalizer → __end__                                   │
66│    Граф завяршыўся                                              │
67│    Вяртаем фінальны стан                                        │
68└───────────────────────────────┬─────────────────────────────────┘
697071                        return state (поўны)

ЧАСТКА 6: FAQ - Частыя пытанні

Чаму reducer для messages дадае, а для topic замяняе?

Паведамленні - гэта гісторыя. Мы хочам захаваць усе паведамленні за ўвесь працэс.

Topic - гэта бягучая тэма. Калі тэма змянілася - старая не патрэбна.

Што будзе, калі я не ўкажу reducer?

LangGraph выкарыстае паводзіны па змаўчанні - замена (як для topic).

Нашто патрэбен iterationCount?

Каб абараніцца ад бясконцага цыкла. Калі рэцэнзент ніколі не скажа "зацверджана", праграма будзе бясконца круціцца паміж writer і reviewer.

Ці можа адзін вузел выклікаць іншы напрамую?

Не. Вузлы не ведаюць адзін пра аднаго. Яны толькі чытаюць/пішуць стан. LangGraph сам вырашае, хто выконваецца наступным, на аснове пераходаў.

Што такое start і end?

Гэта спецыяльныя віртуальныя вузлы:

  • __start__ - адкуль пачынаецца граф
  • __end__ - дзе граф завяршаецца

Яны не выконваюць код - толькі пазначаюць межы.

Ці можна мець некалькі канчатковых вузлоў?

Так! Напрыклад:

typescript
1.addEdge('success', '__end__')
2.addEdge('error', '__end__')

Выснова

Віншуем! Вы вывучылі асноўныя канцэпцыі LangGraph. Давайце падвядзём вынікі таго, што мы разгледзелі:

КанцэпцыяШто робіць
State + AnnotationВызначае структуру даных, якія перадаюцца паміж агентамі
ReducerВызначае, як аб'ядноўваць новыя даныя з існуючымі
Nodes (Вузлы)Функцыі, якія апрацоўваюць стан
Edges (Пераходы)Правілы, якія вызначаюць парадак выканання
Conditional EdgesДынамічны выбар наступнага вузла
CheckpointerЗахаванне стану для працягу пазней

Што далей?

Цяпер, калі вы разумееце асновы, вы можаце:

  1. Пабудаваць уласную агентную сістэму - Пачніце з простага графа з двух вузлоў і паступова дадавайце складанасць
  2. Эксперыментаваць з рознымі патокамі - Паспрабуйце ствараць графы з некалькімі ўмоўнымі галінамі
  3. Дадаць персістэнтнасць - Выкарыстоўвайце MemorySaver або checkpointer-ы на базе дадзеных для прадакшна
  4. Даследаваць прасунутыя магчымасці - Вывучыце падграфы, паралельнае выкананне і патэрны з удзелам чалавека

Ключавыя высновы

  • Думайце графамі: Разбівайце ваш AI-працоўны працэс на дыскрэтныя крокі (вузлы), злучаныя правіламі (пераходамі)
  • Стан - гэта ўсё: Уся камунікацыя паміж вузламі адбываецца праз агульны стан
  • Reducer-ы важныя: Выбірайце правільны reducer для кожнага поля - дадаванне для гісторыі, замена для бягучых значэнняў
  • Цыклы дазваляюць ітэрацыі: У адрозненне ад простых ланцужкоў, графы могуць вяртацца назад для дапрацоўкі

Прыклад з напісаннем артыкула, які мы пабудавалі, дэманструе рэальны патэрн: даследаванне → напісанне → рэцэнзаванне → (паўтарыць пры неабходнасці) → фіналізацыя. Гэты ж патэрн прымяняецца да многіх AI-прыкладанняў: рэцэнзаванне кода, мадэрацыя кантэнту, шматкрокавае разважанне і многае іншае.

Паспяховага кодзінгу! 🚀

LangChain
LangGraph
AI
tools
Admin, 2025-11-26

farmer

Вайб-кодынг - гэта не «магія ў вакууме», а свядомая тэхніка хуткай распрацоўкі з надзейным каркасам. За апошнія месяцы я прайшоў шлях ад bolt.new да Copilot, Claude, Cursor і Google AI Studio: больш за тысячу промптаў, дзясяткі ітэрацый, шмат урокаў. Ніжэй - не зборнік банальнасцяў, а адшліфаваны набор прынцыпаў, інструментаў і шаблонаў, якія сапраўды эканомяць час, грошы і нервы, калі колькасць коду расце.

Уводзіны: што рабіць, каб не падгарала дупа.

Ідэя простая: мы рухаемся маленькімі, але дакладнымі крокамі, замацоўваем вынікі ў git, просім ШІ рабіць лакальныя патчы «diff-only», а не перапісаць усё навокал, і падтрымліваем дызайн-сістэму з першых радкоў. Замест «агента, які ўсё зробіць за вас» - сумесная праца з памочнікам, якому вы ясна фармулюеце задачу і межы. Так мы пазбягаем «галюцынацый», дарэмнай перабудовы і не губляем кантроль над токенамі.

1. План фічы і спецыфікацыя (уваходы/выхады/памылкі)

Перад любым кодам - кароткі, але канкрэтны план:

  • 1–2 сказы пра тое што робім: «Карыстальнік робіць X і атрымлівае Y» (прыклад: «Стварае і дзяліцца спісамі задач за 30 секунд без рэгістрацыі»).
  • 3–7 асноўных flow (сцэнарыяў) і экранаў: напрыклад «Sign in -> Dashboard -> Create item». Без дэталёвай разметкі — проста назвы і парадак.
  • Каркас у межах файлаў: «маршруты -> модулі -> паўторна выкарыстоўваемыя кампаненты».
  • Чорны спіс «не вынаходзіць нанова»: кнопкі, інпуты, алерты, хэлперы, схемы валідацыі.

Далей — спецыфікацыя фічы: уваходы, выхады, памылкі, абмежаванні, крытэрыі done. Усе наступныя промпты — строга ў межах гэтай спецыфікацыі.

2. Сплануй UI/UX наперад (да кода)

Перад кодам — візуалізуй і эксперыментуй з layout. Выкарыстоўвай інструменты накшталт v0, каб хутка пабачыць, як будуць выглядаць экраны, і ўнесці карэкціроўкі.

Кансістэнтнасць - база. Вызнач дызайн-сістэму на старце і трымайся яе:

  • Адзін базавы файл: breakpoints, spacing scale, grid, тыпаграфіка.
  • Стварыце паўторна выкарыстоўваемыя кампаненты адразу: Button, Input, Select, Alert, Loader, Empty/Error states ці спасылайцесь на бібліятэку.
  • Праверка пасля кожнай ітэрацыі: ці не «распаўзліся» памеры і шрыфты.
  • У промптах: «Выкарыстай існуючыя ButtonX, InputY. Новыя стылі не ўводзіць без патрэбы».

Гэта зэканоміць вам тоны часу і выратуе ад хаатычных рэфактарынгаў пазней, ну і не будзе паліць токены.

Рэсурсы: 21st.dev — гатовыя UI-патэрны з AI-промптамі, проста капіруй-устаўляй.

3. Папулярны стэк, які дапамагае (не перашкаджае)

Чым шырэй супольнасць і дакументацыя, тым дакладней ШІ трапляе ў API і патэрны. Практычныя звязкі:

  • Next.js - фронт + лёгкі API-слой.
  • Tailwind CSS - хуткія кансістэнтныя стылі без «CSS-кашы» на старце.
  • Fastify + MongoDB або Supabase - мінімум рытуалаў, шмат гатовых рэцэптаў.

Галоўнае - не экзотыка, а надзейныя адказы мадэлі.

4. Git-дысцыпліна: рабіце каміты як мага часцей

Ваш лепшы страхавы поліс:

  • Адна фіча - асобная галіна.
  • Маленькія працоўныя кавалкі - частыя каміты з яснымі паведамленнямі.
  • Перад рызыкоўнымі генерацыямі/рэарганізацыямі - commit або branch.

Так не давядзецца «адкручваць» назад па 700 радкоў, калі ШІ «аптымізаваў» не там.

5. Дробім складанае: Спецыфікацыя -> Каркас -> Логіка -> Тэсты

Не трэба даваць вялікія промпты накшталт «зрабі ўвесь модуль цалкам». ШІ пачне галюцынаваць і выдаваць лайно. Раздзяляйце любую складаную фічу на этапы (фазы): замест аднаго вялікага запыту - 3–5 малых або больш, калі трэба.

Паслядоўны канвеер:

  1. Маршруты і каркас файлаў.
  2. Базавая разметка і кампаненты.
  3. Логіка/валідацыя/станы.
  4. Тэсты, бяспека, аптымізацыя.

ШІ працуе найбольш стабільна, калі граніцы задачы вузкія і выразныя.

6. Канкрэтныя промпты з межамі (diff-only)

Garbage in, garbage out. Даваць дрэнныя промпты = атрымаць такое ж лайно. Промпты павінны быць настолькі падрабязнымі, наколькі магчыма — не пакідайце месца для здагадак ШІ. Калі не атрымліваецца, запусці Gemini 2.5 Pro ў Google AI Studio і папрасі яго зрабіць дэталёвы промпт на аснове тваёй ідэі (Чат GPT таксама добра выконвае такую задачу).

Канчатковае фармуляванне — ваш рычаг кіравання. Мінімальны шаблон:

«Адрэфактар ProfileForm.tsx: вынесі валідацыю ў асобны хук, API не чапай, захавай імёны пропсаў і публічны API, выкарыстоўвай InputX і ButtonY. Не змяняй нічога па-за пералічаным.»

Дадайце прыклад фрагмента кода/інтэрфейса — мадэль хутчэй «зловіць» ідэю. Ахоўная фраза «Не змяняй нічога, пра што не прасіў» — абавязковая.

7. Кантэкст чата і reset: калі адкрываць новы трэд (чат)

Вялікі чат = дрэйф патэрнаў, страта кантэкста. Перазапуск - гэта не параза, а гігіена:

  • Кароткае ўвядзенне для новага акна: «Фіча X, файлы A/B/C, чапаць дазволена толькі …»
  • Памятайце: занадта шмат кантэксту так жа шкодна, як і яго недахоп - пакідайце толькі істотнае.

8. Эканомія токенаў: асцярожна з бюджэтам

  • Дробныя патчы замест гіганцкіх «перапісаў».
  • Diff-first: «пакажы план патча + diff, потым прыменім» .
  • Пераключэнне мадэляў: простыя рашэнні - Auto/меншая мадэль; агляды і бяспека - Gemini 2.5 Pro / Sonnet.

9. Кода-гігіена: ESLint, тыпы, мінімальныя тэсты

  • Маленькія чыстыя функцыі, без «лянівых» пабочных эфектаў.
  • ESLint + аўтафіксы; выдаленне мёртвага кода на кожным кроку.
  • Мінімум юніт-тэстаў: «шчаслівы шлях» + пагранічныя выпадкі (null/пуста/невядомы тып).
  • TypeScript са строгімі правіламі - менш каментароў, больш гарантый.

Перад камітам: прыбярыце лішнія логі і «часовыя» каментары - яны з’ядаюць увагу падчас ітэрацый і ядуць токены.

10. Бяспека: кароткі, але сур'ёзны чэкліст

(на самой справе - проста відавочная база, але ў працы з ШІ - трэба заўседы кантраляваць)

Тут заўсёды будуць недахопы (у кожнага), але гэтыя правілы выратуюць ад самых жорсткіх:

Давяраць кліенцкім даным: прыняць form/URL уводы напрамую.
-> Fix: Заўсёды валідуй і санітызуй на серверы; экрануй вывад.

Сакрэты ў фронтэндзе: API-ключы/credentials у React/Next.js кліенцкім кодзе.
-> Fix: Трымай сакрэты толькі на серверы (env vars, .env у .gitignore).

Слабая аўтарызацыя: правяраць толькі "ці залагінены", а не "ці дазволена гэта".
-> Fix: Сервер павінен правяраць дазволы для кожнага дзеяння і рэсурсу.

Лішак у памылках: паказваць stack trace / памылкі базы карыстальніку.
-> Fix: Агульнае паведамленне карыстальніку, падрабязныя логі — распрацоўшчыку.

IDOR і ўласнасць: дазваляць карыстальніку X рэдагаваць даныя карыстальніка Y праз ID.
-> Fix: Сервер павінен пацвердзіць, што бягучы карыстальнік валодае гэтым ID.

Ігнараванне DB-бяспекі: абыходзіць такія рэчы, як RLS (Row Level Security).
-> Fix: Вызнач правілы доступу да даных наўпрост у базе (RLS).

Незахаваныя API: адсутнасць rate limit; незашыфраваныя чуллівыя даныя.
-> Fix: Rate limit праз middleware; шыфруй даныя ў спакоі; заўсёды HTTPS.

11. Ітэратыўны агляд (Gemini/Claude): праблема -> рызыка -> патч

Гэта выкарыстоўваць не зусім проста праз тое што капіраваць усе файлы цяжка, але нават просты аналіз з чату можа выявіць значныя недахопы, таму перыядычна робім гэта.

Пасля пабудовы фічы скапіруй увесь код у Gemini 2.5 Pro (у Google AI Studio) ці проста запусці якія вялікія мадэлі для праверкі коду і фіч — яны маюць вялікае кантэкстнае вакно і выдатна знаходзяць уразлівасці і дрэнныя патэрны.

Як працаваць:

  1. Скажы Gemini: «Ты эксперт па бяспецы. Знайдзі ўразлівасці.» / «Ты эксперт па [твой стэк]. Знайдзі праблемы прадукцыйнасці і дрэнныя патэрны.»
  2. Gemini вяртае спіс праблем. Скапіруй іх у Claude ў Cursor і скажы выправіць.
  3. Пасля выпраўлення — зноў Gemini, пакуль ён не скажа "усё ОК".

Мэты аналізу: бяспека, прадукцыйнасць, дубляжы, лішнія залежнасці.

Фармат адказу, які працуе:

  1. Праблема;
  2. Чаму гэта праблема;
  3. Рызыка;
  4. Канкрэтны патч/крокі.

Далей — лакальныя diff-патчы, невялікія тэсты, паўторны прагляд.

12. "Упартыя" багі: фіксім без панікі

Калі пасля 2–3 заходаў усё яшчэ «не туды»:

  1. Папрасіце мадэль назваць топ-падазраваных па ланцужку залежнасцяў.
  2. Дадайце логі ў вузкія месцы, дадайце факты (stack, payload, межы).
  3. Пры неабходнасці - адкат да апошняга паспяховага каміту і дробныя крокі наперад. Часам толькі так і вырашаюцца праблемы. Ну ці самаму рукамі выпраўляць, але ж мы не за гэтым прыйшлі да вайбкодынгу.

13. Правіла межаў: «Не чапай, калі не прасілі»

ШІ любіць «падчысціць», калі бачыць магчымасць. Абмежаванні - заключная фраза ў кожным промпце: «Нічога не змяняй па-за пералічаным». Пасля некалькіх ітэрацый мадэль пачынае паважаць межы.

14. Repo-інструкцыі і «Агульныя памылкі ШІ» як код

  • Вядзіце ai_common_mistakes.md: ШІ любіць пераносіць валідацыю ў UI; змяняе назвы пропсаў; выдаляе патрэбныя імпарты - усё сюды.
  • Папка instructions/ з markdown-прыкладамі, шаблонамі промптаў, «Cursor Rules», кароткімі best practices.
  • У новай фічы дадавайце спасылку на файл памылак - эканоміць токены і час.

15. Інструменты і патэрны, якія працу паскараюць без мітусні

Інструменты:

  • Storybook - ізаляваны UI і дакументаванне патэрнаў.
  • Playwright / Vitest - хуткія E2E/юніт-тэсты; добра спалучаюцца з diff-патчамі.
  • CodeSandbox / StackBlitz - імгненныя пясочніцы для PoC.
  • Sourcegraph Cody - глыбокі пошук + кантэкстныя патчы.
  • Continue / Aider / Windsurf / Codeium - лёгкія асістэнты для «застряганняў».
  • Tabby / лакальныя LLM - танная генерацыя для шаблоннага коду.
  • Perplexity / Phind - хуткае тэхнічнае даследаванне і параўнанне падыходаў.
  • MCP (Model Context Protocol) - стандартызаваны доступ да файлаў/камандаў без «балбатні» ў промпце.
  • Commit message генератары (глядзіце таксама CommitGPT) - эканомяць час, але чытайце перад пушам.
  • ESLint з аўтафіксам - машынная гігіена «на ўваходзе».

Патэрны працы:

  • Triple Pass Review: структура -> логіка/паток даных -> краявыя выпадкі/бяспека.
  • Interface Freeze: замарозьце публічны API/параметры перад глыбокімі генерацыямі (рэфактарынгам).
  • Context Ledger: кароткія запісы па фічах (файлы, рашэнні, outstanding TODO) - лёгка перанесці ў новы чат.
  • Session Reset Cadence: рэгулярнае абнуленне доўгіх сесій.
  • Red Team Self-Check: асобны праход на ін’екцыі, IDOR, гонкі.

16. Cursor Rules, інструкцыі і «не баяцца вяртацца назад»

  • Cursor Rules - выдатная адпраўная кропка: зафіксуйце стэк, патэрны, забароны, анты-прыёмы.
  • Папка з інструкцыямі: прыклады кампанентаў, кароткія рэцэпты для тыпавых задач (замена «гарачай памяці» чата).
  • Калі мадэль збілася: вяртайцеся на крок назад, удакладняйце промпт і кантэкст - працягваць «па інэрцыі» даражэй.

17. Прадухіленне непажаданых змен ад ШІ — каротка

Паўтараем правіла з п.13: «Не дадавай/не выдаляй/не пераймяноўвай тое, пра што не прасіў». Ясныя межы лепшыя за эмацыйныя фразы — і працуюць стабільней.

18. Міні-чэкліст перад камітам

  • Функцыя ўпісаная ў існуючыя патэрны і кампаненты.
  • Тыпы строгія, без any; базавыя тэсты і логі прысутнічаюць.
  • Бяспека: сакрэты на сервэры; правы і валідацыя правераныя.
  • UI кансістэнтны: водступы, станы, назвы.
  • Паведамленне каміту кароткае і змястоўнае.

Карысныя знешнія рэсурсы

Ніжэй - толькі знешнія, публічныя крыніцы (сэрвісы і інструменты), якія даюць практычную вартасць пры «вайб»-падыходзе.

bolt.new
Што: онлайн-асяроддзе хуткага стварэння каркаса (Full‑stack / frontend) з генерацыяй пачатковага коду праз ШІ.
Навошта: імгненны MVP / протатып да таго, як укладвацца ў структуру асноўнага рэпазіторыю.
Калі: у фазе праверкі ідэі або пошуку агульнай формы без тонкай архітэктуры.

GitHub Copilot
Што: інструмент аўтадапаўнення і inline-падказак у рэдактара (VS Code, JetBrains).
Навошта: паскорыць шаблонны код (канфігурацыі, дапаможныя функцыі, невялікія React‑кампаненты), знізіць колькасць механічнага набору.
Калі: калі патрэбны хуткі «скетч» або дапаўненне радкоў, а не глыбокая шматфайлавая генерацыя логікі. (Але зараз ужо +- добра працуе і тут)

Claude Sonnet / мадэлі Anthropic
Што: мадэлі з моцным разуменнем кантэксту і больш менш дакладным вывадам.
Навошта: агляд вялікіх кавалкаў коду, прапановы па структуры, бяспецы, стылі.
Калі: перад рэфактарынгам, для пошуку дубляў або патэнцыйных уразлівасцяў.

Cursor
Што: IDE (форк VS Code) з глыбокай інтэграцыяй LLM (чат + генерацыя патчаў + «Rules»).
Навошта: кіраваныя промпты, лакальныя diff‑патчы, хуткія ітэрацыі без ручнога капіравання.
Калі: у асноўнай распрацоўцы, калі патрэбна шмат малых структурных змяненняў.

cursor.directory
Што: каталог гатовых Cursor Rules і промпт-шаблонаў.
Навошта: стартавы набор правілаў (стыль, архітэктура, ахоўныя абмежаванні) замест ручнога выпрацоўвання.
Калі: на этапе наладжвання «правілаў гульні» ў праекце.

Google AI Studio (Gemini 2.5 Pro)
Што: інтэрфейс да мадэляў з вялікім кантэкстным акном.
Навошта: комплексныя праверкі - бяспека, прадукцыйнасць, дублі, залежнасці; падсумаванне перад перабудовай.
Калі: калі код-база ўжо значная і патрэбны «стратэгічны прагляд».

21st.dev
Што: калекцыя UI-патэрнаў з прыкладнымі промптамі.
Навошта: уніфікаваць стылі і структуру кампанентаў без прыдумвання «з нуля».
Калі: перад маштабаваннем фронтэнду або стандартызацыяй форм / спісаў.

Sourcegraph Cody
Што: інтэлектуальны пошук па вялікіх рэпазіторыях + генерацыя патчаў.
Навошта: знайсці ўсе ўжыванні функцыі / залежнасці, пабудаваць карціну сувязяў перад зменамі.
Калі: перад глыбокім рэфактарынгам або выдаленнем модуля.

CodeSandbox
Што: хмарныя пясочніцы для імгненнага запуску прыкладання без лакальнай інсталяцыі.
Навошта: праверыць бібліятэку, пратэставаць ідэю, паказаць канцэпт калегам.
Калі: ранняя валідацыя або ізаляваная дэманстрацыя.

Storybook
Што: ізаляванае асяроддзе для прагляду і тэставання UI-кампанентаў.
Навошта: гарантаваць кансістэнтнасць дызайн-сістэмы, візуальны кантроль станаў (loading/empty/error).
Калі: у момант вылучэння агульных кампанентаў або перад маштабаваннем фронтэнду.

Playwright
Што: інструмент для E2E-тэстаў (браузерныя сцэнары з высокай дакладнасцю).
Навошта: праверыць ключавыя карыстальніцкія патокі пасля аўтаматычных патчаў ад ШІ.
Калі: перад merge важных змен або выпуском версіі.

Vitest
Што: хуткі юніт/інтэграцыйны тэстар для экосістэмы Vite / сучаснага TS.
Навошта: пакрыць чыстыя функцыі і hooks, каб стабілізаваць рэфактарынг.
Калі: адразу пасля вылучэння невялікіх утыліт / логікі ў асобныя модулі.

Perplexity
Што: LLM-пашукавікі з абагульняючымі адказамі і спасылкамі.
Навошта: імгненна даведацца нюансы API, статус бібліятэк, параўнаць падыходы.
Калі: перад выбарам стэка або аптымізацыяй.

LangSmith
Што: інструменты ацэнкі якасці інтэграцый LLM і промптаў.
Навошта: аб’ектыўна меркаваць, ці паляпшаецца вынік ад вашых правілаў/карэкціровак.
Калі: калі колькасць промптаў і мадэляў > 1 і патрабуецца кіраванне якасцю.

Regex101
Што: онлайн-адладчык рэгулярных выразаў з тлумачэннямі.
Навошта: хутка правяраць і правільна будаваць правілы валідацыі / парсінгу.
Калі: перад уключэннем складанай валідацыі ў форму / API.

Як эфектыўна спалучаць:

  1. Ідэя -> bolt.new (прататып) -> перанос у Cursor.
  2. Структура -> Sourcegraph (залежнасці) -> Claude (заўвагі) -> лакальныя патчы.
  3. UI -> 21st.dev (патэрн) + Storybook (прагляд) + Tailwind (стылі).
  4. Бяспека -> OWASP (чэкліст) + Gemini (аўдыт) + Playwright (патокі).
  5. Чысціня -> ESLint (правілы) + TypeScript (строгія тыпы) + Vitest (тэсты).

Паступова ўводзьце рэсурсы - не ўсе адразу: гэта зніжае кагнітыўную нагрузку і павялічвае стабільнасць працэсу.

Заключэнне: хуткасць з каркасам

Вайб-кодынг - гэта не хаос і не «мэта сама па сабе». Гэта цыкл «бачанне -> маленькі крок -> праверка -> стабілізацыя». Чым лепш бачанне і патэрны, тым больш ШІ становіцца партнёрам, а не крыніцай сюрпрызаў і праблем. Памылкі будуць, але з гэтым наборам вы не згубіцеся - проста працягнеце ітэраваць без болю.

Дзякуй за ўвагу

Дзякуй, што дачыталі. Спадзяюся, матэрыял будзе для вас карысны. Калі спадабалася — падтрымайце наш праект і падзяліцеся з калегамі.

ЗЫ: Выява ў шапцы спецыяльна крыху ўпоратая.

Vibe
AI
Admin, 2025-11-07

head

Вітанкі!
Калі вы стаміліся ад ручнога рэдагавання бясконцых JSON-файлаў з перакладамі і хочаце, каб ваш AI-агент (Copilot, Cursor, Claude) рабіў гэта за вас — гэты артыкул для вас.

Сёння разгледзім Goman.live — інструмент, які ператварае руціну лакалізацыі ў магію. Разгледзім, навошта ён патрэбен, як ён эканоміць ваш час і чаму гэта must-have для сучаснага "вайбкодзера".


Што такое Goman.live і навошта ён вам?

Goman.live — гэта не проста чарговы перакладчык. Гэта разумны бэкэнд для кіравання кантэнтам вашага прыкладання.

Уявіце: вы пішаце код, а ўсе тэксты — кнопкі, памылкі, апісанні — аўтаматычна з'яўляюцца на ўсіх патрэбных мовах, улічваючы кантэкст і стыль вашага праекта. Без ручнога капіравання ў Google Translate, без памылак у ключах і без "зламаных" файлаў лакалізацыі.

Сэрвіс працуе ў двух рэжымах:

  1. Аўтапілот (праз MCP): Вы проста просіце свайго AI-агента ў IDE "дадаць кнопку", і ўсё адбываецца само.
  2. Цэнтр кіравання (Web Editor): Магутны інтэрфейс для ручной даводкі, праверкі якасці і кіравання складанымі кантэкстамі.

Каму гэта сапраўды патрэбна?

Goman.live ствараўся, каб прыбраць боль з працэсу распрацоўкі:

  • 🚀 Вайбкодзерам (AI-Native Developers): Вы прывыклі працаваць хутка. Пераключэнне кантэксту на рэдагаванне JSON забівае паток (flow). Goman дазваляе не выходзіць з IDE.
  • 👨‍💻 Распрацоўшчыкам Pet-праектаў і стартапаў: Хочаце запусціцца адразу на 10 мовах? З Goman гэта займае столькі ж часу, колькі і на адной.
  • 👩‍💼 Камандам: Адзіная крыніца праўды для ўсіх тэкстаў. Распрацоўшчык не чакае перакладчыка, перакладчык не ламае JSON.

MCP: Аўтаматызацыя лакалізацыі ў IDE

Гэта галоўная фішка. MCP (Model Context Protocol) дазваляе падключыць Goman наўпрост да вашага Copilot або Cursor.

🎬 Першае дэма (Крыху састарэла)

🎬 Дадаем гішпанскую мову

Як гэта выглядае на практыцы? Замест таго, каб адкрываць 5 файлаў (en.json, de.json, es.json...), шукаць патрэбны ключ і ўстаўляць тэкст, вы пішаце ў чаце IDE:

"Праскануй адкрыты файл і ствары пераклады для ўсіх тэкставых радкоў."

Або нават для цэлага модуля:

"Лакалізуй усе кампаненты ў папцы src/features/auth. Захоўвай ключы ў namespace auth."

Можна папрасіць лакалізаваць і ўвесь праект адразу, але для лепшага кантролю рэкамендуецца рабіць гэта па частках.

Што адбываецца пад капотам:

  1. Агент правярае, ці ёсць такі ключ (каб не было дубляў).
  2. Генеруе пераклады на ўсе падтрымліваемыя праектам мовы.
  3. Захоўвае іх у базу.
  4. Вы адразу можаце выкарыстоўваць t('actions.save') у кодзе.

Важна адзначыць: акрамя саміх перакладаў, сістэма захоўвае кантэкст для кожнага ключа (гэта працуе і праз MCP, і праз Рэдактар). Такім чынам, агент і вы заўсёды можаце ведаць, дзе выкарыстоўваецца канкрэтная лакалізацыя і што яна азначае.

Гэта эканоміць гадзіны руціннай працы і дазваляе вам засяродзіцца на логіцы прыкладання, а не на слоўніках.

Поўны набор інструментаў (MCP Tools)

MCP-сервер дае вашаму агенту поўны кантроль над працэсам лакалізацыі. Сэрвіс пакрывае ўвесь жыццёвы цыкл працы з тэкстамі:

1. Даследаванне праекта (Discovery)

  • get_active_languages: Першае, што робіць агент — правярае, якія мовы актыўныя ў праекце. Гэта гарантуе, што пераклады будуць створаны толькі для патрэбных лакаляў.
  • get_namespaces: Паказвае структуру праекта (спіс файлаў/прастор імёнаў), каб агент ведаў, куды менавіта захоўваць новыя тэксты (напрыклад, у common ці auth).

2. Пошук і Праверка (Search & Verification)

  • search_localizations: Магутны пошук па ключах і значэннях. Агент можа знайсці ўсе кнопкі са словам "Cancel" або праверыць, як перакладзена слова "Save" у іншых месцах, каб захаваць кансістэнтнасць.
  • get_localization_exists: Дакладная праверка канкрэтнага ключа. Дазваляе пазбегнуць дублявання і перазапісу існуючых важных тэкстаў.

3. Кіраванне кантэнтам (Management)

  • create_localization: Асноўны інструмент. Стварае або абнаўляе пераклады. Разумее кантэкст і можа дадаваць пераклады адразу на ўсе актыўныя мовы праекта адным запытам.
  • delete_localization: Дазваляе выдаляць састарэлыя або памылковыя ключы, падтрымліваючы чысціню ў праекце.

Гэты набор інструментаў ператварае вашага AI-агента ў паўнавартаснага лакалізатар-менеджара.

Гатовыя шаблоны (Prompts) для хуткага старту

Каб не траціць час на напісанне інструкцый для AI, у сістэме ўжо ёсць набор правераных промптаў для тыповых задач. Яны даступныя выключна праз MCP і гатовыя да выкарыстання вашым агентам:

  • init-project: Поўная налада лакалізацыі з нуля. Дапаможа выбраць структуру праекта, праскануе файлы і створыць першыя ключы.
  • localize-component: Проста ўстаўце код кампанента (React, Vue і інш.), і агент знойдзе ўсе тэксты, створыць ключы і нават пакажа, як змяніць код.
  • localize-folder: Тое ж самае, але для цэлых папак. Ідэальна для масавай лакалізацыі.
  • add-language: Хочаце дадаць польскую мову? Гэты промпт возьме ўсе існуючыя англійскія ключы і перакладзе іх на новую мову.
  • check-coverage: Аўдыт праекта. Пакажа, якія ключы прапушчаны ў якіх мовах (напрыклад, "у es не хапае 5 перакладаў").
  • localization-audit: Глыбокі аналіз. Знойдзе ключы, якія больш не выкарыстоўваюцца ў кодзе, і прапануе іх выдаліць.

Проста абярыце патрэбны шаблон, і сістэма сама падставіць аптымальныя налады для якаснага выніку.

Кіраванне кантэкстам і промптамі ў IDE

Гэта функцыя звязвае налады ў вэб-інтэрфейсе з працоўным асяроддзем распрацоўшчыка. У сістэме прадугледжаны Рэдактар Промптаў, які дазваляе ствараць спецыялізаваныя інструкцыі для AI-агентаў.

Гэта вырашае праблему "чыстага ліста", калі мадэлі трэба кожны раз тлумачыць кантэкст задачы.

Што дазваляе рабіць рэдактар: Галоўная функцыя — гэта стварэнне і рэдагаванне саміх промптаў. Менавіта праз іх вы кіруеце кантэкстам у вашай IDE або агенце. Вы адзін раз прапісваеце правілы гульні, і агент пачынае іх прытрымлівацца.

Важна адзначыць: гэта працуе не толькі для перакладаў. Вы можаце ствараць промпты для любых задач распрацоўкі — ад рэфактарынгу да напісання тэстаў.

Прыклады выкарыстання:

  • Для кодынгу: "Выкарыстоўвай стрэлачныя функцыі, пазбягай any, пішы каментары ў фармаце JSDoc і заўсёды пакрывай новы код тэстамі".
  • Для інтэрфейсу: Можна задаць строгае правіла: "Перакладай максімальна коратка, каб тэкст улазіў у кнопкі, выкарыстоўвай тэрміналогію Apple HIG".
  • Для маркетынгу: "Пішы эмацыйна, звяртайся да карыстальніка на 'ты', дадавай адпаведныя эмодзі".
  • Для тэхнічнай дакументацыі: "Захоўвай афіцыйны стыль, не перакладай спецыфічныя тэрміны (напрыклад, 'middleware', 'token'), фармулюй думкі дакладна і суха".

Карыстальнік проста выбірае патрэбны промпт са спісу ў Copilot або Cursor, і агент імгненна пераключаецца на патрэбны рэжым працы.


editor

Рэдактар: Поўны кантроль над якасцю

Калі MCP — гэта хуткасць, то вэб-рэдактар — гэта дакладнасць.

Тут вы можаце:

  • Бачыць поўную карціну: Усе мовы побач.
  • Рэдагаваць кантэкст: Дадаць апісанне для AI, каб ён разумеў, што "Home" — гэта старонка, а не будынак.
  • Выпраўляць нюансы: Калі AI крыху памыліўся са стылем, вы можаце хутка паправіць гэта ўручную або папрасіць перарабіць варыянт.

Гэта ідэальна для маркетынгавых тэкстаў, лендынгаў і важных паведамленняў, дзе кожнае слова мае значэнне.

prompt

Промпты: Ваш персанальны стыль

Чаму AI-пераклады часам выглядаюць "машыннымі"? Бо мадэль не ведае вашага кантэксту. У Goman.live вы ствараеце Промпты — гэта набор правілаў для вашага праекта.

Гэта замена састарэлым "гласарыям". Вы можаце сказаць мадэлі:

  • "Звяртайся да карыстальніка на 'ты'"
  • "Не перакладай назву брэнда 'SuperApp'"
  • "Выкарыстоўвай вясёлы, нефармальны тон"

AI-асістэнт для промптаў

Не ведаеце, як правільна напісаць промпт? Убудаваны AI-чат дапаможа сфармуляваць ідэальныя інструкцыі для мадэлі, каб вынік быў менавіта такім, як вы чакаеце.

versions

Захоўванне промптаў і версіяніраванне

Вы можаце захоўваць да чатырох (пакуль чатырох) версій аднаго промпта і пераключацца паміж імі ў адзін клік.
Гэта вельмі зручна, калі хочаце эксперыментаваць з фармулёўкамі або правіламі перакладу. Версіянірванне промптаў пры належным карчстанні можа дазволіць значна паменьшыць разход токенаў. Таксама гэта можа быць карысна пры тэсціраванні і пошуку найбольш падыходзячых промптаў - у сэрвісе дададзена сістэма тэсціравання промптаў - можна адразу запускаць запыты на выкананне і атрымліваць вынікі.

Сумесная праца

Калі вы працуеце не адны - проста дадайце email калегі.
Ён атрымае доступ да вашага праекта, і вы зможаце разам працаваць над лакалізацыямі і перакладамі. Абмежаванні толькі па тарыфным плане. Токены пры перакладзе бяруцца з уліковага запісу ўласніка - то бок таго, хто "пашарыў"


languages

Падтрымліваемыя мовы

Поўнага спісу моў у сэрвісе няма - і гэта добра.
Выкарыстоўваюцца мадэлі, якія ўмеюць працаваць з дзясяткамі і сотнямі моў, таму абмежаванняў фактычна няма.
Якасць перакладу залежыць ад самога тэксту, ад распаўсюджанасці мовы і ад таго, ці ёсць падобныя пераклады ў вашай базе.

Пераклады праз рэдактар часта атрымліваюцца лепшыя, чым праз звычайныя інструменты, бо ўлічваецца кантэкст і папярэднія вынікі.
А калі вы працуеце праз MCP, якасць залежыць ад мадэлі, якую выкарыстоўвае ваш агент - напрыклад, Claude, GPT ці інш.


mistakes

Кантроль якасці: Давярай, але правярай

AI — гэта магутны інструмент, але не ідэальны. Таму ў Goman.live убудаваны механізмы страхоўкі:

  1. Аўтаматычная сінтаксічная праверка: Сэрвіс сочыць, каб AI не зламаў зменныя (напрыклад, {{name}}) або HTML-тэгі.
  2. Падсветка падазроных месцаў: У рэдактары вы ўбачыце папярэджанні, калі пераклад выглядае няўпэўнена.

Вы заўсёды маеце апошняе слова. Сэрвіс прапануе — вы зацвярджаеце.


Абмежаванні і асаблівасці

Паколькі сэрвіс працуе на LLM, ён мае свае асаблівасці.
Перш за ўсё - гэта памер кантэксту: мадэль можа апрацоўваць толькі пэўную колькасць інфармацыі за раз (у сярэднім каля 8–10 тысяч токенаў).
Калі тэкст занадта вялікі, яго лепш падзяліць на лагічныя часткі - так мадэль лепш разумее структуру і кантэкст, і пераклады выходзяць больш дакладнымі.

Пры выкарыстанні RAG кантэкст таксама можа быць непоўны - бо ў ім захоўваюцца асобныя кавалкі тэксту і пашук адбываецца па ім.
Таму лепш перакладаць невялікімі блокамі і пазбягаць перагрузу мадэлі.

Гэта не недахоп, а хутчэй асаблівасць працы LLM - яны проста павінны “разумець” тэкст у межах свайго кантэкстнага вакна.
Затое гэта дазваляе дасягаць стабільных вынікаў і лёгка апрацоўваць пераклады.


Пра токены і кошт

Прынцып працы - сумленнасць.

  • Праз MCP: Вы выкарыстоўваеце свой уласны ключ API (Copilot, Cursor, OpenAI), таму Goman.live не спаганяе ніякіх дадатковых плацяжоў за токены. Гэта фактычна бясплатна з боку сэрвісу.
  • Праз Рэдактар: Выкарыстоўваюцца магутнасці сэрвісу, таму спісваюцца ўнутраныя токены.

Як атрымаць зніжку?

Дзейнічае рэферальная праграма: прывядзіце сябра і атрымайце да 90% зніжкі. Можна звярнуцца на goman.live.service@gmail.com, калі хочаце даведацца больш.


Пра захаванне даных

Усе вашы даныя захоўваюцца на ўласных серверах.
Дамп робіцца кожныя 6 гадзін, а інфармацыя не перадаецца трэцім бакам апроч мадэлей (LLM), якія апрацоўваюць пераклады. Даныя пасля выдаленне аплікацыі могуць яшчэ некаторы час захоўвацца - зроблена для магчымасці па персанальным запыце ўсе ж аднавіць іх. Так сама вы у любы час можаце выгрузіць лакалізацыі у прапанаванай у сэрвісе форме. Загружаць даныя магчыма як праз MCP, праз форму (па адным запісы) ці адразу шмат з файла у неабходным фармаце.


Пра супрацу

Каманда праекта адкрыта да новых ідэй і супрацоўніцтва.
Пры наяўнасці сэрвісу ці бізнесу, які можна інтэграваць з Goman.live, або пры ўзнікненні цікавасці да праекта — можна звязацца з распрацоўшчыкамі.
Магчыма стварэнне кастамных планаў, API-інтэграцыі і нават асобныя рашэнні пад канкрэтныя патрэбы.


Дадатковы функцыянал

Goman.live - гэта не толькі лакалізацыі.
Сэрвіс дазваляе тэставаць промпты, глядзець вынікі, захоўваць іх у розных версіях і нават працаваць у камандзе. Больш дакладна гэта апісана ў дакументацыі сэрвісу


Што далей

Вядзецца праца над наступнымі рэчамі:

  • паляпшэнне інтэграцыі промптаў з GitHub Copilot, Cursor і іншымі IDE,
  • выбар мадэлі перакладу ды выкарыстанне ўласных API-ключоў,
  • паляпшэнне RAG і аўтаматычнае абнаўленне лакалізацый,
  • і яшчэ шмат ідэй, якія зробяць працу з перакладамі яшчэ зручнейшай.

Падсумаванне: Чаму варта паспрабаваць?

Калі вы хочаце ствараць глабальныя прадукты, але не хочаце марнаваць жыццё на табліцы з перакладамі — Goman.live для вас.

  1. Хуткасць: Лакалізацыя становіцца часткай напісання кода, а не асобным этапам.
  2. Якасць: AI ведае кантэкст і стыль лепш, чым Google Translate.
  3. Зручнасць: Кіруйце ўсім прама з вашай любімай IDE.

👉 Паспрабуйце самі на goman.live і адчуйце розніцу. Вашы карыстальнікі скажуць вам "Дзякуй" (на сваёй роднай мове 😉).

AI
MCP
translations
Admin, 2025-11-02