隐语实训-11组件介绍与自定义开发

一、隐语开放标准
1.1 标准

在这里插入图片描述- 隐语提出的适用于隐私计算应用的一系列协议的集合。

  • 目前包括数据,组件,节点执行,运行报告等协议。
  • 隐语生态各模块均遵守本标准。
  • 链接:Github Repo: https://github.com/secretflow/spec Doc: https://www.secretflow.org.cn/docs/spec/latest/zh-Hans

隐语中各个模块的交互是依赖于开放标准的,通过标准化协议,提高系统兼容性和开发效率。

1.2 数据协议

隐语中数据部分包含两部分:Public Data和DataRef

  • Public:包含数据名称、类型、元信息和系统信息,是完全公开的。
  • DataRef:引用具体数据的位置和格式,其指向私有数据。
  • 参考文档
    在这里插入图片描述
    比如在联邦学习中的联合数据表,每个Partition可以看作是一个DataRef指向Remote Object
1.3 组件
  • ComponentDef:通过domain、name和version可以定位到唯一的组件,

    • 域(domain):组件的命名空间。

    • 名称(name):组件在命名空间内的唯一标识。

    • 版本(version):组件的版本号。

    • 属性(attributes):组件的属性定义。

    • 输入/输出(inputs/outputs):组件的输入和输出要求,支持多种类型,并可以指定使用的列和参数。

    如果把组件的属性当成一个问卷的话,全部展开这个问卷表是非常庞大的,那么可以先按照属性分类,然后再根据属性的具体值去分模块,比如问卷中问题会有姓名、职业、性别,这是一个模块,根据其不同的回答再去细分更进一步的模块,不同的职业里划分为不同的模块,通过这种方式来构造树结构的问卷表,直观上更有逻辑性些。
    在这里插入图片描述##### 1.4 组件I/O

  1. 指定输入输出的类型,可以是多种类型。
  2. 如果是表,可以进一步指定使用的列。
  3. 还可以进一步指定每一选中列需要填入的参数。
1.5 节点执行协议

在这里插入图片描述- Node Evaluation:规范节点执行的过程,确保节点能够正确地处理输入数据并生成输出结果。

  • 节点是组件的实例

  • StorageConfig参与方的数据路径配置

  • NodeEvalParam定义组件的相关参数Attribute和IO

  • NodeEvalResult是组件运行结果outputs

1.6 运行报告协议

Report:定义运行报告的结构,包括描述、表格、页面部分(Div)、选项卡(Tab)等,用于前端展示组件运行的结果和状态。

二、隐语组件列表

查看sf组件列表有三种方式:

三、调用隐语组件

3.1 调用方式

  • SecretFlow CLI/Lib:无需其他依赖,通过命令行或库调用组件,调用比较复杂,一般用于内部测试。
  • Kuscia:用于简化数据同步和调度操作,隐语推出的一个调度框架。
  • SecretPad:通过用户界面调用组件,操作简便。

3.2 实操示例:

下面展示一个利用python API调用组件的例子,先写一个生成文本的脚本generate_csv.sh

#!/bin/bash

set -e
show_help() {
    echo "Usage: bash generate_csv.sh -c {col_name} -p {file_name}"
    echo "  -c"
    echo "          the column name of id."
    echo "  -p"
    echo "          the path of output csv."
}
if [[ "$#" -lt 1 ]]; then
    show_help
    exit
fi

while getopts ":c:p:" OPTION; do
    case $OPTION in
    c)
        COL_NAME=$OPTARG
        ;;
    p)
        FILE_PATH=$OPTARG
        ;;
    *)
        echo "Incorrect options provided"
        exit 1
        ;;
    esac
done


# header
echo $COL_NAME > $FILE_PATH

# generate 800 random int
for ((i=0; i<800; i++))
do
# from 0 to 1000
id=$(shuf -i 0-1000 -n 1)

# check duplicates
while grep -q "^$id$" $FILE_PATH
do
    id=$(shuf -i 0-1000 -n 1)
done

# write
echo "$id" >> $FILE_PATH
done

echo "Generated csv file is $FILE_PATH."

传到Alice和Bob两个参与者,然后执行去产生数据

alice:

mkdir -p /tmp/alice

sh generate_csv.sh -c id1 -p /tmp/alice/input.csv

Bob:

mkdir -p /tmp/bob

sh generate_csv.sh -c id2 -p /tmp/bob/input.csv

然后是调用组件的脚本psi_demo.py:

import json

from secretflow.component.entry import comp_eval
from secretflow.spec.extend.cluster_pb2 import (
    SFClusterConfig,
    SFClusterDesc,
)
from secretflow.spec.v1.component_pb2 import Attribute
from secretflow.spec.v1.data_pb2 import (
    DistData,
    TableSchema,
    IndividualTable,
    StorageConfig,
)
from secretflow.spec.v1.evaluation_pb2 import NodeEvalParam
import click


@click.command()
@click.argument("party", type=str)
def run(party: str):
    desc = SFClusterDesc(
        parties=["alice", "bob"],
        devices=[
            SFClusterDesc.DeviceDesc(
                name="spu",
                type="spu",
                parties=["alice", "bob"],
                config=json.dumps(
                    {
                        "runtime_config": {"protocol": "REF2K", "field": "FM64"},
                        "link_desc": {
                            "connect_retry_times": 60,
                            "connect_retry_interval_ms": 1000,
                            "brpc_channel_protocol": "http",
                            "brpc_channel_connection_type": "pooled",
                            "recv_timeout_ms": 1200 * 1000,
                            "http_timeout_ms": 1200 * 1000,
                        },
                    }
                ),
            ),
            SFClusterDesc.DeviceDesc(
                name="heu",
                type="heu",
                parties=[],
                config=json.dumps(
                    {
                        "mode": "PHEU",
                        "schema": "paillier",
                        "key_size": 2048,
                    }
                ),
            ),
        ],
    )

    sf_cluster_config = SFClusterConfig(
        desc=desc,
        public_config=SFClusterConfig.PublicConfig(
            ray_fed_config=SFClusterConfig.RayFedConfig(
                parties=["alice", "bob"],
                addresses=[
                    "127.0.0.1:61041",
                    "127.0.0.1:61042",
                ],
            ),
            spu_configs=[
                SFClusterConfig.SPUConfig(
                    name="spu",
                    parties=["alice", "bob"],
                    addresses=[
                        "127.0.0.1:61045",
                        "127.0.0.1:61046",
                    ],
                )
            ],
        ),
        private_config=SFClusterConfig.PrivateConfig(
            self_party=party,
            ray_head_addr="local",  # local means setup a Ray cluster instead connecting to an existed one.
        ),
    )

    # check https://www.secretflow.org.cn/docs/spec/latest/zh-Hans/intro#nodeevalparam for details.
    sf_node_eval_param = NodeEvalParam(
        domain="preprocessing",
        name="psi",
        version="0.0.1",
        attr_paths=[
            "protocol",
            "sort",
            "bucket_size",
            "ecdh_curve_type",
            "input/receiver_input/key",
            "input/sender_input/key",
        ],
        attrs=[
            Attribute(s="ECDH_PSI_2PC"),
            Attribute(b=True),
            Attribute(i64=1048576),
            Attribute(s="CURVE_FOURQ"),
            Attribute(ss=["id1"]),
            Attribute(ss=["id2"]),
        ],
        inputs=[
            DistData(
                name="receiver_input",
                type="sf.table.individual",
                data_refs=[
                    DistData.DataRef(uri="input.csv", party="alice", format="csv"),
                ],
            ),
            DistData(
                name="sender_input",
                type="sf.table.individual",
                data_refs=[
                    DistData.DataRef(uri="input.csv", party="bob", format="csv"),
                ],
            ),
        ],
        output_uris=[
            "output.csv",
        ],
    )

    sf_node_eval_param.inputs[0].meta.Pack(
        IndividualTable(
            schema=TableSchema(
                id_types=["str"],
                ids=["id1"],
            ),
            line_count=-1,
        ),
    )

    sf_node_eval_param.inputs[1].meta.Pack(
        IndividualTable(
            schema=TableSchema(
                id_types=["str"],
                ids=["id2"],
            ),
            line_count=-1,
        ),
    )

    storage_config = StorageConfig(
        type="local_fs",
        local_fs=StorageConfig.LocalFSConfig(wd=f"/tmp/{party}"),
    )

    res = comp_eval(sf_node_eval_param, storage_config, sf_cluster_config)

    print(f'Node eval res is \n{res}')


if __name__ == "__main__":
    run()

在Alice和Bob中分别执行这个psi脚本,两个终端中能看到一下输出:

Node eval res is
outputs {
  name: "output.csv"
  type: "sf.table.vertical_table"
  system_info {
  }
  meta {
    type_url: "type.googleapis.com/secretflow.spec.v1.VerticalTable"
    value: "\n\n\n\003id1\"\003str\n\n\n\003id2\"\003str\020\211\005"
  }
  data_refs {
    uri: "output.csv"
    party: "alice"
    format: "csv"
  }
  data_refs {
    uri: "output.csv"
    party: "bob"
    format: "csv"
  }
}

/tmp/alice/output.csv/tmp/bob/output.csv 中检查结果。两个文件的内容除了表头应该是一致的。

四、创建组件

在隐语中新增组件,主要有以下步骤:

1、新建文件,在 secretflow/component/ 目录下创建一个新的文件。

2、声明组件,使用 secretflow.component.component 创建一个组件类。

3、定义组件参数、属性和输入输出。

4、定义组件执行内容。

5、注册组件、将新增组件加入到secretflow.component.entry 的 ALL_COMPONENTS 中。

6、打包隐语镜像(更新组件列表及翻译,打包镜像),注册隐语镜像(更新隐语SecretPad平台组件列表,在Kuscia中注册自定义算法镜像)。

7、在隐语SecretPad平台上使用新组件。

具体参考文档链接:secretpad新增组件:https://www.secretflow.org.cn/zh-CN/docs/secretpad-all-in-one/v1.6.1b0/more_tutorials/new_components

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值