feat: 插件新增配置项以支持在渲染新结果前清除旧的 HTML 输出
This commit is contained in:
@@ -50,6 +50,7 @@ Content to process:
|
|||||||
|
|
||||||
# HTML Template for rendering the result in the chat
|
# HTML Template for rendering the result in the chat
|
||||||
HTML_TEMPLATE = """
|
HTML_TEMPLATE = """
|
||||||
|
<!-- OPENWEBUI_PLUGIN_OUTPUT -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{user_language}">
|
<html lang="{user_language}">
|
||||||
<head>
|
<head>
|
||||||
@@ -86,6 +87,10 @@ class Action:
|
|||||||
default=50,
|
default=50,
|
||||||
description="Minimum text length required for processing (characters).",
|
description="Minimum text length required for processing (characters).",
|
||||||
)
|
)
|
||||||
|
CLEAR_PREVIOUS_HTML: bool = Field(
|
||||||
|
default=False,
|
||||||
|
description="Whether to clear existing plugin-generated HTML content in the message before appending new results (identified by marker).",
|
||||||
|
)
|
||||||
# Add other configuration fields as needed
|
# Add other configuration fields as needed
|
||||||
# MAX_TEXT_LENGTH: int = Field(default=2000, description="...")
|
# MAX_TEXT_LENGTH: int = Field(default=2000, description="...")
|
||||||
|
|
||||||
@@ -138,6 +143,12 @@ class Action:
|
|||||||
# pass
|
# pass
|
||||||
return llm_output.strip()
|
return llm_output.strip()
|
||||||
|
|
||||||
|
def _remove_existing_html(self, content: str) -> str:
|
||||||
|
"""Removes existing plugin-generated HTML code blocks from the content."""
|
||||||
|
# Match ```html <!-- OPENWEBUI_PLUGIN_OUTPUT --> ... ``` pattern
|
||||||
|
pattern = r"```html\s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[\s\S]*?```"
|
||||||
|
return re.sub(pattern, "", content).strip()
|
||||||
|
|
||||||
async def _emit_status(
|
async def _emit_status(
|
||||||
self,
|
self,
|
||||||
emitter: Optional[Callable[[Any], Awaitable[None]]],
|
emitter: Optional[Callable[[Any], Awaitable[None]]],
|
||||||
@@ -253,6 +264,11 @@ class Action:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 9. Inject Result
|
# 9. Inject Result
|
||||||
|
if self.valves.CLEAR_PREVIOUS_HTML:
|
||||||
|
body["messages"][-1]["content"] = self._remove_existing_html(
|
||||||
|
body["messages"][-1]["content"]
|
||||||
|
)
|
||||||
|
|
||||||
html_embed_tag = f"```html\n{final_html}\n```"
|
html_embed_tag = f"```html\n{final_html}\n```"
|
||||||
body["messages"][-1]["content"] += f"\n\n{html_embed_tag}"
|
body["messages"][-1]["content"] += f"\n\n{html_embed_tag}"
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ USER_PROMPT_TEMPLATE = """
|
|||||||
|
|
||||||
# 用于在聊天中渲染结果的 HTML 模板
|
# 用于在聊天中渲染结果的 HTML 模板
|
||||||
HTML_TEMPLATE = """
|
HTML_TEMPLATE = """
|
||||||
|
<!-- OPENWEBUI_PLUGIN_OUTPUT -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{user_language}">
|
<html lang="{user_language}">
|
||||||
<head>
|
<head>
|
||||||
@@ -86,6 +87,10 @@ class Action:
|
|||||||
default=50,
|
default=50,
|
||||||
description="处理所需的最小文本长度(字符数)。",
|
description="处理所需的最小文本长度(字符数)。",
|
||||||
)
|
)
|
||||||
|
CLEAR_PREVIOUS_HTML: bool = Field(
|
||||||
|
default=False,
|
||||||
|
description="是否在追加新结果前清除消息中已有的插件生成 HTML 内容 (通过标记识别)。",
|
||||||
|
)
|
||||||
# 根据需要添加其他配置字段
|
# 根据需要添加其他配置字段
|
||||||
# MAX_TEXT_LENGTH: int = Field(default=2000, description="...")
|
# MAX_TEXT_LENGTH: int = Field(default=2000, description="...")
|
||||||
|
|
||||||
@@ -138,6 +143,13 @@ class Action:
|
|||||||
# pass
|
# pass
|
||||||
return llm_output.strip()
|
return llm_output.strip()
|
||||||
|
|
||||||
|
def _remove_existing_html(self, content: str) -> str:
|
||||||
|
"""移除内容中已有的插件生成 HTML 代码块 (通过标记识别)。"""
|
||||||
|
# 匹配 ```html <!-- OPENWEBUI_PLUGIN_OUTPUT --> ... ``` 模式
|
||||||
|
# 使用 [\s\S]*? 非贪婪匹配任意字符
|
||||||
|
pattern = r"```html\s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[\s\S]*?```"
|
||||||
|
return re.sub(pattern, "", content).strip()
|
||||||
|
|
||||||
async def _emit_status(
|
async def _emit_status(
|
||||||
self,
|
self,
|
||||||
emitter: Optional[Callable[[Any], Awaitable[None]]],
|
emitter: Optional[Callable[[Any], Awaitable[None]]],
|
||||||
@@ -253,6 +265,11 @@ class Action:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 9. 注入结果
|
# 9. 注入结果
|
||||||
|
if self.valves.CLEAR_PREVIOUS_HTML:
|
||||||
|
body["messages"][-1]["content"] = self._remove_existing_html(
|
||||||
|
body["messages"][-1]["content"]
|
||||||
|
)
|
||||||
|
|
||||||
html_embed_tag = f"```html\n{final_html}\n```"
|
html_embed_tag = f"```html\n{final_html}\n```"
|
||||||
body["messages"][-1]["content"] += f"\n\n{html_embed_tag}"
|
body["messages"][-1]["content"] += f"\n\n{html_embed_tag}"
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ class Action:
|
|||||||
default=True,
|
default=True,
|
||||||
description="Whether to show status updates in the chat interface.",
|
description="Whether to show status updates in the chat interface.",
|
||||||
)
|
)
|
||||||
|
clear_previous_html: bool = Field(
|
||||||
|
default=False,
|
||||||
|
description="Whether to clear existing plugin-generated HTML content in the message before appending new results (identified by marker).",
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.valves = self.Valves()
|
self.valves = self.Valves()
|
||||||
@@ -176,6 +180,11 @@ Important Principles:
|
|||||||
html_card = self.generate_html_card(card_data)
|
html_card = self.generate_html_card(card_data)
|
||||||
|
|
||||||
# 3. Append to message
|
# 3. Append to message
|
||||||
|
if self.valves.clear_previous_html:
|
||||||
|
body["messages"][-1]["content"] = self._remove_existing_html(
|
||||||
|
body["messages"][-1]["content"]
|
||||||
|
)
|
||||||
|
|
||||||
html_embed_tag = f"```html\n{html_card}\n```"
|
html_embed_tag = f"```html\n{html_card}\n```"
|
||||||
body["messages"][-1]["content"] += f"\n\n{html_embed_tag}"
|
body["messages"][-1]["content"] += f"\n\n{html_embed_tag}"
|
||||||
|
|
||||||
@@ -206,9 +215,15 @@ Important Principles:
|
|||||||
)
|
)
|
||||||
return body
|
return body
|
||||||
|
|
||||||
|
def _remove_existing_html(self, content: str) -> str:
|
||||||
|
"""Removes existing plugin-generated HTML code blocks from the content."""
|
||||||
|
pattern = r"```html\s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[\s\S]*?```"
|
||||||
|
return re.sub(pattern, "", content).strip()
|
||||||
|
|
||||||
def generate_html_card(self, data):
|
def generate_html_card(self, data):
|
||||||
# Enhanced CSS with premium styling
|
# Enhanced CSS with premium styling
|
||||||
style = """
|
style = """
|
||||||
|
<!-- OPENWEBUI_PLUGIN_OUTPUT -->
|
||||||
<style>
|
<style>
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ class Action:
|
|||||||
show_status: bool = Field(
|
show_status: bool = Field(
|
||||||
default=True, description="是否在聊天界面显示状态更新。"
|
default=True, description="是否在聊天界面显示状态更新。"
|
||||||
)
|
)
|
||||||
|
clear_previous_html: bool = Field(
|
||||||
|
default=False,
|
||||||
|
description="是否在追加新结果前清除消息中已有的插件生成 HTML 内容 (通过标记识别)。",
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.valves = self.Valves()
|
self.valves = self.Valves()
|
||||||
@@ -178,6 +182,11 @@ class Action:
|
|||||||
# Actions usually modify the input or trigger a side effect.
|
# Actions usually modify the input or trigger a side effect.
|
||||||
# To show the card, we can append it to the message content.
|
# To show the card, we can append it to the message content.
|
||||||
|
|
||||||
|
if self.valves.clear_previous_html:
|
||||||
|
body["messages"][-1]["content"] = self._remove_existing_html(
|
||||||
|
body["messages"][-1]["content"]
|
||||||
|
)
|
||||||
|
|
||||||
html_embed_tag = f"```html\n{html_card}\n```"
|
html_embed_tag = f"```html\n{html_card}\n```"
|
||||||
body["messages"][-1]["content"] += f"\n\n{html_embed_tag}"
|
body["messages"][-1]["content"] += f"\n\n{html_embed_tag}"
|
||||||
|
|
||||||
@@ -208,9 +217,15 @@ class Action:
|
|||||||
)
|
)
|
||||||
return body
|
return body
|
||||||
|
|
||||||
|
def _remove_existing_html(self, content: str) -> str:
|
||||||
|
"""移除内容中已有的插件生成 HTML 代码块 (通过标记识别)。"""
|
||||||
|
pattern = r"```html\s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[\s\S]*?```"
|
||||||
|
return re.sub(pattern, "", content).strip()
|
||||||
|
|
||||||
def generate_html_card(self, data):
|
def generate_html_card(self, data):
|
||||||
# Enhanced CSS with premium styling
|
# Enhanced CSS with premium styling
|
||||||
style = """
|
style = """
|
||||||
|
<!-- OPENWEBUI_PLUGIN_OUTPUT -->
|
||||||
<style>
|
<style>
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ User Language: {user_language}
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
HTML_TEMPLATE_MINDMAP = """
|
HTML_TEMPLATE_MINDMAP = """
|
||||||
|
<!-- OPENWEBUI_PLUGIN_OUTPUT -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{user_language}">
|
<html lang="{user_language}">
|
||||||
<head>
|
<head>
|
||||||
@@ -369,6 +370,10 @@ class Action:
|
|||||||
default=100,
|
default=100,
|
||||||
description="Minimum text length (character count) required for mind map analysis.",
|
description="Minimum text length (character count) required for mind map analysis.",
|
||||||
)
|
)
|
||||||
|
CLEAR_PREVIOUS_HTML: bool = Field(
|
||||||
|
default=False,
|
||||||
|
description="Whether to clear existing plugin-generated HTML content in the message before appending new results (identified by marker).",
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.valves = self.Valves()
|
self.valves = self.Valves()
|
||||||
@@ -393,6 +398,11 @@ class Action:
|
|||||||
extracted_content = llm_output.strip()
|
extracted_content = llm_output.strip()
|
||||||
return extracted_content.replace("</script>", "<\\/script>")
|
return extracted_content.replace("</script>", "<\\/script>")
|
||||||
|
|
||||||
|
def _remove_existing_html(self, content: str) -> str:
|
||||||
|
"""Removes existing plugin-generated HTML code blocks from the content."""
|
||||||
|
pattern = r"```html\s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[\s\S]*?```"
|
||||||
|
return re.sub(pattern, "", content).strip()
|
||||||
|
|
||||||
async def action(
|
async def action(
|
||||||
self,
|
self,
|
||||||
body: dict,
|
body: dict,
|
||||||
@@ -558,6 +568,9 @@ class Action:
|
|||||||
.replace("{markdown_syntax}", markdown_syntax)
|
.replace("{markdown_syntax}", markdown_syntax)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.valves.CLEAR_PREVIOUS_HTML:
|
||||||
|
long_text_content = self._remove_existing_html(long_text_content)
|
||||||
|
|
||||||
html_embed_tag = f"```html\n{final_html_content}\n```"
|
html_embed_tag = f"```html\n{final_html_content}\n```"
|
||||||
body["messages"][-1]["content"] = f"{long_text_content}\n\n{html_embed_tag}"
|
body["messages"][-1]["content"] = f"{long_text_content}\n\n{html_embed_tag}"
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ Python
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
HTML_TEMPLATE_MINDMAP = """
|
HTML_TEMPLATE_MINDMAP = """
|
||||||
|
<!-- OPENWEBUI_PLUGIN_OUTPUT -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{user_language}">
|
<html lang="{user_language}">
|
||||||
<head>
|
<head>
|
||||||
@@ -367,7 +368,12 @@ class Action:
|
|||||||
description="用于文本分析的内置LLM模型ID。如果为空,则使用当前对话的模型。",
|
description="用于文本分析的内置LLM模型ID。如果为空,则使用当前对话的模型。",
|
||||||
)
|
)
|
||||||
MIN_TEXT_LENGTH: int = Field(
|
MIN_TEXT_LENGTH: int = Field(
|
||||||
default=100, description="进行思维导图分析所需的最小文本长度(字符数)。"
|
default=100,
|
||||||
|
description="进行思维导图分析所需的最小文本长度(字符数)。",
|
||||||
|
)
|
||||||
|
CLEAR_PREVIOUS_HTML: bool = Field(
|
||||||
|
default=False,
|
||||||
|
description="是否在追加新结果前清除消息中已有的插件生成 HTML 内容 (通过标记识别)。",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -393,6 +399,11 @@ class Action:
|
|||||||
extracted_content = llm_output.strip()
|
extracted_content = llm_output.strip()
|
||||||
return extracted_content.replace("</script>", "<\\/script>")
|
return extracted_content.replace("</script>", "<\\/script>")
|
||||||
|
|
||||||
|
def _remove_existing_html(self, content: str) -> str:
|
||||||
|
"""移除内容中已有的插件生成 HTML 代码块 (通过标记识别)。"""
|
||||||
|
pattern = r"```html\s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[\s\S]*?```"
|
||||||
|
return re.sub(pattern, "", content).strip()
|
||||||
|
|
||||||
async def action(
|
async def action(
|
||||||
self,
|
self,
|
||||||
body: dict,
|
body: dict,
|
||||||
@@ -557,6 +568,9 @@ class Action:
|
|||||||
.replace("{markdown_syntax}", markdown_syntax)
|
.replace("{markdown_syntax}", markdown_syntax)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.valves.CLEAR_PREVIOUS_HTML:
|
||||||
|
long_text_content = self._remove_existing_html(long_text_content)
|
||||||
|
|
||||||
html_embed_tag = f"```html\n{final_html_content}\n```"
|
html_embed_tag = f"```html\n{final_html_content}\n```"
|
||||||
body["messages"][-1]["content"] = f"{long_text_content}\n\n{html_embed_tag}"
|
body["messages"][-1]["content"] = f"{long_text_content}\n\n{html_embed_tag}"
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ Please conduct a deep and comprehensive analysis, focusing on actionable advice.
|
|||||||
# =================================================================
|
# =================================================================
|
||||||
|
|
||||||
HTML_TEMPLATE = """
|
HTML_TEMPLATE = """
|
||||||
|
<!-- OPENWEBUI_PLUGIN_OUTPUT -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{ user_language }}">
|
<html lang="{{ user_language }}">
|
||||||
<head>
|
<head>
|
||||||
@@ -292,6 +293,10 @@ class Action:
|
|||||||
default=500,
|
default=500,
|
||||||
description="Recommended minimum text length for best analysis results.",
|
description="Recommended minimum text length for best analysis results.",
|
||||||
)
|
)
|
||||||
|
CLEAR_PREVIOUS_HTML: bool = Field(
|
||||||
|
default=False,
|
||||||
|
description="Whether to clear existing plugin-generated HTML content in the message before appending new results (identified by marker).",
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.valves = self.Valves()
|
self.valves = self.Valves()
|
||||||
@@ -348,6 +353,11 @@ class Action:
|
|||||||
"actions_html": actions_html,
|
"actions_html": actions_html,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _remove_existing_html(self, content: str) -> str:
|
||||||
|
"""Removes existing plugin-generated HTML code blocks from the content."""
|
||||||
|
pattern = r"```html\s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[\s\S]*?```"
|
||||||
|
return re.sub(pattern, "", content).strip()
|
||||||
|
|
||||||
def _build_html(self, context: dict) -> str:
|
def _build_html(self, context: dict) -> str:
|
||||||
"""
|
"""
|
||||||
Build final HTML content using Jinja2 template and context data.
|
Build final HTML content using Jinja2 template and context data.
|
||||||
@@ -488,6 +498,10 @@ class Action:
|
|||||||
}
|
}
|
||||||
|
|
||||||
final_html_content = self._build_html(context)
|
final_html_content = self._build_html(context)
|
||||||
|
|
||||||
|
if self.valves.CLEAR_PREVIOUS_HTML:
|
||||||
|
original_content = self._remove_existing_html(original_content)
|
||||||
|
|
||||||
html_embed_tag = f"```html\n{final_html_content}\n```"
|
html_embed_tag = f"```html\n{final_html_content}\n```"
|
||||||
body["messages"][-1]["content"] = f"{original_content}\n\n{html_embed_tag}"
|
body["messages"][-1]["content"] = f"{original_content}\n\n{html_embed_tag}"
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ USER_PROMPT_GENERATE_SUMMARY = """
|
|||||||
# =================================================================
|
# =================================================================
|
||||||
|
|
||||||
HTML_TEMPLATE = """
|
HTML_TEMPLATE = """
|
||||||
|
<!-- OPENWEBUI_PLUGIN_OUTPUT -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{ user_language }}">
|
<html lang="{{ user_language }}">
|
||||||
<head>
|
<head>
|
||||||
@@ -287,6 +288,10 @@ class Action:
|
|||||||
RECOMMENDED_MIN_LENGTH: int = Field(
|
RECOMMENDED_MIN_LENGTH: int = Field(
|
||||||
default=500, description="建议的最小文本长度,以获得最佳分析效果。"
|
default=500, description="建议的最小文本长度,以获得最佳分析效果。"
|
||||||
)
|
)
|
||||||
|
CLEAR_PREVIOUS_HTML: bool = Field(
|
||||||
|
default=False,
|
||||||
|
description="是否在追加新结果前清除消息中已有的插件生成 HTML 内容 (通过标记识别)。",
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.valves = self.Valves()
|
self.valves = self.Valves()
|
||||||
@@ -337,6 +342,11 @@ class Action:
|
|||||||
"actions_html": actions_html,
|
"actions_html": actions_html,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _remove_existing_html(self, content: str) -> str:
|
||||||
|
"""移除内容中已有的插件生成 HTML 代码块 (通过标记识别)。"""
|
||||||
|
pattern = r"```html\s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[\s\S]*?```"
|
||||||
|
return re.sub(pattern, "", content).strip()
|
||||||
|
|
||||||
def _build_html(self, context: dict) -> str:
|
def _build_html(self, context: dict) -> str:
|
||||||
"""
|
"""
|
||||||
使用 Jinja2 模板和上下文数据构建最终的HTML内容。
|
使用 Jinja2 模板和上下文数据构建最终的HTML内容。
|
||||||
@@ -477,6 +487,10 @@ class Action:
|
|||||||
}
|
}
|
||||||
|
|
||||||
final_html_content = self._build_html(context)
|
final_html_content = self._build_html(context)
|
||||||
|
|
||||||
|
if self.valves.CLEAR_PREVIOUS_HTML:
|
||||||
|
original_content = self._remove_existing_html(original_content)
|
||||||
|
|
||||||
html_embed_tag = f"```html\n{final_html_content}\n```"
|
html_embed_tag = f"```html\n{final_html_content}\n```"
|
||||||
body["messages"][-1]["content"] = f"{original_content}\n\n{html_embed_tag}"
|
body["messages"][-1]["content"] = f"{original_content}\n\n{html_embed_tag}"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user