← Усі статті

Локальний ШІ через FastAPI та Ollama: від моделі до безпечного API

Як обгорнути локальну LLM у FastAPI, обмежити виконання SQL і не втратити швидкість на CPU.

Локальний ШІ через FastAPI та Ollama: від моделі до безпечного API
Зміст

Коротко

Автор проєкту перетворив донавчену 3-мільярдну модель для генерації SQL на локальний API з FastAPI та Ollama. Сервіс працює на CPU, відповідає на запитання до SQLite природною мовою і в 73% із 22 робочих запитів згенерував коректний SQL.

Важливий тут не лише запуск моделі на ноутбуці. Модель отримала HTTP-інтерфейс, який може викликати інша програма, але не дістає необмеженого доступу до бази даних.

Що сталося

Навколо Qwen2.5-Coder-3B-Instruct зібрали шлюз із шістьма кінцевими точками: перевірка стану, перелік схем і таблиць, перетворення запитання на SQL, виконання SQL та спільний виклик «запитання — результат».

Застосунок навмисно невеликий: налаштування, перевірка X-API-Key, клієнт Ollama, отримання опису SQLite, виконавець SQL і моделі запитів та відповідей Pydantic. У шляху обслуговування немає складних засобів оркестрації — це HTTP-сервер, що звертається до сервера моделі.

На 22 запитах медіанна затримка становила 17 секунд, а діапазон — від 9 до 61 секунди. Модель упевнено виконувала агрегації та з’єднання до чотирьох таблиць, але віконні функції залишилися її помітним обмеженням.

Чому це важливо

Кінцева точка, що перетворює запитання на SQL і виконує його, має більшу поверхню помилок, ніж звичайний генератор тексту. Самої інструкції ШІ «не змінюй дані» недостатньо: його вивід треба обмежувати на рівні сервісу й бази.

У проєкті застосовано п’ять незалежних захисних шарів:

  1. Регулярні вирази відхиляють DROP, DELETE, UPDATE, INSERT, ALTER та інші заборонені команди.
  2. Із рядка залишається лише перша SQL-команда, що зупиняє конструкції на кшталт SELECT ...; DROP ....
  3. З’єднання з SQLite відкривається в режимі mode=ro, тож сама база не дозволяє запис.
  4. Тайм-аут обмежує надто довгі запити.
  5. Ліміт рядків не дає випадково повернути всю велику таблицю.

Шість перевірок зі шкідливими та некоректними запитами не виявили порушень безпеки. Це не замінює розмежування доступу та перевірку коду, проте підтверджує корисний принцип: SQL від LLM потребує контролю нижче за рівень моделі.

На практиці

Найбільше часу під час роботи на CPU забирав розмір контексту зі схемою. Початковий опис схеми сервісу з 16 таблицями й 135 стовпцями сягав 14 800 символів, а деякі запити не завершувалися за кілька хвилин.

Замість повного вилучення прикладів проєкт їх відфільтровує. Стовпці з іменами, електронною поштою, URL, коментарями, JSON та іншим вільним текстом виключаються за назвою. Для решти текстових стовпців приклади додаються лише за малої кількості унікальних значень.

Це скоротило один опис схеми з 9 800 до 8 200 символів, а кількість прикладів — із 202 до 96. Після цього запити виконувалися за 10–32 секунди. Для CPU вилучення зайвого контексту — не дрібна оптимізація, а умова, за якої API взагалі відповідає.

Для подібного сервісу варто:

  1. Відкривати бази лише для читання та ізолювати їх від систем, які можуть записувати дані.
  2. Перевіряти згенерований SQL, обмежувати час виконання та число рядків у відповіді.
  3. Передавати моделі лише доречні таблиці й компактні приклади категоріальних значень.
  4. Вимірювати затримку, тайм-аути, помилки синтаксису та спроби небезпечних операцій разом із точністю SQL.
  5. Фіксувати межі моделі: для складної аналітики може знадобитися більша модель або додаткова перевірка.

Підсумок

Локальна LLM стає корисною в роботі, коли має зрозумілий і безпечний інтерфейс, а не просто вміє генерувати відповідь. FastAPI та Ollama дають змогу створити такий сервіс без рахунку за зовнішній вивід моделі, проте результат визначає архітектура навколо неї: захист SQL, компактний контекст і вимірювані межі.

3-мільярдна модель не замінить аналітика для віконних функцій чи заплутаної бізнес-логіки. Але вона вже може допомагати у контрольованому сценарії звітності, якщо має безпечний шлях до даних і відомі обмеження.