Làm chủ Open-WebUI Pipelines: Xây dựng Logic Python tùy chỉnh cho LLM cục bộ

AI tutorial - IT technology blog
AI tutorial - IT technology blog

Vượt xa khỏi khung Chat: Kết nối LLM cục bộ với thế giới thực

Chạy một LLM cục bộ với Ollama và Open-WebUI đã trở thành thiết lập ưu tiên cho các nhà phát triển quan tâm đến quyền riêng tư. Nó mô phỏng trải nghiệm ChatGPT trong khi vẫn giữ mọi token trên phần cứng của riêng bạn. Tuy nhiên, một LLM độc lập thường là một ốc đảo biệt lập. Nó không thể truy vấn cơ sở dữ liệu PostgreSQL, không biết trạng thái ticket Jira hiện tại và không thể tự mình thực thi các quy tắc phong cách (style guide) cụ thể của doanh nghiệp.

Open-WebUI Pipelines thu hẹp khoảng cách này bằng cách đóng vai trò như một middleware có thể lập trình được. Hãy coi chúng như những bộ chặn (interceptors) cho cuộc hội thoại của bạn. Bạn có thể loại bỏ dữ liệu nhạy cảm khỏi prompt trước khi nó đến được mô hình hoặc định dạng đầu ra của mô hình trước khi nó hiển thị trên màn hình. Theo kinh nghiệm của tôi khi triển khai các hệ thống này cho các môi trường khắt khe về quy định, pipelines là cách đáng tin cậy nhất để đảm bảo trợ lý AI hoạt động đúng phạm vi cho phép.

Kiến trúc Pipeline hoạt động như thế nào

Pipelines hoạt động như một dịch vụ phụ trợ. Chúng thường chạy trong một container Docker nhẹ cùng với instance Open-WebUI của bạn. Khi bạn nhấn ‘Gửi’, Open-WebUI sẽ truyền tải dữ liệu tin nhắn đến server Pipeline thông qua một lệnh gọi API. Thiết lập này thường chỉ thêm chưa tới 50ms độ trễ, khiến quá trình chuyển đổi mang lại cảm giác tức thì cho người dùng.

Ba trụ cột của một Pipeline

  • Lớp Pipe (Pipe Class): Đây là điểm khởi đầu của bạn. Đó là lớp Python mà Open-WebUI nhận diện và tải vào giao diện.
  • Valves: Chúng đóng vai trò như bảng điều khiển cấu hình. Thay vì viết cứng (hardcoding) các API key cho các dịch vụ như Tavily hoặc LangChain, bạn định nghĩa chúng dưới dạng Valves. Chúng xuất hiện dưới dạng các trường văn bản trong cài đặt UI, cho phép cập nhật nhanh chóng.
  • Filters và Actions: Filters sửa đổi luồng văn bản trong thời gian thực. Actions kích hoạt các sự kiện cụ thể, như gửi thông báo Slack khi một chủ đề nhất định được nhắc đến.

Khởi động Engine Pipeline của bạn

Bạn cần engine Pipeline chạy trước khi có thể viết bất kỳ mã Python nào. Nếu đang sử dụng Docker, bạn có thể chạy image chính thức bằng một lệnh duy nhất. Container này sẽ giám sát các script của bạn và tải lại chúng bất cứ khi nào bạn lưu thay đổi.

docker run -d -p 9099:9099 --add-host=host.docker.internal:host-gateway -v pipelines:/app/pipelines --name pipelines ghcr.io/open-webui/pipelines:main

Bất kỳ tệp Python nào bạn di chuyển vào thư mục /app/pipelines đều được tự động phát hiện. Bạn thậm chí không cần khởi động lại container để thấy logic mới của mình xuất hiện trong bảng điều khiển Open-WebUI.

Hướng dẫn thực hành: Xây dựng bộ lọc làm sạch dữ liệu PII

Hãy xây dựng một bộ lọc ngăn chặn LLM làm rò rỉ tên dự án nội bộ. Chúng ta muốn thay thế các thuật ngữ nhạy cảm như “Project-X” hoặc “Internal-Vault” bằng một nhãn thay thế đã được che đi trước khi người dùng nhìn thấy chúng.

1. Tạo Script

Tạo một tệp có tên security_filter.py. Chúng ta sẽ sử dụng Pydantic để định nghĩa các cài đặt giao diện người dùng. Điều này cho phép người dùng không chuyên về kỹ thuật có thể cập nhật danh sách từ hạn chế trực tiếp từ trình duyệt.

from typing import List, Optional, Union, Generator
from pydantic import BaseModel, Field

class Pipeline:
    class Valves(BaseModel):
        # Các trường này xuất hiện dưới dạng cài đặt trong Open-WebUI
        blacklisted_terms: str = Field(default="Project-X,Internal-Vault,Top-Secret")
        replacement_label: str = Field(default="[ĐÃ CHE]")

    def __init__(self):
        self.type = "filter"
        self.name = "Bộ lọc làm sạch bảo mật"
        self.valves = self.Valves()

    async def outlet(self, body: dict, user: Optional[dict] = None) -> dict:
        # Hàm này chạy sau khi LLM tạo phản hồi
        terms = self.valves.blacklisted_terms.split(",")
        content = body.get("messages", [])[-1].get("content", "")

        for term in terms:
            clean_term = term.strip()
            if clean_term in content:
                content = content.replace(clean_term, self.valves.replacement_label)
        
        body["messages"][-1]["content"] = content
        return body

2. Kết nối với các API bên ngoài

Pipelines cũng có thể đóng vai trò như các “mô hình ảo”. Thay vì chỉ lọc, bạn có thể điều hướng các truy vấn đến các công cụ bên ngoài. Ví dụ, nếu người dùng hỏi về thông tin thời tiết, pipeline có thể gọi OpenWeather API và trả về dữ liệu trực tiếp, bỏ qua quá trình tạo văn bản thông thường của LLM.

import requests

class Pipeline:
    def __init__(self):
        self.name = "Trợ lý dữ liệu trực tiếp"

    async def pipe(self, body: dict, user: Optional[dict] = None) -> str:
        last_message = body.get("messages", [])[-1].get("content", "").lower()
        
        if "thời tiết tại hà nội" in last_message:
            # Trong kịch bản thực tế, hãy sử dụng một lệnh gọi API bảo mật tại đây
            return "Hiện tại Hà Nội đang là 28°C với độ ẩm 80%."
        
        return "Hiện tại tôi chỉ có quyền truy cập dữ liệu thời tiết của Hà Nội."

Những bài học từ môi trường thực tế

Tôi đã dành nhiều tháng để tinh chỉnh các quy trình này cho các nhóm nội bộ. Việc chuyển từ một thử nghiệm cục bộ sang một công cụ được sử dụng bởi hai mươi người đòi hỏi sự tập trung vào tính ổn định và tốc độ.

Ưu tiên các lệnh gọi không đồng bộ

Không bao giờ sử dụng thư viện requests tiêu chuẩn của Python cho các API bên ngoài. Nó sẽ chặn luồng chính. Nếu API của bạn mất ba giây để phản hồi, toàn bộ giao diện người dùng sẽ bị đóng băng đối với tất cả mọi người. Hãy sử dụng httpx với async/await để giữ cho giao diện luôn mượt mà.

Xây dựng cơ chế dự phòng lỗi mạnh mẽ

API có thể gặp lỗi. Nếu pipeline của bạn bị sập, Open-WebUI sẽ trả về lỗi “Server Error” chung chung khiến người dùng khó chịu. Luôn bao bọc logic của bạn trong các khối try-except. Nếu một công cụ thất bại, hãy lập trình pipeline để trả về một thông báo hữu ích hoặc điều hướng truy vấn đến một mô hình dự phòng cục bộ như Llama 3.

Giữ cho logic có tính di động với Valves

Tránh viết cứng các thông tin bí mật. Sử dụng lớp Valves cho mọi thứ, từ chuỗi kết nối cơ sở dữ liệu đến API token. Điều này cho phép bạn chia sẻ các script .py với nhóm của mình mà không làm lộ thông tin cá nhân. Họ chỉ cần nhập key của riêng mình trong menu Settings > Pipelines.

Lời kết

Open-WebUI Pipelines biến một giao diện chat cơ bản thành một lớp điều phối mạnh mẽ. Chỉ bằng cách viết vài dòng mã Python, bạn có thể thay đổi cách AI cục bộ tương tác với dữ liệu của mình. Hãy bắt đầu với một bộ lọc văn bản đơn giản để làm quen. Khi bạn thấy việc tích hợp dễ dàng như thế nào, bạn có thể bắt đầu xây dựng các quy trình đa công cụ phức tạp giúp AI của bạn thực sự hữu ích.

Share: