[Proxied artifact operations] Implement REST API endpoints and artifact repository#4946
Conversation
| return f.read() | ||
|
|
||
|
|
||
| def test_log_artifact(tmpdir): |
There was a problem hiding this comment.
This is a minimal integration test to make sure an aritafct can be logged using the mlflow artifacts service.
d138f38 to
d32c6a4
Compare
Signed-off-by: harupy <17039389+harupy@users.noreply.github.com>
Signed-off-by: harupy <17039389+harupy@users.noreply.github.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
| This example requires a wheel for `mlflow` to be stored in `dist`. | ||
|
|
||
| ```sh | ||
| # Clean up existing wheels | ||
| rm dist/* | ||
|
|
||
| # Build a wheel for the development version of mlflow | ||
| pip wheel --no-deps --wheel-dir dist ../.. | ||
|
|
||
| # Build a wheel for the latest version of mlflow on PyPI | ||
| pip wheel --no-deps --wheel-dir dist mlflow | ||
| ``` |
There was a problem hiding this comment.
Why are these steps required? If there's a way to avoid them, that would be nice in order to reduce complexity for users.
There was a problem hiding this comment.
This is mainly for development purposes. We can simplify the workflow by preparing two Docker files (Dockerfile and Dockerfile.dev) and switching them with variable substitution.
docker-compose.yml would look like:
# docker-compose.yml
tracking-server:
build:
context: .
# Defaults to `Dockerfile` if `DOCKERFILE` environment variable doesn't exist.
dockerfile: "${DOCKERFILE:-Dockerfile}"
depends_on:
- postgres
- artifacts-server
README.md would look like:
This directory contains a set of files for demonstrating the MLflow Artifacts service.
## Run the example
```sh
# Build services
docker-compose build
# Launch tracking and artifacts servers
docker-compose up -d
# Run `run.py` that uploads, downloads, and list artifacts
docker-compose run -v ${PWD}/run.py:/app/run.py client python run.py
```
## Explore the logging results:
```sh
# Make sure both tracking and artifacts servers are running
docker-compose ps
```
- MLflow UI is available at http://localhost:5000 to explore tracking results.
- MinIO Console is available at http://localhost:9001 to explore logged artifacts. The login username and password are `user` and `password`.
## Reset tracking and artifacts servers
```
docker-compose down --volumes --remove-orphans
```
👇👇👇
## Development
```
pip wheel --no-deps --wheel-dir dist ../..
DOCKERFILE=Dockerfile.dev docker-compose build
docker-compose run -v ${PWD}/run.py:/app/run.py client python run.py
```
What do you think about this approach?
There was a problem hiding this comment.
Dockerfile and Dockerfile.dev would look like this.
Dockerfile:
FROM python:3.6
WORKDIR /app
RUN pip install psycopg2 boto3
RUN pip install mlflow
Dockerfile.dev:
FROM python:3.6
WORKDIR /app
RUN pip install psycopg2 boto3
RUN pip install mlflow
COPY dist ./dist
RUN pip install dist/mlflow-*.whl
| metavar="URI", | ||
| default="./mlartifacts", | ||
| help=( | ||
| "The base artifact location from which to resolve artifact upload/download/list requests " |
There was a problem hiding this comment.
Love it! Can we also clarify that this only applies when the tracking server is configured to stream artifacts and the experiment artifact root is http or mlflow-artifacts?
There was a problem hiding this comment.
In general, we should figure out how to tell users about the http and mlflow-artifacts URIs for --default-artifact-root as well.
There was a problem hiding this comment.
Love it! Can we also clarify that this only applies when the tracking server is configured to stream artifacts and the experiment artifact root is http or mlflow-artifacts?
Sure!
In general, we should figure out how to tell users about the http and mlflow-artifacts URIs for --default-artifact-root as well.
Can we new sections for HTTP and mlflow-artifacts schemes in https://www.mlflow.org/docs/latest/tracking.html#artifact-stores?
There was a problem hiding this comment.
In general, we should figure out how to tell users about the http and mlflow-artifacts URIs for --default-artifact-root as well.
That's a good idea. We should also make it easy for users to learn about these through the mlflow server CLI in a follow-up PR.
| with open(tmp_path, "wb") as f: | ||
| chunk_size = 1024 * 1024 # 1 MB | ||
| while True: | ||
| chunk = request.stream.read(chunk_size) |
There was a problem hiding this comment.
Is there any timeout on the stream read operation? Else, we may get stuck here forever.
There was a problem hiding this comment.
request.streamis an instance ofgunicorn.http.body.Body.gunicorn.http.body.Body.readdoesn't seem to have an option related totimeout:
def read(self, size=None):
size = self.getsize(size)
...There was a problem hiding this comment.
Got it. This probably isn't too big a deal because we set gunicorn worker timeouts. Worst case, we may hang here until the worker times out, which is fine :).
|
|
||
| def _download_file(self, remote_file_path, local_path): | ||
| url = posixpath.join(self.artifact_uri, remote_file_path) | ||
| with self._session.get(url, stream=True) as resp: |
There was a problem hiding this comment.
Is there a timeout we should specify here? Else, we may get stuck here
There was a problem hiding this comment.
Yes, what about 10 minutes?. I'm checking the behavior of timeout when stream=True.
There was a problem hiding this comment.
There was a problem hiding this comment.
Can we set timeout=10 (seconds)?
| @@ -0,0 +1,80 @@ | |||
| syntax = "proto2"; | |||
There was a problem hiding this comment.
Can we add a docstring to this proto file explaining which use cases it serves?
| @@ -0,0 +1,45 @@ | |||
| This directory contains a set of files for demonstrating the MLflow Artifacts service. | |||
There was a problem hiding this comment.
Can we explain what the artifacts service does and provide a small example command that users could run manually to serve artifacts via mlflow server in the README?
Signed-off-by: harupy <17039389+harupy@users.noreply.github.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
Signed-off-by: harupy <hkawamura0130@gmail.com>
| with open(tmp_path, "wb") as f: | ||
| chunk_size = 1024 * 1024 # 1 MB | ||
| while True: | ||
| chunk = request.stream.read(chunk_size) |
There was a problem hiding this comment.
Got it. This probably isn't too big a deal because we set gunicorn worker timeouts. Worst case, we may hang here until the worker times out, which is fine :).
|
@dbczumar Thanks for reviewing this PR! |

Signed-off-by: harupy 17039389+harupy@users.noreply.github.com
What changes are proposed in this pull request?
Implement REST API endpoints + artifact repository.
How is this patch tested?
Unit tests
Release Notes
Is this a user-facing change?
(Details in 1-2 sentences. You can just refer to another PR with a description if this PR is part of a larger change.)
What component(s), interfaces, languages, and integrations does this PR affect?
Components
area/artifacts: Artifact stores and artifact loggingarea/build: Build and test infrastructure for MLflowarea/docs: MLflow documentation pagesarea/examples: Example codearea/model-registry: Model Registry service, APIs, and the fluent client calls for Model Registryarea/models: MLmodel format, model serialization/deserialization, flavorsarea/projects: MLproject format, project running backendsarea/scoring: MLflow Model server, model deployment tools, Spark UDFsarea/server-infra: MLflow Tracking server backendarea/tracking: Tracking Service, tracking client APIs, autologgingInterface
area/uiux: Front-end, user experience, plotting, JavaScript, JavaScript dev serverarea/docker: Docker use across MLflow's components, such as MLflow Projects and MLflow Modelsarea/sqlalchemy: Use of SQLAlchemy in the Tracking Service or Model Registryarea/windows: Windows supportLanguage
language/r: R APIs and clientslanguage/java: Java APIs and clientslanguage/new: Proposals for new client languagesIntegrations
integrations/azure: Azure and Azure ML integrationsintegrations/sagemaker: SageMaker integrationsintegrations/databricks: Databricks integrationsHow should the PR be classified in the release notes? Choose one:
rn/breaking-change- The PR will be mentioned in the "Breaking Changes" sectionrn/none- No description will be included. The PR will be mentioned only by the PR number in the "Small Bugfixes and Documentation Updates" sectionrn/feature- A new user-facing feature worth mentioning in the release notesrn/bug-fix- A user-facing bug fix worth mentioning in the release notesrn/documentation- A user-facing documentation change worth mentioning in the release notes