[PR #23898] [CLOSED] refactor: extract provider-facing helpers from routers into open_webui.clients #98469

Closed
opened 2026-05-16 01:16:46 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/23898
Author: @ashm-dev
Created: 4/20/2026
Status: Closed

Base: devHead: refactor/extract-provider-clients


📝 Commits (5)

  • 78c772f refactor: add clients package
  • 460e3a0 refactor: extract pipelines client from router
  • 4399ce6 refactor: extract memories client from router
  • 1fcd87e refactor: extract tasks client from router
  • 70a4cdb refactor: preserve original template fallback semantics

📊 Changes

10 files changed (+651 additions, -705 deletions)

View changed files

backend/open_webui/clients/__init__.py (+0 -0)
backend/open_webui/clients/memories.py (+173 -0)
backend/open_webui/clients/pipelines.py (+136 -0)
backend/open_webui/clients/tasks.py (+260 -0)
📝 backend/open_webui/routers/memories.py (+30 -162)
📝 backend/open_webui/routers/pipelines.py (+12 -172)
📝 backend/open_webui/routers/tasks.py (+35 -366)
📝 backend/open_webui/tools/builtin.py (+1 -1)
📝 backend/open_webui/utils/chat.py (+1 -1)
📝 backend/open_webui/utils/middleware.py (+3 -3)

📄 Description

Pull Request Checklist

Note to first-time contributors: Please open a discussion post in Discussions to discuss your idea/fix with the community before creating a pull request, and describe your changes before submitting a pull request.

This is to ensure large feature PRs are discussed with the community first, before starting work on it. If the community does not want this feature or it is not relevant for Open WebUI as a project, it can be identified in the discussion before working on the feature and submitting the PR.

Before submitting, make sure you've checked the following:

  • Target branch: Verify that the pull request targets the dev branch. PRs targeting main will be immediately closed.
  • Description: Provide a concise description of the changes made in this pull request down below.
  • Changelog: Ensure a changelog entry following the format of Keep a Changelog is added at the bottom of the PR description.
  • Documentation: Add docs in Open WebUI Docs Repository. Document user-facing behavior, environment variables, public APIs/interfaces, or deployment steps. — N/A, internal refactor with no user-facing, env, or public API surface changes.
  • Dependencies: Are there any new or upgraded dependencies? If so, explain why, update the changelog/docs, and include any compatibility notes. — No new or upgraded dependencies.
  • Testing: Perform manual tests to verify the implemented fix/feature works as intended AND does not break any other functionality. Include reproducible steps to demonstrate the issue before the fix. Test edge cases (URL encoding, HTML entities, types).
  • Agentic AI Code: Confirm this Pull Request is not written by any AI Agent or has at least gone through additional human review AND manual testing. — Human-reviewed and manually tested; no AI co-author on commits.
  • Code review: Have you performed a self-review of your code, addressing any coding standard issues and ensuring adherence to the project's coding standards?
  • Design & Architecture: Prefer smart defaults over adding new settings; use local state for ephemeral UI logic. Open a Discussion for major architectural or UX changes.
  • Git Hygiene: Keep PRs atomic (one logical change). Clean up commits and rebase on dev to ensure no unrelated commits (e.g. from main) are included. Push updates to the existing PR branch instead of closing and reopening.
  • Title Prefix: refactor.

Changelog Entry

Description

Internal, behavior-preserving refactor. The utils/ layer currently imports FastAPI endpoint-adjacent helpers directly from routers/ (14 top-level edges; e.g. utils/middleware.py imports process_pipeline_inlet_filter from routers/pipelines.py, query_memory from routers/memories.py, and five task-generation helpers from routers/tasks.py). This creates a package-level import cycle (routers ↔ utils) and forces any utility or test to drag in the full FastAPI router module just to call a helper.

This PR introduces a new open_webui.clients package and moves the pure (non-HTTP) helpers for pipelines, memories, and tasks into it. The routers become thin FastAPI wrappers that delegate to the client functions. External call sites (utils/middleware, utils/chat, tools/builtin, routers/tasks) are updated to import from open_webui.clients.*. No behavior changes — every endpoint URL, every response_model, every Pydantic form, and every error path is preserved.

This is the first of a planned series; subsequent PRs will do the same for images, files, retrieval, ollama, openai. This one is sized to be trivially reviewable on its own and to prove the pattern.

Motivation:

  • Break the utils → routers back-edges (14 of them today) that make open_webui/ a strongly-connected component at the package level.
  • Make utility code (the chat-completion pipeline in utils/middleware.py, 5000+ lines) unit-testable without instantiating FastAPI router state.
  • Lower cognitive load for new contributors: clients/ holds "what the code does", routers/ holds "how it's exposed over HTTP".

Scope of this PR:

  • New package: backend/open_webui/clients/ with pipelines.py, memories.py, tasks.py.
  • Routers pipelines.py, memories.py, tasks.py now import from clients/ and keep only their APIRouter / HTTP wrapper responsibilities.
  • utils/middleware.py, utils/chat.py, tools/builtin.py, routers/tasks.py updated to import helpers from clients/ instead of routers/.
  • Type annotations modernized on moved code to Python 3.11 style (X | None, list[...], dict[...]). Functional inputs/outputs unchanged.
  • ruff format --check passes on all changed files; ruff check passes on all changed files.

Explicitly out of scope:

  • images, files, retrieval, ollama, openai extractions — follow-up PRs, one per provider, to keep each review small.
  • No sharding of config.py or decomposition of utils/middleware.py (separate problems; separate PRs).
  • No changes to API surface, wire format, DB schema, migrations, or settings.

Added

  • backend/open_webui/clients/ package exposing pipelines, memories, and tasks helper modules for reuse by utils/ and tools/ without pulling in FastAPI router state.

Changed

  • backend/open_webui/routers/pipelines.py: get_sorted_filters, process_pipeline_inlet_filter, process_pipeline_outlet_filter moved to clients/pipelines.py. Endpoints (/list, /upload, /add, /delete, /, /{pipeline_id}/valves, /{pipeline_id}/valves/spec, /{pipeline_id}/valves/update) unchanged.
  • backend/open_webui/routers/memories.py: add_memory, query_memory, update_memory_by_id, and their Pydantic forms (AddMemoryForm, MemoryUpdateModel, QueryMemoryForm) moved to clients/memories.py; router endpoints (GET /, POST /add, POST /query, POST /reset, DELETE /delete/user, POST /{memory_id}/update, DELETE /{memory_id}) become thin delegators.
  • backend/open_webui/routers/tasks.py: generate_title, generate_follow_ups, generate_chat_tags, generate_image_prompt, generate_queries moved to clients/tasks.py; endpoints (/title/completions, /follow_up/completions, /tags/completions, /image_prompt/completions, /queries/completions) become thin delegators. generate_autocompletion, generate_emoji, generate_moa_response intentionally left in the router (not imported by utils/, so no layering win from moving them).
  • backend/open_webui/utils/middleware.py, utils/chat.py, tools/builtin.py: imports redirected from open_webui.routers.{pipelines,memories,tasks}open_webui.clients.{pipelines,memories,tasks}.

Deprecated

  • None.

Removed

  • None (all moved symbols remain accessible under their original public names via the router modules — endpoints still work exactly as before).

Fixed

  • None (intentional — no bug fixes bundled with this refactor).

Security

  • None. No new attack surface; no dependency changes; no credential or permission handling modified.

Breaking Changes

  • None. Internal import paths changed (routers.Xclients.X) only for code inside this repository. No external API, URL, or behavior changes. Third-party code that imports from open_webui.routers.memories import query_memory would need to switch to from open_webui.clients.memories import query_memory, but no public documentation advertises those as importable from routers/.

Additional Information

Review ergonomics: every commit is self-contained and bisect-safe.

70a4cdb72 refactor: preserve original template fallback semantics
1fcd87e56 refactor: extract tasks client from router
4399ce6ba refactor: extract memories client from router
460e3a081 refactor: extract pipelines client from router
78c772f1a refactor: add clients package

The final commit is a defensive tweak: an earlier draft replaced if CFG.TEMPLATE != '': template = CFG.TEMPLATE else: DEFAULT with template = CFG.TEMPLATE or DEFAULT. These diverge when the config value is None (original would pass None to the template renderer and raise TypeError; shortened form would silently use DEFAULT). The commit restores the exact != '' form to keep behavior bit-identical.

Verification performed:

  • ruff format --check . — no regressions; my files are clean (8 pre-existing format violations outside my scope left alone).
  • ruff check on all touched files — passes.
  • Static AST parse on every changed file — passes.
  • Import-graph audit — zero edges from open_webui.clients.* back to open_webui.routers.* (the whole point of the refactor).
  • Line-by-line diff review between each moved function's pre/post form; all endpoint decorators, response_models, status codes, log messages, error-handling branches, and dict insertion order verified identical.
  • Manual smoke test: chat completion (with and without pipeline filters), title generation, tags generation, follow-up generation, memory add/query/update/delete, pipelines upload path.

Related to:

  • Architecture map of backend/open_webui/ shows one 14-file SCC driven by utils ↔ routers back-edges (not a runtime cycle — all guarded by in-function lazy imports with # Import here to avoid circular imports). This PR removes 3 of those 14 top-level edges; follow-ups will address the rest.

Screenshots or Videos

  • N/A — no UI changes.

Contributor License Agreement

Note

Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/23898 **Author:** [@ashm-dev](https://github.com/ashm-dev) **Created:** 4/20/2026 **Status:** ❌ Closed **Base:** `dev` ← **Head:** `refactor/extract-provider-clients` --- ### 📝 Commits (5) - [`78c772f`](https://github.com/open-webui/open-webui/commit/78c772f1a63f62b4ef8957bb59ae29fc28b0f7e9) refactor: add clients package - [`460e3a0`](https://github.com/open-webui/open-webui/commit/460e3a081bcc1bda93a375c7dac56266ca5528d8) refactor: extract pipelines client from router - [`4399ce6`](https://github.com/open-webui/open-webui/commit/4399ce6ba1938b3c18aaf61b0597da73d4a8ef82) refactor: extract memories client from router - [`1fcd87e`](https://github.com/open-webui/open-webui/commit/1fcd87e561cbbea700e0b74aa7f54d7b4ad43ea9) refactor: extract tasks client from router - [`70a4cdb`](https://github.com/open-webui/open-webui/commit/70a4cdb72ac6d814f47a1ffb90c13df0229e3bb2) refactor: preserve original template fallback semantics ### 📊 Changes **10 files changed** (+651 additions, -705 deletions) <details> <summary>View changed files</summary> ➕ `backend/open_webui/clients/__init__.py` (+0 -0) ➕ `backend/open_webui/clients/memories.py` (+173 -0) ➕ `backend/open_webui/clients/pipelines.py` (+136 -0) ➕ `backend/open_webui/clients/tasks.py` (+260 -0) 📝 `backend/open_webui/routers/memories.py` (+30 -162) 📝 `backend/open_webui/routers/pipelines.py` (+12 -172) 📝 `backend/open_webui/routers/tasks.py` (+35 -366) 📝 `backend/open_webui/tools/builtin.py` (+1 -1) 📝 `backend/open_webui/utils/chat.py` (+1 -1) 📝 `backend/open_webui/utils/middleware.py` (+3 -3) </details> ### 📄 Description <!-- ⚠️ CRITICAL CHECKS FOR CONTRIBUTORS (READ, DON'T DELETE) ⚠️ 1. Target the `dev` branch. PRs targeting `main` will be automatically closed. 2. Do NOT delete the CLA section at the bottom. It is required for the bot to accept your PR. --> # Pull Request Checklist ### Note to first-time contributors: Please open a discussion post in [Discussions](https://github.com/open-webui/open-webui/discussions) to discuss your idea/fix with the community before creating a pull request, and describe your changes before submitting a pull request. This is to ensure large feature PRs are discussed with the community first, before starting work on it. If the community does not want this feature or it is not relevant for Open WebUI as a project, it can be identified in the discussion before working on the feature and submitting the PR. **Before submitting, make sure you've checked the following:** - [x] **Target branch:** Verify that the pull request targets the `dev` branch. **PRs targeting `main` will be immediately closed.** - [x] **Description:** Provide a concise description of the changes made in this pull request down below. - [x] **Changelog:** Ensure a changelog entry following the format of [Keep a Changelog](https://keepachangelog.com/) is added at the bottom of the PR description. - [x] **Documentation:** Add docs in [Open WebUI Docs Repository](https://github.com/open-webui/docs). Document user-facing behavior, environment variables, public APIs/interfaces, or deployment steps. — **N/A**, internal refactor with no user-facing, env, or public API surface changes. - [x] **Dependencies:** Are there any new or upgraded dependencies? If so, explain why, update the changelog/docs, and include any compatibility notes. — **No new or upgraded dependencies.** - [x] **Testing:** Perform manual tests to **verify the implemented fix/feature works as intended AND does not break any other functionality**. Include reproducible steps to demonstrate the issue before the fix. Test edge cases (URL encoding, HTML entities, types). - [x] **Agentic AI Code:** Confirm this Pull Request is **not written by any AI Agent** or has at least **gone through additional human review AND manual testing**. — **Human-reviewed and manually tested; no AI co-author on commits.** - [x] **Code review:** Have you performed a self-review of your code, addressing any coding standard issues and ensuring adherence to the project's coding standards? - [x] **Design & Architecture:** Prefer smart defaults over adding new settings; use local state for ephemeral UI logic. Open a Discussion for major architectural or UX changes. - [x] **Git Hygiene:** Keep PRs atomic (one logical change). Clean up commits and rebase on `dev` to ensure no unrelated commits (e.g. from `main`) are included. Push updates to the existing PR branch instead of closing and reopening. - [x] **Title Prefix:** `refactor`. # Changelog Entry ### Description Internal, behavior-preserving refactor. The `utils/` layer currently imports FastAPI endpoint-adjacent helpers directly from `routers/` (14 top-level edges; e.g. `utils/middleware.py` imports `process_pipeline_inlet_filter` from `routers/pipelines.py`, `query_memory` from `routers/memories.py`, and five task-generation helpers from `routers/tasks.py`). This creates a package-level import cycle (`routers ↔ utils`) and forces any utility or test to drag in the full FastAPI router module just to call a helper. This PR introduces a new `open_webui.clients` package and moves the pure (non-HTTP) helpers for **pipelines**, **memories**, and **tasks** into it. The routers become thin FastAPI wrappers that delegate to the client functions. External call sites (`utils/middleware`, `utils/chat`, `tools/builtin`, `routers/tasks`) are updated to import from `open_webui.clients.*`. No behavior changes — every endpoint URL, every `response_model`, every Pydantic form, and every error path is preserved. This is the first of a planned series; subsequent PRs will do the same for `images`, `files`, `retrieval`, `ollama`, `openai`. This one is sized to be trivially reviewable on its own and to prove the pattern. **Motivation:** - Break the `utils → routers` back-edges (14 of them today) that make `open_webui/` a strongly-connected component at the package level. - Make utility code (the chat-completion pipeline in `utils/middleware.py`, 5000+ lines) unit-testable without instantiating FastAPI router state. - Lower cognitive load for new contributors: `clients/` holds "what the code does", `routers/` holds "how it's exposed over HTTP". **Scope of this PR:** - New package: `backend/open_webui/clients/` with `pipelines.py`, `memories.py`, `tasks.py`. - Routers `pipelines.py`, `memories.py`, `tasks.py` now import from `clients/` and keep only their `APIRouter` / HTTP wrapper responsibilities. - `utils/middleware.py`, `utils/chat.py`, `tools/builtin.py`, `routers/tasks.py` updated to import helpers from `clients/` instead of `routers/`. - Type annotations modernized on moved code to Python 3.11 style (`X | None`, `list[...]`, `dict[...]`). Functional inputs/outputs unchanged. - `ruff format --check` passes on all changed files; `ruff check` passes on all changed files. **Explicitly out of scope:** - `images`, `files`, `retrieval`, `ollama`, `openai` extractions — follow-up PRs, one per provider, to keep each review small. - No sharding of `config.py` or decomposition of `utils/middleware.py` (separate problems; separate PRs). - No changes to API surface, wire format, DB schema, migrations, or settings. ### Added - `backend/open_webui/clients/` package exposing `pipelines`, `memories`, and `tasks` helper modules for reuse by `utils/` and `tools/` without pulling in FastAPI router state. ### Changed - `backend/open_webui/routers/pipelines.py`: `get_sorted_filters`, `process_pipeline_inlet_filter`, `process_pipeline_outlet_filter` moved to `clients/pipelines.py`. Endpoints (`/list`, `/upload`, `/add`, `/delete`, `/`, `/{pipeline_id}/valves`, `/{pipeline_id}/valves/spec`, `/{pipeline_id}/valves/update`) unchanged. - `backend/open_webui/routers/memories.py`: `add_memory`, `query_memory`, `update_memory_by_id`, and their Pydantic forms (`AddMemoryForm`, `MemoryUpdateModel`, `QueryMemoryForm`) moved to `clients/memories.py`; router endpoints (`GET /`, `POST /add`, `POST /query`, `POST /reset`, `DELETE /delete/user`, `POST /{memory_id}/update`, `DELETE /{memory_id}`) become thin delegators. - `backend/open_webui/routers/tasks.py`: `generate_title`, `generate_follow_ups`, `generate_chat_tags`, `generate_image_prompt`, `generate_queries` moved to `clients/tasks.py`; endpoints (`/title/completions`, `/follow_up/completions`, `/tags/completions`, `/image_prompt/completions`, `/queries/completions`) become thin delegators. `generate_autocompletion`, `generate_emoji`, `generate_moa_response` intentionally left in the router (not imported by `utils/`, so no layering win from moving them). - `backend/open_webui/utils/middleware.py`, `utils/chat.py`, `tools/builtin.py`: imports redirected from `open_webui.routers.{pipelines,memories,tasks}` → `open_webui.clients.{pipelines,memories,tasks}`. ### Deprecated - None. ### Removed - None (all moved symbols remain accessible under their original public names via the router modules — endpoints still work exactly as before). ### Fixed - None (intentional — no bug fixes bundled with this refactor). ### Security - None. No new attack surface; no dependency changes; no credential or permission handling modified. ### Breaking Changes - None. Internal import paths changed (`routers.X` → `clients.X`) only for code inside this repository. No external API, URL, or behavior changes. Third-party code that imports `from open_webui.routers.memories import query_memory` would need to switch to `from open_webui.clients.memories import query_memory`, but no public documentation advertises those as importable from `routers/`. --- ### Additional Information **Review ergonomics:** every commit is self-contained and bisect-safe. ``` 70a4cdb72 refactor: preserve original template fallback semantics 1fcd87e56 refactor: extract tasks client from router 4399ce6ba refactor: extract memories client from router 460e3a081 refactor: extract pipelines client from router 78c772f1a refactor: add clients package ``` The final commit is a defensive tweak: an earlier draft replaced `if CFG.TEMPLATE != '': template = CFG.TEMPLATE else: DEFAULT` with `template = CFG.TEMPLATE or DEFAULT`. These diverge when the config value is `None` (original would pass `None` to the template renderer and raise `TypeError`; shortened form would silently use `DEFAULT`). The commit restores the exact `!= ''` form to keep behavior bit-identical. **Verification performed:** - `ruff format --check .` — no regressions; my files are clean (8 pre-existing format violations outside my scope left alone). - `ruff check` on all touched files — passes. - Static AST parse on every changed file — passes. - Import-graph audit — zero edges from `open_webui.clients.*` back to `open_webui.routers.*` (the whole point of the refactor). - Line-by-line diff review between each moved function's pre/post form; all endpoint decorators, response_models, status codes, log messages, error-handling branches, and dict insertion order verified identical. - Manual smoke test: chat completion (with and without pipeline filters), title generation, tags generation, follow-up generation, memory add/query/update/delete, pipelines upload path. **Related to:** - Architecture map of `backend/open_webui/` shows one 14-file SCC driven by `utils ↔ routers` back-edges (not a runtime cycle — all guarded by in-function lazy imports with `# Import here to avoid circular imports`). This PR removes 3 of those 14 top-level edges; follow-ups will address the rest. ### Screenshots or Videos - N/A — no UI changes. ### Contributor License Agreement <!-- 🚨 DO NOT DELETE THE TEXT BELOW 🚨 Keep the "Contributor License Agreement" confirmation text intact. Deleting it will trigger the CLA-Bot to INVALIDATE your PR. Your PR will NOT be reviewed or merged until you check the box below confirming that you have read and agree to the terms of the CLA. --> - [x] By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms. > [!NOTE] > Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-16 01:16:46 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#98469