fix: combine specialist tools with native web search
This commit is contained in:
@@ -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?"
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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]
|
||||||
self._add_system_rule(body, labels, selected)
|
if needs_native_web:
|
||||||
|
labels.append("native Websuche")
|
||||||
|
if 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
|
||||||
|
|||||||
Reference in New Issue
Block a user