feature: support for pylock.toml
Feature request
I would like it if BentoML also supports using pylock.toml to specify Python dependencies.
Motivation
The current options to specify Python dependencies have their limitations because it is impossible to easily configure per-dependency index urls.
- Using
bentoml.images.Image().python_packages()- will duplicate dependency specification (e.g. for the project in pyproject.toml, and for the bento the service).
- does not support
--extra-index-url. In other words, GPU acceleration with torch does not work.
- Using
bentoml.images.Image().requirements_file()- only supports
--extra-index-urlwhen specified in the file, but uv explicitly does not export these becuase requirements.txt is not powerful enough. - BentoML can add the
--extra-index-urlto the requirements.txt file on the fly, but this will apply to all packages. - BentoML can add
pip_argsto specify--index-strategy unsafe-best-matchbut these are added to theuv pip install. Maybe the documentation is outdated?
- only supports
- Using
bentoml.images.Image().run()orrun_script().- There is no way to copy artifacts (e.g. a requirements.txt, or pylock.toml) to the Docker before executing the run.
Hence, any situation where some package require conflicting --extra-index-url the current setup is not sufficient. I downgraded to bentoml<1.3 to fix this.
I think supporting pylock.toml will fix this, because it explicitly defines all the index urls.
Other
I'm creating this as a feature request, because I don't think there is a good solution based on requirements.txt. That will only work when specifying the index urls per package line, but uv is not going to do that.
As an example, trying to install both torch and certifi fails because it tries to install the latter from the pytorch index.
pyproject.toml
[project]
name = "bentoml-index-example"
version = "0.1.0"
description = "Add your description here"
requires-python = ">=3.13"
dependencies = [
"torch",
"certifi",
"bentoml",
]
[tool.uv.sources]
torch = [
{ index = "pytorch-cpu" },
]
[[tool.uv.index]]
name = "pytorch-cpu"
url = "https://download.pytorch.org/whl/cpu"
explicit = true
requirements.txt
Generated with
uv export --prune bentoml --no-annotate --no-hashes -o requirements.txt
# This file was autogenerated by uv via the following command:
# uv export --prune bentoml --no-annotate --no-hashes -o requirements.txt
certifi==2025.8.3
filelock==3.19.1
fsspec==2025.9.0
jinja2==3.1.6
markupsafe==3.0.2
mpmath==1.3.0
networkx==3.5
setuptools==80.9.0
sympy==1.14.0
torch==2.8.0 ; sys_platform == 'darwin'
torch==2.8.0+cpu ; sys_platform != 'darwin'
typing-extensions==4.15.0
service.py
import bentoml
@bentoml.service()
class Service:
@bentoml.api
def predict(self) -> dict:
return {}
bentofile.yaml
python:
requirements_txt: "requirements.txt"
lock_packages: false
extra_index_url:
- "https://download.pytorch.org/whl/cpu"
pip_args: "--index-strategy unsafe-best-match"
Note that without specifying the extra_index_url in the bentofile.yaml the result is unexpected. It will install torch from PyPI and this is the cuda version (on linux).
Also note that the pip_args are not applied apparently.
Output
When building and containerizing the bento with the following command.
uv run bentoml build --containerize
The output is.
=> ERROR [base-container 10/12] RUN --mount=type=cache,target=/root/.cache/ uv --directory ./env/python/ pip install -r requirements.txt 0.8s
------
> [base-container 10/12] RUN --mount=type=cache,target=/root/.cache/ uv --directory ./env/python/ pip install -r requirements.txt:
0.195 Using Python 3.13.7 environment at: /app/.venv
0.775 × No solution found when resolving dependencies:
0.775 ╰─▶ Because there is no version of certifi==2025.8.3 and you require
0.775 certifi==2025.8.3, we can conclude that your requirements are
0.775 unsatisfiable.
0.775
0.775 hint: `certifi` was found on https://download.pytorch.org/whl/cpu, but
0.775 not at the requested version (certifi==2025.8.3). A compatible version
0.775 may be available on a subsequent index (e.g., https://pypi.org/simple).
0.775 By default, uv will only consider versions that are published on the
0.775 first index that contains a given package, to avoid dependency confusion
0.775 attacks. If all indexes are equally trusted, use `--index-strategy
0.775 unsafe-best-match` to consider all versions from all indexes, regardless
0.775 of the order in which they were defined.
------
Dockerfile:48
--------------------
46 | COPY --chown=bentoml:bentoml ./env/python ./env/python/
47 | # install python packages
48 | >>> RUN --mount=type=cache,target=/root/.cache/ uv --directory ./env/python/ pip install -r requirements.txt
49 |
50 |
--------------------
ERROR: failed to build: failed to solve: process "/bin/sh -c uv --directory ./env/python/ pip install -r requirements.txt" did not complete successfully: exit code: 1
ERROR:
Encountered exception while trying to building image: Command '['/usr/bin/docker', 'build', '--tag', 'service:rtuiryepykufzbfj', '--file', '/tmp/tmpsby28cua/env/docker/Dockerfile', '/tmp/tmpsby28cua']' returned non-zero exit status 1.
Traceback (most recent call last):
File "/home/pieter/projects/orbisk/bentoml-index-example/.venv/lib/python3.13/site-packages/bentoml/_internal/container/__init__.py", line 253, in build
return builder.build(**kwargs)
~~~~~~~~~~~~~^^^^^^^^^^
File "/home/pieter/projects/orbisk/bentoml-index-example/.venv/lib/python3.13/site-packages/bentoml/_internal/container/base.py", line 190, in build
raise BentoMLException(str(e)) from None
bentoml.exceptions.BentoMLException: Command '['/usr/bin/docker', 'build', '--tag', 'service:rtuiryepykufzbfj', '--file', '/tmp/tmpsby28cua/env/docker/Dockerfile', '/tmp/tmpsby28cua']' returned non-zero exit status 1.
(bentoml-index-example) [pieter@neelay bentoml-index-example]$ uv export --prune bentoml --no-annotate --no-hashes -o requirements.txt
Also note that the
pip_argsare not applied apparently.
Use env vars UV_INDEX_STRATEGY=unsafe-best-match, set it in @service() decorator.
@pietermarsman @frostming Can i work on this, if it is not assign to anyone : can u assign it to me ?