Compare commits

..

2 Commits

Author SHA1 Message Date
ZePan110
e1f98c896b increase timeout 10s to 60s
Signed-off-by: ZePan110 <ze.pan@intel.com>
2025-04-03 22:23:42 +08:00
ZePan110
e23eb6013f only test
Signed-off-by: ZePan110 <ze.pan@intel.com>
2025-04-03 00:59:49 +08:00
753 changed files with 17143 additions and 33944 deletions

21
.github/CODEOWNERS vendored
View File

@@ -1,18 +1,16 @@
# Code owners will review PRs within their respective folders. * liang1.lv@intel.com feng.tian@intel.com suyue.chen@intel.com
* liang1.lv@intel.com feng.tian@intel.com suyue.chen@intel.com kaokao.lv@intel.com minmin.hou@intel.com rita.brugarolas.brufau@intel.com
/.github/ suyue.chen@intel.com ze.pan@intel.com /.github/ suyue.chen@intel.com ze.pan@intel.com
/AgentQnA/ abolfazl.shahbazi@intel.com kaokao.lv@intel.com minmin.hou@intel.com /AgentQnA/ kaokao.lv@intel.com minmin.hou@intel.com
/AudioQnA/ sihan.chen@intel.com wenjiao.yue@intel.com /AudioQnA/ sihan.chen@intel.com wenjiao.yue@intel.com
/AvatarChatbot/ chun.tao@intel.com kaokao.lv@intel.com /AvatarChatbot/ chun.tao@intel.com kaokao.lv@intel.com
/ChatQnA/ liang1.lv@intel.com letong.han@intel.com /ChatQnA/ liang1.lv@intel.com letong.han@intel.com
/CodeGen/ liang1.lv@intel.com /CodeGen/ liang1.lv@intel.com xinyao.wang@intel.com
/CodeTrans/ sihan.chen@intel.com /CodeTrans/ sihan.chen@intel.com xinyao.wang@intel.com
/DBQnA/ supriya.krishnamurthi@intel.com liang1.lv@intel.com /DBQnA/ supriya.krishnamurthi@intel.com liang1.lv@intel.com
/DocIndexRetriever/ abolfazl.shahbazi@intel.com kaokao.lv@intel.com chendi.xue@intel.com /DocIndexRetriever/ kaokao.lv@intel.com chendi.xue@intel.com
/DocSum/ letong.han@intel.com /DocSum/ letong.han@intel.com xinyao.wang@intel.com
/EdgeCraftRAG/ yongbo.zhu@intel.com mingyuan.qi@intel.com /EdgeCraftRAG/ yongbo.zhu@intel.com mingyuan.qi@intel.com
/FinanceAgent/ abolfazl.shahbazi@intel.com kaokao.lv@intel.com minmin.hou@intel.com rita.brugarolas.brufau@intel.com /FaqGen/ yogesh.pandey@intel.com xinyao.wang@intel.com
/GraphRAG/ rita.brugarolas.brufau@intel.com abolfazl.shahbazi@intel.com /GraphRAG/ rita.brugarolas.brufau@intel.com abolfazl.shahbazi@intel.com
/InstructionTuning/ xinyu.ye@intel.com kaokao.lv@intel.com /InstructionTuning/ xinyu.ye@intel.com kaokao.lv@intel.com
/MultimodalQnA/ melanie.h.buehler@intel.com tiep.le@intel.com /MultimodalQnA/ melanie.h.buehler@intel.com tiep.le@intel.com
@@ -21,6 +19,5 @@
/SearchQnA/ sihan.chen@intel.com letong.han@intel.com /SearchQnA/ sihan.chen@intel.com letong.han@intel.com
/Text2Image/ wenjiao.yue@intel.com xinyu.ye@intel.com /Text2Image/ wenjiao.yue@intel.com xinyu.ye@intel.com
/Translation/ liang1.lv@intel.com sihan.chen@intel.com /Translation/ liang1.lv@intel.com sihan.chen@intel.com
/VideoQnA/ huiling.bao@intel.com /VideoQnA/ huiling.bao@intel.com xinyao.wang@intel.com
/VisualQnA/ liang1.lv@intel.com sihan.chen@intel.com /VisualQnA/ liang1.lv@intel.com sihan.chen@intel.com
/WorkflowExecAgent/ joshua.jian.ern.liew@intel.com kaokao.lv@intel.com

View File

@@ -32,7 +32,6 @@ body:
- Mac - Mac
- BSD - BSD
- Other (Please let us know in description) - Other (Please let us know in description)
- N/A
validations: validations:
required: true required: true
@@ -57,7 +56,6 @@ body:
- GPU-Nvidia - GPU-Nvidia
- GPU-AMD - GPU-AMD
- GPU-other (Please let us know in description) - GPU-other (Please let us know in description)
- N/A
validations: validations:
required: true required: true
@@ -69,7 +67,6 @@ body:
- label: Pull docker images from hub.docker.com - label: Pull docker images from hub.docker.com
- label: Build docker images from source - label: Build docker images from source
- label: Other - label: Other
- label: N/A
validations: validations:
required: true required: true
@@ -83,7 +80,6 @@ body:
- label: Kubernetes Helm Charts - label: Kubernetes Helm Charts
- label: Kubernetes GMC - label: Kubernetes GMC
- label: Other - label: Other
- label: N/A
validations: validations:
required: true required: true
@@ -95,7 +91,6 @@ body:
- Single Node - Single Node
- Multiple Nodes - Multiple Nodes
- Other - Other
- N/A
default: 0 default: 0
validations: validations:
required: true required: true

View File

@@ -32,7 +32,6 @@ body:
- Mac - Mac
- BSD - BSD
- Other (Please let us know in description) - Other (Please let us know in description)
- N/A
validations: validations:
required: true required: true
@@ -57,7 +56,6 @@ body:
- GPU-Nvidia - GPU-Nvidia
- GPU-AMD - GPU-AMD
- GPU-other (Please let us know in description) - GPU-other (Please let us know in description)
- N/A
validations: validations:
required: true required: true
@@ -69,7 +67,6 @@ body:
- Single Node - Single Node
- Multiple Nodes - Multiple Nodes
- Other - Other
- N/A
default: 0 default: 0
validations: validations:
required: true required: true

View File

@@ -1,5 +0,0 @@
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
export VLLM_VER=v0.8.3
export VLLM_FORK_VER=v0.6.6.post1+Gaudi-1.20.0

View File

@@ -35,9 +35,9 @@ jobs:
- name: Check if job should be skipped - name: Check if job should be skipped
id: check-skip id: check-skip
run: | run: |
should_skip=true should_skip=false
if [[ "${{ inputs.node }}" == "gaudi" || "${{ inputs.node }}" == "xeon" ]]; then if [[ "${{ inputs.node }}" == "gaudi3" || "${{ inputs.node }}" == "rocm" || "${{ inputs.node }}" == "arc" ]]; then
should_skip=false should_skip=true
fi fi
echo "should_skip=$should_skip" echo "should_skip=$should_skip"
echo "should_skip=$should_skip" >> $GITHUB_OUTPUT echo "should_skip=$should_skip" >> $GITHUB_OUTPUT

View File

@@ -42,9 +42,9 @@ jobs:
- name: Check if job should be skipped - name: Check if job should be skipped
id: check-skip id: check-skip
run: | run: |
should_skip=true should_skip=false
if [[ "${{ inputs.node }}" == "gaudi" || "${{ inputs.node }}" == "xeon" ]]; then if [[ "${{ inputs.node }}" == "gaudi3" || "${{ inputs.node }}" == "rocm" || "${{ inputs.node }}" == "arc" ]]; then
should_skip=false should_skip=true
fi fi
echo "should_skip=$should_skip" echo "should_skip=$should_skip"
echo "should_skip=$should_skip" >> $GITHUB_OUTPUT echo "should_skip=$should_skip" >> $GITHUB_OUTPUT
@@ -75,12 +75,19 @@ jobs:
run: | run: |
cd ${{ github.workspace }}/${{ inputs.example }}/docker_image_build cd ${{ github.workspace }}/${{ inputs.example }}/docker_image_build
docker_compose_path=${{ github.workspace }}/${{ inputs.example }}/docker_image_build/build.yaml docker_compose_path=${{ github.workspace }}/${{ inputs.example }}/docker_image_build/build.yaml
source ${{ github.workspace }}/.github/env/_build_image.sh
if [[ $(grep -c "vllm:" ${docker_compose_path}) != 0 ]]; then if [[ $(grep -c "vllm:" ${docker_compose_path}) != 0 ]]; then
git clone -b ${VLLM_VER} --single-branch https://github.com/vllm-project/vllm.git git clone https://github.com/vllm-project/vllm.git && cd vllm
# Get the latest tag
VLLM_VER=$(git describe --tags "$(git rev-list --tags --max-count=1)")
echo "Check out vLLM tag ${VLLM_VER}"
git checkout ${VLLM_VER} &> /dev/null && cd ../
fi fi
if [[ $(grep -c "vllm-gaudi:" ${docker_compose_path}) != 0 ]]; then if [[ $(grep -c "vllm-gaudi:" ${docker_compose_path}) != 0 ]]; then
git clone -b ${VLLM_FORK_VER} --single-branch https://github.com/HabanaAI/vllm-fork.git git clone https://github.com/HabanaAI/vllm-fork.git && cd vllm-fork
# Get the latest tag
VLLM_VER=$(git describe --tags "$(git rev-list --tags --max-count=1)")
echo "Check out vLLM tag ${VLLM_VER}"
git checkout ${VLLM_VER} &> /dev/null && cd ../
fi fi
git clone --depth 1 --branch ${{ inputs.opea_branch }} https://github.com/opea-project/GenAIComps.git git clone --depth 1 --branch ${{ inputs.opea_branch }} https://github.com/opea-project/GenAIComps.git
cd GenAIComps && git rev-parse HEAD && cd ../ cd GenAIComps && git rev-parse HEAD && cd ../

View File

@@ -76,7 +76,6 @@ jobs:
example: ${{ inputs.example }} example: ${{ inputs.example }}
hardware: ${{ inputs.node }} hardware: ${{ inputs.node }}
use_model_cache: ${{ inputs.use_model_cache }} use_model_cache: ${{ inputs.use_model_cache }}
opea_branch: ${{ inputs.opea_branch }}
secrets: inherit secrets: inherit

View File

@@ -3,8 +3,7 @@
# This workflow will only test GMC pipeline and will not install GMC any more # This workflow will only test GMC pipeline and will not install GMC any more
name: Single GMC E2e Test For CD Workflow Call name: Single GMC E2e Test For CD Workflow Call
permissions:
contents: read
on: on:
workflow_call: workflow_call:
inputs: inputs:

View File

@@ -2,8 +2,7 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Build and deploy GMC system on call and manual name: Build and deploy GMC system on call and manual
permissions:
contents: read
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:

View File

@@ -2,9 +2,7 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Helm Chart E2e Test For Call name: Helm Chart E2e Test For Call
permissions: permissions: read-all
contents: read
on: on:
workflow_call: workflow_call:
inputs: inputs:
@@ -83,10 +81,6 @@ jobs:
if [[ "${{ inputs.hardware }}" == "gaudi" ]]; then if [[ "${{ inputs.hardware }}" == "gaudi" ]]; then
value_files="${value_files}\"${filename}\"," value_files="${value_files}\"${filename}\","
fi fi
elif [[ "$filename" == *"rocm"* ]]; then
if [[ "${{ inputs.hardware }}" == "rocm" ]]; then
value_files="${value_files}\"${filename}\","
fi
elif [[ "$filename" == *"nv"* ]]; then elif [[ "$filename" == *"nv"* ]]; then
continue continue
else else
@@ -137,28 +131,16 @@ jobs:
env: env:
example: ${{ inputs.example }} example: ${{ inputs.example }}
run: | run: |
if [[ ! "$example" =~ ^[a-zA-Z0-9]{1,20}$ ]] || [[ "$example" =~ \.\. ]] || [[ "$example" == -* || "$example" == *- ]]; then CHART_NAME="${example,,}" # CodeGen
echo "Error: Invalid input - only lowercase alphanumeric and internal hyphens allowed" echo "CHART_NAME=$CHART_NAME" >> $GITHUB_ENV
exit 1 echo "RELEASE_NAME=${CHART_NAME}$(date +%Y%m%d%H%M%S)" >> $GITHUB_ENV
fi echo "NAMESPACE=${CHART_NAME}-$(date +%Y%m%d%H%M%S)" >> $GITHUB_ENV
# SAFE_PREFIX="kb-" echo "ROLLOUT_TIMEOUT_SECONDS=600s" >> $GITHUB_ENV
CHART_NAME="${SAFE_PREFIX}$(echo "$example" | tr '[:upper:]' '[:lower:]')" echo "TEST_TIMEOUT_SECONDS=600s" >> $GITHUB_ENV
RAND_SUFFIX=$(openssl rand -hex 2 | tr -dc 'a-f0-9') echo "KUBECTL_TIMEOUT_SECONDS=60s" >> $GITHUB_ENV
echo "should_cleanup=false" >> $GITHUB_ENV
cat <<EOF >> $GITHUB_ENV echo "skip_validate=false" >> $GITHUB_ENV
CHART_NAME=${CHART_NAME} echo "CHART_FOLDER=${example}/kubernetes/helm" >> $GITHUB_ENV
RELEASE_NAME=${CHART_NAME}-$(date +%s)
NAMESPACE=ns-${CHART_NAME}-${RAND_SUFFIX}
ROLLOUT_TIMEOUT_SECONDS=600s
TEST_TIMEOUT_SECONDS=600s
KUBECTL_TIMEOUT_SECONDS=60s
should_cleanup=false
skip_validate=false
CHART_FOLDER=${example}/kubernetes/helm
EOF
echo "Generated safe variables:" >> $GITHUB_STEP_SUMMARY
echo "- CHART_NAME: ${CHART_NAME}" >> $GITHUB_STEP_SUMMARY
- name: Helm install - name: Helm install
id: install id: install
@@ -191,7 +173,7 @@ jobs:
$RELEASE_NAME \ $RELEASE_NAME \
oci://ghcr.io/opea-project/charts/${CHART_NAME} \ oci://ghcr.io/opea-project/charts/${CHART_NAME} \
--set global.HUGGINGFACEHUB_API_TOKEN=${HFTOKEN} \ --set global.HUGGINGFACEHUB_API_TOKEN=${HFTOKEN} \
--set global.modelUseHostPath=/data2/hf_model \ --set global.modelUseHostPath=/home/sdp/.cache/huggingface/hub \
--set GOOGLE_API_KEY=${{ env.GOOGLE_API_KEY}} \ --set GOOGLE_API_KEY=${{ env.GOOGLE_API_KEY}} \
--set GOOGLE_CSE_ID=${{ env.GOOGLE_CSE_ID}} \ --set GOOGLE_CSE_ID=${{ env.GOOGLE_CSE_ID}} \
--set web-retriever.GOOGLE_API_KEY=${{ env.GOOGLE_API_KEY}} \ --set web-retriever.GOOGLE_API_KEY=${{ env.GOOGLE_API_KEY}} \

View File

@@ -32,10 +32,6 @@ on:
required: false required: false
type: boolean type: boolean
default: false default: false
opea_branch:
default: "main"
required: false
type: string
jobs: jobs:
get-test-case: get-test-case:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -68,10 +64,8 @@ jobs:
cd ${{ github.workspace }}/${{ inputs.example }}/tests cd ${{ github.workspace }}/${{ inputs.example }}/tests
run_test_cases="" run_test_cases=""
if [[ "${{ inputs.hardware }}" == "gaudi"* ]]; then if [ "${{ inputs.hardware }}" == "gaudi2" ] || [ "${{ inputs.hardware }}" == "gaudi3" ]; then
hardware="gaudi" hardware="gaudi"
elif [[ "${{ inputs.hardware }}" == "xeon"* ]]; then
hardware="xeon"
else else
hardware="${{ inputs.hardware }}" hardware="${{ inputs.hardware }}"
fi fi
@@ -121,18 +115,9 @@ jobs:
- name: Clean up Working Directory - name: Clean up Working Directory
run: | run: |
sudo rm -rf ${{github.workspace}}/* || true sudo rm -rf ${{github.workspace}}/* || true
echo "Cleaning up containers using ports..."
cid=$(docker ps --format '{{.Names}} : {{.Ports}}' | grep -v ' : $' | grep -v 0.0.0.0:5000 | awk -F' : ' '{print $1}')
if [[ ! -z "$cid" ]]; then docker stop $cid && docker rm $cid && sleep 1s; fi
docker system prune -f docker system prune -f
docker rmi $(docker images --filter reference="*/*/*:latest" -q) || true
echo "Cleaning up images ..." docker rmi $(docker images --filter reference="*/*:ci" -q) || true
docker images --filter reference="*/*/*:latest" -q | xargs -r docker rmi && sleep 1s
docker images --filter reference="*/*:ci" -q | xargs -r docker rmi && sleep 1s
docker images --filter reference="*:5000/*/*" -q | xargs -r docker rmi && sleep 1s
docker images --filter reference="opea/comps-base" -q | xargs -r docker rmi && sleep 1s
docker images
- name: Checkout out Repo - name: Checkout out Repo
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -151,12 +136,6 @@ jobs:
bash ${{ github.workspace }}/.github/workflows/scripts/docker_compose_clean_up.sh "ports" bash ${{ github.workspace }}/.github/workflows/scripts/docker_compose_clean_up.sh "ports"
docker ps docker ps
- name: Log in DockerHub
uses: docker/login-action@v3.2.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Run test - name: Run test
shell: bash shell: bash
env: env:
@@ -169,11 +148,8 @@ jobs:
SDK_BASE_URL: ${{ secrets.SDK_BASE_URL }} SDK_BASE_URL: ${{ secrets.SDK_BASE_URL }}
SERVING_TOKEN: ${{ secrets.SERVING_TOKEN }} SERVING_TOKEN: ${{ secrets.SERVING_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
FINNHUB_API_KEY: ${{ secrets.FINNHUB_API_KEY }}
FINANCIAL_DATASETS_API_KEY: ${{ secrets.FINANCIAL_DATASETS_API_KEY }}
IMAGE_REPO: ${{ inputs.registry }} IMAGE_REPO: ${{ inputs.registry }}
IMAGE_TAG: ${{ inputs.tag }} IMAGE_TAG: ${{ inputs.tag }}
opea_branch: ${{ inputs.opea_branch }}
example: ${{ inputs.example }} example: ${{ inputs.example }}
hardware: ${{ inputs.hardware }} hardware: ${{ inputs.hardware }}
test_case: ${{ matrix.test_case }} test_case: ${{ matrix.test_case }}
@@ -186,48 +162,25 @@ jobs:
export model_cache="/data2/hf_model" export model_cache="/data2/hf_model"
else else
echo "Model cache directory /data2/hf_model does not exist" echo "Model cache directory /data2/hf_model does not exist"
export model_cache="$HOME/.cache/huggingface/hub" export model_cache="~/.cache/huggingface/hub"
fi
if [[ "$test_case" == *"rocm"* ]]; then
export model_cache="/var/lib/GenAI/data"
fi fi
fi fi
if [ -f "${test_case}" ]; then timeout 60m bash "${test_case}"; else echo "Test script {${test_case}} not found, skip test!"; fi if [ -f "${test_case}" ]; then timeout 30m bash "${test_case}"; else echo "Test script {${test_case}} not found, skip test!"; fi
- name: Clean up container after test - name: Clean up container after test
if: always() shell: bash
if: cancelled() || failure()
run: | run: |
set -x cd ${{ github.workspace }}/${{ inputs.example }}
export test_case=${{ matrix.test_case }}
echo "Cleaning up containers using ports..." export hardware=${{ inputs.hardware }}
cid=$(docker ps --format '{{.Names}} : {{.Ports}}' | grep -v ' : $' | grep -v 0.0.0.0:5000 | awk -F' : ' '{print $1}') bash ${{ github.workspace }}/.github/workflows/scripts/docker_compose_clean_up.sh "containers"
if [[ ! -z "$cid" ]]; then docker stop $cid && docker rm $cid && sleep 1s; fi docker system prune -f
docker rmi $(docker images --filter reference="*:5000/*/*" -q) || true
echo "Cleaning up images ..."
df -h
sleep 1
docker system df
sleep 1
if [[ "${{ inputs.hardware }}" == "xeon"* ]]; then
docker system prune -a -f
else
docker images --filter reference="*/*/*:latest" -q | xargs -r docker rmi && sleep 1s
docker images --filter reference="*/*:ci" -q | xargs -r docker rmi && sleep 1s
docker images --filter reference="*:5000/*/*" -q | xargs -r docker rmi && sleep 1s
docker images --filter reference="opea/comps-base" -q | xargs -r docker rmi && sleep 1s
docker system prune -f
fi
sleep 5
docker images
sleep 1
df -h
sleep 1
docker system df
sleep 1
- name: Publish pipeline artifact - name: Publish pipeline artifact
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.hardware }}_${{ inputs.example }}_${{ matrix.test_case }} name: ${{ inputs.example }}_${{ matrix.test_case }}
path: ${{ github.workspace }}/${{ inputs.example }}/tests/*.log path: ${{ github.workspace }}/${{ inputs.example }}/tests/*.log

View File

@@ -1,94 +0,0 @@
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
name: Daily update vLLM & vLLM-fork version
on:
schedule:
- cron: "30 22 * * *"
workflow_dispatch:
env:
BRANCH_NAME: "update"
USER_NAME: "CICD-at-OPEA"
USER_EMAIL: "CICD@opea.dev"
jobs:
freeze-tag:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- repo: vLLM
repo_name: vllm-project/vllm
ver_name: VLLM_VER
- repo: vLLM-fork
repo_name: HabanaAI/vllm-fork
ver_name: VLLM_FORK_VER
fail-fast: false
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.ref }}
- name: Set up Git
run: |
git config --global user.name ${{ env.USER_NAME }}
git config --global user.email ${{ env.USER_EMAIL }}
git remote set-url origin https://${{ env.USER_NAME }}:"${{ secrets.ACTION_TOKEN }}"@github.com/${{ github.repository }}.git
git fetch
if git ls-remote https://github.com/${{ github.repository }}.git "refs/heads/${{ env.BRANCH_NAME }}_${{ matrix.repo }}" | grep -q "refs/heads/${{ env.BRANCH_NAME }}_${{ matrix.repo }}"; then
echo "branch ${{ env.BRANCH_NAME }}_${{ matrix.repo }} exists"
git checkout ${{ env.BRANCH_NAME }}_${{ matrix.repo }}
else
echo "branch ${{ env.BRANCH_NAME }}_${{ matrix.repo }} not exists"
git checkout -b ${{ env.BRANCH_NAME }}_${{ matrix.repo }}
git push origin ${{ env.BRANCH_NAME }}_${{ matrix.repo }}
echo "branch ${{ env.BRANCH_NAME }}_${{ matrix.repo }} created successfully"
fi
- name: Run script
run: |
latest_vllm_ver=$(curl -s "https://api.github.com/repos/${{ matrix.repo_name }}/tags" | jq '.[0].name' -)
latest_vllm_ver=$(echo "$latest_vllm_ver" | sed 's/"//g')
echo "latest_vllm_ver=${latest_vllm_ver}" >> "$GITHUB_ENV"
find . -type f -name "*.sh" -exec sed -i "s/${{ matrix.ver_name }}=.*/${{ matrix.ver_name }}=${latest_vllm_ver}/" {} \;
- name: Commit changes
run: |
git add .
if git diff-index --quiet HEAD --; then
echo "No changes detected, skipping commit."
exit 1
else
git commit -s -m "Update ${{ matrix.repo }} version to ${latest_vllm_ver}"
git push --set-upstream origin ${{ env.BRANCH_NAME }}_${{ matrix.repo }}
fi
- name: Create Pull Request
env:
GH_TOKEN: ${{ secrets.ACTION_TOKEN }}
run: |
pr_count=$(curl -H "Authorization: token ${{ secrets.ACTION_TOKEN }}" -s "https://api.github.com/repos/${{ github.repository }}/pulls?state=all&head=${{ env.USER_NAME }}:${{ env.BRANCH_NAME }}_${{ matrix.repo }}" | jq '. | length')
if [ $pr_count -gt 0 ]; then
echo "Pull Request exists"
pr_number=$(curl -H "Authorization: token ${{ secrets.ACTION_TOKEN }}" -s "https://api.github.com/repos/${{ github.repository }}/pulls?state=all&head=${{ env.USER_NAME }}:${{ env.BRANCH_NAME }}_${{ matrix.repo }}" | jq '.[0].number')
gh pr edit ${pr_number} \
--title "Update ${{ matrix.repo }} version to ${latest_vllm_ver}" \
--body "Update ${{ matrix.repo }} version to ${latest_vllm_ver}"
echo "Pull Request updated successfully"
else
echo "Pull Request does not exists..."
gh pr create \
-B main \
-H ${{ env.BRANCH_NAME }}_${{ matrix.repo }} \
--title "Update ${{ matrix.repo }} version to ${latest_vllm_ver}" \
--body "Update ${{ matrix.repo }} version to ${latest_vllm_ver}"
echo "Pull Request created successfully"
fi

View File

@@ -26,4 +26,3 @@ jobs:
close-pr-message: "This PR was closed because it has been stalled for 7 days with no activity." close-pr-message: "This PR was closed because it has been stalled for 7 days with no activity."
repo-token: ${{ secrets.ACTION_TOKEN }} repo-token: ${{ secrets.ACTION_TOKEN }}
start-date: "2025-03-01T00:00:00Z" start-date: "2025-03-01T00:00:00Z"
exempt-issue-labels: "Backlog"

View File

@@ -1,119 +0,0 @@
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
name: Update Docker Hub Description
permissions:
contents: read
on:
schedule:
- cron: "0 0 * * 0"
workflow_dispatch:
jobs:
get-images-matrix:
runs-on: ubuntu-latest
outputs:
examples_json: ${{ steps.extract.outputs.examples_json }}
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Extract images info and generate JSON matrix
id: extract
run: |
#!/bin/bash
set -e
images=$(awk -F'|' '/^\| *\[opea\// {
gsub(/^ +| +$/, "", $2);
gsub(/^ +| +$/, "", $4);
gsub(/^ +| +$/, "", $5);
# Extract the path portion of the dockerHub link from the Example Images column
match($2, /\(https:\/\/hub\.docker\.com\/r\/[^)]*\)/);
repository = substr($2, RSTART, RLENGTH);
# Remove the prefix and the trailing right bracket
sub(/^\(https:\/\/hub\.docker\.com\/r\//, "", repository);
sub(/\)$/, "", repository);
# Description Direct assignment
description = $4;
# Extract the content of the github link from the Readme column
match($5, /\(https:\/\/github\.com\/[^)]*\)/);
readme_url = substr($5, RSTART, RLENGTH);
# Remove the prefix and the trailing right bracket
sub(/^\(https:\/\/github\.com\//, "", readme_url);
sub(/\)$/, "", readme_url);
# Remove blob information, such as "blob/main/" or "blob/habana_main/"
gsub(/blob\/[^/]+\//, "", readme_url);
# Remove the organization name and keep only the file path, such as changing "opea-project/GenAIExamples/AudioQnA/README.md" to "GenAIExamples/AudioQnA/README.md"
sub(/^[^\/]+\//, "", readme_url);
# Generate JSON object string
printf "{\"repository\":\"%s\",\"short-description\":\"%s\",\"readme-filepath\":\"%s\"}\n", repository, description, readme_url;
}' docker_images_list.md)
# Concatenate all JSON objects into a JSON array, using paste to separate them with commas
json="[$(echo "$images" | paste -sd, -)]"
echo "$json"
# Set as output variable for subsequent jobs to use
echo "::set-output name=examples_json::$json"
check-images-matrix:
runs-on: ubuntu-latest
needs: get-images-matrix
if: ${{ needs.get-images-matrix.outputs.examples_json != '' }}
strategy:
matrix:
image: ${{ fromJSON(needs.get-images-matrix.outputs.examples_json) }}
fail-fast: false
steps:
- name: Check dockerhub description
run: |
echo "dockerhub description for ${{ matrix.image.repository }}"
echo "short-description: ${{ matrix.image.short-description }}"
echo "readme-filepath: ${{ matrix.image.readme-filepath }}"
dockerHubDescription:
runs-on: ubuntu-latest
needs: get-images-matrix
if: ${{ needs.get-images-matrix.outputs.examples_json != '' }}
strategy:
matrix:
image: ${{ fromJSON(needs.get-images-matrix.outputs.examples_json) }}
fail-fast: false
steps:
- name: Checkout GenAIExamples
uses: actions/checkout@v4
with:
repository: opea-project/GenAIExamples
path: GenAIExamples
- name: Checkout GenAIComps
uses: actions/checkout@v4
with:
repository: opea-project/GenAIComps
path: GenAIComps
- name: Checkout vllm-openvino
uses: actions/checkout@v4
with:
repository: vllm-project/vllm
path: vllm
- name: Checkout vllm-gaudi
uses: actions/checkout@v4
with:
repository: HabanaAI/vllm-fork
ref: habana_main
path: vllm-fork
- name: add dockerhub description
uses: peter-evans/dockerhub-description@v4
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
repository: ${{ matrix.image.repository }}
short-description: ${{ matrix.image.short-description }}
readme-filepath: ${{ matrix.image.readme-filepath }}
enable-url-completion: false

View File

@@ -2,8 +2,6 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Clean up container on manual event name: Clean up container on manual event
permissions:
contents: read
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:

View File

@@ -7,7 +7,7 @@ on:
inputs: inputs:
nodes: nodes:
default: "gaudi,xeon" default: "gaudi,xeon"
description: "Hardware to run test gaudi,xeon,rocm,arc,gaudi3,xeon-gnr" description: "Hardware to run test gaudi,gaudi3,xeon,rocm,arc"
required: true required: true
type: string type: string
examples: examples:

View File

@@ -2,8 +2,7 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Freeze OPEA images release tag name: Freeze OPEA images release tag
permissions:
contents: read
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:

View File

@@ -2,8 +2,6 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Build specific images on manual event name: Build specific images on manual event
permissions:
contents: read
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:

View File

@@ -2,8 +2,6 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Clean up Local Registry on manual event name: Clean up Local Registry on manual event
permissions:
contents: read
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:

View File

@@ -2,8 +2,7 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Trellix Command Line Scanner name: Trellix Command Line Scanner
permissions:
contents: read
on: on:
workflow_dispatch: workflow_dispatch:
schedule: schedule:

View File

@@ -2,11 +2,10 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Nightly build/publish latest docker images name: Nightly build/publish latest docker images
permissions:
contents: read
on: on:
schedule: schedule:
- cron: "30 14 * * 1-5" # UTC time - cron: "30 14 * * *" # UTC time
workflow_dispatch: workflow_dispatch:
env: env:
@@ -39,21 +38,8 @@ jobs:
with: with:
node: gaudi node: gaudi
build-images: build-and-test:
needs: [get-build-matrix, build-comps-base] needs: get-build-matrix
strategy:
matrix:
example: ${{ fromJSON(needs.get-build-matrix.outputs.examples_json) }}
fail-fast: false
uses: ./.github/workflows/_build_image.yml
with:
node: gaudi
example: ${{ matrix.example }}
inject_commit: true
secrets: inherit
test-example:
needs: [get-build-matrix]
if: ${{ needs.get-build-matrix.outputs.examples_json != '' }} if: ${{ needs.get-build-matrix.outputs.examples_json != '' }}
strategy: strategy:
matrix: matrix:
@@ -61,22 +47,21 @@ jobs:
fail-fast: false fail-fast: false
uses: ./.github/workflows/_example-workflow.yml uses: ./.github/workflows/_example-workflow.yml
with: with:
node: xeon node: gaudi
build: false
example: ${{ matrix.example }} example: ${{ matrix.example }}
test_compose: true test_compose: true
inject_commit: true inject_commit: true
secrets: inherit secrets: inherit
get-image-list: get-image-list:
needs: [get-build-matrix] needs: get-build-matrix
uses: ./.github/workflows/_get-image-list.yml uses: ./.github/workflows/_get-image-list.yml
with: with:
examples: ${{ needs.get-build-matrix.outputs.EXAMPLES }} examples: ${{ needs.get-build-matrix.outputs.EXAMPLES }}
publish: publish:
needs: [get-build-matrix, get-image-list, build-images] needs: [get-build-matrix, get-image-list, build-and-test]
if: always() if: ${{ needs.get-image-list.outputs.matrix != '' }}
strategy: strategy:
matrix: matrix:
image: ${{ fromJSON(needs.get-image-list.outputs.matrix) }} image: ${{ fromJSON(needs.get-image-list.outputs.matrix) }}

View File

@@ -2,8 +2,7 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: E2E Test with Helm Charts name: E2E Test with Helm Charts
permissions:
contents: read
on: on:
pull_request_target: pull_request_target:
branches: [main] branches: [main]
@@ -20,9 +19,6 @@ concurrency:
jobs: jobs:
job1: job1:
name: Get-Test-Matrix name: Get-Test-Matrix
permissions:
contents: read
pull-requests: read
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
run_matrix: ${{ steps.get-test-matrix.outputs.run_matrix }} run_matrix: ${{ steps.get-test-matrix.outputs.run_matrix }}
@@ -50,8 +46,6 @@ jobs:
example=$(echo "$values_file" | cut -d'/' -f1) # CodeGen example=$(echo "$values_file" | cut -d'/' -f1) # CodeGen
if [[ "$valuefile" == *"gaudi"* ]]; then if [[ "$valuefile" == *"gaudi"* ]]; then
hardware="gaudi" hardware="gaudi"
elif [[ "$valuefile" == *"rocm"* ]]; then
hardware="rocm"
elif [[ "$valuefile" == *"nv"* ]]; then elif [[ "$valuefile" == *"nv"* ]]; then
continue continue
else else

View File

@@ -2,8 +2,7 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Check Duplicated Images name: Check Duplicated Images
permissions:
contents: read
on: on:
pull_request: pull_request:
branches: [main] branches: [main]

View File

@@ -2,9 +2,7 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Code Scan name: Code Scan
permissions:
contents: read
security-events: write
on: on:
pull_request: pull_request:
branches: [main] branches: [main]

View File

@@ -3,9 +3,6 @@
name: E2E test with docker compose name: E2E test with docker compose
permissions:
contents: read
on: on:
pull_request_target: pull_request_target:
branches: ["main", "*rc"] branches: ["main", "*rc"]

View File

@@ -2,8 +2,7 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
name: Compose file and dockerfile path checking name: Compose file and dockerfile path checking
permissions:
contents: read
on: on:
pull_request: pull_request:
branches: [main] branches: [main]

View File

@@ -3,9 +3,6 @@
name: Check hyperlinks and relative path validity name: Check hyperlinks and relative path validity
permissions:
contents: read
on: on:
pull_request: pull_request:
branches: [main] branches: [main]
@@ -26,7 +23,6 @@ jobs:
- name: Check the Validity of Hyperlinks - name: Check the Validity of Hyperlinks
run: | run: |
cd ${{github.workspace}} cd ${{github.workspace}}
delay=15
fail="FALSE" fail="FALSE"
merged_commit=$(git log -1 --format='%H') merged_commit=$(git log -1 --format='%H')
changed_files="$(git diff --name-status --diff-filter=ARM ${{ github.event.pull_request.base.sha }} ${merged_commit} | awk '/\.md$/ {print $NF}')" changed_files="$(git diff --name-status --diff-filter=ARM ${{ github.event.pull_request.base.sha }} ${merged_commit} | awk '/\.md$/ {print $NF}')"
@@ -39,20 +35,15 @@ jobs:
# echo $url_line # echo $url_line
url=$(echo "$url_line"|cut -d '(' -f2 | cut -d ')' -f1|sed 's/\.git$//') url=$(echo "$url_line"|cut -d '(' -f2 | cut -d ')' -f1|sed 's/\.git$//')
path=$(echo "$url_line"|cut -d':' -f1 | cut -d'/' -f2-) path=$(echo "$url_line"|cut -d':' -f1 | cut -d'/' -f2-)
if [[ "$url" == "https://platform.openai.com/api-keys"* ]]; then response=$(curl -L -s -o /dev/null -w "%{http_code}" "$url")|| true
echo "Link "$url" from ${{github.workspace}}/$path needs to be verified by a real person." if [ "$response" -ne 200 ]; then
else echo "**********Validation failed, try again**********"
sleep $delay response_retry=$(curl -s -o /dev/null -w "%{http_code}" "$url")
response=$(curl -L -s -o /dev/null -w "%{http_code}" "$url")|| true if [ "$response_retry" -eq 200 ]; then
if [ "$response" -ne 200 ]; then echo "*****Retry successfully*****"
echo "**********Validation failed ($response), try again**********" else
response_retry=$(curl -s -o /dev/null -w "%{http_code}" "$url") echo "Invalid link from ${{github.workspace}}/$path: $url"
if [ "$response_retry" -eq 200 ]; then fail="TRUE"
echo "*****Retry successfully*****"
else
echo "Invalid link ($response_retry) from ${{github.workspace}}/$path: $url"
fail="TRUE"
fi
fi fi
fi fi
done done
@@ -83,10 +74,15 @@ jobs:
- name: Checking Relative Path Validity - name: Checking Relative Path Validity
run: | run: |
cd ${{github.workspace}} cd ${{github.workspace}}
delay=15
fail="FALSE" fail="FALSE"
repo_name=${{ github.event.pull_request.head.repo.full_name }} repo_name=${{ github.event.pull_request.head.repo.full_name }}
branch="https://github.com/$repo_name/blob/${{ github.event.pull_request.head.ref }}" if [ "$(echo "$repo_name"|cut -d'/' -f1)" != "opea-project" ]; then
owner=$(echo "${{ github.event.pull_request.head.repo.full_name }}" |cut -d'/' -f1)
branch="https://github.com/$owner/GenAIExamples/tree/${{ github.event.pull_request.head.ref }}"
else
branch="https://github.com/opea-project/GenAIExamples/blob/${{ github.event.pull_request.head.ref }}"
fi
link_head="https://github.com/opea-project/GenAIExamples/blob/main"
merged_commit=$(git log -1 --format='%H') merged_commit=$(git log -1 --format='%H')
changed_files="$(git diff --name-status --diff-filter=ARM ${{ github.event.pull_request.base.sha }} ${merged_commit} | awk '/\.md$/ {print $NF}')" changed_files="$(git diff --name-status --diff-filter=ARM ${{ github.event.pull_request.base.sha }} ${merged_commit} | awk '/\.md$/ {print $NF}')"
@@ -115,15 +111,14 @@ jobs:
if [[ "$png_line" == *#* ]]; then if [[ "$png_line" == *#* ]]; then
if [ -n "changed_files" ] && echo "$changed_files" | grep -q "^${refer_path}$"; then if [ -n "changed_files" ] && echo "$changed_files" | grep -q "^${refer_path}$"; then
url_dev=$branch$(echo "$real_path" | sed 's|.*/GenAIExamples||')$png_path url_dev=$branch$(echo "$real_path" | sed 's|.*/GenAIExamples||')$png_path
sleep $delay
response=$(curl -I -L -s -o /dev/null -w "%{http_code}" "$url_dev") response=$(curl -I -L -s -o /dev/null -w "%{http_code}" "$url_dev")
if [ "$response" -ne 200 ]; then if [ "$response" -ne 200 ]; then
echo "**********Validation failed ($response), try again**********" echo "**********Validation failed, try again**********"
response_retry=$(curl -s -o /dev/null -w "%{http_code}" "$url_dev") response_retry=$(curl -s -o /dev/null -w "%{http_code}" "$url_dev")
if [ "$response_retry" -eq 200 ]; then if [ "$response_retry" -eq 200 ]; then
echo "*****Retry successfully*****" echo "*****Retry successfully*****"
else else
echo "Invalid path ($response_retry) from ${{github.workspace}}/$refer_path: $png_path" echo "Invalid path from ${{github.workspace}}/$refer_path: $png_path"
fail="TRUE" fail="TRUE"
fi fi
else else

View File

@@ -3,9 +3,6 @@
# Test # Test
name: Build latest images on push event name: Build latest images on push event
permissions:
contents: read
on: on:
push: push:
branches: [ 'main' ] branches: [ 'main' ]

View File

@@ -3,12 +3,10 @@
name: Check the validity of links in docker_images_list. name: Check the validity of links in docker_images_list.
permissions:
contents: read
on: on:
push: push:
branches: [main] branches: [main]
types: [opened, reopened, ready_for_review, synchronize]
jobs: jobs:
check-dockerfile-paths: check-dockerfile-paths:

View File

@@ -8,10 +8,6 @@ on:
- "**/docker_compose/**/compose*.yaml" - "**/docker_compose/**/compose*.yaml"
name: Create an issue to GenAIInfra on push name: Create an issue to GenAIInfra on push
permissions:
contents: read
jobs: jobs:
job1: job1:
name: Create issue name: Create issue

View File

@@ -7,7 +7,7 @@ source /GenAIExamples/.github/workflows/scripts/change_color
log_dir=/GenAIExamples/.github/workflows/scripts/codeScan log_dir=/GenAIExamples/.github/workflows/scripts/codeScan
ERROR_WARN=false ERROR_WARN=false
find . -type f \( -name "Dockerfile*" \) -print -exec hadolint --ignore DL3006 --ignore DL3007 --ignore DL3008 --ignore DL3013 --ignore DL3018 --ignore DL3016 {} \; > ${log_dir}/hadolint.log find . -type f \( -name "Dockerfile*" \) -print -exec hadolint --ignore DL3006 --ignore DL3007 --ignore DL3008 --ignore DL3013 {} \; > ${log_dir}/hadolint.log
if [[ $(grep -c "error" ${log_dir}/hadolint.log) != 0 ]]; then if [[ $(grep -c "error" ${log_dir}/hadolint.log) != 0 ]]; then
$BOLD_RED && echo "Error!! Please Click on the artifact button to download and check error details." && $RESET $BOLD_RED && echo "Error!! Please Click on the artifact button to download and check error details." && $RESET

View File

@@ -1,57 +0,0 @@
# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
name: Weekly test all examples on multiple HWs
permissions: read-all
on:
schedule:
- cron: "30 2 * * 6" # UTC time
workflow_dispatch:
env:
EXAMPLES: "CodeTrans" #${{ vars.NIGHTLY_RELEASE_EXAMPLES }}
NODES: "gaudi,xeon,rocm,arc"
jobs:
get-test-matrix:
runs-on: ubuntu-latest
outputs:
examples: ${{ steps.get-matrix.outputs.examples }}
nodes: ${{ steps.get-matrix.outputs.nodes }}
steps:
- name: Create Matrix
id: get-matrix
run: |
examples=($(echo ${EXAMPLES} | tr ',' ' '))
examples_json=$(printf '%s\n' "${examples[@]}" | sort -u | jq -R '.' | jq -sc '.')
echo "examples=$examples_json" >> $GITHUB_OUTPUT
nodes=($(echo ${NODES} | tr ',' ' '))
nodes_json=$(printf '%s\n' "${nodes[@]}" | sort -u | jq -R '.' | jq -sc '.')
echo "nodes=$nodes_json" >> $GITHUB_OUTPUT
build-comps-base:
needs: [get-test-matrix]
strategy:
matrix:
node: ${{ fromJson(needs.get-test-matrix.outputs.nodes) }}
uses: ./.github/workflows/_build_comps_base_image.yml
with:
node: ${{ matrix.node }}
run-examples:
needs: [get-test-matrix, build-comps-base]
strategy:
matrix:
example: ${{ fromJson(needs.get-test-matrix.outputs.examples) }}
node: ${{ fromJson(needs.get-test-matrix.outputs.nodes) }}
fail-fast: false
uses: ./.github/workflows/_example-workflow.yml
with:
node: ${{ matrix.node }}
example: ${{ matrix.example }}
build: true
test_compose: true
test_helmchart: true
secrets: inherit

View File

@@ -74,7 +74,7 @@ repos:
name: Unused noqa name: Unused noqa
- repo: https://github.com/pycqa/isort - repo: https://github.com/pycqa/isort
rev: 6.0.1 rev: 5.13.2
hooks: hooks:
- id: isort - id: isort
@@ -100,7 +100,7 @@ repos:
- prettier@3.2.5 - prettier@3.2.5
- repo: https://github.com/psf/black.git - repo: https://github.com/psf/black.git
rev: 25.1.0 rev: 24.10.0
hooks: hooks:
- id: black - id: black
files: (.*\.py)$ files: (.*\.py)$
@@ -114,7 +114,7 @@ repos:
- black==24.10.0 - black==24.10.0
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v2.4.1 rev: v2.3.0
hooks: hooks:
- id: codespell - id: codespell
args: [-w] args: [-w]
@@ -122,7 +122,7 @@ repos:
- tomli - tomli
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.4 rev: v0.8.6
hooks: hooks:
- id: ruff - id: ruff
args: [--fix, --exit-non-zero-on-fix, --no-cache] args: [--fix, --exit-non-zero-on-fix, --no-cache]

View File

@@ -1,14 +1,5 @@
# Agents for Question Answering # Agents for Question Answering
## Table of contents
1. [Overview](#overview)
2. [Deploy with Docker](#deploy-with-docker)
3. [How to interact with the agent system with UI](#how-to-interact-with-the-agent-system-with-ui)
4. [Validate Services](#validate-services)
5. [Register Tools](#how-to-register-other-tools-with-the-ai-agent)
6. [Monitoring and Tracing](#monitor-and-tracing)
## Overview ## Overview
This example showcases a hierarchical multi-agent system for question-answering applications. The architecture diagram below shows a supervisor agent that interfaces with the user and dispatches tasks to two worker agents to gather information and come up with answers. The worker RAG agent uses the retrieval tool to retrieve relevant documents from a knowledge base - a vector database. The worker SQL agent retrieves relevant data from a SQL database. Although not included in this example by default, other tools such as a web search tool or a knowledge graph query tool can be used by the supervisor agent to gather information from additional sources. This example showcases a hierarchical multi-agent system for question-answering applications. The architecture diagram below shows a supervisor agent that interfaces with the user and dispatches tasks to two worker agents to gather information and come up with answers. The worker RAG agent uses the retrieval tool to retrieve relevant documents from a knowledge base - a vector database. The worker SQL agent retrieves relevant data from a SQL database. Although not included in this example by default, other tools such as a web search tool or a knowledge graph query tool can be used by the supervisor agent to gather information from additional sources.
@@ -99,7 +90,7 @@ flowchart LR
#### First, clone the `GenAIExamples` repo. #### First, clone the `GenAIExamples` repo.
```bash ```
export WORKDIR=<your-work-directory> export WORKDIR=<your-work-directory>
cd $WORKDIR cd $WORKDIR
git clone https://github.com/opea-project/GenAIExamples.git git clone https://github.com/opea-project/GenAIExamples.git
@@ -109,7 +100,7 @@ git clone https://github.com/opea-project/GenAIExamples.git
##### For proxy environments only ##### For proxy environments only
```bash ```
export http_proxy="Your_HTTP_Proxy" export http_proxy="Your_HTTP_Proxy"
export https_proxy="Your_HTTPs_Proxy" export https_proxy="Your_HTTPs_Proxy"
# Example: no_proxy="localhost, 127.0.0.1, 192.168.1.1" # Example: no_proxy="localhost, 127.0.0.1, 192.168.1.1"
@@ -118,24 +109,14 @@ export no_proxy="Your_No_Proxy"
##### For using open-source llms ##### For using open-source llms
Set up a [HuggingFace](https://huggingface.co/) account and generate a [user access token](https://huggingface.co/docs/transformers.js/en/guides/private#step-1-generating-a-user-access-token). ```
Then set an environment variable with the token and another for a directory to download the models:
```bash
export HUGGINGFACEHUB_API_TOKEN=<your-HF-token> export HUGGINGFACEHUB_API_TOKEN=<your-HF-token>
export HF_CACHE_DIR=<directory-where-llms-are-downloaded> # to avoid redownloading models export HF_CACHE_DIR=<directory-where-llms-are-downloaded> #so that no need to redownload every time
``` ```
##### [Optional] OPENAI_API_KEY to use OpenAI models or Intel® AI for Enterprise Inference ##### [Optional] OPANAI_API_KEY to use OpenAI models
To use OpenAI models, generate a key following these [instructions](https://platform.openai.com/api-keys). ```
To use a remote server running Intel® AI for Enterprise Inference, contact the cloud service provider or owner of the on-prem machine for a key to access the desired model on the server.
Then set the environment variable `OPENAI_API_KEY` with the key contents:
```bash
export OPENAI_API_KEY=<your-openai-key> export OPENAI_API_KEY=<your-openai-key>
``` ```
@@ -143,46 +124,38 @@ export OPENAI_API_KEY=<your-openai-key>
##### Gaudi ##### Gaudi
```bash ```
source $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/hpu/gaudi/set_env.sh source $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/hpu/gaudi/set_env.sh
``` ```
##### Xeon ##### Xeon
```bash ```
source $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/cpu/xeon/set_env.sh source $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/cpu/xeon/set_env.sh
``` ```
For running ### 3. Launch the multi-agent system. </br>
### 2. Launch the multi-agent system. </br> Two options are provided for the `llm_engine` of the agents: 1. open-source LLMs on Gaudi, 2. OpenAI models via API calls.
We make it convenient to launch the whole system with docker compose, which includes microservices for LLM, agents, UI, retrieval tool, vector database, dataprep, and telemetry. There are 3 docker compose files, which make it easy for users to pick and choose. Users can choose a different retrieval tool other than the `DocIndexRetriever` example provided in our GenAIExamples repo. Users can choose not to launch the telemetry containers. #### Gaudi
#### Launch on Gaudi On Gaudi, `meta-llama/Meta-Llama-3.1-70B-Instruct` will be served using vllm.
By default, both the RAG agent and SQL agent will be launched to support the React Agent.
The React Agent requires the DocIndexRetriever's [`compose.yaml`](../DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml) file, so two `compose.yaml` files need to be run with docker compose to start the multi-agent system.
On Gaudi, `meta-llama/Meta-Llama-3.3-70B-Instruct` will be served using vllm. The command below will launch the multi-agent system with the `DocIndexRetriever` as the retrieval tool for the Worker RAG agent. > **Note**: To enable the web search tool, skip this step and proceed to the "[Optional] Web Search Tool Support" section.
```bash ```bash
cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/hpu/gaudi/ cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/hpu/gaudi/
docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml -f compose.yaml up -d docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml -f compose.yaml up -d
``` ```
> **Note**: To enable the web search tool, skip this step and proceed to the "[Optional] Web Search Tool Support" section.
To enable Open Telemetry Tracing, compose.telemetry.yaml file need to be merged along with default compose.yaml file.
Gaudi example with Open Telemetry feature:
```bash
cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/hpu/gaudi/
docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml -f compose.yaml -f compose.telemetry.yaml up -d
```
##### [Optional] Web Search Tool Support ##### [Optional] Web Search Tool Support
<details> <details>
<summary> Instructions </summary> <summary> Instructions </summary>
A web search tool is supported in this example and can be enabled by running docker compose with the `compose.webtool.yaml` file. A web search tool is supported in this example and can be enabled by running docker compose with the `compose.webtool.yaml` file.
The Google Search API is used. Follow the [instructions](https://python.langchain.com/docs/integrations/tools/google_search) to create an API key and enable the Custom Search API on a Google account. The environment variables `GOOGLE_CSE_ID` and `GOOGLE_API_KEY` need to be set. The Google Search API is used. Follow the [instructions](https://python.langchain.com/docs/integrations/tools/google_search) to create an API key and enable the Custom Search API on a Google account. The environment variables `GOOGLE_CSE_ID` and `GOOGLE_API_KEY` need to be set.
```bash ```bash
@@ -194,40 +167,19 @@ docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/
</details> </details>
#### Launch on Xeon #### Xeon
On Xeon, OpenAI models and models deployed on a remote server are supported. Both methods require an API key. On Xeon, only OpenAI models are supported.
By default, both the RAG Agent and SQL Agent will be launched to support the React Agent.
The React Agent requires the DocIndexRetriever's [`compose.yaml`](../DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml) file, so two `compose yaml` files need to be run with docker compose to start the multi-agent system.
```bash ```bash
export OPENAI_API_KEY=<your-openai-key> export OPENAI_API_KEY=<your-openai-key>
cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/cpu/xeon cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/cpu/xeon
```
##### OpenAI Models
The command below will launch the multi-agent system with the `DocIndexRetriever` as the retrieval tool for the Worker RAG agent.
```bash
docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml -f compose_openai.yaml up -d docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml -f compose_openai.yaml up -d
``` ```
##### Models on Remote Server ### 4. Ingest Data into the vector database
When models are deployed on a remote server with Intel® AI for Enterprise Inference, a base URL and an API key are required to access them. To run the Agent microservice on Xeon while using models deployed on a remote server, add `compose_remote.yaml` to the `docker compose` command and set additional environment variables.
###### Notes
- `OPENAI_API_KEY` is already set in a previous step.
- `model` is used to overwrite the value set for this environment variable in `set_env.sh`.
- `LLM_ENDPOINT_URL` is the base URL given from the owner of the on-prem machine or cloud service provider. It will follow this format: "https://<DNS>". Here is an example: "https://api.inference.example.com".
```bash
export model=<name-of-model-card>
export LLM_ENDPOINT_URL=<http-endpoint-of-remote-server>
docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml -f compose_openai.yaml -f compose_remote.yaml up -d
```
### 3. Ingest Data into the vector database
The `run_ingest_data.sh` script will use an example jsonl file to ingest example documents into a vector database. Other ways to ingest data and other types of documents supported can be found in the OPEA dataprep microservice located in the opea-project/GenAIComps repo. The `run_ingest_data.sh` script will use an example jsonl file to ingest example documents into a vector database. Other ways to ingest data and other types of documents supported can be found in the OPEA dataprep microservice located in the opea-project/GenAIComps repo.
@@ -238,25 +190,11 @@ bash run_ingest_data.sh
> **Note**: This is a one-time operation. > **Note**: This is a one-time operation.
## How to interact with the agent system with UI ## Launch the UI
The UI microservice is launched in the previous step with the other microservices. Open a web browser to http://localhost:5173 to access the UI. Ensure the environment variable `AGENT_URL` is set to http://$ip_address:9090/v1/chat/completions in [ui/svelte/.env](./ui/svelte/.env) or else the UI may not work properly.
To see the UI, open a web browser to `http://${ip_address}:5173` to access the UI. Note the `ip_address` here is the host IP of the UI microservice.
1. Click on the arrow above `Get started`. Create an admin account with a name, email, and password. The AgentQnA UI can be deployed locally or using Docker. To customize deployment, refer to the [AgentQnA UI Guide](./ui/svelte/README.md).
2. Add an OpenAI-compatible API endpoint. In the upper right, click on the circle button with the user's initial, go to `Admin Settings`->`Connections`. Under `Manage OpenAI API Connections`, click on the `+` to add a connection. Fill in these fields:
- **URL**: `http://${ip_address}:9090/v1`, do not forget the `v1`
- **Key**: any value
- **Model IDs**: any name i.e. `opea-agent`, then press `+` to add it
Click "Save".
![opea-agent-setting](assets/img/opea-agent-setting.png)
3. Test OPEA agent with UI. Return to `New Chat` and ensure the model (i.e. `opea-agent`) is selected near the upper left. Enter in any prompt to interact with the agent.
![opea-agent-test](assets/img/opea-agent-test.png)
## [Optional] Deploy using Helm Charts ## [Optional] Deploy using Helm Charts
@@ -295,8 +233,3 @@ python $WORKDIR/GenAIExamples/AgentQnA/tests/test.py --agent_role "supervisor" -
## How to register other tools with the AI agent ## How to register other tools with the AI agent
The [tools](./tools) folder contains YAML and Python files for additional tools for the supervisor and worker agents. Refer to the "Provide your own tools" section in the instructions [here](https://github.com/opea-project/GenAIComps/tree/main/comps/agent/src/README.md) to add tools and customize the AI agents. The [tools](./tools) folder contains YAML and Python files for additional tools for the supervisor and worker agents. Refer to the "Provide your own tools" section in the instructions [here](https://github.com/opea-project/GenAIComps/tree/main/comps/agent/src/README.md) to add tools and customize the AI agents.
## Monitor and Tracing
Follow [OpenTelemetry OPEA Guide](https://opea-project.github.io/latest/tutorial/OpenTelemetry/OpenTelemetry_OPEA_Guide.html) to understand how to use OpenTelemetry tracing and metrics in OPEA.
For AgentQnA specific tracing and metrics monitoring, follow [OpenTelemetry on AgentQnA](https://opea-project.github.io/latest/tutorial/OpenTelemetry/deploy/AgentQnA.html) section.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

View File

@@ -1,342 +1,101 @@
# Build Mega Service of AgentQnA on AMD ROCm GPU # Single node on-prem deployment with Docker Compose on AMD GPU
## Build Docker Images This example showcases a hierarchical multi-agent system for question-answering applications. We deploy the example on Xeon. For LLMs, we use OpenAI models via API calls. For instructions on using open-source LLMs, please refer to the deployment guide [here](../../../../README.md).
### 1. Build Docker Image ## Deployment with docker
- #### Create application install directory and go to it: 1. First, clone this repo.
```
export WORKDIR=<your-work-directory>
cd $WORKDIR
git clone https://github.com/opea-project/GenAIExamples.git
```
2. Set up environment for this example </br>
```bash ```
mkdir ~/agentqna-install && cd agentqna-install # Example: host_ip="192.168.1.1" or export host_ip="External_Public_IP"
``` export host_ip=$(hostname -I | awk '{print $1}')
# if you are in a proxy environment, also set the proxy-related environment variables
export http_proxy="Your_HTTP_Proxy"
export https_proxy="Your_HTTPs_Proxy"
# Example: no_proxy="localhost, 127.0.0.1, 192.168.1.1"
export no_proxy="Your_No_Proxy"
- #### Clone the repository GenAIExamples (the default repository branch "main" is used here): export TOOLSET_PATH=$WORKDIR/GenAIExamples/AgentQnA/tools/
#OPANAI_API_KEY if you want to use OpenAI models
export OPENAI_API_KEY=<your-openai-key>
# Set AMD GPU settings
export AGENTQNA_CARD_ID="card1"
export AGENTQNA_RENDER_ID="renderD136"
```
```bash 3. Deploy the retrieval tool (i.e., DocIndexRetriever mega-service)
git clone https://github.com/opea-project/GenAIExamples.git
```
If you need to use a specific branch/tag of the GenAIExamples repository, then (v1.3 replace with its own value): First, launch the mega-service.
```bash ```
git clone https://github.com/opea-project/GenAIExamples.git && cd GenAIExamples && git checkout v1.3 cd $WORKDIR/GenAIExamples/AgentQnA/retrieval_tool
``` bash launch_retrieval_tool.sh
```
We remind you that when using a specific version of the code, you need to use the README from this version: Then, ingest data into the vector database. Here we provide an example. You can ingest your own data.
- #### Go to build directory: ```
bash run_ingest_data.sh
```
```bash 4. Launch Tool service
cd ~/agentqna-install/GenAIExamples/AgentQnA/docker_image_build In this example, we will use some of the mock APIs provided in the Meta CRAG KDD Challenge to demonstrate the benefits of gaining additional context from mock knowledge graphs.
``` ```
docker run -d -p=8080:8000 docker.io/aicrowd/kdd-cup-24-crag-mock-api:v0
```
5. Launch `Agent` service
- Cleaning up the GenAIComps repository if it was previously cloned in this directory. ```
This is necessary if the build was performed earlier and the GenAIComps folder exists and is not empty: cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/amd/gpu/rocm
bash launch_agent_service_tgi_rocm.sh
```
```bash 6. [Optional] Build `Agent` docker image if pulling images failed.
echo Y | rm -R GenAIComps
```
- #### Clone the repository GenAIComps (the default repository branch "main" is used here): ```
git clone https://github.com/opea-project/GenAIComps.git
cd GenAIComps
docker build -t opea/agent:latest -f comps/agent/src/Dockerfile .
```
```bash ## Validate services
git clone https://github.com/opea-project/GenAIComps.git
First look at logs of the agent docker containers:
```
# worker agent
docker logs rag-agent-endpoint
``` ```
We remind you that when using a specific version of the code, you need to use the README from this version. ```
# supervisor agent
- #### Setting the list of images for the build (from the build file.yaml) docker logs react-agent-endpoint
If you want to deploy a vLLM-based or TGI-based application, then the set of services is installed as follows:
#### vLLM-based application
```bash
service_list="vllm-rocm agent agent-ui"
```
#### TGI-based application
```bash
service_list="agent agent-ui"
```
- #### Optional. Pull TGI Docker Image (Do this if you want to use TGI)
```bash
docker pull ghcr.io/huggingface/text-generation-inference:2.3.1-rocm
```
- #### Build Docker Images
```bash
docker compose -f build.yaml build ${service_list} --no-cache
```
- #### Build DocIndexRetriever Docker Images
```bash
cd ~/agentqna-install/GenAIExamples/DocIndexRetriever/docker_image_build/
git clone https://github.com/opea-project/GenAIComps.git
service_list="doc-index-retriever dataprep embedding retriever reranking"
docker compose -f build.yaml build ${service_list} --no-cache
```
- #### Pull DocIndexRetriever Docker Images
```bash
docker pull redis/redis-stack:7.2.0-v9
docker pull ghcr.io/huggingface/text-embeddings-inference:cpu-1.5
```
After the build, we check the list of images with the command:
```bash
docker image ls
```
The list of images should include:
##### vLLM-based application:
- opea/vllm-rocm:latest
- opea/agent:latest
- redis/redis-stack:7.2.0-v9
- ghcr.io/huggingface/text-embeddings-inference:cpu-1.5
- opea/embedding:latest
- opea/retriever:latest
- opea/reranking:latest
- opea/doc-index-retriever:latest
##### TGI-based application:
- ghcr.io/huggingface/text-generation-inference:2.3.1-rocm
- opea/agent:latest
- redis/redis-stack:7.2.0-v9
- ghcr.io/huggingface/text-embeddings-inference:cpu-1.5
- opea/embedding:latest
- opea/retriever:latest
- opea/reranking:latest
- opea/doc-index-retriever:latest
---
## Deploy the AgentQnA Application
### Docker Compose Configuration for AMD GPUs
To enable GPU support for AMD GPUs, the following configuration is added to the Docker Compose file:
- compose_vllm.yaml - for vLLM-based application
- compose.yaml - for TGI-based
```yaml
shm_size: 1g
devices:
- /dev/kfd:/dev/kfd
- /dev/dri:/dev/dri
cap_add:
- SYS_PTRACE
group_add:
- video
security_opt:
- seccomp:unconfined
``` ```
This configuration forwards all available GPUs to the container. To use a specific GPU, specify its `cardN` and `renderN` device IDs. For example: You should see something like "HTTP server setup successful" if the docker containers are started successfully.</p>
```yaml Second, validate worker agent:
shm_size: 1g
devices: ```
- /dev/kfd:/dev/kfd curl http://${host_ip}:9095/v1/chat/completions -X POST -H "Content-Type: application/json" -d '{
- /dev/dri/card0:/dev/dri/card0 "query": "Most recent album by Taylor Swift"
- /dev/dri/render128:/dev/dri/render128 }'
cap_add:
- SYS_PTRACE
group_add:
- video
security_opt:
- seccomp:unconfined
``` ```
**How to Identify GPU Device IDs:** Third, validate supervisor agent:
Use AMD GPU driver utilities to determine the correct `cardN` and `renderN` IDs for your GPU.
### Set deploy environment variables ```
curl http://${host_ip}:9090/v1/chat/completions -X POST -H "Content-Type: application/json" -d '{
#### Setting variables in the operating system environment: "query": "Most recent album by Taylor Swift"
}'
```bash
### Replace the string 'server_address' with your local server IP address
export host_ip='server_address'
### Replace the string 'your_huggingfacehub_token' with your HuggingFacehub repository access token.
export HUGGINGFACEHUB_API_TOKEN='your_huggingfacehub_token'
### Replace the string 'your_langchain_api_key' with your LANGCHAIN API KEY.
export LANGCHAIN_API_KEY='your_langchain_api_key'
export LANGCHAIN_TRACING_V2=""
``` ```
### Start the services: ## How to register your own tools with agent
#### If you use vLLM You can take a look at the tools yaml and python files in this example. For more details, please refer to the "Provide your own tools" section in the instructions [here](https://github.com/opea-project/GenAIComps/tree/main/comps/agent/src/README.md).
```bash
cd ~/agentqna-install/GenAIExamples/AgentQnA/docker_compose/amd/gpu/rocm
bash launch_agent_service_vllm_rocm.sh
```
#### If you use TGI
```bash
cd ~/agentqna-install/GenAIExamples/AgentQnA/docker_compose/amd/gpu/rocm
bash launch_agent_service_tgi_rocm.sh
```
All containers should be running and should not restart:
##### If you use vLLM:
- dataprep-redis-server
- doc-index-retriever-server
- embedding-server
- rag-agent-endpoint
- react-agent-endpoint
- redis-vector-db
- reranking-tei-xeon-server
- retriever-redis-server
- sql-agent-endpoint
- tei-embedding-server
- tei-reranking-server
- vllm-service
##### If you use TGI:
- dataprep-redis-server
- doc-index-retriever-server
- embedding-server
- rag-agent-endpoint
- react-agent-endpoint
- redis-vector-db
- reranking-tei-xeon-server
- retriever-redis-server
- sql-agent-endpoint
- tei-embedding-server
- tei-reranking-server
- tgi-service
---
## Validate the Services
### 1. Validate the vLLM/TGI Service
#### If you use vLLM:
```bash
DATA='{"model": "Intel/neural-chat-7b-v3-3t", '\
'"messages": [{"role": "user", "content": "What is Deep Learning?"}], "max_tokens": 256}'
curl http://${HOST_IP}:${VLLM_SERVICE_PORT}/v1/chat/completions \
-X POST \
-d "$DATA" \
-H 'Content-Type: application/json'
```
Checking the response from the service. The response should be similar to JSON:
```json
{
"id": "chatcmpl-142f34ef35b64a8db3deedd170fed951",
"object": "chat.completion",
"created": 1742270316,
"model": "Intel/neural-chat-7b-v3-3",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "",
"tool_calls": []
},
"logprobs": null,
"finish_reason": "length",
"stop_reason": null
}
],
"usage": { "prompt_tokens": 66, "total_tokens": 322, "completion_tokens": 256, "prompt_tokens_details": null },
"prompt_logprobs": null
}
```
If the service response has a meaningful response in the value of the "choices.message.content" key,
then we consider the vLLM service to be successfully launched
#### If you use TGI:
```bash
DATA='{"inputs":"What is Deep Learning?",'\
'"parameters":{"max_new_tokens":256,"do_sample": true}}'
curl http://${HOST_IP}:${TGI_SERVICE_PORT}/generate \
-X POST \
-d "$DATA" \
-H 'Content-Type: application/json'
```
Checking the response from the service. The response should be similar to JSON:
```json
{
"generated_text": " "
}
```
If the service response has a meaningful response in the value of the "generated_text" key,
then we consider the TGI service to be successfully launched
### 2. Validate Agent Services
#### Validate Rag Agent Service
```bash
export agent_port=${WORKER_RAG_AGENT_PORT}
prompt="Tell me about Michael Jackson song Thriller"
python3 ~/agentqna-install/GenAIExamples/AgentQnA/tests/test.py --prompt "$prompt" --agent_role "worker" --ext_port $agent_port
```
The response must contain the meaningful text of the response to the request from the "prompt" variable
#### Validate Sql Agent Service
```bash
export agent_port=${WORKER_SQL_AGENT_PORT}
prompt="How many employees are there in the company?"
python3 ~/agentqna-install/GenAIExamples/AgentQnA/tests/test.py --prompt "$prompt" --agent_role "worker" --ext_port $agent_port
```
The answer should make sense - "8 employees in the company"
#### Validate React (Supervisor) Agent Service
```bash
export agent_port=${SUPERVISOR_REACT_AGENT_PORT}
python3 ~/agentqna-install/GenAIExamples/AgentQnA/tests/test.py --agent_role "supervisor" --ext_port $agent_port --stream
```
The response should contain "Iron Maiden"
### 3. Stop application
#### If you use vLLM
```bash
cd ~/agentqna-install/GenAIExamples/AgentQnA/docker_compose/amd/gpu/rocm
bash stop_agent_service_vllm_rocm.sh
```
#### If you use TGI
```bash
cd ~/agentqna-install/GenAIExamples/AgentQnA/docker_compose/amd/gpu/rocm
bash stop_agent_service_tgi_rocm.sh
```

View File

@@ -1,24 +1,26 @@
# Copyright (C) 2025 Advanced Micro Devices, Inc. # Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
services: services:
tgi-service: agent-tgi-server:
image: ghcr.io/huggingface/text-generation-inference:3.0.0-rocm image: ${AGENTQNA_TGI_IMAGE}
container_name: tgi-service container_name: agent-tgi-server
ports: ports:
- "${TGI_SERVICE_PORT-8085}:80" - "${AGENTQNA_TGI_SERVICE_PORT-8085}:80"
volumes: volumes:
- "${MODEL_CACHE:-./data}:/data" - ${HF_CACHE_DIR:-/var/opea/agent-service/}:/data
environment: environment:
no_proxy: ${no_proxy} no_proxy: ${no_proxy}
http_proxy: ${http_proxy} http_proxy: ${http_proxy}
https_proxy: ${https_proxy} https_proxy: ${https_proxy}
TGI_LLM_ENDPOINT: "http://${ip_address}:${TGI_SERVICE_PORT}" TGI_LLM_ENDPOINT: "http://${HOST_IP}:${AGENTQNA_TGI_SERVICE_PORT}"
HUGGING_FACE_HUB_TOKEN: ${HUGGINGFACEHUB_API_TOKEN} HUGGING_FACE_HUB_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN} HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
shm_size: 32g shm_size: 1g
devices: devices:
- /dev/kfd:/dev/kfd - /dev/kfd:/dev/kfd
- /dev/dri:/dev/dri - /dev/dri/${AGENTQNA_CARD_ID}:/dev/dri/${AGENTQNA_CARD_ID}
- /dev/dri/${AGENTQNA_RENDER_ID}:/dev/dri/${AGENTQNA_RENDER_ID}
cap_add: cap_add:
- SYS_PTRACE - SYS_PTRACE
group_add: group_add:
@@ -29,17 +31,17 @@ services:
command: --model-id ${LLM_MODEL_ID} --max-input-length 4096 --max-total-tokens 8192 command: --model-id ${LLM_MODEL_ID} --max-input-length 4096 --max-total-tokens 8192
worker-rag-agent: worker-rag-agent:
image: ${REGISTRY:-opea}/agent:${TAG:-latest} image: opea/agent:latest
container_name: rag-agent-endpoint container_name: rag-agent-endpoint
volumes: volumes:
- "${TOOLSET_PATH}:/home/user/tools/" # - ${WORKDIR}/GenAIExamples/AgentQnA/docker_image_build/GenAIComps/comps/agent/langchain/:/home/user/comps/agent/langchain/
- ${TOOLSET_PATH}:/home/user/tools/
ports: ports:
- "${WORKER_RAG_AGENT_PORT:-9095}:9095" - "9095:9095"
ipc: host ipc: host
environment: environment:
ip_address: ${ip_address} ip_address: ${ip_address}
strategy: rag_agent_llama strategy: rag_agent_llama
with_memory: false
recursion_limit: ${recursion_limit_worker} recursion_limit: ${recursion_limit_worker}
llm_engine: tgi llm_engine: tgi
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN} HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
@@ -59,49 +61,21 @@ services:
LANGCHAIN_PROJECT: "opea-worker-agent-service" LANGCHAIN_PROJECT: "opea-worker-agent-service"
port: 9095 port: 9095
worker-sql-agent:
image: ${REGISTRY:-opea}/agent:${TAG:-latest}
container_name: sql-agent-endpoint
volumes:
- "${WORKDIR}/tests/Chinook_Sqlite.sqlite:/home/user/chinook-db/Chinook_Sqlite.sqlite:rw"
ports:
- "${WORKER_SQL_AGENT_PORT:-9096}:9096"
ipc: host
environment:
ip_address: ${ip_address}
strategy: sql_agent_llama
with_memory: false
db_name: ${db_name}
db_path: ${db_path}
use_hints: false
recursion_limit: ${recursion_limit_worker}
llm_engine: vllm
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
llm_endpoint_url: ${LLM_ENDPOINT_URL}
model: ${LLM_MODEL_ID}
temperature: ${temperature}
max_new_tokens: ${max_new_tokens}
stream: false
require_human_feedback: false
no_proxy: ${no_proxy}
http_proxy: ${http_proxy}
https_proxy: ${https_proxy}
port: 9096
supervisor-react-agent: supervisor-react-agent:
image: ${REGISTRY:-opea}/agent:${TAG:-latest} image: opea/agent:latest
container_name: react-agent-endpoint container_name: react-agent-endpoint
depends_on: depends_on:
- agent-tgi-server
- worker-rag-agent - worker-rag-agent
volumes: volumes:
- "${TOOLSET_PATH}:/home/user/tools/" # - ${WORKDIR}/GenAIExamples/AgentQnA/docker_image_build/GenAIComps/comps/agent/langchain/:/home/user/comps/agent/langchain/
- ${TOOLSET_PATH}:/home/user/tools/
ports: ports:
- "${SUPERVISOR_REACT_AGENT_PORT:-9090}:9090" - "${AGENTQNA_FRONTEND_PORT}:9090"
ipc: host ipc: host
environment: environment:
ip_address: ${ip_address} ip_address: ${ip_address}
strategy: react_llama strategy: react_langgraph
with_memory: true
recursion_limit: ${recursion_limit_supervisor} recursion_limit: ${recursion_limit_supervisor}
llm_engine: tgi llm_engine: tgi
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN} HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
@@ -109,7 +83,7 @@ services:
model: ${LLM_MODEL_ID} model: ${LLM_MODEL_ID}
temperature: ${temperature} temperature: ${temperature}
max_new_tokens: ${max_new_tokens} max_new_tokens: ${max_new_tokens}
stream: true stream: false
tools: /home/user/tools/supervisor_agent_tools.yaml tools: /home/user/tools/supervisor_agent_tools.yaml
require_human_feedback: false require_human_feedback: false
no_proxy: ${no_proxy} no_proxy: ${no_proxy}
@@ -118,7 +92,6 @@ services:
LANGCHAIN_API_KEY: ${LANGCHAIN_API_KEY} LANGCHAIN_API_KEY: ${LANGCHAIN_API_KEY}
LANGCHAIN_TRACING_V2: ${LANGCHAIN_TRACING_V2} LANGCHAIN_TRACING_V2: ${LANGCHAIN_TRACING_V2}
LANGCHAIN_PROJECT: "opea-supervisor-agent-service" LANGCHAIN_PROJECT: "opea-supervisor-agent-service"
CRAG_SERVER: ${CRAG_SERVER} CRAG_SERVER: $CRAG_SERVER
WORKER_AGENT_URL: ${WORKER_AGENT_URL} WORKER_AGENT_URL: $WORKER_AGENT_URL
SQL_AGENT_URL: ${SQL_AGENT_URL}
port: 9090 port: 9090

View File

@@ -1,128 +0,0 @@
# Copyright (C) 2025 Advanced Micro Devices, Inc.
services:
vllm-service:
image: ${REGISTRY:-opea}/vllm-rocm:${TAG:-latest}
container_name: vllm-service
ports:
- "${VLLM_SERVICE_PORT:-8081}:8011"
environment:
no_proxy: ${no_proxy}
http_proxy: ${http_proxy}
https_proxy: ${https_proxy}
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
HF_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
HF_HUB_DISABLE_PROGRESS_BARS: 1
HF_HUB_ENABLE_HF_TRANSFER: 0
WILM_USE_TRITON_FLASH_ATTENTION: 0
PYTORCH_JIT: 0
volumes:
- "${MODEL_CACHE:-./data}:/data"
shm_size: 20G
devices:
- /dev/kfd:/dev/kfd
- /dev/dri/:/dev/dri/
cap_add:
- SYS_PTRACE
group_add:
- video
security_opt:
- seccomp:unconfined
- apparmor=unconfined
command: "--model ${VLLM_LLM_MODEL_ID} --swap-space 16 --disable-log-requests --dtype float16 --tensor-parallel-size 4 --host 0.0.0.0 --port 8011 --num-scheduler-steps 1 --distributed-executor-backend \"mp\""
ipc: host
worker-rag-agent:
image: ${REGISTRY:-opea}/agent:${TAG:-latest}
container_name: rag-agent-endpoint
volumes:
- ${TOOLSET_PATH}:/home/user/tools/
ports:
- "${WORKER_RAG_AGENT_PORT:-9095}:9095"
ipc: host
environment:
ip_address: ${ip_address}
strategy: rag_agent_llama
with_memory: false
recursion_limit: ${recursion_limit_worker}
llm_engine: vllm
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
llm_endpoint_url: ${LLM_ENDPOINT_URL}
model: ${LLM_MODEL_ID}
temperature: ${temperature}
max_new_tokens: ${max_new_tokens}
stream: false
tools: /home/user/tools/worker_agent_tools.yaml
require_human_feedback: false
RETRIEVAL_TOOL_URL: ${RETRIEVAL_TOOL_URL}
no_proxy: ${no_proxy}
http_proxy: ${http_proxy}
https_proxy: ${https_proxy}
LANGCHAIN_API_KEY: ${LANGCHAIN_API_KEY}
LANGCHAIN_TRACING_V2: ${LANGCHAIN_TRACING_V2}
LANGCHAIN_PROJECT: "opea-worker-agent-service"
port: 9095
worker-sql-agent:
image: ${REGISTRY:-opea}/agent:${TAG:-latest}
container_name: sql-agent-endpoint
volumes:
- "${WORKDIR}/tests/Chinook_Sqlite.sqlite:/home/user/chinook-db/Chinook_Sqlite.sqlite:rw"
ports:
- "${WORKER_SQL_AGENT_PORT:-9096}:9096"
ipc: host
environment:
ip_address: ${ip_address}
strategy: sql_agent_llama
with_memory: false
db_name: ${db_name}
db_path: ${db_path}
use_hints: false
recursion_limit: ${recursion_limit_worker}
llm_engine: vllm
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
llm_endpoint_url: ${LLM_ENDPOINT_URL}
model: ${LLM_MODEL_ID}
temperature: ${temperature}
max_new_tokens: ${max_new_tokens}
stream: false
require_human_feedback: false
no_proxy: ${no_proxy}
http_proxy: ${http_proxy}
https_proxy: ${https_proxy}
port: 9096
supervisor-react-agent:
image: ${REGISTRY:-opea}/agent:${TAG:-latest}
container_name: react-agent-endpoint
depends_on:
- worker-rag-agent
volumes:
- ${TOOLSET_PATH}:/home/user/tools/
ports:
- "${SUPERVISOR_REACT_AGENT_PORT:-9090}:9090"
ipc: host
environment:
ip_address: ${ip_address}
strategy: react_llama
with_memory: true
recursion_limit: ${recursion_limit_supervisor}
llm_engine: vllm
HUGGINGFACEHUB_API_TOKEN: ${HUGGINGFACEHUB_API_TOKEN}
llm_endpoint_url: ${LLM_ENDPOINT_URL}
model: ${LLM_MODEL_ID}
temperature: ${temperature}
max_new_tokens: ${max_new_tokens}
stream: true
tools: /home/user/tools/supervisor_agent_tools.yaml
require_human_feedback: false
no_proxy: ${no_proxy}
http_proxy: ${http_proxy}
https_proxy: ${https_proxy}
LANGCHAIN_API_KEY: ${LANGCHAIN_API_KEY}
LANGCHAIN_TRACING_V2: ${LANGCHAIN_TRACING_V2}
LANGCHAIN_PROJECT: "opea-supervisor-agent-service"
CRAG_SERVER: ${CRAG_SERVER}
WORKER_AGENT_URL: ${WORKER_AGENT_URL}
SQL_AGENT_URL: ${SQL_AGENT_URL}
port: 9090

View File

@@ -1,87 +1,47 @@
# Copyright (C) 2024 Advanced Micro Devices, Inc. # Copyright (C) 2024 Advanced Micro Devices, Inc.
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# Before start script: WORKPATH=$(dirname "$PWD")/..
# export host_ip="your_host_ip_or_host_name"
# export HUGGINGFACEHUB_API_TOKEN="your_huggingface_api_token"
# export LANGCHAIN_API_KEY="your_langchain_api_key"
# export LANGCHAIN_TRACING_V2=""
# Set server hostname or IP address
export ip_address=${host_ip} export ip_address=${host_ip}
export HUGGINGFACEHUB_API_TOKEN=${your_hf_api_token}
export AGENTQNA_TGI_IMAGE=ghcr.io/huggingface/text-generation-inference:2.3.1-rocm
export AGENTQNA_TGI_SERVICE_PORT="8085"
# Set services IP ports # LLM related environment variables
export TGI_SERVICE_PORT="18110" export AGENTQNA_CARD_ID="card1"
export WORKER_RAG_AGENT_PORT="18111" export AGENTQNA_RENDER_ID="renderD136"
export WORKER_SQL_AGENT_PORT="18112" export HF_CACHE_DIR=${HF_CACHE_DIR}
export SUPERVISOR_REACT_AGENT_PORT="18113" ls $HF_CACHE_DIR
export CRAG_SERVER_PORT="18114" export LLM_MODEL_ID="meta-llama/Meta-Llama-3-8B-Instruct"
#export NUM_SHARDS=4
export WORKPATH=$(dirname "$PWD") export LLM_ENDPOINT_URL="http://${ip_address}:${AGENTQNA_TGI_SERVICE_PORT}"
export WORKDIR=${WORKPATH}/../../../
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export LLM_MODEL_ID="Intel/neural-chat-7b-v3-3"
export HF_CACHE_DIR="./data"
export MODEL_CACHE="./data"
export TOOLSET_PATH=${WORKPATH}/../../../tools/
export recursion_limit_worker=12
export LLM_ENDPOINT_URL=http://${ip_address}:${TGI_SERVICE_PORT}
export temperature=0.01 export temperature=0.01
export max_new_tokens=512 export max_new_tokens=512
export RETRIEVAL_TOOL_URL="http://${ip_address}:8889/v1/retrievaltool"
export LANGCHAIN_API_KEY=${LANGCHAIN_API_KEY} # agent related environment variables
export LANGCHAIN_TRACING_V2=${LANGCHAIN_TRACING_V2} export AGENTQNA_WORKER_AGENT_SERVICE_PORT="9095"
export db_name=Chinook export TOOLSET_PATH=/home/huggingface/datamonsters/amd-opea/GenAIExamples/AgentQnA/tools/
export db_path="sqlite:////home/user/chinook-db/Chinook_Sqlite.sqlite" echo "TOOLSET_PATH=${TOOLSET_PATH}"
export recursion_limit_worker=12 export recursion_limit_worker=12
export recursion_limit_supervisor=10 export recursion_limit_supervisor=10
export CRAG_SERVER=http://${ip_address}:${CRAG_SERVER_PORT} export WORKER_AGENT_URL="http://${ip_address}:${AGENTQNA_WORKER_AGENT_SERVICE_PORT}/v1/chat/completions"
export WORKER_AGENT_URL="http://${ip_address}:${WORKER_RAG_AGENT_PORT}/v1/chat/completions" export RETRIEVAL_TOOL_URL="http://${ip_address}:8889/v1/retrievaltool"
export SQL_AGENT_URL="http://${ip_address}:${WORKER_SQL_AGENT_PORT}/v1/chat/completions" export CRAG_SERVER=http://${ip_address}:18881
export HF_CACHE_DIR=${HF_CACHE_DIR}
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN} export AGENTQNA_FRONTEND_PORT="9090"
export no_proxy=${no_proxy}
export http_proxy=${http_proxy} #retrieval_tool
export https_proxy=${https_proxy}
export EMBEDDING_MODEL_ID="BAAI/bge-base-en-v1.5"
export RERANK_MODEL_ID="BAAI/bge-reranker-base"
export TEI_EMBEDDING_ENDPOINT="http://${host_ip}:6006" export TEI_EMBEDDING_ENDPOINT="http://${host_ip}:6006"
export TEI_RERANKING_ENDPOINT="http://${host_ip}:8808" export TEI_RERANKING_ENDPOINT="http://${host_ip}:8808"
export REDIS_URL="redis://${host_ip}:6379" export REDIS_URL="redis://${host_ip}:26379"
export INDEX_NAME="rag-redis" export INDEX_NAME="rag-redis"
export RERANK_TYPE="tei"
export MEGA_SERVICE_HOST_IP=${host_ip} export MEGA_SERVICE_HOST_IP=${host_ip}
export EMBEDDING_SERVICE_HOST_IP=${host_ip} export EMBEDDING_SERVICE_HOST_IP=${host_ip}
export RETRIEVER_SERVICE_HOST_IP=${host_ip} export RETRIEVER_SERVICE_HOST_IP=${host_ip}
export RERANK_SERVICE_HOST_IP=${host_ip} export RERANK_SERVICE_HOST_IP=${host_ip}
export BACKEND_SERVICE_ENDPOINT="http://${host_ip}:8889/v1/retrievaltool" export BACKEND_SERVICE_ENDPOINT="http://${host_ip}:8889/v1/retrievaltool"
export DATAPREP_SERVICE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/ingest" export DATAPREP_SERVICE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/ingest"
export DATAPREP_GET_FILE_ENDPOINT="http://${host_ip}:6008/v1/dataprep/get" export DATAPREP_GET_FILE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/get"
export DATAPREP_DELETE_FILE_ENDPOINT="http://${host_ip}:6009/v1/dataprep/delete" export DATAPREP_DELETE_FILE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/delete"
echo ${WORKER_RAG_AGENT_PORT} > ${WORKPATH}/WORKER_RAG_AGENT_PORT_tmp
echo ${WORKER_SQL_AGENT_PORT} > ${WORKPATH}/WORKER_SQL_AGENT_PORT_tmp
echo ${SUPERVISOR_REACT_AGENT_PORT} > ${WORKPATH}/SUPERVISOR_REACT_AGENT_PORT_tmp
echo ${CRAG_SERVER_PORT} > ${WORKPATH}/CRAG_SERVER_PORT_tmp
echo "Downloading chinook data..."
echo Y | rm -R chinook-database
git clone https://github.com/lerocha/chinook-database.git
echo Y | rm -R ../../../../../AgentQnA/tests/Chinook_Sqlite.sqlite
cp chinook-database/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite ../../../../../AgentQnA/tests
docker compose -f ../../../../../DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml up -d
docker compose -f compose.yaml up -d docker compose -f compose.yaml up -d
n=0
until [[ "$n" -ge 100 ]]; do
docker logs tgi-service > ${WORKPATH}/tgi_service_start.log
if grep -q Connected ${WORKPATH}/tgi_service_start.log; then
break
fi
sleep 10s
n=$((n+1))
done
echo "Starting CRAG server"
docker run -d --runtime=runc --name=kdd-cup-24-crag-service -p=${CRAG_SERVER_PORT}:8000 docker.io/aicrowd/kdd-cup-24-crag-mock-api:v0

View File

@@ -1,88 +0,0 @@
# Copyright (C) 2024 Advanced Micro Devices, Inc.
# SPDX-License-Identifier: Apache-2.0
# Before start script:
# export host_ip="your_host_ip_or_host_name"
# export HUGGINGFACEHUB_API_TOKEN="your_huggingface_api_token"
# export LANGCHAIN_API_KEY="your_langchain_api_key"
# export LANGCHAIN_TRACING_V2=""
# Set server hostname or IP address
export ip_address=${host_ip}
# Set services IP ports
export VLLM_SERVICE_PORT="18110"
export WORKER_RAG_AGENT_PORT="18111"
export WORKER_SQL_AGENT_PORT="18112"
export SUPERVISOR_REACT_AGENT_PORT="18113"
export CRAG_SERVER_PORT="18114"
export WORKPATH=$(dirname "$PWD")
export WORKDIR=${WORKPATH}/../../../
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export VLLM_LLM_MODEL_ID="Intel/neural-chat-7b-v3-3"
export HF_CACHE_DIR="./data"
export MODEL_CACHE="./data"
export TOOLSET_PATH=${WORKPATH}/../../../tools/
export recursion_limit_worker=12
export LLM_ENDPOINT_URL=http://${ip_address}:${VLLM_SERVICE_PORT}
export LLM_MODEL_ID=${VLLM_LLM_MODEL_ID}
export temperature=0.01
export max_new_tokens=512
export RETRIEVAL_TOOL_URL="http://${ip_address}:8889/v1/retrievaltool"
export LANGCHAIN_API_KEY=${LANGCHAIN_API_KEY}
export LANGCHAIN_TRACING_V2=${LANGCHAIN_TRACING_V2}
export db_name=Chinook
export db_path="sqlite:////home/user/chinook-db/Chinook_Sqlite.sqlite"
export recursion_limit_worker=12
export recursion_limit_supervisor=10
export CRAG_SERVER=http://${ip_address}:${CRAG_SERVER_PORT}
export WORKER_AGENT_URL="http://${ip_address}:${WORKER_RAG_AGENT_PORT}/v1/chat/completions"
export SQL_AGENT_URL="http://${ip_address}:${WORKER_SQL_AGENT_PORT}/v1/chat/completions"
export HF_CACHE_DIR=${HF_CACHE_DIR}
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export no_proxy=${no_proxy}
export http_proxy=${http_proxy}
export https_proxy=${https_proxy}
export EMBEDDING_MODEL_ID="BAAI/bge-base-en-v1.5"
export RERANK_MODEL_ID="BAAI/bge-reranker-base"
export TEI_EMBEDDING_ENDPOINT="http://${host_ip}:6006"
export TEI_RERANKING_ENDPOINT="http://${host_ip}:8808"
export REDIS_URL="redis://${host_ip}:6379"
export INDEX_NAME="rag-redis"
export RERANK_TYPE="tei"
export MEGA_SERVICE_HOST_IP=${host_ip}
export EMBEDDING_SERVICE_HOST_IP=${host_ip}
export RETRIEVER_SERVICE_HOST_IP=${host_ip}
export RERANK_SERVICE_HOST_IP=${host_ip}
export BACKEND_SERVICE_ENDPOINT="http://${host_ip}:8889/v1/retrievaltool"
export DATAPREP_SERVICE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/ingest"
export DATAPREP_GET_FILE_ENDPOINT="http://${host_ip}:6008/v1/dataprep/get"
export DATAPREP_DELETE_FILE_ENDPOINT="http://${host_ip}:6009/v1/dataprep/delete"
echo ${WORKER_RAG_AGENT_PORT} > ${WORKPATH}/WORKER_RAG_AGENT_PORT_tmp
echo ${WORKER_SQL_AGENT_PORT} > ${WORKPATH}/WORKER_SQL_AGENT_PORT_tmp
echo ${SUPERVISOR_REACT_AGENT_PORT} > ${WORKPATH}/SUPERVISOR_REACT_AGENT_PORT_tmp
echo ${CRAG_SERVER_PORT} > ${WORKPATH}/CRAG_SERVER_PORT_tmp
echo "Downloading chinook data..."
echo Y | rm -R chinook-database
git clone https://github.com/lerocha/chinook-database.git
echo Y | rm -R ../../../../../AgentQnA/tests/Chinook_Sqlite.sqlite
cp chinook-database/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite ../../../../../AgentQnA/tests
docker compose -f ../../../../../DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml up -d
docker compose -f compose_vllm.yaml up -d
n=0
until [[ "$n" -ge 500 ]]; do
docker logs vllm-service >& "${WORKPATH}"/vllm-service_start.log
if grep -q "Application startup complete" "${WORKPATH}"/vllm-service_start.log; then
break
fi
sleep 20s
n=$((n+1))
done
echo "Starting CRAG server"
docker run -d --runtime=runc --name=kdd-cup-24-crag-service -p=${CRAG_SERVER_PORT}:8000 docker.io/aicrowd/kdd-cup-24-crag-mock-api:v0

View File

@@ -6,7 +6,7 @@
WORKPATH=$(dirname "$PWD")/.. WORKPATH=$(dirname "$PWD")/..
export ip_address=${host_ip} export ip_address=${host_ip}
export HUGGINGFACEHUB_API_TOKEN=${your_hf_api_token} export HUGGINGFACEHUB_API_TOKEN=${your_hf_api_token}
export AGENTQNA_TGI_IMAGE=ghcr.io/huggingface/text-generation-inference:2.4.1-rocm export AGENTQNA_TGI_IMAGE=ghcr.io/huggingface/text-generation-inference:2.3.1-rocm
export AGENTQNA_TGI_SERVICE_PORT="19001" export AGENTQNA_TGI_SERVICE_PORT="19001"
# LLM related environment variables # LLM related environment variables
@@ -14,7 +14,7 @@ export AGENTQNA_CARD_ID="card1"
export AGENTQNA_RENDER_ID="renderD136" export AGENTQNA_RENDER_ID="renderD136"
export HF_CACHE_DIR=${HF_CACHE_DIR} export HF_CACHE_DIR=${HF_CACHE_DIR}
ls $HF_CACHE_DIR ls $HF_CACHE_DIR
export LLM_MODEL_ID="Intel/neural-chat-7b-v3-3" export LLM_MODEL_ID="meta-llama/Meta-Llama-3-8B-Instruct"
export NUM_SHARDS=4 export NUM_SHARDS=4
export LLM_ENDPOINT_URL="http://${ip_address}:${AGENTQNA_TGI_SERVICE_PORT}" export LLM_ENDPOINT_URL="http://${ip_address}:${AGENTQNA_TGI_SERVICE_PORT}"
export temperature=0.01 export temperature=0.01
@@ -44,19 +44,3 @@ export BACKEND_SERVICE_ENDPOINT="http://${host_ip}:8889/v1/retrievaltool"
export DATAPREP_SERVICE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/ingest" export DATAPREP_SERVICE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/ingest"
export DATAPREP_GET_FILE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/get" export DATAPREP_GET_FILE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/get"
export DATAPREP_DELETE_FILE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/delete" export DATAPREP_DELETE_FILE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/delete"
echo "Removing chinook data..."
echo Y | rm -R chinook-database
if [ -d "chinook-database" ]; then
rm -rf chinook-database
fi
echo "Chinook data removed!"
echo "Stopping CRAG server"
docker rm kdd-cup-24-crag-service --force
echo "Stopping Agent services"
docker compose -f compose.yaml down
echo "Stopping Retrieval services"
docker compose -f ../../../../../DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml down

View File

@@ -1,84 +0,0 @@
# Copyright (C) 2024 Advanced Micro Devices, Inc.
# SPDX-License-Identifier: Apache-2.0
# Before start script:
# export host_ip="your_host_ip_or_host_name"
# export HUGGINGFACEHUB_API_TOKEN="your_huggingface_api_token"
# export LANGCHAIN_API_KEY="your_langchain_api_key"
# export LANGCHAIN_TRACING_V2=""
# Set server hostname or IP address
export ip_address=${host_ip}
# Set services IP ports
export VLLM_SERVICE_PORT="18110"
export WORKER_RAG_AGENT_PORT="18111"
export WORKER_SQL_AGENT_PORT="18112"
export SUPERVISOR_REACT_AGENT_PORT="18113"
export CRAG_SERVER_PORT="18114"
export WORKPATH=$(dirname "$PWD")
export WORKDIR=${WORKPATH}/../../../
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export VLLM_LLM_MODEL_ID="Intel/neural-chat-7b-v3-3"
export HF_CACHE_DIR="./data"
export MODEL_CACHE="./data"
export TOOLSET_PATH=${WORKPATH}/../../../tools/
export recursion_limit_worker=12
export LLM_ENDPOINT_URL=http://${ip_address}:${VLLM_SERVICE_PORT}
export LLM_MODEL_ID=${VLLM_LLM_MODEL_ID}
export temperature=0.01
export max_new_tokens=512
export RETRIEVAL_TOOL_URL="http://${ip_address}:8889/v1/retrievaltool"
export LANGCHAIN_API_KEY=${LANGCHAIN_API_KEY}
export LANGCHAIN_TRACING_V2=${LANGCHAIN_TRACING_V2}
export db_name=Chinook
export db_path="sqlite:////home/user/chinook-db/Chinook_Sqlite.sqlite"
export recursion_limit_worker=12
export recursion_limit_supervisor=10
export CRAG_SERVER=http://${ip_address}:${CRAG_SERVER_PORT}
export WORKER_AGENT_URL="http://${ip_address}:${WORKER_RAG_AGENT_PORT}/v1/chat/completions"
export SQL_AGENT_URL="http://${ip_address}:${WORKER_SQL_AGENT_PORT}/v1/chat/completions"
export HF_CACHE_DIR=${HF_CACHE_DIR}
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export no_proxy=${no_proxy}
export http_proxy=${http_proxy}
export https_proxy=${https_proxy}
export EMBEDDING_MODEL_ID="BAAI/bge-base-en-v1.5"
export RERANK_MODEL_ID="BAAI/bge-reranker-base"
export TEI_EMBEDDING_ENDPOINT="http://${host_ip}:6006"
export TEI_RERANKING_ENDPOINT="http://${host_ip}:8808"
export REDIS_URL="redis://${host_ip}:6379"
export INDEX_NAME="rag-redis"
export RERANK_TYPE="tei"
export MEGA_SERVICE_HOST_IP=${host_ip}
export EMBEDDING_SERVICE_HOST_IP=${host_ip}
export RETRIEVER_SERVICE_HOST_IP=${host_ip}
export RERANK_SERVICE_HOST_IP=${host_ip}
export BACKEND_SERVICE_ENDPOINT="http://${host_ip}:8889/v1/retrievaltool"
export DATAPREP_SERVICE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/ingest"
export DATAPREP_GET_FILE_ENDPOINT="http://${host_ip}:6008/v1/dataprep/get"
export DATAPREP_DELETE_FILE_ENDPOINT="http://${host_ip}:6009/v1/dataprep/delete"
echo ${WORKER_RAG_AGENT_PORT} > ${WORKPATH}/WORKER_RAG_AGENT_PORT_tmp
echo ${WORKER_SQL_AGENT_PORT} > ${WORKPATH}/WORKER_SQL_AGENT_PORT_tmp
echo ${SUPERVISOR_REACT_AGENT_PORT} > ${WORKPATH}/SUPERVISOR_REACT_AGENT_PORT_tmp
echo ${CRAG_SERVER_PORT} > ${WORKPATH}/CRAG_SERVER_PORT_tmp
echo "Removing chinook data..."
echo Y | rm -R chinook-database
if [ -d "chinook-database" ]; then
rm -rf chinook-database
fi
echo "Chinook data removed!"
echo "Stopping CRAG server"
docker rm kdd-cup-24-crag-service --force
echo "Stopping Agent services"
docker compose -f compose_vllm.yaml down
echo "Stopping Retrieval services"
docker compose -f ../../../../../DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml down

View File

@@ -103,8 +103,10 @@ services:
agent-ui: agent-ui:
image: opea/agent-ui image: opea/agent-ui
container_name: agent-ui container_name: agent-ui
volumes:
- ${WORKDIR}/GenAIExamples/AgentQnA/ui/svelte/.env:/home/user/svelte/.env # test db
ports: ports:
- "5173:8080" - "5173:5173"
ipc: host ipc: host
networks: networks:

View File

@@ -1,18 +0,0 @@
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
services:
worker-rag-agent:
environment:
llm_endpoint_url: ${LLM_ENDPOINT_URL}
api_key: ${OPENAI_API_KEY}
worker-sql-agent:
environment:
llm_endpoint_url: ${LLM_ENDPOINT_URL}
api_key: ${OPENAI_API_KEY}
supervisor-react-agent:
environment:
llm_endpoint_url: ${LLM_ENDPOINT_URL}
api_key: ${OPENAI_API_KEY}

View File

@@ -1,93 +0,0 @@
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
services:
tei-embedding-service:
command: --model-id ${EMBEDDING_MODEL_ID} --auto-truncate --otlp-endpoint $OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
tei-reranking-service:
command: --model-id ${RERANK_MODEL_ID} --auto-truncate --otlp-endpoint $OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
jaeger:
image: jaegertracing/all-in-one:1.67.0
container_name: jaeger
ports:
- "16686:16686"
- "4317:4317"
- "4318:4318"
- "9411:9411"
ipc: host
environment:
no_proxy: ${no_proxy}
http_proxy: ${http_proxy}
https_proxy: ${https_proxy}
COLLECTOR_ZIPKIN_HOST_PORT: 9411
restart: unless-stopped
prometheus:
image: prom/prometheus:v2.52.0
container_name: prometheus
user: root
volumes:
- ./prometheus.yaml:/etc/prometheus/prometheus.yaml
- ./prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yaml'
ports:
- '9091:9090'
ipc: host
restart: unless-stopped
grafana:
image: grafana/grafana:11.0.0
container_name: grafana
volumes:
- ./grafana_data:/var/lib/grafana
- ./grafana/dashboards:/var/lib/grafana/dashboards
- ./grafana/provisioning:/etc/grafana/provisioning
user: root
environment:
GF_SECURITY_ADMIN_PASSWORD: admin
GF_RENDERING_CALLBACK_URL: http://grafana:3000/
GF_LOG_FILTERS: rendering:debug
depends_on:
- prometheus
ports:
- '3000:3000'
ipc: host
restart: unless-stopped
node-exporter:
image: prom/node-exporter
container_name: node-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- --collector.filesystem.ignored-mount-points
- "^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)"
ports:
- 9100:9100
restart: always
deploy:
mode: global
gaudi-exporter:
image: vault.habana.ai/gaudi-metric-exporter/metric-exporter:1.19.2-32
container_name: gaudi-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
- /dev:/dev
ports:
- 41612:41611
restart: always
deploy:
mode: global
worker-rag-agent:
environment:
- TELEMETRY_ENDPOINT=${TELEMETRY_ENDPOINT}
worker-sql-agent:
environment:
- TELEMETRY_ENDPOINT=${TELEMETRY_ENDPOINT}
supervisor-react-agent:
environment:
- TELEMETRY_ENDPOINT=${TELEMETRY_ENDPOINT}

View File

@@ -3,7 +3,7 @@
services: services:
worker-rag-agent: worker-rag-agent:
image: ${REGISTRY:-opea}/agent:${TAG:-latest} image: opea/agent:latest
container_name: rag-agent-endpoint container_name: rag-agent-endpoint
volumes: volumes:
- ${TOOLSET_PATH}:/home/user/tools/ - ${TOOLSET_PATH}:/home/user/tools/
@@ -34,7 +34,7 @@ services:
port: 9095 port: 9095
worker-sql-agent: worker-sql-agent:
image: ${REGISTRY:-opea}/agent:${TAG:-latest} image: opea/agent:latest
container_name: sql-agent-endpoint container_name: sql-agent-endpoint
volumes: volumes:
- ${WORKDIR}/GenAIExamples/AgentQnA/tests:/home/user/chinook-db # test db - ${WORKDIR}/GenAIExamples/AgentQnA/tests:/home/user/chinook-db # test db
@@ -63,7 +63,7 @@ services:
port: 9096 port: 9096
supervisor-react-agent: supervisor-react-agent:
image: ${REGISTRY:-opea}/agent:${TAG:-latest} image: opea/agent:latest
container_name: react-agent-endpoint container_name: react-agent-endpoint
depends_on: depends_on:
- worker-rag-agent - worker-rag-agent
@@ -104,12 +104,14 @@ services:
- "8080:8000" - "8080:8000"
ipc: host ipc: host
agent-ui: agent-ui:
image: ${REGISTRY:-opea}/agent-ui:${TAG:-latest} image: opea/agent-ui
container_name: agent-ui container_name: agent-ui
volumes:
- ${WORKDIR}/GenAIExamples/AgentQnA/ui/svelte/.env:/home/user/svelte/.env
environment: environment:
host_ip: ${host_ip} host_ip: ${host_ip}
ports: ports:
- "5173:8080" - "5173:5173"
ipc: host ipc: host
vllm-service: vllm-service:
image: ${REGISTRY:-opea}/vllm-gaudi:${TAG:-latest} image: ${REGISTRY:-opea}/vllm-gaudi:${TAG:-latest}
@@ -117,7 +119,7 @@ services:
ports: ports:
- "8086:8000" - "8086:8000"
volumes: volumes:
- "${MODEL_CACHE:-./data}:/data" - "./data:/data"
environment: environment:
no_proxy: ${no_proxy} no_proxy: ${no_proxy}
http_proxy: ${http_proxy} http_proxy: ${http_proxy}
@@ -138,4 +140,4 @@ services:
cap_add: cap_add:
- SYS_NICE - SYS_NICE
ipc: host ipc: host
command: --model $LLM_MODEL_ID --tensor-parallel-size 4 --host 0.0.0.0 --port 8000 --block-size 128 --max-num-seqs 256 --max-seq-len-to-capture 16384 command: --model $LLM_MODEL_ID --tensor-parallel-size 4 --host 0.0.0.0 --port 8000 --block-size 128 --max-num-seqs 256 --max-seq_len-to-capture 16384

View File

@@ -1,10 +0,0 @@
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
rm *.json
wget https://raw.githubusercontent.com/opea-project/GenAIEval/refs/heads/main/evals/benchmark/grafana/chatqna_megaservice_grafana.json
mv chatqna_megaservice_grafana.json agentqna_microervices_grafana.json
wget https://raw.githubusercontent.com/opea-project/GenAIEval/refs/heads/main/evals/benchmark/grafana/vllm_grafana.json
wget https://raw.githubusercontent.com/opea-project/GenAIEval/refs/heads/main/evals/benchmark/grafana/tgi_grafana.json
wget https://raw.githubusercontent.com/opea-project/GenAIEval/refs/heads/main/evals/benchmark/grafana/node_grafana.json
wget https://raw.githubusercontent.com/opea-project/GenAIEval/refs/heads/main/evals/benchmark/grafana/gaudi_grafana.json

View File

@@ -1,14 +0,0 @@
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: ''
type: file
disableDeletion: false
updateIntervalSeconds: 10 #how often Grafana will scan for changed dashboards
options:
path: /var/lib/grafana/dashboards

View File

@@ -1,54 +0,0 @@
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
# config file version
apiVersion: 1
# list of datasources that should be deleted from the database
deleteDatasources:
- name: Prometheus
orgId: 1
# list of datasources to insert/update depending
# what's available in the database
datasources:
# <string, required> name of the datasource. Required
- name: Prometheus
# <string, required> datasource type. Required
type: prometheus
# <string, required> access mode. direct or proxy. Required
access: proxy
# <int> org id. will default to orgId 1 if not specified
orgId: 1
# <string> url
url: http://prometheus:9090
# <string> database password, if used
password:
# <string> database user, if used
user:
# <string> database name, if used
database:
# <bool> enable/disable basic auth
basicAuth: false
# <string> basic auth username, if used
basicAuthUser:
# <string> basic auth password, if used
basicAuthPassword:
# <bool> enable/disable with credentials headers
withCredentials:
# <bool> mark as default datasource. Max one per org
isDefault: true
# <map> fields that will be converted to json and stored in json_data
jsonData:
httpMethod: GET
graphiteVersion: "1.1"
tlsAuth: false
tlsAuthWithCACert: false
# <string> json object of data that will be encrypted.
secureJsonData:
tlsCACert: "..."
tlsClientCert: "..."
tlsClientKey: "..."
version: 1
# <bool> allow users to edit datasources from the UI.
editable: true

View File

@@ -1,55 +0,0 @@
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
global:
scrape_interval: 5s
external_labels:
monitor: "my-monitor"
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["prometheus:9090"]
- job_name: "vllm"
metrics_path: /metrics
static_configs:
- targets: ["vllm-gaudi-server:8000"]
- job_name: "tgi"
metrics_path: /metrics
static_configs:
- targets: ["tgi-gaudi-server:80"]
- job_name: "tei-embedding"
metrics_path: /metrics
static_configs:
- targets: ["tei-embedding-server:80"]
- job_name: "tei-reranking"
metrics_path: /metrics
static_configs:
- targets: ["tei-reranking-server:80"]
- job_name: "retriever"
metrics_path: /metrics
static_configs:
- targets: ["retriever:7000"]
- job_name: "dataprep-redis-service"
metrics_path: /metrics
static_configs:
- targets: ["dataprep-redis-service:5000"]
- job_name: "prometheus-node-exporter"
metrics_path: /metrics
static_configs:
- targets: ["node-exporter:9100"]
- job_name: "prometheus-gaudi-exporter"
metrics_path: /metrics
static_configs:
- targets: ["gaudi-exporter:41611"]
- job_name: "supervisor-react-agent"
metrics_path: /metrics
static_configs:
- targets: ["react-agent-endpoint:9090"]
- job_name: "worker-rag-agent"
metrics_path: /metrics
static_configs:
- targets: ["rag-agent-endpoint:9095"]
- job_name: "worker-sql-agent"
metrics_path: /metrics
static_configs:
- targets: ["sql-agent-endpoint:9096"]

View File

@@ -42,7 +42,7 @@ if [ ! -f $WORKDIR/GenAIExamples/AgentQnA/tests/Chinook_Sqlite.sqlite ]; then
fi fi
# configure agent ui # configure agent ui
# echo "AGENT_URL = 'http://$ip_address:9090/v1/chat/completions'" | tee ${WORKDIR}/GenAIExamples/AgentQnA/ui/svelte/.env echo "AGENT_URL = 'http://$ip_address:9090/v1/chat/completions'" | tee ${WORKDIR}/GenAIExamples/AgentQnA/ui/svelte/.env
# retriever # retriever
export host_ip=$(hostname -I | awk '{print $1}') export host_ip=$(hostname -I | awk '{print $1}')
@@ -64,9 +64,6 @@ export BACKEND_SERVICE_ENDPOINT="http://${host_ip}:8889/v1/retrievaltool"
export DATAPREP_SERVICE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/ingest" export DATAPREP_SERVICE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/ingest"
export DATAPREP_GET_FILE_ENDPOINT="http://${host_ip}:6008/v1/dataprep/get" export DATAPREP_GET_FILE_ENDPOINT="http://${host_ip}:6008/v1/dataprep/get"
export DATAPREP_DELETE_FILE_ENDPOINT="http://${host_ip}:6009/v1/dataprep/delete" export DATAPREP_DELETE_FILE_ENDPOINT="http://${host_ip}:6009/v1/dataprep/delete"
# Set OpenTelemetry Tracing Endpoint
export JAEGER_IP=$(ip route get 8.8.8.8 | grep -oP 'src \K[^ ]+')
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=grpc://$JAEGER_IP:4317
export TELEMETRY_ENDPOINT=http://$JAEGER_IP:4318/v1/traces
export no_proxy="$no_proxy,rag-agent-endpoint,sql-agent-endpoint,react-agent-endpoint,agent-ui,vllm-gaudi-server,jaeger,grafana,prometheus,node-exporter,gaudi-exporter,127.0.0.1,localhost,0.0.0.0,$host_ip,,$JAEGER_IP"
export no_proxy="$no_proxy,rag-agent-endpoint,sql-agent-endpoint,react-agent-endpoint,agent-ui,vllm-gaudi-server,jaeger,grafana,prometheus,127.0.0.1,localhost,0.0.0.0,$host_ip"

View File

@@ -3,7 +3,7 @@
services: services:
tgi-server: tgi-server:
image: ghcr.io/huggingface/tgi-gaudi:2.3.1 image: ghcr.io/huggingface/tgi-gaudi:2.0.6
container_name: tgi-server container_name: tgi-server
ports: ports:
- "8085:80" - "8085:80"

View File

@@ -17,15 +17,3 @@ services:
dockerfile: ./docker/Dockerfile dockerfile: ./docker/Dockerfile
extends: agent extends: agent
image: ${REGISTRY:-opea}/agent-ui:${TAG:-latest} image: ${REGISTRY:-opea}/agent-ui:${TAG:-latest}
vllm-gaudi:
build:
context: vllm-fork
dockerfile: Dockerfile.hpu
extends: agent
image: ${REGISTRY:-opea}/vllm-gaudi:${TAG:-latest}
vllm-rocm:
build:
context: GenAIComps
dockerfile: comps/third_parties/vllm/src/Dockerfile.amd_gpu
extends: agent
image: ${REGISTRY:-opea}/vllm-rocm:${TAG:-latest}

View File

@@ -1,22 +0,0 @@
# Copyright (C) 2025 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
tgi:
enabled: false
vllm:
enabled: true
LLM_MODEL_ID: "meta-llama/Meta-Llama-3-8B-Instruct"
extraCmdArgs: ["--max-seq-len-to-capture", "16384", "--enable-auto-tool-choice", "--tool-call-parser", "llama3_json"]
supervisor:
llm_endpoint_url: http://{{ .Release.Name }}-vllm
llm_engine: vllm
model: "meta-llama/Meta-Llama-3-8B-Instruct"
ragagent:
llm_endpoint_url: http://{{ .Release.Name }}-vllm
llm_engine: vllm
model: "meta-llama/Meta-Llama-3-8B-Instruct"
sqlagent:
llm_endpoint_url: http://{{ .Release.Name }}-vllm
llm_engine: vllm
model: "meta-llama/Meta-Llama-3-8B-Instruct"

View File

@@ -4,32 +4,13 @@
# Accelerate inferencing in heaviest components to improve performance # Accelerate inferencing in heaviest components to improve performance
# by overriding their subchart values # by overriding their subchart values
tgi:
enabled: false
vllm: vllm:
enabled: true enabled: true
accelDevice: "gaudi"
image: image:
repository: opea/vllm-gaudi repository: opea/vllm-gaudi
resources:
limits:
habana.ai/gaudi: 4
LLM_MODEL_ID: "meta-llama/Llama-3.3-70B-Instruct"
OMPI_MCA_btl_vader_single_copy_mechanism: none
PT_HPU_ENABLE_LAZY_COLLECTIVES: true
VLLM_SKIP_WARMUP: true
shmSize: 16Gi
extraCmdArgs: ["--tensor-parallel-size", "4", "--max-seq-len-to-capture", "16384", "--enable-auto-tool-choice", "--tool-call-parser", "llama3_json"]
supervisor: supervisor:
llm_endpoint_url: http://{{ .Release.Name }}-vllm llm_endpoint_url: http://{{ .Release.Name }}-vllm
llm_engine: vllm
model: "meta-llama/Llama-3.3-70B-Instruct"
ragagent: ragagent:
llm_endpoint_url: http://{{ .Release.Name }}-vllm llm_endpoint_url: http://{{ .Release.Name }}-vllm
llm_engine: vllm
model: "meta-llama/Llama-3.3-70B-Instruct"
sqlagent: sqlagent:
llm_endpoint_url: http://{{ .Release.Name }}-vllm llm_endpoint_url: http://{{ .Release.Name }}-vllm
llm_engine: vllm
model: "meta-llama/Llama-3.3-70B-Instruct"

View File

@@ -1,22 +1,7 @@
# Copyright (C) 2024 Intel Corporation # Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
host_ip=$(hostname -I | awk '{print $1}')
port=6007
FILEDIR=${WORKDIR}/GenAIExamples/AgentQnA/example_data/ FILEDIR=${WORKDIR}/GenAIExamples/AgentQnA/example_data/
FILENAME=test_docs_music.jsonl FILENAME=test_docs_music.jsonl
# AgentQnA ingestion script requires following packages python3 index_data.py --filedir ${FILEDIR} --filename ${FILENAME} --host_ip $host_ip
packages=("requests" "tqdm")
# Check if packages are installed
for package in "${packages[@]}"; do
if pip freeze | grep -q "$package="; then
echo "$package is installed"
else
echo "$package is not installed"
pip install --no-cache-dir "$package"
fi
done
python3 index_data.py --filedir ${FILEDIR} --filename ${FILENAME} --host_ip $host_ip --port $port

View File

@@ -31,7 +31,7 @@ function stop_retrieval_tool() {
} }
echo "=================== #1 Building docker images====================" echo "=================== #1 Building docker images===================="
bash step1_build_images.sh xeon bash step1_build_images.sh
echo "=================== #1 Building docker images completed====================" echo "=================== #1 Building docker images completed===================="
echo "=================== #2 Start retrieval tool====================" echo "=================== #2 Start retrieval tool===================="

View File

@@ -15,52 +15,42 @@ function get_genai_comps() {
fi fi
} }
function build_docker_images_for_retrieval_tool(){ function build_docker_images_for_retrieval_tool(){
cd $WORKDIR/GenAIExamples/DocIndexRetriever/docker_image_build/ cd $WORKDIR/GenAIExamples/DocIndexRetriever/docker_image_build/
get_genai_comps get_genai_comps
echo "Build all the images with --no-cache..." echo "Build all the images with --no-cache..."
docker compose -f build.yaml build --no-cache service_list="doc-index-retriever dataprep embedding retriever reranking"
docker compose -f build.yaml build ${service_list} --no-cache
docker pull ghcr.io/huggingface/text-embeddings-inference:cpu-1.6
docker images && sleep 1s docker images && sleep 1s
} }
function build_agent_docker_image_xeon() { function build_agent_docker_image() {
cd $WORKDIR/GenAIExamples/AgentQnA/docker_image_build/ cd $WORKDIR/GenAIExamples/AgentQnA/docker_image_build/
get_genai_comps get_genai_comps
echo "Build agent image with --no-cache..." echo "Build agent image with --no-cache..."
service_list="agent agent-ui" docker compose -f build.yaml build --no-cache
docker compose -f build.yaml build ${service_list} --no-cache
} }
function build_agent_docker_image_gaudi_vllm() { function build_vllm_docker_image() {
cd $WORKDIR/GenAIExamples/AgentQnA/docker_image_build/ echo "Building the vllm docker image"
get_genai_comps cd $WORKPATH
echo $WORKPATH
git clone https://github.com/HabanaAI/vllm-fork.git && cd vllm-fork if [ ! -d "./vllm-fork" ]; then
VLLM_FORK_VER=v0.6.6.post1+Gaudi-1.20.0 git clone https://github.com/HabanaAI/vllm-fork.git
git checkout ${VLLM_FORK_VER} &> /dev/null && cd ../ fi
cd ./vllm-fork
echo "Build agent image with --no-cache..." VLLM_VER=$(git describe --tags "$(git rev-list --tags --max-count=1)")
service_list="agent agent-ui vllm-gaudi" git checkout ${VLLM_VER} &> /dev/null
docker compose -f build.yaml build ${service_list} --no-cache docker build --no-cache -f Dockerfile.hpu -t opea/vllm-gaudi:ci --shm-size=128g . --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy
} if [ $? -ne 0 ]; then
echo "opea/vllm-gaudi:ci failed"
function build_agent_docker_image_rocm() { exit 1
cd $WORKDIR/GenAIExamples/AgentQnA/docker_image_build/ else
get_genai_comps echo "opea/vllm-gaudi:ci successful"
fi
echo "Build agent image with --no-cache..."
service_list="agent agent-ui"
docker compose -f build.yaml build ${service_list} --no-cache
}
function build_agent_docker_image_rocm_vllm() {
cd $WORKDIR/GenAIExamples/AgentQnA/docker_image_build/
get_genai_comps
echo "Build agent image with --no-cache..."
service_list="agent agent-ui vllm-rocm"
docker compose -f build.yaml build ${service_list} --no-cache
} }
@@ -69,32 +59,15 @@ function main() {
build_docker_images_for_retrieval_tool build_docker_images_for_retrieval_tool
echo "==================== Build docker images for retrieval tool completed ====================" echo "==================== Build docker images for retrieval tool completed ===================="
sleep 3s echo "==================== Build agent docker image ===================="
build_agent_docker_image
echo "==================== Build agent docker image completed ===================="
case $1 in echo "==================== Build vllm docker image ===================="
"rocm") build_vllm_docker_image
echo "==================== Build agent docker image for ROCm ====================" echo "==================== Build vllm docker image completed ===================="
build_agent_docker_image_rocm
;;
"rocm_vllm")
echo "==================== Build agent docker image for ROCm VLLM ===================="
build_agent_docker_image_rocm_vllm
;;
"gaudi_vllm")
echo "==================== Build agent docker image for Gaudi ===================="
build_agent_docker_image_gaudi_vllm
;;
"xeon")
echo "==================== Build agent docker image for Xeon ===================="
build_agent_docker_image_xeon
;;
*)
echo "Invalid argument"
exit 1
;;
esac
docker image ls | grep vllm docker image ls | grep vllm
} }
main $1 main

View File

@@ -1,49 +0,0 @@
#!/bin/bash
# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
set -e
WORKPATH=$(dirname "$PWD")
export WORKDIR=$WORKPATH/../
echo "WORKDIR=${WORKDIR}"
export ip_address=$(hostname -I | awk '{print $1}')
export host_ip=${ip_address}
export HF_CACHE_DIR=$WORKPATH/hf_cache
if [ ! -d "$HF_CACHE_DIR" ]; then
echo "Creating HF_CACHE directory"
mkdir -p "$HF_CACHE_DIR"
fi
function start_retrieval_tool() {
echo "Starting Retrieval tool"
cd $WORKPATH/../DocIndexRetriever/docker_compose/intel/cpu/xeon
host_ip=$(hostname -I | awk '{print $1}')
export HF_CACHE_DIR=${HF_CACHE_DIR}
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export no_proxy=${no_proxy}
export http_proxy=${http_proxy}
export https_proxy=${https_proxy}
export EMBEDDING_MODEL_ID="BAAI/bge-base-en-v1.5"
export RERANK_MODEL_ID="BAAI/bge-reranker-base"
export TEI_EMBEDDING_ENDPOINT="http://${host_ip}:6006"
export TEI_RERANKING_ENDPOINT="http://${host_ip}:8808"
export REDIS_URL="redis://${host_ip}:6379"
export INDEX_NAME="rag-redis"
export RERANK_TYPE="tei"
export MEGA_SERVICE_HOST_IP=${host_ip}
export EMBEDDING_SERVICE_HOST_IP=${host_ip}
export RETRIEVER_SERVICE_HOST_IP=${host_ip}
export RERANK_SERVICE_HOST_IP=${host_ip}
export BACKEND_SERVICE_ENDPOINT="http://${host_ip}:8889/v1/retrievaltool"
export DATAPREP_SERVICE_ENDPOINT="http://${host_ip}:6007/v1/dataprep/ingest"
export DATAPREP_GET_FILE_ENDPOINT="http://${host_ip}:6008/v1/dataprep/get"
export DATAPREP_DELETE_FILE_ENDPOINT="http://${host_ip}:6009/v1/dataprep/delete"
docker compose -f compose.yaml up -d
}
echo "==================== Start retrieval tool ===================="
start_retrieval_tool
sleep 20 # needed for downloading the models
echo "==================== Retrieval tool started ===================="

View File

@@ -1,68 +0,0 @@
#!/bin/bash
# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
set -e
WORKPATH=$(dirname "$PWD")
export WORKDIR=$WORKPATH/../../
echo "WORKDIR=${WORKDIR}"
export ip_address=$(hostname -I | awk '{print $1}')
export host_ip=$ip_address
echo "ip_address=${ip_address}"
function validate() {
local CONTENT="$1"
local EXPECTED_RESULT="$2"
local SERVICE_NAME="$3"
if echo "$CONTENT" | grep -q "$EXPECTED_RESULT"; then
echo "[ $SERVICE_NAME ] Content is as expected: $CONTENT"
echo 0
else
echo "[ $SERVICE_NAME ] Content does not match the expected result: $CONTENT"
echo 1
fi
}
function ingest_data_and_validate() {
echo "Ingesting data"
cd $WORKPATH/retrieval_tool/
echo $PWD
local CONTENT=$(bash run_ingest_data.sh)
local EXIT_CODE=$(validate "$CONTENT" "Data preparation succeeded" "dataprep-redis-server")
echo "$EXIT_CODE"
local EXIT_CODE="${EXIT_CODE:0-1}"
echo "return value is $EXIT_CODE"
if [ "$EXIT_CODE" == "1" ]; then
docker logs dataprep-redis-server
return 1
fi
}
function validate_retrieval_tool() {
echo "----------------Test retrieval tool ----------------"
local CONTENT=$(http_proxy="" curl http://${ip_address}:8889/v1/retrievaltool -X POST -H "Content-Type: application/json" -d '{
"text": "Who sang Thriller"
}')
local EXIT_CODE=$(validate "$CONTENT" "Thriller" "retrieval-tool")
if [ "$EXIT_CODE" == "1" ]; then
docker logs retrievaltool-xeon-backend-server
exit 1
fi
}
function main(){
echo "==================== Ingest data ===================="
ingest_data_and_validate
echo "==================== Data ingestion completed ===================="
echo "==================== Validate retrieval tool ===================="
validate_retrieval_tool
echo "==================== Retrieval tool validated ===================="
}
main

View File

@@ -8,8 +8,6 @@ WORKPATH=$(dirname "$PWD")
export WORKDIR=$WORKPATH/../../ export WORKDIR=$WORKPATH/../../
echo "WORKDIR=${WORKDIR}" echo "WORKDIR=${WORKDIR}"
export ip_address=$(hostname -I | awk '{print $1}') export ip_address=$(hostname -I | awk '{print $1}')
export host_ip=$ip_address
echo "ip_address=${ip_address}"
export TOOLSET_PATH=$WORKPATH/tools/ export TOOLSET_PATH=$WORKPATH/tools/
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN} export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
HF_TOKEN=${HUGGINGFACEHUB_API_TOKEN} HF_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
@@ -26,12 +24,12 @@ ls $HF_CACHE_DIR
vllm_port=8086 vllm_port=8086
vllm_volume=${HF_CACHE_DIR} vllm_volume=${HF_CACHE_DIR}
function start_tgi(){
function start_agent_service() { echo "Starting tgi-gaudi server"
echo "Starting agent service"
cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/hpu/gaudi cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/hpu/gaudi
source set_env.sh source set_env.sh
docker compose -f compose.yaml up -d docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml -f compose.yaml tgi_gaudi.yaml up -d
} }
function start_all_services() { function start_all_services() {
@@ -42,7 +40,7 @@ function start_all_services() {
echo "**************model is $model**************" echo "**************model is $model**************"
cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/hpu/gaudi cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/intel/hpu/gaudi
source set_env.sh source set_env.sh
docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml -f compose.yaml -f compose.telemetry.yaml up -d docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml -f compose.yaml up -d
sleep 5s sleep 5s
echo "Waiting vllm gaudi ready" echo "Waiting vllm gaudi ready"
n=0 n=0
@@ -71,6 +69,7 @@ function download_chinook_data(){
cp chinook-database/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite $WORKDIR/GenAIExamples/AgentQnA/tests/ cp chinook-database/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite $WORKDIR/GenAIExamples/AgentQnA/tests/
} }
function validate() { function validate() {
local CONTENT="$1" local CONTENT="$1"
local EXPECTED_RESULT="$2" local EXPECTED_RESULT="$2"
@@ -139,6 +138,24 @@ function remove_chinook_data(){
echo "Chinook data removed!" echo "Chinook data removed!"
} }
export host_ip=$ip_address
echo "ip_address=${ip_address}"
function validate() {
local CONTENT="$1"
local EXPECTED_RESULT="$2"
local SERVICE_NAME="$3"
if echo "$CONTENT" | grep -q "$EXPECTED_RESULT"; then
echo "[ $SERVICE_NAME ] Content is as expected: $CONTENT"
echo 0
else
echo "[ $SERVICE_NAME ] Content does not match the expected result: $CONTENT"
echo 1
fi
}
function ingest_data_and_validate() { function ingest_data_and_validate() {
echo "Ingesting data" echo "Ingesting data"
cd $WORKDIR/GenAIExamples/AgentQnA/retrieval_tool/ cd $WORKDIR/GenAIExamples/AgentQnA/retrieval_tool/

View File

@@ -1,120 +0,0 @@
#!/bin/bash
# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
set -e
WORKPATH=$(dirname "$PWD")
export LOG_PATH=${WORKPATH}
export WORKDIR=$WORKPATH/../../
echo "WORKDIR=${WORKDIR}"
export ip_address=$(hostname -I | awk '{print $1}')
export host_ip=${ip_address}
export TOOLSET_PATH=$WORKPATH/tools/
export HF_CACHE_DIR=$WORKPATH/data2/huggingface
if [ ! -d "$HF_CACHE_DIR" ]; then
HF_CACHE_DIR=$WORKDIR/hf_cache
mkdir -p "$HF_CACHE_DIR"
fi
function download_chinook_data(){
echo "Downloading chinook data..."
cd $WORKDIR
git clone https://github.com/lerocha/chinook-database.git
cp chinook-database/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite ${WORKPATH}/tests/
}
function start_agent_and_api_server() {
echo "Starting Agent services"
cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/amd/gpu/rocm
bash launch_agent_service_vllm_rocm.sh
}
function validate() {
local CONTENT="$1"
local EXPECTED_RESULT="$2"
local SERVICE_NAME="$3"
if echo "$CONTENT" | grep -q "$EXPECTED_RESULT"; then
echo "[ $SERVICE_NAME ] Content is as expected: $CONTENT"
echo 0
else
echo "[ $SERVICE_NAME ] Content does not match the expected result: $CONTENT"
echo 1
fi
}
function validate_agent_service() {
# # test worker rag agent
echo "======================Testing worker rag agent======================"
export agent_port=$(cat ${WORKPATH}/docker_compose/amd/gpu/WORKER_RAG_AGENT_PORT_tmp)
prompt="Tell me about Michael Jackson song Thriller"
local CONTENT=$(python3 $WORKDIR/GenAIExamples/AgentQnA/tests/test.py --prompt "$prompt" --agent_role "worker" --ext_port $agent_port)
# echo $CONTENT
local EXIT_CODE=$(validate "$CONTENT" "Thriller" "rag-agent-endpoint")
echo $EXIT_CODE
local EXIT_CODE="${EXIT_CODE:0-1}"
if [ "$EXIT_CODE" == "1" ]; then
docker logs rag-agent-endpoint
exit 1
fi
# test worker sql agent
echo "======================Testing worker sql agent======================"
export agent_port=$(cat ${WORKPATH}/docker_compose/amd/gpu/WORKER_SQL_AGENT_PORT_tmp)
prompt="How many employees are there in the company?"
local CONTENT=$(python3 $WORKDIR/GenAIExamples/AgentQnA/tests/test.py --prompt "$prompt" --agent_role "worker" --ext_port $agent_port)
local EXIT_CODE=$(validate "$CONTENT" "8" "sql-agent-endpoint")
echo $CONTENT
# echo $EXIT_CODE
local EXIT_CODE="${EXIT_CODE:0-1}"
if [ "$EXIT_CODE" == "1" ]; then
docker logs sql-agent-endpoint
exit 1
fi
# test supervisor react agent
echo "======================Testing supervisor react agent======================"
export agent_port=$(cat ${WORKPATH}/docker_compose/amd/gpu/SUPERVISOR_REACT_AGENT_PORT_tmp)
local CONTENT=$(python3 $WORKDIR/GenAIExamples/AgentQnA/tests/test.py --agent_role "supervisor" --ext_port $agent_port --stream)
local EXIT_CODE=$(validate "$CONTENT" "Iron" "react-agent-endpoint")
# echo $CONTENT
echo $EXIT_CODE
local EXIT_CODE="${EXIT_CODE:0-1}"
if [ "$EXIT_CODE" == "1" ]; then
docker logs react-agent-endpoint
exit 1
fi
}
function remove_chinook_data(){
echo "Removing chinook data..."
cd $WORKDIR
if [ -d "chinook-database" ]; then
rm -rf chinook-database
fi
echo "Chinook data removed!"
}
function main() {
echo "==================== Prepare data ===================="
download_chinook_data
echo "==================== Data prepare done ===================="
echo "==================== Start agent ===================="
start_agent_and_api_server
echo "==================== Agent started ===================="
echo "==================== Validate agent service ===================="
validate_agent_service
echo "==================== Agent service validated ===================="
}
remove_chinook_data
main
remove_chinook_data

View File

@@ -2,30 +2,26 @@
# Copyright (C) 2024 Intel Corporation # Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
set -e set -ex
WORKPATH=$(dirname "$PWD") WORKPATH=$(dirname "$PWD")
export LOG_PATH=${WORKPATH}
export WORKDIR=$WORKPATH/../../ export WORKDIR=$WORKPATH/../../
echo "WORKDIR=${WORKDIR}" echo "WORKDIR=${WORKDIR}"
export ip_address=$(hostname -I | awk '{print $1}') export ip_address=$(hostname -I | awk '{print $1}')
export host_ip=${ip_address} export TOOLSET_PATH=$WORKDIR/GenAIExamples/AgentQnA/tools/
export TOOLSET_PATH=$WORKPATH/tools/ export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export HF_CACHE_DIR=$WORKPATH/data2/huggingface export HF_CACHE_DIR=${model_cache:-"$WORKDIR/hf_cache"}
if [ ! -d "$HF_CACHE_DIR" ]; then if [ ! -d "$HF_CACHE_DIR" ]; then
HF_CACHE_DIR=$WORKDIR/hf_cache
mkdir -p "$HF_CACHE_DIR" mkdir -p "$HF_CACHE_DIR"
fi fi
ls $HF_CACHE_DIR
function download_chinook_data(){
echo "Downloading chinook data..."
cd $WORKDIR
git clone https://github.com/lerocha/chinook-database.git
cp chinook-database/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite ${WORKPATH}/tests/
}
function start_agent_and_api_server() { function start_agent_and_api_server() {
echo "Starting CRAG server"
docker run -d --runtime=runc --name=kdd-cup-24-crag-service -p=8080:8000 docker.io/aicrowd/kdd-cup-24-crag-mock-api:v0
echo "Starting Agent services" echo "Starting Agent services"
cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/amd/gpu/rocm cd $WORKDIR/GenAIExamples/AgentQnA/docker_compose/amd/gpu/rocm
bash launch_agent_service_tgi_rocm.sh bash launch_agent_service_tgi_rocm.sh
@@ -46,63 +42,28 @@ function validate() {
} }
function validate_agent_service() { function validate_agent_service() {
# # test worker rag agent echo "----------------Test agent ----------------"
echo "======================Testing worker rag agent======================" local CONTENT=$(http_proxy="" curl http://${ip_address}:9095/v1/chat/completions -X POST -H "Content-Type: application/json" -d '{
export agent_port=$(cat ${WORKPATH}/docker_compose/amd/gpu/WORKER_RAG_AGENT_PORT_tmp) "query": "Tell me about Michael Jackson song thriller"
prompt="Tell me about Michael Jackson song Thriller" }')
local CONTENT=$(python3 $WORKDIR/GenAIExamples/AgentQnA/tests/test.py --prompt "$prompt" --agent_role "worker" --ext_port $agent_port) local EXIT_CODE=$(validate "$CONTENT" "Thriller" "react-agent-endpoint")
# echo $CONTENT docker logs rag-agent-endpoint
local EXIT_CODE=$(validate "$CONTENT" "Thriller" "rag-agent-endpoint")
echo $EXIT_CODE
local EXIT_CODE="${EXIT_CODE:0-1}"
if [ "$EXIT_CODE" == "1" ]; then if [ "$EXIT_CODE" == "1" ]; then
docker logs rag-agent-endpoint
exit 1 exit 1
fi fi
# test worker sql agent local CONTENT=$(http_proxy="" curl http://${ip_address}:9090/v1/chat/completions -X POST -H "Content-Type: application/json" -d '{
echo "======================Testing worker sql agent======================" "query": "Tell me about Michael Jackson song thriller"
export agent_port=$(cat ${WORKPATH}/docker_compose/amd/gpu/WORKER_SQL_AGENT_PORT_tmp) }')
prompt="How many employees are there in the company?" local EXIT_CODE=$(validate "$CONTENT" "Thriller" "react-agent-endpoint")
local CONTENT=$(python3 $WORKDIR/GenAIExamples/AgentQnA/tests/test.py --prompt "$prompt" --agent_role "worker" --ext_port $agent_port) docker logs react-agent-endpoint
local EXIT_CODE=$(validate "$CONTENT" "8" "sql-agent-endpoint")
echo $CONTENT
# echo $EXIT_CODE
local EXIT_CODE="${EXIT_CODE:0-1}"
if [ "$EXIT_CODE" == "1" ]; then if [ "$EXIT_CODE" == "1" ]; then
docker logs sql-agent-endpoint
exit 1 exit 1
fi fi
# test supervisor react agent
echo "======================Testing supervisor react agent======================"
export agent_port=$(cat ${WORKPATH}/docker_compose/amd/gpu/SUPERVISOR_REACT_AGENT_PORT_tmp)
local CONTENT=$(python3 $WORKDIR/GenAIExamples/AgentQnA/tests/test.py --agent_role "supervisor" --ext_port $agent_port --stream)
local EXIT_CODE=$(validate "$CONTENT" "Iron" "react-agent-endpoint")
# echo $CONTENT
echo $EXIT_CODE
local EXIT_CODE="${EXIT_CODE:0-1}"
if [ "$EXIT_CODE" == "1" ]; then
docker logs react-agent-endpoint
exit 1
fi
}
function remove_chinook_data(){
echo "Removing chinook data..."
cd $WORKDIR
if [ -d "chinook-database" ]; then
rm -rf chinook-database
fi
echo "Chinook data removed!"
} }
function main() { function main() {
echo "==================== Prepare data ===================="
download_chinook_data
echo "==================== Data prepare done ===================="
echo "==================== Start agent ====================" echo "==================== Start agent ===================="
start_agent_and_api_server start_agent_and_api_server
echo "==================== Agent started ====================" echo "==================== Agent started ===================="
@@ -112,9 +73,4 @@ function main() {
echo "==================== Agent service validated ====================" echo "==================== Agent service validated ===================="
} }
remove_chinook_data
main main
remove_chinook_data

View File

@@ -10,41 +10,31 @@ export ip_address=$(hostname -I | awk '{print $1}')
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN} export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export TOOLSET_PATH=$WORKDIR/GenAIExamples/AgentQnA/tools/ export TOOLSET_PATH=$WORKDIR/GenAIExamples/AgentQnA/tools/
export no_proxy="$no_proxy,rag-agent-endpoint,sql-agent-endpoint,react-agent-endpoint,agent-ui,vllm-gaudi-server,jaeger,grafana,prometheus,127.0.0.1,localhost,0.0.0.0,$ip_address" export no_proxy="$no_proxy,rag-agent-endpoint,sql-agent-endpoint,react-agent-endpoint,agent-ui,vllm-gaudi-server,jaeger,grafana,prometheus,127.0.0.1,localhost,0.0.0.0,$ip_address"
IMAGE_REPO=${IMAGE_REPO:-"opea"}
IMAGE_TAG=${IMAGE_TAG:-"latest"}
echo "REGISTRY=IMAGE_REPO=${IMAGE_REPO}"
echo "TAG=IMAGE_TAG=${IMAGE_TAG}"
export REGISTRY=${IMAGE_REPO}
export TAG=${IMAGE_TAG}
export MODEL_CACHE=${model_cache:-"./data"}
function get_genai_comps() {
if [ ! -d "GenAIComps" ] ; then
git clone --depth 1 --branch ${opea_branch:-"main"} https://github.com/opea-project/GenAIComps.git
fi
}
function build_agent_docker_image() {
cd $WORKDIR/GenAIExamples/AgentQnA/docker_image_build/
get_genai_comps
echo "Build agent image with --no-cache..."
docker compose -f build.yaml build --no-cache
}
function stop_crag() { function stop_crag() {
cid=$(docker ps -aq --filter "name=kdd-cup-24-crag-service") cid=$(docker ps -aq --filter "name=kdd-cup-24-crag-service")
echo "Stopping container kdd-cup-24-crag-service with cid $cid" echo "Stopping container kdd-cup-24-crag-service with cid $cid"
if [[ ! -z "$cid" ]]; then docker rm $cid -f && sleep 1s; fi if [[ ! -z "$cid" ]]; then docker rm $cid -f && sleep 1s; fi
} }
function stop_agent_containers() { function stop_agent_docker() {
cd $WORKPATH/docker_compose/intel/hpu/gaudi/ cd $WORKPATH/docker_compose/intel/hpu/gaudi/
container_list=$(cat compose.yaml | grep container_name | cut -d':' -f2) docker compose -f $WORKDIR/GenAIExamples/DocIndexRetriever/docker_compose/intel/cpu/xeon/compose.yaml -f compose.yaml down
for container_name in $container_list; do
cid=$(docker ps -aq --filter "name=$container_name")
echo "Stopping container $container_name"
if [[ ! -z "$cid" ]]; then docker rm $cid -f && sleep 1s; fi
done
}
function stop_telemetry_containers(){
cd $WORKPATH/docker_compose/intel/hpu/gaudi/
container_list=$(cat compose.telemetry.yaml | grep container_name | cut -d':' -f2)
for container_name in $container_list; do
cid=$(docker ps -aq --filter "name=$container_name")
echo "Stopping container $container_name"
if [[ ! -z "$cid" ]]; then docker rm $cid -f && sleep 1s; fi
done
container_list=$(cat compose.telemetry.yaml | grep container_name | cut -d':' -f2)
} }
function stop_llm(){ function stop_llm(){
@@ -78,31 +68,25 @@ function stop_retrieval_tool() {
done done
} }
echo "workpath: $WORKPATH" echo "workpath: $WORKPATH"
echo "::group::=================== Stop containers ====================" echo "=================== Stop containers ===================="
stop_llm
stop_crag stop_crag
stop_agent_containers stop_agent_docker
stop_retrieval_tool
stop_telemetry_containers
echo "::endgroup::"
cd $WORKPATH/tests cd $WORKPATH/tests
echo "::group::=================== Building docker images====================" echo "=================== #1 Building docker images===================="
bash step1_build_images.sh gaudi_vllm > docker_image_build.log build_agent_docker_image
echo "::endgroup::" echo "=================== #1 Building docker images completed===================="
echo "::group::=================== Start agent, API server, retrieval, and ingest data====================" echo "=================== #4 Start agent, API server, retrieval, and ingest data===================="
bash step4_launch_and_validate_agent_gaudi.sh bash $WORKPATH/tests/step4_launch_and_validate_agent_gaudi.sh
echo "::endgroup::" echo "=================== #4 Agent, retrieval test passed ===================="
echo "::group::=================== Stop agent and API server====================" echo "=================== #5 Stop agent and API server===================="
stop_llm
stop_crag stop_crag
stop_agent_containers stop_agent_docker
stop_retrieval_tool echo "=================== #5 Agent and API server stopped===================="
stop_telemetry_containers
echo y | docker system prune echo y | docker system prune
echo "::endgroup::"
echo "ALL DONE!!" echo "ALL DONE!!"

View File

@@ -5,19 +5,11 @@
set -xe set -xe
WORKPATH=$(dirname "$PWD") WORKPATH=$(dirname "$PWD")
ls $WORKPATH
export WORKDIR=$WORKPATH/../../ export WORKDIR=$WORKPATH/../../
echo "WORKDIR=${WORKDIR}" echo "WORKDIR=${WORKDIR}"
export ip_address=$(hostname -I | awk '{print $1}') export ip_address=$(hostname -I | awk '{print $1}')
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN} export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export TOOLSET_PATH=$WORKPATH/tools/ export TOOLSET_PATH=$WORKDIR/GenAIExamples/AgentQnA/tools/
IMAGE_REPO=${IMAGE_REPO:-"opea"}
IMAGE_TAG=${IMAGE_TAG:-"latest"}
echo "REGISTRY=IMAGE_REPO=${IMAGE_REPO}"
echo "TAG=IMAGE_TAG=${IMAGE_TAG}"
export REGISTRY=${IMAGE_REPO}
export TAG=${IMAGE_TAG}
export MODEL_CACHE=${model_cache:-"./data"}
function stop_crag() { function stop_crag() {
cid=$(docker ps -aq --filter "name=kdd-cup-24-crag-service") cid=$(docker ps -aq --filter "name=kdd-cup-24-crag-service")
@@ -27,7 +19,13 @@ function stop_crag() {
function stop_agent_docker() { function stop_agent_docker() {
cd $WORKPATH/docker_compose/amd/gpu/rocm cd $WORKPATH/docker_compose/amd/gpu/rocm
bash stop_agent_service_tgi_rocm.sh # docker compose -f compose.yaml down
container_list=$(cat compose.yaml | grep container_name | cut -d':' -f2)
for container_name in $container_list; do
cid=$(docker ps -aq --filter "name=$container_name")
echo "Stopping container $container_name"
if [[ ! -z "$cid" ]]; then docker rm $cid -f && sleep 1s; fi
done
} }
function stop_retrieval_tool() { function stop_retrieval_tool() {
@@ -43,35 +41,34 @@ function stop_retrieval_tool() {
done done
} }
echo "workpath: $WORKPATH" echo "workpath: $WORKPATH"
echo "::group::=================== Stop containers ====================" echo "=================== Stop containers ===================="
stop_crag stop_crag
stop_agent_docker stop_agent_docker
stop_retrieval_tool stop_retrieval_tool
echo "::endgroup::=================== Stop containers completed ===================="
cd $WORKPATH/tests cd $WORKPATH/tests
echo "::group::=================== #1 Building docker images====================" echo "=================== #1 Building docker images===================="
bash step1_build_images.sh rocm > docker_image_build.log bash step1_build_images.sh
echo "::endgroup::=================== #1 Building docker images completed====================" echo "=================== #1 Building docker images completed===================="
echo "::group::=================== #2 Start retrieval tool====================" echo "=================== #2 Start retrieval tool===================="
bash step2_start_retrieval_tool.sh bash step2_start_retrieval_tool.sh
echo "::endgroup::=================== #2 Retrieval tool started====================" echo "=================== #2 Retrieval tool started===================="
echo "::group::=================== #3 Ingest data and validate retrieval====================" echo "=================== #3 Ingest data and validate retrieval===================="
bash step3_ingest_data_and_validate_retrieval.sh bash step3_ingest_data_and_validate_retrieval.sh
echo "::endgroup::=================== #3 Data ingestion and validation completed====================" echo "=================== #3 Data ingestion and validation completed===================="
echo "::group::=================== #4 Start agent and API server====================" echo "=================== #4 Start agent and API server===================="
bash step4a_launch_and_validate_agent_tgi_on_rocm.sh bash step4a_launch_and_validate_agent_tgi_on_rocm.sh
echo "::endgroup::=================== #4 Agent test passed ====================" echo "=================== #4 Agent test passed ===================="
echo "::group::=================== #5 Stop agent and API server====================" echo "=================== #5 Stop agent and API server===================="
stop_crag stop_crag
stop_agent_docker stop_agent_docker
stop_retrieval_tool stop_retrieval_tool
echo "::endgroup::=================== #5 Agent and API server stopped====================" echo "=================== #5 Agent and API server stopped===================="
echo y | docker system prune echo y | docker system prune

View File

@@ -1,72 +0,0 @@
#!/bin/bash
# Copyright (C) 2024 Advanced Micro Devices, Inc.
# SPDX-License-Identifier: Apache-2.0
set -e
WORKPATH=$(dirname "$PWD")
export WORKDIR=${WORKPATH}/../../
echo "WORKDIR=${WORKDIR}"
export ip_address=$(hostname -I | awk '{print $1}')
export HUGGINGFACEHUB_API_TOKEN=${HUGGINGFACEHUB_API_TOKEN}
export TOOLSET_PATH=$WORKPATH/tools/
IMAGE_REPO=${IMAGE_REPO:-"opea"}
IMAGE_TAG=${IMAGE_TAG:-"latest"}
echo "REGISTRY=IMAGE_REPO=${IMAGE_REPO}"
echo "TAG=IMAGE_TAG=${IMAGE_TAG}"
export REGISTRY=${IMAGE_REPO}
export TAG=${IMAGE_TAG}
export MODEL_CACHE=${model_cache:-"./data"}
function stop_crag() {
cid=$(docker ps -aq --filter "name=kdd-cup-24-crag-service")
echo "Stopping container kdd-cup-24-crag-service with cid $cid"
if [[ ! -z "$cid" ]]; then docker rm $cid -f && sleep 1s; fi
}
function stop_agent_docker() {
cd $WORKPATH/docker_compose/amd/gpu/rocm
bash stop_agent_service_vllm_rocm.sh
}
function stop_retrieval_tool() {
echo "Stopping Retrieval tool"
local RETRIEVAL_TOOL_PATH=$WORKDIR/GenAIExamples/DocIndexRetriever
cd $RETRIEVAL_TOOL_PATH/docker_compose/intel/cpu/xeon/
docker compose -f compose.yaml down
}
echo "workpath: $WORKPATH"
echo "::group::=================== Stop containers ===================="
stop_crag
stop_agent_docker
stop_retrieval_tool
echo "::endgroup::"
cd $WORKPATH/tests
echo "::group::=================== #1 Building docker images===================="
bash step1_build_images.sh rocm_vllm > docker_image_build.log
echo "::endgroup::=================== #1 Building docker images completed===================="
echo "::group::=================== #2 Start retrieval tool===================="
bash step2_start_retrieval_tool_rocm_vllm.sh
echo "::endgroup::=================== #2 Retrieval tool started===================="
echo "::group::=================== #3 Ingest data and validate retrieval===================="
bash step3_ingest_data_and_validate_retrieval_rocm_vllm.sh
echo "::endgroup::=================== #3 Data ingestion and validation completed===================="
echo "::group::=================== #4 Start agent and API server===================="
bash step4_launch_and_validate_agent_rocm_vllm.sh
echo "::endgroup::=================== #4 Agent test passed ===================="
echo "::group::=================== #5 Stop agent and API server===================="
stop_crag
stop_agent_docker
stop_retrieval_tool
echo "::endgroup::=================== #5 Agent and API server stopped===================="
echo y | docker system prune
echo "ALL DONE!!"

View File

@@ -4,11 +4,9 @@
import os import os
import requests import requests
from comps.cores.telemetry.opea_telemetry import opea_telemetry, tracer
from tools.pycragapi import CRAG from tools.pycragapi import CRAG
@opea_telemetry
def search_web_base(query: str) -> str: def search_web_base(query: str) -> str:
import os import os
@@ -27,7 +25,6 @@ def search_web_base(query: str) -> str:
return response return response
@opea_telemetry
def search_knowledge_base(query: str) -> str: def search_knowledge_base(query: str) -> str:
"""Search a knowledge base about music and singers for a given query. """Search a knowledge base about music and singers for a given query.
@@ -43,7 +40,6 @@ def search_knowledge_base(query: str) -> str:
return response.json()["text"] return response.json()["text"]
@opea_telemetry
def search_sql_database(query: str) -> str: def search_sql_database(query: str) -> str:
"""Search a SQL database on artists and their music with a natural language query. """Search a SQL database on artists and their music with a natural language query.
@@ -59,7 +55,6 @@ def search_sql_database(query: str) -> str:
return response.json()["text"] return response.json()["text"]
@opea_telemetry
def get_grammy_best_artist_by_year(year: int) -> dict: def get_grammy_best_artist_by_year(year: int) -> dict:
"""Get the Grammy Best New Artist for a specific year.""" """Get the Grammy Best New Artist for a specific year."""
api = CRAG() api = CRAG()
@@ -67,21 +62,18 @@ def get_grammy_best_artist_by_year(year: int) -> dict:
return api.music_grammy_get_best_artist_by_year(year) return api.music_grammy_get_best_artist_by_year(year)
@opea_telemetry
def get_members(band_name: str) -> dict: def get_members(band_name: str) -> dict:
"""Get the member list of a band.""" """Get the member list of a band."""
api = CRAG() api = CRAG()
return api.music_get_members(band_name) return api.music_get_members(band_name)
@opea_telemetry
def get_artist_birth_place(artist_name: str) -> dict: def get_artist_birth_place(artist_name: str) -> dict:
"""Get the birthplace of an artist.""" """Get the birthplace of an artist."""
api = CRAG() api = CRAG()
return api.music_get_artist_birth_place(artist_name) return api.music_get_artist_birth_place(artist_name)
@opea_telemetry
def get_billboard_rank_date(rank: int, date: str = None) -> dict: def get_billboard_rank_date(rank: int, date: str = None) -> dict:
"""Get Billboard ranking for a specific rank and date.""" """Get Billboard ranking for a specific rank and date."""
api = CRAG() api = CRAG()
@@ -89,7 +81,6 @@ def get_billboard_rank_date(rank: int, date: str = None) -> dict:
return api.music_get_billboard_rank_date(rank, date) return api.music_get_billboard_rank_date(rank, date)
@opea_telemetry
def get_song_release_date(song_name: str) -> dict: def get_song_release_date(song_name: str) -> dict:
"""Get the release date of a song.""" """Get the release date of a song."""
api = CRAG() api = CRAG()

View File

@@ -12,7 +12,7 @@ def search_knowledge_base(query: str) -> str:
print(url) print(url)
proxies = {"http": ""} proxies = {"http": ""}
payload = { payload = {
"messages": query, "text": query,
} }
response = requests.post(url, json=payload, proxies=proxies) response = requests.post(url, json=payload, proxies=proxies)
print(response) print(response)

View File

@@ -1,203 +1,26 @@
# Copyright (C) 2025 Intel Corporation # Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# syntax=docker/dockerfile:1 # Use node 20.11.1 as the base image
# Initialize device type args FROM node:20.11.1
# use build args in the docker build command with --build-arg="BUILDARG=true"
ARG USE_CUDA=false
ARG USE_OLLAMA=false
# Tested with cu117 for CUDA 11 and cu121 for CUDA 12 (default)
ARG USE_CUDA_VER=cu121
# any sentence transformer model; models to use can be found at https://huggingface.co/models?library=sentence-transformers
# Leaderboard: https://huggingface.co/spaces/mteb/leaderboard
# for better performance and multilangauge support use "intfloat/multilingual-e5-large" (~2.5GB) or "intfloat/multilingual-e5-base" (~1.5GB)
# IMPORTANT: If you change the embedding model (sentence-transformers/all-MiniLM-L6-v2) and vice versa, you aren't able to use RAG Chat with your previous documents loaded in the WebUI! You need to re-embed them.
ARG USE_EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
ARG USE_RERANKING_MODEL=""
# Tiktoken encoding name; models to use can be found at https://huggingface.co/models?library=tiktoken # Update package manager and install Git
ARG USE_TIKTOKEN_ENCODING_NAME="cl100k_base" RUN apt-get update -y && apt-get install -y git
ARG BUILD_HASH=dev-build # Copy the front-end code repository
# Override at your own risk - non-root configurations are untested COPY svelte /home/user/svelte
ARG UID=0
ARG GID=0
######## WebUI frontend ######## # Set the working directory
FROM --platform=$BUILDPLATFORM node:22-alpine3.20 AS build WORKDIR /home/user/svelte
ARG BUILD_HASH
WORKDIR /app # Install front-end dependencies
RUN npm install
COPY open_webui_patches /app/patches # Build the front-end application
ARG WEBUI_VERSION=v0.5.20
RUN apk add --no-cache git
# Clone code and use patch
RUN git config --global user.name "opea" && \
git config --global user.email "" && \
git clone https://github.com/open-webui/open-webui.git
WORKDIR /app/open-webui
RUN git checkout ${WEBUI_VERSION} && git am /app/patches/*.patch
WORKDIR /app
RUN mv open-webui/* . && rm -fr open-webui && ls -lrth /app/backend/
RUN npm install onnxruntime-node --onnxruntime-node-install-cuda=skip
RUN apk update && \
apk add --no-cache wget && \
wget https://github.com/microsoft/onnxruntime/releases/download/v1.20.1/onnxruntime-linux-x64-gpu-1.20.1.tgz
ENV APP_BUILD_HASH=${BUILD_HASH}
RUN npm run build RUN npm run build
######## WebUI backend ######## # Expose the port of the front-end application
FROM python:3.11-slim-bookworm AS base EXPOSE 5173
# Use args # Run the front-end application in preview mode
ARG USE_CUDA CMD ["npm", "run", "preview", "--", "--port", "5173", "--host", "0.0.0.0"]
ARG USE_OLLAMA
ARG USE_CUDA_VER
ARG USE_EMBEDDING_MODEL
ARG USE_RERANKING_MODEL
ARG UID
ARG GID
## Basis ##
ENV ENV=prod \
PORT=8080 \
# pass build args to the build
USE_OLLAMA_DOCKER=${USE_OLLAMA} \
USE_CUDA_DOCKER=${USE_CUDA} \
USE_CUDA_DOCKER_VER=${USE_CUDA_VER} \
USE_EMBEDDING_MODEL_DOCKER=${USE_EMBEDDING_MODEL} \
USE_RERANKING_MODEL_DOCKER=${USE_RERANKING_MODEL}
## Basis URL Config ##
ENV OLLAMA_BASE_URL="/ollama" \
OPENAI_API_BASE_URL=""
## API Key and Security Config ##
ENV OPENAI_API_KEY="" \
WEBUI_SECRET_KEY="" \
SCARF_NO_ANALYTICS=true \
DO_NOT_TRACK=true \
ANONYMIZED_TELEMETRY=false
#### Other models #########################################################
## whisper TTS model settings ##
ENV WHISPER_MODEL="base" \
WHISPER_MODEL_DIR="/app/backend/data/cache/whisper/models"
## RAG Embedding model settings ##
ENV RAG_EMBEDDING_MODEL="$USE_EMBEDDING_MODEL_DOCKER" \
RAG_RERANKING_MODEL="$USE_RERANKING_MODEL_DOCKER" \
SENTENCE_TRANSFORMERS_HOME="/app/backend/data/cache/embedding/models"
## Tiktoken model settings ##
ENV TIKTOKEN_ENCODING_NAME="cl100k_base" \
TIKTOKEN_CACHE_DIR="/app/backend/data/cache/tiktoken"
## Hugging Face download cache ##
ENV HF_HOME="/app/backend/data/cache/embedding/models"
## Torch Extensions ##
# ENV TORCH_EXTENSIONS_DIR="/.cache/torch_extensions"
#### Other models ##########################################################
COPY --from=build /app/backend /app/backend
WORKDIR /app/backend
ENV HOME=/root
# Create user and group if not root
RUN if [ $UID -ne 0 ]; then \
if [ $GID -ne 0 ]; then \
addgroup --gid $GID app; \
fi; \
adduser --uid $UID --gid $GID --home $HOME --disabled-password --no-create-home app; \
fi
RUN mkdir -p $HOME/.cache/chroma
RUN printf 00000000-0000-0000-0000-000000000000 > $HOME/.cache/chroma/telemetry_user_id
# Make sure the user has access to the app and root directory
RUN chown -R $UID:$GID /app $HOME
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN if [ "$USE_OLLAMA" = "true" ]; then \
apt-get update && \
# Install pandoc and netcat
apt-get install -y --no-install-recommends git build-essential pandoc netcat-openbsd curl && \
apt-get install -y --no-install-recommends gcc python3-dev && \
# for RAG OCR
apt-get install -y --no-install-recommends ffmpeg libsm6 libxext6 && \
# install helper tools
apt-get install -y --no-install-recommends curl jq && \
# install ollama
curl -fsSL https://ollama.com/install.sh | sh && \
# cleanup
rm -rf /var/lib/apt/lists/*; \
else \
apt-get update && \
# Install pandoc, netcat and gcc
apt-get install -y --no-install-recommends git build-essential pandoc gcc netcat-openbsd curl jq && \
apt-get install -y --no-install-recommends gcc python3-dev && \
# for RAG OCR
apt-get install -y --no-install-recommends ffmpeg libsm6 libxext6 && \
# cleanup
rm -rf /var/lib/apt/lists/*; \
fi
# install python dependencies
# COPY --chown=$UID:$GID ./backend/requirements.txt ./requirements.txt
# RUN cp /app/backend/requirements.txt ./requirements.txt
RUN pip3 install --no-cache-dir uv && \
if [ "$USE_CUDA" = "true" ]; then \
# If you use CUDA the whisper and embedding model will be downloaded on first use
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/$USE_CUDA_DOCKER_VER --no-cache-dir && \
uv pip install --system -r requirements.txt --no-cache-dir && \
python -c "import os; from sentence_transformers import SentenceTransformer; SentenceTransformer(os.environ['RAG_EMBEDDING_MODEL'], device='cpu')" && \
python -c "import os; from faster_whisper import WhisperModel; WhisperModel(os.environ['WHISPER_MODEL'], device='cpu', compute_type='int8', download_root=os.environ['WHISPER_MODEL_DIR'])"; \
python -c "import os; import tiktoken; tiktoken.get_encoding(os.environ['TIKTOKEN_ENCODING_NAME'])"; \
else \
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu --no-cache-dir && \
uv pip install --system -r requirements.txt --no-cache-dir && \
python -c "import os; from sentence_transformers import SentenceTransformer; SentenceTransformer(os.environ['RAG_EMBEDDING_MODEL'], device='cpu')" && \
python -c "import os; from faster_whisper import WhisperModel; WhisperModel(os.environ['WHISPER_MODEL'], device='cpu', compute_type='int8', download_root=os.environ['WHISPER_MODEL_DIR'])"; \
python -c "import os; import tiktoken; tiktoken.get_encoding(os.environ['TIKTOKEN_ENCODING_NAME'])"; \
fi; \
chown -R $UID:$GID /app/backend/data/
# copy embedding weight from build
# RUN mkdir -p /root/.cache/chroma/onnx_models/all-MiniLM-L6-v2
# COPY --from=build /app/onnx /root/.cache/chroma/onnx_models/all-MiniLM-L6-v2/onnx
# copy built frontend files
COPY --chown=$UID:$GID --from=build /app/build /app/build
COPY --chown=$UID:$GID --from=build /app/CHANGELOG.md /app/CHANGELOG.md
COPY --chown=$UID:$GID --from=build /app/package.json /app/package.json
# copy backend files
# COPY --chown=$UID:$GID ./backend .
EXPOSE 8080
HEALTHCHECK CMD curl --silent --fail http://localhost:${PORT:-8080}/health | jq -ne 'input.status == true' || exit 1
USER $UID:$GID
ARG BUILD_HASH
ENV WEBUI_BUILD_VERSION=${BUILD_HASH}
ENV DOCKER=true
CMD [ "bash", "start.sh"]

View File

@@ -1,86 +0,0 @@
From d90ba418f866bc11848d7d6507aabc6b5e8cc3e2 Mon Sep 17 00:00:00 2001
From: lkk12014402 <kaokao.lv@intel.com>
Date: Mon, 7 Apr 2025 07:22:53 +0000
Subject: [PATCH] compatible opea agent tool content
---
backend/open_webui/utils/middleware.py | 56 ++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py
index 289d887df..fddbe8ee1 100644
--- a/backend/open_webui/utils/middleware.py
+++ b/backend/open_webui/utils/middleware.py
@@ -1465,6 +1465,8 @@ async def process_chat_response(
async def stream_body_handler(response):
nonlocal content
nonlocal content_blocks
+ nonlocal events
+ sources = []
response_tool_calls = []
@@ -1486,6 +1488,60 @@ async def process_chat_response(
try:
data = json.loads(data)
+ tool_content_block = []
+ if data.get("tool_name"):
+ sources.append(
+ {
+ "source": {
+ "name": f"TOOL:{data.get('tool_name')}"},
+ "document": [data.get("tool_content")],
+ "metadata": [{
+ "source": f"TOOL:{data.get('tool_name')}"}],
+ }
+ )
+ events.append({"sources": sources})
+
+ await event_emitter(
+ {
+ "type": "chat:completion",
+ "data": {"sources": sources},
+ }
+ )
+ tool_content_block = [
+ {
+ "type": "tool_calls",
+ "content": [
+ {"id": data.get('tool_name'), "function": {"name": data.get('tool_name')}}
+ ]
+ }
+ ]
+
+ await event_emitter(
+ {
+ "type": "chat:completion",
+ "data": {
+ "content": serialize_content_blocks(tool_content_block),
+ },
+ }
+ )
+
+ tool_content_block = [
+ {
+ "type": "tool_calls",
+ "content": [
+ {"id": data.get('tool_name'), "function": {"name": data.get('tool_name')}}
+ ],
+ "results": [
+ {"tool_call_id": data.get('tool_name'), "content": data.get("tool_content")}
+ ]
+ },
+ {
+ "type": "text",
+ "content": "",
+ }
+ ]
+ content_blocks.extend(tool_content_block)
+
data, _ = await process_filter_functions(
request=request,
filter_functions=filter_functions,
--
2.34.1

View File

@@ -1,531 +0,0 @@
From 8ad31e50644eab3c9e698d7828b1857919887841 Mon Sep 17 00:00:00 2001
From: lkk12014402 <kaokao.lv@intel.com>
Date: Tue, 8 Apr 2025 03:38:09 +0000
Subject: [PATCH 2/2] update agent icloud upload feature
---
src/lib/apis/knowledge/index.ts | 60 +++++++
.../admin/Settings/Connections.svelte | 50 +++++-
.../components/icons/UploadCloudIcon.svelte | 18 ++
src/lib/components/workspace/Knowledge.svelte | 57 +++++-
.../KnowledgeBase/AddIcloudContentMenu.svelte | 164 ++++++++++++++++++
.../KnowledgeBase/IcloudFiles.svelte | 37 ++++
src/lib/i18n/locales/zh-CN/translation.json | 15 +-
7 files changed, 396 insertions(+), 5 deletions(-)
create mode 100644 src/lib/components/icons/UploadCloudIcon.svelte
create mode 100644 src/lib/components/workspace/Knowledge/KnowledgeBase/AddIcloudContentMenu.svelte
create mode 100644 src/lib/components/workspace/Knowledge/KnowledgeBase/IcloudFiles.svelte
diff --git a/src/lib/apis/knowledge/index.ts b/src/lib/apis/knowledge/index.ts
index c5fad1323..32be528a7 100644
--- a/src/lib/apis/knowledge/index.ts
+++ b/src/lib/apis/knowledge/index.ts
@@ -345,3 +345,63 @@ export const deleteKnowledgeById = async (token: string, id: string) => {
return res;
};
+
+export const getIcloudFiles = async (ICLOUD_BASE_URLS: string) => {
+ let error = null;
+
+ const res = await fetch(`${ICLOUD_BASE_URLS}/dataprep/get`, {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ }
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .then((json) => {
+ return json;
+ })
+ .catch((err) => {
+ error = err.detail;
+
+ console.log(err);
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
+export const updateIcloudFiles = async (ICLOUD_BASE_URLS: string, formData: any) => {
+ let error = null;
+
+ const res = await fetch(`${ICLOUD_BASE_URLS}/dataprep/ingest`, {
+ method: 'POST',
+ body: formData
+ })
+ .then(async (res) => {
+ if (!res.ok) throw await res.json();
+ return res.json();
+ })
+ .then((json) => {
+ return json;
+ })
+ .catch((err) => {
+ error = err.detail;
+
+ console.log(err);
+ return null;
+ });
+
+ if (error) {
+ throw error;
+ }
+
+ return res;
+};
+
diff --git a/src/lib/components/admin/Settings/Connections.svelte b/src/lib/components/admin/Settings/Connections.svelte
index 2fcfadaec..3237744d5 100644
--- a/src/lib/components/admin/Settings/Connections.svelte
+++ b/src/lib/components/admin/Settings/Connections.svelte
@@ -47,6 +47,9 @@
let showAddOpenAIConnectionModal = false;
let showAddOllamaConnectionModal = false;
+ let ENABLE_ICLOUD_API: null | boolean = (localStorage.getItem('ENABLE_ICLOUD_API') === "enable");
+ let ICLOUD_BASE_URL = localStorage.getItem('ICLOUD_BASE_URL') || '';
+
const updateOpenAIHandler = async () => {
if (ENABLE_OPENAI_API !== null) {
// Remove trailing slashes
@@ -193,10 +196,22 @@
}
});
+ const updateIcloudHandler = async () => {
+ if (ENABLE_ICLOUD_API) {
+ localStorage.setItem('ICLOUD_BASE_URL', ICLOUD_BASE_URL);
+ localStorage.setItem('ENABLE_ICLOUD_API', "enable");
+ } else {
+ localStorage.setItem('ICLOUD_BASE_URL', '');
+ localStorage.setItem('ENABLE_ICLOUD_API', "");
+ }
+ toast.success($i18n.t('Icloud API settings updated'));
+ };
+
const submitHandler = async () => {
updateOpenAIHandler();
updateOllamaHandler();
updateDirectConnectionsHandler();
+ updateIcloudHandler();
dispatch('save');
};
@@ -301,7 +316,7 @@
</div>
{#if ENABLE_OLLAMA_API}
- <hr class=" border-gray-100 dark:border-gray-850 my-2" />
+ <hr class=" border-gray-100 dark:border-gray-850" />
<div class="">
<div class="flex justify-between items-center">
@@ -358,6 +373,39 @@
{/if}
</div>
+ <hr class=" border-gray-50 dark:border-gray-850" />
+
+ <div class="pr-1.5 my-2">
+ <div class="flex justify-between items-center text-sm">
+ <div class="font-medium">{$i18n.t('Icloud File API')}</div>
+
+ <div class="mt-1">
+ <Switch
+ bind:state={ENABLE_ICLOUD_API}
+ on:change={async () => {
+ updateIcloudHandler();
+ }}
+ />
+ </div>
+ </div>
+
+ {#if ENABLE_ICLOUD_API}
+ <hr class=" border-gray-50 dark:border-gray-850 my-2" />
+
+ <div class="">
+ <div class="flex w-full gap-1.5">
+ <div class="flex-1 flex flex-col gap-1.5">
+ <input
+ class="w-full text-sm bg-transparent outline-none"
+ placeholder={$i18n.t('Enter Icloud URL(e.g.') + 'http://localhost:6007/v1)'}
+ bind:value={ICLOUD_BASE_URL}
+ />
+ </div>
+ </div>
+ </div>
+ {/if}
+ </div>
+
<hr class=" border-gray-100 dark:border-gray-850" />
<div class="pr-1.5 my-2">
diff --git a/src/lib/components/icons/UploadCloudIcon.svelte b/src/lib/components/icons/UploadCloudIcon.svelte
new file mode 100644
index 000000000..eed3bd582
--- /dev/null
+++ b/src/lib/components/icons/UploadCloudIcon.svelte
@@ -0,0 +1,18 @@
+<script lang="ts">
+ export let className = 'w-4 h-4';
+</script>
+
+<svg
+ t="1744007283647"
+ viewBox="0 0 1491 1024"
+ version="1.1"
+ xmlns="http://www.w3.org/2000/svg"
+ p-id="1630"
+ class = {className}
+ ><path
+ d="M546.047379 263.651842s-90.221363-91.423424-212.63125-16.762074c-109.521121 71.300031-90.154581 201.768179-90.154582 201.76818S0 498.498962 0 759.902727c5.431535 261.003078 264.186314 263.674325 264.186314 263.674326l388.443814 0.422947V744.565318H466.355181l279.434681-279.412421 279.390161 279.412421h-186.297208V1024l377.157796-0.422947s240.812904 0.222604 274.648698-248.092052c16.094262-271.576764-232.754643-325.113003-232.754643-325.113003S1286.205362 48.327085 936.761752 2.470681C637.181417-29.740104 546.047379 263.651842 546.047379 263.651842z"
+ fill="#507BFC"
+ p-id="1631"
+ ></path></svg
+>
+
diff --git a/src/lib/components/workspace/Knowledge.svelte b/src/lib/components/workspace/Knowledge.svelte
index 57d45312d..43a1f305e 100644
--- a/src/lib/components/workspace/Knowledge.svelte
+++ b/src/lib/components/workspace/Knowledge.svelte
@@ -13,7 +13,8 @@
import {
getKnowledgeBases,
deleteKnowledgeById,
- getKnowledgeBaseList
+ getKnowledgeBaseList,
+ getIcloudFiles
} from '$lib/apis/knowledge';
import { goto } from '$app/navigation';
@@ -26,6 +27,11 @@
import Spinner from '../common/Spinner.svelte';
import { capitalizeFirstLetter } from '$lib/utils';
import Tooltip from '../common/Tooltip.svelte';
+ import AddIcloudConnectionModal from '$lib/components/workspace/Knowledge/KnowledgeBase/AddIcloudContentMenu.svelte';
+ import IcloudFiles from '$lib/components/workspace/Knowledge/KnowledgeBase/IcloudFiles.svelte';
+
+ let showAddTextContentModal = false;
+ let IcloudFile = [];
let loaded = false;
@@ -65,9 +71,26 @@
};
onMount(async () => {
+ await updateIcloudFiles();
+
knowledgeBases = await getKnowledgeBaseList(localStorage.token);
loaded = true;
});
+
+ async function updateIcloudFiles() {
+ let ICLOUD_BASE_URL = localStorage.getItem('ICLOUD_BASE_URL') || '';
+ console.log('ICLOUD_BASE_URL', ICLOUD_BASE_URL);
+
+ if (ICLOUD_BASE_URL !== '') {
+ const res = await getIcloudFiles(ICLOUD_BASE_URL).catch((e) => {
+ toast.error(`${e}`);
+ });
+
+ if (res) {
+ IcloudFile = res;
+ }
+ }
+ }
</script>
<svelte:head>
@@ -187,11 +210,39 @@
{/each}
</div>
- <div class=" text-gray-500 text-xs mt-1 mb-2">
- ⓘ {$i18n.t("Use '#' in the prompt input to load and include your knowledge.")}
+ <div class="flex justify-between items-center">
+ <div class="flex md:self-center text-xl font-medium px-0.5 items-center">
+ {$i18n.t('Icloud Knowledge')}
+ <div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-50 dark:bg-gray-850" />
+ <span class="text-lg font-medium text-gray-500 dark:text-gray-300">{IcloudFile.length}</span>
+ </div>
+ <div>
+ <button
+ class=" px-2 py-2 rounded-xl hover:bg-gray-700/10 dark:hover:bg-gray-100/10 dark:text-gray-300 dark:hover:text-white transition font-medium text-sm flex items-center space-x-1"
+ aria-label={$i18n.t('Upload to Icloud')}
+ on:click={() => {
+ showAddTextContentModal = !showAddTextContentModal;
+ }}
+ >
+ <Plus className="size-3.5" />
+ </button>
+ </div>
+ </div>
+ <hr class="border-gray-100 dark:border-gray-850 my-2" />
+ <div class=" flex overflow-y-auto w-full h-[15rem] scrollbar-hidden text-xs">
+ <IcloudFiles files={IcloudFile} />
</div>
{:else}
<div class="w-full h-full flex justify-center items-center">
<Spinner />
</div>
{/if}
+
+<AddIcloudConnectionModal
+ bind:show={showAddTextContentModal}
+ on:updateIcloudFile={async (e) => {
+ if (e.detail.status) {
+ await updateIcloudFiles();
+ }
+ }}
+/>
diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase/AddIcloudContentMenu.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase/AddIcloudContentMenu.svelte
new file mode 100644
index 000000000..fb906a0d3
--- /dev/null
+++ b/src/lib/components/workspace/Knowledge/KnowledgeBase/AddIcloudContentMenu.svelte
@@ -0,0 +1,164 @@
+<script lang="ts">
+ import { toast } from 'svelte-sonner';
+ import { getContext, onMount, createEventDispatcher } from 'svelte';
+ import Modal from '$lib/components/common/Modal.svelte';
+ import UploadCloudIcon from '$lib/components/icons/UploadCloudIcon.svelte';
+ import Spinner from '$lib/components/common/Spinner.svelte';
+ import { updateIcloudFiles } from '$lib/apis/knowledge';
+
+ const i18n = getContext('i18n');
+ const dispatch = createEventDispatcher();
+
+ export let show = false;
+
+ let url = '';
+
+ let loading = false;
+
+ let selectedFile = null;
+
+ function handleFileSelect(event) {
+ selectedFile = event.target.files[0];
+ }
+
+ function parseAndValidateUrls(normalizedInput: string): string[] {
+ return normalizedInput
+ .split(',')
+ .map((candidate) => {
+ const processed = candidate.replace(/^["']+|["']+$/g, '').trim();
+
+ try {
+ new URL(processed);
+ return processed;
+ } catch {
+ return null;
+ }
+ })
+ .filter((url): url is string => url !== null);
+ }
+
+ async function submitHandler() {
+ loading = true;
+
+ if (!url && !selectedFile) {
+ loading = false;
+ show = false;
+
+ toast.error($i18n.t('URL or File are required'));
+ return;
+ }
+ if (url && selectedFile) {
+ loading = false;
+ show = false;
+
+ toast.error($i18n.t('Upload file or enter URL'));
+ url = '';
+ selectedFile = null;
+ return;
+ }
+
+ const formData = new FormData();
+ if (url) {
+ formData.append('link_list', JSON.stringify(parseAndValidateUrls(url)));
+ }
+ if (selectedFile) {
+ formData.append('files', selectedFile, selectedFile.name);
+ }
+ let ICLOUD_BASE_URL = localStorage.getItem('ICLOUD_BASE_URL') || '';
+ console.log('ICLOUD_BASE_URL', ICLOUD_BASE_URL);
+
+ if (ICLOUD_BASE_URL !== '') {
+ const res = await updateIcloudFiles(ICLOUD_BASE_URL, formData).catch((e) => {
+ toast.error(`${e}`);
+
+ return;
+ });
+
+ if (res) {
+ toast.success($i18n.t('Upload Succeed'));
+ dispatch('updateIcloudFile', { status: true });
+ }
+
+ url = '';
+ selectedFile = null;
+ loading = false;
+ show = false;
+ }
+ }
+</script>
+
+<Modal size="sm" bind:show>
+ <div class="flex flex-col justify-end">
+ <div class=" flex justify-between dark:text-gray-100 px-5 pt-4 pb-2">
+ <div class="flex-col text-lg font-medium self-center font-primary">
+ {$i18n.t('Upload Icloud file')}
+ <span class="text-sm text-gray-500">- {$i18n.t('choose URL or local file')}</span>
+ </div>
+
+ <button
+ class="self-center"
+ on:click={() => {
+ show = false;
+ }}
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 20 20"
+ fill="currentColor"
+ class="w-5 h-5"
+ >
+ <path
+ d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
+ />
+ </svg>
+ </button>
+ </div>
+
+ <div class="flex flex-col md:flex-row w-full px-4 pb-4 md:space-x-4 dark:text-gray-200">
+ <div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
+ <div class="flex items-center w-full">
+ <div class="flex-1 min-w-0 mr-2">
+ <div class="flex flex-col w-full my-8 mx-2">
+ <input
+ class="w-full text-sm bg-transparent placeholder:text-gray-300 outline-none border-b-solid border-b-2 border-blue-500 rounded p-2"
+ type="text"
+ bind:value={url}
+ placeholder={$i18n.t('Upload from URL')}
+ />
+ </div>
+ </div>
+
+ <div class="flex-none w-[1px] h-[60%] mx-2.5 bg-gray-300"></div>
+
+ <div class="flex-1 min-w-0">
+ <input type="file" id="fileInput" hidden on:change={handleFileSelect} />
+
+ <label
+ for="fileInput"
+ class="cursor-pointer flex flex-col items-center hover:bg-gray-100 rounded-lg p-2 transition-colors"
+ >
+ <UploadCloudIcon className="w-12 h-12 text-gray-500" />
+ <div class="text-xs text-gray-500 pt-2">
+ {selectedFile ? selectedFile.name : '点击上传文件'}
+ </div>
+ </label>
+ </div>
+ </div>
+ </div>
+ </div>
+ {#if loading}
+ <Spinner className="my-4 size-4" />
+ {:else}
+ <button
+ class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded text-sm"
+ on:click={(e) => {
+ e.preventDefault();
+ submitHandler();
+ }}
+ >
+ {$i18n.t('Upload Confirm')}
+ </button>
+ {/if}
+ </div>
+</Modal>
+
diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase/IcloudFiles.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase/IcloudFiles.svelte
new file mode 100644
index 000000000..d6490dce2
--- /dev/null
+++ b/src/lib/components/workspace/Knowledge/KnowledgeBase/IcloudFiles.svelte
@@ -0,0 +1,37 @@
+<script lang="ts">
+ export let selectedFileId = null;
+ export let files = [];
+
+ export let small = false;
+</script>
+
+<div class="max-h-full flex flex-col w-full">
+ {#each files as file}
+ <div class="mt-1 px-2 flex hover:bg-gray-50 transition">
+ <div class="p-3 bg-black/20 dark:bg-white/10 text-white rounded-xl my-2">
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 24 24"
+ fill="currentColor"
+ class=" size-3"
+ >
+ <path
+ fill-rule="evenodd"
+ d="M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0 0 16.5 9h-1.875a1.875 1.875 0 0 1-1.875-1.875V5.25A3.75 3.75 0 0 0 9 1.5H5.625ZM7.5 15a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 7.5 15Zm.75 2.25a.75.75 0 0 0 0 1.5H12a.75.75 0 0 0 0-1.5H8.25Z"
+ clip-rule="evenodd"
+ />
+ <path
+ d="M12.971 1.816A5.23 5.23 0 0 1 14.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 0 1 3.434 1.279 9.768 9.768 0 0 0-6.963-6.963Z"
+ />
+ </svg>
+ </div>
+
+ <div class="flex flex-col justify-center -space-y-0.5 px-2.5 w-full">
+ <div class=" dark:text-gray-100 text-sm font-medium line-clamp-1 mb-1">
+ {file.name}
+ </div>
+ </div>
+ </div>
+ {/each}
+</div>
+
diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json
index ebb53a1b5..d6b72e04d 100644
--- a/src/lib/i18n/locales/zh-CN/translation.json
+++ b/src/lib/i18n/locales/zh-CN/translation.json
@@ -1174,5 +1174,18 @@
"Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "您的全部捐款将直接给到插件开发者Open WebUI 不会收取任何比例。但众筹平台可能会有服务费、抽成。",
"Youtube": "YouTube",
"Youtube Language": "Youtube 语言",
- "Youtube Proxy URL": "Youtube 代理 URL"
+ "Youtube Proxy URL": "Youtube 代理 URL",
+ "Upload Icloud file": "上传到云端",
+ "choose URL or local file": "选择URL或本地文件",
+ "Upload from URL": "从URL上传",
+ "Upload Confirm": "确认上传",
+ "URL or File are required": "未上传文件",
+ "Upload file or enter URL": "文件与URL不能同时提交",
+ "Icloud File": "云端文件",
+ "Icloud File API": "云端存储API",
+ "Enter Icloud URL(e.g.": "输入云端存储URL例如.",
+ "Upload to Icloud": "上传到云端",
+ "Icloud Knowledge": "云端数据库",
+ "Upload Succeed": "上传文件成功",
+ "Icloud API settings updated": "云端存储API设置已更新"
}
--
2.34.1

View File

@@ -1,56 +0,0 @@
From ebf3218eef81897b536521e2140bdd9176f3ace3 Mon Sep 17 00:00:00 2001
From: lkk12014402 <kaokao.lv@intel.com>
Date: Tue, 8 Apr 2025 07:13:20 +0000
Subject: [PATCH 3/3] update build script
---
hatch_build.py | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/hatch_build.py b/hatch_build.py
index 8ddaf0749..e15d6e99d 100644
--- a/hatch_build.py
+++ b/hatch_build.py
@@ -3,21 +3,34 @@ import os
import shutil
import subprocess
from sys import stderr
-
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
-
-
+
+
class CustomBuildHook(BuildHookInterface):
def initialize(self, version, build_data):
super().initialize(version, build_data)
- stderr.write(">>> Building Open Webui frontend\n")
+ stderr.write(">>> Building DCAI小智 frontend\n")
npm = shutil.which("npm")
if npm is None:
raise RuntimeError(
- "NodeJS `npm` is required for building Open Webui but it was not found"
+ "NodeJS `npm` is required for building DCAI小智 but it was not found"
)
+ stderr.write("### Installing onnxruntime-node\n")
+ subprocess.run([npm, "install", "onnxruntime-node", "--onnxruntime-node-install-cuda=skip"], check=True) # noqa: S603
+
+ stderr.write("### Installing huggingface/transformers.js\n")
+ subprocess.run([npm, "i", "@huggingface/transformers"], check=True) # noqa: S603
+
+ ort_version = "1.20.1"
+ ort_url = f"https://github.com/microsoft/onnxruntime/releases/download/v{ort_version}/onnxruntime-linux-x64-gpu-{ort_version}.tgz"
+
+ stderr.write(f"### Downloading onnxruntime binaries from {ort_url}\n")
+ subprocess.run(["curl", "-L", ort_url, "-o", f"onnxruntime-linux-x64-gpu-{ort_version}.tgz"], check=True) # noqa: S603
+
stderr.write("### npm install\n")
subprocess.run([npm, "install"], check=True) # noqa: S603
+
stderr.write("\n### npm run build\n")
os.environ["APP_BUILD_HASH"] = version
subprocess.run([npm, "run", "build"], check=True) # noqa: S603
--
2.34.1

View File

@@ -1,31 +0,0 @@
From 36d61dab9306cb8f12c4497a32781d84f8cfb2e7 Mon Sep 17 00:00:00 2001
From: lkk12014402 <kaokao.lv@intel.com>
Date: Tue, 8 Apr 2025 07:22:36 +0000
Subject: [PATCH 4/4] enhance tool formatting
---
backend/open_webui/utils/middleware.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py
index fddbe8ee1..9e44ed91a 100644
--- a/backend/open_webui/utils/middleware.py
+++ b/backend/open_webui/utils/middleware.py
@@ -1142,12 +1142,12 @@ async def process_chat_response(
result_display_content = f"{result_display_content}\n> {tool_name}: {result.get('content', '')}"
if not raw:
- content = f'{content}\n<details type="tool_calls" done="true" content="{html.escape(json.dumps(block_content))}" results="{html.escape(json.dumps(results))}">\n<summary>Tool Executed</summary>\n{result_display_content}\n</details>\n'
+ content = f'{content}\n<details type="tool_calls" done="true" content="{html.escape(json.dumps(block_content))}" results="{html.escape(json.dumps(results))}">\n<summary> Tool: {tool_call.get('function', {}).get('name', '')} Executed</summary>\n{result_display_content}\n</details>\n'
else:
tool_calls_display_content = ""
for tool_call in block_content:
- tool_calls_display_content = f"{tool_calls_display_content}\n> Executing {tool_call.get('function', {}).get('name', '')}"
+ tool_calls_display_content = f"{tool_calls_display_content}\n> Executing Tool: {tool_call.get('function', {}).get('name', '')}"
if not raw:
content = f'{content}\n<details type="tool_calls" done="false" content="{html.escape(json.dumps(block_content))}">\n<summary>Tool Executing...</summary>\n{tool_calls_display_content}\n</details>\n'
--
2.34.1

View File

@@ -1,25 +0,0 @@
From 4723fb2df86df3e1c300f12fc0649823ea1a753b Mon Sep 17 00:00:00 2001
From: lkk12014402 <kaokao.lv@intel.com>
Date: Tue, 8 Apr 2025 08:09:36 +0000
Subject: [PATCH 5/5] fix tool call typo.
---
backend/open_webui/utils/middleware.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py
index 9e44ed91a..82aed5346 100644
--- a/backend/open_webui/utils/middleware.py
+++ b/backend/open_webui/utils/middleware.py
@@ -1142,7 +1142,7 @@ async def process_chat_response(
result_display_content = f"{result_display_content}\n> {tool_name}: {result.get('content', '')}"
if not raw:
- content = f'{content}\n<details type="tool_calls" done="true" content="{html.escape(json.dumps(block_content))}" results="{html.escape(json.dumps(results))}">\n<summary> Tool: {tool_call.get('function', {}).get('name', '')} Executed</summary>\n{result_display_content}\n</details>\n'
+ content = f'{content}\n<details type="tool_calls" done="true" content="{html.escape(json.dumps(block_content))}" results="{html.escape(json.dumps(results))}">\n<summary> Tool: {tool_call.get("function", {}).get("name", "")} Executed</summary>\n{result_display_content}\n</details>\n'
else:
tool_calls_display_content = ""
--
2.34.1

View File

@@ -0,0 +1,10 @@
[*]
indent_style = tab
[package.json]
indent_style = space
indent_size = 2
[*.md]
indent_style = space
indent_size = 2

1
AgentQnA/ui/svelte/.env Normal file
View File

@@ -0,0 +1 @@
AGENT_URL = '/v1/chat/completions'

View File

@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

View File

@@ -0,0 +1,20 @@
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
plugins: ["svelte3", "@typescript-eslint", "neverthrow"],
ignorePatterns: ["*.cjs"],
overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }],
settings: {
"svelte3/typescript": () => require("typescript"),
},
parserOptions: {
sourceType: "module",
ecmaVersion: 2020,
},
env: {
browser: true,
es2017: true,
node: true,
},
};

View File

@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

View File

@@ -0,0 +1,13 @@
{
"pluginSearchDirs": [
"."
],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}

View File

@@ -0,0 +1,72 @@
# AgentQnA
## 📸 Project Screenshots
![project-screenshot](../../assets/img/agent_ui.png)
![project-screenshot](../../assets/img/agent_ui_result.png)
## 🧐 Features
Here're some of the project's features:
- Create AgentProvide more precise answers based on user queries, showcase the high-quality output process of complex queries across different dimensions, and consolidate information to present comprehensive answers.
## 🛠️ Get it Running
1. Clone the repo.
2. cd command to the current folder.
```
cd AgentQnA/ui/svelte
```
3. Modify the required .env variables. The `AGENT_URL` should be in the form of the following:
```
AGENT_URL = "http://${ip_address}:${agent_port}/v1/chat/completions"
```
For example: assume that the ip address of the host machine is 10.10.10.1, and the agent port is 9090,then
```
AGENT_URL = "http://10.10.10.1:9090/v1/chat/completions"
```
You can get the ip address of the host machine by running the command below:
```bash
export ip_address=$(hostname -I | awk '{print $1}')
```
4. **For Local Development:**
- Install the dependencies:
```
npm install
```
- Start the development server:
```
npm run dev
```
- The application will be available at `http://localhost:5173`.
5. **For Docker Setup:**
- Build the Docker image:
```
docker build -t opea:agent-ui .
```
- Run the Docker container:
```
docker run -d -p 5173:5173 --name agent-ui opea:agent-ui
```
- The application will be available at `http://${ip_address}:5173`. You can access it with a web browser on your laptop. Note the `ip_address` should be the ip address of the host machine where the UI container runs.

View File

@@ -0,0 +1,60 @@
{
"name": "agent-example",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev --host 0.0.0.0",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
"devDependencies": {
"@fortawesome/free-solid-svg-icons": "6.2.0",
"@sveltejs/adapter-auto": "1.0.0-next.75",
"@sveltejs/kit": "^1.20.1",
"@tailwindcss/typography": "0.5.7",
"@types/debug": "4.1.7",
"@typescript-eslint/eslint-plugin": "^5.27.0",
"@typescript-eslint/parser": "^5.27.0",
"autoprefixer": "^10.4.7",
"daisyui": "^2.52.0",
"debug": "4.3.4",
"eslint": "^8.16.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-neverthrow": "1.1.4",
"eslint-plugin-svelte3": "^4.0.0",
"neverthrow": "5.0.0",
"pocketbase": "0.7.0",
"postcss": "^8.4.23",
"postcss-load-config": "^4.0.1",
"postcss-preset-env": "^8.3.2",
"prettier": "^2.8.8",
"prettier-plugin-svelte": "^2.7.0",
"prettier-plugin-tailwindcss": "^0.3.0",
"svelte": "^3.59.1",
"svelte-check": "^2.7.1",
"svelte-fa": "3.0.3",
"svelte-preprocess": "^4.10.7",
"tailwindcss": "^3.1.5",
"ts-pattern": "4.0.5",
"tslib": "^2.3.1",
"typescript": "^4.7.4",
"vite": "^4.3.9"
},
"type": "module",
"dependencies": {
"@heroicons/vue": "^2.1.5",
"echarts": "^5.4.2",
"flowbite-svelte": "^0.38.5",
"flowbite-svelte-icons": "^0.3.6",
"fuse.js": "^6.6.2",
"marked": "^15.0.0",
"ramda": "^0.29.0",
"sjcl": "^1.0.8",
"sse.js": "^0.6.1",
"svelte-notifications": "^0.9.98"
}
}

View File

@@ -0,0 +1,13 @@
const tailwindcss = require("tailwindcss");
const autoprefixer = require("autoprefixer");
const config = {
plugins: [
//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
tailwindcss(),
//But others, like autoprefixer, need to run after,
autoprefixer,
],
};
module.exports = config;

50
AgentQnA/ui/svelte/src/app.d.ts vendored Normal file
View File

@@ -0,0 +1,50 @@
// Copyright (C) 2025 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
// See: https://kit.svelte.dev/docs/types#app
// import { Result} from "neverthrow";
declare namespace App {
interface Locals {
user?: User;
}
// interface PageData { }
// interface PageError {}
// interface Platform {}
}
interface User {
id?: string;
email: string;
password?: string;
token?: string;
[key: string]: any;
}
type AuthResponse = Result<User>;
interface AuthAdapter {
login(props: { email: string; password: string }): Promise<AuthResponse>;
signup(props: { email: string; password: string; password_confirm: string }): Promise<AuthResponse>;
validate_session(props: { token: string }): Promise<AuthResponse>;
logout(props: { token: string; email: string }): Promise<Result<void>>;
forgotPassword(props: { email: string; password: string }): Promise<Result<void>>;
}
interface ChatAdapter {
modelList(props: {}): Promise<Result<void>>;
txt2img(props: {}): Promise<Result<void>>;
}
interface ChatMessage {
role: string;
content: string;
}
interface ChatMessageType {
model: string;
knowledge: string;
temperature: string;
max_new_tokens: string;
topk: string;
}

View File

@@ -0,0 +1,17 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body>
<div>%sveltekit.body%</div>
</body>
</html>

View File

@@ -0,0 +1,82 @@
/* Write your global styles here, in PostCSS syntax */
@tailwind base;
@tailwind components;
@tailwind utilities;
.btn {
@apply flex-nowrap;
}
a.btn {
@apply no-underline;
}
.input {
@apply text-base;
}
.bg-dark-blue {
background-color: #004a86;
}
.bg-light-blue {
background-color: #0068b5;
}
.bg-turquoise {
background-color: #00a3f6;
}
.bg-header {
background-color: #ffffff;
}
.bg-button {
background-color: #0068b5;
}
.bg-title {
background-color: #f7f7f7;
}
.text-header {
color: #0068b5;
}
.text-button {
color: #0071c5;
}
.text-title-color {
color: rgb(38,38,38);
}
.font-intel {
font-family: "intel-clear","tahoma",Helvetica,"helvetica",Arial,sans-serif;
}
.font-title-intel {
font-family: "intel-one","intel-clear",Helvetica,Arial,sans-serif;
}
.bg-footer {
background-color: #e7e7e7;
}
.bg-light-green {
background-color: #d7f3a1;
}
.bg-purple {
background-color: #653171;
}
.bg-dark-blue {
background-color: #224678;
}
.border-input-color {
border-color: #605e5c;
}
.w-12\/12 {
width: 100%
}

View File

@@ -0,0 +1,25 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg
t="1731984271860"
class="w-8 h-8"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="11418"
width="200"
height="200"
><path
d="M0 0m170.666667 0l682.666666 0q170.666667 0 170.666667 170.666667l0 682.666666q0 170.666667-170.666667 170.666667l-682.666666 0q-170.666667 0-170.666667-170.666667l0-682.666666q0-170.666667 170.666667-170.666667Z"
fill="#1890FF"
fill-opacity=".1"
p-id="11419"
/><path
d="M404.352 552.661333a63.018667 63.018667 0 1 0 0-125.994666 63.018667 63.018667 0 0 0 0 125.994666z m0 213.333334a63.018667 63.018667 0 1 0 0-125.994667 63.018667 63.018667 0 0 0 0 125.994667z m-213.333333-426.666667a63.018667 63.018667 0 1 0 0-125.994667 63.018667 63.018667 0 0 0 0 125.994667z m669.653333-10.88H376.362667a35.669333 35.669333 0 0 1-35.114667-36.096c0-19.882667 15.786667-36.096 35.114667-36.096h484.394666c19.370667 0 35.157333 16.213333 35.157334 36.096a35.669333 35.669333 0 0 1-35.242667 36.096z m16.384 213.034667h-260.821333c-10.410667 0-18.901333-16.213333-18.901334-36.096 0-19.925333 8.490667-36.138667 18.901334-36.138667h260.864c10.410667 0 18.901333 16.213333 18.901333 36.138667-0.042667 19.882667-8.490667 36.096-18.944 36.096z m0 212.992h-260.821333c-10.410667 0-18.901333-16.213333-18.901334-36.096 0-19.925333 8.490667-36.096 18.901334-36.096h260.864c10.410667 0 18.901333 16.213333 18.901333 36.096-0.042667 19.882667-8.490667 36.096-18.944 36.096z"
fill="#1890FF"
p-id="11420"
/></svg
>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,9 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg class="w-3.5 h-3.5 me-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M14.707 7.793a1 1 0 0 0-1.414 0L11 10.086V1.5a1 1 0 0 0-2 0v8.586L6.707 7.793a1 1 0 1 0-1.414 1.414l4 4a1 1 0 0 0 1.416 0l4-4a1 1 0 0 0-.002-1.414Z"/>
<path d="M18 12h-2.55l-2.975 2.975a3.5 3.5 0 0 1-4.95 0L4.55 12H2a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2Zm-3 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"/>
</svg>

After

Width:  |  Height:  |  Size: 559 B

View File

@@ -0,0 +1,16 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg
class="me-2 h-3 w-3"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 14"
>
<path
d="M10 0C4.612 0 0 5.336 0 7c0 1.742 3.546 7 10 7 6.454 0 10-5.258 10-7 0-1.664-4.612-7-10-7Zm0 10a3 3 0 1 1 0-6 3 3 0 0 1 0 6Z"
/>
</svg>

After

Width:  |  Height:  |  Size: 413 B

View File

@@ -0,0 +1,97 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<!-- <svg class="h-11 w-11 flex-none overflow-visible" fill="none"
><defs
><filter
id="step-icon-2"
x="-3"
y="-1"
width="50"
height="50"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"
><feFlood flood-opacity="0" result="BackgroundImageFix" /><feColorMatrix
in="SourceAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
/><feOffset dy="2" /><feGaussianBlur stdDeviation="2.5" /><feComposite
in2="hardAlpha"
operator="out"
/><feColorMatrix
values="0 0 0 0 0.054902 0 0 0 0 0.647059 0 0 0 0 0.913725 0 0 0 0.12 0"
/><feBlend
in2="BackgroundImageFix"
result="effect1_dropShadow_804_95228"
/><feBlend
in="SourceGraphic"
in2="effect1_dropShadow_804_95228"
result="shape"
/></filter
></defs
><g filter="url(#step-icon-2)"
><path
d="M2.75 10A7.25 7.25 0 0 1 10 2.75h24A7.25 7.25 0 0 1 41.25 10v24A7.25 7.25 0 0 1 34 41.25H10A7.25 7.25 0 0 1 2.75 34V10Z"
fill="#EEF2FF"
/><path
d="M2.75 10A7.25 7.25 0 0 1 10 2.75h24A7.25 7.25 0 0 1 41.25 10v24A7.25 7.25 0 0 1 34 41.25H10A7.25 7.25 0 0 1 2.75 34V10Z"
stroke="#6366F1"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/></g
><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M23 35.25c.69 0 1.25-.56 1.25-1.25A3.75 3.75 0 0 1 28 30.25a1.25 1.25 0 1 0 0-2.5A3.75 3.75 0 0 1 24.25 24a1.25 1.25 0 1 0-2.5 0A3.75 3.75 0 0 1 18 27.75a1.25 1.25 0 0 0 0 2.5A3.75 3.75 0 0 1 21.75 34c0 .69.56 1.25 1.25 1.25Z"
fill="#fff"
/><path
d="M28 27a.75.75 0 0 0 0 1.5V27Zm-4.5 7a.5.5 0 0 1-.5.5V36a2 2 0 0 0 2-2h-1.5Zm5-5a.5.5 0 0 1-.5.5V31a2 2 0 0 0 2-2h-1.5Zm-.5-.5a.5.5 0 0 1 .5.5H30a2 2 0 0 0-2-2v1.5Zm-5-5a.5.5 0 0 1 .5.5H25a2 2 0 0 0-2-2v1.5Zm-.5.5a.5.5 0 0 1 .5-.5V22a2 2 0 0 0-2 2h1.5Zm-5 5a.5.5 0 0 1 .5-.5V27a2 2 0 0 0-2 2h1.5Zm.5.5a.5.5 0 0 1-.5-.5H16a2 2 0 0 0 2 2v-1.5Zm5 5a.5.5 0 0 1-.5-.5H21a2 2 0 0 0 2 2v-1.5ZM18 31a3 3 0 0 1 3 3h1.5a4.5 4.5 0 0 0-4.5-4.5V31Zm3-7a3 3 0 0 1-3 3v1.5a4.5 4.5 0 0 0 4.5-4.5H21Zm7 3a3 3 0 0 1-3-3h-1.5a4.5 4.5 0 0 0 4.5 4.5V27Zm-3 7a3 3 0 0 1 3-3v-1.5a4.5 4.5 0 0 0-4.5 4.5H25Z"
fill="#6366F1"
/><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M13 27.25c.69 0 1.25-.56 1.25-1.25 0-.966.784-1.75 1.75-1.75a1.25 1.25 0 1 0 0-2.5A1.75 1.75 0 0 1 14.25 20a1.25 1.25 0 1 0-2.5 0A1.75 1.75 0 0 1 10 21.75a1.25 1.25 0 0 0 0 2.5c.966 0 1.75.784 1.75 1.75 0 .69.56 1.25 1.25 1.25Z"
fill="#fff"
/><path
d="M16 21a.75.75 0 0 0 0 1.5V21Zm-2.5 5a.5.5 0 0 1-.5.5V28a2 2 0 0 0 2-2h-1.5Zm3-3a.5.5 0 0 1-.5.5V25a2 2 0 0 0 2-2h-1.5Zm-.5-.5a.5.5 0 0 1 .5.5H18a2 2 0 0 0-2-2v1.5Zm-3-3a.5.5 0 0 1 .5.5H15a2 2 0 0 0-2-2v1.5Zm-.5.5a.5.5 0 0 1 .5-.5V18a2 2 0 0 0-2 2h1.5Zm-3 3a.5.5 0 0 1 .5-.5V21a2 2 0 0 0-2 2h1.5Zm.5.5a.5.5 0 0 1-.5-.5H8a2 2 0 0 0 2 2v-1.5Zm3 3a.5.5 0 0 1-.5-.5H11a2 2 0 0 0 2 2v-1.5ZM10 25a1 1 0 0 1 1 1h1.5a2.5 2.5 0 0 0-2.5-2.5V25Zm1-5a1 1 0 0 1-1 1v1.5a2.5 2.5 0 0 0 2.5-2.5H11Zm5 1a1 1 0 0 1-1-1h-1.5a2.5 2.5 0 0 0 2.5 2.5V21Zm-1 5a1 1 0 0 1 1-1v-1.5a2.5 2.5 0 0 0-2.5 2.5H15Z"
fill="#6366F1"
/><path
opacity=".4"
d="M29.75 35.25h2.5a3 3 0 0 0 3-3v-20.5a3 3 0 0 0-3-3h-20.5a3 3 0 0 0-3 3v5.5M12.75 14.25h18.5"
stroke="#6366F1"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/></svg
> -->
<svg
t="1731984480564"
class="h-10 w-10"
viewBox="0 0 1114 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="29550"
width="200"
height="200"
><path
d="M1081.916235 788.781176H909.312v172.634353a24.696471 24.696471 0 0 1-49.332706 0V788.781176H687.314824a24.696471 24.696471 0 0 1 0-49.362823H859.949176V566.814118a24.696471 24.696471 0 0 1 49.332706 0v172.634353h172.664471a24.696471 24.696471 0 0 1 0 49.362823z"
fill="#0972E7"
p-id="29551"
/><path
d="M174.772706 143.028706h509.831529c43.550118 0 78.516706 35.689412 78.516706 80.173176v280.576c0 44.453647-34.966588 80.173176-78.516706 80.173177H174.772706c-43.550118 0-78.516706-35.719529-78.516706-80.173177V223.171765c0-43.851294 34.966588-80.173176 78.516706-80.173177z"
fill="#CAE4FF"
p-id="29552"
/><path
d="M335.600941 910.637176H104.899765c-24.545882 0-43.550118-20.028235-43.550118-45.086117V107.098353c0-25.057882 19.636706-45.086118 44.182588-45.086118h742.912c23.913412 0 44.182588 20.028235 44.182589 44.453647V282.503529c0 16.896 13.492706 31.322353 30.659764 31.322353a30.72 30.72 0 0 0 30.689883-31.322353V106.465882C953.976471 47.585882 906.721882 0 849.046588 0H104.899765C47.224471 0 0 48.218353 0 107.098353v758.452706c0 58.88 46.622118 107.098353 104.297412 107.098353h230.671059c16.564706 0 30.659765-13.793882 30.659764-31.322353a30.027294 30.027294 0 0 0-30.057411-30.689883z"
fill="#0972E7"
p-id="29553"
/><path
d="M709.180235 219.196235c0-16.896-13.492706-31.322353-30.659764-31.322353H171.760941c-16.564706 0-30.659765 13.793882-30.659765 31.322353 0 16.926118 13.492706 31.322353 30.659765 31.322353h506.75953a30.72 30.72 0 0 0 30.659764-31.322353zM171.760941 436.525176c-16.564706 0-30.659765 13.793882-30.659765 31.322353 0 16.896 13.492706 31.322353 30.659765 31.322353h344.786824c16.564706 0 30.689882-13.793882 30.689882-31.322353 0-16.926118-13.522824-31.322353-30.689882-31.322353H171.760941z"
fill="#0972E7"
p-id="29554"
/></svg
>

View File

@@ -0,0 +1,8 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg class="h-5 w-5 flex-shrink-0 text-[#1d4dd5]" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
<path fill-rule="evenodd" d="M15.621 4.379a3 3 0 0 0-4.242 0l-7 7a3 3 0 0 0 4.241 4.243h.001l.497-.5a.75.75 0 0 1 1.064 1.057l-.498.501-.002.002a4.5 4.5 0 0 1-6.364-6.364l7-7a4.5 4.5 0 0 1 6.368 6.36l-3.455 3.553A2.625 2.625 0 1 1 9.52 9.52l3.45-3.451a.75.75 0 1 1 1.061 1.06l-3.45 3.451a1.125 1.125 0 0 0 1.587 1.595l3.454-3.553a3 3 0 0 0 0-4.242Z" clip-rule="evenodd"></path>
</svg>

After

Width:  |  Height:  |  Size: 601 B

View File

@@ -0,0 +1,13 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg
class="pointer-events-none absolute left-0 ml-4 hidden h-4 w-4 fill-current text-gray-500 group-hover:text-gray-400 sm:block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
><path
d="M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"
/></svg
>

After

Width:  |  Height:  |  Size: 413 B

View File

@@ -0,0 +1,17 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg
fill="none"
class="relative h-5 w-5"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
stroke="currentColor"
viewBox="0 0 24 24"
><path
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/></svg
>

After

Width:  |  Height:  |  Size: 369 B

View File

@@ -0,0 +1,20 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg
t="1731987484014"
class="w-5 h-5"
viewBox="0 0 1267 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="49311"
width="200"
height="200"
><path
d="M56.880762 910.214095H1194.666667a57.051429 57.051429 0 0 1 56.880762 56.905143A57.051429 57.051429 0 0 1 1194.666667 1024H56.880762A57.051429 57.051429 0 0 1 0 967.119238a57.051429 57.051429 0 0 1 56.880762-56.905143z m1024-56.880762H170.666667a114.102857 114.102857 0 0 1-113.785905-113.785904V113.785905A114.102857 114.102857 0 0 1 170.666667 0h910.214095A114.102857 114.102857 0 0 1 1194.666667 113.785905l-0.560762 625.761524C1194.105905 802.133333 1143.466667 853.333333 1080.880762 853.333333zM495.006476 227.328a198.948571 198.948571 0 0 0-63.219809 59.977143c-43.227429 63.707429-45.519238 150.747429-3.974096 215.600762 63.146667 99.547429 187.733333 120.027429 277.040762 63.146666l88.185905 88.161524a42.910476 42.910476 0 0 0 60.294095 0 42.910476 42.910476 0 0 0 0-60.294095l-88.746666-88.185905c49.493333-77.360762 40.399238-180.906667-26.745905-248.027428a198.92419 198.92419 0 0 0-242.834286-30.378667z m216.112762 170.910476a113.785905 113.785905 0 1 1-227.571809 0 113.785905 113.785905 0 0 1 227.571809 0z"
fill="#0377FF"
p-id="49312"
/></svg
>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,22 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg
t="1730766012593"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="11065"
class="w-4 h-4"
><path
d="M996.693333 494.933333l-341.333333-126.293333-126.293333-341.333333c-3.413333-13.653333-27.306667-13.653333-30.72 0l-126.293334 341.333333-341.333333 126.293333c-6.826667 3.413333-10.24 10.24-10.24 17.066667s3.413333 13.653333 10.24 17.066667l341.333333 126.293333 126.293334 341.333333c3.413333 6.826667 10.24 10.24 17.066666 10.24s13.653333-3.413333 17.066667-10.24l126.293333-341.333333 341.333334-126.293333c6.826667-3.413333 10.24-10.24 10.24-17.066667s-6.826667-13.653333-13.653334-17.066667z m-314.026666 34.133334h-153.6V682.666667c0 10.24-6.826667 17.066667-17.066667 17.066666s-17.066667-6.826667-17.066667-17.066666v-153.6H341.333333c-10.24 0-17.066667-6.826667-17.066666-17.066667s6.826667-17.066667 17.066666-17.066667h153.6V341.333333c0-10.24 6.826667-17.066667 17.066667-17.066666s17.066667 6.826667 17.066667 17.066666v153.6H682.666667c10.24 0 17.066667 6.826667 17.066666 17.066667s-6.826667 17.066667-17.066666 17.066667z"
fill="#ffffff"
p-id="11066"
/><path
d="M293.546667 703.146667l-136.533334 136.533333c-6.826667 6.826667-6.826667 17.066667 0 23.893333 3.413333 3.413333 6.826667 3.413333 13.653334 3.413334s10.24 0 13.653333-3.413334l136.533333-136.533333c6.826667-6.826667 6.826667-17.066667 0-23.893333s-20.48-6.826667-27.306666 0zM716.8 324.266667c3.413333 0 10.24 0 13.653333-3.413334l136.533334-136.533333c6.826667-6.826667 6.826667-17.066667 0-23.893333s-17.066667-6.826667-23.893334 0l-136.533333 136.533333c-6.826667 6.826667-6.826667 17.066667 0 23.893333 0 0 6.826667 3.413333 10.24 3.413334zM293.546667 317.44c3.413333 3.413333 10.24 6.826667 13.653333 6.826667s10.24 0 13.653333-3.413334c6.826667-6.826667 6.826667-17.066667 0-23.893333l-136.533333-136.533333c-6.826667-6.826667-17.066667-6.826667-23.893333 0s-6.826667 17.066667 0 23.893333l133.12 133.12zM730.453333 703.146667c-6.826667-6.826667-17.066667-6.826667-23.893333 0s-6.826667 17.066667 0 23.893333l136.533333 136.533333c3.413333 3.413333 6.826667 3.413333 13.653334 3.413334s10.24 0 13.653333-3.413334c6.826667-6.826667 6.826667-17.066667 0-23.893333l-139.946667-136.533333z"
fill="#ffffff"
p-id="11067"
/></svg
>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,44 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg
t="1731984744752"
class="w-12 h-12"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="31753"
width="200"
height="200"
><path
d="M244.224 370.78016h526.336c48.64 0 87.552 39.424 87.552 87.552v292.352c0 48.64-39.424 87.552-87.552 87.552H244.224c-48.64 0-87.552-39.424-87.552-87.552v-292.352c-0.512-48.128 38.912-87.552 87.552-87.552z"
fill="#CAE4FF"
p-id="31754"
/><path
d="M760.832 983.30624H245.76c-114.176 0-206.848-92.672-206.848-206.848v-357.888c0-114.176 92.672-206.336 206.848-206.848h515.072c114.176 0 206.336 92.672 206.848 206.848v357.888c0 114.176-92.672 206.848-206.848 206.848zM245.76 270.09024c-81.92 0-148.48 66.56-148.48 148.48v357.888c0 81.92 66.56 148.48 148.48 148.48h515.072c81.92 0 148.48-66.56 148.48-148.48v-357.888c0-81.92-66.56-148.48-148.48-148.48H245.76z"
fill="#0972E7"
p-id="31755"
/><path
d="M303.616 748.29824c0.512 14.848-11.264 27.648-26.112 28.16-14.848 0.512-27.648-11.264-28.16-26.112v-291.328c0.512-14.848 13.312-26.624 28.16-26.112 14.336 0.512 25.6 11.776 26.112 26.112v289.28z"
fill="#0972E7"
p-id="31756"
/><path
d="M742.912 758.53824c0 13.824-11.264 25.088-25.088 25.088H274.432c-13.824 0.512-25.6-9.728-26.112-23.552-0.512-13.824 9.728-25.6 23.552-26.112h446.464c13.312 0 24.576 11.264 24.576 24.576z m-261.12-224.768c-9.728-10.24-26.112-10.24-36.352-0.512l-78.848 79.36c-10.24 10.24-10.24 26.624 0 36.864 9.728 10.24 26.112 10.24 36.352 0.512l79.36-78.848c9.728-10.752 9.728-27.136-0.512-37.376z"
fill="#0972E7"
p-id="31757"
/><path
d="M564.736 648.97024c10.24-9.728 10.24-26.112 0-36.352l-79.36-78.848c-10.24-10.24-26.624-10.24-36.864 0-10.24 9.728-10.24 26.112 0 36.352l78.848 78.848c10.752 10.24 27.136 10.24 37.376 0z"
fill="#0972E7"
p-id="31758"
/><path
d="M649.216 533.77024c-9.728-10.24-26.112-10.24-36.352-0.512l-79.36 78.848c-10.24 10.24-10.24 26.624 0 36.864 9.728 10.24 26.112 10.24 36.352 0.512l79.36-78.848c9.728-10.24 9.728-26.624 0-36.864z"
fill="#0972E7"
p-id="31759"
/><path
d="M714.24 468.74624c-9.728-10.24-26.112-10.24-36.352-0.512l-79.36 78.848c-10.24 10.24-10.24 26.624 0 36.864 9.728 10.24 26.112 10.24 36.352 0.512l79.36-78.848c10.24-10.24 10.24-27.136 0-36.864zM97.792 404.74624H39.936c0-51.2-0.512-120.832-0.512-120.832 0-112.128 91.136-203.264 203.264-203.264h136.704c123.392 0 194.56 66.56 194.56 182.784h-57.856c0-83.968-44.544-124.928-136.192-124.928H242.688c-80.384 0-145.408 65.024-145.408 145.408 0 0 0.512 69.632 0.512 120.832z"
fill="#0972E7"
p-id="31760"
/></svg
>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,24 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg
t="1731987065328"
class="w-5 h-5"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="35111"
width="200"
height="200"
><path
d="M740.565333 112c63.146667 0 114.304 51.2 114.304 114.304v457.130667H169.130667V226.304c0-63.146667 51.2-114.304 114.304-114.304h457.130666z m-219.434666 326.826667H331.434667c-32 0-48 16.042667-48 48.042666l0.213333 6.186667c2.005333 27.861333 17.92 41.813333 47.786667 41.813333h189.696c32 0 48-16 48-48l-0.213334-6.186666c-1.962667-27.904-17.92-41.813333-47.786666-41.813334z m171.434666-212.522667H331.434667c-32 0-48 16-48 48l0.213333 6.186667c2.005333 27.861333 17.92 41.813333 47.786667 41.813333h361.130666c32 0 48-16 48-48l-0.213333-6.186667c-2.005333-27.904-17.92-41.813333-47.786667-41.813333z"
fill="#93C0FB"
p-id="35112"
/><path
d="M154.752 422.101333l343.68 196.096a28.586667 28.586667 0 0 0 28.330667 0l342.485333-196.010666a28.586667 28.586667 0 0 1 42.752 24.789333v350.72c0 63.146667-51.2 114.304-114.304 114.304H226.261333c-63.104 0-114.261333-51.2-114.261333-114.304v-350.805333a28.586667 28.586667 0 0 1 42.752-24.789334z"
fill="#4B96F9"
p-id="35113"
/></svg
>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,60 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg
t="1731987759041"
class="w-7 h-7"
viewBox="0 0 1230 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="50480"
width="200"
height="200"
><path
d="M455.756297 168.055915a69.477515 69.477515 0 0 1-1.687986 16.069629c-2.768298 18.837927-9.385204 26.062508-9.385204 31.058948s5.536595 6.076751 10.465515 6.07675c30.991428 0 98.51088-32.679414 196.414084-32.679414 28.695767 0 112.554925 3.848609 112.554926 32.139259C764.117632 276.154556 533.403666 351.101147 533.403666 351.101147a0.540156 0.540156 0 0 0 0.540156 0.540156h15.461954c40.511671-2.228142 140.643017-39.36384 321.662667-39.36384 118.024001 0 291.819069 21.606224 291.819069 62.590531 0 23.901886-56.783859 73.731241-116.94369 121.535013-51.7199 40.849268-122.885402 77.51233-122.885402 118.024001 0 27.007781 30.856389 31.599103 59.012001 31.599103 55.703547 0 139.02255-19.378083 193.645786-19.378083 23.766847 0 54.623236 3.848609 54.623236 27.007781 0 37.743373-262.042991 370.344191-652.710536 370.344191-44.090202 0-102.021891-6.751945-102.021891-49.896875s55.163392-108.031122 103.169721-145.301859c38.080971-29.303442 67.519451-38.216009 67.519452-43.752605 0-3.308453-11.07319-3.916128-14.921799-3.916128-32.00422 0-110.866939 16.137149-183.720427 60.767507-55.703547 34.367401-71.165502 48.208888-121.535013 73.73124-31.396545 15.529474-63.94092 37.135698-110.326783 37.135699-62.320454 0-93.784518-37.743373-93.784518-93.716999 0-63.738362 60.767506-81.495978 60.767506-143.006198C183.180272 657.571937 47.263616 698.556244 47.263616 629.821443c0-29.911117 27.007781-65.966504 33.759726-74.811552 114.242912-152.458921 226.190162-143.613873 253.805618-157.995517 31.464064-16.069629-2.768298-25.522353-25.387314-25.522352-20.998549 0-45.778188 8.304893-67.519452 17.21746-9.385204 3.848609-22.078861 16.069629-40.51167 16.069629-14.921799 0-19.378083-14.989318-19.378083-29.978636C180.95213 282.231307 374.057761 143.681393 434.757748 143.681393c15.461954 0 20.998549 8.845048 20.998549 24.374522z"
fill="#E1EBFF"
p-id="50481"
/><path
d="M898.751418 191.350125H341.513385A24.712119 24.712119 0 0 0 316.666227 216.062244v671.886061a24.712119 24.712119 0 0 0 24.847158 24.374522h557.238033a25.049716 25.049716 0 0 0 24.847158-24.374522V216.062244a24.712119 24.712119 0 0 0-24.847158-24.374521"
fill="#335DFF"
p-id="50482"
/><path
d="M847.436635 853.783463h-458.457075a25.049716 25.049716 0 0 1-24.847159-24.374522V279.463009a24.6446 24.6446 0 0 1 24.847159-24.374522h458.457075a25.049716 25.049716 0 0 1 24.847158 24.374522v549.945932a24.712119 24.712119 0 0 1-24.847158 24.374522z"
fill="#FFFFFF"
p-id="50483"
/><path
d="M58.471845 792.273243H41.389424v-17.21746a8.507451 8.507451 0 0 0-8.304893-8.304893 8.439931 8.439931 0 0 0-8.237373 8.304893v17.21746H8.304893a8.304893 8.304893 0 1 0 0 16.609785h17.082421v17.21746A8.507451 8.507451 0 0 0 33.759726 834.40538a8.57497 8.57497 0 0 0 8.237373-8.304892v-17.21746h17.082421a8.304893 8.304893 0 1 0-0.607675-16.609785z"
fill="#D2DFFF"
p-id="50484"
/><path
d="M809.355664 225.717526h-371.356983a16.204668 16.204668 0 0 1-16.542265-16.069629v-39.903996a16.204668 16.204668 0 0 1 16.542265-16.137149h371.356983a16.204668 16.204668 0 0 1 16.609785 16.069629v40.511671a16.137149 16.137149 0 0 1-16.609785 15.529474z"
fill="#8FAFFF"
p-id="50485"
/><path
d="M677.490175 181.357246H570.471845A16.542266 16.542266 0 0 1 553.659502 165.287617v-55.973625a16.137149 16.137149 0 0 1 16.542265-16.06963h107.018331a16.542266 16.542266 0 0 1 16.609785 16.06963v56.513781a16.474746 16.474746 0 0 1-16.339708 15.529473z"
fill="#8FAFFF"
p-id="50486"
/><path
d="M459.13227 688.02321h280.205723a16.272188 16.272188 0 0 1 16.542265 16.609785v8.912567a16.272188 16.272188 0 0 1-16.542265 16.609785H459.13227a16.272188 16.272188 0 0 1-16.542266-16.002109v-9.520243A17.014902 17.014902 0 0 1 459.13227 688.02321z m0-111.947251h224.569695a16.272188 16.272188 0 0 1 16.542266 16.609785v8.845049a16.272188 16.272188 0 0 1-16.542266 16.677304H459.13227a16.272188 16.272188 0 0 1-16.542266-16.069629 1.890545 1.890545 0 0 1 0-0.607675v-8.845049A16.609785 16.609785 0 0 1 459.13227 576.075959z m0-112.014769h224.569695a16.272188 16.272188 0 0 1 16.542266 16.609785v8.912567a16.272188 16.272188 0 0 1-16.677305 16.812344H459.13227a16.204668 16.204668 0 0 1-16.542266-16.00211 1.890545 1.890545 0 0 1 0-0.607676v-9.115125A16.677304 16.677304 0 0 1 459.13227 464.06119z m0-111.947251h280.205723a16.272188 16.272188 0 0 1 16.879863 16.609785v8.912568a16.272188 16.272188 0 0 1-16.542266 16.609785H459.13227A16.339707 16.339707 0 0 1 442.454965 378.108928v-9.452723A16.609785 16.609785 0 0 1 459.13227 352.113939zM247.526309 0.810233l-10.465515 18.905447a39.093762 39.093762 0 0 1-14.921799 14.921799l-18.230252 10.533034a2.160622 2.160622 0 0 0 0 3.375973l18.230252 10.465515A39.296321 39.296321 0 0 1 237.060794 74.271397l10.465515 18.837926a2.025584 2.025584 0 0 0 3.308453 0L261.300277 74.271397a38.823685 38.823685 0 0 1 14.921799-14.989319l18.230252-10.465515a2.160622 2.160622 0 0 0 0-3.375972l-18.230252-10.533035a38.621126 38.621126 0 0 1-14.921799-15.191876L250.834762 0.810233c-0.540156-0.810233-2.228142-0.810233-3.308453 0zM1057.624687 183.585388a22.754055 22.754055 0 1 1-22.011341 22.686536 21.606224 21.606224 0 0 1 22.011341-22.686536z m0-11.07319a33.759726 33.759726 0 0 0-33.084531 33.759726 33.152051 33.152051 0 1 0 66.236581 0 33.354609 33.354609 0 0 0-33.15205-33.759726z"
fill="#D2DFFF"
p-id="50487"
/><path
d="M642.785177 138.144798a22.821575 22.821575 0 0 1-22.686535 22.686535 22.281419 22.281419 0 0 1-22.551497-22.213899 1.147831 1.147831 0 0 1 0-0.472636 22.821575 22.821575 0 0 1 22.619016-22.754056 22.416458 22.416458 0 0 1 22.686536 22.2139z m68.059607 445.628379A178.791507 178.791507 0 1 0 762.969801 456.971647a179.66926 179.66926 0 0 0-52.125017 126.869049z"
fill="#FFFFFF"
p-id="50488"
/><path
d="M889.298694 436.91837a145.706976 145.706976 0 0 0-145.504417 145.909535v1.012791a145.571937 145.571937 0 1 0 291.076355 0.742714v-0.742714a146.787287 146.787287 0 0 0-145.571938-146.989845z"
fill="#2ED073"
p-id="50489"
/><path
d="M856.230925 638.373959m5.681472-5.681472l95.534667-95.534667q5.681472-5.681472 11.362944 0l0 0q5.681472 5.681472 0 11.362943l-95.534667 95.534668q-5.681472 5.681472-11.362944 0l0 0q-5.681472-5.681472 0-11.362944Z"
fill="#FFFFFF"
p-id="50490"
/><path
d="M804.217647 586.365756m5.681472-5.681472l0 0q5.681472-5.681472 11.362944 0l51.944886 51.944887q5.681472 5.681472 0 11.362944l0 0q-5.681472 5.681472-11.362944 0l-51.944886-51.944887q-5.681472-5.681472 0-11.362944Z"
fill="#FFFFFF"
p-id="50491"
/></svg
>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -0,0 +1,8 @@
<!--
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->
<svg class="w-2.5 h-2.5 text-blue-800 dark:text-blue-300" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/>
</svg>

After

Width:  |  Height:  |  Size: 451 B

Some files were not shown because too many files have changed in this diff Show More