Repository: bentoml/BentoML

Issue:
BentoML adds wrong requirement for PytorchLightning
**Describe the bug**
BentoML adds package ```pytorch``` to ```requirements.txt``` file which cannot be installed.


**To Reproduce**
deploy.py
```python
requirements = [
    'bentoml==0.11.0',
    'dask[bag]==2021.1.0',
    'imageio==2.9.0',
    'toolz==0.11.1',
    'torch==1.7.1',
    'numpy==1.18.2',
    'pilgram==1.2.0',
    'pillow==8.1.0',
    'torchvision==0.8.2',
    'pytorch-lightning==1.1.7',
]


@bentoml.env(pip_packages=requirements)
@bentoml.artifacts([PytorchLightningModelArtifact('model')])
class PytorchLightningService(bentoml.BentoService):
    @bentoml.api(input=ImageInput())
    def predict(self, img):
        input_tensor = transform(img)
        return self.artifacts.model(input_tensor).detach().numpy()
```
create_bento_service.py
```python
model = ResnetPL()
model = model.load_from_checkpoint('checkpoint.ckpt')
model.freeze()

svc = PytorchLightningService()
svc.pack('model', model)
svc.save_to_dir(CHECKPOINT_DIR / 'services')
```
```bash
docker build services/.
```

**Expected behavior**
Easily created and built docker image.

**Screenshots/Logs**
```bash
Running setup.py install for pytorch: started
    Running setup.py install for pytorch: finished with status 'error'
    ERROR: Command errored out with exit status 1:
     command: /opt/conda/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-4h0bku66/pytorch_d4dd611406b64330b1aec7fd18f8967c/setup.py'"'"'; __file__='"'"'/tmp/pip-install-4h0bku66/pytorch_d4dd611406b64330b1aec7fd18f8967c/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-ii868i92/install-record.txt --single-version-externally-managed --compile --install-headers /opt/conda/include/python3.8/pytorch
         cwd: /tmp/pip-install-4h0bku66/pytorch_d4dd611406b64330b1aec7fd18f8967c/
    Complete output (5 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-4h0bku66/pytorch_d4dd611406b64330b1aec7fd18f8967c/setup.py", line 11, in <module>
        raise Exception(message)
    Exception: You tried to install "pytorch". The package named for PyTorch is "torch"
    ----------------------------------------
ERROR: Command errored out with exit status 1: /opt/conda/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-4h0bku66/pytorch_d4dd611406b64330b1aec7fd18f8967c/setup.py'"'"'; __file__='"'"'/tmp/pip-install-4h0bku66/pytorch_d4dd611406b64330b1aec7fd18f8967c/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-ii868i92/install-record.txt --single-version-externally-managed --compile --install-headers /opt/conda/include/python3.8/pytorch Check the logs for full command output.
```

**Environment:**
 - OS: Ubuntu 20.04.1 LTS
 - Python 3.8.5
 - BentoML 0.11.0


**Additional context**
I find out that ```pytorch``` is added to ```requirements.txt``` because of:
```python
class PytorchLightningModelArtifact(BentoServiceArtifact):
  def set_dependencies(self, env: BentoServiceEnv):
    env.add_pip_packages(['pytorch'])
```
in ```bentoml.frameworks/pytorch.py:250```. Is it a bug?



Discussion:
@pkolebski This is a bug. Thanks for reporting it.

I am going to add a fix for this right now

Resolving patch:
diff --git a/bentoml/frameworks/pytorch.py b/bentoml/frameworks/pytorch.py
--- a/bentoml/frameworks/pytorch.py
+++ b/bentoml/frameworks/pytorch.py
@@ -248,7 +248,7 @@ def load(self, path):
         self._model = self._get_torch_script_model(self._saved_model_file_path(path))
 
     def set_dependencies(self, env: BentoServiceEnv):
-        env.add_pip_packages(['pytorch'])
+        env.add_pip_packages(['pytorch-lightning'])
 
     def get(self):
         if self._model is None:


Test patch:
diff --git a/ci/pytorch_lightning_integration_tests.sh b/ci/pytorch_lightning_integration_tests.sh
--- a/ci/pytorch_lightning_integration_tests.sh
+++ b/ci/pytorch_lightning_integration_tests.sh
@@ -9,8 +9,8 @@ trap 'error=1' ERR
 GIT_ROOT=$(git rev-parse --show-toplevel)
 cd "$GIT_ROOT" || exit
 
-# Install PyTorch
-pip install torch==1.5.0+cpu torchvision==0.6.0+cpu -f https://download.pytorch.org/whl/torch_stable.html pytorch-lightning
+# Install PyTorchLightning
+pip install pytorch-lightning
 pytest "$GIT_ROOT"/tests/integration/test_pytorch_lightning_model_artifact.py --cov=bentoml --cov-config=.coveragerc
 
 test $error = 0 # Return non-zero if pytest failed
diff --git a/tests/integration/test_pytorch_lightning_model_artifact.py b/tests/integration/test_pytorch_lightning_model_artifact.py
--- a/tests/integration/test_pytorch_lightning_model_artifact.py
+++ b/tests/integration/test_pytorch_lightning_model_artifact.py
@@ -1,3 +1,7 @@
+import json
+import uuid
+import pytest
+
 import torch
 import pandas as pd
 
@@ -8,7 +12,10 @@
     PytorchLightningService,
 )
 from pytorch_lightning.core.lightning import LightningModule
-from tests.integration.utils import export_service_bundle
+from tests.integration.utils import (
+    run_api_server_docker_container,
+    build_api_server_docker_image,
+)
 
 
 class TorchLightningModel(LightningModule):
@@ -16,6 +23,11 @@ def forward(self, x):
         return x.add(1)
 
 
+class TorchLightningModelTwo(LightningModule):
+    def forward(self, x):
+        return x.add(2)
+
+
 def test_pytorch_lightning_model_artifact_with_saved_lightning_model():
     with TempDirectory() as temp_dir:
         svc = PytorchLightningService()
@@ -25,7 +37,7 @@ def test_pytorch_lightning_model_artifact_with_saved_lightning_model():
         torch.jit.save(script, script_path)
         svc.pack('model', script_path)
 
-        saved_path = svc.save()
+        saved_path = svc.save(version=uuid.uuid4().hex[0:8])
         svc = bentoml.load(saved_path)
         result = svc.predict(pd.DataFrame([[5, 4, 3, 2]]))
         assert result.tolist() == [[6, 5, 4, 3]]
@@ -36,7 +48,37 @@ def test_pytorch_lightning_model_artifact():
     model = TorchLightningModel()
     svc.pack('model', model)
 
-    with export_service_bundle(svc) as saved_path:
-        svc = bentoml.load(saved_path)
-        result = svc.predict(pd.DataFrame([[5, 4, 3, 2]]))
-        assert result.tolist() == [[6, 5, 4, 3]]
+    saved_path = svc.save(version=uuid.uuid4().hex[0:8])
+    svc = bentoml.load(saved_path)
+    result = svc.predict(pd.DataFrame([[5, 4, 3, 2]]))
+    assert result.tolist() == [[6, 5, 4, 3]]
+
+
+@pytest.fixture(scope='module')
+def image(clean_context):
+    svc = PytorchLightningService()
+    model = TorchLightningModelTwo()
+    svc.pack('model', model)
+    saved_path = svc.save(version=uuid.uuid4().hex[0:8])
+
+    yield clean_context.enter_context(build_api_server_docker_image(saved_path))
+
+
+@pytest.fixture(scope='module')
+def host(image):
+    with run_api_server_docker_container(
+        image, enable_microbatch=True, timeout=500
+    ) as host:
+        yield host
+
+
+@pytest.mark.asyncio
+async def test_pytorch_lightning_with_docker(host):
+    await pytest.assert_request(
+        "POST",
+        f"http://{host}/predict",
+        headers=(("Content-Type", "application/json"),),
+        data=json.dumps([[5, 4, 3, 2]]),
+        assert_status=200,
+        assert_data=b'[[7, 6, 5, 4]]',
+    )