AskTable

AskTable SDI 安全脱敏推理:基于 Faker 的高性能数据脱敏方案

AskTable 团队
AskTable 团队 2026年3月5日

在 AI 数据分析场景中,数据安全是头等大事。企业数据中往往包含敏感信息:用户手机号、身份证号、银行卡号、地址等。如何在保证 AI 推理准确性的同时,保护这些敏感数据不被泄露?

AskTable 的 SDI(Secure Data Inference)技术,通过 字段级脱敏 + Faker 生成 + Vault 映射 的方案,实现了高性能、高安全的数据脱敏。

本文将深入剖析这套方案的设计与实现。


一、为什么需要 SDI?

1. AI 推理中的数据泄露风险

场景:用户问"手机号为 138xxxx1234 的用户购买了什么?"

传统方案

# 直接将敏感数据传递给 LLM
prompt = f"数据:{dataframe.to_string()}\n问题:{question}"

风险

2. 传统脱敏方案的局限

完全脱敏

# 将敏感字段替换为 ***
df["phone"] = "***"

问题

加密

# 加密敏感数据
df["phone"] = encrypt(df["phone"])

问题


二、SDI 的核心设计

1. 字段级脱敏标记

class IdentifiableType(StrEnum):
    """敏感字段类型"""
    NONE = "none"  # 非敏感
    PHONE = "phone"  # 手机号
    ID_CARD = "id_card"  # 身份证号
    EMAIL = "email"  # 邮箱
    ADDRESS = "address"  # 地址
    NAME = "name"  # 姓名
    BANK_CARD = "bank_card"  # 银行卡号

元数据标记

field = {
    "name": "phone",
    "type": "VARCHAR",
    "identifiable_type": "phone",  # 标记为敏感字段
}

2. SecureDataFrame 设计

class SecureDataFrame:
    """安全数据框架:支持脱敏的 DataFrame"""

    def __init__(self, df: pd.DataFrame, vault: Vault):
        self.df = df
        self.vault = vault  # 映射关系管理器

    def to_str(self, anonymize: bool = True) -> str:
        """转换为字符串,支持脱敏"""
        if not anonymize:
            return self.df.to_string()

        # 脱敏处理
        anonymized_df = self.df.copy()
        for col in self.df.columns:
            if self.vault.is_sensitive(col):
                anonymized_df[col] = anonymized_df[col].apply(
                    lambda x: self.vault.anonymize(col, x)
                )

        return anonymized_df.to_string()

3. Vault 映射管理

class Vault:
    """映射关系管理器:原值 ↔ 假值"""

    def __init__(self):
        self._forward_map: dict[str, dict[str, str]] = {}  # 原值 -> 假值
        self._reverse_map: dict[str, dict[str, str]] = {}  # 假值 -> 原值
        self._faker = Faker("zh_CN")

    def anonymize(self, field: str, value: str) -> str:
        """脱敏:原值 -> 假值"""
        if value in self._forward_map.get(field, {}):
            return self._forward_map[field][value]

        # 生成假值
        fake_value = self._generate_fake_value(field, value)

        # 保存映射关系
        if field not in self._forward_map:
            self._forward_map[field] = {}
            self._reverse_map[field] = {}

        self._forward_map[field][value] = fake_value
        self._reverse_map[field][fake_value] = value

        return fake_value

    def deanonymize(self, field: str, fake_value: str) -> str:
        """还原:假值 -> 原值"""
        return self._reverse_map.get(field, {}).get(fake_value, fake_value)

    def _generate_fake_value(self, field: str, value: str) -> str:
        """根据字段类型生成假值"""
        field_type = self._get_field_type(field)

        if field_type == "phone":
            return self._faker.phone_number()
        elif field_type == "email":
            return self._faker.email()
        elif field_type == "name":
            return self._faker.name()
        elif field_type == "address":
            return self._faker.address()
        elif field_type == "id_card":
            return self._faker.ssn()
        else:
            return "***"

三、核心实现:深入源码

1. 脱敏流程

async def query_with_sdi(question: str, datasource: DataSourceAdmin) -> QueryResult:
    """带 SDI 的查询流程"""
    # 1. 生成 SQL
    sql = await generate_sql(question, datasource)

    # 2. 执行 SQL,获取原始数据
    raw_df = await datasource.execute_sql(sql)

    # 3. 创建 Vault
    vault = Vault()
    for field in datasource.get_sensitive_fields():
        vault.register_field(field.name, field.identifiable_type)

    # 4. 创建 SecureDataFrame
    secure_df = SecureDataFrame(raw_df, vault)

    # 5. 脱敏后传递给 LLM(用于生成解释)
    anonymized_data = secure_df.to_str(anonymize=True)
    explanation = await generate_explanation(question, anonymized_data)

    # 6. 返回原始数据给用户(不脱敏)
    return QueryResult(
        sql=sql,
        dataframe=raw_df,  # 原始数据
        explanation=explanation,  # 基于脱敏数据生成的解释
    )

2. Faker 生成假值

from faker import Faker

faker = Faker("zh_CN")

# 生成假手机号
fake_phone = faker.phone_number()
# 输出:138-1234-5678

# 生成假姓名
fake_name = faker.name()
# 输出:张伟

# 生成假地址
fake_address = faker.address()
# 输出:北京市朝阳区建国路88号

# 生成假邮箱
fake_email = faker.email()
# 输出:zhangwei@example.com

关键点

3. 映射关系管理

# 示例:脱敏手机号
vault = Vault()
vault.register_field("phone", "phone")

# 原值 -> 假值
fake1 = vault.anonymize("phone", "138-1234-5678")
# 输出:156-7890-1234

# 相同原值 -> 相同假值(保持一致性)
fake2 = vault.anonymize("phone", "138-1234-5678")
# 输出:156-7890-1234(与 fake1 相同)

# 假值 -> 原值
original = vault.deanonymize("phone", "156-7890-1234")
# 输出:138-1234-5678

关键点


四、技术选型:为什么选择 Faker?

1. 对比方案

方案性能准确性可逆性部署成本
Faker⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
本地小模型⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
加密⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
完全脱敏⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

2. Faker 的优势

性能

# Faker 生成速度
import time
start = time.time()
for _ in range(10000):
    faker.phone_number()
print(f"耗时:{time.time() - start:.2f}s")
# 输出:耗时:0.15s(10000 次生成)

准确性

可逆性

部署成本

3. 本地小模型的局限

问题

结论:对于脱敏场景,Faker 是更优选择。


五、实战案例

案例 1:手机号脱敏

# 原始数据
df = pd.DataFrame({
    "name": ["张三", "李四"],
    "phone": ["138-1234-5678", "139-8765-4321"],
    "amount": [1000, 2000],
})

# 创建 Vault
vault = Vault()
vault.register_field("phone", "phone")

# 脱敏
secure_df = SecureDataFrame(df, vault)
anonymized_str = secure_df.to_str(anonymize=True)

# 输出(脱敏后)
"""
   name          phone  amount
0  张三  156-7890-1234    1000
1  李四  157-1234-5678    2000
"""

# 传递给 LLM
explanation = await generate_explanation(question, anonymized_str)

# 返回给用户(原始数据)
return df  # 包含真实手机号

案例 2:多字段脱敏

# 原始数据
df = pd.DataFrame({
    "name": ["张三", "李四"],
    "phone": ["138-1234-5678", "139-8765-4321"],
    "email": ["zhangsan@example.com", "lisi@example.com"],
    "address": ["北京市朝阳区", "上海市浦东新区"],
})

# 创建 Vault
vault = Vault()
vault.register_field("name", "name")
vault.register_field("phone", "phone")
vault.register_field("email", "email")
vault.register_field("address", "address")

# 脱敏
secure_df = SecureDataFrame(df, vault)
anonymized_str = secure_df.to_str(anonymize=True)

# 输出(脱敏后)
"""
   name          phone                email        address
0  王伟  156-7890-1234  wangwei@example.com  广州市天河区
1  刘洋  157-1234-5678  liuyang@example.com  深圳市南山区
"""

六、性能优化

1. 缓存映射关系

class Vault:
    def __init__(self):
        self._cache: dict[str, str] = {}  # 缓存映射关系

    def anonymize(self, field: str, value: str) -> str:
        cache_key = f"{field}:{value}"
        if cache_key in self._cache:
            return self._cache[cache_key]

        fake_value = self._generate_fake_value(field, value)
        self._cache[cache_key] = fake_value
        return fake_value

效果

2. 批量脱敏

def anonymize_batch(self, field: str, values: list[str]) -> list[str]:
    """批量脱敏"""
    return [self.anonymize(field, v) for v in values]

效果


七、安全保障

1. 会话隔离

# 每个会话使用独立的 Vault
session_vaults: dict[str, Vault] = {}

def get_vault(session_id: str) -> Vault:
    if session_id not in session_vaults:
        session_vaults[session_id] = Vault()
    return session_vaults[session_id]

效果

2. 映射表加密

class EncryptedVault(Vault):
    def __init__(self, encryption_key: str):
        super().__init__()
        self.cipher = Fernet(encryption_key)

    def save_to_disk(self, path: str):
        """加密保存映射表"""
        data = json.dumps(self._forward_map)
        encrypted_data = self.cipher.encrypt(data.encode())
        with open(path, "wb") as f:
            f.write(encrypted_data)

效果


八、总结与展望

AskTable 的 SDI 技术,通过 Faker + Vault + SecureDataFrame 的组合,实现了:

高安全性:敏感数据不暴露给 LLM ✅ 高性能:Faker 生成速度快(< 1ms) ✅ 高准确性:不影响 AI 推理质量 ✅ 低成本:无需 GPU,部署简单

未来优化方向

  1. 智能识别:自动识别敏感字段
  2. 差分隐私:引入差分隐私技术
  3. 联邦学习:支持多方数据联合分析
  4. 审计日志:记录所有脱敏操作

相关阅读

技术交流