import json
import re
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import List, Literal, Optional, Tuple, Union
from .data_utils import SLOTS
from .tool_utils import DefaultToolUtils, GLM4ToolUtils
@dataclass
class Formatter(ABC):
slots: SLOTS = field(default_factory=list)
tool_format: Optional[Literal["default", "glm4"]] = None
@abstractmethod
def apply(self, **kwargs) -> SLOTS: ...
def extract(self, content: str) -> Union[str, List[Tuple[str, str]]]:
raise NotImplementedError
@dataclass
class EmptyFormatter(Formatter):
def __post_init__(self):
has_placeholder = False
for slot in filter(lambda s: isinstance(s, str), self.slots):
if re.search(r"\{\{[a-zA-Z_][a-zA-Z0-9_]*\}\}", slot):
has_placeholder = True
if has_placeholder:
raise ValueError("Empty formatter should not contain any placeholder.")
def apply(self, **kwargs) -> SLOTS:
return self.slots
我会为您逐行解释这段代码:
python
复制
from .data_utils import SLOTS
from .tool_utils import DefaultToolUtils, GLM4ToolUtils
这些是导入语句,从当前包的其他模块导入所需的类型和工具。
python
复制
@dataclass
class Formatter(ABC):
定义了一个名为Formatter
的抽象基类,使用了@dataclass
装饰器。
python
复制
slots: SLOTS = field(default_factory=list)
定义了一个名为slots
的属性,类型为SLOTS
,默认值是一个空列表。
python
复制
tool_format: Optional[Literal["default", "glm4"]] = None
定义了一个名为tool_format
的可选属性,可以是"default"或"glm4",默认为None。
python
复制
@abstractmethod
def apply(self, **kwargs) -> SLOTS: ...
定义了一个抽象方法apply
,它接受任意关键字参数并返回SLOTS
类型。子类必须实现这个方法。
python
复制
def extract(self, content: str) -> Union[str, List[Tuple[str, str]]]:
raise NotImplementedError
定义了一个extract
方法,但默认实现抛出NotImplementedError
。子类可以选择性地重写这个方法。
python
复制
@dataclass
class EmptyFormatter(Formatter):
定义了一个名为EmptyFormatter
的类,它继承自Formatter
。
python
复制
def __post_init__(self):
这是一个在对象初始化后自动调用的方法。
python
复制
has_placeholder = False
for slot in filter(lambda s: isinstance(s, str), self.slots):
if re.search(r"\{\{[a-zA-Z_][a-zA-Z0-9_]*\}\}", slot):
has_placeholder = True
这段代码检查self.slots
中的字符串是否包含占位符(形如{{name}}
)。
python
复制
if has_placeholder:
raise ValueError("Empty formatter should not contain any placeholder.")
如果发现占位符,抛出ValueError
异常。这是因为EmptyFormatter
不应包含任何占位符。
python
复制
def apply(self, **kwargs) -> SLOTS:
return self.slots
EmptyFormatter
的apply
方法简单地返回self.slots
,不进行任何处理。
这段代码定义了一个格式化器的基础结构。Formatter
是一个抽象基类,定义了格式化器应该具有的基本接口。EmptyFormatter
是一个具体的实现,它不对输入进行任何处理,只是简单地返回原始的slots。这种设计允许在需要时创建更复杂的格式化器,同时保持了一个统一的接口。
@dataclass
class StringFormatter(Formatter):
def __post_init__(self):
has_placeholder = False
for slot in filter(lambda s: isinstance(s, str), self.slots):
if re.search(r"\{\{[a-zA-Z_][a-zA-Z0-9_]*\}\}", slot):
has_placeholder = True
if not has_placeholder:
raise ValueError("A placeholder is required in the string formatter.")
def apply(self, **kwargs) -> SLOTS:
elements = []
for slot in self.slots:
if isinstance(slot, str):
for name, value in kwargs.items():
if not isinstance(value, str):
raise RuntimeError("Expected a string, got {}".format(value))
slot = slot.replace("{{" + name + "}}", value, 1)
elements.append(slot)
elif isinstance(slot, (dict, set)):
elements.append(slot)
else:
raise RuntimeError("Input must be string, set[str] or dict[str, str], got {}".format(type(slot)))
return elements
我会为您逐行解释这段代码:
python
复制
@dataclass
class StringFormatter(Formatter):
这定义了一个名为StringFormatter
的类,它继承自Formatter
类。@dataclass
装饰器用于自动生成一些常用的方法,如__init__
、__repr__
等。
python
复制
def __post_init__(self):
这是一个特殊方法,在对象初始化后自动调用。它用于执行一些额外的初始化逻辑。
python
复制
has_placeholder = False
for slot in filter(lambda s: isinstance(s, str), self.slots):
if re.search(r"\{\{[a-zA-Z_][a-zA-Z0-9_]*\}\}", slot):
has_placeholder = True
这段代码检查self.slots
中的字符串是否包含占位符(形如{{name}}
)。它使用正则表达式来查找这种模式。
python
复制
if not has_placeholder:
raise ValueError("A placeholder is required in the string formatter.")
如果没有找到占位符,抛出一个ValueError
异常。
python
复制
def apply(self, **kwargs) -> SLOTS:
定义apply
方法,接受任意关键字参数,返回类型为SLOTS
(这可能是在其他地方定义的类型)。
python
复制
elements = []
初始化一个空列表来存储处理后的元素。
python
复制
for slot in self.slots:
if isinstance(slot, str):
遍历self.slots
中的每个元素。如果元素是字符串:
python
复制
for name, value in kwargs.items():
if not isinstance(value, str):
raise RuntimeError("Expected a string, got {}".format(value))
slot = slot.replace("{{" + name + "}}", value, 1)
用提供的关键字参数替换字符串中的占位符。如果值不是字符串,抛出RuntimeError
。
python
复制
elements.append(slot)
将处理后的字符串添加到elements
列表。
python
复制
elif isinstance(slot, (dict, set)):
elements.append(slot)
如果slot是字典或集合,直接添加到elements
列表。
python
复制
else:
raise RuntimeError("Input must be string, set[str] or dict[str, str], got {}".format(type(slot)))
如果slot既不是字符串也不是字典或集合,抛出RuntimeError
。
python
复制
return elements
返回处理后的elements
列表。
总的来说,这个StringFormatter
类用于处理包含占位符的字符串模板。它确保模板中至少有一个占位符,并提供了一个apply
方法来用实际值替换这些占位符。这种formatter可能用于生成结构化的文本,如聊天模板或其他需要动态内容填充的场景。