コード例 #1
0
    def _build_resolver_for_latest_model_blessing(
            self,
            model_blessing_channel_key: str) -> pipeline_pb2.PipelineTaskSpec:
        """Builds the resolver spec for latest valid ModelBlessing artifact."""
        # 1. Build the task info.
        result = pipeline_pb2.PipelineTaskSpec()
        name = '{}{}'.format(self._name, _MODEL_BLESSING_RESOLVER_SUFFIX)
        result.task_info.CopyFrom(pipeline_pb2.PipelineTaskInfo(name=name))
        executor_label = _EXECUTOR_LABEL_PATTERN.format(name)
        result.executor_label = executor_label

        # 2. Specify the outputs of the task.
        result.outputs.artifacts[model_blessing_channel_key].CopyFrom(
            compiler_utils.build_output_artifact_spec(
                self._outputs[model_blessing_channel_key]))

        # 3. Build the resolver executor spec for latest valid ModelBlessing.
        executor = pipeline_pb2.PipelineDeploymentConfig.ExecutorSpec()
        artifact_queries = {}
        query_filter = ("artifact_type='{type}' and state={state}"
                        " and custom_properties['{key}']='{value}'").format(
                            type=compiler_utils.get_artifact_title(
                                standard_artifacts.ModelBlessing),
                            state=metadata_store_pb2.Artifact.State.Name(
                                metadata_store_pb2.Artifact.LIVE),
                            key=constants.ARTIFACT_PROPERTY_BLESSED_KEY,
                            value=constants.BLESSED_VALUE)
        artifact_queries[
            model_blessing_channel_key] = ResolverSpec.ArtifactQuerySpec(
                filter=query_filter)
        executor.resolver.CopyFrom(
            ResolverSpec(output_artifact_queries=artifact_queries))

        self._deployment_config.executors[executor_label].CopyFrom(executor)
        return result
コード例 #2
0
    def _build_latest_artifact_resolver(
            self) -> List[pipeline_pb2.PipelineTaskSpec]:
        """Builds a resolver spec for a latest artifact resolver.

    Returns:
      A list of two PipelineTaskSpecs. One represents the query for latest valid
      ModelBlessing artifact. Another one represents the query for latest
      blessed Model artifact.
    Raises:
      ValueError: when desired_num_of_artifacts != 1. 1 is the only supported
        value currently.
    """

        task_spec = pipeline_pb2.PipelineTaskSpec()
        task_spec.task_info.CopyFrom(
            pipeline_pb2.PipelineTaskInfo(name=self._name))
        executor_label = _EXECUTOR_LABEL_PATTERN.format(self._name)
        task_spec.executor_label = executor_label

        # Fetch the init kwargs for the resolver.
        resolver_config = self._exec_properties[resolver.RESOLVER_CONFIG]
        if (isinstance(resolver_config, dict)
                and resolver_config.get('desired_num_of_artifacts', 0) > 1):
            raise ValueError(
                'Only desired_num_of_artifacts=1 is supported currently.'
                ' Got {}'.format(
                    resolver_config.get('desired_num_of_artifacts')))

        # Specify the outputs of the task.
        for name, output_channel in self._outputs.items():
            # Currently, we're working under the assumption that for tasks
            # (those generated by BaseComponent), each channel contains a single
            # artifact.
            output_artifact_spec = compiler_utils.build_output_artifact_spec(
                output_channel)
            task_spec.outputs.artifacts[name].CopyFrom(output_artifact_spec)

        # Specify the input parameters of the task.
        for k, v in compiler_utils.build_input_parameter_spec(
                self._exec_properties).items():
            task_spec.inputs.parameters[k].CopyFrom(v)

        artifact_queries = {}
        # Buid the artifact query for each channel in the input dict.
        for name, c in self._inputs.items():
            query_filter = ("artifact_type='{type}' and state={state}").format(
                type=compiler_utils.get_artifact_title(c.type),
                state=metadata_store_pb2.Artifact.State.Name(
                    metadata_store_pb2.Artifact.LIVE))
            artifact_queries[name] = ResolverSpec.ArtifactQuerySpec(
                filter=query_filter)

        resolver_spec = ResolverSpec(output_artifact_queries=artifact_queries)
        executor = pipeline_pb2.PipelineDeploymentConfig.ExecutorSpec()
        executor.resolver.CopyFrom(resolver_spec)
        self._deployment_config.executors[executor_label].CopyFrom(executor)
        return [task_spec]
コード例 #3
0
    def _build_resolver_for_latest_blessed_model(
            self, model_channel_key: str, model_blessing_resolver_name: str,
            model_blessing_channel_key: str) -> pipeline_pb2.PipelineTaskSpec:
        """Builds the resolver spec for latest blessed Model artifact."""
        # 1. Build the task info.
        result = pipeline_pb2.PipelineTaskSpec()
        name = '{}{}'.format(self._name, _MODEL_RESOLVER_SUFFIX)
        result.task_info.CopyFrom(pipeline_pb2.PipelineTaskInfo(name=name))
        executor_label = _EXECUTOR_LABEL_PATTERN.format(name)
        result.executor_label = executor_label

        # 2. Specify the input of the task. The output from model_blessing_resolver
        # will be used as the input.
        input_artifact_spec = pipeline_pb2.TaskInputsSpec.InputArtifactSpec(
            producer_task=model_blessing_resolver_name,
            output_artifact_key=model_blessing_channel_key)
        result.inputs.artifacts[_MODEL_RESOLVER_INPUT_KEY].CopyFrom(
            input_artifact_spec)

        # 3. Specify the outputs of the task. model_resolver has one output for
        # the latest blessed model.
        result.outputs.artifacts[model_channel_key].CopyFrom(
            compiler_utils.build_output_artifact_spec(
                self._outputs[model_channel_key]))

        # 4. Build the resolver executor spec for latest blessed Model.
        executor = pipeline_pb2.PipelineDeploymentConfig.ExecutorSpec()
        artifact_queries = {}
        query_filter = (
            "artifact_type='{type}' and "
            "state={state} and name={{$.inputs.artifacts['{input_key}']"
            ".custom_properties['{property_key}']}}").format(
                type=compiler_utils.get_artifact_title(
                    standard_artifacts.Model),
                state=metadata_store_pb2.Artifact.State.Name(
                    metadata_store_pb2.Artifact.LIVE),
                input_key=_MODEL_RESOLVER_INPUT_KEY,
                property_key=constants.ARTIFACT_PROPERTY_CURRENT_MODEL_ID_KEY)
        artifact_queries[model_channel_key] = ResolverSpec.ArtifactQuerySpec(
            filter=query_filter)
        executor.resolver.CopyFrom(
            ResolverSpec(output_artifact_queries=artifact_queries))
        self._deployment_config.executors[executor_label].CopyFrom(executor)

        return result
コード例 #4
0
    def build(self) -> List[pipeline_pb2.PipelineTaskSpec]:
        """Builds a pipeline StepSpec given the node information.

    Returns:
      A list of PipelineTaskSpec messages corresponding to the node. For most of
      the cases, the list contains a single element. The only exception is when
      compiling latest blessed model resolver. One DSL node will be
      split to two resolver specs to reflect the two-phased query execution.
    Raises:
      NotImplementedError: When the node being built is an InfraValidator.
    """
        task_spec = pipeline_pb2.PipelineTaskSpec()
        task_spec.task_info.CopyFrom(
            pipeline_pb2.PipelineTaskInfo(name=self._name))
        executor_label = _EXECUTOR_LABEL_PATTERN.format(self._name)
        task_spec.executor_label = executor_label
        executor = pipeline_pb2.PipelineDeploymentConfig.ExecutorSpec()

        # 1. Resolver tasks won't have input artifacts in the API proto. First we
        #    specialcase two resolver types we support.
        if isinstance(self._node, resolver.Resolver):
            return self._build_resolver_spec()

        # 2. Build the node spec.
        # TODO(b/157641727): Tests comparing dictionaries are brittle when comparing
        # lists as ordering matters.
        dependency_ids = [node.id for node in self._node.upstream_nodes]
        # Specify the inputs of the task.
        for name, input_channel in self._inputs.items():
            # If the redirecting map is provided (usually for latest blessed model
            # resolver, we'll need to redirect accordingly. Also, the upstream node
            # list will be updated and replaced by the new producer id.
            producer_id = input_channel.producer_component_id
            output_key = input_channel.output_key
            for k, v in self._channel_redirect_map.items():
                if k[0] == producer_id and producer_id in dependency_ids:
                    dependency_ids.remove(producer_id)
                    dependency_ids.append(v[0])
            producer_id = self._channel_redirect_map.get(
                (producer_id, output_key), (producer_id, output_key))[0]
            output_key = self._channel_redirect_map.get(
                (producer_id, output_key), (producer_id, output_key))[1]

            input_artifact_spec = pipeline_pb2.TaskInputsSpec.InputArtifactSpec(
                producer_task=producer_id, output_artifact_key=output_key)
            task_spec.inputs.artifacts[name].CopyFrom(input_artifact_spec)

        # Specify the outputs of the task.
        for name, output_channel in self._outputs.items():
            # Currently, we're working under the assumption that for tasks
            # (those generated by BaseComponent), each channel contains a single
            # artifact.
            output_artifact_spec = compiler_utils.build_output_artifact_spec(
                output_channel)
            task_spec.outputs.artifacts[name].CopyFrom(output_artifact_spec)

        # Specify the input parameters of the task.
        for k, v in compiler_utils.build_input_parameter_spec(
                self._exec_properties).items():
            task_spec.inputs.parameters[k].CopyFrom(v)

        # 3. Build the executor body for other common tasks.
        if isinstance(self._node, importer.Importer):
            executor.importer.CopyFrom(self._build_importer_spec())
        elif isinstance(self._node, components.FileBasedExampleGen):
            executor.container.CopyFrom(
                self._build_file_based_example_gen_spec())
        elif isinstance(self._node, (components.InfraValidator)):
            raise NotImplementedError(
                'The componet type "{}" is not supported'.format(
                    type(self._node)))
        else:
            executor.container.CopyFrom(self._build_container_spec())

        dependency_ids = sorted(dependency_ids)
        for dependency in dependency_ids:
            task_spec.dependent_tasks.append(dependency)

        task_spec.caching_options.CopyFrom(
            pipeline_pb2.PipelineTaskSpec.CachingOptions(
                enable_cache=self._enable_cache))

        # 4. Attach the built executor spec to the deployment config.
        self._deployment_config.executors[executor_label].CopyFrom(executor)

        return [task_spec]