Skip to content

Commit fa72d05

Browse files
authored
LCORE-438: Fix imabe building for GPU variant (#32)
* LCORE-438: Fix imabe building for GPU variant * LCORE-438: Add GH actions for gpu image * LCORE-438: Cleanup - do not use llama-stack git version * LCORE-438: Cleanup - update uv.lock * LCORE-438: Fix installing in image pytorch with gpu support * LCORE-438: Try building in Gitlab-CI * LCORE-438: Add detection of GPU Python libs in image building * LCORE-438: Remove detection of GPU Python libs in image building * LCORE-438: Rebase from main * LCORE-438: Enable downloading models again. * LCORE-438: Fix linters. * LCORE-438: Fix linters 2. * LCORE-438: Fix linters 3. * LCORE-438: Do not build gpu image in a PR. It takes ~20min.
1 parent 3e4708c commit fa72d05

File tree

5 files changed

+1090
-813
lines changed

5 files changed

+1090
-813
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: Build image, main branch push quay.io
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
7+
env:
8+
IMAGE_NAME: rag-content-gpu
9+
IMAGE_NAMESPACE: ${{ github.repository_owner }}
10+
IMAGE_REGISTRY: ghcr.io
11+
LATEST_TAG: latest
12+
CONTAINER_FILE: Containerfile-gpu
13+
14+
jobs:
15+
build-and-push-dev-gpu:
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: read
19+
# Required for image pushing to a registry
20+
packages: write
21+
steps:
22+
- name: Install buildah
23+
run: |
24+
sudo apt update
25+
# qemu is required for arm64 builds
26+
sudo apt install -y buildah qemu-user-static
27+
- name: Checkout code
28+
uses: actions/checkout@v4
29+
- name: Free Disk Space (Ubuntu)
30+
uses: jlumbroso/free-disk-space@v1.3.1
31+
with:
32+
# this might remove tools that are actually needed,
33+
# if set to "true" but frees about 6 GB
34+
tool-cache: true
35+
36+
- name: Create dev image tag
37+
run: |
38+
echo "DEV_TAG=dev-$(date +%Y%m%d)-$(git rev-parse --short HEAD)" >> $GITHUB_ENV
39+
echo "dev image tag: ${{ env.DEV_TAG }}"
40+
- name: Build image with Buildah
41+
id: build_image
42+
uses: redhat-actions/buildah-build@v2
43+
with:
44+
image: ${{ env.IMAGE_NAME }}
45+
tags: |
46+
${{ env.DEV_TAG }}
47+
${{ env.LATEST_TAG }}
48+
containerfiles: |
49+
${{ env.CONTAINER_FILE }}
50+
archs: amd64, arm64
51+
oci: true
52+
- name: Check images
53+
run: |
54+
buildah images | grep '${{ env.IMAGE_NAME }}'
55+
echo '${{ steps.build_image.outputs.image }}'
56+
echo '${{ steps.build_image.outputs.tags }}'
57+
- name: Check manifest
58+
run: |
59+
set -x
60+
buildah manifest inspect ${{ steps.build_image.outputs.image }}:${{ env.LATEST_TAG }}
61+
62+
- name: Push image to Quay.io
63+
uses: redhat-actions/push-to-registry@v2
64+
if: ${{ github.event_name != 'pull_request' }}
65+
with:
66+
image: ${{ steps.build_image.outputs.image }}
67+
tags: ${{ steps.build_image.outputs.tags }}
68+
registry: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAMESPACE }}
69+
username: ${{ github.actor }}
70+
password: ${{ github.token }}

Containerfile-gpu

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,53 @@
1-
ARG FLAVOR=gpu
1+
# Image with GPU CUDA only backend.
2+
FROM nvcr.io/nvidia/cuda:12.9.1-devel-ubi9
23

3-
FROM registry.access.redhat.com/ubi9/python-312 as cpu-base
4-
ARG FLAVOR
5-
6-
FROM nvcr.io/nvidia/cuda:12.6.2-devel-ubi9 as gpu-base
7-
ARG FLAVOR
8-
RUN dnf install -y python3.12 python3.12-pip libcudnn8 libnccl git
4+
# Install Python
5+
RUN dnf install -y --nodocs --setopt=keepcache=0 --setopt=tsflags=nodocs \
6+
python3.12 python3.12-devel python3.12-pip libcudnn9 libnccl libcusparselt0 && \
7+
dnf clean all
98
RUN ln -sf /usr/bin/python3.12 /usr/bin/python
10-
ENV LD_LIBRARY_PATH=/usr/local/cuda-12.6/compat:$LD_LIBRARY_PATH
11-
12-
FROM ${FLAVOR}-base as lightspeed-core-rag-builder
13-
ARG FLAVOR
9+
ENV LD_LIBRARY_PATH=/usr/local/cuda-12/compat:$LD_LIBRARY_PATH
1410

15-
USER 0
11+
# Install asciidoctor
1612
RUN dnf install -y rubygems && \
1713
dnf clean all && \
1814
gem install asciidoctor
15+
# Install uv package manager
16+
RUN pip3.12 install uv==0.7.20
1917

2018
WORKDIR /rag-content
21-
ENV EMBEDDING_MODEL=sentence-transformers/all-mpnet-base-v2
2219

23-
COPY . /rag-content
24-
RUN make install-global
20+
COPY Makefile pyproject.toml uv.lock README.md ./
21+
COPY src ./src
22+
COPY tests ./tests
23+
COPY scripts ./scripts
24+
25+
# Configure UV environment variables for optimal performance
26+
# Pytorch backend - cpu. `uv` contains convenient way to specify the backend.
27+
ENV UV_COMPILE_BYTECODE=0 \
28+
UV_PYTHON_DOWNLOADS=0
29+
30+
# Remove pytorch-cpu dependency from pyproject.toml
31+
RUN uv venv && uv pip install tomlkit
32+
RUN uv run python ./scripts/remove_pytorch_cpu_pyproject.py
2533

26-
# Test torch
27-
RUN if [[ $(echo $LD_LIBRARY_PATH) == *"/usr/local/cuda-12.6/compat"* ]]; then \
28-
python -c "import torch; print(torch.version.cuda); print(torch.cuda.is_available());"; \
29-
fi
34+
# Update uv.lock file and install dependencies
35+
RUN uv lock && uv sync --locked --no-install-project
3036

31-
# # Download embeddings model
37+
# Then, add the rest of the project source code and install it
38+
# Installing separately from its dependencies allows optimal layer caching
39+
RUN uv sync --locked
40+
41+
# Add executables from .venv to system PATH
42+
ENV PATH="/rag-content/.venv/bin:$PATH"
43+
44+
# Download embeddings model
45+
ENV EMBEDDING_MODEL=sentence-transformers/all-mpnet-base-v2
3246
RUN python ./scripts/download_embeddings_model.py \
33-
-l ./embeddings_model \
34-
-r ${EMBEDDING_MODEL}
47+
-l ./embeddings_model \
48+
-r ${EMBEDDING_MODEL}
49+
50+
# Reset the entrypoint.
51+
ENTRYPOINT []
3552

3653
LABEL description="Contains embedding model and dependencies needed to generate a vector database"

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ dependencies = [
4646
"llama-stack-client==0.2.16",
4747
"aiosqlite==0.21.0",
4848
"sqlite-vec==0.1.6",
49+
"tomlkit",
4950
]
5051
requires-python = "==3.12.*"
5152
dynamic = ["license", "readme"]
@@ -57,9 +58,7 @@ name = "pytorch-cpu"
5758
url = "https://download.pytorch.org/whl/cpu"
5859
explicit = true
5960
[tool.uv.sources]
60-
torch = [{ index = "pytorch-cpu" }]
6161
torchvision = [{ index = "pytorch-cpu" }]
62-
llama-stack = { git = "https://github.com/meta-llama/llama-stack.git", rev = "20c319795259f097101917d7304e63aeeeb21c5c" }
6362

6463
[dependency-groups]
6564
dev = [
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
Removes the pytorch-cpu dependency from the pyproject.toml file.
3+
4+
This script removes the pytorch-cpu dependency from the pyproject.toml file.
5+
It is used to create a container image with GPU CUDA backend.
6+
7+
Usage:
8+
python remove_pytorch_cpu_pyproject.py
9+
10+
The script will remove the 'tool.uv.index' and 'tool.uv.sources' sections
11+
from the pyproject.toml file in the current directory.
12+
"""
13+
14+
from tomlkit import parse, dumps
15+
from pathlib import Path
16+
17+
18+
def remove_sections(file_path: str, sections_to_remove: list[str]) -> None:
19+
"""
20+
Remove specified sections from a TOML file.
21+
22+
Args:
23+
file_path (str): Path to the TOML file to modify
24+
sections_to_remove (list[str]): List of section paths to remove,
25+
using dot notation (e.g., "tool.uv.index")
26+
27+
The function parses the TOML file, removes the specified sections,
28+
and writes the modified content back to the file.
29+
"""
30+
path = Path(file_path)
31+
content = path.read_text(encoding="utf-8")
32+
doc = parse(content)
33+
34+
for section in sections_to_remove:
35+
keys = section.split(".")
36+
current = doc
37+
for key in keys[:-1]:
38+
if key not in current:
39+
break
40+
current = current[key] # type: ignore
41+
else:
42+
current.pop(keys[-1], None)
43+
44+
path.write_text(dumps(doc), encoding="utf-8")
45+
46+
47+
if __name__ == "__main__":
48+
file_path = "pyproject.toml"
49+
print(f"pyproject file path: {file_path}")
50+
sections = ["tool.uv.index", "tool.uv.sources"]
51+
remove_sections(file_path, sections)

0 commit comments

Comments
 (0)