← Все статьи

Локальный ИИ через FastAPI и Ollama: от модели к безопасному API

Как обернуть локальную LLM в FastAPI, ограничить выполнение SQL и не потерять скорость на CPU.

Локальный ИИ через FastAPI и Ollama: от модели к безопасному API
Содержание

Коротко

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

Главный результат здесь не сама модель, а путь от эксперимента на ноутбуке к сервису, который можно вызвать по HTTP и при этом не дать ему испортить базу данных.

Что произошло

Вокруг модели Qwen2.5-Coder-3B-Instruct собрали шлюз из шести конечных точек: проверка состояния, получение списка схем и таблиц, преобразование вопроса в SQL, а также выполнение запроса. Самый удобный маршрут принимает вопрос и возвращает строки из базы одним вызовом.

Сервис разделён на небольшие модули: настройки, проверку X-API-Key, клиент Ollama, получение описания SQLite, исполнитель SQL и контракты Pydantic. Для запуска не понадобились сложные средства оркестрации: это HTTP-сервер, который обращается к серверу модели.

На тестовом наборе медианная задержка составила 17 секунд, диапазон — от 9 до 61 секунды. Простые агрегаты и соединения до четырёх таблиц модель строила уверенно, а оконные функции оказались её заметным ограничением.

Почему это важно

Эндпоинт «вопрос — SQL — результат» опаснее обычного генератора текста. Ошибочный ответ может стать командой к данным, поэтому автор не ограничился инструкцией модели «не меняй базу».

Исполнение защищено пятью независимыми слоями:

  1. Регулярные выражения отклоняют DROP, DELETE, UPDATE, INSERT, ALTER и другие запрещённые команды.
  2. Из строки берётся только первое SQL-выражение, чтобы блокировать конструкцию вида SELECT ...; DROP ....
  3. Соединение с SQLite открывается в режиме mode=ro, поэтому сама файловая система не разрешает запись.
  4. Тайм-аут останавливает слишком долгие запросы.
  5. Ограничение числа строк не даёт случайно вернуть всю большую таблицу.

В шести проверках с вредоносными и некорректными запросами нарушений безопасности не было. Такой результат не отменяет аудит и разграничение доступа, но показывает правильный принцип: ограничения должны существовать ниже уровня LLM.

На практике

Самым дорогим местом при работе модели на CPU оказался размер контекста. Для схемы из 16 таблиц и 135 столбцов первоначальное описание с примерами значений занимало до 14 800 символов; часть запросов не укладывалась даже в пять минут.

Решение — не выбрасывать все примеры, а отсеивать бесполезные. Столбцы с именами, почтой, URL, комментариями, JSON и другими свободными текстами исключаются по имени. Для остальных сначала считается число уникальных значений: если их больше 20, образцы тоже не добавляются в инструкцию модели.

После такой фильтрации описание сократилось с 9 800 до 8 200 символов, а число примеров — с 202 до 96. Запросы к схеме стали завершаться за 10–32 секунды. Для локального запуска это важнее тонкой настройки: размер входного текста прямо определяет время ответа.

Если вы строите похожий API, начните с малого:

  1. Открывайте рабочую БД только для чтения и отделяйте её от исходных данных.
  2. Проверяйте SQL до исполнения, ограничивайте время и размер результата.
  3. Передавайте модели только релевантные таблицы и компактные примеры допустимых значений.
  4. Измеряйте не только точность SQL, но и задержку, тайм-ауты, ошибки синтаксиса и попытки опасных операций.
  5. Честно фиксируйте границы модели: для сложных аналитических запросов может понадобиться более крупная модель или дополнительная проверка.

Итог

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

3-миллиардная модель ещё не заменяет аналитика для оконных функций и сложных условий. Зато она уже способна закрыть часть задач отчётности, если оставить ей только безопасный путь к данным и заранее обозначить пределы применимости.