Tool calling в Ollama — одна з найбільш неочевидних фіч локальних моделей.
Не тому що API складний. А тому що між «модель підтримує tools» у документації
і «модель стабільно викликає tools у продакшні» — велика різниця яку
можна виявити тільки під навантаженням.
Одні моделі навчені на tool calling нативно: вони розпізнають JSON Schema,
повертають структурований tool_calls і рідко помиляються з аргументами.
Інші — знають про існування формату, але вирішують самостійно чи використовувати його.
Треті — серіалізують tools у системний промпт і намагаються відповісти JSON-подібним текстом.
Поведінка ззовні однакова. Результати — принципово різні.
Далі — конкретно: які моделі куди потрапляють, як це перевірити за одну команду
і що робити коли навіть надійна модель мовчить.
Якщо ще не знайомий з тим як tool calling влаштований на рівні API —
почни з Ollama REST API: інтеграція у свій застосунок,
там є повний розбір циклу виклику з прикладами на Java, Python і JavaScript.
Що значить «підтримує tool calling» — і чому це не просто прапорець
В офіційній документації Ollama є сторінка
Tool Calling
з прикладами коду. Там є список моделей, є curl-приклади, є формат JSON Schema.
Але документація не відповідає на головне питання:
наскільки надійно конкретна модель викликає tools у реальних умовах?
Слово «підтримує» у контексті tool calling — розмите. Воно може означати
три принципово різні речі, і зовні вони виглядають однаково.
Аналогія перш ніж до коду
Уяви що ти найняв трьох помічників і дав кожному з них інструкцію:
«Якщо клієнт питає про погоду — подзвони до метеослужби і скажи мені результат.
Якщо питає про курс валют — запроси банківський API.»
Перший помічник чітко розуміє коли дзвонити і завжди повертає тобі структурований результат — «дзвінок зроблено, відповідь: +18°C».
Другий помічник іноді дзвонить, іноді відповідає «ну, напевно тепло» без дзвінка — залежно від настрою.
Третій помічник взагалі не знає як дзвонити, але якщо ти детально пояснив йому у записці що саме писати — іноді він намагається скопіювати формат. Результат непередбачуваний.
У всіх трьох ти сказав одне і те саме. Поведінка — різна.
Саме так виглядає «підтримка tool calling» у різних моделях Ollama.
Три рівні підтримки — технічно
1. Нативна підтримка (на рівні ваг)
Модель навчалась на даних де були приклади tool calling.
Вона не просто «знає формат» — вона розуміє коли потрібно викликати зовнішню функцію,
а коли відповісти текстом. JSON Schema сприймається як частина діалогу, а не як текст.
Ollama передає tools через спеціальні токени — і модель реагує на них предметно.
Результат: стабільний tool_calls у відповіді, коректні аргументи,
передбачувана поведінка при повторних запитах.
Приклади: qwen3, llama3.1+, gemma4.
2. Часткова підтримка
Модель знає формат JSON Schema і може повернути tool_calls —
але не завжди. Вона оцінює запит і сама вирішує чи «варто» викликати tool.
Іноді ця оцінка правильна. Іноді — ні. Поведінка залежить від формулювання
питання, від довжини промпту, від температури генерації.
Практичний наслідок: у простих тестових запитах все виглядає добре.
Під реальним навантаженням з'являються «мовчазні» відповіді де tool_calls
не прийшов, але і помилки немає. Агент зависає на кроці де мав щось зробити.
3. «Підтримка» через промпт-інжиніринг
Ollama серіалізує опис tools у звичайний текст і вставляє його у системний промпт.
Модель бачить щось на кшталт: «У тебе є функція get_weather з параметрами city і units.
Якщо потрібно — поверни JSON у форматі…».
Модель відповідає на основі інструкції, а не навчання.
Результат: JSON може прийти у полі content як звичайний текст
(часто у ```json ... ``` блоці), а не у структурованому tool_calls.
Або JSON неповний. Або модель вирішила що питання «досить просте» і відповіла
без будь-якого виклику. Парсити такий вивід — ненадійно.
Як виглядає різниця у відповіді
Один і той самий запит — «Яка погода у Харкові?» — з різними моделями:
{
"message": {
"role": "assistant",
"content": "Зараз у Харкові помірна температура. Зазвичай влітку +20–25°C..."
}
}
HTTP 200 у всіх трьох випадках. Код без явної перевірки на наявність
tool_calls «проковтне» другий і третій варіант як успішну відповідь —
і агент піде далі з неправильними або відсутніми даними.
Чому це важливо саме в продакшні
На одному тестовому запиті проблема непомітна. Навіть модель з частковою підтримкою
спрацює правильно якщо питання чітке і коротке.
Проблема проявляється коли:
Запитів багато і серед них є нетипові або довгі
Агент має зробити кілька послідовних кроків (multi-step)
Один пропущений tool call ламає весь подальший ланцюг
Немає явної перевірки що tool_calls прийшов перед тим як рухатись далі
Саме тому вибір моделі для агентного пайплайну — це не питання якості відповідей.
Це питання надійності структурованого виводу під різними умовами.
Різниця між першим і третім варіантом підтримки — це різниця між агентом
який стабільно працює і агентом який ламається на другому кроці без жодного логу.
Як Ollama передає tools моделі: системний промпт vs native function calling
Коли ти відправляєш запит до /api/chat з масивом tools —
Ollama не просто пересилає твій JSON далі. Він вирішує як саме передати
опис функцій моделі. І це рішення залежить від того, чи підтримує модель
нативний шлях. Два різних шляхи — два різних результати.
Аналогія перш ніж до деталей
Уяви що ти даєш завдання двом перекладачам.
Першому ти передаєш завдання рідною мовою — він розуміє одразу, без зусиль,
і відповідає точно у потрібному форматі.
Другому ти передаєш завдання через перекладача-посередника який переформулює
всю інструкцію у звичайний текст. Другий перекладач намагається — але
посередник міг щось спростити, щось переформулювати не так. Результат менш передбачуваний.
Нативний шлях — це перший перекладач. Промпт-шлях — другий.
Нативний шлях: tools як частина мови моделі
Моделі з нативною підтримкою мають у своїй архітектурі спеціальні токени
для опису функцій — так само як є токени для ролей user,
assistant, system. Під час навчання модель бачила
тисячі прикладів де ці токени з'являлись у певному контексті і за ними
слідував структурований виклик.
Коли Ollama отримує запит з tools і розуміє що модель підтримує
нативний шлях — він серіалізує JSON Schema у ці спеціальні токени
і вставляє їх у правильне місце в шаблоні чату. Модель «читає» їх
так само природно як читає повідомлення користувача.
Результат: модель сама вирішує коли викликати tool (і вирішує правильно
у переважній більшості випадків), повертає структурований tool_calls
з коректними аргументами, і не потребує додаткових підказок у системному промпті.
Схема нативного шляху:
Твій запит (tools + messages)
↓
Ollama
↓ серіалізує tools у спеціальні токени моделі
[TOOL_DEF] get_weather(city: string) [/TOOL_DEF]
[USER] Яка погода у Харкові? [/USER]
↓
Модель генерує:
[TOOL_CALL] {"name": "get_weather", "arguments": {"city": "Харків"}} [/TOOL_CALL]
↓
Ollama парсить → повертає структурований tool_calls у відповіді
Промпт-шлях: tools як текстова інструкція
Якщо модель не підтримує нативний шлях — Ollama не може передати tools
через спеціальні токени (їх просто немає у словнику моделі).
Замість цього він конвертує весь опис функцій у звичайний текст
і додає його до системного промпту.
Модель отримує щось на кшталт:
You have access to the following tools:
get_weather: Отримати поточну погоду для міста
Parameters:
- city (string, required): Назва міста
- units (string, optional): celsius або fahrenheit
If you need to call a tool, respond with JSON in this format:
{"tool": "tool_name", "arguments": {...}}
[USER]: Яка погода у Харкові?
Тепер модель намагається слідувати текстовій інструкції.
Проблема в тому що ця інструкція — лише текст серед іншого тексту.
Модель не «знає» що від неї чекають структурований виклик на рівні навчання.
Вона просто генерує наступний токен на основі всього що бачить.
Тому результат може бути будь-яким:
Правильний JSON у полі content (але не у tool_calls)
JSON у ```json``` блоці — текст, який треба парсити вручну
Частковий JSON без закриваючої дужки
Відповідь текстом без будь-якого JSON — модель вирішила що «і так зрозуміло»
JSON з ключами які відрізняються від тих що ти описав ("tool_name" замість "name")
Схема промпт-шляху:
Твій запит (tools + messages)
↓
Ollama
↓ конвертує tools у текстову інструкцію → додає до system prompt
"You have access to: get_weather(city)... respond with JSON..."
[USER] Яка погода у Харкові? [/USER]
↓
Модель генерує текст (може бути JSON, може бути ні)
↓
Ollama повертає все у полі content — tool_calls порожній або відсутній
Як визначити який шлях використовує твоя модель — одна команда
Ollama показує capabilities кожної моделі через ollama show.
Наявність tools у секції — ознака нативної підтримки:
# Нативна підтримка — tools є у capabilities
ollama show llama3.1:8b
Model
arch llama
parameters 8.0B
context length 131072
...
Capabilities
completion
tools ← є — Ollama використає нативний шлях
vision
# Промпт-шлях — tools відсутній
ollama show mistral-nemo:latest
Model
arch mistral
parameters 12.2B
context length 131072
...
Capabilities
completion ← tools немає — буде fallback через промпт
Це перша команда яку варто виконати перед тим як будувати агентний пайплайн
на новій моделі. Якщо tools немає у capabilities —
не витрачай час на дебаг «чому не викликає» — модель просто не підтримує нативно.
Чи можна використовувати промпт-шлях у продакшні?
Технічно — так. На практиці — з великими застереженнями.
Промпт-шлях може спрацювати якщо:
У тебе один простий tool з одним-двома параметрами
Запити завжди чіткі і короткі
Ти готовий писати і підтримувати парсер для content замість tool_calls
Збій не є критичним — агент може спробувати ще раз
Але якщо у тебе кілька tools, складні параметри, multi-step агент або
production де кожен збій коштує грошей і часу клієнта —
обирай модель з нативною підтримкою. Це не питання переваг, це питання надійності.
Коротко: перевір ollama show <model> перед стартом.
Є tools у capabilities — нативний шлях, стабільно.
Немає — промпт-шлях, непередбачувано. Вибір моделі для агента починається з цієї перевірки.
Моделі з нативною підтримкою: хто реально викликає tools
Нижче — моделі з моєї локальної колекції та публічних даних, які підтверджено
підтримують tool calling нативно через Ollama станом на травень 2026.
Для кожної моделі — не просто «підтримує», а конкретно: що вона робить добре,
де має обмеження, і для яких задач підходить найкраще.
Перш ніж пробувати будь-яку з цих моделей — перевір нативну підтримку:
ollama show <model> і шукай tools у секції Capabilities.
Навіть у межах однієї серії різні версії можуть відрізнятись.
Qwen3 (8b, 14b, 30b, 32b) — найстабільніший вибір у 2026
Qwen3 від Alibaba — зараз найстабільніша серія для tool calling серед моделей
які запускаються локально. За даними
Morph LLM benchmarks,
Qwen3 має найнижчий відсоток «dropped tool calls» — модель рідко ігнорує
tools або повертає невалідний JSON.
Що робить Qwen3 особливим для tool calling:
Thinking mode (think=True) — модель спочатку «думає» у прихованому блоці, потім генерує виклик. Це підвищує точність при складних multi-tool сценаріях де треба вибрати правильний tool з кількох варіантів.
Стабільний JSON — аргументи у tool_calls майже завжди валідні, типи відповідають схемі.
Широкий вибір розмірів — від 8B (5.2 GB, влазить у будь-який сучасний Mac) до 32B для тих у кого є потужне залізо.
qwen3:8b — мій поточний вибір для локальної розробки на Mac M1 16 GB.
Запускається разом з nomic-embed-text для RAG без свопу на диск.
ollama pull qwen3:8b # 5.2 GB — для 8–16 GB RAM
ollama pull qwen3:14b # ~9 GB — якщо потрібна вища точність
ollama pull qwen3:32b # ~20 GB — для потужного заліза
Коли обирати Qwen3: агенти з кількома tools, RAG-пайплайни де треба вибирати між searchDocuments / findDeadlines / extractContacts, будь-яка задача де важлива стабільність виклику.
Обмеження: thinking mode збільшує latency першої відповіді на 1–3 секунди. Якщо потрібна максимальна швидкість — можна вимкнути через "think": false у запиті.
Llama 3.1 від Meta була однією з перших широкодоступних моделей з нативним
tool calling — і з тих пір серія залишається стандартом де найбільше
готових прикладів, туторіалів і підтримки у фреймворках.
llama3.1:8b (4.9 GB) — найбільш «вивчена» модель для tool calling:
якщо ти шукаєш приклад інтеграції зі Spring AI, LangChain або LlamaIndex —
у 90% випадків він буде саме на llama3.1.
За даними Prompt Quorum,
Llama 4 Scout (MoE архітектура, ~10 GB VRAM) — найсвіжіший варіант
з найширшою підтримкою інструментів у лінійці Meta.
Коли обирати Llama: якщо використовуєш Spring AI, LangChain або LlamaIndex і хочеш максимум готових прикладів. Llama 3.1 — найбезпечніший вибір для старту.
Обмеження: llama3.1:8b поступається qwen3:8b у надійності multi-tool викликів. На простих single-tool задачах різниця непомітна.
Gemma 4 (9b, 26b) — найнадійніший tool calling у своєму класі
Google проектував Gemma 4 з нативним function calling від початку —
це не fine-tuning поверх базової моделі, а архітектурне рішення.
На практиці це означає менше dropped tool calls і рідше невалідний JSON
порівняно з моделями де tool calling додавався пізніше.
gemma4:latest є в моїй локальній колекції (9.6 GB, завантажив 3 тижні тому).
З мого досвіду — найвища надійність серед 8–10B моделей: у тестах
на 20 запитів з двома tools одночасно (searchDocuments і findDeadlines)
повертала валідний tool_calls у ~90% випадків проти ~85% у qwen3:8b.
Додатковий бонус — vision підтримка з тими самими tools:
# Можна передати зображення І викликати tool в одному запиті
curl http://localhost:11434/api/chat \
-d '{
"model": "gemma4:latest",
"messages": [{
"role": "user",
"content": "Що зображено на скані документу? Знайди дати.",
"images": ["<base64_image>"]
}],
"tools": [{ ... "findDeadlines" ... }]
}'
Коли обирати Gemma 4: агенти де потрібна максимальна надійність виклику, multimodal задачі (документи + зображення + tools), production де збій коштує.
Обмеження: 9.6 GB — більший файл ніж qwen3:8b (5.2 GB) або llama3.1:8b (4.9 GB). На Mac M1 16 GB паралельно з nomic-embed-text можливий своп при тривалих сесіях.
Qwen2.5 / Qwen2.5-Coder — попереднє покоління, досі актуальне
Qwen2.5 підтримує tool calling нативно і досі є сенс розглядати його
якщо Qwen3 з якихось причин не підходить.
У моїй колекції є qwen2.5-coder:1.5b-base —
але це base модель без instruction tuning.
Base модель не навчена слідувати інструкціям, вона лише передбачає
наступний токен. Для tool calling це означає: модель не «розуміє»
що від неї чекають виклику функції — вона просто продовжує текст.
Важливо: для tool calling завжди потрібна instruct-версія моделі,
а не base. Base — для fine-tuning. Instruct — для використання.
Якщо бачиш -base у назві — це не та модель.
# Неправильно для tool calling:
ollama pull qwen2.5-coder:1.5b-base # base — не підходить
# Правильно:
ollama pull qwen2.5:7b # instruct варіант
ollama pull qwen2.5-coder:7b # instruct + фокус на код
Коли обирати Qwen2.5: якщо Qwen3 недоступний або потрібна специфічна версія з підтримкою певного фреймворку. Qwen2.5-Coder:7b — хороший вибір для агентів що працюють з кодом.
DeepSeek-R1 (7b, 14b, 32b) — для складних reasoning задач
DeepSeek-R1 підтримує tool calling, але з архітектурною особливістю
яку важливо розуміти: перед тим як повернути tool_calls,
модель генерує розмірковування у прихованому блоці <think>...</think>.
Як це виглядає у відповіді:
{
"message": {
"role": "assistant",
"content": "<think>\nКористувач питає про погоду. У мене є tool get_weather.\nТреба передати city='Харків'. units не вказано, використаю celsius за замовчуванням.\n</think>",
"tool_calls": [
{
"function": {
"name": "get_weather",
"arguments": { "city": "Харків", "units": "celsius" }
}
}
]
}
}
Блок <think> — це внутрішнє розмірковування моделі.
Твій код має його ігнорувати і читати лише tool_calls.
Але саме завдяки цьому розмірковуванню DeepSeek-R1 рідше помиляється
з вибором аргументів і краще справляється з ambiguous запитами
де незрозуміло який tool викликати.
Практичний наслідок для latency:
Модель
Час до першого token у tool_calls
Причина
llama3.1:8b
1.2–2.0 с
Одразу генерує виклик
qwen3:8b (think=true)
1.5–2.5 с
Коротке think-розмірковування
deepseek-r1:7b
3.0–6.0 с
Довше think перед викликом
deepseek-r1:14b
5.0–10.0 с
Ще довше thinking
ollama pull deepseek-r1:7b # 4.5 GB — баланс якості і швидкості
ollama pull deepseek-r1:14b # ~9 GB — для складних reasoning задач
Коли обирати DeepSeek-R1: агенти де важлива правильність вибору tool, а не швидкість. Наприклад: юридичний аналіз документів де модель має вирішити чи викликати checkCompliance чи extractKeyFacts — і помилка в виборі коштує.
Обмеження: latency першого виклику у 2–3 рази вища ніж у llama3.1:8b. Для real-time чат-агентів де важлива швидкість реакції — не найкращий вибір.
З особистого досвіду: як я обирав модель для AskYourDocs
Коли я реалізовував агентний пайплайн для
AskYourDocs —
RAG-сервісу де агент має викликати кілька tools (searchDocuments,
extractKeyFacts, findDeadlines, extractContacts,
checkCompliance) — я пройшов через кілька моделей перш ніж зупинився
на робочому варіанті.
Спочатку я підключив qwen3:8b через Spring AI 2.0.0-M3 і Ollama.
Модель приходила і… відповідала текстом. Жодного tool_calls.
Проблема виявилась не в моделі — у Spring AI 2.0.0-M3 є обмеження
як передаються tools до Ollama через ToolCallingChatOptions.
Модель просто не отримувала tools у правильному форматі.
Після того як я розібрався з форматом передачі — порівняв кілька моделей
на одному наборі тестових запитів:
qwen3:8b — після виправлення формату запрацював стабільно. Думаючий режим допоміг при складних запитах де треба вибрати між кількома tools.
llama3.1:8b — найпростіша інтеграція зі Spring AI, найбільше прикладів у документації фреймворку.
mistral-nemo — не спрацював нативно, відповідав текстом. Перевірка через ollama show підтвердила: немає tools у capabilities.
У підсумку для локальної розробки я використовую qwen3:8b,
для production на Railway — deepseek/deepseek-chat через OpenRouter
(для звичайних клієнтів) або anthropic/claude-3.5-sonnet
(для юридичних клієнтів де важлива точність).
Локальна модель для розробки і хмарна для продакшну — це стандартна практика
коли залізо на сервері не тягне великі моделі локально.
Моделі які «роблять вигляд»: відповідають текстом замість JSON
Якщо попередня секція — про тих хто реально викликає tools,
то ця — про тих хто цього не робить, але і не повертає помилку.
HTTP 200, текст у content, порожній tool_calls.
Саме ці моделі забирають найбільше часу при дебагу — бо зовні все виглядає нормально.
Важливо: це не означає що ці моделі погані. Вони просто не призначені для агентних пайплайнів.
У кожної є своя сильна сторона — і вона не тут.
Mistral Nemo — відмінний текстовий асистент, не агент
mistral-nemo:latest є в моїй локальній колекції (7.1 GB).
Перевірка одразу дає відповідь:
ollama show mistral-nemo:latest
Capabilities
completion ← tools відсутній
Mistral Nemo не має нативного tool calling. Ollama використовує промпт-шлях —
серіалізує опис функцій у текст системного промпту.
Результат непередбачуваний: у ~30% тестових запитів модель повертала JSON
у текстовому блоці ```json...``` всередині content,
у решті — просто відповідала текстом як ніби tools не існують.
Де Mistral Nemo дійсно сильний: резюмування довгих документів,
переклад, написання текстів, питання-відповідь без зовнішніх викликів.
12.2B параметрів у 7.1 GB — хороший розмір/якість для цих задач.
Просто не для агентів.
Задача
Mistral Nemo
Резюмування документів
✅ Відмінно
Переклад і редагування тексту
✅ Відмінно
Чат без зовнішніх викликів
✅ Добре
Tool calling в агенті
❌ Ненадійно
Multi-tool пайплайн
❌ Не підходить
Phi-4 — аналітика так, агенти ні
Phi-4 від Microsoft — компактна модель (9.1 GB, 16K контекст) з сильними
показниками на STEM і аналітичних задачах. За даними
Computing for Geeks,
Phi-4 займає високі позиції в бенчмарках з математики і reasoning —
але явно слабка на tool calling і long-context retrieval.
Причина технічна: Phi-4 оптимізована для щільного знання на параметр,
а не для instruction following у форматі function calling.
Модель «розуміє» задачу, але не повертає структурований виклик стабільно.
Практичне правило: якщо потрібен локальний аналітичний асистент для
числових даних, звітів або математичних задач без зовнішніх API — Phi-4 чудовий вибір.
Якщо потрібен агент який викликає tools — шукай далі.
Gemma 3 — не плутати з Gemma 4
Це часта помилка: людина читає що «Gemma підтримує tool calling»,
встановлює gemma3:9b — і отримує текст замість tool_calls.
Причина проста: нативний tool calling з'явився у Gemma 4,
не в Gemma 3.
ollama show gemma3:9b
Capabilities
completion
vision ← tool calling відсутній
ollama show gemma4:9b
Capabilities
completion
tools ← є — нативна підтримка
vision
Між поколіннями — принципова різниця в архітектурі навчання.
Якщо у тебе встановлена gemma3:* і ти будуєш агента — оновлюйся до gemma4.
Якщо оновитись не можна (обмеження по RAM або диску) — розглянь llama3.1:8b
або qwen3:8b як альтернативу того ж розміру.
Старі кодові моделі — CodeLlama, StarCoder2, CodeGemma
Ці моделі проектувались для code completion — передбачення наступного рядка коду
у файлі. Це фундаментально інша задача ніж instruction following або tool calling.
Code completion модель бачить незавершений код і продовжує його.
Tool calling вимагає: зрозуміти запит природною мовою → вирішити який інструмент викликати →
сформувати JSON з аргументами. Ці моделі не навчались цьому шляху.
У 2026 вони поступились місцем спеціалізованим instruct-моделям:
qwen2.5-coder:7b для коду і kimi-k2.6 для складних агентних задач.
CodeLlama і StarCoder2 — реліквії 2023 року, корисні для вузьких задач
автодоповнення, але не для агентів.
Як швидко перевірити будь-яку нову модель
Перш ніж витрачати час на інтеграцію — два кроки перевірки:
Крок 1 — capabilities:
ollama show <model> | grep tools
# Якщо нічого не вивела — tools немає, промпт-шлях
Якщо у виводі є tool_calls з коректним name і arguments —
модель підходить. Якщо вивід порожній або tool_calls відсутній —
дивись capabilities і рости до наступної моделі зі списку в секції 3.
Бенчмарк: надійність, швидкість першого tool call, multi-tool
Документація каже «підтримує». Але скільки разів з 10 модель реально повертає
валідний tool_calls? Скільки секунд минає до першого токена?
Чи може модель викликати два tools паралельно — чи тільки один за раз?
Саме ці три параметри визначають чи підходить модель для агентного пайплайну
у реальних умовах, а не у тестовому curl-запиті.
Що і як вимірювалось
Бенчмарк гібридний: особисті тести на Mac M1 16 GB з моделями
з моєї поточної колекції (ollama list), доповнені публічними
даними від Morph LLM
і Computing for Geeks
(RTX 4090, Ollama 0.23.1, травень 2026).
Три параметри які мають значення для агентів:
1. Надійність tool call — відсоток запитів де модель повернула
валідний tool_calls з коректними аргументами, а не текст у content.
Вимірюється на 20 однотипних запитах з однаковим набором tools.
Чому 20, а не 100: для локальної розробки 20 запитів достатньо щоб побачити
системну поведінку. 100% на 5 запитах нічого не означає — подивись на 20.
2. Час до першого токена у tool_calls (TTFT) —
скільки секунд проходить від відправки запиту до появи першого байта
структурованої відповіді. Для стрімінгу — час до першого токена взагалі.
Для агента який чекає результат tool перед наступним кроком — це пряма затримка UX.
3. Multi-tool (паралельний виклик) — чи може модель в одному запиті
повернути кілька tool_calls одночасно. Наприклад: «Знайди документи
про оренду ТА витягни ключові дати» — ідеально мало б стригернути і
searchDocuments, і findDeadlines в одній відповіді.
Якщо модель не підтримує multi-tool — вона викликає їх послідовно або
взагалі ігнорує один із запитів.
Тест на Mac M1 16 GB — особистий
Тестовий запит: «Знайди документи про оренду та витягни ключові дати»
з двома tools: searchDocuments (пошук по документам) і
findDeadlines (пошук дат і дедлайнів). Обидва tools є в моєму
реальному проєкті AskYourDocs — тому запит не синтетичний,
це реальний агентний сценарій.
Умови: Ollama запущений локально, моделі завантажені в RAM перед тестом
(щоб виключити cold-start), stream: false, температура за замовчуванням.
Модель
Надійність
TTFT
Multi-tool
Що спостерігав
qwen3:8b
~85%
1.5–2.5 с
✅
Думаючий режим додає ~0.5–1 с але знижує кількість помилок в аргументах. У 15% випадків відповідав текстом на неоднозначних формулюваннях.
llama3.1:8b
~80%
1.2–2.0 с
✅
Найшвидший TTFT серед протестованих. 20% — текстова відповідь, частіше на запитах де питання сформульоване неточно.
gemma4:latest
~90%
1.8–3.0 с
✅
Найвища надійність. Повільніший старт через більший розмір (9.6 GB). Multi-tool спрацьовував найстабільніше з усіх.
mistral-nemo:latest
~30%
—
❌
У 70% запитів — текст. У ~30% — JSON у текстовому блоці всередині content, не у tool_calls. Жодного разу не повернув два tools паралельно.
qwen3-ua:latest
~75%
2.0–3.5 с
⚠️
Модель адаптована під українську мову. Tool calling менш стабільний ніж у базового qwen3. Multi-tool спрацьовував через раз.
Відсотки надійності — наближені оцінки на 20 запитів кожної моделі.
Реальні показники залежать від трьох факторів: точності формулювання запиту,
якості description у JSON Schema функції, і версії Ollama.
Погано написаний description може знизити надійність навіть
найкращої моделі на 20–30%.
Що реально впливає на надійність — не тільки модель
Під час тестів я помітив: одна і та сама модель може дати 90% надійність
на чіткому запиті і 60% — на розмитому. Модель — лише половина рівняння.
Друга половина — якість опису функції.
Порівняй два описи одного і того самого tool:
// Поганий опис — модель часто ігнорує tool
{
"name": "searchDocuments",
"description": "Search documents",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string"}
}
}
}
// Хороший опис — модель викликає стабільно
{
"name": "searchDocuments",
"description": "Шукає релевантні документи у базі знань за текстовим запитом. Викликай цей tool ЗАВЖДИ коли користувач питає про документи, договори, умови або будь-яку інформацію з бази.",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Текстовий запит для пошуку. Наприклад: 'умови оренди', 'дати платежів', 'відповідальність сторін'"
},
"topK": {
"type": "integer",
"description": "Кількість результатів. За замовчуванням 5."
}
},
"required": ["query"]
}
}
Різниця в надійності на qwen3:8b між цими двома описами —
приблизно 20–25 відсоткових пунктів на тому самому наборі запитів.
Перш ніж звинувачувати модель — перевір свій description.
Для тих у кого є потужне GPU або хто планує серверне розгортання —
нижче дані на RTX 4090 (24 GB VRAM, CUDA 12.6).
Tokens/sec — швидкість генерації відповіді після першого токена.
VRAM — потреба при Q4_K_M квантизації і дефолтному розмірі контексту.
Модель
Параметри
Tokens/sec
VRAM (Q4_K_M)
Tool calling
Для чого
gemma4:26b (MoE)
26B / 4B active
~55 tok/s
~18 GB
✅ Нативний
Найкращий баланс якість/швидкість для агентів на GPU
qwen2.5-coder:32b
32B
~35 tok/s
~20 GB
✅ Нативний
Агенти з кодом; найсильніша локальна coding модель у 2026
llama3.3:70b
70B
~18 tok/s
~43 GB
✅ Нативний
Максимальна якість reasoning; потрібно 48+ GB VRAM
llama3.1:8b
8B
~50 tok/s
~6 GB
✅ Нативний
Найшвидша 8B модель на GPU; стандартний вибір для dev-середовища
phi4:14b
14B
~40 tok/s
~10 GB
⚠️ Слабкий
Швидко, але tool calling ненадійний — тільки для аналітики без tools
Зверни увагу на gemma4:26b MoE: 26B параметрів загалом,
але активних лише 4B на кожен токен. Тому швидкість (~55 tok/s) вища
ніж у dense 32B моделей, а VRAM менша. MoE архітектура —
це не «маленька модель», це розумний розподіл обчислень.
Ключовий висновок по бенчмарку
Для локальної розробки (8–16 GB RAM, Apple Silicon або середній ноутбук):
llama3.1:8b якщо важлива швидкість, gemma4:latest
якщо важлива надійність, qwen3:8b — золота середина.
Для GPU-сервера з 20–24 GB VRAM: gemma4:26b — найкращий варіант
для production агентів. MoE архітектура дає якість 26B при споживанні
значно менших ресурсів.
І пам'ятай: 10–15% приросту надійності можна отримати просто
покращивши description у JSON Schema — без зміни моделі.
Порівняльна таблиця: модель / розмір / надійність / RAM
Зведена таблиця всіх моделей про які йшлося у статті.
Призначена як швидкий довідник — щоб не гортати текст знову
коли треба вибрати модель під конкретне залізо і задачу.
Позначення надійності tool calling:
✅ Нативний — стабільно 75%+, структурований tool_calls у відповіді.
⚠️ Частковий / Промпт — нестабільно, менше 50%, JSON може з'явитись у content.
❌ Відсутній — модель не повертає tool_calls у стандартних умовах.
Модель
Розмір файлу
RAM мін.
Tool calling
Multi-tool
Надійність
Найкраще для
gemma4:9b
9.6 GB
12 GB
✅ Нативний
✅
~90%
Агенти + vision; максимальна надійність у 8–10B класі
qwen3:8b
5.2 GB
8 GB
✅ Нативний
✅
~85%
Оптимальний баланс розмір/надійність; старт для більшості задач
llama3.1:8b
4.9 GB
8 GB
✅ Нативний
✅
~80%
Найширша підтримка фреймворків; найкращий TTFT серед 8B
llama4:scout
~10 GB
12 GB
✅ Нативний
✅
~85%
MoE; найновіший від Meta; найширша підтримка інструментів у лінійці
qwen3:14b
~9 GB
12 GB
✅ Нативний
✅
~88%
Крок вгору від 8B коли потрібна вища точність аргументів
gemma4:26b
18 GB
20 GB
✅ Нативний
✅
~93%
Production GPU; MoE; найвища надійність у таблиці
deepseek-r1:7b
~4.5 GB
8 GB
✅ Нативний
⚠️
~80%
Складні reasoning задачі де важлива правильність вибору tool
deepseek-r1:14b
~9 GB
12 GB
✅ Нативний
⚠️
~85%
Те саме що r1:7b але вища точність; latency 5–10 с до першого виклику
qwen3-ua:latest
5.2 GB
8 GB
✅ Нативний
⚠️
~75%
Українськомовні задачі; tool calling менш стабільний ніж базовий qwen3
mistral-nemo:latest
7.1 GB
8 GB
⚠️ Промпт
❌
~30%
Резюмування, переклад, чат без tools — не для агентів
phi4:14b
9.1 GB
12 GB
⚠️ Слабкий
❌
~40%
Аналітика, STEM, математика — не для агентів з tools
gemma3:9b
~5.5 GB
8 GB
❌ Відсутній
❌
—
Попереднє покоління; оновись до gemma4 для agents
Як читати таблицю під своє залізо
Mac / ноутбук 8 GB RAM:
Старт: llama3.1:8b або qwen3:8b
Разом з RAG (nomic-embed-text): qwen3:8b — обидві влазять без свопу
Оптимум для tool calling: gemma4:9b (~90% надійність) або qwen3:8b (~85%)
З RAG паралельно: qwen3:8b + nomic-embed-text — без свопу (5.2 + 0.27 GB)
Якщо потрібна вища точність: qwen3:14b (~9 GB) — працюватиме, але щільно. З RAG можливий своп.
Уникай: gemma4:26b (18 GB) і llama3.3:70b — не вміщуються
GPU-сервер 20–24 GB VRAM (RTX 3090 / 4090):
Production агент: gemma4:26b — ~93% надійність tool calling, ~55 tok/s завдяки MoE
Агент з фокусом на код: qwen2.5-coder:32b (~20 GB, найсильніша локальна coding модель у 2026)
Якщо залізо 20 GB і треба залишити буфер: qwen3:14b + RAG-модель паралельно
GPU-сервер 40+ GB VRAM:
Максимальна якість: llama3.3:70b (~43 GB при Q4_K_M)
Але зважай: ~18 tok/s на RTX 4090 — для real-time чату може бути замало. Для batch-обробки документів — прийнятно.
Альтернатива: два екземпляри gemma4:26b (~36 GB разом) з балансуванням навантаження — вища пропускна здатність ніж один 70B
Якщо не впевнений у своєму залізі — запусти ollama ps після завантаження моделі
і перевір поле size_vram. Якщо значення менше ніж розмір моделі —
частина завантажена у системну RAM і модель свопить. Для tool calling агента своп
означає latency 5–15 с замість 1–2 с на перший виклик.
Рекомендації по розміру: 3B / 7–8B / 14B+ — де проходить межа якості
Розмір моделі — не єдиний фактор надійності tool calling,
але він задає стелю. Навіть ідеально написаний description
не витягне 3B модель до рівня 14B на складному multi-tool сценарії.
Нижче — де проходить практична межа і як я до цього прийшов.
До 4B: для edge і тестування, не для продакшну
Маленькі моделі (1–4B) технічно можуть повернути tool_calls —
але їхня здатність правильно інтерпретувати JSON Schema обмежена.
Що конкретно ламається:
Опис функції довший за 2–3 рядки — модель «не дочитує» і пропускає параметри
Кілька tools у запиті — модель обирає перший і ігнорує решту
Нестандартне формулювання запиту — модель відповідає текстом замість виклику
Параметри зі складними типами (enum, nested object) — часто повертає невалідний JSON
Єдиний розумний виняток у 2026 — gemma4:2b (E2B варіант від Google).
Це єдина sub-4B модель яка більш-менш надійно викликає tools завдяки
нативній підтримці function calling в архітектурі.
Але «більш-менш» — це все одно не production. Для edge-пристроїв
або MVP де збій не критичний — ок. Для реального агента — ні.
Якщо у тебе є тільки 4–6 GB RAM і ти хочеш спробувати tool calling —
llama3.2:3b або gemma4:2b дадуть відчуття механіки.
Але не будуй на цьому продукт.
7–8B: «золота середина» для локального розгортання
Це мій робочий діапазон. На Mac M1 16 GB я розробляю агентний пайплайн
для AskYourDocs
саме з qwen3:8b (5.2 GB) і nomic-embed-text (274 MB) паралельно —
обидві моделі в RAM одночасно, без свопу на диск.
Чому 7–8B — практична межа для більшості задач:
Вміщуються у 6–8 GB VRAM або 8–16 GB системної RAM
Дають 70–85% надійності tool calling на типових бізнес-запитах
Запускаються на більшості сучасних ноутбуків і MacBook без додаткового заліза
Single-tool і базовий multi-tool — стабільно. Складні 3+ tool ланцюги — вже гірше.
qwen3:8b і llama3.1:8b — стандартний вибір для цього класу.
Якщо треба обрати між ними: llama3.1:8b якщо важлива сумісність
зі Spring AI / LangChain і швидкий TTFT. qwen3:8b якщо важлива
вища надійність і є час на налаштування thinking mode.
Критичне застереження про своп: якщо модель не вміщується
у RAM і починає свопити на диск — швидкість генерації падає з 15–25 tok/s
до 1–3 tok/s. Для агента це означає 10–30 секунд на один tool call
замість 1–2. На практиці це робить агента непридатним для real-time взаємодії.
Перевір після завантаження:
ollama ps
# NAME SIZE PROCESSOR UNTIL
# qwen3:8b 5.5GB 100% GPU 4 minutes from now
# ↑ якщо тут CPU або частково CPU — модель свопить
14B+: для складних агентів і production
Якщо 8B дає 80–85% надійності — чи варто переходити на 14B?
Залежить від задачі. Ось де різниця відчутна:
Сценарій
8B достатньо?
Коментар
Single tool, чіткий запит
✅ Так
Різниця між 8B і 14B мінімальна
2–3 tools, типові бізнес-запити
✅ Здебільшого
8B дає ~80%, 14B — ~88%
Ambiguous запит (незрозуміло який tool)
⚠️ Частково
14B значно рідше обирає неправильний tool
Hallucinated arguments (вигадані значення)
⚠️ Бувають
14B помиляється з аргументами рідше на ~30%
Multi-step агент (5+ кроків)
❌ Нестабільно
8B частіше «зависає» або йде в loop після 3–4 кроків
Production де збій = гроші/репутація
❌ Ризиковано
14B+ або хмарна модель (OpenRouter, Anthropic)
qwen3:14b (~9 GB) — оптимальний крок вгору від 8B:
більша точність при помірному збільшенні розміру.
gemma4:26b (MoE, 4B параметрів активних на токен) —
найкращий вибір якщо є 20+ GB VRAM: якість 26B при споживанні ресурсів
значно нижчому ніж у dense 26B моделей.
У своєму production-стеку для
AskYourDocs
я не використовую локальні моделі на сервері — Railway не дає GPU.
Для production я використовую OpenRouter:
deepseek/deepseek-chat для стандартних клієнтів і
anthropic/claude-3.5-sonnet для юридичних клієнтів де потрібна
максимальна точність при роботі з документами.
Локальний Ollama — тільки для розробки і тестування нових tools
перед деплоєм. Це чесна відповідь на питання «що використовувати в продакшні».
Практичне правило: алгоритм вибору
Замість загальних рекомендацій — конкретний алгоритм який я використовую:
Починай з llama3.1:8b або qwen3:8b залежно від заліза.
Запусти 20 тестових запитів зі своїм реальним набором tools.
Підрахуй скільки разів прийшов валідний tool_calls.
Якщо менше 80% — спочатку перепиши description функцій. Повтори тест.
Якщо після покращення description все одно менше 80% — переходь на 14B.
Якщо і 14B нестабільний на складних multi-step сценаріях — розглядай хмарну модель для production.
З мого досвіду: у половині випадків коли «модель не викликає tools» —
проблема в поганому description, а не в розмірі моделі.
Виправлення опису функції дешевше ніж перехід на більшу модель.
Перевір це спочатку.
Типові помилки і як їх діагностувати
Більшість помилок з tool calling виглядають однаково: HTTP 200, порожній tool_calls,
і повна тиша у логах. Нижче — сім конкретних сценаріїв які я зустрічав особисто
або які регулярно з'являються у GitHub Issues Ollama. Для кожного — діагноз і рішення.
Помилка 1. Модель ігнорує tools і відповідає текстом
Як виглядає: відправляєш запит з tools, отримуєш нормальну текстову відповідь. tool_calls у відповіді немає або порожній масив.
Три причини в порядку частоти:
Модель не підтримує tool calling нативно — перевір ollama show <model>, шукай tools у Capabilities
Опис функції (description) нечіткий — модель не розуміє коли її викликати
Фреймворк (Spring AI, LangChain) не передає tools у правильному форматі до Ollama
Діагностика — ізолюй фреймворк: протестуй напряму через curl.
Якщо curl повертає tool_calls — проблема у фреймворку.
Якщо ні — проблема у моделі або описі функції.
curl http://localhost:11434/api/chat \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3:8b",
"messages": [{"role": "user", "content": "Яка погода у Харкові?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Отримати поточну погоду для будь-якого міста. Викликай цей tool ЗАВЖДИ коли питають про погоду.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "Назва міста"}
},
"required": ["city"]
}
}
}],
"stream": false
}' | python3 -m json.tool
Помилка 2. Модель повертає JSON у текстовому блоці замість tool_calls
Це промпт-шлях у дії (секція 2). Ollama не зміг передати tools через нативні токени
і вставив їх у системний промпт як текст. Модель відповіла «як могла» —
намагаючись повторити формат з інструкції.
Чому не варто парсити content вручну:
формат непередбачуваний. Іноді ```json```, іноді просто {...},
іноді ключі називаються по-іншому ("tool" замість "name").
Будь-який парсер буде крихким.
Рішення: замінити модель на ту що має tools у Capabilities.
Це єдине надійне рішення.
Помилка 3. Невалідний або неповний JSON у аргументах
Як виглядає:tool_calls є, але аргументи не те що очікуєш:
відсутні обов'язкові поля, неправильний тип, або null там де має бути значення.
Найчастіша причина — мінімальний опис параметрів:
// ❌ Погано — модель не знає що передати
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
}
}
// ✅ Добре — детальний опис з прикладом і required
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Назва міста українською або англійською. Наприклад: 'Харків' або 'Kharkiv'"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Одиниці температури. За замовчуванням celsius."
}
},
"required": ["city"]
}
Поле required — не опціональне. Без нього модель може вирішити
що всі параметри необов'язкові і не передасть жодного.
Навіть якщо логічно зрозуміло що city потрібне — явно вкажи це у схемі.
Помилка 4. Нескінченний loop — модель викликає той самий tool знову і знову
Як виглядає: агент викликає searchDocuments,
отримує результат, і… знову викликає searchDocuments з тим самим запитом.
І знову. І знову. Без зупинки.
Причина: модель не отримала чіткого сигналу що задачу вирішено.
Вона бачить результат tool у messages, але не розуміє що тепер треба дати фінальну відповідь —
і продовжує генерувати наступний крок.
Два рішення:
1. Системний промпт з явною інструкцією:
Ти — агент який відповідає на питання користувача.
У тебе є доступ до інструментів для пошуку інформації.
Правила:
- Викликай tool тільки якщо потрібна зовнішня інформація
- Після отримання результату від tool — одразу давай фінальну відповідь
- Не викликай один і той самий tool двічі в одному діалозі
- Якщо отримав результат — НЕ роби додаткових викликів, одразу відповідай
2. Ліміт кроків на рівні коду (надійніше):
// Java: захист від нескінченного циклу
int maxSteps = 5;
int step = 0;
while (step < maxSteps) {
var response = callOllama(messages);
var toolCalls = response.getMessage().getToolCalls();
if (toolCalls == null || toolCalls.isEmpty()) {
// Модель дала фінальну відповідь — виходимо
return response.getMessage().getContent();
}
// Виконуємо tool calls і додаємо результати в messages
executeToolCalls(toolCalls, messages);
step++;
}
// Якщо досягли ліміту — повертаємо що є
log.warn("Agent reached max steps limit: {}", maxSteps);
return "Не вдалося завершити за відведену кількість кроків.";
Помилка 5. Tool calling не працює у Spring AI 2.0.0-M3 з Ollama — моя особиста
Це та сама ситуація яку я описав у секції 3: я підключив qwen3:8b
через Spring AI і модель просто відповідала текстом. Curl давав правильний
tool_calls — значить модель підтримує. Проблема була у Spring AI.
Конкретно: Spring AI 2.0.0-M3 має відоме обмеження —
ToolCallingChatOptions не завжди коректно серіалізує tools
у формат який Ollama очікує для нативного виклику.
Частина конфігурацій передавала tools у форматі специфічному для OpenAI,
а не для Ollama — і Ollama мовчки ігнорував їх або переходив на промпт-шлях.
Що допомогло:
// ❌ Не завжди спрацьовує з Ollama
ToolCallingChatOptions options = ToolCallingChatOptions.builder()
.toolCallbacks(toolCallbacks)
.build();
// ✅ Передавай tools через стандартний Prompt
List<Message> messages = buildMessages(question);
Prompt prompt = new Prompt(messages,
OllamaChatOptions.builder()
.model("qwen3:8b")
.build()
);
// tools реєструй через @Tool анотацію на методах,
// не через ToolCallingChatOptions
Помилка 6. Модель «вигадує» аргументи яких немає (hallucinated arguments)
Як виглядає:tool_calls є, аргументи є,
але значення не відповідають запиту. Наприклад, користувач питає про Харків —
а модель передає "city": "Kyiv". Або передає "date": "2024-01-01"
хоча ніякої дати в запиті не було.
Причина: мала модель (до 8B) при неоднозначному запиті
«заповнює» відсутні аргументи своїми здогадками замість того щоб
або запитати у користувача, або передати порожнє значення.
Рішення — три підходи:
Валідація аргументів перед виконанням: перевіряй що отримані аргументи логічно відповідають запиту користувача перед тим як передавати їх у реальну функцію
Обов'язкові поля з enum: якщо параметр має обмежений набір значень — завжди вказуй "enum": [...]. Модель значно рідше вигадує значення якщо бачить дозволений список
Перехід на 14B: hallucinated arguments — один з основних симптомів де 14B суттєво краще 8B
Помилка 7. Cold start — перший запит займає 10–30 секунд
Як виглядає: перший запит після запуску Ollama або після тривалої паузи
займає в рази довше ніж наступні. Агент «завис» на першому кроці.
Причина: модель вивантажилась з RAM (за замовчуванням через 5 хвилин
після останнього запиту) і тепер завантажується знову — це займає 5–15 секунд
залежно від розміру моделі і швидкості диска.
Рішення — keep_alive:
// У кожному запиті — тримати модель в RAM 30 хвилин
{
"model": "qwen3:8b",
"messages": [...],
"tools": [...],
"keep_alive": "30m" // або -1 щоб тримати постійно
}
// Або глобально через змінну середовища:
// OLLAMA_KEEP_ALIVE=30m ollama serve
Для агентного пайплайну де запити приходять пачками — "keep_alive": "30m"
стандартне рішення. Для одиничних запитів або batch-задач де RAM важлива —
"keep_alive": 0 вивантажить модель одразу після відповіді.
Швидка таблиця діагностики
Симптом
Перша перевірка
Найімовірніша причина
Відповідь текстом, немає tool_calls
ollama show <model> → є tools?
Модель без нативної підтримки або поганий description
JSON у content, не у tool_calls
Перевір capabilities моделі
Промпт-шлях — замінити модель
curl дає tool_calls, фреймворк — ні
Перевір як фреймворк серіалізує tools
Spring AI / LangChain передає tools у неправильному форматі
Неповні або неправильні аргументи
Перевір required і description
Мінімальний опис параметрів або маленька модель (до 8B)
Нескінченний loop
Перевір системний промпт
Немає інструкції «після результату — давай відповідь»
Вигадані значення аргументів
Перевір enum у схемі
Модель заповнює відсутні дані здогадками — 8B частіше ніж 14B
Перший запит 10–30 секунд
ollama ps — чи є модель у RAM?
Cold start — додай keep_alive
Яка найнадійніша модель для tool calling на Mac з 16 GB RAM?
Залежить від того що важливіше — надійність чи можливість запускати RAG паралельно.
Якщо тільки агент без RAG:gemma4:latest (9.6 GB) —
найвища надійність у своєму класі (~90% на 20 тестових запитах).
Google проектував Gemma 4 з нативним function calling від початку,
тому multi-tool спрацьовує стабільніше ніж у конкурентів того ж розміру.
Якщо агент + RAG паралельно:qwen3:8b (5.2 GB) +
nomic-embed-text (274 MB) — обидві вміщуються без свопу на M1 16 GB
(разом ~5.5 GB, залишається буфер). Надійність ~85% — трохи нижча ніж Gemma 4,
але для більшості бізнес-задач достатньо.
Я особисто використовую саме цю комбінацію для локальної розробки AskYourDocs:
qwen3:8b як агент і nomic-embed-text для ембедингів.
Обидві постійно в RAM, без cold start між запитами.
Якщо потрібна вища точність і RAM дозволяє:qwen3:14b (~9 GB) —
але тоді паралельно запускати RAG-модель стане щільно, можливий своп.
Як перевірити чи підтримує модель tool calling нативно?
Один крок — ollama show:
ollama show qwen3:8b
# Model
# arch qwen3
# parameters 8.2B
# context length 40960
#
# Capabilities
# completion
# tools ← є — нативна підтримка
# thinking
Якщо хочеш перевірити одразу кілька моделей зі своєї колекції:
# Перевірити всі встановлені моделі на наявність tool calling
ollama list | awk 'NR>1 {print $1}' | while read model; do
result=$(ollama show "$model" 2>/dev/null | grep -c "tools")
if [ "$result" -gt 0 ]; then
echo "✅ $model — tools підтримуються"
else
echo "❌ $model — tools відсутні"
fi
done
Після цього — живий тест через curl (1 хвилина) щоб підтвердити на практиці. Деталі у секції 4.
Чи можна змусити модель без нативного tool calling все одно викликати tools?
Технічно — так. Детальний системний промпт де описуєш формат JSON Schema
і просиш відповідати у чіткій структурі іноді спрацьовує:
system: """
Коли потрібна зовнішня інформація — відповідай ТІЛЬКИ у форматі:
{"tool": "назва_функції", "arguments": {"параметр": "значення"}}
Доступні функції: get_weather(city: string), get_rate(currency: string)
Нічого більше не пиши — тільки JSON.
"""
На практиці — нестабільно. З мого досвіду з mistral-nemo:
у ~30% запитів модель повертала щось схоже на JSON у content.
Але формат міг відрізнятись від запиту до запиту,
ключі іноді називались інакше ніж описано, іноді приходив неповний JSON.
Парсер для цього складніше підтримувати ніж просто замінити модель.
Коли промпт-підхід виправданий: якщо у тебе один простий tool,
чіткі запити і MVP де швидкість розробки важливіша за надійність.
Для production — не рекомендується. Заміна моделі на qwen3:8b
або llama3.1:8b займе 30 хвилин і вирішить проблему назавжди.
Mistral підтримує tool calling?
Залежить від версії — і це головна пастка:
Модель
Tool calling
Перевірка
mistral:7b-instruct-v0.3
✅ Нативний
tools є у capabilities
mistral-small:latest (Small 3.1)
✅ Нативний
tools є у capabilities
mistral-nemo:latest
❌ Промпт-шлях
tools відсутній у capabilities
mixtral:8x7b
⚠️ Часткова
Залежить від версії тегу
mistral-nemo:latest є в моїй колекції (7.1 GB) — я перевіряв особисто.
Відмінна модель для текстових задач, але для агентів — ні.
Якщо хочеш Mistral для tool calling — бери mistral-small:latest,
не Nemo. І завжди перевіряй конкретну версію через ollama show
перед тим як будувати пайплайн.
DeepSeek-R1 підходить для агентів?
Підходить — але з чіткою сферою застосування. Це не «загальний» агент,
це агент для задач де важлива правильність рішення, а не швидкість реакції.
Latency: перший токен у tool_calls з'являється
через 3–10 секунд (залежно від розміру моделі і складності запиту) —
бо спочатку генерується <think> блок.
Для real-time чату де користувач чекає відповідь — це забагато.
Для batch-обробки документів де ніхто не дивиться на годинник — норм.
Де виграє: ambiguous запити де незрозуміло який tool викликати.
Наприклад, «перевір чи договір відповідає законодавству» —
модель має вирішити між checkCompliance і extractKeyFacts.
DeepSeek-R1 завдяки thinking рідше помиляється з таким вибором.
Мій висновок: для юридичних клієнтів AskYourDocs де документи
складні і помилка у виборі tool коштує — я б розглядав DeepSeek-R1:14b.
Для звичайних клієнтів де важлива швидкість — Qwen3 або Llama 3.1.
Чому curl повертає tool_calls, а Spring AI — ні?
Це найбільш заплутана ситуація і я сам через неї пройшов.
Коли curl з тим самим запитом і тою самою моделлю повертає правильний
tool_calls, а Spring AI — текст, це майже завжди означає
що фреймворк передає tools не у тому форматі.
У Spring AI 2.0.0-M3 конкретна проблема: ToolCallingChatOptions
в деяких конфігураціях серіалізує tools у формат OpenAI, а не у формат
який Ollama очікує для нативного виклику. Ollama мовчки переходить
на промпт-шлях — і модель відповідає текстом.
Діагностика — увімкни debug логування запиту до Ollama:
Знайди у логах тіло запиту і перевір чи є там поле tools
у правильному форматі. Якщо tools немає або формат відрізняється
від того що ти передаєш у curl — проблема у серіалізації фреймворку.
Яка різниця між qwen3:8b і qwen3-ua:latest для tool calling?
qwen3-ua:latest є в моїй колекції (5.2 GB) — це адаптована версія
Qwen3 з покращеною підтримкою української мови. Для текстових задач українською —
помітно краща якість відповідей.
Але для tool calling — базовий qwen3:8b стабільніший.
З моїх тестів: qwen3:8b давав ~85% надійності,
qwen3-ua:latest — ~75% на тому самому наборі запитів.
Multi-tool у UA-версії спрацьовував через раз.
Мій підхід для україномовних проєктів: qwen3:8b для агентної частини
(tool calling), і налаштування мови через системний промпт
(«Відповідай виключно українською мовою»).
Базова модель розуміє українські запити — просто генерує відповіді англійською
якщо не вказати мову явно.
Скільки tools можна передати в одному запиті?
Ollama формально не обмежує кількість tools у запиті.
Але на практиці є межа де якість починає падати — і вона залежить від розміру моделі.
Розмір моделі
Рекомендована кількість tools
Що відбувається при перевищенні
До 4B
1–2 tools
Модель ігнорує більшість tools, викликає перший або жодного
7–8B
3–5 tools
При 6+ починаються пропуски і неправильний вибір
14B+
до 8–10 tools
Стабільно на більшості запитів
У AskYourDocs у мене 5 tools: searchDocuments, extractKeyFacts,
findDeadlines, extractContacts, checkCompliance.
На qwen3:8b це на межі — інколи модель не викликає checkCompliance
на запитах де він потрібен. Якщо б інструментів було 8–10 — переходив би на 14B.
Висновки
Перевіряй capabilities перед вибором:ollama show <model> одразу покаже чи є нативна підтримка tools.
Для 8 GB RAM:qwen3:8b або llama3.1:8b — надійний старт.
Для Mac 16 GB + RAG:qwen3:8b + nomic-embed-text — обидві вміщуються без свопу.
Для максимальної надійності tool calling:gemma4:latest (якщо є 12+ GB RAM) або gemma4:26b (20+ GB).
Mistral Nemo і Phi-4 — відмінні моделі для своїх задач, але не для agents з tools.
Якщо модель ігнорує tools — спочатку тестуй через curl напряму, щоб відокремити проблему фреймворку від проблеми моделі.
В продакшні з складними агентними пайплайнами — qwen3:14b або gemma4:26b. Різниця у надійності між 8B і 14B+ відчутна при multi-tool і довгих ланцюгах викликів.
Tool calling в Ollama — одна з найбільш неочевидних фіч локальних моделей.
Не тому що API складний. А тому що між «модель підтримує tools» у документації
і «модель стабільно викликає tools у продакшні» — велика різниця яку
можна виявити тільки під навантаженням.
Одні моделі...
12 лютого 2026 року OpenAI випустила GPT-5.3-Codex-Spark — і більшість розробників одразу запитали одне й те саме: «Це новий додаток? Мені треба щось перевстановлювати?» Ні. Spark — це модель всередині Codex App яку ти вже маєш. Просто інша модель у model picker — але з принципово іншим принципом...
OpenAI Codex у 2026 році — це не той інструмент, про який ви, можливо, читали кілька років тому. Оригінальний Codex API (2021–2023) був моделлю для автодоповнення коду на базі GPT-3, яка живила ранні версії GitHub Copilot. OpenAI закрила той API у березні 2023 року. Те, що існує сьогодні —...
Ollama — це не тільки CLI-інструмент для запуску моделей у терміналі.
Це повноцінний локальний сервер з REST API, який слухає на порту 11434
і приймає запити від будь-якого застосунку — Spring Boot, Node.js, Python,
або будь-якої мови з підтримкою HTTP. У цій статті — повний практичний...
Питання «Ollama чи ChatGPT?» — неправильне питання.
Правильне: «яку задачу я зараз вирішую — і де її краще вирішувати?»
Ця стаття не про те, що краще. Вона про те, як обирати без фанатизму.
Якщо ще не знайомий з Ollama —
почни з вступної статті про те, що таке Ollama і навіщо вона...
TL;DR за 30 секунд: DeepSeek V4 Pro — найбільша open-weight модель у світі: 1.6T параметрів (49B активних), контекст 1M токенів, MIT-ліцензія. Вийшла 24 квітня 2026 як preview. Коштує $3.48/M output токенів — у 7 разів дешевше за GPT-5.5 і в 6 разів дешевше за Claude Opus 4.7. На...