开源 AI 食谱文档

PII 检测的 LLM 网关

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

Open In Colab

PII 检测的 LLM 网关

作者:Anthony Susevski

关于企业用例采用 LLM 的一个常见抱怨是数据隐私问题;特别是对于处理敏感数据的团队。虽然开源权重模型始终是一个很好的选择,并且如果可能,应该进行试验,但有时我们只是想快速演示一些东西,或者有充分的理由使用 LLM API。在这些情况下,最好有一个网关来处理个人身份信息 (PII) 数据的清理,以降低 PII 泄露的风险。

Wealthsimple 是一家总部位于加拿大 Toronto 的金融科技公司,它开源了一个仓库,正是为此目的而创建的。在本 notebook 中,我们将探讨如何利用这个仓库在向 LLM 提供商发出 API 调用之前清理我们的数据。为此,我们将查看 AI4Privacy 的 PII 数据集,并使用 Cohere 免费试用 apiCommand R+ 模型来演示 Wealthsimple 仓库的 PII 清理功能。

首先,按照 README 中的这些说明进行安装

  1. 安装 Poetry 和 Pyenv
  2. 安装 pyenv install 3.11.3
  3. 安装项目要求
brew install gitleaks
poetry install
poetry run pre-commit install
  1. 运行 cp .envrc.example .envrc 并使用 API 密钥更新
import os
from llm_gateway.providers.cohere import CohereWrapper
from datasets import load_dataset
import cohere
import types
import re
COHERE_API_KEY = os.environ["COHERE_API_KEY"]
DATABASE_URL = os.environ[
    "DATABASE_URL"
]  # default database url: "postgresql://postgres:postgres@postgres:5432/llm_gateway"

LLM Wrapper

wrapper 对象是一个简单的 wrapper,它在进行 API 调用之前将“scrubber”应用于 prompt。使用 wrapper 发出请求后,我们将收到一个响应和一个 db_record 对象。在我们深入了解更多细节之前,让我们先看看它的实际效果。

wrapper = CohereWrapper()
example = "Michael Smith (msmith@gmail.com, (+1) 111-111-1111) committed a mistake when he used PyTorch Trainer instead of HF Trainer."
>>> response, db_record = wrapper.send_cohere_request(
...     endpoint="generate",
...     model="command-r-plus",
...     max_tokens=25,
...     prompt=f"{example}\n\nSummarize the above text in 1-2 sentences.",
...     temperature=0.3,
... )

>>> print(response)
{'data': ['Michael Smith made a mistake by using PyTorch Trainer instead of HF Trainer.'], 'return_likelihoods': None, 'meta': {'api_version': {'version': '1'}, 'billed_units': {'input_tokens': 48, 'output_tokens': 14}}}

响应返回 LLM 输出;在这种情况下,由于我们要求模型返回对已很短句子的摘要,因此它返回了消息

['Michael Smith 犯了一个错误,他使用了 PyTorch Trainer 而不是 HF Trainer。']

>>> print(db_record)
{'user_input': 'Michael Smith ([REDACTED EMAIL ADDRESS], (+1) [REDACTED PHONE NUMBER]) committed a mistake when he used PyTorch Trainer instead of HF Trainer.\n\nSummarize the above text in 1-2 sentences.', 'user_email': None, 'cohere_response': {'data': ['Michael Smith made a mistake by using PyTorch Trainer instead of HF Trainer.'], 'return_likelihoods': None, 'meta': {'api_version': {'version': '1'}, 'billed_units': {'input_tokens': 48, 'output_tokens': 14}}}, 'cohere_model': 'command-r-plus', 'temperature': 0.3, 'extras': '{}', 'created_at': datetime.datetime(2024, 6, 10, 2, 16, 7, 666438), 'cohere_endpoint': 'generate'}

返回的第二个项目是数据库记录。该仓库旨在与 postgres 后端一起使用;事实上,该仓库带有一个使用 Docker 构建的完整前端。postgres 数据库用于存储网关的聊天历史记录。但是,它也非常有帮助,因为它向我们展示了每个请求中实际发送的数据。正如我们所见,prompt 已被清理,并发送了以下内容

Michael Smith ([已编辑的电子邮件地址], (+1) [已编辑的电话号码]) 在使用 PyTorch Trainer 而不是 HF Trainer 时犯了一个错误。\n\n用 1-2 句话概括以上文本。

但是等等,我听到你在想。Michael Smith 不是 PII 吗?可能是。但这个仓库实际上并没有实现名称 scrubber。下面,我们将调查哪些 scrubber 应用于 prompt

generate endpoint 实际上已弃用 Cohere,因此为 Cohere 的 API 的新 Chat endpoint 创建和提交集成将是一个非常出色的开源贡献。

Scrubbers!

根据他们的仓库,这些是他们实现的 scrubber

ALL_SCRUBBERS = [
    scrub_phone_numbers,
    scrub_credit_card_numbers,
    scrub_email_addresses,
    scrub_postal_codes,
    scrub_sin_numbers,
]

网关将按顺序应用每个 scrubber。

这有点 hacky,但如果您确实需要实现另一个 scrubber,您可以通过修改 wrapper 调用 scrubber 的方法来做到这一点。下面我们将演示

作者提到 sin scrubber 特别容易清理东西,因此他们将其放在最后应用,以确保其他与数字相关的 PII 首先被清理

def my_custom_scrubber(text: str) -> str:
    """
    Scrub Michael Smith in text

    :param text: Input text to scrub
    :type text: str
    :return: Input text with any mentions of Michael Smith scrubbed
    :rtype: str
    """
    return re.sub(r"Michael Smith", "[REDACTED PERSON]", text, re.IGNORECASE)
original_method = wrapper.send_cohere_request


def modified_method(self, **kwargs):
    self._validate_cohere_endpoint(kwargs.get("endpoint", None))  # Unfortunate double validate cohere endpoint call
    prompt = kwargs.get("prompt", None)
    text = my_custom_scrubber(prompt)
    kwargs["prompt"] = text
    return original_method(**kwargs)


# Assign the new method to the instance
wrapper.send_cohere_request = types.MethodType(modified_method, wrapper)
>>> response, db_record = wrapper.send_cohere_request(
...     endpoint="generate",
...     model="command-r-plus",
...     max_tokens=25,
...     prompt=f"{example}\n\nSummarize the above text in 1-2 sentences.",
...     temperature=0.3,
... )

>>> print(response)
{'data': ['[REDACTED PERSON] made an error by using PyTorch Trainer instead of HF Trainer. They can be contacted at [RED'], 'return_likelihoods': None, 'meta': {'api_version': {'version': '1'}, 'billed_units': {'input_tokens': 52, 'output_tokens': 25}}}
>>> print(db_record)
{'user_input': '[REDACTED PERSON] ([REDACTED EMAIL ADDRESS], (+1) [REDACTED PHONE NUMBER]) committed a mistake when he used PyTorch Trainer instead of HF Trainer.\n\nSummarize the above text in 1-2 sentences.', 'user_email': None, 'cohere_response': {'data': ['[REDACTED PERSON] made an error by using PyTorch Trainer instead of HF Trainer. They can be contacted at [RED'], 'return_likelihoods': None, 'meta': {'api_version': {'version': '1'}, 'billed_units': {'input_tokens': 52, 'output_tokens': 25}}}, 'cohere_model': 'command-r-plus', 'temperature': 0.3, 'extras': '{}', 'created_at': datetime.datetime(2024, 6, 10, 2, 59, 58, 733195), 'cohere_endpoint': 'generate'}

如果您真的必须这样做,请务必记住 scrubber 是按顺序应用的,因此如果您的自定义 scrubber 干扰了任何默认 scrubber,则可能会出现一些奇怪的行为。

例如,对于专门的名称,有 其他清理库 您可以探索,这些库采用更复杂的算法来清理 PII。该仓库涵盖更多 PII,例如 IP 地址、主机名等。但是,如果您只需要删除特定的匹配项,则可以恢复为上面的代码。

数据集

让我们在一个完整的数据集上探索这个 wrapper 的实际应用。

pii_ds = load_dataset("ai4privacy/pii-masking-200k")
pii_ds["train"][36]["source_text"]
>>> example = pii_ds["train"][36]["source_text"]

>>> response, db_record = wrapper.send_cohere_request(
...     endpoint="generate",
...     model="command-r-plus",
...     max_tokens=50,
...     prompt=f"{example}\n\nSummarize the above text in 1-2 sentences.",
...     temperature=0.3,
... )

>>> print(response)
{'data': ["The person is requesting an update on assessment results and is offering Kip 100,000 in exchange for the information and the recipient's account details."], 'return_likelihoods': None, 'meta': {'api_version': {'version': '1'}, 'billed_units': {'input_tokens': 64, 'output_tokens': 33}}}
>>> print(db_record)
{'user_input': "I need the latest update on assessment results. Please send the files to V[REDACTED EMAIL ADDRESS]. For your extra time, we'll offer you Kip 100,000 but please provide your лв account details.\n\nSummarize the above text in 1-2 sentences.", 'user_email': None, 'cohere_response': {'data': ["The person is requesting an update on assessment results and is offering Kip 100,000 in exchange for the information and the recipient's account details."], 'return_likelihoods': None, 'meta': {'api_version': {'version': '1'}, 'billed_units': {'input_tokens': 64, 'output_tokens': 33}}}, 'cohere_model': 'command-r-plus', 'temperature': 0.3, 'extras': '{}', 'created_at': datetime.datetime(2024, 6, 10, 3, 10, 51, 416091), 'cohere_endpoint': 'generate'}

常规输出

如果我们只是按原样将文本发送到 endpoint,摘要会是什么样子

 co = cohere.Client(
    api_key=os.environ['COHERE_API_KEY']


 esponse_vanilla = co.generate(
    prompt=f"{example}\n\nSummarize the above text in 1-2 sentences.",
    model="command-r-plus",
    max_tokens=50,
    temperature=0.3
response_vanilla

总而言之,在本 notebook 中,我们演示了如何使用 Wealthsimple 开源的 PII 检测网关示例,并通过添加自定义 scrubber 对其进行了构建。如果您实际上需要可靠的 PII 检测,请确保运行自己的测试以验证您使用的任何清理算法实际上都涵盖了您的用例。最重要的是,在可能的情况下,在您托管的基础设施上部署开源模型始终是使用 LLM 构建的最安全和最可靠的选择 :)

< > 在 GitHub 上更新