深入介绍Great Expectations声明式期望套件,涵盖期望规则定义、自动化数据验证、Checkpoint调度与告警、数据文档自动生成。学习如何构建声明式数据质量验证体系、设计Checkpoint调度策略、实现数据质量文档化。适用于数据工程团队数据质量治理、ETL数据验证、数据平台质量自动化等场景。
需要学习数据质量Great Expectations:声明式期望套件、自动化数据验证与文档生成、Checkpoint调度与告警,GPU调度和算力优化是AI运维的关键差异化技能。本篇涵盖GPU/TPU/NPU、CUDA、集群调度、算力优化,帮助你理解硬件加速原理。
目录
可视化演示
展示GE四大核心:期望套件规则定义、自动化验证流程、Checkpoint调度告警、数据文档自动生成与质量报告。
本节配有交互动效(进入视口后自动加载,约 3KB)。
声明式期望套件设计 JSON配置声明验证规则:非空检查、值域约束、唯一性校验、分布检验 期望套件绑定到数据批次,声明式定义数据质量契约 Suite = [expect_not_null, expect_between, expect_unique, expect_distribution] 期望套件通过JSON声明式定义每列数据的期望规则
Great Expectations声明式期望套件设计
期望套件(Expectation Suite)是 Great Expectations 的核心概念,它通过 JSON 配置文件声明式地定义每列数据的期望规则,如非空检查、值域约束、唯一性校验和分布检验等。开发者无需编写验证代码,只需用声明式语法描述数据质量标准,框架自动将期望规则编译为可执行的验证逻辑。这种设计让数据质量规则与业务逻辑解耦,使得非技术人员也能参与数据质量标准的定义和维护。
期望套件的声明式特性带来了三个关键优势。首先是可读性:JSON 格式的期望规则直观易懂,团队成员可以快速理解数据质量要求。其次是可版本化:套件文件可以纳入 Git 管理,每次数据模式变更都有完整的变更历史。最后是可复用:同一套期望规则可以应用于不同的数据集和管道阶段,避免重复定义。从架构上看,一个期望套件包含套件名称、期望列表和元数据三部分,每个期望项定义了期望类型(如 expect_column_values_to_not_be_null)、目标列名和验证参数。
在实际项目中,期望套件的设计需要遵循分层原则。列级期望验证单列数据的基本属性,如表层期望验证跨列关系和聚合统计,而自定义期望则封装业务特定的质量规则。例如在 AI 训练数据管道中,列级期望检查文本长度是否在合理范围,表层期望验证特征列之间的相关性是否符合预期,自定义期望则检查数据是否包含敏感信息。内置的期望类型覆盖了非空、值域、唯一性、分布、类型和统计等常见维度,满足大部分数据质量验证需求。
import json # 声明式期望套件示例:AI训练数据质量规则suite = { "suite_name": "training_data_quality", "expectations": [ { "expectation_type": "expect_column_values_to_not_be_null", "kwargs": {"column": "text"} }, { "expectation_type": "expect_column_values_to_be_between", "kwargs": {"column": "text_length", "min_value": 10, "max_value": 10000} }, { "expectation_type": "expect_column_values_to_be_unique", "kwargs": {"column": "doc_id"} } ]}print(json.dumps(suite, indent=2, ensure_ascii=False))
自动化数据验证流程与期望类型
数据验证流程将期望套件应用于实际数据集,自动执行所有期望规则检查并生成结构化的验证结果。整个流程分为三步:首先加载数据源并创建数据上下文,然后将期望套件绑定到数据批次执行验证,最后汇总验证结果按通过、失败和异常三类分类输出。验证引擎会逐条执行期望规则,每条期望的执行结果包含成功状态、期望配置和实际观测值,便于快速定位质量问题。
Great Expectations 内置了超过 200 种期望类型,覆盖了从基础到复杂的数据质量验证维度。基础期望包括 expect_column_values_to_not_be_null(非空检查)、expect_column_values_to_be_between(值域检查)和 expect_column_values_to_be_unique(唯一性检查)。统计分布期望包括 expect_column_mean_to_be_between(均值范围)、expect_column_kl_divergence_to_be_less_than(KL散度分布漂移检测)和 expect_column_quantile_values_to_be_between(分位数范围)。跨列一致性期望包括 expect_compound_columns_to_be_unique(复合列唯一性)和 expect_multicolumn_values_to_be_unique(多列联合唯一性)。
验证结果的分类汇总机制是快速定位质量问题的关键。通过状态表示每条期望的验证结果:success 表示数据符合期望,failure 表示数据违反期望规则,observed_value 字段记录实际观测到的统计值。对于 AI 训练数据管道,验证结果还需要与管道编排系统集成:当关键期望失败时触发管道阻断,非关键期望失败时仅记录告警。这种分级处理机制避免了因次要质量问题过度阻断管道,同时确保严重问题不会传播到下游训练环节。
from collections import defaultdict class ExpectationValidator: """简化版期望验证器:执行期望套件并汇总结果""" def __init__(self, suite): self.suite = suite self._handlers = { "expect_column_values_to_not_be_null": self._check_not_null, "expect_column_values_to_be_between": self._check_between, "expect_column_values_to_be_unique": self._check_unique, } def validate(self, dataframe): results = [] for exp in self.suite["expectations"]: handler = self._handlers.get(exp["expectation_type"]) if handler: results.append(handler(dataframe, exp["kwargs"])) return results def _check_not_null(self, df, kwargs): col = kwargs["column"] null_count = sum(1 for r in df if r.get(col) is None) return {"success": null_count == 0, "observed": {"null_count": null_count}} def _check_between(self, df, kwargs): col = kwargs["column"] vals = [r[col] for r in df if r.get(col) is not None] out = sum(1 for v in vals if v < kwargs["min_value"] or v > kwargs["max_value"]) return {"success": out == 0, "observed": {"out_of_range": out}} def _check_unique(self, df, kwargs): col = kwargs["column"] vals = [r[col] for r in df if r.get(col) is not None] return {"success": len(vals) == len(set(vals)), "observed": {"duplicates": len(vals) - len(set(vals))}}
Checkpoint调度与告警机制
Checkpoint 是 Great Expectations 中将期望套件、数据源和验证动作封装为可调度执行单元的核心机制。一个 Checkpoint 定义了验证时使用哪个期望套件、从哪个数据源读取数据、验证完成后执行哪些动作。这种封装使得数据质量验证可以作为一个独立的可调度任务嵌入到 ETL 管道中,无需在管道代码中硬编码验证逻辑。Checkpoint 的配置采用声明式格式,包含 validations 列表(指定套件和数据批次)和 action_list(指定验证后动作)。
Action 列表是 Checkpoint 的执行引擎,定义了验证完成后自动触发的操作。常见的 Action 类型包括:StoreValidationResultAction 将验证结果存储到结果存储后端,UpdateDataDocsAction 自动更新 HTML 数据文档,SlackNotificationAction 发送 Slack 告警通知。每个 Action 可以配置触发条件,如仅在验证失败时发送告警。这种设计使得验证结果的存储、文档更新和告警通知完全自动化,无需人工干预。
Checkpoint 与 Airflow 等调度器的集成实现了数据质量门控的自动化执行。在 Airflow DAG 中,Checkpoint 验证作为一个 Task 节点嵌入管道,其执行状态决定后续 Task 是否触发。当验证失败时,Checkpoint 返回失败状态,Airflow 根据配置决定是重试、跳过还是阻断整个管道。对于 AI 训练数据管道,通常将 Checkpoint 设置为管道的关键门控点:数据采集后验证原始数据完整性,ETL 转换后验证中间结果一致性,最终输出前验证数据准确性。任何一个环节的 Checkpoint 失败都会阻断数据流入下游训练环节。
class Checkpoint: """简化版Checkpoint:封装套件、数据源和验证动作""" def __init__(self, name, suite_name, datasource, actions=None): self.name = name self.suite_name = suite_name self.datasource = datasource self.actions = actions or [] def run(self, suites, data_fetcher): suite = suites[self.suite_name] data = data_fetcher(self.datasource) validator = ExpectationValidator(suite) results = validator.validate(data) success = all(r["success"] for r in results) for action in self.actions: action(results, success) return {"success": success, "results": results} def alert_action(results, success): if not success: failed = [r for r in results if not r["success"]] print(f"[ALERT] 验证失败,{len(failed)}条期望未通过") def store_action(results, success): print(f"[STORE] 验证结果已存储,状态: {'通过' if success else '失败'}")
数据文档自动生成与质量报告
Great Expectations 根据期望套件和验证结果自动生成 HTML 数据文档(Data Docs),为团队提供实时的数据质量可观测性。数据文档包含三个核心部分:数据概况展示每列的统计摘要和分布信息,期望规则详情列出每条期望的配置和验证结果,验证结果趋势展示历史验证通过率的变化曲线。文档随每次验证自动更新,无需手动维护,确保团队看到的数据质量信息始终是最新的。
数据文档的自动生成机制基于验证结果的存储和渲染。每次 Checkpoint 执行后,验证结果被存储到结果存储后端(如文件系统或数据库),UpdateDataDocsAction 读取最新的验证结果和期望套件,渲染为 HTML 页面并部署到文档站点。这种自动更新机制保证了数据文档与实际验证结果的同步,避免了手动编写报告的滞后性和不一致性。对于 AI 训练数据管道,数据文档提供了训练数据质量的完整可观测性:数据科学家可以查看训练集的分布变化,运维团队可以监控管道的验证通过率趋势。
数据文档在团队协作中扮演着数据质量知识库的角色。新加入团队的成员可以通过数据文档快速了解数据模式和质量标准,无需阅读代码或询问同事。数据质量问题排查时,文档中的期望规则详情和验证结果历史为根因分析提供了关键线索。在数据治理实践中,数据文档还支持审计需求:合规团队可以查看历史验证记录,确认数据质量标准在各个时间点的执行情况。
数据质量治理体系构建实践
构建数据质量治理体系需要按数据管道阶段设计分层期望套件。源头数据阶段验证完整性,确保必需字段非空、数据量符合预期;ETL 转换中间阶段验证一致性,确保跨表关联正确、转换逻辑无数据丢失;最终输出阶段验证准确性,确保数据值域合理、分布符合业务预期。这种分层设计使得质量问题在管道早期就被发现和阻断,避免低质量数据传播到下游训练环节造成算力浪费。
Checkpoint 门控是质量治理体系的执行层,通过阻断机制防止质量问题传播。门控策略需要区分阻塞性和非阻塞性规则:阻塞性规则(如必需字段非空、主键唯一性)验证失败时立即阻断管道;非阻塞性规则(如分布漂移预警、统计指标偏差)验证失败时仅发送告警但允许管道继续执行。这种分级处理避免了过度保守的阻断策略影响数据时效性,同时确保严重质量问题不会逃逸到下游。门控策略的配置需要与业务方协商,明确每个期望规则的重要级别和响应流程。
质量治理体系的持续运营需要建立 SLA 标准和责任归属机制。SLA 标准定义了数据质量的量化指标和目标值,如非空率不低于 99.5%、分布漂移检测通过率不低于 95%。责任归属机制明确了每个数据资产的质量负责人,当质量问题发生时自动通知负责人并跟踪修复进度。在 AI 训练数据管道的实践中,质量治理体系还需要与模型评估闭环联动:数据质量下降导致的模型性能退化需要追溯到具体的数据质量问题,形成从数据质量到模型质量的完整追溯链路。
AI 应用场景
AI训练数据管道质量门控
阶段:数据工程
解决的问题:AI训练数据管道中数据质量问题如空值、分布漂移和格式错误在训练阶段才暴露导致返工浪费算力,缺乏自动化质量门控机制
具体案例:团队为LLM训练数据管道部署Great Expectations,在数据采集后定义期望套件检查文本长度分布和去重率及语言识别准确率,ETL转换后检查字段完整性和跨表一致性,某次数据采集发现文本长度中位数从800突降到200触发告警,及时阻断管道避免了用低质量数据浪费200GPU小时的训练算力
Python 演示
import jsonfrom collections import defaultdictfrom datetime import datetime class Expectation: """期望规则基类:声明式定义数据质量验证规则""" def __init__(self, expectation_type, column, **kwargs): self.expectation_type = expectation_type self.column = column self.kwargs = kwargs def to_dict(self): return { "expectation_type": self.expectation_type, "kwargs": {"column": self.column, **self.kwargs} } class ExpectationSuite: """期望套件:管理一组期望规则的声明式配置""" def __init__(self, name): self.name = name self.expectations = [] def add_expectation(self, expectation): self.expectations.append(expectation) return self def to_dict(self): return { "suite_name": self.name, "expectations": [e.to_dict() for e in self.expectations] } class ValidationResult: """验证结果:记录每条期望的执行结果""" def __init__(self, expectation_type, column, success, observed): self.expectation_type = expectation_type self.column = column self.success = success self.observed = observed self.timestamp = datetime.now().isoformat() class Checkpoint: """Checkpoint:封装套件、数据源和验证动作的可调度单元""" def __init__(self, name, suite, actions=None): self.name = name self.suite = suite self.actions = actions or [] def run(self, data): results = self._validate(data) overall_success = all(r.success for r in results) for action in self.actions: action(results, overall_success) return {"success": overall_success, "results": results} def _validate(self, data): results = [] for exp in self.suite.expectations: handler = VALIDATORS.get(exp.expectation_type) if handler: success, observed = handler(data, exp) results.append(ValidationResult( exp.expectation_type, exp.column, success, observed )) return results def validate_not_null(data, exp): null_count = sum(1 for r in data if r.get(exp.column) is None) return null_count == 0, {"null_count": null_count} def validate_between(data, exp): vals = [r[exp.column] for r in data if r.get(exp.column) is not None] out_of_range = sum(1 for v in vals if v < exp.kwargs["min_value"] or v > exp.kwargs["max_value"]) return out_of_range == 0, {"out_of_range": out_of_range} def validate_unique(data, exp): vals = [r[exp.column] for r in data if r.get(exp.column) is not None] return len(vals) == len(set(vals)), {"duplicates": len(vals) - len(set(vals))} VALIDATORS = { "expect_column_values_to_not_be_null": validate_not_null, "expect_column_values_to_be_between": validate_between, "expect_column_values_to_be_unique": validate_unique,} def alert_action(results, success): if not success: failed = [r for r in results if not r.success] print(f"[ALERT] 验证失败: {len(failed)} 条期望未通过") def store_action(results, success): print(f"[STORE] 结果已存储, 状态: {'通过' if success else '失败'}") # 构建期望套件suite = ExpectationSuite("training_data_quality")suite.add_expectation(Expectation("expect_column_values_to_not_be_null", "text"))suite.add_expectation(Expectation("expect_column_values_to_be_between", "text_length", min_value=10, max_value=10000))suite.add_expectation(Expectation("expect_column_values_to_be_unique", "doc_id")) # 模拟训练数据data = [ {"doc_id": 1, "text": "大模型训练数据", "text_length": 7}, {"doc_id": 2, "text": "数据质量验证", "text_length": 6}, {"doc_id": 3, "text": None, "text_length": 0},] # 创建并运行Checkpointcheckpoint = Checkpoint("training_gate", suite, [store_action, alert_action])report = checkpoint.run(data)print(json.dumps({"success": report["success"], "total": len(report["results"])}, ensure_ascii=False))
class Expectation:期望规则基类,声明式定义数据质量验证规则,包含期望类型、目标列和验证参数def __init__(self, expectation_type, column, **kwargs):初始化期望规则,expectation_type标识验证类型如非空检查,column指定验证目标列class ExpectationSuite:期望套件类,管理一组期望规则的声明式配置,支持链式添加期望def add_expectation(self, expectation):向套件添加期望规则,返回self支持链式调用,便于流畅地构建完整套件class Checkpoint:Checkpoint封装套件、数据源和验证动作为可调度单元,是管道集成的核心组件def run(self, data):执行验证流程:运行所有期望规则并触发后续动作,返回包含成功状态和详细结果的对象overall_success = all(r.success for r in results)汇总所有期望的验证结果,只有全部通过才标记整体成功,任一失败即阻断for action in self.actions:遍历Action列表,依次执行存储结果、更新文档和发送告警等验证后动作def _validate(self, data):核心验证逻辑:逐条执行期望规则,通过VALIDATORS分发到对应的验证函数def validate_not_null(data, exp):非空验证函数:统计目标列的空值数量,返回是否全部非空和观测到的空值计数def validate_between(data, exp):值域验证函数:检查值是否在min_value和max_value范围内,返回越界记录数def validate_unique(data, exp):唯一性验证函数:通过集合去重比较长度,返回重复记录数VALIDATORS = {验证函数分发表:将期望类型字符串映射到具体验证函数,实现声明式规则到执行逻辑的解耦suite = ExpectationSuite("training_data_quality")创建名为training_data_quality的期望套件,用于AI训练数据质量验证checkpoint = Checkpoint("training_gate", suite, [store_action, alert_action])创建Checkpoint绑定套件和动作列表,包含结果存储和告警通知两个验证后动作
常见问答
Great Expectations的期望套件和数据验证代码有什么区别?
Checkpoint中的阻塞性和非阻塞性规则如何区分?
Great Expectations能检测数据分布漂移吗?
数据文档自动更新机制是如何工作的?
期望套件如何与Airflow调度器集成?
常见误区
误区期望套件定义后就不需要更新
正解数据模式和质量要求会随业务演进变化,期望套件需要定期review和更新,静态套件会逐渐与实际数据脱节导致误报或漏报
为何常见:套件作为配置文件容易被视为一次性设置,忽略了数据演进对质量规则持续更新的需求
误区Great Expectations可以验证所有类型的数据质量问题
正解Great Expectations擅长结构性数据质量验证如完整性和值域,但对于语义正确性和业务逻辑合理性等主观维度仍需人工或模型辅助验证
为何常见:框架名称暗示了全面的数据质量保障,容易让人忽略其在语义级验证上的局限性
误区Checkpoint验证失败就应该直接阻断整个数据管道
正解并非所有验证失败都需要阻断管道,需根据期望的重要级别区分阻塞性和非阻塞性规则,非关键规则失败可以告警但继续执行避免过度阻断影响数据时效性
为何常见:门控概念容易让人联想到全部阻断,忽略了实际需要分级处理避免过度保守
参考来源
- docGreat Expectations Official DocumentationGreat Expectations官方文档,涵盖期望套件设计、Checkpoint配置、数据文档生成和验证流程的完整指南
- webpageGreat Expectations GitHub RepositoryGreat Expectations开源仓库,包含内置期望类型列表、示例套件和社区最佳实践
- docCheckpoints and Actions ReferenceCheckpoint和Action的官方参考文档,详解Action类型、触发条件配置和调度器集成方法
- webpageGreat Expectations Blog - Data Quality Best PracticesGreat Expectations官方博客,分享数据质量治理体系构建、分层期望套件设计和门控策略的最佳实践