# Open WebUI Pipelines: как перейти на Functions без потери поведения

Источник: https://modelium.tech/zhurnal/open-webui-pipelines-functions/

Документация Open WebUI относит Pipelines к legacy и для новой разработки рекомендует Functions: Pipeline pipe переносится в Pipe Function, а pipeline filter — в Filter Function. Это не автоматический импорт старого Python-файла: нужно проверить сигнатуры, зависимости, настройки и права исполнения, затем сравнить ответы на одинаковых тестовых запросах. Functions исполняются внутри процесса Open WebUI, поэтому изоляция отдельного Pipelines-сервера при переносе исчезает.

**Документы просмотрены 29 сентября 2026 года**, закреплённый commit `bd62c17a83d0fd6ddf8ae7aae55599181a85fab4`. Этот материал описывает перенос по документации, а не успешный прогон Modelium. Сверьте возможности и интерфейс со своей установленной версией Open WebUI. Числовая частотность запроса не измерялась.

## Нужно ли выключать Pipelines прямо сейчас?

Нет автоматического требования немедленно отключать действующий сервер. Официальная документация помечает Pipelines как legacy, сохраняет страницы для существующих установок и направляет **новую** разработку к Functions или внешним инструментам [s1](#src-s1). Pipelines — отдельный сервис, подключаемый к Open WebUI как OpenAI-совместимое соединение. В отличие от него Function хранится в базе Open WebUI и загружается в Python-процесс приложения [s1](#src-s1)[s4](#src-s4)[s7](#src-s7). Это изменение границы исполнения: при миграции нельзя считать новую Function «тем же контейнером с другим названием».

Вначале выпишите реальное назначение старого модуля: он создаёт модель/маршрутизирует вызовы, изменяет сообщение до или после модели, либо лишь вызывает внешний HTTP-сервис? Официальная карта замены: Pipeline **pipe** → Pipe Function; Pipeline **filter** → Filter Function; для внешнего HTTP-сервиса рассмотрите OpenAPI/MCP tool server, если задача — дать модели инструмент, а не менять жизненный цикл запроса [s1](#src-s1)[s2](#src-s2)[s3](#src-s3). Ни одно из соответствий не гарантирует запуск старого файла без изменений: тела запросов, значения Valves, зависимости и контракт ответа надо сверять по коду конкретного расширения [s4](#src-s4)[s5](#src-s5)[s6](#src-s6).

## Что сохранить до переноса?

Снимите список подключений Pipelines, копию исходного Python-кода, версии Open WebUI и отдельного Pipelines-сервера, настройки Valves, переменные среды, зависимости и список моделей/фильтров, на которые расширение назначено. Не экспортируйте токены в публичный репозиторий и не включайте реальные чаты в тестовые артефакты. Это предлагаемый порядок миграции, а не команда, исполнявшаяся на инсталляции Modelium. Отдельно запишите ожидаемое поведение на двух синтетических запросах — обычном и ошибочном — чтобы было с чем сравнивать новую реализацию.

При переносе изменится и управление: администратор создаёт Function через **Admin Panel → Functions**, кодом с верхнеуровневым классом `Pipe` или `Filter`, а Open WebUI определяет тип автоматически. Активность, глобальность, настройки Valves и привязка фильтра к конкретной модели настраиваются отдельно [s4](#src-s4). Простой перенос файла без проверки этих переключателей может дать либо невидимую модель, либо фильтр, действующий на все чаты.

## Как перенести Pipeline Pipe в Pipe Function?

Pipeline pipe предоставляет собственный ответ и появляется в выборе моделей; новый `class Pipe` тоже регистрируется как модель, а `pipe(body)` получает входной запрос и возвращает ответ. Официальное руководство показывает `async def pipe(self, body: dict)` и рекомендует async для будущей совместимости [s2](#src-s2)[s4](#src-s4)[s5](#src-s5). Сначала проверьте сам маршрут исполнения без провайдера и платных вызовов. Минимальный *тестовый* код Function:

class Pipe:    async def pipe(self, body: dict) -> str:        return "MIGRATION_TEST_OK"

Администратор создаёт отдельную Function в тестовом Open WebUI, сохраняет и включает её, выбирает появившуюся модель и отправляет синтетическое сообщение. Если в чате приходит ровно `MIGRATION_TEST_OK`, проверен лишь вызов этого тестового Pipe, **не работа старого Pipeline и не обращение к локальной LLM** [s4](#src-s4)[s5](#src-s5). Заменяйте заглушку перенесённой логикой только после ревью: разберите прежние `pipe()`-аргументы, преобразование `body`, обработку ошибок и тип ответа. Для нескольких моделей нужен отдельный `pipes()`; строки, генераторы и структурированные ответы имеют разные правила выдачи в Open WebUI [s5](#src-s5).

Если старый Pipeline сам вызывает инструменты агента, не транслируйте слепо `delta.tool_calls` в новый поток: документация предупреждает, что Open WebUI может воспринять их как просьбу выполнить инструмент повторно. Сначала решите, кто владеет выполнением, и проверьте один реальный вызов с трассировкой; красивый финальный ответ сам по себе не доказательство правильного маршрута [s2](#src-s2). Внешние API-ключи не кодируйте в исходник: руководство Function предлагает администраторские Valves для настроек и отдельный контроль секретов [s4](#src-s4)[s5](#src-s5).

## Как перенести Pipeline Filter без глобального воздействия?

Pipeline filter обрабатывал входящий `inlet` перед запросом модели и исходящий `outlet` после неё [s3](#src-s3). В Function верхнеуровневый `class Filter` предоставляет соответствующие методы, а более новые версии документации отдельно описывают `request` для *каждого* вызова модели и `stream` для потока. Не предполагайте, что `inlet` заменяет проверку на каждом ходе цепочки инструментов: сверяйте контракт установленной версии и именно ту точку, где нужны изменения [s4](#src-s4)[s6](#src-s6). Для начальной проверки области действия можно создать **пустой** тестовый Filter:

class Filter:    async def inlet(self, body: dict) -> dict:        return body    async def outlet(self, body: dict) -> dict:        return body

Этот код намеренно **ничего не фильтрует** и не является контролем безопасности. Администратор должен сделать Function активной и назначить её одной тестовой модели, не переключая `Global`; модельно-специфичная и глобальная области различаются [s4](#src-s4)[s6](#src-s6). Затем перенесите собственную логику с тестами: исходное сообщение до вызова, итоговый ответ, случаи отказа и повторные вызовы инструментов. Для переключаемого фильтра `self.toggle = True` означает выбор пользователем в интерфейсе, а не булев флаг, который надо читать внутри каждого `inlet` [s6](#src-s6). Не переносите обязательную проверку доступа в пользовательский переключатель: этот совет о проектировании, не гарантия безопасности Open WebUI.

## Что проверить перед отключением старого сервера?

- На синтетических входных данных сравните старую и новую версии **на одной версии модели/runtime**: выбранный маршрут, текст или поля ответа, ошибки, поток и число фактических вызовов инструмента. Оценка качества модели и скорости здесь не измерялась; это план испытаний, а не результат Modelium.

- Проверьте охват Filter на тестовой и нетестовой моделях, при отключении Function и после повторного входа. Для глобального Filter ожидается совсем иной охват, чем для привязанного к модели [s4](#src-s4)[s6](#src-s6).

- Проверьте исходящие адреса, зависимости, файлы и права учётной записи приложения. Functions исполняют произвольный Python-код **внутри** backend без песочницы; право создавать/изменять их оставьте только доверенным администраторам. Публичная библиотека расширений не равнозначна проверке кода [s7](#src-s7)[s8](#src-s8). Если прежний контейнер был намеренно изолирован, сохраните аналогичную границу в архитектуре или откажитесь от переноса данного модуля.

- Запишите идентификатор и код прежней версии, держите старое соединение отключаемым, а не удалённым до прохождения тестов. При регрессии выключите новую Function, верните прежнее соединение и повторите контрольный запрос. **Отключение не отменяет побочных действий кода при загрузке** (например, monkey-patch); если они были, нужен рестарт и отдельный разбор состояния backend [s7](#src-s7).

**Критерий приёмки:** один перенесённый тестовый Pipe или Filter даёт заранее записанный результат без лишних tool calls, не затрагивает чужие модели, а круг администраторов с правом установки расширений ограничен. Без этих наблюдений перенос не объявляется успешным. **Следующий шаг:** [подготовьте тестовый Open WebUI с локальной моделью](/zhurnal/open-webui/), перенесите один модуль и сохраните сравнение двух версий; для операционного контроля отдельно проверьте [возможности и пробелы audit log](/zhurnal/open-webui-audit-log/).

## Источники

1. [Open WebUI — Pipelines, overview (pinned documentation)](https://raw.githubusercontent.com/open-webui/docs/bd62c17a83d0fd6ddf8ae7aae55599181a85fab4/docs/features/extensibility/pipelines/index.mdx) — получено 2026-09-29
2. [Open WebUI — Pipelines Pipes (pinned documentation)](https://raw.githubusercontent.com/open-webui/docs/bd62c17a83d0fd6ddf8ae7aae55599181a85fab4/docs/features/extensibility/pipelines/pipes.md) — получено 2026-09-29
3. [Open WebUI — Pipelines Filters (pinned documentation)](https://raw.githubusercontent.com/open-webui/docs/bd62c17a83d0fd6ddf8ae7aae55599181a85fab4/docs/features/extensibility/pipelines/filters.md) — получено 2026-09-29
4. [Open WebUI — Functions, types and administration (pinned documentation)](https://raw.githubusercontent.com/open-webui/docs/bd62c17a83d0fd6ddf8ae7aae55599181a85fab4/docs/features/extensibility/plugin/functions/index.mdx) — получено 2026-09-29
5. [Open WebUI — Pipe Function, Python contract (pinned documentation)](https://raw.githubusercontent.com/open-webui/docs/bd62c17a83d0fd6ddf8ae7aae55599181a85fab4/docs/features/extensibility/plugin/functions/pipe.mdx) — получено 2026-09-29
6. [Open WebUI — Filter Function, hooks and scope (pinned documentation)](https://raw.githubusercontent.com/open-webui/docs/bd62c17a83d0fd6ddf8ae7aae55599181a85fab4/docs/features/extensibility/plugin/functions/filter.mdx) — получено 2026-09-29
7. [Open WebUI — Plugin loader under the hood (pinned documentation)](https://raw.githubusercontent.com/open-webui/docs/bd62c17a83d0fd6ddf8ae7aae55599181a85fab4/docs/features/extensibility/plugin/development/under-the-hood.mdx) — получено 2026-09-29
8. [Open WebUI — Plugin security and permissions (pinned documentation)](https://raw.githubusercontent.com/open-webui/docs/bd62c17a83d0fd6ddf8ae7aae55599181a85fab4/docs/features/extensibility/plugin/index.mdx) — получено 2026-09-29
