Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Artifact type based visualization for HTML, Markdown and etc #3970

Closed
2 of 3 tasks
Ark-kun opened this issue Jun 11, 2020 · 8 comments · Fixed by #6367
Closed
2 of 3 tasks

Artifact type based visualization for HTML, Markdown and etc #3970

Ark-kun opened this issue Jun 11, 2020 · 8 comments · Fixed by #6367

Comments

@Ark-kun
Copy link
Contributor

Ark-kun commented Jun 11, 2020

Currently, the UX visualizes data from mlpipleine-ui-metadata output JSON structure.

It would be great to just support visualizing the individual output artifacts based on type. Only few simple types are needed: HTML and Markdown (plus maybe URI). Everything more complicated can be accomplished by visualizer components.

This issue is a prerequisite for visualizer components.

  • HTML
  • Markdown
  • URI ?

Example code that generates several typed outputs:

import kfp

sample_visualizations_op = kfp.components.load_component_from_text('''
name: Create visualizations
outputs:
- {name: Some Url 1, type: URI}
#- {name: Some Url 2, type: {URI: {data_type: something}}}  # Metadata Writer does not seem to handle complex types at this moment
- {name: Some Url 2, type: URI}
- {name: Some HTML, type: HTML}
- {name: Some Markdown, type: Markdown}
- {name: Some metrics, type: Metrics}

implementation:
  container:
    image: alpine
    command:
    - sh
    - -ex
    - -c
    - |
      output_url1_path="$0"
      output_url2_path="$1"
      output_html_path="$2"
      output_markdown_path="$3"
      output_metrics_path="$4"

      mkdir -p "$(dirname "$output_url1_path")"
      mkdir -p "$(dirname "$output_url2_path")"
      mkdir -p "$(dirname "$output_html_path")"
      mkdir -p "$(dirname "$output_markdown_path")"
      mkdir -p "$(dirname "$output_metrics_path")"

      echo 'https://github.com/kubeflow/pipelines' > "$output_url1_path"
      echo 'https://github.com/kubeflow/pipelines' > "$output_url2_path"
      echo '<html><body>Hello <b>World</b></body></html>' > "$output_html_path"
      echo 'Hello **World**' > "$output_markdown_path"
      echo '{"precision": 0.7, "recall": 0.9}' > "$output_metrics_path"

    - {outputPath: Some Url 1}
    - {outputPath: Some Url 2}
    - {outputPath: Some HTML}
    - {outputPath: Some Markdown}
    - {outputPath: Some metrics}
''')


kfp_endpoint = 'https://XXX.pipelines.googleusercontent.com/'
kfp.Client(host=kfp_endpoint).create_run_from_pipeline_func(sample_visualizations_op, arguments={})

After the execution has finished here are the pod annotations ().

  annotations:
    pipelines.kubeflow.org/component_ref: >-
      {"digest":
      "d2462fd80103d923181e62ae718fd2269189e948dd151a7c406facf9e64a72d8"}
    pipelines.kubeflow.org/component_spec: >-
      {"name":
      "Create visualizations", "outputs": [{"name": "Some Url 1", "type":
      "URI"}, {"name": "Some Url 2", "type": "URI"}, {"name": "Some HTML",
      "type": "HTML"}, {"name": "Some Markdown", "type": "Markdown"}, {"name":
      "Some metrics", "type": "Metrics"}]}
    pipelines.kubeflow.org/execution_cache_key: 7c478724f2cd1c3dbe282070d94ca934168fbb6425722c70b756472f2b22d7e8
    pipelines.kubeflow.org/metadata_input_artifact_ids: '[]'
    pipelines.kubeflow.org/metadata_output_artifact_ids: >-
      [{"id": 4310, "name": "Some-HTML", "uri":
      "minio://mlpipeline/artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/create-visualizations-Some-HTML.tgz",
      "type": "HTML"}, {"id": 4311, "name": "Some-Markdown", "uri":
      "minio://mlpipeline/artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/create-visualizations-Some-Markdown.tgz",
      "type": "Markdown"}, {"id": 4312, "name": "Some-Url-1", "uri":
      "minio://mlpipeline/artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/create-visualizations-Some-Url-1.tgz",
      "type": "URI"}, {"id": 4313, "name": "Some-Url-2", "uri":
      "minio://mlpipeline/artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/create-visualizations-Some-Url-2.tgz",
      "type": "URI"}, {"id": 4314, "name": "Some-metrics", "uri":
      "minio://mlpipeline/artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/create-visualizations-Some-metrics.tgz",
      "type": "Metrics"}, {"id": 4315, "name": "main-logs", "uri":
      "minio://mlpipeline/artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/main.log",
      "type": "NoType"}]
    sidecar.istio.io/inject: 'false'
    workflows.argoproj.io/node-name: create-visualizations-2-jhckp.create-visualizations
    workflows.argoproj.io/outputs: >-
      {"artifacts":[{"name":"create-visualizations-Some-HTML","path":"/tmp/outputs/Some_HTML/data","s3":{"endpoint":"minio-service.default:9000","bucket":"mlpipeline","insecure":true,"accessKeySecret":{"name":"mlpipeline-minio-artifact","key":"accesskey"},"secretKeySecret":{"name":"mlpipeline-minio-artifact","key":"secretkey"},"key":"artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/create-visualizations-Some-HTML.tgz"}},{"name":"create-visualizations-Some-Markdown","path":"/tmp/outputs/Some_Markdown/data","s3":{"endpoint":"minio-service.default:9000","bucket":"mlpipeline","insecure":true,"accessKeySecret":{"name":"mlpipeline-minio-artifact","key":"accesskey"},"secretKeySecret":{"name":"mlpipeline-minio-artifact","key":"secretkey"},"key":"artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/create-visualizations-Some-Markdown.tgz"}},{"name":"create-visualizations-Some-Url-1","path":"/tmp/outputs/Some_Url_1/data","s3":{"endpoint":"minio-service.default:9000","bucket":"mlpipeline","insecure":true,"accessKeySecret":{"name":"mlpipeline-minio-artifact","key":"accesskey"},"secretKeySecret":{"name":"mlpipeline-minio-artifact","key":"secretkey"},"key":"artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/create-visualizations-Some-Url-1.tgz"}},{"name":"create-visualizations-Some-Url-2","path":"/tmp/outputs/Some_Url_2/data","s3":{"endpoint":"minio-service.default:9000","bucket":"mlpipeline","insecure":true,"accessKeySecret":{"name":"mlpipeline-minio-artifact","key":"accesskey"},"secretKeySecret":{"name":"mlpipeline-minio-artifact","key":"secretkey"},"key":"artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/create-visualizations-Some-Url-2.tgz"}},{"name":"create-visualizations-Some-metrics","path":"/tmp/outputs/Some_metrics/data","s3":{"endpoint":"minio-service.default:9000","bucket":"mlpipeline","insecure":true,"accessKeySecret":{"name":"mlpipeline-minio-artifact","key":"accesskey"},"secretKeySecret":{"name":"mlpipeline-minio-artifact","key":"secretkey"},"key":"artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/create-visualizations-Some-metrics.tgz"}},{"name":"main-logs","archiveLogs":true,"s3":{"endpoint":"minio-service.default:9000","bucket":"mlpipeline","insecure":true,"accessKeySecret":{"name":"mlpipeline-minio-artifact","key":"accesskey"},"secretKeySecret":{"name":"mlpipeline-minio-artifact","key":"secretkey"},"key":"artifacts/create-visualizations-2-jhckp/create-visualizations-2-jhckp-2030028307/main.log"}}]}

To get the types we should probably join workflows.argoproj.io/outputs with pipelines.kubeflow.org/component_spec. We can take the Argo outputs, remove the common template name prefix (create-visualizations-) from output names, then normalize and match them with the component_spec outputs.

@Bobgy
Copy link
Contributor

Bobgy commented Jun 12, 2020

Thanks @Ark-kun for preparing the sample for me! That's super helpful.

I'll put this into post 1.0 planning for now. I think it's low effort and really beneficial, definitely something I want to do.

@Bobgy Bobgy added priority/p0 status/triaged Whether the issue has been explicitly triaged kind/feature labels Jun 12, 2020
@stale
Copy link

stale bot commented Sep 11, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the lifecycle/stale The issue / pull request is stale, any activities remove this label. label Sep 11, 2020
@Bobgy
Copy link
Contributor

Bobgy commented Sep 11, 2020

/lifecycle frozen

@k8s-ci-robot k8s-ci-robot added lifecycle/frozen and removed lifecycle/stale The issue / pull request is stale, any activities remove this label. labels Sep 11, 2020
@Bobgy
Copy link
Contributor

Bobgy commented Mar 1, 2021

Moving this to KFP IR backlog, it should work with MLMD artifacts.

@Bobgy Bobgy changed the title Frontend - Add primitive type-based visualizations for HTML, Markdown Artifact type based visualization for HTML, Markdown and etc May 18, 2021
@Bobgy Bobgy removed their assignment May 18, 2021
@Bobgy Bobgy added size/M and removed priority/p0 kind/feature status/triaged Whether the issue has been explicitly triaged labels May 24, 2021
@Bobgy
Copy link
Contributor

Bobgy commented Jun 3, 2021

Code example for downloading artifact content:

const artifactDownloadUrl = Apis.buildReadFileUrl({
path: storagePath,
namespace,
isDownload: true,
});
const artifactViewUrl = Apis.buildReadFileUrl({ path: storagePath, namespace });

@Ark-kun
Copy link
Contributor Author

Ark-kun commented Jun 3, 2021

Previously I've started exploring solution for this in: https://github.com/Ark-kun/pipelines/commits/Frontend---Visualize-HTML It does not do anything yet. Just getting component spec for a node, so that we can get to the output types.

@zijianjoy
Copy link
Collaborator

Currently we cannot get visualization type from Artifact type in V2 compatible:

v2compattype

UI rely on type to visualize viewerContent: https://github.com/kubeflow/pipelines/blob/master/frontend/src/lib/OutputArtifactLoader.ts#L84. But we cannot get this information on V2 compatible.

There are a few potential options:

  1. Use schemaTitle/instanceSchema:
    oneof kind {
    // The name of the type. The format of the title must be:
    // `<namespace>.<title>.<version>`.
    // Examples:
    // - `aiplatform.Model.v1`
    // - `acme.CustomModel.v2`
    // When this field is set, the type must be pre-registered in the MLMD
    // store.
    string schema_title = 1;
  2. Enable componentSpec in v2 compatible:
    if isinstance(op, dsl.ContainerOp) and op._metadata and not op.is_v2:

We need some help to make this decision for exposing original artifact type to UI.

@zijianjoy
Copy link
Collaborator

Currently pending the decision and implementation of #5798.

google-oss-robot pushed a commit that referenced this issue Aug 17, 2021
 (#6349)

* test: Update visualization v2 to output HTML and Markdown.

* address comment

* vis test
google-oss-robot pushed a commit that referenced this issue Aug 18, 2021
)

* feat(frontend): Support v2 HTML/Markdown visualization.

* improve

* shorter name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants