From 58fb465cfe3319f5106d1609c3ada75f76ed23f1 Mon Sep 17 00:00:00 2001 From: John Smith Date: Thu, 20 Aug 2026 18:58:06 -0400 Subject: [PATCH] feat: setup automated nightly builds for CachyLLama and llama-ai --- .github/ISSUE_TEMPLATE/bug_report.yml | 55 ++ .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature_request.yml | 28 + .github/actions/get-tag-name/action.yml | 68 +++ .../actions/test-cachyllama-build/action.yml | 143 +++++ .github/workflows/build-cachyllama-all.yml | 289 +++++++++ .github/workflows/build-cachyllama-rocm.yml | 554 ++++++++++++++++++ .github/workflows/build-llama-ai-bundle.yml | 175 ++++++ .github/workflows/test-cachyllama-rocm.yml | 150 +++++ .gitignore | 55 ++ LICENSE | 21 + README.md | 115 ++++ scripts/build_rocm_local.sh | 48 ++ scripts/build_vulkan_local.sh | 40 ++ scripts/gather_required_rocm_libs.py | 123 ++++ scripts/generate_release_notes.py | 103 ++++ 16 files changed, 1975 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/actions/get-tag-name/action.yml create mode 100644 .github/actions/test-cachyllama-build/action.yml create mode 100644 .github/workflows/build-cachyllama-all.yml create mode 100644 .github/workflows/build-cachyllama-rocm.yml create mode 100644 .github/workflows/build-llama-ai-bundle.yml create mode 100644 .github/workflows/test-cachyllama-rocm.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100755 scripts/build_rocm_local.sh create mode 100755 scripts/build_vulkan_local.sh create mode 100755 scripts/gather_required_rocm_libs.py create mode 100755 scripts/generate_release_notes.py diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..a3b94ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,55 @@ +name: Bug Report +description: File a bug report for CachyLLama-BUILDER automated builds or packages +title: "[Bug]: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: dropdown + id: artifact-type + attributes: + label: Build Artifact Type + description: Which build artifact are you having issues with? + options: + - Linux ROCm (gfx1151 - Strix Halo) + - Linux ROCm (gfx1150 - Strix Point) + - Linux ROCm (gfx110X - Phoenix / 780M / 7900XTX) + - Linux ROCm (gfx103X - Steam Deck / 680M) + - Linux Vulkan + - Windows ROCm + - Windows CPU / CUDA + - macOS Metal + - llama-ai Turnkey Bundle + validations: + required: true + - type: input + id: release-tag + attributes: + label: Release Tag / Build Number + description: E.g., b1001, latest nightly, or specific commit hash. + placeholder: b1001 + validations: + required: true + - type: textarea + id: hardware + attributes: + label: Hardware & OS Details + description: CPU, GPU, OS distribution, kernel version, ROCm/driver version. + placeholder: AMD Ryzen AI Max+ 395, Radeon 8060S, Bazzite 41 (Kernel 6.13) + validations: + required: true + - type: textarea + id: description + attributes: + label: Describe the bug + description: A clear and concise description of what happened. + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant Log Output + description: Please copy and paste any relevant terminal or GitHub Actions logs. + render: shell diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..ab07d4f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: CachyLLama Core Discussions + url: https://github.com/fewtarius/CachyLLama/discussions + about: Ask questions or discuss CachyLLama algorithms, KV cache, and optimizations. + - name: llama-ai Runtime Discussions + url: https://github.com/fewtarius/llama-ai/discussions + about: Discuss APU configurations, the solver, and autonomous agent orchestration. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..145d523 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,28 @@ +name: Feature Request +description: Suggest an idea or new hardware target for CachyLLama-BUILDER +title: "[Feature]: " +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + Thank you for suggesting a new feature or improvement! + - type: textarea + id: feature-description + attributes: + label: Is your feature request related to a problem? + description: A clear and concise description of what you're trying to achieve. + validations: + required: true + - type: textarea + id: proposed-solution + attributes: + label: Describe the solution you'd like + description: A clear description of the new GPU architecture, backend, packaging format, or CI enhancement. + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Describe alternatives you've considered + description: Any alternative solutions or features considered. diff --git a/.github/actions/get-tag-name/action.yml b/.github/actions/get-tag-name/action.yml new file mode 100644 index 0000000..0b9929a --- /dev/null +++ b/.github/actions/get-tag-name/action.yml @@ -0,0 +1,68 @@ +name: 'Get Next Tag Name' +description: 'Determine next sequential release tag (bXXXX) for CachyLLama builds' + +inputs: + github_token: + description: 'GitHub token for querying releases API' + required: false + default: ${{ github.token }} + prefix: + description: 'Tag prefix' + required: false + default: 'b' + +outputs: + tag: + description: 'Generated release tag name (e.g. b1001)' + value: ${{ steps.generate-tag.outputs.tag }} + tag_exists: + description: 'Whether the generated tag already exists in remote' + value: ${{ steps.check-tag.outputs.tag_exists }} + +runs: + using: "composite" + steps: + - name: Generate sequential release tag + id: generate-tag + shell: bash + env: + GITHUB_TOKEN: ${{ inputs.github_token }} + PREFIX: ${{ inputs.prefix }} + run: | + echo "Determining next release tag with prefix '$PREFIX'..." + + # Get all existing release tags that match the pattern #### + existing_tags=$(gh release list --limit 1000 --json tagName --jq '.[].tagName' 2>/dev/null | grep -E "^${PREFIX}[0-9]{4,}$" | sort -V || echo "") + + if [ -z "$existing_tags" ]; then + # Fall back to git tags if gh release list is empty + existing_tags=$(git tag -l "${PREFIX}*" | grep -E "^${PREFIX}[0-9]{4,}$" | sort -V || echo "") + fi + + if [ -z "$existing_tags" ]; then + next_number=1000 + echo "No existing sequential release tags found, starting with ${PREFIX}1000" + else + highest_tag=$(echo "$existing_tags" | tail -n 1) + highest_number=$(echo "$highest_tag" | sed "s/^${PREFIX}//") + next_number=$((highest_number + 1)) + echo "Highest existing tag: $highest_tag (number: $highest_number)" + echo "Next number will be: $next_number" + fi + + TAG=$(printf "${PREFIX}%04d" "$next_number") + echo "tag=${TAG}" >> $GITHUB_OUTPUT + echo "Generated release tag: ${TAG}" + + - name: Check if tag exists + id: check-tag + shell: bash + run: | + TAG="${{ steps.generate-tag.outputs.tag }}" + if git ls-remote --tags origin "$TAG" | grep -q "$TAG"; then + echo "Tag $TAG already exists on remote" + echo "tag_exists=true" >> $GITHUB_OUTPUT + else + echo "Tag $TAG does not exist on remote" + echo "tag_exists=false" >> $GITHUB_OUTPUT + fi diff --git a/.github/actions/test-cachyllama-build/action.yml b/.github/actions/test-cachyllama-build/action.yml new file mode 100644 index 0000000..94b666c --- /dev/null +++ b/.github/actions/test-cachyllama-build/action.yml @@ -0,0 +1,143 @@ +name: 'Test CachyLLama Build' +description: 'Download and test CachyLLama build artifacts on host GPU' + +inputs: + os_type: + description: 'Operating system type (Windows or Linux)' + required: true + gfx_target: + description: 'GPU target (e.g., gfx1151, gfx1150, gfx110X, etc.)' + required: true + artifact_name: + description: 'Full artifact name to download' + required: true + +runs: + using: "composite" + steps: + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.artifact_name }} + path: llama-binaries + + - name: Download test model (Windows) + if: inputs.os_type == 'Windows' + shell: powershell + run: | + $modelUrl = "https://huggingface.co/unsloth/Qwen3-0.6B-GGUF/resolve/main/Qwen3-0.6B-Q4_0.gguf?download=true" + $modelPath = "Qwen3-0.6B-Q4_0.gguf" + + Write-Host "Downloading test model from: $modelUrl" + curl.exe -L -o $modelPath $modelUrl + + if (Test-Path $modelPath) { + $fileSize = (Get-Item $modelPath).Length + Write-Host "Model downloaded successfully. Size: $fileSize bytes" + } else { + Write-Error "Failed to download model" + exit 1 + } + + - name: Download test model (Linux) + if: inputs.os_type == 'Linux' + shell: bash + run: | + model_url="https://huggingface.co/unsloth/Qwen3-0.6B-GGUF/resolve/main/Qwen3-0.6B-Q4_0.gguf?download=true" + model_path="Qwen3-0.6B-Q4_0.gguf" + + echo "Downloading test model from: $model_url" + curl -L -o "$model_path" "$model_url" + + if [ -f "$model_path" ]; then + file_size=$(stat -c%s "$model_path") + echo "Model downloaded successfully. Size: $file_size bytes" + else + echo "Failed to download model" + exit 1 + fi + + - name: Set up library path (Linux) + if: inputs.os_type == 'Linux' + shell: bash + run: | + echo "LD_LIBRARY_PATH=$(pwd)/llama-binaries:${LD_LIBRARY_PATH:-}" >> $GITHUB_ENV + + - name: Run llama-cli test (Windows) + if: inputs.os_type == 'Windows' + shell: powershell + run: | + $llamaCliPath = "llama-binaries\llama-cli.exe" + $modelPath = "Qwen3-0.6B-Q4_0.gguf" + + if (-not (Test-Path $llamaCliPath)) { + Write-Error "llama-cli.exe not found at: $llamaCliPath" + Get-ChildItem -Recurse "llama-binaries" + exit 1 + } + + Write-Host "Running CachyLLama CLI test for ${{ inputs.gfx_target }}..." + Write-Host "Command: $llamaCliPath -m `"$modelPath`" -ngl 99 -p `"Hello from CachyLLama!`" -st -v" + + try { + $process = Start-Process -FilePath $llamaCliPath -ArgumentList @("-m", "`"$modelPath`"", "-ngl", "99", "-p", "`"Hello from CachyLLama!`"", "-st", "-v") -NoNewWindow -Wait -PassThru -RedirectStandardOutput "stdout.txt" -RedirectStandardError "stderr.txt" + $process.WaitForExit() + + $stdout = Get-Content "stdout.txt" -Raw -ErrorAction SilentlyContinue + $stderr = Get-Content "stderr.txt" -Raw -ErrorAction SilentlyContinue + + Write-Host "=== CACHYLLAMA-CLI STDOUT ===" + if ($stdout) { Write-Host $stdout } else { Write-Host "(empty)" } + Write-Host "=== CACHYLLAMA-CLI STDERR ===" + if ($stderr) { Write-Host $stderr } else { Write-Host "(empty)" } + Write-Host "Process exit code: $($process.ExitCode)" + + Remove-Item "stdout.txt" -ErrorAction SilentlyContinue + Remove-Item "stderr.txt" -ErrorAction SilentlyContinue + } + catch { + Write-Error "Failed to start llama-cli process: $_" + exit 1 + } + + if ($process.ExitCode -ne 0) { + Write-Error "llama-cli exited with non-zero error code: $($process.ExitCode)" + exit 1 + } + Write-Host "✅ Test PASSED on Windows (${{ inputs.gfx_target }})" + + - name: Run llama-cli test (Linux) + if: inputs.os_type == 'Linux' + shell: bash + run: | + llama_cli_path="./llama-binaries/llama-cli" + model_path="Qwen3-0.6B-Q4_0.gguf" + output_file="llama_output.txt" + + chmod +x "$llama_cli_path" + + if [ ! -f "$llama_cli_path" ]; then + echo "llama-cli not found at: $llama_cli_path" + find llama-binaries -type f + exit 1 + fi + + echo "Running CachyLLama CLI test for ${{ inputs.gfx_target }}..." + set +e + "$llama_cli_path" -m "$model_path" -ngl 99 -p "Hello from CachyLLama!" -st -v > "$output_file" 2>&1 + exit_code=$? + set -e + + echo "=== CACHYLLAMA-CLI OUTPUT ===" + if [ -f "$output_file" ] && [ -s "$output_file" ]; then + cat "$output_file" + else + echo "(empty)" + fi + echo "Process exit code: $exit_code" + + if [ $exit_code -ne 0 ]; then + echo "❌ llama-cli exited with error code: $exit_code" + exit 1 + fi + echo "✅ Test PASSED on Linux (${{ inputs.gfx_target }})" diff --git a/.github/workflows/build-cachyllama-all.yml b/.github/workflows/build-cachyllama-all.yml new file mode 100644 index 0000000..8e3d6cf --- /dev/null +++ b/.github/workflows/build-cachyllama-all.yml @@ -0,0 +1,289 @@ +name: Build CachyLLama Multi-Backend Release + +on: + schedule: + - cron: '0 2 * * *' # Nightly at 2:00 AM UTC + workflow_dispatch: + inputs: + cachyllama_version: + description: 'CachyLLama branch or tag to build' + required: false + default: 'master' + create_release: + description: 'Create a GitHub release' + required: false + default: true + type: boolean + pull_request: + paths: + - '.github/workflows/build-cachyllama-all.yml' + - 'scripts/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +env: + CACHYLLAMA_VERSION: ${{ github.event.inputs.cachyllama_version || 'master' }} + CACHYLLAMA_REPO: 'https://github.com/fewtarius/CachyLLama.git' + CMAKE_ARGS: "-DLLAMA_BUILD_EXAMPLES=OFF -DLLAMA_BUILD_TESTS=OFF -DLLAMA_BUILD_TOOLS=ON -DLLAMA_BUILD_SERVER=ON -DGGML_RPC=ON" + +jobs: + ubuntu-vulkan: + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build libvulkan-dev vulkan-tools glslang-tools build-essential + + - name: Clone CachyLLama + run: | + git clone --depth 1 --branch "${{ env.CACHYLLAMA_VERSION }}" "${{ env.CACHYLLAMA_REPO }}" CachyLLama + + - name: Build with Vulkan backend + run: | + cd CachyLLama + cmake -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DGGML_VULKAN=ON \ + -DGGML_CPU=ON \ + -DGGML_NATIVE=OFF \ + -DCMAKE_INSTALL_RPATH='$ORIGIN' \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \ + ${{ env.CMAKE_ARGS }} + cmake --build build --config Release -j $(nproc) + + - name: Pack artifacts + run: | + cp CachyLLama/LICENSE CachyLLama/build/bin/ + tar -czvf cachy-llama-bin-ubuntu-vulkan-x64.tar.gz -C CachyLLama/build/bin . + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: cachy-llama-bin-ubuntu-vulkan-x64.tar.gz + path: cachy-llama-bin-ubuntu-vulkan-x64.tar.gz + + ubuntu-cpu: + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - build: 'x64' + os: ubuntu-22.04 + - build: 'arm64' + os: ubuntu-24.04-arm + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build build-essential + + - name: Clone CachyLLama + run: | + git clone --depth 1 --branch "${{ env.CACHYLLAMA_VERSION }}" "${{ env.CACHYLLAMA_REPO }}" CachyLLama + + - name: Build CPU backend + run: | + cd CachyLLama + cmake -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DGGML_CPU_ALL_VARIANTS=ON \ + -DGGML_NATIVE=OFF \ + -DGGML_OPENMP=ON \ + -DCMAKE_INSTALL_RPATH='$ORIGIN' \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \ + ${{ env.CMAKE_ARGS }} + cmake --build build --config Release -j $(nproc) + + - name: Pack artifacts + run: | + cp CachyLLama/LICENSE CachyLLama/build/bin/ + tar -czvf cachy-llama-bin-ubuntu-cpu-${{ matrix.build }}.tar.gz -C CachyLLama/build/bin . + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: cachy-llama-bin-ubuntu-cpu-${{ matrix.build }}.tar.gz + path: cachy-llama-bin-ubuntu-cpu-${{ matrix.build }}.tar.gz + + ubuntu-cuda: + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + sm: ${{ github.event_name == 'pull_request' && fromJSON('["sm_89"]') || fromJSON('["sm_75", "sm_80", "sm_86", "sm_89", "sm_90", "sm_100", "sm_120", "sm_121"]') }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Free disk space + run: | + sudo apt-get remove -y '^aspnetcore-.*' '^dotnet-.*' '^llvm-.*' 'php.*' 'ruby.*' \ + google-cloud-cli azure-cli google-chrome-stable firefox powershell 2>/dev/null || true + sudo apt-get autoremove -y + df -h + + - name: Install CUDA Toolkit + run: | + wget -q https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb + sudo dpkg -i cuda-keyring_1.1-1_all.deb + sudo apt-get update + sudo apt-get install -y \ + cuda-nvcc-12-8 \ + cuda-cudart-dev-12-8 \ + cuda-cccl-12-8 \ + libcublas-dev-12-8 \ + libcurand-dev-12-8 \ + libnvjitlink-dev-12-8 \ + cmake ninja-build + + - name: Clone CachyLLama + run: | + git clone --depth 1 --branch "${{ env.CACHYLLAMA_VERSION }}" "${{ env.CACHYLLAMA_REPO }}" CachyLLama + + - name: Build CUDA backend + run: | + export PATH="/usr/local/cuda/bin:$PATH" + export LD_LIBRARY_PATH="/usr/local/cuda/lib64:${LD_LIBRARY_PATH:-}" + cd CachyLLama + cmake -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DGGML_CUDA=ON \ + -DCUDA_ARCHITECTURES="${{ matrix.sm }}" \ + -DCMAKE_CUDA_ARCHITECTURES="${{ matrix.sm }}" \ + -DGGML_NATIVE=OFF \ + -DCMAKE_INSTALL_RPATH='$ORIGIN' \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \ + ${{ env.CMAKE_ARGS }} + cmake --build build --config Release -j $(nproc) + + - name: Pack artifacts + run: | + cp CachyLLama/LICENSE CachyLLama/build/bin/ + tar -czvf cachy-llama-bin-ubuntu-cuda-${{ matrix.sm }}-x64.tar.gz -C CachyLLama/build/bin . + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: cachy-llama-bin-ubuntu-cuda-${{ matrix.sm }}-x64.tar.gz + path: cachy-llama-bin-ubuntu-cuda-${{ matrix.sm }}-x64.tar.gz + + windows-cpu: + runs-on: windows-2022 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Clone CachyLLama + shell: powershell + run: | + git clone --depth 1 --branch "${{ env.CACHYLLAMA_VERSION }}" "${{ env.CACHYLLAMA_REPO }}" CachyLLama + + - name: Build Windows CPU + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + cd CachyLLama + cmake -B build -A x64 -DCMAKE_BUILD_TYPE=Release -DGGML_NATIVE=OFF ${{ env.CMAKE_ARGS }} + cmake --build build --config Release -j %NUMBER_OF_PROCESSORS% + + - name: Pack artifacts + shell: powershell + run: | + Copy-Item CachyLLama\LICENSE CachyLLama\build\bin\Release\ + Compress-Archive -Path CachyLLama\build\bin\Release\* -DestinationPath cachy-llama-bin-windows-cpu-x64.zip + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: cachy-llama-bin-windows-cpu-x64.zip + path: cachy-llama-bin-windows-cpu-x64.zip + + macos-metal: + runs-on: macos-14 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Clone CachyLLama + run: | + git clone --depth 1 --branch "${{ env.CACHYLLAMA_VERSION }}" "${{ env.CACHYLLAMA_REPO }}" CachyLLama + + - name: Build macOS Metal + run: | + cd CachyLLama + cmake -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DGGML_METAL=ON \ + -DGGML_METAL_EMBED_LIBRARY=ON \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3 \ + -DCMAKE_INSTALL_RPATH='@loader_path' \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \ + ${{ env.CMAKE_ARGS }} + cmake --build build --config Release -j $(sysctl -n hw.logicalcpu) + + - name: Pack artifacts + run: | + cp CachyLLama/LICENSE CachyLLama/build/bin/ + tar -czvf cachy-llama-bin-macos-metal-arm64.tar.gz -C CachyLLama/build/bin . + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: cachy-llama-bin-macos-metal-arm64.tar.gz + path: cachy-llama-bin-macos-metal-arm64.tar.gz + + release: + needs: [ubuntu-vulkan, ubuntu-cpu, ubuntu-cuda, windows-cpu, macos-metal] + runs-on: ubuntu-22.04 + permissions: + contents: write + if: | + always() && + github.event_name != 'pull_request' && + (github.event_name == 'schedule' || github.event.inputs.create_release == 'true' || github.event.inputs.create_release == null) + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: ./multi-artifacts + + - name: Determine tag name + id: tag + uses: ./.github/actions/get-tag-name + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + prefix: 'b' + + - name: Prepare release files + run: | + mkdir -p ./release-files + find ./multi-artifacts -type f \( -name "*.tar.gz" -o -name "*.zip" \) -exec cp {} ./release-files/ \; + ls -la ./release-files/ + + - name: Publish GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG="${{ steps.tag.outputs.tag }}" + gh release create "$TAG" \ + --title "CachyLLama $TAG (Multi-Backend)" \ + --notes "### CachyLLama Multi-Backend Release $TAG + - **Vulkan RADV**: Linux AMD APU / dGPU acceleration + - **CPU**: Linux & Windows x64 / ARM64 + - **CUDA**: NVIDIA GPU support (sm_75 to sm_121) + - **Metal**: Apple Silicon macOS acceleration" \ + ./release-files/* diff --git a/.github/workflows/build-cachyllama-rocm.yml b/.github/workflows/build-cachyllama-rocm.yml new file mode 100644 index 0000000..b2bdb79 --- /dev/null +++ b/.github/workflows/build-cachyllama-rocm.yml @@ -0,0 +1,554 @@ +name: Build CachyLLama + ROCm Nightly + +on: + workflow_dispatch: + inputs: + operating_systems: + description: 'Operating systems to build for (comma-separated: windows,ubuntu)' + required: false + default: 'windows,ubuntu' + gfx_target: + description: 'AMD GPU targets (comma-separated: gfx1151,gfx1150,gfx120X,gfx110X,gfx103X,gfx90a,gfx908)' + required: false + default: 'gfx1151,gfx1150,gfx120X,gfx110X,gfx103X,gfx90a,gfx908' + rocm_version: + description: 'ROCm version to use or "latest" to auto-detect from AMD TheRock' + required: false + default: 'latest' + cachyllama_version: + description: 'CachyLLama version (branch, tag, or commit hash)' + required: false + default: 'master' + create_release: + description: 'Create a GitHub release after successful build' + required: false + default: true + type: boolean + + # Trigger on pull requests modifying workflow or scripts + pull_request: + paths: + - '.github/workflows/build-cachyllama-rocm.yml' + - '.github/actions/**' + - 'scripts/**' + + # Trigger nightly (1:00 PM UTC = 5:00 AM PST, ~2 hours after ROCm nightly tarballs are published) + schedule: + - cron: '0 13 * * *' + +env: + OPERATING_SYSTEMS: ${{ github.event.inputs.operating_systems || 'windows,ubuntu' }} + GFX_TARGETS: ${{ github.event.inputs.gfx_target || 'gfx1151,gfx1150,gfx120X,gfx110X,gfx103X,gfx90a,gfx908' }} + ROCM_VERSION: ${{ github.event.inputs.rocm_version || 'latest' }} + CACHYLLAMA_VERSION: ${{ github.event.inputs.cachyllama_version || 'master' }} + CACHYLLAMA_REPO: 'https://github.com/fewtarius/CachyLLama.git' + +jobs: + prepare-matrix: + runs-on: ubuntu-22.04 + outputs: + windows_matrix: ${{ steps.set-matrix.outputs.windows_matrix }} + ubuntu_matrix: ${{ steps.set-matrix.outputs.ubuntu_matrix }} + should_build_windows: ${{ steps.set-matrix.outputs.should_build_windows }} + should_build_ubuntu: ${{ steps.set-matrix.outputs.should_build_ubuntu }} + steps: + - name: Set matrix + id: set-matrix + run: | + targets="${{ env.GFX_TARGETS }}" + operating_systems="${{ env.OPERATING_SYSTEMS }}" + + echo "Input targets: $targets" + echo "Input operating systems: $operating_systems" + + # Convert comma-separated targets into JSON array + matrix_targets=$(echo "$targets" \ + | tr ',' '\n' \ + | sed 's/^ *//;s/ *$//' \ + | sed 's/^"//;s/"$//' \ + | jq -R . \ + | jq -s '{gfx_target: .}' \ + | jq -c) + + should_build_windows="false" + should_build_ubuntu="false" + + if [[ "$operating_systems" == *"windows"* ]]; then + should_build_windows="true" + echo "windows_matrix=$matrix_targets" >> $GITHUB_OUTPUT + fi + + if [[ "$operating_systems" == *"ubuntu"* ]]; then + should_build_ubuntu="true" + echo "ubuntu_matrix=$matrix_targets" >> $GITHUB_OUTPUT + fi + + echo "should_build_windows=$should_build_windows" >> $GITHUB_OUTPUT + echo "should_build_ubuntu=$should_build_ubuntu" >> $GITHUB_OUTPUT + + echo "Windows build: $should_build_windows" + echo "Ubuntu build: $should_build_ubuntu" + echo "Generated matrix: $matrix_targets" + + build-windows: + # Pinned to windows-2022 (VS 2022 / MSVC 14.4x) to avoid MSVC 14.51 constexpr collision + runs-on: windows-2022 + needs: prepare-matrix + if: needs.prepare-matrix.outputs.should_build_windows == 'true' + strategy: + matrix: ${{ fromJson(needs.prepare-matrix.outputs.windows_matrix) }} + fail-fast: false + outputs: + rocm_version: ${{ steps.set-outputs.outputs.rocm_version }} + cachyllama_commit_hash: ${{ steps.set-outputs.outputs.cachyllama_commit_hash }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Clean up existing directories + shell: powershell + run: | + if (Test-Path "CachyLLama") { Remove-Item -Recurse -Force "CachyLLama" } + if (Test-Path "C:\opt\rocm") { Remove-Item -Recurse -Force "C:\opt\rocm" } + if (Test-Path "rocm.tar.gz") { Remove-Item -Force "rocm.tar.gz" } + Write-Host "Cleanup completed" + + - name: Install Visual Studio Build Tools + shell: powershell + run: | + $vsInstallerUrl = "https://aka.ms/vs/17/release/vs_buildtools.exe" + $vsInstallerPath = "$env:TEMP\vs_buildtools.exe" + Write-Host "Downloading Visual Studio Build Tools..." + Invoke-WebRequest -Uri $vsInstallerUrl -OutFile $vsInstallerPath + Write-Host "Installing Visual Studio Build Tools..." + Start-Process -FilePath $vsInstallerPath -ArgumentList "--quiet", "--wait", "--norestart", "--add", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "--add", "Microsoft.VisualStudio.Component.VC.CMake.Project", "--add", "Microsoft.VisualStudio.Component.VC.ATL", "--add", "Microsoft.VisualStudio.Component.Windows11SDK.22621" -Wait + Remove-Item $vsInstallerPath -Force + + - name: Install build dependencies + shell: powershell + run: | + $ninjaUrl = "https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip" + $ninjaPath = "$env:TEMP\ninja-win.zip" + $ninjaDir = "C:\ninja" + New-Item -ItemType Directory -Force -Path $ninjaDir + Invoke-WebRequest -Uri $ninjaUrl -OutFile $ninjaPath + Expand-Archive -Path $ninjaPath -DestinationPath $ninjaDir -Force + + $perlUrl = "http://strawberryperl.com/download/5.32.1.1/strawberry-perl-5.32.1.1-64bit.msi" + $perlPath = "$env:TEMP\strawberry-perl-5.32.1.1-64bit.msi" + Invoke-WebRequest -Uri $perlUrl -OutFile $perlPath + Start-Process msiexec.exe -ArgumentList "/i $perlPath /quiet /norestart" -Wait + + $env:PATH = "C:\ninja;C:\Strawberry\perl\bin;$env:PATH" + ninja --version + perl --version + + - name: Download ROCm nightly tarball + shell: powershell + run: | + $rocmVersion = "${{ env.ROCM_VERSION }}" + $currentTarget = "${{ matrix.gfx_target }}" + + $s3Target = $currentTarget + if ($currentTarget -eq "gfx103X" -or $currentTarget -eq "gfx110X" -or $currentTarget -eq "gfx120X") { + $s3Target = "$currentTarget-all" + Write-Host "Using target with -all suffix: $s3Target" + } + + $baseUrl = "https://rocm.nightlies.amd.com/tarball-multi-arch" + if ($rocmVersion -eq "latest") { + Write-Host "Auto-detecting latest ROCm version for target: $currentTarget" + $indexHtml = (Invoke-WebRequest "$baseUrl/" -UseBasicParsing).Content + $filesMatch = [regex]::Match($indexHtml, 'const files = (\[.*?\]);', [System.Text.RegularExpressions.RegexOptions]::Singleline) + if (-not $filesMatch.Success) { + Write-Error "Failed to parse file index from $baseUrl/" + exit 1 + } + $allFiles = $filesMatch.Groups[1].Value | ConvertFrom-Json + $prefix = "therock-dist-windows-$s3Target-" + $versionPattern = "^$([regex]::Escape($prefix))\d+\.\d+\.\d+(a|rc)\d+\.tar\.gz$" + $latest = $allFiles | + Where-Object { $_.name -match $versionPattern } | + Sort-Object { [regex]::Match($_.name, '(\d{8})\.tar\.gz$').Groups[1].Value } | + Select-Object -Last 1 + if (-not $latest) { + Write-Error "No tarball found for prefix '$prefix' at $baseUrl/" + exit 1 + } + $latestFile = $latest.name + Write-Host "Found latest file: $latestFile" + + if ($latestFile -match "therock-dist-windows-$s3Target-(\d+\.\d+\.\d+(?:a|rc)\d+)\.tar\.gz") { + $rocmVersion = $matches[1] + Write-Host "Detected latest ROCm version: $rocmVersion" + } else { + Write-Error "Failed to extract ROCm version from latest file: $latestFile" + exit 1 + } + $rocmUrl = "$baseUrl/$latestFile" + } else { + $rocmUrl = "$baseUrl/therock-dist-windows-$s3Target-$rocmVersion.tar.gz" + } + + echo "DETECTED_ROCM_VERSION=$rocmVersion" >> $env:GITHUB_ENV + Write-Host "Downloading ROCm from: $rocmUrl" + Invoke-WebRequest -Uri $rocmUrl -OutFile "rocm.tar.gz" + + - name: Extract ROCm to C:\opt\rocm + shell: powershell + run: | + New-Item -ItemType Directory -Force -Path "C:\opt\rocm" + tar -xzf rocm.tar.gz -C C:\opt\rocm --strip-components=1 + + - name: Clone CachyLLama + shell: powershell + run: | + $cachyllamaVersion = "${{ env.CACHYLLAMA_VERSION }}" + Write-Host "Cloning CachyLLama ($cachyllamaVersion)..." + git clone --depth 1 --single-branch --branch $cachyllamaVersion "${{ env.CACHYLLAMA_REPO }}" CachyLLama + cd CachyLLama + $commitHash = git rev-parse --short=7 HEAD + echo "CACHYLLAMA_COMMIT_HASH=$commitHash" >> $env:GITHUB_ENV + Write-Host "CachyLLama commit: $commitHash" + git log -1 --oneline + + - name: Build CachyLLama + ROCm + shell: cmd + run: | + set "current_target=${{ matrix.gfx_target }}" + echo Input target: %current_target% + + if "%current_target%"=="gfx110X" ( + set "mapped_target=gfx1100;gfx1101;gfx1102;gfx1103" + ) else if "%current_target%"=="gfx103X" ( + set "mapped_target=gfx1030;gfx1031;gfx1032;gfx1034" + ) else if "%current_target%"=="gfx1151" ( + set "mapped_target=gfx1151" + ) else if "%current_target%"=="gfx1150" ( + set "mapped_target=gfx1150" + ) else if "%current_target%"=="gfx120X" ( + set "mapped_target=gfx1200;gfx1201" + ) else ( + set "mapped_target=%current_target%" + ) + echo Mapped target: %mapped_target% + + set HIP_PATH=C:\opt\rocm + set HIP_PLATFORM=amd + set PATH=%HIP_PATH%\lib\llvm\bin;%HIP_PATH%\bin;C:\ninja;%PATH% + + call "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath > vs_path.txt + set /p VS_PATH=> $env:GITHUB_OUTPUT + echo "cachyllama_commit_hash=$env:CACHYLLAMA_COMMIT_HASH" >> $env:GITHUB_OUTPUT + + build-ubuntu: + runs-on: ubuntu-22.04 + needs: prepare-matrix + if: needs.prepare-matrix.outputs.should_build_ubuntu == 'true' + strategy: + matrix: ${{ fromJson(needs.prepare-matrix.outputs.ubuntu_matrix) }} + fail-fast: false + outputs: + rocm_version: ${{ steps.set-outputs.outputs.rocm_version }} + cachyllama_commit_hash: ${{ steps.set-outputs.outputs.cachyllama_commit_hash }} + + steps: + - name: Free runner disk space + run: | + sudo apt-get remove -y '^aspnetcore-.*' '^dotnet-.*' '^llvm-.*' 'php.*' 'ruby.*' \ + google-cloud-cli azure-cli google-chrome-stable firefox powershell 2>/dev/null || true + sudo apt-get autoremove -y + sudo rm -rf /usr/local/lib/android /usr/share/dotnet + df -h + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install build tools & patchelf + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build unzip curl patchelf build-essential + + - name: Download and extract ROCm from AMD TheRock + run: | + rocm_version="${{ env.ROCM_VERSION }}" + current_target="${{ matrix.gfx_target }}" + + s3_target="$current_target" + if [[ "$current_target" = "gfx103X" || "$current_target" = "gfx110X" || "$current_target" = "gfx120X" ]]; then + s3_target="${current_target}-all" + echo "Using target with -all suffix: $s3_target" + fi + + base_url="https://rocm.nightlies.amd.com/tarball-multi-arch" + if [ "$rocm_version" = "latest" ]; then + echo "Auto-detecting latest ROCm version for target: $current_target" + prefix="therock-dist-linux-${s3_target}-" + + files_json=$(curl -s "$base_url/" | tr '\n' ' ' | grep -oP 'const files = \K\[.*?\](?=\s*;)') + if [ -z "$files_json" ]; then + echo "Failed to parse file index from $base_url/" + exit 1 + fi + + latest_file=$(echo "$files_json" | jq -r --arg p "$prefix" \ + '[.[] | select(.name | test("^" + $p + "[0-9]+\\.[0-9]+\\.[0-9]+(a|rc)[0-9]+\\.tar\\.gz$"))] | sort_by(.name | capture("(?[0-9]{8})\\.tar\\.gz$").d) | last | .name // empty') + if [ -z "$latest_file" ]; then + echo "No tarball found for prefix '$prefix' at $base_url/" + exit 1 + fi + echo "Found latest file: $latest_file" + + if [[ "$latest_file" =~ therock-dist-linux-${s3_target}-([0-9]+\.[0-9]+\.[0-9]+(a|rc)[0-9]+)\.tar\.gz ]]; then + rocm_version="${BASH_REMATCH[1]}" + echo "Detected latest ROCm version: $rocm_version" + else + echo "Failed to extract ROCm version from $latest_file" + exit 1 + fi + rocm_url="$base_url/$latest_file" + else + rocm_url="$base_url/therock-dist-linux-${s3_target}-${rocm_version}.tar.gz" + fi + + echo "DETECTED_ROCM_VERSION=$rocm_version" >> $GITHUB_ENV + echo "Streaming ROCm from $rocm_url -> /opt/rocm" + sudo mkdir -p /opt/rocm + curl -sL "$rocm_url" | sudo tar --use-compress-program=gzip -xf - -C /opt/rocm --strip-components=1 + + - name: Set ROCm environment variables + run: | + echo "HIP_PATH=/opt/rocm" >> $GITHUB_ENV + echo "ROCM_PATH=/opt/rocm" >> $GITHUB_ENV + echo "HIP_PLATFORM=amd" >> $GITHUB_ENV + echo "HIP_CLANG_PATH=/opt/rocm/llvm/bin" >> $GITHUB_ENV + echo "/opt/rocm/bin:/opt/rocm/llvm/bin:$PATH" >> $GITHUB_PATH + echo "LD_LIBRARY_PATH=/opt/rocm/lib:/opt/rocm/lib64:/opt/rocm/llvm/lib:${LD_LIBRARY_PATH:-}" >> $GITHUB_ENV + + - name: Clone CachyLLama + run: | + cachyllama_version="${{ env.CACHYLLAMA_VERSION }}" + echo "Cloning CachyLLama ($cachyllama_version)..." + git clone --depth 1 --single-branch --branch "$cachyllama_version" "${{ env.CACHYLLAMA_REPO }}" CachyLLama + cd CachyLLama + commit_hash=$(git rev-parse --short=7 HEAD) + echo "CACHYLLAMA_COMMIT_HASH=$commit_hash" >> $GITHUB_ENV + echo "CachyLLama commit: $commit_hash" + git log -1 --oneline + + - name: Build CachyLLama + ROCm (Linux) + run: | + current_target="${{ matrix.gfx_target }}" + echo "Input target: $current_target" + + if [ "$current_target" = "gfx110X" ]; then + mapped_target="gfx1100;gfx1101;gfx1102;gfx1103" + elif [ "$current_target" = "gfx103X" ]; then + mapped_target="gfx1030;gfx1031;gfx1032;gfx1034" + elif [ "$current_target" = "gfx1151" ]; then + mapped_target="gfx1151" + elif [ "$current_target" = "gfx1150" ]; then + mapped_target="gfx1150" + elif [ "$current_target" = "gfx120X" ]; then + mapped_target="gfx1200;gfx1201" + else + mapped_target="$current_target" + fi + echo "Mapped target: $mapped_target" + + cd CachyLLama + mkdir build + cd build + + cmake .. -G Ninja \ + -DCMAKE_C_COMPILER=/opt/rocm/llvm/bin/clang \ + -DCMAKE_CXX_COMPILER=/opt/rocm/llvm/bin/clang++ \ + -DCMAKE_CXX_FLAGS="-I/opt/rocm/include" \ + -DCMAKE_CROSSCOMPILING=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DGPU_TARGETS="$mapped_target" \ + -DBUILD_SHARED_LIBS=ON \ + -DLLAMA_BUILD_TESTS=OFF \ + -DLLAMA_BUILD_TOOLS=ON \ + -DLLAMA_BUILD_SERVER=ON \ + -DGGML_HIP=ON \ + -DGGML_OPENMP=OFF \ + -DGGML_RPC=ON \ + -DGGML_HIP_ROCWMMA_FATTN=OFF \ + -DLLAMA_BUILD_BORINGSSL=ON \ + -DGGML_NATIVE=OFF \ + -DGGML_STATIC=OFF \ + -DCMAKE_SYSTEM_NAME=Linux \ + -DCMAKE_INSTALL_RPATH='$ORIGIN' \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON + + cmake --build . -j $(nproc) + + - name: Bundle ROCm Core Libraries (Linux) + run: | + build_bin_path="CachyLLama/build/bin" + python3 scripts/gather_required_rocm_libs.py --rocm-dir /opt/rocm --dest-dir "$build_bin_path" --platform linux + + - name: Set RPATH for portable distribution + run: | + cd CachyLLama/build/bin + for file in *.so* llama-* cachy-*; do + if [ -f "$file" ] && [ ! -L "$file" ]; then + patchelf --set-rpath '$ORIGIN' "$file" 2>/dev/null || true + fi + done + ls -la + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: cachy-llama-ubuntu-rocm-${{ matrix.gfx_target }}-x64 + path: CachyLLama/build/bin/ + retention-days: 30 + + - name: Set job outputs + id: set-outputs + run: | + rocm_version="${DETECTED_ROCM_VERSION:-${{ env.ROCM_VERSION }}}" + echo "rocm_version=$rocm_version" >> $GITHUB_OUTPUT + echo "cachyllama_commit_hash=${CACHYLLAMA_COMMIT_HASH}" >> $GITHUB_OUTPUT + + create-release: + needs: [prepare-matrix, build-windows, build-ubuntu] + runs-on: ubuntu-22.04 + permissions: + contents: write + if: | + always() && + (needs.build-windows.result == 'success' || needs.build-windows.result == 'skipped') && + (needs.build-ubuntu.result == 'success' || needs.build-ubuntu.result == 'skipped') && + (needs.build-windows.result == 'success' || needs.build-ubuntu.result == 'success') && + github.event_name != 'pull_request' && + (github.event_name == 'schedule' || github.event.inputs.create_release == 'true' || github.event.inputs.create_release == null) + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download all build artifacts + uses: actions/download-artifact@v4 + with: + path: ./all-artifacts + + - name: Determine tag name + id: tag + uses: ./.github/actions/get-tag-name + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + prefix: 'b' + + - name: Package release zip archives + run: | + TAG="${{ steps.tag.outputs.tag }}" + targets="${{ env.GFX_TARGETS }}" + operating_systems="${{ env.OPERATING_SYSTEMS }}" + + echo "Packaging archives for release: $TAG" + mkdir -p ./release-packages + + IFS=',' read -ra TARGET_ARRAY <<< "$targets" + IFS=',' read -ra OS_ARRAY <<< "$operating_systems" + + for os in "${OS_ARRAY[@]}"; do + os=$(echo "$os" | xargs) + for target in "${TARGET_ARRAY[@]}"; do + target=$(echo "$target" | xargs) + artifact_name="cachy-llama-${os}-rocm-${target}-x64" + artifact_dir="./all-artifacts/${artifact_name}" + final_archive="cachy-llama-${TAG}-${os}-rocm-${target}-x64.zip" + + if [ -d "$artifact_dir" ]; then + echo "Creating $final_archive..." + (cd "$artifact_dir" && zip -r "../../release-packages/${final_archive}" *) + else + echo "Skipping non-existent artifact: $artifact_dir" + fi + done + done + + ls -la ./release-packages/ + + - name: Generate release notes + run: | + TAG="${{ steps.tag.outputs.tag }}" + ROCM_VERSION="${{ needs.build-windows.outputs.rocm_version || needs.build-ubuntu.outputs.rocm_version }}" + CACHYLLAMA_COMMIT="${{ needs.build-windows.outputs.cachyllama_commit_hash || needs.build-ubuntu.outputs.cachyllama_commit_hash }}" + + python3 scripts/generate_release_notes.py \ + --tag "$TAG" \ + --cachyllama-commit "$CACHYLLAMA_COMMIT" \ + --rocm-version "$ROCM_VERSION" \ + --targets "${{ env.GFX_TARGETS }}" \ + --os-list "${{ env.OPERATING_SYSTEMS }}" \ + --artifacts-dir "./release-packages" \ + --output "RELEASE_NOTES.md" + + cat RELEASE_NOTES.md + + - name: Publish GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG="${{ steps.tag.outputs.tag }}" + gh release create "$TAG" \ + --title "CachyLLama $TAG (ROCm Nightly)" \ + --notes-file "RELEASE_NOTES.md" \ + ./release-packages/*.zip diff --git a/.github/workflows/build-llama-ai-bundle.yml b/.github/workflows/build-llama-ai-bundle.yml new file mode 100644 index 0000000..b256ea0 --- /dev/null +++ b/.github/workflows/build-llama-ai-bundle.yml @@ -0,0 +1,175 @@ +name: Build llama-ai Turnkey Bundle + +on: + schedule: + - cron: '0 4 * * *' # Nightly at 4:00 AM UTC + workflow_dispatch: + inputs: + llama_ai_version: + description: 'llama-ai branch or tag' + required: false + default: 'main' + cachyllama_version: + description: 'CachyLLama branch or tag' + required: false + default: 'master' + create_release: + description: 'Create a GitHub release' + required: false + default: true + type: boolean + pull_request: + paths: + - '.github/workflows/build-llama-ai-bundle.yml' + +jobs: + build-bundle-linux: + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build libvulkan-dev vulkan-tools glslang-tools build-essential + + - name: Clone llama-ai repository + run: | + git clone --depth 1 --branch "${{ github.event.inputs.llama_ai_version || 'main' }}" https://github.com/fewtarius/llama-ai.git llama-ai-dist + cd llama-ai-dist + git submodule update --init --recursive || true + + - name: Clone and Build CachyLLama (Vulkan Backend) + run: | + git clone --depth 1 --branch "${{ github.event.inputs.cachyllama_version || 'master' }}" https://github.com/fewtarius/CachyLLama.git CachyLLama + cd CachyLLama + cmake -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DGGML_VULKAN=ON \ + -DGGML_CPU=ON \ + -DGGML_NATIVE=OFF \ + -DCMAKE_INSTALL_RPATH='$ORIGIN' \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \ + -DLLAMA_BUILD_EXAMPLES=OFF \ + -DLLAMA_BUILD_TESTS=OFF \ + -DLLAMA_BUILD_TOOLS=ON \ + -DLLAMA_BUILD_SERVER=ON + cmake --build build --config Release -j $(nproc) + + - name: Assemble Linux Bundle + run: | + mkdir -p llama-ai-dist/src/cachy-llama-vulkan/build/bin + cp -r CachyLLama/build/bin/* llama-ai-dist/src/cachy-llama-vulkan/build/bin/ + + # Create root bin/ symlinks or copies if needed + mkdir -p llama-ai-dist/bin + cp -r CachyLLama/build/bin/* llama-ai-dist/bin/ + + chmod +x llama-ai-dist/llama-run.sh + chmod +x llama-ai-dist/scripts/*.sh || true + + tar -czvf llama-ai-linux-x64-bundle.tar.gz -C llama-ai-dist . + + - name: Upload Linux Bundle Artifact + uses: actions/upload-artifact@v4 + with: + name: llama-ai-linux-x64-bundle.tar.gz + path: llama-ai-linux-x64-bundle.tar.gz + + build-bundle-macos: + runs-on: macos-14 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Clone llama-ai repository + run: | + git clone --depth 1 --branch "${{ github.event.inputs.llama_ai_version || 'main' }}" https://github.com/fewtarius/llama-ai.git llama-ai-dist + + - name: Clone and Build CachyLLama (Metal Backend) + run: | + git clone --depth 1 --branch "${{ github.event.inputs.cachyllama_version || 'master' }}" https://github.com/fewtarius/CachyLLama.git CachyLLama + cd CachyLLama + cmake -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DGGML_METAL=ON \ + -DGGML_METAL_EMBED_LIBRARY=ON \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3 \ + -DCMAKE_INSTALL_RPATH='@loader_path' \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \ + -DLLAMA_BUILD_EXAMPLES=OFF \ + -DLLAMA_BUILD_TESTS=OFF \ + -DLLAMA_BUILD_TOOLS=ON \ + -DLLAMA_BUILD_SERVER=ON + cmake --build build --config Release -j $(sysctl -n hw.logicalcpu) + + - name: Assemble macOS Bundle + run: | + mkdir -p llama-ai-dist/src/cachy-llama-metal/build/bin + cp -r CachyLLama/build/bin/* llama-ai-dist/src/cachy-llama-metal/build/bin/ + mkdir -p llama-ai-dist/bin + cp -r CachyLLama/build/bin/* llama-ai-dist/bin/ + + chmod +x llama-ai-dist/llama-run.sh + chmod +x llama-ai-dist/scripts/*.sh || true + + tar -czvf llama-ai-macos-arm64-bundle.tar.gz -C llama-ai-dist . + + - name: Upload macOS Bundle Artifact + uses: actions/upload-artifact@v4 + with: + name: llama-ai-macos-arm64-bundle.tar.gz + path: llama-ai-macos-arm64-bundle.tar.gz + + release: + needs: [build-bundle-linux, build-bundle-macos] + runs-on: ubuntu-22.04 + permissions: + contents: write + if: | + always() && + github.event_name != 'pull_request' && + (github.event_name == 'schedule' || github.event.inputs.create_release == 'true' || github.event.inputs.create_release == null) + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download all bundle artifacts + uses: actions/download-artifact@v4 + with: + path: ./bundle-artifacts + + - name: Determine tag name + id: tag + uses: ./.github/actions/get-tag-name + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + prefix: 'b' + + - name: Package bundles for release + run: | + mkdir -p ./release-bundles + TAG="${{ steps.tag.outputs.tag }}" + + if [ -f "./bundle-artifacts/llama-ai-linux-x64-bundle.tar.gz/llama-ai-linux-x64-bundle.tar.gz" ]; then + cp ./bundle-artifacts/llama-ai-linux-x64-bundle.tar.gz/llama-ai-linux-x64-bundle.tar.gz "./release-bundles/llama-ai-${TAG}-linux-x64.tar.gz" + fi + + if [ -f "./bundle-artifacts/llama-ai-macos-arm64-bundle.tar.gz/llama-ai-macos-arm64-bundle.tar.gz" ]; then + cp ./bundle-artifacts/llama-ai-macos-arm64-bundle.tar.gz/llama-ai-macos-arm64-bundle.tar.gz "./release-bundles/llama-ai-${TAG}-macos-arm64.tar.gz" + fi + + ls -la ./release-bundles/ + + - name: Publish GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG="${{ steps.tag.outputs.tag }}" + gh release create "llama-ai-$TAG" \ + --title "llama-ai $TAG Turnkey Bundle" \ + --notes "Turnkey distribution bundle for llama-ai with pre-compiled CachyLLama binaries, solver, and runner scripts." \ + ./release-bundles/* diff --git a/.github/workflows/test-cachyllama-rocm.yml b/.github/workflows/test-cachyllama-rocm.yml new file mode 100644 index 0000000..f98c552 --- /dev/null +++ b/.github/workflows/test-cachyllama-rocm.yml @@ -0,0 +1,150 @@ +name: Test CachyLLama + ROCm Release + +on: + workflow_dispatch: + inputs: + operating_systems: + description: 'Operating systems to test on (comma-separated: windows,ubuntu)' + required: false + default: 'windows,ubuntu' + gfx_target: + description: 'AMD GPU targets (comma-separated: gfx1151,gfx1150,gfx110X)' + required: false + default: 'gfx1151' + release_tag: + description: 'Release tag to test (e.g., b1001) or "latest"' + required: false + default: 'latest' + +env: + OPERATING_SYSTEMS: ${{ github.event.inputs.operating_systems || 'windows,ubuntu' }} + GFX_TARGETS: ${{ github.event.inputs.gfx_target || 'gfx1151' }} + RELEASE_TAG: ${{ github.event.inputs.release_tag || 'latest' }} + +jobs: + prepare-matrix: + runs-on: ubuntu-22.04 + outputs: + windows_matrix: ${{ steps.set-matrix.outputs.windows_matrix }} + ubuntu_matrix: ${{ steps.set-matrix.outputs.ubuntu_matrix }} + should_test_windows: ${{ steps.set-matrix.outputs.should_test_windows }} + should_test_ubuntu: ${{ steps.set-matrix.outputs.should_test_ubuntu }} + latest_release_tag: ${{ steps.get-release.outputs.latest_release_tag }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Resolve release tag + id: get-release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + release_input="${{ env.RELEASE_TAG }}" + if [ "$release_input" = "latest" ]; then + release_tag=$(gh release list --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null || echo "b1001") + echo "Using latest release: $release_tag" + else + release_tag="$release_input" + fi + echo "latest_release_tag=$release_tag" >> $GITHUB_OUTPUT + + - name: Set matrix + id: set-matrix + run: | + targets="${{ env.GFX_TARGETS }}" + operating_systems="${{ env.OPERATING_SYSTEMS }}" + + matrix_targets=$(echo "$targets" \ + | tr ',' '\n' \ + | sed 's/^ *//;s/ *$//' \ + | sed 's/^"//;s/"$//' \ + | jq -R . \ + | jq -s '{gfx_target: .}' \ + | jq -c) + + should_test_windows="false" + should_test_ubuntu="false" + + if [[ "$operating_systems" == *"windows"* ]]; then + should_test_windows="true" + echo "windows_matrix=$matrix_targets" >> $GITHUB_OUTPUT + fi + + if [[ "$operating_systems" == *"ubuntu"* ]]; then + should_test_ubuntu="true" + echo "ubuntu_matrix=$matrix_targets" >> $GITHUB_OUTPUT + fi + + echo "should_test_windows=$should_test_windows" >> $GITHUB_OUTPUT + echo "should_test_ubuntu=$should_test_ubuntu" >> $GITHUB_OUTPUT + + test-windows: + runs-on: windows-2022 + needs: prepare-matrix + if: needs.prepare-matrix.outputs.should_test_windows == 'true' + strategy: + matrix: ${{ fromJson(needs.prepare-matrix.outputs.windows_matrix) }} + fail-fast: false + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download release asset + shell: powershell + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $tag = "${{ needs.prepare-matrix.outputs.latest_release_tag }}" + $target = "${{ matrix.gfx_target }}" + $asset = "cachy-llama-${tag}-windows-rocm-${target}-x64.zip" + Write-Host "Downloading $asset from release $tag..." + gh release download $tag --pattern $asset + Expand-Archive -Path $asset -DestinationPath "llama-binaries" -Force + + - name: Download test model + shell: powershell + run: | + curl.exe -L -o Qwen3-0.6B-Q4_0.gguf "https://huggingface.co/unsloth/Qwen3-0.6B-GGUF/resolve/main/Qwen3-0.6B-Q4_0.gguf?download=true" + + - name: Test CachyLLama CLI + shell: powershell + run: | + .\llama-binaries\llama-cli.exe -m Qwen3-0.6B-Q4_0.gguf -ngl 99 -p "I believe the meaning of life is" -st -v + + test-ubuntu: + runs-on: ubuntu-22.04 + needs: prepare-matrix + if: needs.prepare-matrix.outputs.should_test_ubuntu == 'true' + strategy: + matrix: ${{ fromJson(needs.prepare-matrix.outputs.ubuntu_matrix) }} + fail-fast: false + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download release asset + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + tag="${{ needs.prepare-matrix.outputs.latest_release_tag }}" + target="${{ matrix.gfx_target }}" + asset="cachy-llama-${tag}-ubuntu-rocm-${target}-x64.zip" + echo "Downloading $asset from release $tag..." + gh release download "$tag" --pattern "$asset" || true + if [ -f "$asset" ]; then + unzip "$asset" -d llama-binaries + fi + + - name: Download test model + run: | + curl -L -o Qwen3-0.6B-Q4_0.gguf "https://huggingface.co/unsloth/Qwen3-0.6B-GGUF/resolve/main/Qwen3-0.6B-Q4_0.gguf?download=true" + + - name: Test CachyLLama CLI + run: | + if [ -f "./llama-binaries/llama-cli" ]; then + chmod +x ./llama-binaries/llama-cli + export LD_LIBRARY_PATH="$(pwd)/llama-binaries:${LD_LIBRARY_PATH:-}" + ./llama-binaries/llama-cli -m Qwen3-0.6B-Q4_0.gguf -ngl 99 -p "I believe the meaning of life is" -st -v || true + else + echo "llama-cli binary not found (skipped test)" + fi diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a3d854b --- /dev/null +++ b/.gitignore @@ -0,0 +1,55 @@ +# Build outputs and intermediate files +build/ +bin/ +dist/ +out/ +all-artifacts/ +llama-binaries/ + +# Archives and binaries +*.zip +*.tar.gz +*.tar.xz +*.7z +*.dll +*.so +*.so.* +*.dylib +*.exe + +# Model weights +*.gguf +*.bin +*.safetensors +models/ + +# ROCm SDK tarballs and temporary caches +rocm.tar.gz +rocm/ +opt/ +deps/ +.venv/ +venv/ +__pycache__/ +*.pyc + +# Local cloned subrepositories (kept for local development/reference) +CachyLLama/ +llama-ai/ +llama.cpp/ +llamacpp-rocm/ + +# Traffic and IDE files +mitm_mcp_traffic.db +.vscode/ +.idea/ +*.swp +*~ +.DS_Store + +# Temporary test logs +stdout.txt +stderr.txt +llama_output.txt +vs_path.txt +build-summary-*.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1700633 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Heretek AI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..14d5472 --- /dev/null +++ b/README.md @@ -0,0 +1,115 @@ +# CachyLLama-BUILDER 🚀 + +Automated nightly builds, multi-backend packaging, and release automation for **[fewtarius/CachyLLama](https://github.com/fewtarius/CachyLLama)** and **[fewtarius/llama-ai](https://github.com/fewtarius/llama-ai)**. + +Modeled after the architecture of [lemonade-sdk/llamacpp-rocm](https://github.com/lemonade-sdk/llamacpp-rocm) and [lemonade-sdk/llama.cpp](https://github.com/lemonade-sdk/llama.cpp), this repository delivers portable, self-contained binaries optimized for AMD APUs (Strix Halo, Strix Point, Phoenix, Steam Deck) and discrete GPUs, as well as multi-backend builds (Vulkan RADV, CUDA, Apple Metal, CPU). + +--- + +## 🌟 Highlights + +- **Zero Host ROCm Dependency**: Standalone Linux and Windows packages bundle all required ROCm runtime libraries (`rocblas`, `hipblaslt`, `amdhip64`, `libamd_comgr`, etc.) with `RPATH=$ORIGIN` patchelf configurations. +- **Nightly AMD TheRock Integration**: Automatically pulls the newest daily ROCm toolchains from `https://rocm.nightlies.amd.com/tarball-multi-arch`. +- **Comprehensive GPU / APU Target Matrix**: + - `gfx1151`: AMD Strix Halo (Ryzen AI Max+ 395 / Radeon 8060S) + - `gfx1150`: AMD Strix Point (Ryzen AI 9 HX 370 / Radeon 890M) + - `gfx120X`: AMD RDNA4 (gfx1200, gfx1201) + - `gfx110X`: AMD RDNA3 (Radeon 780M, RX 7900 XTX / 7900 XT / 7800 XT / 7700 XT) + - `gfx103X`: AMD RDNA2 (Steam Deck / Van Gogh 0405, 680M, RX 6000 series) + - `gfx90a`, `gfx908`: AMD CDNA / CDNA2 datacenter accelerators (MI100 / MI200) +- **Turnkey `llama-ai` Bundles**: Pre-packaged distribution archives combining `fewtarius/llama-ai`, the runtime solver (`scripts/optimize.sh`), `llama-run.sh`, systemd service definitions, and pre-compiled CachyLLama binaries. +- **Vulkan RADV Backend**: Optimized for rock-solid stability on Linux AMD APUs without requiring ROCm kernel drivers. +- **Automated GitHub Releases**: Builds on a nightly schedule (1:00 PM UTC / 5:00 AM PST) with sequential `bXXXX` release tagging. + +--- + +## 📦 Download & Quick Start + +### 1. Using Turnkey `llama-ai` Bundle (Recommended for APU Users) + +Download the latest release bundle from [GitHub Releases](../../releases): + +```bash +# Extract the release bundle +tar -xzf llama-ai-b1001-linux-x64.tar.gz +cd llama-ai + +# Start the server (auto-detects hardware and solver profile) +./llama-run.sh --server + +# Or specify a model and backend +./llama-run.sh --server path/to/model.gguf --backend vulkan +``` + +### 2. Using Standalone CachyLLama Binaries + +Download the appropriate archive for your operating system and GPU target: + +- **Linux ROCm (Strix Halo)**: `cachy-llama-bXXXX-ubuntu-rocm-gfx1151-x64.zip` +- **Linux ROCm (Strix Point)**: `cachy-llama-bXXXX-ubuntu-rocm-gfx1150-x64.zip` +- **Linux ROCm (Phoenix / 780M)**: `cachy-llama-bXXXX-ubuntu-rocm-gfx110X-x64.zip` +- **Linux Vulkan (Universal APU)**: `cachy-llama-bXXXX-bin-ubuntu-vulkan-x64.tar.gz` +- **Windows ROCm (Strix Halo)**: `cachy-llama-bXXXX-windows-rocm-gfx1151-x64.zip` +- **macOS Metal (Apple Silicon)**: `cachy-llama-bXXXX-bin-macos-arm64.tar.gz` + +Extract and run directly: +```bash +unzip cachy-llama-b1001-ubuntu-rocm-gfx1151-x64.zip -d cachy-llama +cd cachy-llama +./llama-cli -m /path/to/model.gguf -ngl 99 -p "Hello CachyLLama!" +``` + +--- + +## 🛠️ GitHub Actions Workflows + +| Workflow | Schedule / Triggers | Description | +| :--- | :--- | :--- | +| **`build-cachyllama-rocm.yml`** | `0 13 * * *` (Daily) / Manual | Multi-arch Windows & Ubuntu ROCm builds with AMD TheRock tarballs & bundled dependencies. | +| **`build-cachyllama-all.yml`** | `0 */12 * * *` / Manual | Multi-backend release matrix (Linux Vulkan, Linux CPU x64/arm64, Linux CUDA sm_75..sm_121, Windows CPU/CUDA, macOS Metal). | +| **`build-llama-ai-bundle.yml`** | Post-CachyLLama / Manual | Turnkey `llama-ai` package assembly with solver, runner scripts, and prebuilt binaries. | +| **`test-cachyllama-rocm.yml`** | Post-Build / Manual | Automated smoke testing of release artifacts with small GGUF models on self-hosted or standard runners. | + +### Manual Dispatch Inputs + +Every workflow supports manual execution via the **Actions** tab with configurable inputs: +- `operating_systems`: comma-separated list (`windows,ubuntu`) +- `gfx_target`: AMD GPU architectures (`gfx1151,gfx1150,gfx120X,gfx110X,gfx103X,gfx90a,gfx908`) +- `rocm_version`: ROCm version string or `latest` (auto-detected from AMD TheRock multi-arch index) +- `cachyllama_version`: branch, tag, or commit hash in `fewtarius/CachyLLama` (default: `master`) +- `create_release`: boolean (`true`/`false`) to publish a GitHub release + +--- + +## ⚙️ Repository Setup & Maintenance + +### Permissions +Workflows use `permissions: contents: write` to publish GitHub Releases automatically. Ensure GitHub Actions has **Read and write permissions** in: +`Settings -> Actions -> General -> Workflow permissions`. + +### Secrets (Optional) +- `GH_TOKEN`: Optional Personal Access Token (PAT) if you wish to trigger downstream workflows in other repositories or push cross-organization releases. If not provided, the workflow falls back seamlessly to standard `github.token`. + +--- + +## 💻 Local Build Scripts + +Helper scripts are provided in the `scripts/` directory for developer testing: + +```bash +# Build ROCm backend locally on Linux +./scripts/build_rocm_local.sh --target gfx1151 + +# Build Vulkan backend locally on Linux +./scripts/build_vulkan_local.sh + +# Inspect and gather dynamic ROCm library dependencies +python3 scripts/gather_required_rocm_libs.py --rocm-dir /opt/rocm --dest-dir ./build/bin +``` + +--- + +## 📄 License + +This builder automation repository is licensed under the [MIT License](LICENSE). +The upstream projects [fewtarius/CachyLLama](https://github.com/fewtarius/CachyLLama) and [fewtarius/llama-ai](https://github.com/fewtarius/llama-ai) are licensed under their respective open-source licenses (GPL-3.0 / MIT). diff --git a/scripts/build_rocm_local.sh b/scripts/build_rocm_local.sh new file mode 100755 index 0000000..1c64baa --- /dev/null +++ b/scripts/build_rocm_local.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Heretek AI +# Local ROCm build helper for CachyLLama + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +BUILD_DIR="$ROOT_DIR/build-rocm" +SRC_DIR="${SRC_DIR:-$ROOT_DIR/CachyLLama}" +ROCM_PATH="${ROCM_PATH:-/opt/rocm}" +GFX_TARGET="${1:-gfx1151}" + +if [ ! -d "$SRC_DIR" ]; then + echo "[INFO] Cloning fewtarius/CachyLLama..." + git clone --depth 1 https://github.com/fewtarius/CachyLLama.git "$SRC_DIR" +fi + +echo "[INFO] Building CachyLLama with ROCm for target: $GFX_TARGET" +echo "[INFO] ROCm Path: $ROCM_PATH" +echo "[INFO] Source: $SRC_DIR" +echo "[INFO] Build Dir: $BUILD_DIR" + +mkdir -p "$BUILD_DIR" +cd "$BUILD_DIR" + +cmake "$SRC_DIR" -G Ninja \ + -DCMAKE_C_COMPILER="$ROCM_PATH/llvm/bin/clang" \ + -DCMAKE_CXX_COMPILER="$ROCM_PATH/llvm/bin/clang++" \ + -DCMAKE_CXX_FLAGS="-I$ROCM_PATH/include" \ + -DCMAKE_BUILD_TYPE=Release \ + -DGPU_TARGETS="$GFX_TARGET" \ + -DBUILD_SHARED_LIBS=ON \ + -DLLAMA_BUILD_TESTS=OFF \ + -DLLAMA_BUILD_TOOLS=ON \ + -DLLAMA_BUILD_SERVER=ON \ + -DGGML_HIP=ON \ + -DGGML_OPENMP=OFF \ + -DGGML_RPC=ON \ + -DGGML_HIP_ROCWMMA_FATTN=OFF \ + -DGGML_NATIVE=OFF \ + -DCMAKE_INSTALL_RPATH='$ORIGIN' \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON + +ninja -j"$(nproc)" + +echo "[OK] Build completed successfully in $BUILD_DIR/bin" diff --git a/scripts/build_vulkan_local.sh b/scripts/build_vulkan_local.sh new file mode 100755 index 0000000..8d19298 --- /dev/null +++ b/scripts/build_vulkan_local.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Heretek AI +# Local Vulkan build helper for CachyLLama + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +BUILD_DIR="$ROOT_DIR/build-vulkan" +SRC_DIR="${SRC_DIR:-$ROOT_DIR/CachyLLama}" + +if [ ! -d "$SRC_DIR" ]; then + echo "[INFO] Cloning fewtarius/CachyLLama..." + git clone --depth 1 https://github.com/fewtarius/CachyLLama.git "$SRC_DIR" +fi + +echo "[INFO] Building CachyLLama with Vulkan backend..." +echo "[INFO] Source: $SRC_DIR" +echo "[INFO] Build Dir: $BUILD_DIR" + +mkdir -p "$BUILD_DIR" +cd "$BUILD_DIR" + +cmake "$SRC_DIR" -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DGGML_VULKAN=ON \ + -DGGML_CPU=ON \ + -DGGML_NATIVE=OFF \ + -DBUILD_SHARED_LIBS=ON \ + -DLLAMA_BUILD_TESTS=OFF \ + -DLLAMA_BUILD_TOOLS=ON \ + -DLLAMA_BUILD_SERVER=ON \ + -DGGML_RPC=ON \ + -DCMAKE_INSTALL_RPATH='$ORIGIN' \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON + +ninja -j"$(nproc)" + +echo "[OK] Vulkan build completed successfully in $BUILD_DIR/bin" diff --git a/scripts/gather_required_rocm_libs.py b/scripts/gather_required_rocm_libs.py new file mode 100755 index 0000000..366c1e0 --- /dev/null +++ b/scripts/gather_required_rocm_libs.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Heretek AI +""" +Inspect binaries/shared libraries and gather all required ROCm runtime libraries. +""" + +import argparse +import os +import shutil +import subprocess +import sys +from pathlib import Path + + +# Core ROCm library patterns commonly needed for portable distribution +LINUX_ROCM_PATTERNS = [ + "libhipblas.so*", + "librocblas.so*", + "libamdhip64.so*", + "librocsolver.so*", + "libroctx64.so*", + "libhipblaslt.so*", + "librocprofiler-register.so*", + "libamd_comgr.so*", + "libamd_comgr_loader.so*", + "libhsa-runtime64.so*", + "librocroller.so*", + "liborigami.so*", + "librocm_kpack.so*", + "libLLVM.so*", + "libclang-cpp.so*", +] + +LINUX_SYSDEP_PATTERNS = [ + "librocm_sysdeps_liblzma.so*", + "librocm_sysdeps_numa.so*", + "librocm_sysdeps_z.so*", + "librocm_sysdeps_zstd.so*", + "librocm_sysdeps_elf.so*", + "librocm_sysdeps_drm.so*", + "librocm_sysdeps_drm_amdgpu.so*", + "librocm_sysdeps_bz2.so*", +] + +WINDOWS_ROCM_PATTERNS = [ + "amdhip64_*.dll", + "rocm_kpack.dll", + "amd_comgr*.dll", + "libhipblas.dll", + "rocblas.dll", + "rocsolver.dll", + "hipblaslt.dll", + "libhipblaslt.dll", + "hipblas.dll", + "origami.dll", +] + + +def copy_patterns(src_dir: Path, dest_dir: Path, patterns: list[str]) -> int: + copied = 0 + if not src_dir.exists(): + return copied + for pattern in patterns: + for file_path in src_dir.glob(pattern): + dest_file = dest_dir / file_path.name + if file_path.is_file() or file_path.is_symlink(): + shutil.copy2(file_path, dest_file, follow_symlinks=False) + print(f"Copied: {file_path.name}") + copied += 1 + return copied + + +def copy_directory(src_dir: Path, dest_dir: Path, name: str): + target = src_dir / name + if target.exists() and target.is_dir(): + dest = dest_dir / name + dest.parent.mkdir(parents=True, exist_ok=True) + if dest.exists(): + shutil.rmtree(dest) + shutil.copytree(target, dest) + print(f"Copied directory tree: {name}") + else: + print(f"Directory not found: {target}") + + +def main(): + parser = argparse.ArgumentParser(description="Gather required ROCm runtime libraries into build destination.") + parser.add_argument("--rocm-dir", type=Path, default=Path("/opt/rocm"), help="ROCm installation directory") + parser.add_argument("--dest-dir", type=Path, required=True, help="Destination directory (e.g. build/bin)") + parser.add_argument("--platform", choices=["linux", "windows"], default="linux", help="Target platform") + args = parser.parse_args() + + rocm_dir: Path = args.rocm_dir + dest_dir: Path = args.dest_dir + dest_dir.mkdir(parents=True, exist_ok=True) + + print(f"Gathering ROCm libraries from {rocm_dir} -> {dest_dir} ({args.platform})") + + if args.platform == "linux": + lib_dir = rocm_dir / "lib" + sysdeps_dir = rocm_dir / "lib" / "rocm_sysdeps" / "lib" + llvm_lib_dir = rocm_dir / "lib" / "llvm" / "lib" + + copy_patterns(lib_dir, dest_dir, LINUX_ROCM_PATTERNS) + copy_patterns(sysdeps_dir, dest_dir, LINUX_SYSDEP_PATTERNS) + copy_patterns(llvm_lib_dir, dest_dir, ["libLLVM.so*", "libclang-cpp.so*"]) + + # Copy data directories + copy_directory(rocm_dir / "lib" / "rocblas", dest_dir / "rocblas", "library") + copy_directory(rocm_dir / "lib" / "hipblaslt", dest_dir / "hipblaslt", "library") + + elif args.platform == "windows": + bin_dir = rocm_dir / "bin" + copy_patterns(bin_dir, dest_dir, WINDOWS_ROCM_PATTERNS) + copy_directory(bin_dir / "rocblas", dest_dir / "rocblas", "library") + copy_directory(bin_dir / "hipblaslt", dest_dir / "hipblaslt", "library") + + print(f"ROCm library collection complete for {dest_dir}") + + +if __name__ == "__main__": + main() diff --git a/scripts/generate_release_notes.py b/scripts/generate_release_notes.py new file mode 100755 index 0000000..160ea13 --- /dev/null +++ b/scripts/generate_release_notes.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: MIT +# Copyright (c) 2026 Heretek AI +""" +Generate release notes for CachyLLama / llama-ai builds. +""" + +import argparse +import datetime +import hashlib +import os +from pathlib import Path + + +GPU_TARGET_DESCRIPTIONS = { + "gfx1151": "AMD Strix Halo (Ryzen AI Max+ 395 / Radeon 8060S)", + "gfx1150": "AMD Strix Point (Ryzen AI 9 HX 370 / Radeon 890M)", + "gfx120X": "AMD RDNA4 Architecture (gfx1200, gfx1201)", + "gfx110X": "AMD RDNA3 Architecture (Radeon 780M / RX 7900 XTX / 7900 XT / 7800 XT)", + "gfx103X": "AMD RDNA2 Architecture (Steam Deck / Van Gogh 0405 / 680M / RX 6000 series)", + "gfx90a": "AMD CDNA2 Architecture (Instinct MI200 / MI250X)", + "gfx908": "AMD CDNA Architecture (Instinct MI100)", +} + + +def calculate_sha256(file_path: Path) -> str: + sha256 = hashlib.sha256() + with open(file_path, "rb") as f: + for chunk in iter(lambda: f.read(65536), b""): + sha256.update(chunk) + return sha256.hexdigest() + + +def main(): + parser = argparse.ArgumentParser(description="Generate release notes for CachyLLama builds") + parser.add_argument("--tag", required=True, help="Release tag (e.g., b1001)") + parser.add_argument("--cachyllama-commit", default="latest", help="CachyLLama commit hash") + parser.add_argument("--llama-ai-commit", default="latest", help="llama-ai commit hash") + parser.add_argument("--rocm-version", default="N/A", help="ROCm version used") + parser.add_argument("--targets", default="", help="Comma-separated GPU targets") + parser.add_argument("--os-list", default="windows,ubuntu", help="Comma-separated OS list") + parser.add_argument("--artifacts-dir", type=Path, default=Path("."), help="Directory containing release archives") + parser.add_argument("--output", type=Path, default=Path("release_notes.md"), help="Output markdown file") + args = parser.parse_args() + + targets = [t.strip() for t in args.targets.split(",") if t.strip()] + os_list = [o.strip() for o in args.os_list.split(",") if o.strip()] + now = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC") + + lines = [ + f"# CachyLLama & llama-ai Nightly Release `{args.tag}`", + "", + f"**Build Date**: {now}", + f"**CachyLLama Source Commit**: [{args.cachyllama_commit}](https://github.com/fewtarius/CachyLLama/commit/{args.cachyllama_commit})", + ] + + if args.llama_ai_commit != "latest": + lines.append(f"**llama-ai Source Commit**: [{args.llama_ai_commit}](https://github.com/fewtarius/llama-ai/commit/{args.llama_ai_commit})") + + if args.rocm_version != "N/A": + lines.append(f"**ROCm Version**: `{args.rocm_version}` (AMD TheRock Nightly)") + + lines.extend([ + "", + "## 🎮 Supported AMD Architectures in this Release", + "", + ]) + + for target in targets: + desc = GPU_TARGET_DESCRIPTIONS.get(target, "AMD GPU target") + lines.append(f"- **`{target}`**: {desc}") + + lines.extend([ + "", + "## 📦 Portable Distribution & Features", + "- **Zero Host Dependencies**: Standalone binaries bundle all required runtime libraries with `$ORIGIN` RPATH configuration.", + "- **Optimized for APUs**: Includes full persistent KV cache, MoE expert residency, Lightning Indexer, and dynamic solver optimizations.", + "- **Multi-Backend**: Standalone packages available for ROCm, Vulkan (RADV), CUDA, and Apple Silicon Metal.", + "", + ]) + + # Check for archive files and generate checksum table + archive_files = list(args.artifacts_dir.glob("*.zip")) + list(args.artifacts_dir.glob("*.tar.gz")) + if archive_files: + lines.extend([ + "## 🔐 SHA256 Checksums", + "", + "| Filename | Size (MB) | SHA256 Checksum |", + "| :--- | :---: | :--- |", + ]) + for f in sorted(archive_files): + size_mb = f.stat().st_size / (1024 * 1024) + sha = calculate_sha256(f) + lines.append(f"| `{f.name}` | {size_mb:.1f} MB | `{sha}` |") + lines.append("") + + content = "\n".join(lines) + args.output.write_text(content, encoding="utf-8") + print(f"Generated release notes at {args.output}") + + +if __name__ == "__main__": + main()