From 96b1f98e514979126d83781c493a3b4b839ae6d4 Mon Sep 17 00:00:00 2001 From: lilei Date: Wed, 16 Jul 2025 17:01:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Template=E8=B0=83=E6=95=B4name=E9=9D=9E?= =?UTF-8?q?=E5=BF=85=E5=A1=AB=E4=B8=8E=E5=A1=AB=E5=85=85=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Template调整name非必填与填充校验 #ICM71W --- jiuwen/core/common/exception/status_code.py | 1 + .../prompt/assemble/variables/textable.py | 4 ++- jiuwen/core/utils/prompt/template/template.py | 30 +++++++++++++++++-- .../utils/prompt/template/template_manager.py | 10 ++++++- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/jiuwen/core/common/exception/status_code.py b/jiuwen/core/common/exception/status_code.py index d8f2f82..11805e7 100644 --- a/jiuwen/core/common/exception/status_code.py +++ b/jiuwen/core/common/exception/status_code.py @@ -30,6 +30,7 @@ class StatusCode(Enum): # Prompt 模板管理 102100 - 102149 PROMPT_TEMPLATE_DUPLICATED_ERROR = (102101, "Template duplicated") PROMPT_TEMPLATE_NOT_FOUND_ERROR = (102102, "Template not found") + PROMPT_TEMPLATE_INCORRECT_ERROR = (102103, "Template data incorrect") # 插件管理 105000~105999 PLUGIN_UNEXPECTED_ERROR = (105001, "Plugin unexpected error") diff --git a/jiuwen/core/utils/prompt/assemble/variables/textable.py b/jiuwen/core/utils/prompt/assemble/variables/textable.py index 38bb726..de4a646 100644 --- a/jiuwen/core/utils/prompt/assemble/variables/textable.py +++ b/jiuwen/core/utils/prompt/assemble/variables/textable.py @@ -5,6 +5,8 @@ from jiuwen.core.common.exception.exception import JiuWenBaseException from jiuwen.core.common.exception.status_code import StatusCode from jiuwen.core.utils.prompt.assemble.variables.variable import Variable +TEMPLATE_VARIABLE_PLACEHOLDER_PATTERN = r"\{\{(.*?)\}\}" + class TextableVariable(Variable): """Variable class for processing string-type placeholders""" @@ -12,7 +14,7 @@ class TextableVariable(Variable): clean_text = text placeholders = [] input_keys = [] - placeholder_matches = re.finditer(r"\{\{(.*?)\}\}", text) + placeholder_matches = re.finditer(TEMPLATE_VARIABLE_PLACEHOLDER_PATTERN, text) for match in placeholder_matches: placeholder = match.group(1).strip() if len(placeholder) == 0: diff --git a/jiuwen/core/utils/prompt/template/template.py b/jiuwen/core/utils/prompt/template/template.py index 7fc9f5f..8e1de41 100644 --- a/jiuwen/core/utils/prompt/template/template.py +++ b/jiuwen/core/utils/prompt/template/template.py @@ -1,10 +1,16 @@ +import re from typing import Union, List, Dict from pydantic import BaseModel, Field + +from jiuwen.core.common.logging.base import logger +from jiuwen.core.common.exception.exception import JiuWenBaseException +from jiuwen.core.common.exception.status_code import StatusCode from jiuwen.core.utils.llm.messages import BaseMessage from jiuwen.core.utils.prompt.assemble.assembler import Assembler from jiuwen.core.utils.prompt.assemble.message_handler import template_to_messages +from jiuwen.core.utils.prompt.assemble.variables.textable import TEMPLATE_VARIABLE_PLACEHOLDER_PATTERN class Template(BaseModel): @@ -12,7 +18,7 @@ class Template(BaseModel): template data """ - name: str + name: str = Field(default='') content: Union[List[Dict], List[BaseMessage], str] filters: dict = Field(default=None) @@ -31,8 +37,12 @@ class Template(BaseModel): elif isinstance(msg, dict): messages.append(BaseMessage(**msg)) else: - pass + raise JiuWenBaseException( + error_code=StatusCode.PROMPT_TEMPLATE_INCORRECT_ERROR.code, + message=f"Template type must be in str, list[dict] or list[BaseMessage]." + ) self.content = messages + self._validate_template_content_assembled() return self.content def format(self, keywords: dict = None): @@ -44,3 +54,19 @@ class Template(BaseModel): if keywords and keywords.get(key): format_dict[key] = keywords.get(key) self.content = assembler.assemble(**format_dict) + return self + + def _validate_template_content_assembled(self): + if isinstance(self.content, str): + placeholder_matches = re.findall(TEMPLATE_VARIABLE_PLACEHOLDER_PATTERN, self.content) + if placeholder_matches: + logger.warning(f"template content has not assembled " + f"with variable placeholders: {', '.join(placeholder_matches)}") + return + for message in self.content: + content = message.content if isinstance(message, BaseMessage) else message.get('content', '') + placeholder_matches = re.findall(TEMPLATE_VARIABLE_PLACEHOLDER_PATTERN, content) + if placeholder_matches: + logger.warning(f"template content has not assembled " + f"with variable placeholders: {', '.join(placeholder_matches)}") + return diff --git a/jiuwen/core/utils/prompt/template/template_manager.py b/jiuwen/core/utils/prompt/template/template_manager.py index 6a37a17..c52f2f7 100644 --- a/jiuwen/core/utils/prompt/template/template_manager.py +++ b/jiuwen/core/utils/prompt/template/template_manager.py @@ -3,6 +3,9 @@ import os from typing import Callable, List from jiuwen.core.common.logging.base import logger + +from jiuwen.core.common.exception.exception import JiuWenBaseException +from jiuwen.core.common.exception.status_code import StatusCode from jiuwen.core.utils.prompt.assemble.message_handler import messages_to_template, template_to_messages from jiuwen.core.utils.prompt.common.singleton import Singleton from jiuwen.core.utils.prompt.index.template_store.in_memory_template_store import InMemoryTemplateStore @@ -45,7 +48,7 @@ class TemplateManager(metaclass=Singleton): """init customer templates""" customer_templates_path = os.environ.get("PROMPT_DEFAULT_TEMPLATES_PATH", None) if not customer_templates_path: - logger.warn("Customer templates path is not set") + logger.warning("Customer templates path is not set") return self.__load_default_templates_dir(customer_templates_path) @@ -70,6 +73,11 @@ class TemplateManager(metaclass=Singleton): def register(self, template: Template, force: bool = False): """register template""" + if not template.name: + raise JiuWenBaseException( + error_code=StatusCode.PROMPT_TEMPLATE_INCORRECT_ERROR.code, + message="Template data is missing `name` field when registering." + ) template_copy = copy.deepcopy(template) if isinstance(template_copy.content, list): template_copy.content = messages_to_template(template_copy.content) -- Gitee