From d0c51793af5c4d045fca4c859e407bf2679058e5 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Thu, 17 Apr 2025 22:07:00 +0200 Subject: [PATCH] remove thinking.py --- thinking.py | 173 ---------------------------------------------------- 1 file changed, 173 deletions(-) delete mode 100644 thinking.py diff --git a/thinking.py b/thinking.py deleted file mode 100644 index 90618f6..0000000 --- a/thinking.py +++ /dev/null @@ -1,173 +0,0 @@ -""" -title: Collapsible Thought Filter -author: projectmoon -author_url: https://git.agnos.is/projectmoon/open-webui-filters -version: 0.2.0 -license: AGPL-3.0+, MIT -required_open_webui_version: 0.3.32 -""" - -######################################################### -# OpenWebUI Filter that collapses model reasoning/thinking into a -# separate section in the reply. - -# Based on the Add or Delete Text Filter by anfi. -# https://openwebui.com/f/anfi/add_or_delete_text -# -# Therefore, portions of this code are licensed under the MIT license. -# The modifications made for "thought enclosure" etc are licensed -# under the AGPL using the MIT's sublicensing clause. -# -# For those portions under the MIT license, the following applies: -# -# MIT License -# -# Copyright (c) 2024 anfi -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -######################################################### - -from typing import Optional, Dict, List -import re -from pydantic import BaseModel, Field - -THOUGHT_ENCLOSURE = """ -
-{{THOUGHT_TITLE}} -{{THOUGHTS}} -
-""" - -DETAIL_DELETION_REGEX = r"[\s\S]*?" - -class Filter: - class Valves(BaseModel): - priority: int = Field( - default=0, description="Priority level for the filter operations." - ) - thought_title: str = Field( - default="Thought Process", - description="Title for the collapsible reasoning section." - ) - thought_tag: str = Field( - default="thinking", - description="The XML tag for model thinking output." - ) - output_tag: str = Field( - default="output", - description="The XML tag for model final output." - ) - use_thoughts_as_context: bool = Field( - default=False, - description=("Include previous thought processes as context for the AI. " - "Disabled by default.") - ) - pass - - def __init__(self): - self.valves = self.Valves() - - def _create_thought_regex(self) -> str: - tag = self.valves.thought_tag - return f"<{tag}>(.*?)" - - def _create_output_regex(self) -> str: - tag = self.valves.output_tag - return f"<{tag}>(.*?)" - - def _create_thought_tag_deletion_regex(self) -> str: - tag = self.valves.thought_tag - return "[\s\S]*?".replace("{{THINK}}", tag) - - def _create_output_tag_deletion_regex(self) -> str: - tag = self.valves.output_tag - return r"[\s\S]*?".replace("{{OUT}}", tag) - - def _enclose_thoughts(self, messages: List[Dict[str, str]]) -> None: - if not messages: - return - - # collapsible thinking process section - thought_regex = self._create_thought_regex() - output_regex = self._create_output_regex() - reply = messages[-1]["content"] - - thoughts = re.findall(thought_regex, reply, re.DOTALL) - thoughts = "\n".join(thoughts).strip() - - output = re.findall(output_regex, reply, re.DOTALL) - output = "\n".join(output).strip() - - enclosure = THOUGHT_ENCLOSURE.replace("{{THOUGHT_TITLE}}", self.valves.thought_title) - enclosure = enclosure.replace("{{THOUGHTS}}", thoughts).strip() - - # remove processed thinking and output tags. - # some models do not close output tags properly. - thought_tag_deletion_regex = self._create_thought_tag_deletion_regex() - output_tag_deletion_regex = self._create_output_tag_deletion_regex() - reply = re.sub(thought_tag_deletion_regex, "", reply, count=1) - reply = re.sub(output_tag_deletion_regex, "", reply, count=1) - reply = reply.replace(f"<{self.valves.output_tag}>", "", 1) - reply = reply.replace(f"", "", 1) - - # because some models do not close the output tag, we prefer - # using the captured output via regex, but if that does not - # work, we use whatever's left over as the output (which is - # already set). - if output is not None and len(output) > 0: - reply = output - - # prevents empty thought process blocks when filter used with - # malformed LLM output. - if len(enclosure) > 0: - reply = f"{enclosure}\n{reply}" - - messages[-1]["content"] = reply - - def _handle_include_thoughts(self, messages: List[Dict[str, str]]) -> None: - """Remove
tags from input, if configured to do so.""" - #
tags are created by the outlet filter for display - # in OWUI. - if self.valves.use_thoughts_as_context: - return - - for message in messages: - message["content"] = re.sub( - DETAIL_DELETION_REGEX, "", message["content"], count=1 - ) - - def inlet(self, body: Dict[str, any], __user__: Optional[Dict[str, any]] = None) -> Dict[str, any]: - try: - original_messages: List[Dict[str, str]] = body.get("messages", []) - self._handle_include_thoughts(original_messages) - body["messages"] = original_messages - return body - except Exception as e: - print(e) - return body - - def outlet(self, body: Dict[str, any], __user__: Optional[Dict[str, any]] = None) -> Dict[str, any]: - try: - original_messages: List[Dict[str, str]] = body.get("messages", []) - self._enclose_thoughts(original_messages) - body["messages"] = original_messages - return body - except Exception as e: - print(e) - return body