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

EmptyFormatterapply方法简单地返回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可能用于生成结构化的文本,如聊天模板或其他需要动态内容填充的场景。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐