0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Open WebUI カスタムヘッダー(ユーザー情報)

Posted at

Open WebUI の環境変数「ENABLE_FORWARD_USER_INFO_HEADERS」を有効にすると、LLM へのリクエストに「ユーザー情報を格納したカスタムヘッダー」が付加されるようになります。
「ユーザー名」や「ユーザーID」が必要なときは、この機能を利用できるでしょう。

環境変数

名称: ENABLE_FORWARD_USER_INFO_HEADERS
設定値: False(ユーザー情報 カスタムヘッダーを付加しない)
     True(ユーザー情報 カスタムヘッダーを付加する)
 
付加されるカスタムヘッダー情報

ヘッダー名 説明
X-OpenWebUI-User-Name ユーザーのログインID
 例. "test"
X-OpenWebUI-User-Id ユーザーの識別子
X-OpenWebUI-User-Email ユーザーのメールアドレス
 例. "test-user@example.or.zz"
X-OpenWebUI-User-Role ユーザーに割り当てられたロール
 例. "admin"
X-OpenWebUI-Chat-Id チャットメッセージの識別子

値が「非ASCII文字」の場合、カスタムヘッダーの値が不正になる』という問題が、2025年5月 に報告されていました。
 https://github.com/open-webui/open-webui/discussions/14391

解消されたかどうかは不明ですが、少なくとも「ログインID」「メールアドレス」「ロール名」では 非ASCII文字 の利用は避けた方が良いでしょう。

設定方法

Open WebUI 用の docker-compose.yml に前述の環境変数を記述した後、コンテナを再起動してください。

services:
  open-webui:
     ... (省略)
    environment:
      - ENABLE_FORWARD_USER_INFO_HEADERS=True
    ... (省略)

実際のヘッダ情報

dify2openai にログ出力処理を追加し、実際のリクエストヘッダーを抽出してみました。

/v1/models

x-openwebui-user-namex-openwebui-user-email に、ログインユーザーの情報が格納されています。

--- HTTP Request Headers ---
host: 192.168.0.200:20001
authorization: Bearer app-9W********************cH
x-openwebui-user-name: b*****
x-openwebui-user-id: b89*****-****-****-****-**********6d
x-openwebui-user-email: b**********0@gmail.com
x-openwebui-user-role: admin
accept: */*
accept-encoding: gzip, deflate, br
user-agent: Python/3.11 aiohttp/3.12.15
--------------------------
--- リクエスト情報 ---
Request Method: GET
Request Path: /v1/models
リクエストボディ: なし、またはJSON形式ではありません。

/v1/chat/completions

チャットメッセージ送信直後のリクエストヘッダーです。
x-openwebui-chat-id にチャットメッセージを識別するための識別子が格納されています。
同じチャットでやり取りを続ける限り、同じ識別子が使われ続けるようです。

次の操作を行うと、別の識別子に切り替わります。

  • 「新しいチャット」をクリックし、新規メッセージを送信。
  • 「チャット履歴」から過去のタイトルをクリックし、新規メッセージを送信。
```text
--- HTTP Request Headers ---
host: 192.168.0.200:20001
content-type: application/json
x-openwebui-user-name: b*****
x-openwebui-user-id: b89*****-****-****-****-**********6d
x-openwebui-user-email: b**********0@gmail.com
x-openwebui-user-role: admin
x-openwebui-chat-id: 071*****-****-****-****-**********cc
authorization: Bearer app-9W********************cH
accept: */*
accept-encoding: gzip, deflate, br
user-agent: Python/3.11 aiohttp/3.12.15
content-length: 161
--------------------------
--- リクエスト情報 ---
Request Method: POST
Request Path: /v1/chat/completions
リクエストボディ (JSON): {
  "stream": true,
  "model": "My Dify",
  "messages": [
    {
      "role": "user",
      "content": "東京タワーの住所を教えて。"
    }
  ]
}

Dify へのリクエストに「ユーザー情報」を埋め込む

dify2openai に少し手を加えるだけで、カスタムヘッダーに埋め込まれている「ユーザー情報」を取り出すことができます。

Dify API (/chat-messages) の「ユーザー識別子」に、「ユーザーのメールアドレス」を設定してみましょう。

改造前

app.js 内で「requestBody」を作成している個所を改造します。
以下は、改造前のソース内容です。

    let requestBody;
    if (inputVariable) {
      requestBody = {
        inputs: { [inputVariable]: queryString },
        response_mode: "streaming",
        conversation_id: "",
        user: "apiuser",
        auto_generate_name: false
      };
    } else {
      requestBody = {
        "inputs": {},
        query: queryString,
        response_mode: "streaming",
        conversation_id: "",
        user: "apiuser",
        auto_generate_name: false
      };
    }

改造後

カスタムヘッダーから「メールアドレス」を抽出処理を追加します。

    let userEmail = "apiuser";

    // x-openwebui-user-email ヘッダを取得します。
    const userEmailHeader = req.headers['x-openwebui-user-email'];

    if (userEmailHeader && typeof userEmailHeader === 'string') {
        // ヘッダの値の前後にある空白文字(スペース、タブ、改行など)を除去します。
        const trimmedEmail = userEmailHeader.trim();

        // 空文字列 ('') でなければ、その値をDifyに渡すユーザー名として採用します。
        if (trimmedEmail !== '') {
            userEmail = trimmedEmail;
        }
    }

    let requestBody;
    if (inputVariable) {
      requestBody = {
        inputs: { [inputVariable]: queryString },
        response_mode: "streaming",
        conversation_id: "",
        user: userEmail,  // メールアドレスを指定
        auto_generate_name: false
      };
    } else {
      requestBody = {
        "inputs": {},
        query: queryString,
        response_mode: "streaming",
        conversation_id: "",
        user: userEmail,  // メールアドレスを指定
        auto_generate_name: false
      };
    }

実行結果(Dify 上でのログ記録)

下図は、「新しいチャット」をクリックしてメッセージを送信してみた結果です。

これまでは固定値 apiuser を記録していましたが、改造後は Open WebUI のログインユーザー情報「メールアドレス」が記録されるようになりました。

終わりに

Dify 内部では、連続する一連のチャットメッセージを「会話ID(conversation_id)」で取り纏めて管理しますが、dify2openai は「会話ID(conversation_id)」をサポートしておらず、常に「独立した1個のメッセージ」として記録されます。

Dify API から返却される「会話ID(conversation_id)」と「チャットメッセージ識別子(X-OpenWebUI-Chat-Id)」を紐づければ、連続する一連のチャットメッセージを Dify 内で 一括り に管理することもできそうです。

ただ、改造量は結構大きくなると思われ、そこまでくると「dify2openai 相当のプロダクツ」を自作しても良いかもしれません。

GitHub には、dify2openai をもっと高機能にしたプロダクツも登録されています。
ただ、利用する際は ソースファイルの内容を注意深くチェックし、セキュリティ上の脅威とならないことを確認した方が良いでしょう。
(変なバックドアなどが仕掛けられていたら大事になってしまいます)

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?