fix: combine specialist tools with native web search

This commit is contained in:
Mikei386
2026-08-24 12:25:12 +02:00
parent 5834342f8c
commit 5528f3ab22
4 changed files with 71 additions and 13 deletions
+12
View File
@@ -260,6 +260,18 @@ class AutoToolSelectorTests(unittest.IsolatedAsyncioTestCase):
) )
self.assertIn("unraid_files_inventory", result["messages"][0]["content"]) self.assertIn("unraid_files_inventory", result["messages"][0]["content"])
async def test_unraid_media_audit_with_deezer_enables_native_web(self):
result = await self._select(
"Prüfe auf Unraid, welche Folgen meiner Hörspielserie fehlen, ermittle die "
"aktuelle offizielle Liste online und prüfe jede fehlende Folge bei Deezer. "
"Nur lesen, ohne Downloads oder Änderungen."
)
self.assertEqual(result["tool_ids"], ["server:mcp:mua-readonly-local"])
self.assertTrue(result["features"]["web_search"])
self.assertTrue(result["metadata"]["features"]["web_search"])
self.assertIn("search_web/fetch_url", result["messages"][0]["content"])
self.assertEqual(result["reasoning_effort"], "medium")
async def test_voice_transcription_variants_select_unraid(self): async def test_voice_transcription_variants_select_unraid(self):
result = await self._select( result = await self._select(
"Welche Dacher Contäner laufen aktuell auf dem Anrate Server?" "Welche Dacher Contäner laufen aktuell auf dem Anrate Server?"
+5 -3
View File
@@ -190,10 +190,12 @@ Unraid ist ausschließlich über das MUA-Plugin angebunden. Die Verbindungen
`mua-readonly-local` und `mua` nutzen denselben MUA-Endpunkt. Mehrere bestätigte `mua-readonly-local` und `mua` nutzen denselben MUA-Endpunkt. Mehrere bestätigte
Docker-Updates laufen ab MUA r019 gebündelt und idempotent; echte Image-IDs Docker-Updates laufen ab MUA r019 gebündelt und idempotent; echte Image-IDs
verhindern Neuerstellungen aufgrund eines veralteten Statuscaches. verhindern Neuerstellungen aufgrund eines veralteten Statuscaches.
Ab MUA r020 inventarisiert `unraid_files_inventory` Datei- und Ordnernamen Ab MUA r021 inventarisiert `unraid_files_inventory` Datei- und Ordnernamen
begrenzt, ohne Dateiinhalte zu lesen. Auto Tool Selector 3.4 hält ausdrücklich begrenzt, ohne Dateiinhalte zu lesen, und beendet eine gefilterte Erkennung an
einem passenden Sammlungsordner. Auto Tool Selector 3.5 hält ausdrücklich
lesende Bibliotheksprüfungen bei MUA read-only und verwechselt Hörspielfolgen lesende Bibliotheksprüfungen bei MUA read-only und verwechselt Hörspielfolgen
nicht mit Sonarr-Episoden. Der Ablauf steht in nicht mit Sonarr-Episoden. Verlangt derselbe Auftrag aktuelle Onlinebelege,
aktiviert er zusätzlich die native Websuche. Der Ablauf steht in
`docs/UNRAID_MEDIA_AUDIT_WORKFLOW.md`. Der frühere GraphQL-basierte Unraid-MCP wurde `docs/UNRAID_MEDIA_AUDIT_WORKFLOW.md`. Der frühere GraphQL-basierte Unraid-MCP wurde
entfernt und gehört weder zum Start noch zum Recovery. entfernt und gehört weder zum Start noch zum Recovery.
+7 -6
View File
@@ -10,18 +10,20 @@ einschaltet. Der Ablauf bleibt vollständig read-only.
## Werkzeugwahl ## Werkzeugwahl
Der Auto Tool Selector 3.4 erkennt einen ausdrücklich lesenden Unraid-Auftrag Der Auto Tool Selector 3.5 erkennt einen ausdrücklich lesenden Unraid-Auftrag
und stellt ausschließlich `mua-readonly-local` bereit. Wörter wie „Folgen und stellt ausschließlich `mua-readonly-local` bereit. Wörter wie „Folgen
fehlen“ oder „Hörspielserie“ aktivieren nicht mehr fälschlich Sonarr/Radarr. fehlen“ oder „Hörspielserie“ aktivieren nicht mehr fälschlich Sonarr/Radarr.
Formulierungen wie „ohne Änderungen“, „ohne Downloads“ und „keinerlei Formulierungen wie „ohne Änderungen“, „ohne Downloads“ und „keinerlei
Änderungen“ verhindern zuverlässig die Auswahl von MUA-Admin. Änderungen“ verhindern zuverlässig die Auswahl von MUA-Admin.
Die öffentliche Recherche erfolgt anschließend mit Open WebUIs nativen Verlangt derselbe Auftrag aktuelle Online- oder Streaming-Belege, aktiviert der
Werkzeugen `search_web` und `fetch_url`. Selector zusätzlich Open WebUIs native Werkzeuge `search_web` und `fetch_url`.
Damit ist MUA plus Websuche ein einziger automatischer Mischauftrag; der alte
Web-MCP wird dafür nicht benötigt.
## Dateiinventar ## Dateiinventar
MUA r020 stellt `unraid_files_inventory` bereit. Das Werkzeug liest keine MUA r021 stellt `unraid_files_inventory` bereit. Das Werkzeug liest keine
Dateiinhalte und akzeptiert ausschließlich einen vorhandenen Unraid-Share plus Dateiinhalte und akzeptiert ausschließlich einen vorhandenen Unraid-Share plus
einen relativen Pfad unterhalb dieses Shares. Pfadtraversal, absolute Pfade und einen relativen Pfad unterhalb dieses Shares. Pfadtraversal, absolute Pfade und
Symlink-Verfolgung sind gesperrt. Tiefe, Trefferzahl und Zahl der untersuchten Symlink-Verfolgung sind gesperrt. Tiefe, Trefferzahl und Zahl der untersuchten
@@ -48,10 +50,9 @@ für Bibliotheksprüfungen nicht vorgesehen.
Der ursprüngliche Lauf zur Reihe „Die drei ???“ brauchte nach dem Share-Fund Der ursprüngliche Lauf zur Reihe „Die drei ???“ brauchte nach dem Share-Fund
vier einzelne Shell-Aufrufe und verbrauchte das Werkzeugbudget vor dem vier einzelne Shell-Aufrufe und verbrauchte das Werkzeugbudget vor dem
eigentlichen Datei- und Webabgleich. Dieser Fall ist der verbindliche eigentlichen Datei- und Webabgleich. Dieser Fall ist der verbindliche
Regressionstest für Selector 3.4 und MUA r020: Regressionstest für Selector 3.5 und MUA r021:
- automatisch nur MUA read-only; - automatisch nur MUA read-only;
- höchstens zwei Inventaraufrufe für Lokalisierung und Bestand; - höchstens zwei Inventaraufrufe für Lokalisierung und Bestand;
- danach native Webrecherche; - danach native Webrecherche;
- keine Rückfrage, kein Download und keine Dateisystemänderung. - keine Rückfrage, kein Download und keine Dateisystemänderung.
@@ -1,7 +1,7 @@
""" """
title: MikeAI Auto Tool Selector title: MikeAI Auto Tool Selector
author: MikeAI author: MikeAI
version: 3.4.0 version: 3.5.0
description: Selects a small, relevant set of MCP servers for each user request. description: Selects a small, relevant set of MCP servers for each user request.
""" """
@@ -74,6 +74,19 @@ class Filter:
return str(content) return str(content)
return "" return ""
def _needs_native_web(self, raw_text: str) -> bool:
"""Return whether this request explicitly requires current public-web evidence."""
text = self._normalise(raw_text)
return self._matches(
text,
(
r"\b(?:web|internet|online|websuche|webrecherche)\b",
r"\b(?:such|recherchier|pr[uü]f|schau)\w*\b.{0,80}\b(?:netz|web|internet|online)\b",
r"\b(?:deezer|youtube|makerworld|wikipedia|docker\s*hub)\b",
r"\b(?:aktuell|neueste|heute|bis heute)\w*\b.{0,100}\b(?:quelle|liste|verf[uü]gbar|erschienen|video|folge)\w*\b",
),
)
@staticmethod @staticmethod
def _add_system_rule(body: dict, labels: list[str], selected: list[str]) -> None: def _add_system_rule(body: dict, labels: list[str], selected: list[str]) -> None:
rule = ( rule = (
@@ -277,8 +290,25 @@ class Filter:
if not self.valves.enabled: if not self.valves.enabled:
return body return body
selected = self._classify(self._latest_user_text(body)) latest_text = self._latest_user_text(body)
selected = self._classify(latest_text)
needs_native_web = self._needs_native_web(latest_text)
if not selected and not needs_native_web:
return body
if needs_native_web:
features = body.setdefault("features", {})
if isinstance(features, dict):
features["web_search"] = True
metadata = body.setdefault("metadata", {})
if isinstance(metadata, dict):
metadata_features = metadata.setdefault("features", {})
if isinstance(metadata_features, dict):
metadata_features["web_search"] = True
if not selected: if not selected:
if needs_native_web:
await self._notify(__event_emitter__, ["native Websuche"])
return body return body
existing = body.get("tool_ids") existing = body.get("tool_ids")
@@ -298,7 +328,7 @@ class Filter:
# never overwritten. # never overwritten.
if ( if (
self.valves.enable_multidomain_reasoning self.valves.enable_multidomain_reasoning
and len(selected) >= 2 and len(selected) + int(needs_native_web) >= 2
and body.get("reasoning_effort") in (None, "", "none") and body.get("reasoning_effort") in (None, "", "none")
): ):
body["reasoning_effort"] = self.valves.multidomain_reasoning_effort body["reasoning_effort"] = self.valves.multidomain_reasoning_effort
@@ -306,6 +336,19 @@ class Filter:
body["reasoning_budget"] = self.valves.multidomain_reasoning_budget body["reasoning_budget"] = self.valves.multidomain_reasoning_budget
labels = [self.LABELS[category] for category in selected] labels = [self.LABELS[category] for category in selected]
if needs_native_web:
labels.append("native Websuche")
if selected:
self._add_system_rule(body, labels, selected) self._add_system_rule(body, labels, selected)
if needs_native_web:
for message in body.get("messages", []):
if message.get("role") == "system" and isinstance(message.get("content"), str):
message["content"] += (
" Native Open WebUI web search is also enabled for this request. "
"After collecting local or specialist-tool evidence, continue with "
"search_web/fetch_url for current public evidence; do not stop merely "
"because no separate web MCP appears in the MCP tool list."
)
break
await self._notify(__event_emitter__, labels) await self._notify(__event_emitter__, labels)
return body return body