SmartETL:大模型赋能的开源情报数据处理框架(5)

1. 项目简介

SmartETL:一个简单实用、灵活可配、开箱即用的Python数据处理(ETL)框架,提供Wikidata / Wikipedia / GDELT等多种开源情报数据的处理流程; 支持大模型、API、常见文件、数据库等多种输入输出及转换处理,支撑各类数据集成接入大数据处理、离线分析计算、AI智能分析知识图谱构建等任务。项目内置50+常用流程、180+常用ETL算子、10+领域特色数据处理流程,覆盖常见数据处理需求。

项目源码已经开放在SmartETL,感兴趣的小伙伴可以直接拉取源码进行试用,并且这个项目我会持续丰富完善,也欢迎大家提出提意见或是直接提出数据处理需求,也可以一起来参与项目建设。

文本是《SmartETL:大模型赋能的开源情报数据处理框架》系列第五篇,介绍processor数据处理算子(T+L)设计。

2.Processor设计

SmartETL中数据处理(包括T和L两个阶段)节点统一设计为Processor,对应YAML流程配置文件中的processor nodes默认节点类型,对应Python模块为wikidata_filter.iterator
采用面向对象的设计,定义了JsonIterator这个抽象基类(abstract base class),设计如下(源码见https://github.com/ictchenbo/SmartETL/blob/main/wikidata_filter/iterator/base.py):

class JsonIterator:
    """流程处理算子(不包括数据加载)的基础接口"""
    def _set(self, **kwargs):
        """设置组件参数,提供对象属性链式设置"""
        for k, w in kwargs.items():
            setattr(self, k, w)
        return self

    def _get(self, key: str):
        """获取组件参数"""
        return getattr(self, key)

    def on_start(self):
        """处理数据前,主要用于一些数据处理的准备工作,不应该用于具体数据处理"""
        pass

    def on_data(self, data: Any, *args):
        """处理数据的方法。根据实际需要重写此方法。"""
        pass

    def __process__(self, data: Any, *args):
        """内部调用的处理方法,先判断是否为None 否则调用on_data进行处理,普通节点的on_data方法不会接收到None"""
        # print(f'{self.name}.__process__', data)
        if data is not None:
            if isinstance(data, Message):
                if data.msg_type == 'end':
                    # print(f'{self.name} end')
                    pass
                else:
                    self.on_data(data.data)
            else:
                return self.on_data(data)

    def on_complete(self):
        """结束处理。主要用于数据处理结束后的清理工作,不应该用于具体数据处理"""
        pass

    @property
    def name(self):
        return self.__class__.__name__

    def __str__(self):
        return f"{self.name}"
  • __init__(self, *args, **kwargs) 构造方法,是YAML组件构造表达式中大部分情况就是对这个方法的调用,例如“Print”等价于“Print()”,就是调用“wikidata_filter.iterator.Print”class的__init__方法。这里可以看到,如果组件的__init__方法支持默认参数,对组件使用者将会非常便利。
  • _set(self, **kwargs) 设置节点的属性,支持链式语法,方便在YAML组件构造表达式中调用。
  • on_data(self, data: Any, *args) 定义数据处理方法,主要通过重写此方法实现具体数据处理逻辑。如果在数据处理流程中,某个Processor节点输出为None,会停止消息流处理,因此不会调用此方法。
  • __process__(self, data: Any, *args) 这是框架内部引擎直接调用的数据处理方法,与on_data区别在于可以接收Message类型消息和None消息。默认处理逻辑为:如果dataNone,则直接返回;否则如果dataMessage类型且消息不为end,则调用on_data处理该消息包裹的具体消息(data.data);否则如果data不是Message,则调用on_data处理该消息;否则,直接返回。
  • on_start(self) 节点初始化方法,比如创建数据库连接。在具体开发时,也可以在构造方法__init__中进行节点初始化。
  • on_complete(self) 数据处理完成后调用的方法,主要用于节点清理,比如关闭数据库连接、关闭文件等。
  • _get(self, key: str) 获取节点的属性。
  • @property name(self) 获取节点名称。
  • __str__(self) 节点的字符串表示,可重写以提供更加友好的表示。

3.Processor体系

采用继承、封装和多态的面向对象设计思想进行Processor体系设计,实现大量算子的体系化组织和高效率扩展。
Processor组件体系

主要包括以下几个分支:

  1. 流程控制组件,目前包括ChainFork,分别实现串行和并行处理逻辑,这是与流程执行引擎实现关系最紧密的组件,下一步扩展执行引擎、性能优化都需要从这类组件上下功夫。
  2. Map,实现数据的1->1转换处理。Map自身需要提供一个mapper函数,支持行级或字段级的转换(根据是否提供key参数确定),支持选择目标字段(target_key,如果未提供,则与key值相同)。子类可通过实现__call__方法,从而将自身作为mapper参数传递给Map构造方法。Map子类主要包括:MapUtil(通过提供任意的工具函数进行Map处理)、MapFill(基于提供的dict进行source_key值查找并设置为target_key字段)、Format(对字符串字段进行格式化)、FromJson(从json字符串字段加载为json对象)、ToJson(对任意对象序列化为json字符串)等。此外,单独提供一个Function,可调用任意给定函数,实现数据处理。
  3. Flat,实现数据的扁平化操作,即1->*处理模式。支持行级或字段级的Flat转换(根据是否提供key参数确定)。根据不同数据类型进行Flat,如果是数组、元组或set类型(主要应用场景),则将其每个元素作为一条单独的数据输出;如果是字典类型,则根据flat_mode配置,提供kv、key、value三种输出模式。Flat子类主要包括:FlatMap(通过提供mapper函数获取需要Flat对象,而不是输入数据本身)、FlatProperty(假设输入为dict,对其某个类型为dict的字段进行Flat,达到字段提升的效果)等。
  4. Filter,实现数据的过滤,即1->0/1处理模式。对经过Filter的数据,只有符合某种条件才能输出,否则输出None,达到数据截断或丢弃的目的。Filter主要子类包括:SimpleMatch(基于简单属性匹配规则)、JsonPathMaptch(基于jsonpath语法的匹配过滤)、WikidataMatch(针对Wikidata的匹配过滤)、WhiteList(白名单过滤机制,即仅在名单中的数据才保留)、BlackList(黑名单过滤机制,即在名单中的数据就会被丢弃)、Distinct(去重,基于本地缓存或基于Redis的缓存去重)、TakeN/SkipN/Sample(基于采样的过滤)、FieldsExist/FieldsNonEmpty(字段存在/字段非空)、All/Any/Not(组合过滤)等。
  5. ReduceBase,对数据进行聚合、规约,即*->?处理模式。ReduceBase本身为抽象基类,具体功能为其子类实现,包括:Buffer(缓冲,积攒一批数据后再集中输出)、Reduce(规约,对一组数据根据提供的规约方法进行规约后输出)、Group(分组,将具有相同属性的数据放在一起输出,可以看成一类特殊规约)。它们分别代表了一大类数据处理场景,其中Buffer广泛用于数据输出(包括写文件、写数据库等)等Processor基类;Reduce/Group则类似SQL的group by操作,可以紧跟Count/Sum/Max/Min/Mean/Var/Std/Sample/Head/Tail/OrderBy/Distinct等算子。
  6. DictProcessorBase,处理dict数据的基类,子类on_data方法的调用参数只需要考虑为dict的情况,从而减少类型检查代码。在实际应用中,为了统一,通常将处理数据都看成dict(或json对象)进行处理,因此DictProcessorBase分支将会非常庞大。包括(1)转换处理类:MapRules(基于一种简单规则对dict/json进行转换)、MapMulti(基于提供的mapper对多个字段进行转换处理)、MapKV(将输入dict和K-V反转为V-K的dict);(2)选择投影类:Select(类似SQL的select操作,支持基于点号分隔的嵌套字段)、SelectVal(选择字段的值输出);(3)字段增删改类:AddFieldsReplaceFieldsRenameFieldsMergeFieldsCopyFieldsInjectFieldConcatFields(拼接若干个字段);(4)模型调用类:LLM(基于OpenAI兼容接口调用大模型获得模型输出结果)、Embed(调用嵌入式模型进行嵌入向量生成);等等。
  7. 输出/Load组件,实现数据输出到目标数据库系统,主要包括文件和数据库。其中文件内置提供了TextJsonCSV三种格式,且支持开启gzip压缩。数据库内置提供了MySQLMongoDBElasticSearchClickHouseQdrantMinIO。这类组件均继承自Buffer组件,实现带缓冲输出。
  8. 业务组件,根据业务实际需要实现的组件,如web.gdelt.Export(实现GDELT数据下载、组合元信息)、web.polls.PollData(实现对民调数据结构转换)、web.image.Download(图片下载)、wikidata.*(实现对wikidata的结构简化、信息融合、实体关系生成等)等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值