Skip to content

Merge pull request #101 from beehive-lab/refactor/simplify-layerplanner #20

Merge pull request #101 from beehive-lab/refactor/simplify-layerplanner

Merge pull request #101 from beehive-lab/refactor/simplify-layerplanner #20

name: Integration Quarkus-LangChain4j
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
types: [opened, synchronize, reopened]
schedule:
# Run every Saturday at 02:30 UTC to catch dependency breakages
- cron: '30 2 * * 6'
workflow_dispatch:
inputs:
quarkus_langchain4j_version:
description: 'Quarkus LangChain4j version to test against'
required: false
type: string
quarkus_version:
description: 'Quarkus platform version to test against'
required: false
type: string
env:
JAVA_HOME: /opt/jenkins/jdks/graal-23.1.0/jdk-21.0.3
TORNADO_ROOT: ${{ github.workspace }}/GPULlama3.java/external/tornadovm
GRAAL_JARS: /opt/graalJars
QUARKUS_PORT: 8081
jobs:
quarkus-integration-test:
if: github.repository == 'beehive-lab/GPULlama3.java'
runs-on: [self-hosted]
timeout-minutes: 30
strategy:
fail-fast: true
matrix:
backend:
- name: opencl
- name: ptx
steps:
- name: Checkout GPULlama3
uses: actions/checkout@v4
# Step 1: Clone and build TornadoVM
- name: Clone TornadoVM master
run: |
git clone --depth 1 --branch master \
https://github.com/beehive-lab/TornadoVM.git \
$TORNADO_ROOT
- name: Set up Python venv for TornadoVM
run: |
python3 -m venv $TORNADO_ROOT/venv
source $TORNADO_ROOT/venv/bin/activate
python --version
- name: Build TornadoVM
run: |
cd $TORNADO_ROOT
mkdir -p graalJars && cp $GRAAL_JARS/* graalJars/
source venv/bin/activate
echo "=== Building TornadoVM ==="
make BACKEND=${{ matrix.backend.name }}
echo "=== Searching for TornadoVM SDK directory ==="
SDK_DIR=$(find dist -type d -maxdepth 3 -path "*/tornadovm-*-${{ matrix.backend.name }}" | head -n 1)
if [ -z "$SDK_DIR" ]; then
echo "::error::Could not locate TornadoVM SDK directory!"
find dist -maxdepth 5 -type d
exit 1
fi
FULL_SDK="${PWD}/${SDK_DIR}"
echo "Detected TornadoVM SDK: $FULL_SDK"
# Export for current shell session
export TORNADOVM_HOME="$FULL_SDK"
export PATH="$FULL_SDK/bin:$JAVA_HOME/bin:$PATH"
# Save for subsequent steps
echo "TORNADOVM_HOME=$FULL_SDK" >> $GITHUB_ENV
echo "PATH=$PATH" >> $GITHUB_ENV
echo "=== Checking tornado CLI ==="
which tornado || { echo "::error::tornado not in PATH"; exit 1; }
tornado --devices
# Step 2: Build GPULlama3.java
- name: Build GPULlama3.java
run: |
cd ${{ github.workspace }}
echo "Using TORNADOVM_HOME=$TORNADOVM_HOME"
export PATH="$TORNADOVM_HOME/bin:$JAVA_HOME/bin:$PATH"
tornado --version
# Append SNAPSHOT to GPULlama3 version
GPULLAMA3_VERSION=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)
GPULLAMA3_VERSION="${GPULLAMA3_VERSION}-SNAPSHOT"
echo "GPULlama3 version: $GPULLAMA3_VERSION"
./mvnw versions:set -DnewVersion=$GPULLAMA3_VERSION
# Build
./mvnw clean install -DskipTests
# Save GPULlama3.java version for subsequent steps
echo "GPULLAMA3_VERSION=$GPULLAMA3_VERSION" >> $GITHUB_ENV
# Step 3: Clone Quarkus LangChain4j
- name: Clone Quarkus LangChain4j
run: |
cd ${{ github.workspace }}
git clone https://github.com/quarkiverse/quarkus-langchain4j.git
# Step 4: Build Quarkus LangChain4j with current GPULlama3.java
- name: Build Quarkus LangChain4j
run: |
cd ${{ github.workspace }}/quarkus-langchain4j
export PATH="$TORNADOVM_HOME/bin:$JAVA_HOME/bin:$PATH"
# Update the GPULlama3 version used by quarkus-langchain4j
POM="pom.xml"
sed -i 's/<gpu-llama3\.version>.*<\/gpu-llama3\.version>/<gpu-llama3.version>'$GPULLAMA3_VERSION'<\/gpu-llama3.version>/' "$POM"
# Use reactor to build *only *GPULlama3 integration test + dependencies
# This recompiles everything with the same Java version, avoiding compatibility issues
# The -Dtornado flag activates the TornadoVM profile which includes gpu-llama3 module
mvn clean install -pl integration-tests/gpu-llama3 -am -DskipTests -Dtornado
# Step 4.5: Verify GPULlama3 JAR
- name: Verify GPULlama3 Dependency
run: |
cd ${{ github.workspace }}/quarkus-langchain4j/integration-tests/gpu-llama3
echo "GPULlama3 dependency used by Quarkus-LangChain4j:"
mvn dependency:tree | grep "io.github.beehive-lab:gpu-llama3"
# Step 5: Start Quarkus Application and Wait for Startup
- name: Start Quarkus Application and Wait for Startup
run: |
cd ${{ github.workspace }}/quarkus-langchain4j/integration-tests/gpu-llama3
export PATH="$TORNADOVM_HOME/bin:$JAVA_HOME/bin:$PATH"
echo "Starting Quarkus application on port $QUARKUS_PORT..."
# Start the Quarkus application in the background
java @"$TORNADOVM_HOME/tornado-argfile" \
-Dtornado.device.memory=8GB \
-Dquarkus.http.port=$QUARKUS_PORT \
-jar target/quarkus-app/quarkus-run.jar &
APP_PID=$!
if [ -z "$APP_PID" ]; then
echo "ERROR: Failed to start Quarkus application"
exit 1
fi
echo "Waiting for Quarkus application to start..."
# Wait for application to be ready
for i in {1..30}; do
if curl -s http://localhost:$QUARKUS_PORT/q/health > /dev/null 2>&1; then
echo "Application ready after ${i} seconds"
echo "Health endpoint: http://localhost:$QUARKUS_PORT/q/health"
break
elif [ $i -eq 30 ]; then
echo "ERROR: Application failed to start within 30 seconds"
echo "Debugging info:"
echo "- Port: $QUARKUS_PORT"
echo "- Process ID: $APP_PID"
echo "- Health URL: http://localhost:$QUARKUS_PORT/q/health"
kill $APP_PID || true
exit 1
else
[ $((i % 5)) -eq 0 ] && echo "Still waiting... (${i}s)"
sleep 1
fi
done
# Step 6: Run test 1
- name: Trigger Blocking Endpoint
run: |
MAX_ATTEMPTS=3
ATTEMPT=1
SUCCESS=false
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
echo "Attempt $ATTEMPT of $MAX_ATTEMPTS for blocking endpoint..."
# Trigger endpoint
HTTP_RESPONSE=$(curl -s -w "%{http_code}" http://localhost:$QUARKUS_PORT/chat/blocking)
HTTP_RESPONSE_CODE="${HTTP_RESPONSE: -3}"
HTTP_RESPONSE_BODY="${HTTP_RESPONSE%???}"
# Check response code
if [ "$HTTP_RESPONSE_CODE" = "200" ]; then
echo "SUCCESS: Blocking endpoint returned HTTP code: $HTTP_RESPONSE_CODE"
echo "HTTP Response body: $HTTP_RESPONSE_BODY"
SUCCESS=true
break
else
echo "Attempt $ATTEMPT failed: Blocking endpoint returned HTTP code $HTTP_RESPONSE_CODE"
echo "Response body: $HTTP_RESPONSE_BODY"
if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then
echo "Retrying in 2 seconds..."
sleep 2
fi
fi
ATTEMPT=$((ATTEMPT + 1))
done
if [ "$SUCCESS" = false ]; then
echo "ERROR: Blocking endpoint failed after $MAX_ATTEMPTS attempts"
exit 1
fi
# Step 7: Run test 2
- name: Trigger Streaming Endpoint
run: |
MAX_ATTEMPTS=3
ATTEMPT=1
SUCCESS=false
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
echo "Attempt $ATTEMPT of $MAX_ATTEMPTS for streaming endpoint..."
# Trigger endpoint
HTTP_RESPONSE=$(timeout 10s curl -s -w "%{http_code}" http://localhost:$QUARKUS_PORT/chat/streaming)
HTTP_RESPONSE_CODE="${HTTP_RESPONSE: -3}"
#HTTP_RESPONSE_BODY="$HTTP_RESPONSE%???}"
# Check response code
if [ "$HTTP_RESPONSE_CODE" == "200" ]; then
echo "SUCCESS: Streaming endpoint returned HTTP code: ${HTTP_RESPONSE: -3}"
# do not show ugly streaming response body
#echo "HTTP Response body: $HTTP_RESPONSE_BODY"
SUCCESS=true
break
else
echo "Attempt $ATTEMPT failed: Streaming endpoint returned HTTP code $HTTP_RESPONSE_CODE"
if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then
echo "Retrying in 2 seconds..."
sleep 2
fi
fi
ATTEMPT=$((ATTEMPT + 1))
done
if [ "$SUCCESS" = false ]; then
echo "ERROR: Streaming endpoint failed after $MAX_ATTEMPTS attempts"
exit 1
fi
# Step 8: Cleanup & Shutdown
- name: Cleanup & Shutdown
run: |
# Clean shutdown
kill $APP_PID || true
wait $APP_PID 2>/dev/null || true