Make OpenWebUI reasoning filter order reproducible

This commit is contained in:
Mikei386 committed 2026-08-21 14:56:39 +02:00
1 parent bf90698b99
commit 9a40758c7f
7 files changed
+220

No files matched your search

@@ -0,0 +1,24 @@
"""
title: Reasoning Default Off
author: Mike
version: 1.0.1
description: Forces llama.cpp reasoning off by default.
"""
from pydantic import BaseModel
class Filter:
class Valves(BaseModel):
# OpenWebUI runs lower priorities first. This default must precede the
# optional Thinking override.
priority: int = 10
def __init__(self):
self.valves = self.Valves()
self.toggle = False
async def inlet(self, body: dict, **kwargs) -> dict:
body["reasoning_effort"] = "none"
body["thinking_budget_tokens"] = 0
return body
+57
View File
@@ -0,0 +1,57 @@
"""
title: Thinking
author: Mike
version: 2.0.1
description: Optional Qwen3.8 reasoning override - Low / Medium / High.
"""
from pydantic import BaseModel, Field
from typing import Literal
from urllib.parse import quote
class Filter:
class Valves(BaseModel):
# Runs after Reasoning Default Off and may deliberately override it.
priority: int = 20
class UserValves(BaseModel):
level: Literal["Low", "Medium", "High"] = Field(
default="Low",
description="Thinking depth",
)
def __init__(self):
self.valves = self.Valves()
self.toggle = True
svg = """
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<text x="16" y="23" text-anchor="middle" font-size="24">🧠</text>
</svg>
"""
self.icon = "data:image/svg+xml," + quote(svg)
async def inlet(
self,
body: dict,
__user__: dict = None,
**kwargs,
) -> dict:
level = "Low"
if __user__ and __user__.get("valves") is not None:
valves = __user__["valves"]
if isinstance(valves, dict):
level = valves.get("level", "Low")
else:
level = getattr(valves, "level", "Low")
if level == "Low":
body["reasoning_effort"] = "low"
body["thinking_budget_tokens"] = 512
elif level == "Medium":
body["reasoning_effort"] = "medium"
body["thinking_budget_tokens"] = 3072
elif level == "High":
body["reasoning_effort"] = "xhigh"
body["thinking_budget_tokens"] = 8192
return body
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
CONTAINER=${OPENWEBUI_CONTAINER:-mike-ai-open-webui}
VOLUME=${OPENWEBUI_VOLUME:-mike-ai_open-webui-data}
FILTER_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/filters" && pwd)
die() { printf 'FEHLER: %s\n' "$*" >&2; exit 1; }
[[ $EUID -eq 0 ]] || die "Bitte als root ausführen."
for file in reasoning_default_off.py thinking.py; do
[[ -s $FILTER_DIR/$file ]] || die "Filterdatei fehlt: $file"
done
volume_path=$(docker volume inspect -f '{{.Mountpoint}}' "$VOLUME")
db=$volume_path/webui.db
[[ -s $db ]] || die "OpenWebUI-Datenbank fehlt: $db"
was_running=false
if [[ $(docker inspect -f '{{.State.Running}}' "$CONTAINER" 2>/dev/null || true) == true ]]; then
was_running=true
docker stop "$CONTAINER" >/dev/null
fi
restart_on_exit() {
if [[ $was_running == true ]]; then
docker start "$CONTAINER" >/dev/null 2>&1 || true
fi
}
trap restart_on_exit EXIT
stamp=$(date +%Y%m%d-%H%M%S)
backup=$volume_path/webui.db.before-filter-install-$stamp
cp -a "$db" "$backup"
rm -f "$volume_path/webui.db-wal" "$volume_path/webui.db-shm"
python3 - "$db" "$FILTER_DIR" "${OPENWEBUI_FILTER_OWNER_ID:-}" <<'PY'
import json
import pathlib
import sqlite3
import sys
import time
db, filter_dir, requested_owner = sys.argv[1:]
con = sqlite3.connect(db)
columns = {row[1] for row in con.execute("pragma table_info(function)")}
required = {
"id", "user_id", "name", "type", "content", "meta", "valves",
"is_active", "is_global", "updated_at", "created_at",
}
if not required <= columns:
raise SystemExit("Unbekanntes OpenWebUI-Function-Schema; keine Änderung vorgenommen.")
owner = requested_owner
if not owner:
existing = con.execute(
"select user_id from function where id in (?, ?) order by id limit 1",
("reasoning_default_off", "thinking"),
).fetchone()
if existing:
owner = existing[0]
if not owner:
admins = con.execute("select id from user where role='admin'").fetchall()
if len(admins) != 1:
raise SystemExit(
"Filter-Eigentümer ist nicht eindeutig; OPENWEBUI_FILTER_OWNER_ID setzen."
)
owner = admins[0][0]
now = int(time.time())
filters = [
("reasoning_default_off", "Reasoning Default Off", 10),
("thinking", "Thinking", 20),
]
with con:
for function_id, name, priority in filters:
content = pathlib.Path(filter_dir, f"{function_id}.py").read_text()
con.execute(
"""
insert into function
(id,user_id,name,type,content,meta,valves,is_active,is_global,updated_at,created_at)
values (?,?,?,?,?,?,?,?,?,?,?)
on conflict(id) do update set
name=excluded.name,
type=excluded.type,
content=excluded.content,
valves=excluded.valves,
is_active=excluded.is_active,
is_global=excluded.is_global,
updated_at=excluded.updated_at
""",
(
function_id, owner, name, "filter", content, "{}",
json.dumps({"priority": priority}), True, True, now, now,
),
)
print("OpenWebUI-Filter installiert: Default Off=10, Thinking=20")
PY
if [[ $was_running == true ]]; then
docker start "$CONTAINER" >/dev/null
deadline=$((SECONDS + 180))
until [[ $(docker inspect -f '{{.State.Health.Status}}' "$CONTAINER" 2>/dev/null || true) == healthy ]]; do
(( SECONDS < deadline )) || die "$CONTAINER wurde nicht rechtzeitig gesund."
sleep 3
done
fi
trap - EXIT
printf 'Datenbanksicherung: %s\n' "$backup"