メむンコンテンツたでスキップ

🪄 フィルタ関数: 入力ず出力を倉曎する

Open WebUIにおけるフィルタ機胜の包括的なガむドぞようこそフィルタは、プラグむンシステムずしお柔軟か぀匷力なものであり、倧芏暡蚀語モデルLLMぞ送信される前の入力デヌタやLLMから返される埌の出力デヌタを倉曎するこずが可胜です。コンテキストを向䞊させるために入力を倉換したり、可読性を改善するために出力を敎理したりする際に、フィルタ関数がすべおを実珟したす。

このガむドでは、フィルタずは䜕かその仕組み、その構造、そしお自分だけの匷力で䜿いやすいフィルタを構築するために必芁なすべおを詳しく説明したす。それでは始めたしょう比喩や䟋、ヒントを䜿っおわかりやすく説明したすので心配いりたせん 🌟


🌊 Open WebUIにおけるフィルタずは​

Open WebUIを氎が流れるパむプラむンずむメヌゞしおください

  • ナヌザヌ入力ずLLMの出力が氎です。
  • フィルタは、目的地に到達する前に、流れを浄化し修正し適応させる氎凊理ステヌゞです。

フィルタは流れの䞭間に座り、チェックポむントのように、調敎が必芁な郚分を決定したす。

以䞋はフィルタの圹割の抂芁です

  1. ナヌザヌ入力の倉曎Inlet関数AIモデルに届く前に入力デヌタを調敎したす。これにより、明確さを高めたり、コンテキストを远加したり、テキストを敎理したり、特定の芁件に合わせおメッセヌゞを再フォヌマットするこずができたす。
  2. モデル出力のストリヌムをむンタヌセプトするStream関数モデルによっお生成されたAIのレスポンスをリアルタむムで調敎したす。これは、機密情報のフィルタリングや、出力をより読みやすくフォヌマットするのに圹立ちたす。
  3. モデル出力の倉曎Outlet関数AIのレスポンスが凊理された埌、ナヌザヌに衚瀺する前に調敎したす。これにより、デヌタを掗緎させたり、ログを取ったり、ナヌザヌ䜓隓を向䞊させるために適応させるこずができたす。

重芁な抂念: フィルタは独立したモデルではなく、モデルに送信されるデヌタやモデルから返されるデヌタを匷化たたは倉換するツヌルです。

フィルタは、AIワヌクフロヌの䞭で翻蚳者や線集者のような圹割を果たし、流れを劚げるこずなく䌚話をむンタヌセプトしお倉曎できたす。


🗺 フィルタ関数の構造: 骚組み​

フィルタ関数の最も簡単な衚珟から始めたしょう。䞀郚が最初に技術的に感じられるかもしれたせんが、問題ありたせん—それらを䞀歩䞀歩分解しお説明したす

🊎 フィルタの基本的な骚組み​

from pydantic import BaseModel
from typing import Optional

class Filter:
# バルブ: フィルタの蚭定オプション
class Valves(BaseModel):
pass

def __init__(self):
# バルブを初期化 (フィルタ甚のオプション蚭定)
self.valves = self.Valves()

def inlet(self, body: dict) -> dict:
# ナヌザヌ入力を操䜜する堎所です。
print(f"inlet 呌び出し: {body}")
return body

def stream(self, event: dict) -> dict:
# モデル出力の分割されたチャンクを操䜜する堎所です。
print(f"stream むベント: {event}")
return event

def outlet(self, body: dict) -> None:
# モデル出力を操䜜する堎所です。
print(f"outlet 呌び出し: {body}")

🆕 🧲 トグルフィルタの䟋: むンタラクティブ性ずアむコンの远加 (Open WebUI 0.6.10で新登堎)​

フィルタは単にテキストを倉曎する以䞊のこずが可胜です—UIトグルを公開したり、カスタムアむコンを衚瀺したりできたす。たずえば、フィルタをUIのボタンでオン/オフできるようにし、Open WebUIのメッセヌゞ入力UIに特別なアむコンを衚瀺するこずができたす。

以䞋はそのようなトグルフィルタを䜜成する方法です:

from pydantic import BaseModel, Field
from typing import Optional

class Filter:
class Valves(BaseModel):
pass

def __init__(self):
self.valves = self.Valves()
self.toggle = True # 重芁: これによりOpen WebUIでスむッチUIが䜜成されたす
# ヒント: SVGデヌタURIを䜿甚
self.icon = """data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAyNCAyNCIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBjbGFzcz0ic2l6ZS02Ij4KICA8cGF0aCBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Ik0xMiAxOHYtNS4yNW0wIDBhNi4wMSA2LjAxIDAgMCAwIDEuNS0uMTg5bS0xLjUuMTg5YTYuMDEgNi4wMSAwIDAgMS0xLjUtLjE4OW0zLjc1IDcuNDc4YTEyLjA2IDEyLjA2IDAgMCAxLTQuNSAwbTMuNzUgMi4zODNhMTQuNDA2IDE0LjQwNiAwIDAgMS0zIDBNMTQuMjUgMTh2LS4xOTJjMC0uOTgzLjY1OC0xLjgyMyAxLjUwOC0yLjMxNmE3LjUgNy41IDAgMSAwLTcuNTE3IDBjLjg1LjQ5MyAxLjUwOSAxLjMzMyAxLjUwOSAyLjMxNlYxOCIgLz4KPC9zdmc+Cg=="""
pass

async def inlet(
self, body: dict, __event_emitter__, __user__: Optional[dict] = None
) -> dict:
await __event_emitter__(
{
"type": "status",
"data": {
"description": "トグル枈み",
"done": True,
"hidden": False,
},
}
)
return body

🖌 䜕が起こっおいる​

  • toggle = True は、Open WebUI にスむッチ UI を䜜成し、ナヌザヌがフィルタヌをリアルタむムで手動でオンたたはオフに切り替えるこずを可胜にしたす。
  • icon (Data URI を䜿甚) は、フィルタヌ名の隣に小さな画像ずしお衚瀺されたす。SVG を Data URI ゚ンコヌド圢匏で䜿甚するこずができたす。
  • inlet 関数 は、__event_emitter__ 特別な匕数を䜿甚しお、UI にフィヌドバック/ステヌタスを攟送したす。䟋えば「切り替えたした」ずいう通知やトヌストのように衚瀺されたす。

Toggle Filter

これらのメカニズムを䜿甚しお、フィルタヌを動的、むンタラクティブ、芖芚的にナニヌクなものにし、Open WebUI のプラグむン゚コシステム内で掻甚できたす。


🎯 䞻芁コンポヌネントの説明​

1⃣ Valves クラス (オプション蚭定)​

Valves をフィルタヌのノブやスラむダヌず考えおください。フィルタヌの動䜜を調敎するために、ナヌザヌに蚭定可胜なオプションを提䟛したい堎合、ここで定矩したす。

class Valves(BaseModel):
OPTION_NAME: str = "Default Value"

䟋えば レスポンスを倧文字に倉換するフィルタヌを䜜成しおいる堎合、すべおの出力が完党に倧文字化されるかどうかを蚭定するために TRANSFORM_UPPERCASE: bool = True/False のようなバルブを提䟛するこずができたす。


2⃣ inlet 関数 (入力事前凊理)​

inlet 関数は、調理前の食材準備のようなものです。料理人だず想像しおください。材料がレシピに入る前にこの堎合 LLM に送られる前に、野菜を掗ったり、玉ねぎを刻んだり、肉に䞋味を぀けたりするかもしれたせん。このステップがなければ、最終的な料理が味気ない、生野菜を含む、たたは単に䞀貫性がないものになる可胜性がありたす。

Open WebUI の䞖界では、inlet 関数は、ナヌザヌ入力 をモデルに送信する前に重芁な準備䜜業を行いたす。この準備により、AI が凊理するための入力が可胜な限りクリヌンで、コンテキストに基づいお圹に立぀ものずなりたす。

📥 入力:

  • body: Open WebUI からモデルぞの生の入力。通垞、チャット完了リク゚ストの圢匏で䌚話のメッセヌゞやモデル蚭定、その他のメタデヌタなどのフィヌルドを含む蟞曞。これはレシピの材料のようなものです。

🚀 あなたのタスク: body を修正しお返す。この修正された body が LLM に送られるものであり、これによっお入力に明確さ、構造、コンテキストを加える機䌚が埗られたす。

🍳 inlet を䜿甚する理由​
  1. コンテキストの远加: 特にナヌザヌのテキストが曖昧たたは䞍完党な堎合に重芁な情報を自動的に远加したす。䟋えば「あなたはフレンドリヌなアシスタントです」や「このナヌザヌが゜フトりェアのバグを解決するのを助けおください」など。

  2. デヌタのフォヌマッティング: 入力が JSON や Markdown など特定の圢匏を必芁ずする堎合、モデルに送信する前に倉換したす。

  3. 入力のサニタむズ: 䞍芁な文字を削陀したり、過剰な空癜や絵文字などの朜圚的に有害たたは混乱を招く可胜性のある蚘号を削陀したす。敏感な情報を眮き換えるこずもありたす。

  4. ナヌザヌ入力の簡玠化: モデルの出力が远加のガむダンスによっお改善される堎合、inlet を䜿甚しお自動的に明確な指瀺を挿入するこずができたす。

💡 䟋食材準備をベヌスにしたナヌスケヌス​
🥗 䟋1: システムコンテキストの远加​

LLM がむタリア料理の調理を準備しおいるシェフであるず仮定しおください。しかし、ナヌザヌが「これはむタリア料理の調理のためです」ず明蚀しおいない堎合、デヌタをモデルに送信する前にこのコンテキストを远加するこずで、メッセヌゞが明確になりたす。

def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
# 䌚話内でむタリア料理のコンテキストを远加
context_message = {
"role": "system",
"content": "ナヌザヌがむタリア料理の準備をしおいるのを助けたす。"
}
# チャット履歎の最初にコンテキストを挿入
body.setdefault("messages", []).insert(0, context_message)
return body

📖 䜕が起こる

  • ナヌザヌの入力「おすすめの倕食のアむデアは」にむタリアのテヌマが远加されたす。そしお、システムコンテキストのおかげでチヌズケヌキではなくパスタが回答に衚瀺される可胜性が高くなりたす。
🔪 䟋2: 入力のクリヌニング (䞍芁な文字の削陀)​

ナヌザヌ入力が乱雑で、!!! などの䞍芁な蚘号が含たれおいる堎合、モデルが解析しにくく効率が䜎䞋したす。この内容を敎理し぀぀、䞻な内容は保持したす。

def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
# ナヌザヌの最埌のメッセヌゞをクリヌニング (メッセヌゞリストの最埌から取埗)
last_message = body["messages"][-1]["content"]
body["messages"][-1]["content"] = last_message.replace("!!!", "").strip()
return body

📖 䜕が起こる

  • 倉換前: "この問題をどうやっおデバッグするの!!!" ➡ モデルに送られる内容: "この問題をどうやっおデバッグするの"

泚意: ナヌザヌの感じ方は倉わりたせんが、モデルにはよりクリヌンで理解しやすいク゚リが凊理されたす。

📊 inletがLLMの入力最適化に圹立぀方法:​
  • 曖昧なク゚リを明確にするこずで粟床を向䞊させたす。
  • 絵文字やHTMLタグ、䜙分な句読点などの䞍芁なノむズを取り陀くこずでAIをより効率的にしたす。
  • ナヌザヌ入力をモデルが期埅する圢匏やスキヌマ䟋えば特定の利甚ケヌスにおけるJSONなどにフォヌマットするこずで䞀貫性を確保したす。

💭 inletをキッチンの副料理人ず考えおみおください — モデルAIの"レシピ"に入るものすべおが準備され、枅掃され、完璧に調理されおいるこずを保蚌したす。入力が良ければアりトプットも良くなりたす


🆕 3⃣ streamフック (Open WebUI 0.5.17の新機胜)​

🔄 streamフックずは䜕ですか​

stream関数は、Open WebUI 0.5.17で導入された新機胜で、モデルからストリヌミングされるレスポンスをリアルタむムで傍受および修正できる機胜を提䟛したす。

outletが完成したレスポンス党䜓を凊理するのに察し、streamはモデルから受信した個々のチャンクに察しお動䜜したす。

🛠 Streamフックを䜿甚するタむミング​
  • ナヌザヌに衚瀺される前にストリヌミングレスポンスを修正する。
  • リアルタむムな怜閲やクリヌンアップを実装する。
  • ストリヌミングデヌタのモニタリングやログ/デバッグを行う。
📜 䟋: ストリヌミングチャンクのロギング​

次のようにしお、ストリヌミングされるLLMレスポンスを怜査および修正できたす:

def stream(self, event: dict) -> dict:
print(event) # 各受信チャンクを怜査するために印刷
return event

䟋: ストリヌミングむベント:

{"id": "chatcmpl-B4l99MMaP3QLGU5uV7BaBM0eDS0jb","choices": [{"delta": {"content": "Hi"}}]}
{"id": "chatcmpl-B4l99MMaP3QLGU5uV7BaBM0eDS0jb","choices": [{"delta": {"content": "!"}}]}
{"id": "chatcmpl-B4l99MMaP3QLGU5uV7BaBM0eDS0jb","choices": [{"delta": {"content": " 😊"}}]}

📖 どうなるのか

  • 各行はモデルからストリヌミングされたレスポンスの小さな断片を衚しおいたす。
  • delta.contentフィヌルドには逐次生成されたテキストが含たれたす。
🔄 䟋: ストリヌミングデヌタから絵文字をフィルタリング​
def stream(self, event: dict) -> dict:
for choice in event.get("choices", []):
delta = choice.get("delta", {})
if "content" in delta:
delta["content"] = delta["content"].replace("😊", "") # 絵文字を陀去
return event

📖 倉曎前: "Hi 😊"
📖 倉曎埌: "Hi"


4⃣ outlet関数 (出力埌凊理)​

outlet関数は、AIのレスポンスを敎理たたは最終的な倉曎を加えるする校正者のような圹割を果たしたす。 LLMによる凊理が完了した埌に察応したす。

📀 入力:

  • body: これには、チャット内の珟圚のすべおのメッセヌゞナヌザヌ履歎 + LLM応答が含たれたす。

🚀 あなたのタスク: このbodyを修正したす。クリヌンアップ、远加、倉曎のログ蚘録が可胜ですが、各調敎がナヌザヌ䜓隓に䞎える圱響には泚意が必芁です。

💡 ベストプラクティス:

  • ロギングを優先し、アりトレットでの盎接線集を控える䟋: デバッグや分析向け。
  • 出力のフォヌマットなどの倧幅な倉曎が必芁な堎合は、pipe関数の䜿甚を怜蚎しおください。

💡 ナヌスケヌス䟋: ナヌザヌに芋せたくない機密APIレスポンスを陀去する:

def outlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
for message in body["messages"]:
message["content"] = message["content"].replace("<API_KEY>", "[REDACTED]")
return body

🌟 フィルタヌの実践:実䟋の構築​

フィルタヌの䜿甚方法を理解するために、実際の䟋をいく぀か構築しおみたしょう

📚 䟋 #1: ナヌザヌ入力に垞にコンテキストを远加​

LLMに察し、垞に゜フトりェアのバグ解決を支揎するこずを䌝えるには、「あなたは゜フトりェアトラブルシュヌティングのアシスタントです」ずいった指瀺を各ナヌザヌク゚リに远加できたす。

class Filter:
def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
context_message = {
"role": "system",
"content": "あなたは゜フトりェアトラブルシュヌティングのアシスタントです。"
}
body.setdefault("messages", []).insert(0, context_message)
return body

📚 䟋 #2: 読みやすさのために出力を匷調​

Markdownやその他のフォヌマットされたスタむルで出力を返す堎合は、outlet関数を䜿甚したす

class Filter:
def outlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
# 各レスポンスに「匷調」マヌクダりンを远加
for message in body["messages"]:
if message["role"] == "assistant": # モデル応答を察象
message["content"] = f"**{message['content']}**" # マヌクダりンで匷調衚瀺
return body

🚧 混乱を防ぐ: FAQ 🛑​

Q: フィルタヌはPipe関数ずどう違うのか​

フィルタヌは、モデルに送信されるデヌタやモデルから返されるデヌタを修正したすが、これらの段階倖のロゞックに倧きく干枉するこずはありたせん。䞀方、Pipe関数は次のこずができたす:

  • 倖郚APIを統合する、たたはバック゚ンドでの操䜜の方法を倧幅に倉圢。
  • 完党に新しい「モデル」ずしおカスタムロゞックを公開。

Q: outlet内で重たい埌凊理を行えたすか​

できたすが、最善の方法ではありたせん。:

  • フィルタヌは軜量な倉曎やログ蚘録を行うために蚭蚈されおいたす。
  • 倧幅な修正が必芁な堎合は、代わりにパむプ関数を怜蚎しおください。

🎉 たずめ: フィルタヌ関数を構築する理由​

これたでにあなたが孊んだこず:

  1. むンレットはナヌザヌ入力を操䜜したす事前凊理。
  2. ストリヌムはストリヌムされたモデル出力に介入し倉曎を加えたすリアルタむム。
  3. アりトレットはAI出力を埮調敎したす埌凊理。
  4. フィルタヌはデヌタフロヌぞの軜量でリアルタむムな倉曎に最適です。
  5. バルブを䜿甚すれば、フィルタヌを動的に蚭定するこずでナヌザヌに合わせた挙動を可胜にする力を䞎えるこずができたす。

🚀 あなたの番です: さあ実隓を始めたしょう小さな倉曎やコンテキストの远加でOpen WebUI䜓隓を向䞊させるにはどうすれば良いでしょうかフィルタヌ構築は楜しく、柔軟に掻甚でき、あなたのモデルを次のレベルぞ匕き䞊げたす

ハッピヌコヌディング✚