尧图精选

Comet (Opik) PII 防护栏详解:Python SDK 的个人信息检测 Guard 及其 Presidio 后端实现

🕒 发布时间:2026/9/13 7:51:32 📁 来源:尧图网络
Comet (Opik) PII 防护栏详解Python SDK 的个人信息检测 Guard 及其 Presidio 后端实现【免费下载链接】comet-llmDebug, evaluate, and monitor your LLM applications, RAG systems, and agentic workflows with comprehensive tracing, automated evaluations, and production-ready dashboards.项目地址: https://gitcode.com/GitHub_Trending/co/comet-llm在 LLM 应用的输入/输出中混入邮箱、手机号、IP 地址等个人信息PII, Personally Identifiable Information会引发合规与隐私风险。Opik 的 Guardrails防护栏体系提供了PII这一内置 Guard用于在文本进入下游模型或对外返回前做个人信息检测与拦截判断。本文基于仓库中 PII 防护栏的文档页 pii.rst、SDK 侧实现 pii.py 与独立的 guardrails 后端服务 opik_guardrails完整讲解 PII Guard 的接口参数、配置下发机制以及后端基于 Microsoft Presidio 的实际检测流程与结果结构读完后可掌握如何在 Opik 中配置并调优一个可运行的 PII 防护策略。一、PII 防护栏文档页与代码文档的对应关系Opik Python SDK 的 Sphinx 文档中PII 防护栏对应 pii.rst 这个页面PII guardrail .. automodule:: opik.guardrails.guards.pii :members: :undoc-members: :show-inheritance:该页面本身非常简短因为它使用automodule指令直接从源码模块opik.guardrails.guards.pii自动生成 API 参考文档——也就是说文档页所展示的类说明、参数说明实际源头是 SDK 源码中的 docstring。真正需要深入阅读的是它指向的实现代码。与 PII 并列的其它内置防护栏Topic、PromptInjection、LLMJudge、CustomGuardrail 等的文档页位于同一目录 guardrails 下如 guardrail.rst、topic.rst。二、SDK 侧实现PII类的接口与参数PII Guard 的 SDK 实现位于 pii.py它继承自防护栏基类 Guardclass PII(guard.Guard): Guard that validates text for personally identifiable information (PII). def __init__( self, blocked_entities: Optional[List[str]] None, language: str en, threshold: float 0.5, ) - None: Initialize a PII guard. Args: blocked_entities: List of PII entity types to block. Default entities include: IP_ADDRESS, PHONE_NUMBER, PERSON, MEDICAL_LICENSE, URL, EMAIL_ADDRESS, IBAN_CODE. self._blocked_entities blocked_entities self._language language self._threshold threshold三个构造参数及其语义如下参数类型默认值说明blocked_entitiesOptional[List[str]]None要拦截的 PII 实体类型列表如EMAIL_ADDRESS、PHONE_NUMBER、CREDIT_CARD等。传None时使用后端默认实体清单见下文后端 schema 的默认值。支持的实体类型以 Presidio 的受支持实体列表为准languagestren被检测文本的语言代码用于选择对应的 NER命名实体识别模型thresholdfloat0.5置信度阈值检测结果的score低于该阈值的实体命中将被忽略不触发拦截源码中有两处值得注意的设计细节get_validation_configs是配置下发方法。它把三个参数打包成一个验证配置随防护栏一起发送给 guardrails 后端functools.lru_cache() def get_validation_configs(self) - List[Dict[str, Any]]: return [ { type: schemas.ValidationType.PII, config: { entities: self._blocked_entities, language: self._language, threshold: self._threshold, }, } ]方法上加了functools.lru_cache()同一PII实例的配置只会被构造一次。PII 是远端执行型防护栏。基类 Guard 定义了执行位置开关class Guard(abc.ABC): # Whether this guard executes locally in the SDK (True) or remotely on the # guardrails backend (False). local: bool FalsePII未覆写local属性因此继承local False——即 PII 检测不在 SDK 本地运行而是把entities / language / threshold配置发送到独立的 guardrails 后端opik-guardrails-backend服务执行。这也解释了为什么 SDK 侧只有薄薄的配置封装真正的检测引擎在后端下一节展开。三、典型用法组合多个 Guard 组成防护栏Guardrail 的 docstring 给出了把PII与Topic组合使用的官方示例见 guardrail.pyguard Guardrail( guards[ Topic(restricted_topics[finance], threshold0.8), PII(blocked_entities[CREDIT_CARD, PERSON], threshold0.4), ] )示例中threshold0.4低于默认值 0.5意味着放宽置信度要求、更激进地拦截疑似实体。实际调优方向是降低threshold如 0.3~0.4召回更高减少漏报但误报会增多提高threshold如 0.7只拦截高置信度命中误报少但可能放过低置信度的真实 PII缩小blocked_entities只关注合规要求覆盖的实体类型如仅EMAIL_ADDRESS、PHONE_NUMBER检测更快、噪声更少设置language处理非英文文本时应传入对应语言代码以加载匹配的 NER 模型。此外防护栏还可以从服务端存储的策略还原为本地 Guard 对象。stored_policies.py 中可以看到当服务端策略类型为PII时会按其配置重建 SDK 侧的PII实例if stored_guard.type schemas.ValidationType.PII: return guards.PII( blocked_entitiesconfig[blocked_entities], thresholdconfig[threshold], )这说明 PII 防护栏的配置在SDK 本地构造和服务端存储策略两条路径上是同构的均最终收敛为PIIValidationConfig这一份配置。四、后端实现基于 Microsoft Presidio 的检测引擎guardrails 后端位于 opik-guardrails-backendPII 验证器由三个文件构成constructor.py工厂函数construct_pii_validator()负责加载检测引擎并构造PIIValidatorengine_loader.py返回一个 Presidio 分析引擎validator.py核心验证逻辑。引擎加载的实现直截了当def load_engine() - presidio_analyzer.AnalyzerEngine: # TODO: make sure everything is downloaded and the engine is ready-to-use return presidio_analyzer.AnalyzerEngine()从源码结构看AnalyzerEngine在首次构造时完成 NER 模型与识别器Recognizer的装配源码中的 TODO 注释表明确保模型已下载、引擎就绪这件事依赖服务部署环境预置资源guardrails 后端提供 Dockerfile 与 Dockerfile.cpu 两种构建入口。PIIValidator.validate是核心入口完整流程如下validator.pydef validate(self, text, config): results self._analyzer_engine.analyze( texttext, entitiesconfig.entities, languageconfig.language, ) grouped_results: Dict[str, List[PIIEntity]] collections.defaultdict(list) validation_passed True for result in results: entity_type result.entity_type if result.score config.threshold: continue # 低于置信度阈值忽略不拦截 validation_passed False grouped_results[entity_type].append( PIIEntity( startresult.start, endresult.end, scoreresult.score, texttext[result.start : result.end], # 原文中命中片段 ) ) return schemas.ValidationResult( validation_passedvalidation_passed, validation_detailsPIIValidationDetails(detected_entitiesgrouped_results), typeschemas.ValidationType.PII, validation_configconfig, )关键行为可以归纳为四点按配置裁剪识别器entities与language直接透传给 Presidio 的analyze()即只运行与配置实体相关的识别器并加载对应语言的 NER 模型阈值过滤score threshold的命中被continue跳过既不计入结果也不影响通过状态——threshold是纯粹的置信度闸门任一有效命中即失败只要存在一个超过阈值的实体validation_passed就置为False按实体类型分组返回detected_entities是一个以实体类型为键的字典每个命中片段记录start / end / score / text四个字段text直接从原文切片得到方便调用方做脱敏或日志审计。五、默认实体清单与结果结构后端对配置的定义位于 schemas.py其中PIIValidationConfig给出了entities的服务端默认值class PIIValidationConfig(ValidationConfig): entities: Optional[List[str]] pydantic.Field( [ IP_ADDRESS, PHONE_NUMBER, PERSON, MEDICAL_LICENSE, URL, EMAIL_ADDRESS, IBAN_CODE, ], descriptionOptional list of entity types to detect. If not provided, the default list will be used., )这与 SDK docstring 中列出的默认实体清单完全一致IP_ADDRESS、PHONE_NUMBER、PERSON、MEDICAL_LICENSE、URL、EMAIL_ADDRESS、IBAN_CODE。也就是说SDK 侧blocked_entitiesNone的语义是交给后端用默认清单而 SDK 本身并不保存一份默认值副本——这是一个前后端约定。验证结果统一封装为ValidationResultschemas.py包含四个字段validation_passed是否通过、type此处为PII、validation_config回显本次使用的配置、validation_detailsPII 场景下即detected_entities。六、测试用例从单测看预期行为单元测试 test_pii_validator.py 用 mock 引擎精确固化了validate的输入输出契约两个用例分别对应通过与拦截两条路径用例一无 PII 命中验证通过mock_engine.analyze.return_value [] text This is a text with no PII information. config schemas.PIIValidationConfig( entities[PERSON, EMAIL_ADDRESS, PHONE_NUMBER], languageen, threshold0.5, ) result pii_validator.validate(text, config) # validation_passed Truedetected_entities {}用例二命中邮箱与手机号验证失败mock_engine.analyze.return_value [ presidio_analyzer.RecognizerResult( entity_typeEMAIL_ADDRESS, start11, end31, score0.85, ), presidio_analyzer.RecognizerResult( entity_typePHONE_NUMBER, start32, end44, score0.95, ), ] text Contact at john.doeexample.com 1234567890期望结果结构展示了detected_entities的完整形态{ validation_passed: False, validation_details: { detected_entities: { EMAIL_ADDRESS: [ {start: 11, end: 31, score: 0.85, text: john.doeexample.com}, ], PHONE_NUMBER: [ {start: 32, end: 44, score: 0.95, text: 1234567890}, ], } }, validation_config: { entities: [EMAIL_ADDRESS, PHONE_NUMBER], language: en, threshold: 0.5, }, type: PII, }从测试断言可以直接确认text字段就是原文对应区间的切片text[start:end]validation_config会原样回显便于调用方核对本次到底用哪份配置做的检测。七、小结与使用要点配置三要素blocked_entities拦截哪些实体缺省走后端默认清单、language检测语言、threshold置信度闸门默认 0.5SDK 侧只保存配置检测由 guardrails 后端用 Presidio 执行结果可解释性强每个命中都带实体类型、起止下标、置信度与原文片段validation_passed与detected_entities可直接驱动拦截、脱敏或人工复核逻辑调优路径先固定实体清单再根据误报/漏报情况在 0.3~0.7 区间内调threshold处理多语言场景时务必同步设置language适用前提远端执行模式要求 guardrails 后端服务可用其部署与依赖见 opik-guardrails-backend 的 README 与 DockerfileAnalyzerEngine首次初始化需加载 NER 模型属于一次性开销。以上所有结论均可在仓库中按路径复核SDK 侧为 sdks/python/src/opik/guardrails/guards/pii.py后端为 apps/opik-guardrails-backend/opik_guardrails/services/validators/pii/validator.py 与 schemas.py行为契约由 tests/unit/services/test_pii_validator.py 固化。【免费下载链接】comet-llmDebug, evaluate, and monitor your LLM applications, RAG systems, and agentic workflows with comprehensive tracing, automated evaluations, and production-ready dashboards.项目地址: https://gitcode.com/GitHub_Trending/co/comet-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →