onMessage(String message) {
19 | return bot.chat(message).onFailure().recoverWithItem(t ->
20 | "There was an error in communicating with the model server");
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-java-quarkus/app/src/main/java/io/quarkiverse/langchain4j/sample/chatbot/ImportmapResource.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.langchain4j.sample.chatbot;
2 |
3 | import jakarta.annotation.PostConstruct;
4 | import jakarta.enterprise.context.ApplicationScoped;
5 | import jakarta.ws.rs.GET;
6 | import jakarta.ws.rs.Path;
7 | import jakarta.ws.rs.Produces;
8 |
9 | import io.mvnpm.importmap.Aggregator;
10 |
11 | /**
12 | * Dynamically create the import map
13 | */
14 | @ApplicationScoped
15 | @Path("/_importmap")
16 | public class ImportmapResource {
17 | private String importmap;
18 |
19 | // See https://github.com/WICG/import-maps/issues/235
20 | // This does not seem to be supported by browsers yet...
21 | @GET
22 | @Path("/dynamic.importmap")
23 | @Produces("application/importmap+json")
24 | public String importMap() {
25 | return this.importmap;
26 | }
27 |
28 | @GET
29 | @Path("/dynamic-importmap.js")
30 | @Produces("application/javascript")
31 | public String importMapJson() {
32 | return JAVASCRIPT_CODE.formatted(this.importmap);
33 | }
34 |
35 | @PostConstruct
36 | void init() {
37 | Aggregator aggregator = new Aggregator();
38 | // Add our own mappings
39 | aggregator.addMapping("icons/", "/icons/");
40 | aggregator.addMapping("components/", "/components/");
41 | aggregator.addMapping("fonts/", "/fonts/");
42 | this.importmap = aggregator.aggregateAsJson();
43 | }
44 |
45 | private static final String JAVASCRIPT_CODE = """
46 | const im = document.createElement('script');
47 | im.type = 'importmap';
48 | im.textContent = JSON.stringify(%s);
49 | document.currentScript.after(im);
50 | """;
51 | }
52 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-java-quarkus/app/src/main/resources/META-INF/resources/components/demo-title.js:
--------------------------------------------------------------------------------
1 | import {LitElement, html, css} from 'lit';
2 |
3 | export class DemoTitle extends LitElement {
4 |
5 | static styles = css`
6 | h1 {
7 | font-family: "Red Hat Mono", monospace;
8 | font-size: 60px;
9 | font-style: normal;
10 | font-variant: normal;
11 | font-weight: 700;
12 | line-height: 26.4px;
13 | color: var(--main-highlight-text-color);
14 | }
15 |
16 | .title {
17 | text-align: center;
18 | padding: 1em;
19 | background: var(--main-bg-color);
20 | }
21 |
22 | .explanation {
23 | margin-left: auto;
24 | margin-right: auto;
25 | width: 50%;
26 | text-align: justify;
27 | font-size: 20px;
28 | }
29 |
30 | .explanation img {
31 | max-width: 60%;
32 | display: block;
33 | float:left;
34 | margin-right: 2em;
35 | margin-top: 1em;
36 | }
37 | `
38 |
39 | render() {
40 | return html`
41 |
42 |
Chatbot
43 |
44 |
45 | This demo shows how to build a simple chatbot.
46 | Click the red robot button and start chatting.
47 |
48 | `
49 | }
50 |
51 | }
52 |
53 | customElements.define('demo-title', DemoTitle);
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-java-quarkus/app/src/main/resources/META-INF/resources/images/chatbot-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/containers/ai-lab-recipes/1bace0e7c5b8aa50d723e80315eeb6a8cdee86c0/recipes/natural_language_processing/chatbot-java-quarkus/app/src/main/resources/META-INF/resources/images/chatbot-architecture.png
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-java-quarkus/app/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | quarkus.langchain4j.timeout=120s
2 | quarkus.langchain4j.openai.api-key=NOT-NECESSARY
3 | quarkus.langchain4j.openai.base-url=${MODEL_ENDPOINT}/v1/
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 | APP ?= chatbot-nodejs
3 | PORT ?= 8501
4 |
5 | include ../../common/Makefile.common
6 |
7 | RECIPE_BINARIES_PATH := $(shell realpath ../../common/bin)
8 | RELATIVE_MODELS_PATH := ../../../models
9 | RELATIVE_TESTS_PATH := ../tests
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/ai-lab.yaml:
--------------------------------------------------------------------------------
1 | version: v1.0
2 | application:
3 | type: language
4 | name: ChatBot_nodejs
5 | description: Chat with a model service in a web frontend.
6 | containers:
7 | - name: llamacpp-server
8 | contextdir: ../../../model_servers/llamacpp_python
9 | containerfile: ./base/Containerfile
10 | model-service: true
11 | backend:
12 | - llama-cpp
13 | arch:
14 | - arm64
15 | - amd64
16 | ports:
17 | - 8001
18 | image: quay.io/ai-lab/llamacpp_python:latest
19 | - name: nodejs-chat-app
20 | contextdir: app
21 | containerfile: Containerfile
22 | arch:
23 | - arm64
24 | - amd64
25 | ports:
26 | - 8501
27 | image: quay.io/ai-lab/chatbot-nodejs:latest
28 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/app/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/app/app/layout.tsx:
--------------------------------------------------------------------------------
1 | export const metadata = {
2 | title: 'Sample Node.js AI Chatbot',
3 | description: 'Sample Node.js AI Chatbot',
4 | }
5 |
6 | export default function RootLayout({
7 | children,
8 | }: {
9 | children: React.ReactNode
10 | }) {
11 | return (
12 |
13 | {children}
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/app/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | module.exports = {
3 | output: "standalone",
4 | };
5 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@langchain/community": "^0.2.18",
7 | "@langchain/core": "^0.2.14",
8 | "@langchain/openai": "^0.2.1",
9 | "@testing-library/jest-dom": "^5.17.0",
10 | "@testing-library/react": "^13.4.0",
11 | "@testing-library/user-event": "^13.5.0",
12 | "next": "^14.2.5",
13 | "react": "^18.3.1",
14 | "react-chatbotify": "^1.7.0",
15 | "react-dom": "^18.3.1",
16 | "react-scripts": "5.0.1",
17 | "socket.io": "^4.7.2",
18 | "socket.io-client": "^4.7.2",
19 | "web-vitals": "^2.1.4"
20 | },
21 | "devDependencies": {
22 | "autoprefixer": "^10.4.20",
23 | "eslint": "^8",
24 | "eslint-config-next": "14.0.3",
25 | "postcss": "^8.4.39",
26 | "tailwindcss": "^3.4.16"
27 | },
28 | "overrides": {
29 | "typescript": "^5.5.3",
30 | "@langchain/core": "^0.2.14"
31 | },
32 | "scripts": {
33 | "dev": "next dev -p 8501",
34 | "build": "next build",
35 | "lint": "next lint"
36 | },
37 | "eslintConfig": {
38 | "extends": [
39 | "react-app",
40 | "react-app/jest"
41 | ]
42 | },
43 | "browserslist": {
44 | "production": [
45 | ">0.2%",
46 | "not dead",
47 | "not op_mini all"
48 | ],
49 | "development": [
50 | "last 1 chrome version",
51 | "last 1 firefox version",
52 | "last 1 safari version"
53 | ]
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/bootc/Containerfile.nocache:
--------------------------------------------------------------------------------
1 | # Example: an AI powered sample application is embedded as a systemd service
2 | # via Podman quadlet files in /usr/share/containers/systemd
3 | #
4 | # from recipes/natural_language_processing/chatbot-nodejs, run
5 | # 'make bootc'
6 |
7 | FROM quay.io/centos-bootc/centos-bootc:stream9
8 | ARG SSHPUBKEY
9 |
10 | # The --build-arg "SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)" option inserts your
11 | # public key into the image, allowing root access via ssh.
12 | RUN set -eu; mkdir -p /usr/ssh && \
13 | echo 'AuthorizedKeysFile /usr/ssh/%u.keys .ssh/authorized_keys .ssh/authorized_keys2' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
14 | echo ${SSHPUBKEY} > /usr/ssh/root.keys && chmod 0600 /usr/ssh/root.keys
15 |
16 | ARG RECIPE=chatbot-nodejs
17 |
18 | # Include growfs service
19 | COPY build/usr/lib /usr/lib
20 | COPY --chmod=0755 build/usr/libexec/bootc-generic-growpart /usr/libexec/bootc-generic-growpart
21 |
22 | # Add quadlet files to setup system to automatically run AI application on boot
23 | COPY build/${RECIPE}.image build/${RECIPE}.kube build/${RECIPE}.yaml /usr/share/containers/systemd
24 |
25 | # Added for running as an OCI Container to prevent Overlay on Overlay issues.
26 | VOLUME /var/lib/containers
27 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/quadlet/README.md:
--------------------------------------------------------------------------------
1 | ### Run chatbot as a systemd service
2 |
3 | ```bash
4 | (cd ../;make quadlet)
5 | sudo cp ../build/chatbot-nodejs.yaml ../build/chatbot-nodejs.kube ../build/chatbot-nodejs.image /usr/share/containers/systemd/
6 | sudo /usr/libexec/podman/quadlet --dryrun #optional
7 | sudo systemctl daemon-reload
8 | sudo systemctl start chatbot-nodejs
9 | ```
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/quadlet/chatbot-nodejs.image:
--------------------------------------------------------------------------------
1 | ../../../common/quadlet/app.image
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/quadlet/chatbot-nodejs.kube:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Kubernetes YAML file used to do chatbot inferencing
3 | Documentation=man:podman-generate-systemd(1)
4 | Wants=network-online.target
5 | After=network-online.target
6 | RequiresMountsFor=%t/containers
7 |
8 | [Kube]
9 | # Point to the yaml file in the same directory
10 | Yaml=chatbot-nodejs.yaml
11 |
12 | [Service]
13 | Restart=always
14 |
15 | [Install]
16 | WantedBy=default.target
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-nodejs/quadlet/chatbot-nodejs.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: chatbot-nodejs
6 | name: chatbot-nodejs
7 | spec:
8 | initContainers:
9 | - name: model-file
10 | image: MODEL_IMAGE
11 | command: ['/usr/bin/install', "/model/model.file", "/shared/"]
12 | volumeMounts:
13 | - name: model-file
14 | mountPath: /shared
15 | containers:
16 | - env:
17 | - name: MODEL_ENDPOINT
18 | value: http://0.0.0.0:8001
19 | image: APP_IMAGE
20 | name: chatbot-nodejs-inference
21 | ports:
22 | - containerPort: 8501
23 | hostPort: 8501
24 | securityContext:
25 | runAsNonRoot: true
26 | - env:
27 | - name: HOST
28 | value: 0.0.0.0
29 | - name: PORT
30 | value: 8001
31 | - name: MODEL_PATH
32 | value: /model/model.file
33 | image: SERVER_IMAGE
34 | name: chatbot-model-service
35 | ports:
36 | - containerPort: 8001
37 | hostPort: 8001
38 | securityContext:
39 | runAsNonRoot: true
40 | volumeMounts:
41 | - name: model-file
42 | mountPath: /model
43 | volumes:
44 | - name: model-file
45 | emptyDir: {}
46 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-pydantic-ai/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 | APP ?= chatbot-pydantic-ai
3 | PORT ?= 8501
4 |
5 | include ../../common/Makefile.common
6 |
7 | RECIPE_BINARIES_PATH := $(shell realpath ../../common/bin)
8 | RELATIVE_MODELS_PATH := ../../../models
9 | RELATIVE_TESTS_PATH := ../tests
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-pydantic-ai/ai-lab.yaml:
--------------------------------------------------------------------------------
1 | version: v1.0
2 | application:
3 | type: language
4 | name: chatbot-pydantic-ai
5 | description: Chat with a model service in a web frontend with history using pydantic ai framework.
6 | containers:
7 | - name: llamacpp-server
8 | contextdir: ../../../model_servers/llamacpp_python
9 | containerfile: ./base/Containerfile
10 | model-service: true
11 | backend:
12 | - llama-cpp
13 | arch:
14 | - arm64
15 | - amd64
16 | ports:
17 | - 8001
18 | image: quay.io/ai-lab/llamacpp_python:latest
19 | - name: streamlit-chat-app
20 | contextdir: app
21 | containerfile: Containerfile
22 | arch:
23 | - arm64
24 | - amd64
25 | ports:
26 | - 8501
27 | image: quay.io/ai-lab/chatbot-pydantic-ai:latest
28 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-pydantic-ai/app/Containerfile:
--------------------------------------------------------------------------------
1 | FROM registry.access.redhat.com/ubi9/python-311:1-77.1726664316
2 | WORKDIR /chatbot-pydantic-ai
3 | # Ensure the default user has the correct permissions on the working directory
4 | RUN chown -R 1001:0 /chatbot-pydantic-ai
5 | COPY requirements.txt .
6 | RUN pip install --upgrade pip
7 | RUN pip install --no-cache-dir --upgrade -r /chatbot-pydantic-ai/requirements.txt
8 | COPY chatbot-pydantic-ai.py .
9 | EXPOSE 8501
10 | ENTRYPOINT [ "streamlit", "run", "chatbot-pydantic-ai.py" ]
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-pydantic-ai/app/requirements.txt:
--------------------------------------------------------------------------------
1 | streamlit==1.41.1
2 | pydantic-ai==0.0.55
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-pydantic-ai/bootc/Containerfile.nocache:
--------------------------------------------------------------------------------
1 | # Example: an AI powered sample application is embedded as a systemd service
2 | # via Podman quadlet files in /usr/share/containers/systemd
3 | #
4 | # from recipes/natural_language_processing/chatbot, run
5 | # 'make bootc'
6 |
7 | FROM quay.io/centos-bootc/centos-bootc:stream9
8 | ARG SSHPUBKEY
9 |
10 | # The --build-arg "SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)" option inserts your
11 | # public key into the image, allowing root access via ssh.
12 | RUN set -eu; mkdir -p /usr/ssh && \
13 | echo 'AuthorizedKeysFile /usr/ssh/%u.keys .ssh/authorized_keys .ssh/authorized_keys2' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
14 | echo ${SSHPUBKEY} > /usr/ssh/root.keys && chmod 0600 /usr/ssh/root.keys
15 |
16 | ARG RECIPE=chatbot-pydantic-ai
17 |
18 | # Include growfs service
19 | COPY build/usr/lib /usr/lib
20 | COPY --chmod=0755 build/usr/libexec/bootc-generic-growpart /usr/libexec/bootc-generic-growpart
21 |
22 | # Add quadlet files to setup system to automatically run AI application on boot
23 | COPY build/${RECIPE}.image build/${RECIPE}.kube build/${RECIPE}.yaml /usr/share/containers/systemd
24 |
25 | # Added for running as an OCI Container to prevent Overlay on Overlay issues.
26 | VOLUME /var/lib/containers
27 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-pydantic-ai/provision/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Test Environment Provisioning
3 | hosts: test_environments
4 | remote_user: fedora
5 | become: true
6 | gather_facts: false
7 |
8 | tasks:
9 |
10 | - name: Wait until the instance is ready
11 | ansible.builtin.wait_for_connection:
12 | delay: 10
13 | timeout: 60
14 |
15 | - name: Gather facts for first time
16 | ansible.builtin.setup:
17 |
18 | - name: Required Packages
19 | ansible.builtin.package:
20 | name: "{{ item }}"
21 | state: present
22 | with_items:
23 | - podman
24 | - python3-libdnf5
25 |
26 | - name: Models host directory
27 | ansible.builtin.file:
28 | path: locallm/models
29 | state: directory
30 |
31 | - name: Download Model
32 | ansible.builtin.get_url:
33 | url: https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q5_K_S.gguf
34 | dest: locallm/models
35 |
36 | - name: Run Model
37 | containers.podman.podman_container:
38 | name: llamacpp_python
39 | image: ghcr.io/containers/llamacpp_python:latest
40 | state: started
41 | interactive: true
42 | tty: true
43 | detach: true
44 | ports:
45 | - 8001:8001
46 | volume:
47 | - ./locallm/models:/locallm/models:ro,Z
48 | env:
49 | MODEL_PATH: models/llama-2-7b-chat.Q5_K_S.gguf
50 | HOST: 0.0.0.0
51 | PORT: 8001
52 |
53 | - name: Run Application
54 | containers.podman.podman_container:
55 | name: chatbot
56 | image: ghcr.io/containers/chatbot-pydantic-ai:latest
57 | state: started
58 | interactive: true
59 | tty: true
60 | ports:
61 | - 8501:8501
62 | env:
63 | MODEL_ENDPOINT: http://10.88.0.1:8001
64 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-pydantic-ai/provision/requirements.yml:
--------------------------------------------------------------------------------
1 | ---
2 | collections:
3 | - name: containers.podman
4 | version: 1.13.0
5 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-pydantic-ai/quadlet/chatbot-pydantic-ai.image:
--------------------------------------------------------------------------------
1 | [Install]
2 | WantedBy=APP.service
3 |
4 | [Service]
5 | TimeoutStartSec=infinity
6 |
7 | [Image]
8 | Image=APP_IMAGE
9 | Image=MODEL_IMAGE
10 | Image=SERVER_IMAGE
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-pydantic-ai/quadlet/chatbot-pydantic-ai.kube:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Kubernetes YAML file used to do chatbot pydantic ai inferencing
3 | Documentation=man:podman-generate-systemd(1)
4 | Wants=network-online.target
5 | After=network-online.target
6 | RequiresMountsFor=%t/containers
7 |
8 | [Kube]
9 | # Point to the yaml file in the same directory
10 | Yaml=chatbot-pydantic-ai.yaml
11 |
12 | [Service]
13 | Restart=always
14 |
15 | [Install]
16 | WantedBy=default.target
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot-pydantic-ai/quadlet/chatbot-pydantic-ai.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: chatbot-pydantic-ai
6 | name: chatbot-pydantic-ai
7 | spec:
8 | initContainers:
9 | - name: model-file
10 | image: MODEL_IMAGE
11 | command: ['/usr/bin/install', "/model/model.file", "/shared/"]
12 | volumeMounts:
13 | - name: model-file
14 | mountPath: /shared
15 | containers:
16 | - env:
17 | - name: MODEL_ENDPOINT
18 | value: http://0.0.0.0:8001
19 | image: APP_IMAGE
20 | name: chatbot-pydantic-ai-inference
21 | ports:
22 | - containerPort: 8501
23 | hostPort: 8501
24 | securityContext:
25 | runAsNonRoot: true
26 | - env:
27 | - name: HOST
28 | value: 0.0.0.0
29 | - name: PORT
30 | value: 8001
31 | - name: MODEL_PATH
32 | value: /model/model.file
33 | image: SERVER_IMAGE
34 | name: chatbot-pydantic-ai-model-service
35 | ports:
36 | - containerPort: 8001
37 | hostPort: 8001
38 | securityContext:
39 | runAsNonRoot: true
40 | volumeMounts:
41 | - name: model-file
42 | mountPath: /model
43 | volumes:
44 | - name: model-file
45 | emptyDir: {}
46 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 | APP ?= chatbot
3 | PORT ?= 8501
4 |
5 | include ../../common/Makefile.common
6 |
7 | RECIPE_BINARIES_PATH := $(shell realpath ../../common/bin)
8 | RELATIVE_MODELS_PATH := ../../../models
9 | RELATIVE_TESTS_PATH := ../tests
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/ai-lab.yaml:
--------------------------------------------------------------------------------
1 | version: v1.0
2 | application:
3 | type: language
4 | name: ChatBot_Streamlit
5 | description: Chat with a model service in a web frontend.
6 | containers:
7 | - name: llamacpp-server
8 | contextdir: ../../../model_servers/llamacpp_python
9 | containerfile: ./base/Containerfile
10 | model-service: true
11 | backend:
12 | - llama-cpp
13 | arch:
14 | - arm64
15 | - amd64
16 | ports:
17 | - 8001
18 | image: quay.io/ai-lab/llamacpp_python:latest
19 | - name: streamlit-chat-app
20 | contextdir: app
21 | containerfile: Containerfile
22 | arch:
23 | - arm64
24 | - amd64
25 | ports:
26 | - 8501
27 | image: quay.io/ai-lab/chatbot:latest
28 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/app/Containerfile:
--------------------------------------------------------------------------------
1 | FROM registry.access.redhat.com/ubi9/python-311:1-77.1726664316
2 | WORKDIR /chat
3 | COPY requirements.txt .
4 | RUN pip install --upgrade pip
5 | RUN pip install --no-cache-dir --upgrade -r /chat/requirements.txt
6 | COPY chatbot_ui.py .
7 | EXPOSE 8501
8 | ENTRYPOINT [ "streamlit", "run", "chatbot_ui.py" ]
9 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/app/requirements.txt:
--------------------------------------------------------------------------------
1 | langchain==0.2.3
2 | langchain-openai==0.1.7
3 | langchain-community==0.2.4
4 | streamlit==1.34.0
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/bootc/Containerfile.nocache:
--------------------------------------------------------------------------------
1 | # Example: an AI powered sample application is embedded as a systemd service
2 | # via Podman quadlet files in /usr/share/containers/systemd
3 | #
4 | # from recipes/natural_language_processing/chatbot, run
5 | # 'make bootc'
6 |
7 | FROM quay.io/centos-bootc/centos-bootc:stream9
8 | ARG SSHPUBKEY
9 |
10 | # The --build-arg "SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)" option inserts your
11 | # public key into the image, allowing root access via ssh.
12 | RUN set -eu; mkdir -p /usr/ssh && \
13 | echo 'AuthorizedKeysFile /usr/ssh/%u.keys .ssh/authorized_keys .ssh/authorized_keys2' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
14 | echo ${SSHPUBKEY} > /usr/ssh/root.keys && chmod 0600 /usr/ssh/root.keys
15 |
16 | ARG RECIPE=chatbot
17 |
18 | # Include growfs service
19 | COPY build/usr/lib /usr/lib
20 | COPY --chmod=0755 build/usr/libexec/bootc-generic-growpart /usr/libexec/bootc-generic-growpart
21 |
22 | # Add quadlet files to setup system to automatically run AI application on boot
23 | COPY build/${RECIPE}.image build/${RECIPE}.kube build/${RECIPE}.yaml /usr/share/containers/systemd
24 |
25 | # Added for running as an OCI Container to prevent Overlay on Overlay issues.
26 | VOLUME /var/lib/containers
27 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/provision/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Test Environment Provisioning
3 | hosts: test_environments
4 | remote_user: fedora
5 | become: true
6 | gather_facts: false
7 |
8 | tasks:
9 |
10 | - name: Wait until the instance is ready
11 | ansible.builtin.wait_for_connection:
12 | delay: 10
13 | timeout: 60
14 |
15 | - name: Gather facts for first time
16 | ansible.builtin.setup:
17 |
18 | - name: Required Packages
19 | ansible.builtin.package:
20 | name: "{{ item }}"
21 | state: present
22 | with_items:
23 | - podman
24 | - python3-libdnf5
25 |
26 | - name: Models host directory
27 | ansible.builtin.file:
28 | path: locallm/models
29 | state: directory
30 |
31 | - name: Download Model
32 | ansible.builtin.get_url:
33 | url: https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q5_K_S.gguf
34 | dest: locallm/models
35 |
36 | - name: Run Model
37 | containers.podman.podman_container:
38 | name: llamacpp_python
39 | image: ghcr.io/containers/llamacpp_python:latest
40 | state: started
41 | interactive: true
42 | tty: true
43 | detach: true
44 | ports:
45 | - 8001:8001
46 | volume:
47 | - ./locallm/models:/locallm/models:ro,Z
48 | env:
49 | MODEL_PATH: models/llama-2-7b-chat.Q5_K_S.gguf
50 | HOST: 0.0.0.0
51 | PORT: 8001
52 |
53 | - name: Run Application
54 | containers.podman.podman_container:
55 | name: chatbot
56 | image: ghcr.io/containers/chatbot:latest
57 | state: started
58 | interactive: true
59 | tty: true
60 | ports:
61 | - 8501:8501
62 | env:
63 | MODEL_ENDPOINT: http://10.88.0.1:8001
64 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/provision/requirements.yml:
--------------------------------------------------------------------------------
1 | ---
2 | collections:
3 | - name: containers.podman
4 | version: 1.13.0
5 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/quadlet/README.md:
--------------------------------------------------------------------------------
1 | ### Run chatbot as a systemd service
2 |
3 | ```bash
4 | (cd ../;make quadlet)
5 | sudo cp ../build/chatbot.yaml ../build/chatbot.kube ../build/chatbot.image /usr/share/containers/systemd/
6 | sudo /usr/libexec/podman/quadlet --dryrun #optional
7 | sudo systemctl daemon-reload
8 | sudo systemctl start chatbot
9 | ```
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/quadlet/chatbot.image:
--------------------------------------------------------------------------------
1 | ../../../common/quadlet/app.image
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/quadlet/chatbot.kube:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Kubernetes YAML file used to do chatbot inferencing
3 | Documentation=man:podman-generate-systemd(1)
4 | Wants=network-online.target
5 | After=network-online.target
6 | RequiresMountsFor=%t/containers
7 |
8 | [Kube]
9 | # Point to the yaml file in the same directory
10 | Yaml=chatbot.yaml
11 |
12 | [Service]
13 | Restart=always
14 |
15 | [Install]
16 | WantedBy=default.target
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/chatbot/quadlet/chatbot.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: chatbot
6 | name: chatbot
7 | spec:
8 | initContainers:
9 | - name: model-file
10 | image: MODEL_IMAGE
11 | command: ['/usr/bin/install', "/model/model.file", "/shared/"]
12 | volumeMounts:
13 | - name: model-file
14 | mountPath: /shared
15 | containers:
16 | - env:
17 | - name: MODEL_ENDPOINT
18 | value: http://0.0.0.0:8001
19 | image: APP_IMAGE
20 | name: chatbot-inference
21 | ports:
22 | - containerPort: 8501
23 | hostPort: 8501
24 | securityContext:
25 | runAsNonRoot: true
26 | - env:
27 | - name: HOST
28 | value: 0.0.0.0
29 | - name: PORT
30 | value: 8001
31 | - name: MODEL_PATH
32 | value: /model/model.file
33 | image: SERVER_IMAGE
34 | name: chatbot-model-service
35 | ports:
36 | - containerPort: 8001
37 | hostPort: 8001
38 | securityContext:
39 | runAsNonRoot: true
40 | volumeMounts:
41 | - name: model-file
42 | mountPath: /model
43 | volumes:
44 | - name: model-file
45 | emptyDir: {}
46 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 | APP ?= codegen
3 | PORT ?= 8501
4 |
5 | include ../../common/Makefile.common
6 |
7 | RECIPE_BINARIES_PATH := $(shell realpath ../../common/bin)
8 | RELATIVE_MODELS_PATH := ../../../models
9 | RELATIVE_TESTS_PATH := ../tests
10 | MODEL_IMAGE := quay.io/ai-lab/mistral-7b-code-16k-qlora:latest
11 | MODEL_NAME := mistral-7b-code-16k-qlora.Q4_K_M.gguf
12 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/ai-lab.yaml:
--------------------------------------------------------------------------------
1 | version: v1.0
2 | application:
3 | type: language
4 | name: codegen-demo
5 | description: Generate code in countless programming languages.
6 | containers:
7 | - name: llamacpp-server
8 | contextdir: ../../../model_servers/llamacpp_python
9 | containerfile: ./base/Containerfile
10 | model-service: true
11 | backend:
12 | - llama-cpp
13 | arch:
14 | - arm64
15 | - amd64
16 | ports:
17 | - 8001
18 | image: quay.io/ai-lab/llamacpp_python:latest
19 | - name: codegen-app
20 | contextdir: app
21 | containerfile: Containerfile
22 | arch:
23 | - arm64
24 | - amd64
25 | ports:
26 | - 8501
27 | image: quay.io/ai-lab/codegen:latest
28 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/app/Containerfile:
--------------------------------------------------------------------------------
1 | FROM registry.access.redhat.com/ubi9/python-311:1-77.1726664316
2 | WORKDIR /codegen
3 | COPY requirements.txt .
4 | RUN pip install --upgrade pip
5 | RUN pip install --no-cache-dir --upgrade -r /codegen/requirements.txt
6 | COPY codegen-app.py .
7 | EXPOSE 8501
8 | ENTRYPOINT ["streamlit", "run", "codegen-app.py"]
9 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/app/requirements.txt:
--------------------------------------------------------------------------------
1 | langchain==0.1.20
2 | langchain-openai==0.1.7
3 | streamlit==1.34.0
4 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/bootc/Containerfile.nocache:
--------------------------------------------------------------------------------
1 | # Example: an AI powered sample application is embedded as a systemd service
2 | # via Podman quadlet files in /usr/share/containers/systemd
3 | #
4 | # from recipes/natural_language_processing/codegen, run
5 | # 'make bootc'
6 |
7 | FROM quay.io/centos-bootc/centos-bootc:stream9
8 | ARG SSHPUBKEY
9 |
10 | # The --build-arg "SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)" option inserts your
11 | # public key into the image, allowing root access via ssh.
12 | RUN set -eu; mkdir -p /usr/ssh && \
13 | echo 'AuthorizedKeysFile /usr/ssh/%u.keys .ssh/authorized_keys .ssh/authorized_keys2' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
14 | echo ${SSHPUBKEY} > /usr/ssh/root.keys && chmod 0600 /usr/ssh/root.keys
15 |
16 | ARG RECIPE=codegen
17 |
18 | # Add quadlet files to setup system to automatically run AI application on boot
19 | COPY build/${RECIPE}.image build/${RECIPE}.kube build/${RECIPE}.yaml /usr/share/containers/systemd
20 |
21 | # Added for running as an OCI Container to prevent Overlay on Overlay issues.
22 | VOLUME /var/lib/containers
23 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/provision/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Test Environment Provisioning
3 | hosts: test_environments
4 | remote_user: fedora
5 | become: true
6 | gather_facts: false
7 |
8 | tasks:
9 |
10 | - name: Wait until the instance is ready
11 | ansible.builtin.wait_for_connection:
12 | delay: 10
13 | timeout: 60
14 |
15 | - name: Gather facts for first time
16 | ansible.builtin.setup:
17 |
18 | - name: Required Packages
19 | ansible.builtin.package:
20 | name: podman
21 | state: present
22 |
23 | - name: Models host directory
24 | ansible.builtin.file:
25 | path: locallm/models
26 | state: directory
27 |
28 | - name: Download Model
29 | ansible.builtin.get_url:
30 | url: https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q5_K_S.gguf
31 | dest: locallm/models
32 |
33 | - name: Run Model
34 | containers.podman.podman_container:
35 | name: llamacpp_python
36 | image: ghcr.io/containers/llamacpp_python:latest
37 | state: started
38 | interactive: true
39 | tty: true
40 | detach: true
41 | ports:
42 | - 8001:8001
43 | volume:
44 | - ./locallm/models:/locallm/models:ro,Z
45 | env:
46 | MODEL_PATH: models/llama-2-7b-chat.Q5_K_S.gguf
47 | HOST: 0.0.0.0
48 | PORT: 8001
49 |
50 | - name: Run Application
51 | containers.podman.podman_container:
52 | name: codegen
53 | image: ghcr.io/containers/codegen:latest
54 | state: started
55 | interactive: true
56 | tty: true
57 | ports:
58 | - 8501:8501
59 | env:
60 | MODEL_SERVICE_ENDPOINT: http://10.88.0.1:8001/v1
61 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/provision/requirements.yml:
--------------------------------------------------------------------------------
1 | ---
2 | collections:
3 | - name: containers.podman
4 | version: 1.13.0
5 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/quadlet/README.md:
--------------------------------------------------------------------------------
1 | ### Run codegen as a systemd service
2 |
3 | ```bash
4 | (cd ../;make quadlet)
5 | sudo cp ../build/codegen.yaml ../build/codegen.kube /usr/share/containers/systemd/codegen.kube ../build/codegen.image /usr/share/containers/systemd/
6 | sudo /usr/libexec/podman/quadlet --dryrun #optional
7 | sudo systemctl daemon-reload
8 | sudo systemctl start codegen
9 | ```
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/quadlet/codegen.image:
--------------------------------------------------------------------------------
1 | ../../../common/quadlet/app.image
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/quadlet/codegen.kube:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Python script to run against downloaded LLM
3 | Documentation=man:podman-generate-systemd(1)
4 | Wants=network-online.target
5 | After=network-online.target
6 | RequiresMountsFor=%t/containers
7 |
8 | [Kube]
9 | # Point to the yaml file in the same directory
10 | Yaml=codegen.yaml
11 |
12 | [Service]
13 | Restart=always
14 |
15 | [Install]
16 | WantedBy=default.target
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/codegen/quadlet/codegen.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: codegen
6 | name: codegen
7 | spec:
8 | initContainers:
9 | - name: model-file
10 | image: MODEL_IMAGE
11 | command: ['/usr/bin/install', "/model/model.file", "/shared/"]
12 | volumeMounts:
13 | - name: model-file
14 | mountPath: /shared
15 | containers:
16 | - env:
17 | - name: MODEL_ENDPOINT
18 | value: http://0.0.0.0:8001
19 | image: APP_IMAGE
20 | name: codegen-inference
21 | ports:
22 | - containerPort: 8501
23 | hostPort: 8501
24 | securityContext:
25 | runAsNonRoot: true
26 | - env:
27 | - name: HOST
28 | value: 0.0.0.0
29 | - name: PORT
30 | value: 8001
31 | - name: MODEL_PATH
32 | value: /model/model.file
33 | image: SERVER_IMAGE
34 | name: codegen-model-service
35 | ports:
36 | - containerPort: 8001
37 | hostPort: 8001
38 | securityContext:
39 | runAsNonRoot: true
40 | volumeMounts:
41 | - name: model-file
42 | mountPath: /model
43 | volumes:
44 | - name: model-file
45 | emptyDir: {}
46 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 | APP ?= function-calling-nodejs
3 | PORT ?= 8501
4 |
5 | include ../../common/Makefile.common
6 |
7 | RECIPE_BINARIES_PATH := $(shell realpath ../../common/bin)
8 | RELATIVE_MODELS_PATH := ../../../models
9 | RELATIVE_TESTS_PATH := ../tests
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/ai-lab.yaml:
--------------------------------------------------------------------------------
1 | version: v1.0
2 | application:
3 | type: language
4 | name: FunctionCalling_nodejs
5 | description: Call a function to get weather data.
6 | containers:
7 | - name: llamacpp-server
8 | contextdir: ../../../model_servers/llamacpp_python
9 | containerfile: ./base/Containerfile
10 | model-service: true
11 | backend:
12 | - llama-cpp
13 | arch:
14 | - arm64
15 | - amd64
16 | ports:
17 | - 8001
18 | image: quay.io/ai-lab/llamacpp_python:latest
19 | - name: nodejs-function-calling-app
20 | contextdir: app
21 | containerfile: Containerfile
22 | arch:
23 | - arm64
24 | - amd64
25 | ports:
26 | - 8501
27 | image: quay.io/ai-lab/function-calling-nodejs:latest
28 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/app/.dockerignore:
--------------------------------------------------------------------------------
1 | ./node_modules
2 |
3 | Dockerfile
4 |
5 | .dockerignore
6 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/app/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/app/Containerfile:
--------------------------------------------------------------------------------
1 | # Install the app dependencies in a full UBI Node docker image
2 | FROM registry.access.redhat.com/ubi9/nodejs-20:9.5-1746604787
3 |
4 | # Copy package.json
5 | COPY --chown=default:root --chmod=0775 package*.json ./
6 | COPY --chown=default:root --chmod=0775 ./ ./
7 |
8 | # Install npm packages
9 | RUN npm install
10 |
11 | ENV NODE_ENV production
12 |
13 | USER 1001
14 | EXPOSE 8501
15 |
16 | ENV PORT 8501
17 |
18 | CMD ["sh", "-c", "HOSTNAME=0.0.0.0 node ."]
19 |
20 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/app/ai/tools/weather.mjs:
--------------------------------------------------------------------------------
1 | import { z } from 'zod';
2 | import { tool } from '@langchain/core/tools';
3 |
4 | const weatherSchema = z.object({
5 | latitude: z.number().describe('The latitude of a place'),
6 | longitude: z.number().describe('The longitude of a place')
7 | });
8 |
9 | const weather = tool(
10 | async function ({ latitude, longitude }) {
11 | const response = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&hourly=temperature_2m`);
12 | const json = await response.json();
13 | return json;
14 | },
15 | {
16 | name: 'weather',
17 | description: 'Get the current weather in a given latitude and longitude.',
18 | schema: weatherSchema
19 | }
20 | );
21 |
22 | export default weather;
23 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "function-calling-nodejs-just-html",
3 | "version": "1.0.0",
4 | "main": "server.mjs",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1"
7 | },
8 | "keywords": [],
9 | "author": "",
10 | "license": "ISC",
11 | "description": "",
12 | "dependencies": {
13 | "@fastify/static": "^8.1.1",
14 | "@langchain/core": "^0.3.41",
15 | "@langchain/langgraph": "^0.2.49",
16 | "@langchain/openai": "^0.4.4",
17 | "fastify": "^5.2.1",
18 | "fastify-plugin": "^5.0.1",
19 | "zod": "^3.24.2"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/app/routes/temperatures.mjs:
--------------------------------------------------------------------------------
1 | import { askQuestion } from '../ai/weather-prompt.mjs';
2 |
3 | async function temperatureRoutes (fastify, options) {
4 | fastify.post('/api/temperatures', async (request, reply) => {
5 | const city = request.body.city;
6 |
7 | // Call the AI stuff
8 | const response = await askQuestion(city);
9 |
10 | return {
11 | result: response
12 | }
13 | });
14 | }
15 |
16 | export default temperatureRoutes;
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/app/server.mjs:
--------------------------------------------------------------------------------
1 | import Fastify from 'fastify';
2 | import fastifyStatic from '@fastify/static';
3 | import path from 'node:path';
4 | import { fileURLToPath } from 'url';
5 | import fs from 'node:fs';
6 | const __filename = fileURLToPath(import.meta.url);
7 | const __dirname = path.dirname(__filename);
8 |
9 | import temperatureRoute from './routes/temperatures.mjs';
10 |
11 | // Setup Logging
12 | const fastify = Fastify({
13 | logger: true
14 | });
15 |
16 | // WebUI related setup and serving
17 | const webuiLocation = './public';
18 |
19 | fastify.register(fastifyStatic, {
20 | wildcard: false,
21 | root: path.join(__dirname, webuiLocation)
22 | });
23 |
24 | fastify.get('/*', (req, res) => {
25 | res.send(fs.createReadStream(path.join(__dirname, webuiLocation, 'index.html')));
26 | });
27 |
28 | fastify.register(temperatureRoute);
29 |
30 | /**
31 | * Run the server!
32 | */
33 | const start = async () => {
34 | try {
35 | await fastify.listen({ port: process.env.PORT || 8005, host: process.env.HOSTNAME })
36 | } catch (err) {
37 | fastify.log.error(err)
38 | process.exit(1)
39 | }
40 | };
41 | start();
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/bootc/Containerfile.nocache:
--------------------------------------------------------------------------------
1 | # Example: an AI powered sample application is embedded as a systemd service
2 | # via Podman quadlet files in /usr/share/containers/systemd
3 | #
4 | # from recipes/natural_language_processing/function-calling-nodejs, run
5 | # 'make bootc'
6 |
7 | FROM quay.io/centos-bootc/centos-bootc:stream9
8 | ARG SSHPUBKEY
9 |
10 | # The --build-arg "SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)" option inserts your
11 | # public key into the image, allowing root access via ssh.
12 | RUN set -eu; mkdir -p /usr/ssh && \
13 | echo 'AuthorizedKeysFile /usr/ssh/%u.keys .ssh/authorized_keys .ssh/authorized_keys2' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
14 | echo ${SSHPUBKEY} > /usr/ssh/root.keys && chmod 0600 /usr/ssh/root.keys
15 |
16 | ARG RECIPE=function-calling-nodejs
17 |
18 | # Include growfs service
19 | COPY build/usr/lib /usr/lib
20 | COPY --chmod=0755 build/usr/libexec/bootc-generic-growpart /usr/libexec/bootc-generic-growpart
21 |
22 | # Add quadlet files to setup system to automatically run AI application on boot
23 | COPY build/${RECIPE}.image build/${RECIPE}.kube build/${RECIPE}.yaml /usr/share/containers/systemd
24 |
25 | # Added for running as an OCI Container to prevent Overlay on Overlay issues.
26 | VOLUME /var/lib/containers
27 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/quadlet/README.md:
--------------------------------------------------------------------------------
1 | ### Run chatbot as a systemd service
2 |
3 | ```bash
4 | (cd ../;make quadlet)
5 | sudo cp ../build/function-callling-nodejs.yaml ../build/function-callling-nodejs.kube ../build/function-callling-nodejs.image /usr/share/containers/systemd/
6 | sudo /usr/libexec/podman/quadlet --dryrun #optional
7 | sudo systemctl daemon-reload
8 | sudo systemctl start function-callling-nodejs
9 | ```
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/quadlet/function-calling-nodejs.image:
--------------------------------------------------------------------------------
1 | ../../../common/quadlet/app.image
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/quadlet/function-calling-nodejs.kube:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Kubernetes YAML file used to do function-calling inferencing
3 | Documentation=man:podman-generate-systemd(1)
4 | Wants=network-online.target
5 | After=network-online.target
6 | RequiresMountsFor=%t/containers
7 |
8 | [Kube]
9 | # Point to the yaml file in the same directory
10 | Yaml=function-calling-nodejs.yaml
11 |
12 | [Service]
13 | Restart=always
14 |
15 | [Install]
16 | WantedBy=default.target
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function-calling-nodejs/quadlet/function-calling-nodejs.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: function-calling-nodejs
6 | name: function-calling-nodejs
7 | spec:
8 | initContainers:
9 | - name: model-file
10 | image: MODEL_IMAGE
11 | command: ['/usr/bin/install', "/model/model.file", "/shared/"]
12 | volumeMounts:
13 | - name: model-file
14 | mountPath: /shared
15 | containers:
16 | - env:
17 | - name: MODEL_ENDPOINT
18 | value: http://0.0.0.0:8001
19 | image: APP_IMAGE
20 | name: function-calling-nodejs-inference
21 | ports:
22 | - containerPort: 8501
23 | hostPort: 8501
24 | securityContext:
25 | runAsNonRoot: true
26 | - env:
27 | - name: HOST
28 | value: 0.0.0.0
29 | - name: PORT
30 | value: 8001
31 | - name: MODEL_PATH
32 | value: /model/model.file
33 | image: SERVER_IMAGE
34 | name: chatbot-model-service
35 | ports:
36 | - containerPort: 8001
37 | hostPort: 8001
38 | securityContext:
39 | runAsNonRoot: true
40 | volumeMounts:
41 | - name: model-file
42 | mountPath: /model
43 | volumes:
44 | - name: model-file
45 | emptyDir: {}
46 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function_calling/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 | APP ?= function_calling
3 | PORT ?= 8501
4 |
5 | include ../../common/Makefile.common
6 |
7 | RECIPE_BINARIES_PATH := $(shell realpath ../../common/bin)
8 | RELATIVE_MODELS_PATH := ../../../models
9 | RELATIVE_TESTS_PATH := ../tests
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function_calling/ai-lab.yaml:
--------------------------------------------------------------------------------
1 | version: v1.0
2 | application:
3 | type: language
4 | name: Function_Calling_Streamlit
5 | description: Function calling a remote service with a model service in a web frontend.
6 | containers:
7 | - name: llamacpp-server
8 | contextdir: ../../../model_servers/llamacpp_python
9 | containerfile: ./base/Containerfile
10 | model-service: true
11 | backend:
12 | - llama-cpp
13 | arch:
14 | - arm64
15 | - amd64
16 | ports:
17 | - 8001
18 | image: quay.io/ai-lab/llamacpp_python:latest
19 | - name: streamlit-function-calling-app
20 | contextdir: app
21 | containerfile: Containerfile
22 | arch:
23 | - arm64
24 | - amd64
25 | ports:
26 | - 8501
27 | image: quay.io/ai-lab/function-calling:latest
28 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function_calling/app/Containerfile:
--------------------------------------------------------------------------------
1 | FROM registry.access.redhat.com/ubi9/python-311:1-77.1726664316
2 | WORKDIR /function-call
3 | COPY requirements.txt .
4 | RUN pip install --upgrade pip
5 | RUN pip install --no-cache-dir --upgrade -r /function-call/requirements.txt
6 | COPY *.py .
7 | EXPOSE 8501
8 | ENTRYPOINT [ "streamlit", "run", "app.py" ]
9 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function_calling/app/requirements.txt:
--------------------------------------------------------------------------------
1 | langchain==0.2.3
2 | langchain-openai==0.1.7
3 | langchain-community==0.2.4
4 | streamlit==1.34.0
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function_calling/bootc/Containerfile.nocache:
--------------------------------------------------------------------------------
1 | # Example: an AI powered sample application is embedded as a systemd service
2 | # via Podman quadlet files in /usr/share/containers/systemd
3 | #
4 | # from recipes/natural_language_processing/chatbot, run
5 | # 'make bootc'
6 |
7 | FROM quay.io/centos-bootc/centos-bootc:stream9
8 | ARG SSHPUBKEY
9 |
10 | # The --build-arg "SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)" option inserts your
11 | # public key into the image, allowing root access via ssh.
12 | RUN set -eu; mkdir -p /usr/ssh && \
13 | echo 'AuthorizedKeysFile /usr/ssh/%u.keys .ssh/authorized_keys .ssh/authorized_keys2' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
14 | echo ${SSHPUBKEY} > /usr/ssh/root.keys && chmod 0600 /usr/ssh/root.keys
15 |
16 | ARG RECIPE=function_calling
17 |
18 | # Include growfs service
19 | COPY build/usr/lib /usr/lib
20 | COPY --chmod=0755 build/usr/libexec/bootc-generic-growpart /usr/libexec/bootc-generic-growpart
21 |
22 | # Add quadlet files to setup system to automatically run AI application on boot
23 | COPY build/${RECIPE}.image build/${RECIPE}.kube build/${RECIPE}.yaml /usr/share/containers/systemd
24 |
25 | # Added for running as an OCI Container to prevent Overlay on Overlay issues.
26 | VOLUME /var/lib/containers
27 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function_calling/provision/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Test Environment Provisioning
3 | hosts: test_environments
4 | remote_user: fedora
5 | become: true
6 | gather_facts: false
7 |
8 | tasks:
9 |
10 | - name: Wait until the instance is ready
11 | ansible.builtin.wait_for_connection:
12 | delay: 10
13 | timeout: 60
14 |
15 | - name: Gather facts for first time
16 | ansible.builtin.setup:
17 |
18 | - name: Required Packages
19 | ansible.builtin.package:
20 | name: "{{ item }}"
21 | state: present
22 | with_items:
23 | - podman
24 | - python3-libdnf5
25 |
26 | - name: Models host directory
27 | ansible.builtin.file:
28 | path: locallm/models
29 | state: directory
30 |
31 | - name: Download Model
32 | ansible.builtin.get_url:
33 | url: https://huggingface.co/MaziyarPanahi/Mistral-7B-Instruct-v0.3-GGUF/resolve/main/Mistral-7B-Instruct-v0.3.Q4_K_M.gguf
34 | dest: locallm/models
35 |
36 | - name: Run Model
37 | containers.podman.podman_container:
38 | name: llamacpp_python
39 | image: ghcr.io/containers/llamacpp_python:latest
40 | state: started
41 | interactive: true
42 | tty: true
43 | detach: true
44 | ports:
45 | - 8001:8001
46 | volume:
47 | - ./locallm/models:/locallm/models:ro,Z
48 | env:
49 | MODEL_PATH: models/Mistral-7B-Instruct-v0.3.Q4_K_M.gguf
50 | HOST: 0.0.0.0
51 | PORT: 8001
52 |
53 | - name: Run Application
54 | containers.podman.podman_container:
55 | name: function_calling
56 | image: ghcr.io/containers/function_calling:latest
57 | state: started
58 | interactive: true
59 | tty: true
60 | ports:
61 | - 8501:8501
62 | env:
63 | MODEL_ENDPOINT: http://10.88.0.1:8001
64 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function_calling/provision/requirements.yml:
--------------------------------------------------------------------------------
1 | ---
2 | collections:
3 | - name: containers.podman
4 | version: 1.13.0
5 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function_calling/quadlet/README.md:
--------------------------------------------------------------------------------
1 | ### Run function calling as a systemd service
2 |
3 | ```bash
4 | (cd ../;make quadlet)
5 | sudo cp ../build/function_calling.yaml ../build/function_calling.kube ../build/function_calling.image /usr/share/containers/systemd/
6 | sudo /usr/libexec/podman/quadlet --dryrun #optional
7 | sudo systemctl daemon-reload
8 | sudo systemctl start function_calling
9 | ```
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function_calling/quadlet/function_calling.kube:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Kubernetes YAML file used to do function calling inferencing
3 | Documentation=man:podman-generate-systemd(1)
4 | Wants=network-online.target
5 | After=network-online.target
6 | RequiresMountsFor=%t/containers
7 |
8 | [Kube]
9 | # Point to the yaml file in the same directory
10 | Yaml=function_calling.yaml
11 |
12 | [Service]
13 | Restart=always
14 |
15 | [Install]
16 | WantedBy=default.target
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/function_calling/quadlet/function_calling.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: function_calling
6 | name: function_calling
7 | spec:
8 | initContainers:
9 | - name: model-file
10 | image: MODEL_IMAGE
11 | command: ['/usr/bin/install', "/model/model.file", "/shared/"]
12 | volumeMounts:
13 | - name: model-file
14 | mountPath: /shared
15 | containers:
16 | - env:
17 | - name: MODEL_ENDPOINT
18 | value: http://0.0.0.0:8001
19 | image: APP_IMAGE
20 | name: function_calling-inference
21 | ports:
22 | - containerPort: 8501
23 | hostPort: 8501
24 | securityContext:
25 | runAsNonRoot: true
26 | - env:
27 | - name: HOST
28 | value: 0.0.0.0
29 | - name: PORT
30 | value: 8001
31 | - name: MODEL_PATH
32 | value: /model/model.file
33 | image: SERVER_IMAGE
34 | name: function_calling-model-service
35 | ports:
36 | - containerPort: 8001
37 | hostPort: 8001
38 | securityContext:
39 | runAsNonRoot: true
40 | volumeMounts:
41 | - name: model-file
42 | mountPath: /model
43 | volumes:
44 | - name: model-file
45 | emptyDir: {}
46 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 | APP ?= graph-rag
3 | PORT ?= 8501
4 | # MODEL_IMAGE ?= huggingface://TheBloke/Mistral-7B-Instruct-v0.2-GGUF/mistral-7b-instruct-v0.2.Q4_K_M.gguf
5 |
6 | include ../../common/Makefile.common
7 |
8 | RECIPE_BINARIES_PATH := $(shell realpath ../../common/bin)
9 | RELATIVE_MODELS_PATH := ../../../models
10 | RELATIVE_TESTS_PATH := ../tests
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/ai-lab.yaml:
--------------------------------------------------------------------------------
1 | version: v1.0
2 | application:
3 | type: language
4 | name: Graphrag_Streamlit
5 | description: Chat with a model service in a web frontend.
6 | containers:
7 | - name: llamacpp-server
8 | contextdir: ../../../model_servers/llamacpp_python
9 | containerfile: ./base/Containerfile
10 | model-service: true
11 | backend:
12 | - llama-cpp
13 | arch:
14 | - arm64
15 | - amd64
16 | ports:
17 | - 8001
18 | image: quay.io/ai-lab/llamacpp_python:latest
19 | - name: streamlit-chat-app
20 | contextdir: app
21 | containerfile: Containerfile
22 | arch:
23 | - arm64
24 | - amd64
25 | ports:
26 | - 8501
27 | image: quay.io/ai-lab/graph-rag:latest
28 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/app/Containerfile:
--------------------------------------------------------------------------------
1 | FROM registry.access.redhat.com/ubi9/python-311:1-77.1726664316
2 |
3 | # Set the working directory
4 | WORKDIR /graph-rag
5 | # Ensure the default user has the correct permissions on the working directory
6 | RUN chown -R 1001:0 /graph-rag
7 |
8 | # Copy the application files
9 | COPY requirements.txt .
10 | COPY rag_app.py .
11 |
12 | RUN pip install --upgrade pip && \
13 | pip install --no-cache-dir --upgrade -r /graph-rag/requirements.txt
14 |
15 | # Expose the port for the application
16 | EXPOSE 8501
17 |
18 | # Set the entrypoint to run the application
19 | ENTRYPOINT [ "streamlit", "run", "rag_app.py" ]
20 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/app/requirements.txt:
--------------------------------------------------------------------------------
1 | streamlit==1.45.1
2 | langchain-graph-retriever==0.8.0
3 | langchain-huggingface==0.2.0
4 | langchain-openai==0.3.17
5 | transformers==4.52.4
6 | torch==2.7.0
7 | PyMuPDF==1.25.5
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/bootc/Containerfile.nocache:
--------------------------------------------------------------------------------
1 | # Example: an AI powered sample application is embedded as a systemd service
2 | # via Podman quadlet files in /usr/share/containers/systemd
3 | #
4 | # from recipes/natural_language_processing/chatbot, run
5 | # 'make bootc'
6 |
7 | FROM quay.io/centos-bootc/centos-bootc:stream9
8 | ARG SSHPUBKEY
9 |
10 | # The --build-arg "SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)" option inserts your
11 | # public key into the image, allowing root access via ssh.
12 | RUN set -eu; mkdir -p /usr/ssh && \
13 | echo 'AuthorizedKeysFile /usr/ssh/%u.keys .ssh/authorized_keys .ssh/authorized_keys2' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
14 | echo ${SSHPUBKEY} > /usr/ssh/root.keys && chmod 0600 /usr/ssh/root.keys
15 |
16 | ARG RECIPE=graph-rag
17 |
18 | # Include growfs service
19 | COPY build/usr/lib /usr/lib
20 | COPY --chmod=0755 build/usr/libexec/bootc-generic-growpart /usr/libexec/bootc-generic-growpart
21 |
22 | # Add quadlet files to setup system to automatically run AI application on boot
23 | COPY build/${RECIPE}.image build/${RECIPE}.kube build/${RECIPE}.yaml /usr/share/containers/systemd
24 |
25 | # Added for running as an OCI Container to prevent Overlay on Overlay issues.
26 | VOLUME /var/lib/containers
27 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/provision/playbook.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Test Environment Provisioning
3 | hosts: test_environments
4 | remote_user: fedora
5 | become: true
6 | gather_facts: false
7 |
8 | tasks:
9 |
10 | - name: Wait until the instance is ready
11 | ansible.builtin.wait_for_connection:
12 | delay: 10
13 | timeout: 60
14 |
15 | - name: Gather facts for first time
16 | ansible.builtin.setup:
17 |
18 | - name: Required Packages
19 | ansible.builtin.package:
20 | name: "{{ item }}"
21 | state: present
22 | with_items:
23 | - podman
24 | - python3-libdnf5
25 |
26 | - name: Models host directory
27 | ansible.builtin.file:
28 | path: locallm/models
29 | state: directory
30 |
31 | - name: Download Model
32 | ansible.builtin.get_url:
33 | url: https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q5_K_S.gguf
34 | dest: locallm/models
35 |
36 | - name: Run Model
37 | containers.podman.podman_container:
38 | name: llamacpp_python
39 | image: ghcr.io/containers/llamacpp_python:latest
40 | state: started
41 | interactive: true
42 | tty: true
43 | detach: true
44 | ports:
45 | - 8001:8001
46 | volume:
47 | - ./locallm/models:/locallm/models:ro,Z
48 | env:
49 | MODEL_PATH: models/llama-2-7b-chat.Q5_K_S.gguf
50 | HOST: 0.0.0.0
51 | PORT: 8001
52 |
53 | - name: Run Application
54 | containers.podman.podman_container:
55 | name: graph-rag
56 | image: ghcr.io/containers/graph-rag:latest
57 | state: started
58 | interactive: true
59 | tty: true
60 | ports:
61 | - 8501:8501
62 | env:
63 | MODEL_ENDPOINT: http://10.88.0.1:8001
64 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/provision/requirements.yml:
--------------------------------------------------------------------------------
1 | ---
2 | collections:
3 | - name: containers.podman
4 | version: 1.13.0
5 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/quadlet/README.md:
--------------------------------------------------------------------------------
1 | ### Run chatbot as a systemd service
2 |
3 | ```bash
4 | (cd ../;make quadlet)
5 | sudo cp ../build/chatbot.yaml ../build/chatbot.kube ../build/chatbot.image /usr/share/containers/systemd/
6 | sudo /usr/libexec/podman/quadlet --dryrun #optional
7 | sudo systemctl daemon-reload
8 | sudo systemctl start chatbot
9 | ```
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/quadlet/graph-rag.image:
--------------------------------------------------------------------------------
1 | ../../../common/quadlet/app.image
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/quadlet/graph-rag.kube:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Kubernetes YAML file used to do chatbot inferencing
3 | Documentation=man:podman-generate-systemd(1)
4 | Wants=network-online.target
5 | After=network-online.target
6 | RequiresMountsFor=%t/containers
7 |
8 | [Kube]
9 | # Point to the yaml file in the same directory
10 | Yaml=graph-rag.yaml
11 |
12 | [Service]
13 | Restart=always
14 |
15 | [Install]
16 | WantedBy=default.target
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/graph-rag/quadlet/graph-rag.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: graph-rag
6 | name: graph-rag
7 | spec:
8 | initContainers:
9 | - name: model-file
10 | image: MODEL_IMAGE
11 | command: ['/usr/bin/install', "/model/model.file", "/shared/"]
12 | volumeMounts:
13 | - name: model-file
14 | mountPath: /shared
15 | containers:
16 | - env:
17 | - name: MODEL_ENDPOINT
18 | value: http://0.0.0.0:8001
19 | image: APP_IMAGE
20 | name: graph-rag-inference
21 | ports:
22 | - containerPort: 8501
23 | hostPort: 8501
24 | securityContext:
25 | runAsNonRoot: true
26 | - env:
27 | - name: HOST
28 | value: 0.0.0.0
29 | - name: PORT
30 | value: 8001
31 | - name: MODEL_PATH
32 | value: /model/model.file
33 | image: SERVER_IMAGE
34 | name: graph-rag-model-service
35 | ports:
36 | - containerPort: 8001
37 | hostPort: 8001
38 | securityContext:
39 | runAsNonRoot: true
40 | volumeMounts:
41 | - name: model-file
42 | mountPath: /model
43 | volumes:
44 | - name: model-file
45 | emptyDir: {}
46 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/ai-lab.yaml:
--------------------------------------------------------------------------------
1 | version: v1.0
2 | application:
3 | type: language
4 | name: nodejs-rag-demo
5 | description: A Node.js RAG chat bot using local documents.
6 | containers:
7 | - name: llamacpp-server
8 | contextdir: ../../../model_servers/llamacpp_python
9 | containerfile: ./base/Containerfile
10 | model-service: true
11 | backend:
12 | - llama-cpp
13 | arch:
14 | - arm64
15 | - amd64
16 | ports:
17 | - 8001
18 | image: quay.io/ai-lab/llamacpp_python:latest
19 | - name: chromadb-server
20 | contextdir: ../../../vector_dbs/chromadb
21 | containerfile: Containerfile
22 | vectordb: true
23 | arch:
24 | - arm64
25 | - amd64
26 | ports:
27 | - 8000
28 | image: quay.io/ai-lab/chromadb:latest
29 | - name: nodejs-rag-inference-app
30 | contextdir: app
31 | containerfile: Containerfile
32 | arch:
33 | - arm64
34 | - amd64
35 | ports:
36 | - 8501
37 | image: quay.io/ai-lab/rag-nodejs:latest
38 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/app/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/app/app/layout.tsx:
--------------------------------------------------------------------------------
1 | export const metadata = {
2 | title: 'Sample Node.js RAG example ',
3 | description: 'Sample Node.js RAG example',
4 | }
5 |
6 | export default function RootLayout({
7 | children,
8 | }: {
9 | children: React.ReactNode
10 | }) {
11 | return (
12 |
13 | {children}
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/app/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
5 | // NOTE: This file should not be edited
6 | // see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
7 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/app/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | module.exports = {
3 | output: "standalone",
4 |
5 | // Indicate that these packages should not be bundled by webpack
6 | experimental: {
7 | serverComponentsExternalPackages: ['sharp', 'onnxruntime-node', 'chromadb', '@xenova/transformers' ],
8 | },
9 | };
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@langchain/community": "^0.3.10",
7 | "@langchain/core": "^0.2.14",
8 | "@langchain/openai": "^0.2.1",
9 | "@testing-library/jest-dom": "^5.17.0",
10 | "@testing-library/react": "^13.4.0",
11 | "@testing-library/user-event": "^13.5.0",
12 | "@xenova/transformers": "^2.17.2",
13 | "chromadb": "^1.10.0",
14 | "install": "^0.13.0",
15 | "next": "^14.2.5",
16 | "npm": "^10.9.1",
17 | "pdf-parse": "^1.1.1",
18 | "primereact": "^10.8.5",
19 | "react": "^18.3.1",
20 | "react-chatbotify": "^1.7.0",
21 | "react-dom": "^18.3.1",
22 | "react-scripts": "5.0.1",
23 | "socket.io": "^4.7.2",
24 | "socket.io-client": "^4.7.2",
25 | "web-vitals": "^2.1.4"
26 | },
27 | "devDependencies": {
28 | "autoprefixer": "^10.4.20",
29 | "eslint": "^8",
30 | "eslint-config-next": "14.0.3",
31 | "postcss": "^8",
32 | "tailwindcss": "^3.3.0"
33 | },
34 | "overrides": {
35 | "typescript": "^5.5.3",
36 | "@langchain/core": "^0.2.14"
37 | },
38 | "scripts": {
39 | "dev": "next dev -p 8501",
40 | "build": "next build",
41 | "lint": "next lint"
42 | },
43 | "eslintConfig": {
44 | "extends": [
45 | "react-app",
46 | "react-app/jest"
47 | ]
48 | },
49 | "browserslist": {
50 | "production": [
51 | ">0.2%",
52 | "not dead",
53 | "not op_mini all"
54 | ],
55 | "development": [
56 | "last 1 chrome version",
57 | "last 1 firefox version",
58 | "last 1 safari version"
59 | ]
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/app/pages/api/delete/index.js:
--------------------------------------------------------------------------------
1 | import { ChromaClient } from 'chromadb';
2 |
3 | const vectorDBHost = process.env.VECTORDB_HOST || '0.0.0.0';
4 | const vectorDBPort = process.env.VECTORDB_PORT || 8000;
5 | const vectorDBName = process.env.VECTORDB_NAME || 'nodejs_test_collection';
6 |
7 | const url = `http://${vectorDBHost}:${vectorDBPort}`;
8 | const client = new ChromaClient({path: url});
9 |
10 | /////////////////////////////////////////////////////
11 | // delete and recreate the collection in Chroma when
12 | // requested by the front end
13 | const HANDLER = async (req, res) => {
14 | try {
15 | const collection = await client.getOrCreateCollection({name: vectorDBName});
16 | const result = await collection.get({include: []});
17 | if (result && result.ids && (result.ids.length > 0)) {
18 | await collection.delete({ids: result.ids});
19 | }
20 | res.statusCode = 200;
21 | res.statusMessage = 'Success';
22 | res.end("Deleted succesfully, count is:" + await collection.count());
23 | } catch (error) {
24 | res.statusCode = 500;
25 | res.statusMessage = 'Deletion failed';
26 | res.end(error.toString());
27 | }
28 | };
29 |
30 | export default HANDLER;
31 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": [
4 | "dom",
5 | "dom.iterable",
6 | "esnext"
7 | ],
8 | "allowJs": true,
9 | "skipLibCheck": true,
10 | "strict": false,
11 | "noEmit": true,
12 | "incremental": true,
13 | "module": "esnext",
14 | "esModuleInterop": true,
15 | "moduleResolution": "node",
16 | "resolveJsonModule": true,
17 | "isolatedModules": true,
18 | "jsx": "preserve",
19 | "plugins": [
20 | {
21 | "name": "next"
22 | }
23 | ],
24 | "strictNullChecks": true
25 | },
26 | "include": [
27 | "next-env.d.ts",
28 | ".next/types/**/*.ts",
29 | "**/*.ts",
30 | "**/*.tsx"
31 | ],
32 | "exclude": [
33 | "node_modules"
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/bootc/Containerfile.nocache:
--------------------------------------------------------------------------------
1 | # Example: an AI powered sample application is embedded as a systemd service
2 | # via Podman quadlet files in /usr/share/containers/systemd
3 | #
4 | # from recipes/natural_language_processing/rag-nodejs, run
5 | # 'make bootc'
6 |
7 | FROM quay.io/centos-bootc/centos-bootc:stream9
8 | ARG SSHPUBKEY
9 |
10 | # The --build-arg "SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)" option inserts your
11 | # public key into the image, allowing root access via ssh.
12 | RUN set -eu; mkdir -p /usr/ssh && \
13 | echo 'AuthorizedKeysFile /usr/ssh/%u.keys .ssh/authorized_keys .ssh/authorized_keys2' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
14 | echo ${SSHPUBKEY} > /usr/ssh/root.keys && chmod 0600 /usr/ssh/root.keys
15 |
16 | ARG RECIPE=rag-nodejs
17 |
18 | # Add quadlet files to setup system to automatically run AI application on boot
19 | COPY build/${RECIPE}.image build/${RECIPE}.kube build/${RECIPE}.yaml /usr/share/containers/systemd
20 |
21 | # Added for running as an OCI Container to prevent Overlay on Overlay issues.
22 | VOLUME /var/lib/containers
23 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/quadlet/README.md:
--------------------------------------------------------------------------------
1 | ### Run rag-nodejs as a systemd service
2 |
3 | ```bash
4 | (cd ../;make quadlet)
5 | sudo cp ../build/rag-nodejs.yaml ../build/rag-nodejs.kube ../build/rag-nodejs.image /usr/share/containers/systemd/
6 | sudo /usr/libexec/podman/quadlet --dryrun #optional
7 | sudo systemctl daemon-reload
8 | sudo systemctl start rag-nodejs
9 | ```
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/quadlet/rag-nodejs.image:
--------------------------------------------------------------------------------
1 | ../../../common/quadlet/app.image
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/quadlet/rag-nodejs.kube:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Kubernetes YAML file used to do rag inferencing
3 | Documentation=man:podman-generate-systemd(1)
4 | Wants=network-online.target
5 | After=network-online.target
6 | RequiresMountsFor=%t/containers
7 |
8 | [Kube]
9 | # Point to the yaml file in the same directory
10 | Yaml=rag-nodejs.yaml
11 |
12 | [Service]
13 | Restart=always
14 |
15 | [Install]
16 | WantedBy=default.target
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag-nodejs/quadlet/rag-nodejs.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: rag-nodejs
6 | name: rag-nodejs
7 | spec:
8 | initContainers:
9 | - name: model-file
10 | image: MODEL_IMAGE
11 | command: ['/usr/bin/install', "/model/model.file", "/shared/"]
12 | volumeMounts:
13 | - name: model-file
14 | mountPath: /shared
15 | containers:
16 | - env:
17 | - name: MODEL_ENDPOINT
18 | value: http://0.0.0.0:8001
19 | image: APP_IMAGE
20 | name: rag-nodejs-inference
21 | ports:
22 | - containerPort: 8501
23 | hostPort: 8501
24 | securityContext:
25 | runAsNonRoot: true
26 | - env:
27 | - name: CHROMADB_ENDPOINT
28 | value: http://0.0.0.0:8000/v1
29 | image: ghcr.io/chroma-core/chroma:0.5.23
30 | name: rag-chromadb
31 | ports:
32 | - containerPort: 8000
33 | hostPort: 8000
34 | securityContext:
35 | runAsNonRoot: true
36 | - env:
37 | - name: HOST
38 | value: 0.0.0.0
39 | - name: PORT
40 | value: 8001
41 | - name: MODEL_PATH
42 | value: /model/model.file
43 | image: SERVER_IMAGE
44 | name: rag-model-service
45 | ports:
46 | - containerPort: 8001
47 | hostPort: 8001
48 | securityContext:
49 | runAsNonRoot: true
50 | volumeMounts:
51 | - name: model-file
52 | mountPath: /model
53 | volumes:
54 | - name: model-file
55 | emptyDir: {}
56 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag/ai-lab.yaml:
--------------------------------------------------------------------------------
1 | version: v1.0
2 | application:
3 | type: language
4 | name: rag-demo
5 | description: A RAG chat bot using local documents.
6 | containers:
7 | - name: llamacpp-server
8 | contextdir: ../../../model_servers/llamacpp_python
9 | containerfile: ./base/Containerfile
10 | model-service: true
11 | backend:
12 | - llama-cpp
13 | arch:
14 | - arm64
15 | - amd64
16 | ports:
17 | - 8001
18 | image: quay.io/ai-lab/llamacpp_python:latest
19 | - name: chromadb-server
20 | contextdir: ../../../vector_dbs/chromadb
21 | containerfile: Containerfile
22 | vectordb: true
23 | arch:
24 | - arm64
25 | - amd64
26 | ports:
27 | - 8000
28 | image: quay.io/ai-lab/chromadb:latest
29 | - name: rag-inference-app
30 | contextdir: app
31 | containerfile: Containerfile
32 | arch:
33 | - arm64
34 | - amd64
35 | ports:
36 | - 8501
37 | image: quay.io/ai-lab/rag:latest
38 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag/app/Containerfile:
--------------------------------------------------------------------------------
1 | FROM registry.access.redhat.com/ubi9/python-311:1-77.1726664316
2 | ### Update sqlite for chroma
3 | USER root
4 | RUN dnf remove sqlite3 -y
5 | RUN wget https://www.sqlite.org/2023/sqlite-autoconf-3410200.tar.gz
6 | RUN tar -xvzf sqlite-autoconf-3410200.tar.gz
7 | WORKDIR sqlite-autoconf-3410200
8 | RUN ./configure
9 | RUN make
10 | RUN make install
11 | RUN mv /usr/local/bin/sqlite3 /usr/bin/sqlite3
12 | ENV LD_LIBRARY_PATH="/usr/local/lib"
13 | ####
14 | WORKDIR /rag
15 | COPY requirements.txt .
16 | RUN pip install --upgrade pip
17 | RUN pip install --no-cache-dir --upgrade -r /rag/requirements.txt
18 | COPY rag_app.py .
19 | COPY manage_vectordb.py .
20 | EXPOSE 8501
21 | ENV HF_HUB_CACHE=/rag/models/
22 | RUN mkdir -p /rag/models/
23 | RUN chgrp -R 0 /rag/models/ && chmod -R g=u /rag/models/
24 | ENTRYPOINT [ "streamlit", "run" ,"rag_app.py" ]
25 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag/app/requirements.txt:
--------------------------------------------------------------------------------
1 | langchain-openai==0.1.7
2 | langchain==0.1.20
3 | chromadb==0.5.23
4 | sentence-transformers==2.7.0
5 | streamlit==1.34.0
6 | pypdf==4.2.0
7 | pymilvus==2.4.1
8 |
9 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag/bootc/Containerfile.nocache:
--------------------------------------------------------------------------------
1 | # Example: an AI powered sample application is embedded as a systemd service
2 | # via Podman quadlet files in /usr/share/containers/systemd
3 | #
4 | # from recipes/natural_language_processing/rag, run
5 | # 'make bootc'
6 |
7 | FROM quay.io/centos-bootc/centos-bootc:stream9
8 | ARG SSHPUBKEY
9 |
10 | # The --build-arg "SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)" option inserts your
11 | # public key into the image, allowing root access via ssh.
12 | RUN set -eu; mkdir -p /usr/ssh && \
13 | echo 'AuthorizedKeysFile /usr/ssh/%u.keys .ssh/authorized_keys .ssh/authorized_keys2' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
14 | echo ${SSHPUBKEY} > /usr/ssh/root.keys && chmod 0600 /usr/ssh/root.keys
15 |
16 | ARG RECIPE=rag
17 |
18 | # Add quadlet files to setup system to automatically run AI application on boot
19 | COPY build/${RECIPE}.image build/${RECIPE}.kube build/${RECIPE}.yaml /usr/share/containers/systemd
20 |
21 | # Added for running as an OCI Container to prevent Overlay on Overlay issues.
22 | VOLUME /var/lib/containers
23 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag/provision/requirements.yml:
--------------------------------------------------------------------------------
1 | ---
2 | collections:
3 | - name: containers.podman
4 | version: 1.13.0
5 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag/quadlet/README.md:
--------------------------------------------------------------------------------
1 | ### Run rag as a systemd service
2 |
3 | ```bash
4 | (cd ../;make quadlet)
5 | sudo cp ../build/rag.yaml ../build/rag.kube ../build/rag.image /usr/share/containers/systemd/
6 | sudo /usr/libexec/podman/quadlet --dryrun #optional
7 | sudo systemctl daemon-reload
8 | sudo systemctl start rag
9 | ```
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag/quadlet/rag.image:
--------------------------------------------------------------------------------
1 | ../../../common/quadlet/app.image
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag/quadlet/rag.kube:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Kubernetes YAML file used to do rag inferencing
3 | Documentation=man:podman-generate-systemd(1)
4 | Wants=network-online.target
5 | After=network-online.target
6 | RequiresMountsFor=%t/containers
7 |
8 | [Kube]
9 | # Point to the yaml file in the same directory
10 | Yaml=rag.yaml
11 |
12 | [Service]
13 | Restart=always
14 |
15 | [Install]
16 | WantedBy=default.target
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/rag/quadlet/rag.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: rag
6 | name: rag
7 | spec:
8 | initContainers:
9 | - name: model-file
10 | image: MODEL_IMAGE
11 | command: ['/usr/bin/install', "/model/model.file", "/shared/"]
12 | volumeMounts:
13 | - name: model-file
14 | mountPath: /shared
15 | containers:
16 | - env:
17 | - name: MODEL_ENDPOINT
18 | value: http://0.0.0.0:8001
19 | image: APP_IMAGE
20 | name: rag-inference
21 | ports:
22 | - containerPort: 8501
23 | hostPort: 8501
24 | securityContext:
25 | runAsNonRoot: true
26 | - env:
27 | - name: CHROMADB_ENDPOINT
28 | value: http://0.0.0.0:800O/v1
29 | image: CHROMADB_IMAGE
30 | name: rag-chromadb
31 | ports:
32 | - containerPort: 8000
33 | hostPort: 8000
34 | securityContext:
35 | runAsNonRoot: true
36 | - env:
37 | - name: HOST
38 | value: 0.0.0.0
39 | - name: PORT
40 | value: 8001
41 | - name: MODEL_PATH
42 | value: /model/model.file
43 | image: SERVER_IMAGE
44 | name: rag-model-service
45 | ports:
46 | - containerPort: 8001
47 | hostPort: 8001
48 | securityContext:
49 | runAsNonRoot: true
50 | volumeMounts:
51 | - name: model-file
52 | mountPath: /model
53 | volumes:
54 | - name: model-file
55 | emptyDir: {}
56 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 | APP ?= summarizer
3 | PORT ?= 8501
4 |
5 | include ../../common/Makefile.common
6 |
7 | RECIPE_BINARIES_PATH := $(shell realpath ../../common/bin)
8 | RELATIVE_MODELS_PATH := ../../../models
9 | RELATIVE_TESTS_PATH := ../tests
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/ai-lab.yaml:
--------------------------------------------------------------------------------
1 | version: v1.0
2 | application:
3 | type: language
4 | name: Summarizer_App
5 | description: Summarize text files in a web frontend.
6 | containers:
7 | - name: llamacpp-server
8 | contextdir: ../../../model_servers/llamacpp_python
9 | containerfile: ./base/Containerfile
10 | model-service: true
11 | backend:
12 | - llama-cpp
13 | arch:
14 | - arm64
15 | - amd64
16 | ports:
17 | - 8001
18 | image: quay.io/ai-lab/llamacpp_python:latest
19 | - name: streamlit-summary-app
20 | contextdir: app
21 | containerfile: Containerfile
22 | arch:
23 | - arm64
24 | - amd64
25 | ports:
26 | - 8501
27 | image: quay.io/ai-lab/summarizer:latest
28 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/app/Containerfile:
--------------------------------------------------------------------------------
1 | FROM registry.access.redhat.com/ubi9/python-311:1-77.1726664316
2 | WORKDIR /summarizer
3 | COPY requirements.txt .
4 | RUN pip install --upgrade pip
5 | RUN pip install --no-cache-dir --upgrade -r /summarizer/requirements.txt
6 | COPY summarizer.py .
7 | EXPOSE 8501
8 | ENTRYPOINT [ "streamlit", "run", "summarizer.py" ]
9 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/app/requirements.txt:
--------------------------------------------------------------------------------
1 | langchain==0.1.20
2 | langchain-openai==0.1.7
3 | streamlit==1.34.0
4 | PyMuPDF==1.24.11
5 | rouge_score==0.1.2
6 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/bootc/Containerfile.nocache:
--------------------------------------------------------------------------------
1 | # Example: an AI powered sample application is embedded as a systemd service
2 | # via Podman quadlet files in /usr/share/containers/systemd
3 | #
4 | # from recipes/natural_language_processing/summarizer, run
5 | # 'make bootc'
6 |
7 | FROM quay.io/centos-bootc/centos-bootc:stream9
8 | ARG SSHPUBKEY
9 |
10 | # The --build-arg "SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)" option inserts your
11 | # public key into the image, allowing root access via ssh.
12 | RUN set -eu; mkdir -p /usr/ssh && \
13 | echo 'AuthorizedKeysFile /usr/ssh/%u.keys .ssh/authorized_keys .ssh/authorized_keys2' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
14 | echo ${SSHPUBKEY} > /usr/ssh/root.keys && chmod 0600 /usr/ssh/root.keys
15 |
16 | ARG RECIPE=summarizer
17 |
18 | # Add quadlet files to setup system to automatically run AI application on boot
19 | COPY build/${RECIPE}.image build/${RECIPE}.kube build/${RECIPE}.yaml /usr/share/containers/systemd
20 |
21 | # Added for running as an OCI Container to prevent Overlay on Overlay issues.
22 | VOLUME /var/lib/containers
23 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/provision/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Test Environment Provisioning
3 | hosts: test_environments
4 | remote_user: fedora
5 | become: true
6 | gather_facts: false
7 |
8 | tasks:
9 |
10 | - name: Wait until the instance is ready
11 | ansible.builtin.wait_for_connection:
12 | delay: 10
13 | timeout: 60
14 |
15 | - name: Gather facts for first time
16 | ansible.builtin.setup:
17 |
18 | - name: Required Packages
19 | ansible.builtin.package:
20 | name: podman
21 | state: present
22 |
23 | - name: Models host directory
24 | ansible.builtin.file:
25 | path: locallm/models
26 | state: directory
27 |
28 | - name: Download Model
29 | ansible.builtin.get_url:
30 | url: https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q5_K_S.gguf
31 | dest: locallm/models
32 |
33 | - name: Run Model
34 | containers.podman.podman_container:
35 | name: llamacpp_python
36 | image: ghcr.io/containers/llamacpp_python:latest
37 | state: started
38 | interactive: true
39 | tty: true
40 | detach: true
41 | ports:
42 | - 8001:8001
43 | volume:
44 | - ./locallm/models:/locallm/models:ro,Z
45 | env:
46 | MODEL_PATH: models/llama-2-7b-chat.Q5_K_S.gguf
47 | HOST: 0.0.0.0
48 | PORT: 8001
49 |
50 | - name: Run Application
51 | containers.podman.podman_container:
52 | name: summarizer
53 | image: ghcr.io/containers/summarizer:latest
54 | state: started
55 | interactive: true
56 | tty: true
57 | ports:
58 | - 8501:8501
59 | env:
60 | MODEL_SERVICE_ENDPOINT: http://10.88.0.1:8001/v1
61 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/provision/requirements.yml:
--------------------------------------------------------------------------------
1 | ---
2 | collections:
3 | - name: containers.podman
4 | version: 1.13.0
5 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/quadlet/README.md:
--------------------------------------------------------------------------------
1 | ### Run summarizer as a systemd service
2 |
3 | ```bash
4 | (cd ../;make quadlet)
5 | sudo cp ../build/summarizer.yaml ../build/summarizer.kube ../build/summarizer.image /usr/share/containers/systemd/
6 | sudo /usr/libexec/podman/quadlet --dryrun #optional
7 | sudo systemctl daemon-reload
8 | sudo systemctl start summarizer
9 | ```
10 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/quadlet/summarizer.image:
--------------------------------------------------------------------------------
1 | ../../../common/quadlet/app.image
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/quadlet/summarizer.kube:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Python script to run against downloaded LLM
3 | Documentation=man:podman-generate-systemd(1)
4 | Wants=network-online.target
5 | After=network-online.target
6 | RequiresMountsFor=%t/containers
7 |
8 | [Kube]
9 | # Point to the yaml file in the same directory
10 | Yaml=summarizer.yaml
11 |
12 | [Service]
13 | Restart=always
14 |
15 | [Install]
16 | WantedBy=default.target
17 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/summarizer/quadlet/summarizer.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | labels:
5 | app: summarizer
6 | name: summarizer
7 | spec:
8 | initContainers:
9 | - name: model-file
10 | image: MODEL_IMAGE
11 | command: ['/usr/bin/install', "/model/model.file", "/shared/"]
12 | volumeMounts:
13 | - name: model-file
14 | mountPath: /shared
15 | containers:
16 | - env:
17 | - name: MODEL_ENDPOINT
18 | value: http://0.0.0.0:8001
19 | image: APP_IMAGE
20 | name: summarizer-inference
21 | ports:
22 | - containerPort: 8501
23 | hostPort: 8501
24 | securityContext:
25 | runAsNonRoot: true
26 | - env:
27 | - name: HOST
28 | value: 0.0.0.0
29 | - name: PORT
30 | value: 8001
31 | - name: MODEL_PATH
32 | value: /model/model.file
33 | image: SERVER_IMAGE
34 | name: summarizer-model-service
35 | ports:
36 | - containerPort: 8001
37 | hostPort: 8001
38 | securityContext:
39 | runAsNonRoot: true
40 | volumeMounts:
41 | - name: model-file
42 | mountPath: /model
43 | volumes:
44 | - name: model-file
45 | emptyDir: {}
46 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/tests/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import os
3 |
4 |
5 | @pytest.fixture
6 | def chrome_options(chrome_options):
7 | chrome_options.add_argument("--headless")
8 | return chrome_options
9 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/tests/functional/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/containers/ai-lab-recipes/1bace0e7c5b8aa50d723e80315eeb6a8cdee86c0/recipes/natural_language_processing/tests/functional/__init__.py
--------------------------------------------------------------------------------
/recipes/natural_language_processing/tests/functional/test_app.py:
--------------------------------------------------------------------------------
1 | import pytest_container
2 | from .conftest import CB
3 | import tenacity
4 |
5 | CONTAINER_IMAGES = [CB]
6 |
7 | def test_etc_os_release_present(auto_container: pytest_container.container.ContainerData):
8 | assert auto_container.connection.file("/etc/os-release").exists
9 |
10 | @tenacity.retry(stop=tenacity.stop_after_attempt(5), wait=tenacity.wait_exponential())
11 | def test_alive(auto_container: pytest_container.container.ContainerData, host):
12 | host.run_expect([0],f"curl http://localhost:{auto_container.forwarded_ports[0].host_port}",).stdout.strip()
13 |
14 | def test_title(auto_container: pytest_container.container.ContainerData, selenium):
15 | selenium.get(f"http://localhost:{auto_container.forwarded_ports[0].host_port}")
16 | assert selenium.title == "Streamlit"
17 |
18 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/tests/integration/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/containers/ai-lab-recipes/1bace0e7c5b8aa50d723e80315eeb6a8cdee86c0/recipes/natural_language_processing/tests/integration/__init__.py
--------------------------------------------------------------------------------
/recipes/natural_language_processing/tests/integration/conftest.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pytest
3 |
4 |
5 | @pytest.fixture()
6 | def url():
7 | return os.environ["URL"]
8 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/tests/integration/test_app.py:
--------------------------------------------------------------------------------
1 | def test_title(url,selenium):
2 | selenium.get(f"http://{url}:8501")
3 | assert selenium.title == "Streamlit"
4 |
--------------------------------------------------------------------------------
/recipes/natural_language_processing/tests/requirements.txt:
--------------------------------------------------------------------------------
1 | pip==24.0
2 | pytest-container==0.4.0
3 | pytest-selenium==4.1.0
4 | pytest-testinfra==10.1.0
5 | pytest==8.1.1
6 | requests==2.31.0
7 | selenium==4.19.0
8 | tenacity==8.2.3
9 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "github>platform-engineering-org/.github"
5 | ],
6 | "packageRules": [
7 | {
8 | "matchPackageNames": ["langchain"],
9 | "allowedVersions": "<0.2.3"
10 | },
11 | {
12 | "matchPackageNames": ["langchain-openai"],
13 | "allowedVersions": "<=0.1.7"
14 | },
15 | {
16 | "matchPackageNames": ["langchain-community"],
17 | "allowedVersions": "<=0.2.4"
18 | },
19 | {
20 | "matchPackageNames": ["pymilvus"],
21 | "allowedVersions": "<=2.4.1"
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/requirements-test.txt:
--------------------------------------------------------------------------------
1 | pip==24.0
2 | pytest-container==0.4.3
3 | pytest-selenium==4.1.0
4 | pytest-testinfra==10.1.1
5 | pytest==8.2.2
6 | requests==2.31.0
7 | selenium==4.20.0
8 | tenacity==8.2.3
9 |
--------------------------------------------------------------------------------
/training/amd-bootc/Makefile:
--------------------------------------------------------------------------------
1 | HARDWARE ?= amd
2 | IMAGE_NAME ?= $(HARDWARE)-bootc
3 |
4 | include ../common/Makefile.common
5 |
6 | default: bootc
7 |
8 | .PHONY: bootc
9 | bootc: prepare-files
10 | "${CONTAINER_TOOL}" build \
11 | $(ARCH:%=--platform linux/%) \
12 | $(BUILD_ARG_FILE:%=--build-arg-file=%) \
13 | $(EXTRA_RPM_PACKAGES:%=--build-arg EXTRA_RPM_PACKAGES=%) \
14 | $(DRIVER_TOOLKIT_IMAGE:%=--build-arg DRIVER_TOOLKIT_IMAGE=%) \
15 | $(FROM:%=--build-arg BASEIMAGE=%) \
16 | $(INSTRUCTLAB_IMAGE:%=--build-arg INSTRUCTLAB_IMAGE=%) \
17 | $(SOURCE_DATE_EPOCH:%=--timestamp=%) \
18 | $(VENDOR:%=--build-arg VENDOR=%) \
19 | $(if $(SSH_PUBKEY),--build-arg SSHPUBKEY='$(SSH_PUBKEY)') \
20 | --cap-add SYS_ADMIN \
21 | --file Containerfile \
22 | --security-opt label=disable \
23 | --tag "${BOOTC_IMAGE}" \
24 | -v ${OUTDIR}:/run/.input:ro \
25 | ${CONTAINER_TOOL_EXTRA_ARGS} .
26 |
--------------------------------------------------------------------------------
/training/amd-bootc/containers-storage.conf:
--------------------------------------------------------------------------------
1 | [storage]
2 | driver = "overlay"
3 |
4 | [storage.options]
5 | size = ""
6 | remap-uids = ""
7 | remap-gids = ""
8 | ignore_chown_errors = ""
9 | remap-user = ""
10 | remap-group = ""
11 | skip_mount_home = ""
12 | mount_program = "/usr/bin/fuse-overlayfs"
13 | mountopt = ""
14 | additionalimagestores = [ "/usr/lib/containers/storage",]
15 |
16 | [storage.options.overlay]
17 | force_mask = "shared"
18 |
--------------------------------------------------------------------------------
/training/amd-bootc/repos.d/amdgpu.repo:
--------------------------------------------------------------------------------
1 | [amdgpu]
2 | name=amdgpu
3 | baseurl=https://repo.radeon.com/amdgpu/6.2/el/9.4/main/x86_64/
4 | enabled=1
5 | priority=50
6 | gpgcheck=1
7 | gpgkey=https://repo.radeon.com/rocm/rocm.gpg.key
8 |
--------------------------------------------------------------------------------
/training/amd-bootc/repos.d/rocm.repo:
--------------------------------------------------------------------------------
1 | [ROCm-6.2]
2 | name=ROCm6.2
3 | baseurl=https://repo.radeon.com/rocm/el9/6.2/main
4 | enabled=1
5 | priority=50
6 | gpgcheck=1
7 | gpgkey=https://repo.radeon.com/rocm/rocm.gpg.key
8 |
--------------------------------------------------------------------------------
/training/cloud/Containerfile:
--------------------------------------------------------------------------------
1 | ARG BASEIMAGE=quay.io/ai-labs/bootc-nvidia:latest
2 | FROM ${BASEIMAGE}
3 |
4 | ARG CLOUD
5 |
6 | COPY $CLOUD/cloud-setup.sh /tmp
7 | RUN /tmp/cloud-setup.sh && rm -f /tmp/cloud-setup.sh
8 | COPY $CLOUD/files/ /
9 |
--------------------------------------------------------------------------------
/training/cloud/Makefile:
--------------------------------------------------------------------------------
1 | CLOUD ?=
2 | VERSION ?= 1.1
3 | HARDWARE ?= nvidia
4 | REGISTRY ?= quay.io
5 | REGISTRY_ORG ?= ai-lab
6 | IMAGE_NAME ?= bootc-${HARDWARE}-rhel9-${CLOUD}
7 | IMAGE_TAG ?= ${VERSION}
8 | CONTAINER_TOOL ?= podman
9 | CONTAINER_TOOL_EXTRA_ARGS ?=
10 |
11 | BOOTC_IMAGE_CLOUD ?= ${REGISTRY}/${REGISTRY_ORG}/${IMAGE_NAME}:${IMAGE_TAG}
12 |
13 | default: help
14 |
15 | -include $(CLOUD)/Makefile.env
16 |
17 | cloud-image: ## Create bootc image for a cloud, using stable RHEL AI as base
18 | "${CONTAINER_TOOL}" build \
19 | $(BASEIMAGE:%=--build-arg BASEIMAGE=%) \
20 | $(CLOUD:%=--build-arg CLOUD=%) \
21 | ${CONTAINER_TOOL_EXTRA_ARGS} \
22 | --tag ${BOOTC_IMAGE_CLOUD} \
23 | --file Containerfile \
24 | .
25 |
26 | cloud-disk: ## Create disk image for a cloud, using the image built with cloud-image target
27 | make -f ../common/Makefile.common bootc-image-builder \
28 | BOOTC_IMAGE=${BOOTC_IMAGE_CLOUD} \
29 | DISK_TYPE=${DISK_TYPE} \
30 | IMAGE_BUILDER_CONFIG=$(abspath $(CLOUD))/config.toml
31 |
32 | help: ## Shows this message.
33 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(shell echo "$(MAKEFILE_LIST) " | tac -s' ') | perl -pe 's/^.*Makefile.*?://g' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
34 |
35 |
--------------------------------------------------------------------------------
/training/cloud/aws/Makefile.env:
--------------------------------------------------------------------------------
1 | DISK_TYPE=ami
2 |
--------------------------------------------------------------------------------
/training/cloud/aws/README.md:
--------------------------------------------------------------------------------
1 | # Amazon Web Services modifications for RHEL AI
2 | Trying to mimic as much as possible the [changes on RHEL for AWS](https://github.com/osbuild/images/blob/main/pkg/distro/rhel/rhel9/ami.go)
3 |
4 | ## Changes
5 |
6 | - Extra kernel parameters
7 |
8 | ```
9 | console=ttyS0,115200n8 net.ifnames=0 nvme_core.io_timeout=4294967295
10 | ```
11 |
12 | - Timezone: UTC
13 | - Chrony configuration:
14 | - Change server
15 | - LeapsecTz
16 | - Locale: en_US.UTF-8
17 | - Keymap: us
18 | - X11 layout: us
19 |
20 | - Getty configuration
21 | - NautoVTs false
22 |
23 | - Packages
24 | - @core metapackage
25 | - authselect-compat
26 | - langpacks-en
27 | - tuned
28 |
29 | - Services
30 | - nm-cloud-setup.service
31 | - nm-cloud-setup.timer
32 | - tuned
33 |
--------------------------------------------------------------------------------
/training/cloud/aws/cloud-setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -o errexit
4 |
5 | mv /etc/selinux /etc/selinux.tmp
6 | dnf install -y --nobest \
7 | cloud-init \
8 | langpacks-en \
9 | tuned
10 | mv /etc/selinux.tmp /etc/selinux
11 |
12 | # Chrony configuration
13 | sed -i \
14 | -e '/^pool /c\server 169.254.169.123 prefer iburst minpoll 4 maxpoll 4' \
15 | -e '/^leapsectz /d' \
16 | /etc/chrony.conf
17 |
--------------------------------------------------------------------------------
/training/cloud/aws/config.toml:
--------------------------------------------------------------------------------
1 | [customizations.kernel]
2 | name = "customizations-for-aws"
3 | append = "console=ttyS0,115200n8 net.ifnames=0 nvme_core.io_timeout=4294967295"
4 |
5 |
--------------------------------------------------------------------------------
/training/cloud/aws/files/etc/X11/xorg.conf.d/00-keyboard.conf:
--------------------------------------------------------------------------------
1 | # Do not edit manually, use localectl(1).
2 | Section "InputClass"
3 | Identifier "system-keyboard"
4 | MatchIsKeyboard "on"
5 | Option "XkbLayout" "us"
6 | EndSection
7 |
--------------------------------------------------------------------------------
/training/cloud/aws/files/etc/locale.conf:
--------------------------------------------------------------------------------
1 | LANG=en_US.UTF-8
2 |
--------------------------------------------------------------------------------
/training/cloud/aws/files/etc/localtime:
--------------------------------------------------------------------------------
1 | ../usr/share/zoneinfo/UTC
--------------------------------------------------------------------------------
/training/cloud/aws/files/etc/systemd/system/NetworkManager.service.wants/nm-cloud-setup.service:
--------------------------------------------------------------------------------
1 | /usr/lib/systemd/system/nm-cloud-setup.service
--------------------------------------------------------------------------------
/training/cloud/aws/files/etc/systemd/system/sshd-keygen@.service.d/disable-sshd-keygen-if-cloud-init-active.conf:
--------------------------------------------------------------------------------
1 | # In some cloud-init enabled images the sshd-keygen template service may race
2 | # with cloud-init during boot causing issues with host key generation. This
3 | # drop-in config adds a condition to sshd-keygen@.service if it exists and
4 | # prevents the sshd-keygen units from running *if* cloud-init is going to run.
5 | #
6 | [Unit]
7 | ConditionPathExists=!/run/systemd/generator.early/multi-user.target.wants/cloud-init.target
8 |
--------------------------------------------------------------------------------
/training/cloud/aws/files/etc/systemd/system/timers.target.wants/nm-cloud-setup.timer:
--------------------------------------------------------------------------------
1 | /usr/lib/systemd/system/nm-cloud-setup.timer
--------------------------------------------------------------------------------
/training/cloud/aws/files/etc/vconsole.conf:
--------------------------------------------------------------------------------
1 | KEYMAP=us
2 |
--------------------------------------------------------------------------------
/training/cloud/aws/files/usr/lib/bootc/install/05-cloud-kargs.toml:
--------------------------------------------------------------------------------
1 | [install]
2 | kargs = ["console=tty0", "console=ttyS0,115200n8", "net.ifnames=0", "nvme_core.io_timeout=4294967295"]
3 |
--------------------------------------------------------------------------------
/training/cloud/aws/files/usr/lib/systemd/logind.conf.d/00-getty-fixes.conf:
--------------------------------------------------------------------------------
1 | [Login]
2 | NAutoVTs=0
3 |
4 |
--------------------------------------------------------------------------------
/training/cloud/aws/files/usr/lib/systemd/system/nm-cloud-setup.service.d/10-rh-enable-for-ec2.conf:
--------------------------------------------------------------------------------
1 | [Service]
2 | Environment="NM_CLOUD_SETUP_EC2=yes"
3 |
--------------------------------------------------------------------------------
/training/cloud/azure/Makefile.env:
--------------------------------------------------------------------------------
1 | DISK_TYPE=raw
2 |
--------------------------------------------------------------------------------
/training/cloud/azure/README.md:
--------------------------------------------------------------------------------
1 | # Azure for RHEL AI
2 | Trying to mimic as much as possible the [changes on RHEL for Azure](https://github.com/osbuild/images/blob/main/pkg/distro/rhel/rhel9/azure.go)
3 |
4 | # Summary
5 | - Extra kernel parameters
6 |
7 | Even if in the link [Kernel Parameters on RHEL for Azure](https://github.com/osbuild/images/blob/a4ae81dc3eed3e86c359635e3135fc8a07f411dd/pkg/distro/rhel/rhel9/azure.go#L454) we see other changes, when running a RHEL instance in Azure, the extra kernel parameters are others, so we will take those as our reference
8 | ```
9 | loglevel=3 console=tty1 console=ttyS0,115200n8 earlyprintk=ttyS0,115200 net.ifnames=0 cloud-init=disabled
10 | ```
11 |
12 | Note that we also disable cloud-init via kernel parameter
13 |
14 | - Timezone: UTC
15 | - Locale: en_US.UTF-8
16 | - Keymap: us
17 | - X11 layout: us
18 |
19 | - sshd config
20 | - ClientAliveInterval: 180
21 |
22 | - Packages
23 | - hyperv-daemons
24 | - langpacks-en
25 | - NetworkManager-cloud-setup
26 | - nvme-cli
27 | - patch
28 | - rng-tools
29 | - uuid
30 | - WALinuxAgent
31 |
32 | - Services
33 | - nm-cloud-setup.service
34 | - nm-cloud-setup.timer
35 | - waagent
36 |
37 | - Systemd
38 | - nm-cloud-setup.service: `Environment=NM_CLOUD_SETUP_AZURE=yes`
39 |
40 | - Kernel Modules
41 | - blacklist amdgpu
42 | - blacklist intel_cstate
43 | - blacklist floppy
44 | - blacklist nouveau
45 | - blacklist lbm-nouveau
46 | - blacklist skx_edac
47 |
48 | - Cloud Init
49 | - 10-azure-kvp.cfg
50 | - 91-azure_datasource.cfg
51 |
52 | - PwQuality
53 | - /etc/security/pwquality.conf
54 |
55 | - WaAgentConfig
56 | - RDFormat false
57 | - RDEnableSwap false
58 |
59 | - udev rules
60 | - /etc/udev/rules.d/68-azure-sriov-nm-unmanaged.rules
61 |
--------------------------------------------------------------------------------
/training/cloud/azure/cloud-setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -o errexit
4 |
5 | mv /etc/selinux /etc/selinux.tmp
6 | dnf install -y --nobest \
7 | cloud-init \
8 | hyperv-daemons \
9 | langpacks-en \
10 | NetworkManager-cloud-setup \
11 | nvme-cli \
12 | patch \
13 | rng-tools \
14 | uuid \
15 | WALinuxAgent
16 | mv /etc/selinux.tmp /etc/selinux
17 |
18 | # sshd configuration
19 | cat << EOF >> /etc/ssh/sshd_config
20 | ClientAliveInterval 180
21 | EOF
22 |
23 | # pwquality configuration
24 | cat << EOF >> /etc/security/pwquality.conf
25 | minlen = 6
26 | dcredit = 0
27 | ucredit = 0
28 | lcredit = 0
29 | ocredit = 0
30 | minclass = 3
31 | EOF
32 |
33 | # WAAgent configuration
34 | sed -i \
35 | -e '/^ResourceDisk.Format=y/c\ResourceDisk.Format=n' \
36 | -e '/^ResourceDisk.EnableSwap=y/c\ResourceDisk.EnableSwap=n' \
37 | -e '/^Provisioning.RegenerateSshHostKeyPair=y/c\Provisioning.RegenerateSshHostKeyPair=n' \
38 | /etc/waagent.conf
39 |
--------------------------------------------------------------------------------
/training/cloud/azure/config.toml:
--------------------------------------------------------------------------------
1 | [customizations.kernel]
2 | name = "customizations-for-azure"
3 | # This is suggested by https://github.com/osbuild/images/blob/a4ae81dc3eed3e86c359635e3135fc8a07f411dd/pkg/distro/rhel/rhel9/azure.go#L454
4 | # append = "ro loglevel=3 console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300"
5 | # However, starting a RHEL instance in azure shows this one, and I'll be using it
6 | append = "loglevel=3 console=tty1 console=ttyS0,115200n8 earlyprintk=ttyS0,115200 net.ifnames=0"
7 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/X11/xorg.conf.d/00-keyboard.conf:
--------------------------------------------------------------------------------
1 | # Do not edit manually, use localectl(1).
2 | Section "InputClass"
3 | Identifier "system-keyboard"
4 | MatchIsKeyboard "on"
5 | Option "XkbLayout" "us"
6 | EndSection
7 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/cloud/cloud.cfg.d/10-azure-kvp.cfg:
--------------------------------------------------------------------------------
1 | # This configuration file is used to enable logging to Hyper-V kvp
2 | reporting:
3 | logging:
4 | type: log
5 | telemetry:
6 | type: hyperv
7 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/cloud/cloud.cfg.d/91-azure_datasource.cfg:
--------------------------------------------------------------------------------
1 | datasource_list: [ Azure ]
2 | datasource:
3 | Azure:
4 | apply_network_config: False
5 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/locale.conf:
--------------------------------------------------------------------------------
1 | LANG=en_US.UTF-8
2 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/localtime:
--------------------------------------------------------------------------------
1 | ../usr/share/zoneinfo/UTC
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/modprobe.d/blacklist-floppy.conf:
--------------------------------------------------------------------------------
1 | blacklist floppy
2 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/modprobe.d/blacklist-intel-cstate.conf:
--------------------------------------------------------------------------------
1 | blacklist intel_cstate
2 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/modprobe.d/blacklist-nouveau.conf:
--------------------------------------------------------------------------------
1 | blacklist nouveau
2 | blacklist lbm-nouveau
3 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/modprobe.d/blacklist-skylake-edac.conf:
--------------------------------------------------------------------------------
1 | blacklist skx_edac
2 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/systemd/system/NetworkManager.service.wants/nm-cloud-setup.service:
--------------------------------------------------------------------------------
1 | /usr/lib/systemd/system/nm-cloud-setup.service
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/systemd/system/multi-user.target.wants/waagent.service:
--------------------------------------------------------------------------------
1 | /usr/lib/systemd/system/waagent.service
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/systemd/system/timers.target.wants/nm-cloud-setup.timer:
--------------------------------------------------------------------------------
1 | /usr/lib/systemd/system/nm-cloud-setup.timer
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/udev/rules.d/68-azure-sriov-nm-unmanaged.rules:
--------------------------------------------------------------------------------
1 | # Accelerated Networking on Azure exposes a new SRIOV interface to the VM.
2 | # This interface is transparently bonded to the synthetic interface,
3 | # so NetworkManager should just ignore any SRIOV interfaces.
4 | SUBSYSTEM=="net", DRIVERS=="hv_pci", ACTION=="add", ENV{NM_UNMANAGED}="1"
5 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/etc/vconsole.conf:
--------------------------------------------------------------------------------
1 | KEYMAP=us
2 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/usr/lib/bootc/install/05-cloud-kargs.toml:
--------------------------------------------------------------------------------
1 | [install]
2 | # This is suggested by https://github.com/osbuild/images/blob/a4ae81dc3eed3e86c359635e3135fc8a07f411dd/pkg/distro/rhel/rhel9/azure.go#L454
3 | # kargs = ["ro", "loglevel=3", "console=tty1", "console=ttyS0", "earlyprintk=ttyS0", "rootdelay=300"]
4 | # However, starting a RHEL instance in azure shows this one, and I'll be using it
5 | kargs = ["loglevel=3", "console=tty1", "console=ttyS0,115200n8", "earlyprintk=ttyS0,115200", "net.ifnames=0"]
6 |
--------------------------------------------------------------------------------
/training/cloud/azure/files/usr/lib/systemd/system/nm-cloud-setup.service.d/10-rh-enable-for-azure.conf:
--------------------------------------------------------------------------------
1 | [Service]
2 | Environment="NM_CLOUD_SETUP_AZURE=yes"
3 |
--------------------------------------------------------------------------------
/training/cloud/gcp/Makefile.env:
--------------------------------------------------------------------------------
1 | DISK_TYPE=raw
2 |
--------------------------------------------------------------------------------
/training/cloud/gcp/README.md:
--------------------------------------------------------------------------------
1 | # Google Cloud Platform modifications for RHEL AI
2 | Trying to mimic as much as possible the [changes on RHEL for GCP](https://github.com/osbuild/images/blob/main/pkg/distro/rhel/rhel9/gce.go)
3 |
4 | ## Changes
5 |
6 | - Extra kernel parameters
7 |
8 | ```
9 | net.ifnames=0 biosdevname=0 scsi_mod.use_blk_mq=Y console=ttyS0,38400n8d
10 | ```
11 |
12 | - Timezone: UTC
13 | - Chrony configuration:
14 | - Change server
15 | - Locale: en_US.UTF-8
16 | - Keymap: us
17 | - X11 layout: us
18 |
19 | - sshd config
20 | - PasswordAuthentication: false
21 | - ClientAliveInterval: 420
22 | - PermitRootLogin: No
23 |
24 | - Modules
25 | - blacklist floppy
26 |
27 | - GCPGuestAgentConfig
28 | - SetBotoConfig: false
29 |
30 | - Packages
31 | - langpacks-en
32 | - acpid
33 | - rng-tools
34 | - vim
35 | - google-compute-engine
36 | - google-osconfig-agent
37 | - gce-disk-expand
38 | - timedatex
39 | - tuned
40 |
41 | - Remove Packages
42 | - irqbalance
43 | - microcode_ctl
44 |
--------------------------------------------------------------------------------
/training/cloud/gcp/cloud-setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -o errexit
4 |
5 | eval $(grep VERSION_ID /etc/os-release)
6 | tee /etc/yum.repos.d/google-cloud.repo << EOF
7 | [google-compute-engine]
8 | name=Google Compute Engine
9 | baseurl=https://packages.cloud.google.com/yum/repos/google-compute-engine-el${VERSION_ID/.*}-x86_64-stable
10 | enabled=1
11 | gpgcheck=1
12 | repo_gpgcheck=0
13 | gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
14 | https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
15 | EOF
16 |
17 | mv /etc/selinux /etc/selinux.tmp
18 | dnf install -y --nobest \
19 | acpid \
20 | cloud-init \
21 | google-compute-engine \
22 | google-osconfig-agent \
23 | langpacks-en \
24 | rng-tools \
25 | timedatex \
26 | tuned \
27 | vim
28 | mv /etc/selinux.tmp /etc/selinux
29 |
30 | # The current version of google-cloud-ops-agent is impacted by a CVE: https://access.redhat.com/security/cve/CVE-2024-41110
31 | # It will be disable for the meantime
32 | #
33 | # # Install Google Ops Agent
34 | # curl -sSo /tmp/add-google-cloud-ops-agent-repo.sh https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh
35 | # bash /tmp/add-google-cloud-ops-agent-repo.sh --also-install --remove-repo
36 | # rm /tmp/add-google-cloud-ops-agent-repo.sh
37 |
38 | # rpm-state is needed to remove microcode_ctl
39 | mkdir -p /var/lib/rpm-state
40 | dnf remove -y \
41 | irqbalance \
42 | microcode_ctl
43 |
44 | rm -f /etc/yum.repos.d/google-cloud.repo
45 |
46 | # Chrony configuration
47 | sed -i \
48 | -e '/^pool /c\server metadata.google.internal iburst' \
49 | /etc/chrony.conf
50 |
51 | # sshd configuration
52 | cat << EOF >> /etc/ssh/sshd_config
53 | PermitRootLogin no
54 | PasswordAuthentication no
55 | ClientAliveInterval 420
56 | EOF
57 |
--------------------------------------------------------------------------------
/training/cloud/gcp/config.toml:
--------------------------------------------------------------------------------
1 | [customizations.kernel]
2 | name = "customizations-for-gcp"
3 | append = "net.ifnames=0 biosdevname=0 scsi_mod.use_blk_mq=Y console=ttyS0,38400n8d cloud-init=disabled"
4 |
5 |
--------------------------------------------------------------------------------
/training/cloud/gcp/files/etc/X11/xorg.conf.d/00-keyboard.conf:
--------------------------------------------------------------------------------
1 | # Do not edit manually, use localectl(1).
2 | Section "InputClass"
3 | Identifier "system-keyboard"
4 | MatchIsKeyboard "on"
5 | Option "XkbLayout" "us"
6 | EndSection
7 |
--------------------------------------------------------------------------------
/training/cloud/gcp/files/etc/default/instance_configs.cfg:
--------------------------------------------------------------------------------
1 | # Disable boto plugin setup.
2 | [InstanceSetup]
3 | set_boto_config = false
4 |
--------------------------------------------------------------------------------
/training/cloud/gcp/files/etc/locale.conf:
--------------------------------------------------------------------------------
1 | LANG=en_US.UTF-8
2 |
--------------------------------------------------------------------------------
/training/cloud/gcp/files/etc/localtime:
--------------------------------------------------------------------------------
1 | ../usr/share/zoneinfo/UTC
--------------------------------------------------------------------------------
/training/cloud/gcp/files/etc/modprobe.d/blacklist-floppy.conf:
--------------------------------------------------------------------------------
1 | blacklist floppy
2 |
--------------------------------------------------------------------------------
/training/cloud/gcp/files/etc/vconsole.conf:
--------------------------------------------------------------------------------
1 | KEYMAP=us
2 |
--------------------------------------------------------------------------------
/training/cloud/gcp/files/usr/lib/bootc/install/05-cloud-kargs.toml:
--------------------------------------------------------------------------------
1 | [install]
2 | kargs = ["net.ifnames=0", "biosdevname=0", "scsi_mod.use_blk_mq=Y", "console=ttyS0,38400n8d", "cloud-init=disabled"]
3 |
--------------------------------------------------------------------------------
/training/cloud/ibm/Makefile.env:
--------------------------------------------------------------------------------
1 | DISK_TYPE=qcow2
2 |
--------------------------------------------------------------------------------
/training/cloud/ibm/README.md:
--------------------------------------------------------------------------------
1 | # IBM Cloud modifications for RHEL AI
2 |
3 | ## Changes
4 |
5 | - Timezone: UTC
6 | - Chrony configuration:
7 | - Change server
8 | - LeapsecTz
9 | - Locale: en_US.UTF-8
10 | - Keymap: us
11 | - X11 layout: us
12 |
13 | - Packages
14 | - langpacks-en
15 |
--------------------------------------------------------------------------------
/training/cloud/ibm/cloud-setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -o errexit
4 |
5 | mv /etc/selinux /etc/selinux.tmp
6 | dnf install -y --nobest \
7 | cloud-init \
8 | langpacks-en
9 | mv /etc/selinux.tmp /etc/selinux
10 |
--------------------------------------------------------------------------------
/training/cloud/ibm/config.toml:
--------------------------------------------------------------------------------
1 | [customizations.kernel]
2 |
3 |
--------------------------------------------------------------------------------
/training/cloud/ibm/files/etc/X11/xorg.conf.d/00-keyboard.conf:
--------------------------------------------------------------------------------
1 | # Do not edit manually, use localectl(1).
2 | Section "InputClass"
3 | Identifier "system-keyboard"
4 | MatchIsKeyboard "on"
5 | Option "XkbLayout" "us"
6 | EndSection
7 |
--------------------------------------------------------------------------------
/training/cloud/ibm/files/etc/locale.conf:
--------------------------------------------------------------------------------
1 | LANG=en_US.UTF-8
2 |
--------------------------------------------------------------------------------
/training/cloud/ibm/files/etc/localtime:
--------------------------------------------------------------------------------
1 | ../usr/share/zoneinfo/UTC
--------------------------------------------------------------------------------
/training/cloud/ibm/files/etc/vconsole.conf:
--------------------------------------------------------------------------------
1 | KEYMAP=us
2 |
--------------------------------------------------------------------------------
/training/common/usr/lib/systemd/system/basic.target.wants/upgrade-informer.service:
--------------------------------------------------------------------------------
1 | ../upgrade-informer.service
--------------------------------------------------------------------------------
/training/common/usr/lib/systemd/system/timers.target.wants/upgrade-informer.timer:
--------------------------------------------------------------------------------
1 | ../upgrade-informer.timer
--------------------------------------------------------------------------------
/training/common/usr/lib/systemd/system/upgrade-informer.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Check for available RHEL AI upgrade
3 | ConditionPathExists=/run/ostree-booted
4 | After=network-online.target
5 | StartLimitIntervalSec=400
6 | StartLimitBurst=3
7 |
8 | [Service]
9 | Type=oneshot
10 | ExecStart=/usr/libexec/upgrade-informer
11 | Restart=on-failure
12 | RestartSec=90
13 |
--------------------------------------------------------------------------------
/training/common/usr/lib/systemd/system/upgrade-informer.timer:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Runs upgrade informer periodically
3 | ConditionPathExists=/run/ostree-booted
4 |
5 | [Timer]
6 | OnBootSec=1h
7 | OnUnitInactiveSec=1day
8 | RandomizedDelaySec=2h
9 |
10 | [Install]
11 | WantedBy=timers.target
12 |
--------------------------------------------------------------------------------
/training/common/usr/libexec/upgrade-informer:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Run the command and capture its output
4 | output=$(bootc upgrade --check | sed -e 1q)
5 | message_file="/etc/motd.d/upgrade-message"
6 | bootc_auth="/etc/ostree/auth.json"
7 |
8 | if [[ $output == Update\ available* ]]; then
9 | if [[ ! -f $message_file ]]; then
10 | echo "New version was found"
11 | bootc_image=$(awk '{print $4}' <<< "$output")
12 | # If auth file exists we should use it
13 | auth_params=""
14 | if [[ -f $bootc_auth ]]; then
15 | auth_params="--authfile $bootc_auth"
16 | fi
17 |
18 | # Get image version
19 | # shellcheck disable=SC2086
20 | image_version_id=$(skopeo inspect --format json $auth_params "$bootc_image" | jq -r '.Labels | .["image_version_id"] // empty')
21 |
22 | # If upgrade available, write the output to the file
23 | cat > $message_file << EOF
24 |
25 | ** Attention! **
26 | ** A new $image_version_id version is available **
27 | ** In order to apply it run: bootc upgrade --apply
28 | ** Please note that the system will reboot after the upgrade **
29 |
30 | EOF
31 | fi
32 | else
33 | echo "No upgrade was found"
34 | rm $message_file 2> /dev/null
35 | fi
36 |
37 | echo "Finished running upgrade informer"
38 |
--------------------------------------------------------------------------------
/training/deepspeed/Containerfile:
--------------------------------------------------------------------------------
1 | # Containerfile for running deepspeed training
2 | FROM nvcr.io/nvidia/cuda:12.1.1-cudnn8-devel-ubi9
3 |
4 | ARG VENDOR=''
5 | LABEL vendor=${VENDOR}
6 | LABEL org.opencontainers.image.vendor=${VENDOR}
7 |
8 | RUN dnf install -y python python-devel git
9 | RUN python -m ensurepip --upgrade
10 | RUN pip3 install torch==2.1.2 --index-url https://download.pytorch.org/whl/cu121
11 | RUN pip3 install packaging wheel
12 | RUN pip3 install flash-attn==2.5.7
13 | RUN pip3 install deepspeed==0.14.2
14 | RUN pip3 install transformers==4.40.1
15 | RUN pip3 install ipdb jupyterlab gpustat matplotlib hydra-core datasets rich numba
16 | RUN git clone https://github.com/instructlab/training.git
17 | RUN mkdir -p /ilab-data/training_output
18 |
19 | WORKDIR /training
20 |
21 | CMD ["/bin/bash"]
22 |
--------------------------------------------------------------------------------
/training/deepspeed/Makefile:
--------------------------------------------------------------------------------
1 | IMAGE_NAME ?= deepspeed-trainer
2 | CONTAINER_TOOL ?= podman
3 | SOURCE_DATE_EPOCH ?= $(shell git log -1 --pretty=%ct)
4 | BUILD_ARG_FILE ?=
5 |
6 | default: image
7 |
8 | .PHONY: image
9 | image:
10 | @mkdir -p ../build
11 | rm -rf ../build/deepspeed-trainer
12 | "${CONTAINER_TOOL}" build \
13 | $(ARCH:%=--platform linux/%) \
14 | $(BUILD_ARG_FILE:%=--build-arg-file=%) \
15 | $(SOURCE_DATE_EPOCH:%=--timestamp=%) \
16 | $(VENDOR:%=--build-arg VENDOR=%) \
17 | --file Containerfile \
18 | --squash-all \
19 | --tag oci:../build/deepspeed-trainer
20 |
--------------------------------------------------------------------------------
/training/ilab-wrapper/ilab-qlora:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Template values replaced by container build
4 | TRAIN_DEVICE="__REPLACE_TRAIN_DEVICE__"
5 | CONTAINER_DEVICE="__REPLACE_CONTAINER_DEVICE__"
6 | CONTAINER_NAME="__REPLACE_CONTAINER_NAME__"
7 |
8 | # HF caching uses relative symlink structures, so keep cache relative to
9 | # the central working directory
10 | CONTAINER_CACHE="/instructlab/cache"
11 | HOST_CACHE="$(pwd)/cache"
12 | WORKDIR="$(pwd)"
13 |
14 | has_argument() {
15 | match=$1
16 | shift
17 | for arg in "$@"; do
18 | if [[ "$arg" == *"$match"* ]]; then
19 | return 0
20 | fi
21 | done
22 | return 1
23 | }
24 |
25 | mkdir -p "${HOST_CACHE}"
26 | PODMAN_COMMAND=("podman" "run" "--rm" "-it" "--device" "${CONTAINER_DEVICE}" \
27 | "--security-opt" "label=disable" "--net" "host" \
28 | "-v" "${WORKDIR}:/instructlab" "--entrypoint" "" \
29 | "-e" "HF_HOME=${CONTAINER_CACHE}" \
30 | "${CONTAINER_NAME}")
31 | if [[ "$1" = "init" ]]; then
32 | if ! has_argument "--repository" "$@"; then
33 | shift
34 | "${PODMAN_COMMAND[@]}" ilab init \
35 | --repository https://github.com/instructlab/taxonomy.git "$@"
36 | exit $?
37 | fi
38 | elif [[ "$1" = "train" ]]; then
39 | if ! has_argument "--device" "$@"; then
40 | shift
41 | "${PODMAN_COMMAND[@]}" ilab train --device ${TRAIN_DEVICE} "$@"
42 | exit $?
43 | fi
44 | fi
45 |
46 | "${PODMAN_COMMAND[@]}" ilab "$@"
47 |
48 |
--------------------------------------------------------------------------------
/training/intel-bootc/Makefile:
--------------------------------------------------------------------------------
1 | IMAGE_NAME ?= intel-bootc
2 |
3 | include ../common/Makefile.common
4 |
5 | default: bootc
6 |
7 | .PHONY: bootc
8 | bootc: prepare-files
9 | ${CONTAINER_TOOL} build \
10 | $(ARCH:%=--platform linux/%) \
11 | $(BUILD_ARG_FILE:%=--build-arg-file=%) \
12 | $(DRIVER_TOOLKIT_IMAGE:%=--build-arg DRIVER_TOOLKIT_IMAGE=%) \
13 | $(DRIVER_VERSION:%=--build-arg DRIVER_VERSION=%) \
14 | $(EXTRA_RPM_PACKAGES:%=--build-arg EXTRA_RPM_PACKAGES=%) \
15 | $(FROM:%=--build-arg BASEIMAGE=%) \
16 | $(INSTRUCTLAB_IMAGE:%=--build-arg INSTRUCTLAB_IMAGE=%) \
17 | $(SOURCE_DATE_EPOCH:%=--timestamp=%) \
18 | $(VENDOR:%=--build-arg VENDOR=%) \
19 | $(if $(SSH_PUBKEY),--build-arg SSHPUBKEY='$(SSH_PUBKEY)') \
20 | --cap-add SYS_ADMIN \
21 | --file Containerfile \
22 | --security-opt label=disable \
23 | --tag "${BOOTC_IMAGE}" \
24 | -v ${OUTDIR}:/run/.input:ro \
25 | ${CONTAINER_TOOL_EXTRA_ARGS} .
26 |
--------------------------------------------------------------------------------
/training/intel-bootc/duplicated/common/usr/lib/systemd/system/basic.target.wants/upgrade-informer.service:
--------------------------------------------------------------------------------
1 | ../upgrade-informer.service
--------------------------------------------------------------------------------
/training/intel-bootc/duplicated/common/usr/lib/systemd/system/timers.target.wants/upgrade-informer.timer:
--------------------------------------------------------------------------------
1 | ../upgrade-informer.timer
--------------------------------------------------------------------------------
/training/intel-bootc/duplicated/common/usr/lib/systemd/system/upgrade-informer.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Check for available RHEL AI upgrade
3 | ConditionPathExists=/run/ostree-booted
4 | After=network-online.target
5 | StartLimitIntervalSec=400
6 | StartLimitBurst=3
7 |
8 | [Service]
9 | Type=oneshot
10 | ExecStart=/usr/libexec/upgrade-informer
11 | Restart=on-failure
12 | RestartSec=90
13 |
--------------------------------------------------------------------------------
/training/intel-bootc/duplicated/common/usr/lib/systemd/system/upgrade-informer.timer:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Runs upgrade informer periodically
3 | ConditionPathExists=/run/ostree-booted
4 |
5 | [Timer]
6 | OnBootSec=1h
7 | OnUnitInactiveSec=1day
8 | RandomizedDelaySec=2h
9 |
10 | [Install]
11 | WantedBy=timers.target
12 |
--------------------------------------------------------------------------------
/training/intel-bootc/duplicated/common/usr/libexec/upgrade-informer:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Run the command and capture its output
4 | output=$(bootc upgrade --check | sed -e 1q)
5 | message_file="/etc/motd.d/upgrade-message"
6 | bootc_auth="/etc/ostree/auth.json"
7 |
8 | if [[ $output == Update\ available* ]]; then
9 | if [[ ! -f $message_file ]]; then
10 | echo "New version was found"
11 | bootc_image=$(awk '{print $4}' <<< "$output")
12 | # If auth file exists we should use it
13 | auth_params=""
14 | if [[ -f $bootc_auth ]]; then
15 | auth_params="--authfile $bootc_auth"
16 | fi
17 |
18 | # Get image version
19 | # shellcheck disable=SC2086
20 | image_version_id=$(skopeo inspect --format json $auth_params "$bootc_image" | jq -r '.Labels | .["image_version_id"] // empty')
21 |
22 | # If upgrade available, write the output to the file
23 | cat > $message_file << EOF
24 |
25 | ** Attention! **
26 | ** A new $image_version_id version is available **
27 | ** In order to apply it run: bootc upgrade --apply
28 | ** Please note that the system will reboot after the upgrade **
29 |
30 | EOF
31 | fi
32 | else
33 | echo "No upgrade was found"
34 | rm $message_file 2> /dev/null
35 | fi
36 |
37 | echo "Finished running upgrade informer"
38 |
--------------------------------------------------------------------------------
/training/intel-bootc/scripts/os_dependencies.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | REPOS_REPO="redhat/rhel-ai/wheels/builder.git"
3 |
4 | centos_habana_repos() {
5 | echo "[habanalabs]" > /etc/yum.repos.d/habanalabs.repo && \
6 | echo "name=Habana RH9 Linux repo" >> /etc/yum.repos.d/habanalabs.repo && \
7 | echo "baseurl=https://${ARTIFACTORY_URL}/artifactory/rhel/9/9.4" >> /etc/yum.repos.d/habanalabs.repo && \
8 | echo "gpgkey=https://${ARTIFACTORY_URL}/artifactory/api/v2/repositories/rhel/keyPairs/primary/public" >> /etc/yum.repos.d/habanalabs.repo && \
9 | echo "gpgcheck=1" >> /etc/yum.repos.d/habanalabs.repo && \
10 | update-crypto-policies --set DEFAULT:SHA1
11 | }
12 | centos_epel_crb() {
13 | #EPEL only needed in CentOS for libsox-devel
14 | dnf config-manager --set-enabled crb && \
15 | dnf install -y https://dl.fedoraproject.org/pub/epel/epel{,-next}-release-latest-9.noarch.rpm
16 | }
17 | OS=$(grep -w ID /etc/os-release)
18 |
19 | echo "OS line is $OS"
20 | if [[ "$OS" == *"rhel"* ]]; then \
21 | mkdir -p /tmp/git && cd /tmp/git && \
22 | GIT_TOKEN=$(cat /run/secrets/extra-secrets-intel-bootc/BUILDERS_TOKEN) && \
23 | git clone https://dummy_user:${GIT_TOKEN}@gitlab.com/${REPOS_REPO} && \
24 | cd builder/repos && \
25 | cp redhat.repo rhelai.repo habanalabs.repo /etc/yum.repos.d/ && \
26 | cp RPM-GPG-KEY-HABANALABS /etc/pki/rpm-gpg/ && \
27 | dnf config-manager --enable habanalabs && \
28 | dnf config-manager --enable rhelai-1.2-stage && \
29 | rm -rf /tmp/git;
30 | elif [[ "$OS" == *"centos"* ]]; then \
31 | centos_habana_repos && centos_epel_crb; \
32 | else
33 | echo "Only RHEL and CentOS supported."
34 | fi
35 |
36 |
--------------------------------------------------------------------------------
/training/model/Containerfile:
--------------------------------------------------------------------------------
1 | FROM registry.access.redhat.com/ubi9/ubi
2 |
3 | ARG VENDOR=''
4 | LABEL vendor=${VENDOR}
5 | LABEL org.opencontainers.image.vendor=${VENDOR}
6 |
7 | RUN dnf install -y python3-pip && python3 -m pip install huggingface_hub[cli]
8 | COPY entrypoint.sh /entrypoint.sh
9 | WORKDIR /download
10 | ENTRYPOINT ["bash", "/entrypoint.sh"]
11 |
--------------------------------------------------------------------------------
/training/model/Makefile:
--------------------------------------------------------------------------------
1 | include ../common/Makefile.common
2 |
3 | TARGET_MODELS_IMAGE ?= $(BOOTC_MODELS_IMAGE)
4 | FROM_BOOTC_IMAGE ?= $(BOOTC_IMAGE)
5 |
6 | GRANITE_MODEL_REPO ?= instructlab/granite-7b-lab
7 |
8 | HF_TOKEN ?= $(shell echo $$HF_TOKEN)
9 |
10 | BUILD_MODELS_PATH := $(shell realpath ..)/build/models
11 | COMMON_PATH := $(shell realpath ../common)
12 |
13 | MODEL_REPO ?=
14 |
15 | default: download
16 |
17 | .PHONY: image
18 | image:
19 | "${CONTAINER_TOOL}" build \
20 | --file Containerfile \
21 | --tag $(REGISTRY)/$(REGISTRY_ORG)/model-downloader:latest \
22 | ${CONTAINER_TOOL_EXTRA_ARGS} .
23 |
24 | .PHONY: download-all
25 | download-all: image
26 | $(MAKE) MODEL_REPO=$(GRANITE_MODEL_REPO) download-model
27 |
28 | .PHONY: download-model
29 | download-model:
30 | mkdir -p $(BUILD_MODELS_PATH)
31 | podman run \
32 | -e HF_TOKEN=$(HF_TOKEN) \
33 | -v $(BUILD_MODELS_PATH):/download:z \
34 | --pull=never \
35 | -e MODEL_REPO=$(MODEL_REPO) \
36 | -t $(REGISTRY)/$(REGISTRY_ORG)/model-downloader:latest
37 |
38 | .PHONY: generate-model-cfile
39 | generate-model-cfile: download-all
40 | echo "FROM ${FROM_BOOTC_IMAGE}" > ${MODELS_CONTAINERFILE}
41 | echo "RUN rsync -ah --progress --exclude '.hug*' --exclude '*.safetensors' /run/.input/models /usr/share" >> ${MODELS_CONTAINERFILE}
42 | "${CONTAINER_TOOL}" run \
43 | -v .:/work:z \
44 | -v ${OUTDIR}:/run/.input:ro \
45 | --pull=never \
46 | --entrypoint python3 \
47 | $(REGISTRY)/$(REGISTRY_ORG)/model-downloader:latest \
48 | /work/generate-model-cfile.py /run/.input/models >> ${MODELS_CONTAINERFILE}
49 |
50 | .PHONY: bootc-models
51 | bootc-models: generate-model-cfile
52 | "${CONTAINER_TOOL}" build \
53 | $(ARCH:%=--platform linux/%) \
54 | --file ${MODELS_CONTAINERFILE} \
55 | --security-opt label=disable \
56 | --tag "${TARGET_MODELS_IMAGE}" \
57 | -v ${OUTDIR}:/run/.input:ro
58 |
--------------------------------------------------------------------------------
/training/model/entrypoint.sh:
--------------------------------------------------------------------------------
1 | set -x
2 | if [ -z "$HF_TOKEN" ]; then
3 | echo "Error. Please set your \$HF_TOKEN in env. Required to pull mixtral."
4 | exit 1
5 | fi
6 |
7 | huggingface-cli download --exclude "*.pt" --local-dir "/download/${MODEL_REPO}" "${MODEL_REPO}"
8 |
--------------------------------------------------------------------------------
/training/model/generate-model-cfile.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 | import sys
5 |
6 | def isHuggingDir(elements):
7 | for n in s:
8 | if n.startswith(".hug"):
9 | return True
10 | return False
11 |
12 | def printNonEmpty(*args):
13 | if len(args[0]) > 0:
14 | print(*args)
15 |
16 | dir = sys.argv[1]
17 | cwd = os.getcwd()
18 | os.chdir(dir)
19 | c = 0
20 | result=""
21 | for root, dirs, files in os.walk("."):
22 | s = root.split(os.path.sep)
23 | s.pop(0)
24 | if isHuggingDir(s):
25 | continue
26 | for file in files:
27 | if not file.endswith(".safetensors"):
28 | continue
29 | path = os.path.join("/run", ".input", "models", *s, file)
30 | partial = os.path.join("/usr", "share", "models", *s, file)
31 | cmd = f"rsync -ah --progress {path} {partial}"
32 | if c % 4 != 0:
33 | result = f"{result} \\\n\t && {cmd}"
34 | else:
35 | printNonEmpty(result)
36 | result = f"RUN {cmd}"
37 | c += 1
38 | printNonEmpty(result)
39 | os.chdir(cwd)
40 |
--------------------------------------------------------------------------------
/training/nvidia-bootc/Makefile:
--------------------------------------------------------------------------------
1 | HARDWARE ?= nvidia
2 | IMAGE_NAME ?= $(HARDWARE)-bootc
3 |
4 | CUDA_VERSION ?=
5 | OS_VERSION_MAJOR ?=
6 | include ../common/Makefile.common
7 |
8 | default: bootc
9 |
10 | .PHONY: bootc
11 | bootc: driver-toolkit check-sshkey prepare-files
12 | "${CONTAINER_TOOL}" build \
13 | $(ARCH:%=--platform linux/%) \
14 | $(BUILD_ARG_FILE:%=--build-arg-file=%) \
15 | $(CUDA_VERSION:%=--build-arg CUDA_VERSION=%) \
16 | $(DRIVER_TOOLKIT_IMAGE:%=--build-arg DRIVER_TOOLKIT_IMAGE=%) \
17 | $(DRIVER_VERSION:%=--build-arg DRIVER_VERSION=%) \
18 | $(DRIVER_VERSION:%=--label driver-version=%) \
19 | $(IMAGE_VERSION_ID:%=--build-arg IMAGE_VERSION_ID=%) \
20 | $(EXTRA_RPM_PACKAGES:%=--build-arg EXTRA_RPM_PACKAGES=%) \
21 | $(FROM:%=--build-arg BASEIMAGE=%) \
22 | $(INSTRUCTLAB_IMAGE:%=--build-arg INSTRUCTLAB_IMAGE=%) \
23 | $(KERNEL_VERSION:%=--build-arg KERNEL_VERSION=%) \
24 | $(OS_VERSION_MAJOR:%=--build-arg OS_VERSION_MAJOR=%) \
25 | $(SOURCE_DATE_EPOCH:%=--timestamp=%) \
26 | $(VENDOR:%=--build-arg VENDOR=%) \
27 | $(if $(SSH_PUBKEY),--build-arg SSHPUBKEY='$(SSH_PUBKEY)') \
28 | --cap-add SYS_ADMIN \
29 | --file Containerfile \
30 | --security-opt label=disable \
31 | --tag "${BOOTC_IMAGE}" \
32 | -v ${OUTDIR}:/run/.input:ro \
33 | ${CONTAINER_TOOL_EXTRA_ARGS} .
34 |
--------------------------------------------------------------------------------
/training/nvidia-bootc/containers-storage.conf:
--------------------------------------------------------------------------------
1 | [storage]
2 | driver = "overlay"
3 |
4 | [storage.options]
5 | size = ""
6 | remap-uids = ""
7 | remap-gids = ""
8 | ignore_chown_errors = ""
9 | remap-user = ""
10 | remap-group = ""
11 | skip_mount_home = ""
12 | mount_program = "/usr/bin/fuse-overlayfs"
13 | mountopt = ""
14 | additionalimagestores = [ "/usr/lib/containers/storage",]
15 |
16 | [storage.options.overlay]
17 | force_mask = "shared"
18 |
--------------------------------------------------------------------------------
/training/nvidia-bootc/duplicated/common/usr/lib/systemd/system/basic.target.wants/upgrade-informer.service:
--------------------------------------------------------------------------------
1 | ../upgrade-informer.service
--------------------------------------------------------------------------------
/training/nvidia-bootc/duplicated/common/usr/lib/systemd/system/timers.target.wants/upgrade-informer.timer:
--------------------------------------------------------------------------------
1 | ../upgrade-informer.timer
--------------------------------------------------------------------------------
/training/nvidia-bootc/duplicated/common/usr/lib/systemd/system/upgrade-informer.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Check for available RHEL AI upgrade
3 | ConditionPathExists=/run/ostree-booted
4 | After=network-online.target
5 | StartLimitIntervalSec=400
6 | StartLimitBurst=3
7 |
8 | [Service]
9 | Type=oneshot
10 | ExecStart=/usr/libexec/upgrade-informer
11 | Restart=on-failure
12 | RestartSec=90
13 |
--------------------------------------------------------------------------------
/training/nvidia-bootc/duplicated/common/usr/lib/systemd/system/upgrade-informer.timer:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Runs upgrade informer periodically
3 | ConditionPathExists=/run/ostree-booted
4 |
5 | [Timer]
6 | OnBootSec=1h
7 | OnUnitInactiveSec=1day
8 | RandomizedDelaySec=2h
9 |
10 | [Install]
11 | WantedBy=timers.target
12 |
--------------------------------------------------------------------------------
/training/nvidia-bootc/duplicated/common/usr/libexec/upgrade-informer:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Run the command and capture its output
4 | output=$(bootc upgrade --check | sed -e 1q)
5 | message_file="/etc/motd.d/upgrade-message"
6 | bootc_auth="/etc/ostree/auth.json"
7 |
8 | if [[ $output == Update\ available* ]]; then
9 | if [[ ! -f $message_file ]]; then
10 | echo "New version was found"
11 | bootc_image=$(awk '{print $4}' <<< "$output")
12 | # If auth file exists we should use it
13 | auth_params=""
14 | if [[ -f $bootc_auth ]]; then
15 | auth_params="--authfile $bootc_auth"
16 | fi
17 |
18 | # Get image version
19 | # shellcheck disable=SC2086
20 | image_version_id=$(skopeo inspect --format json $auth_params "$bootc_image" | jq -r '.Labels | .["image_version_id"] // empty')
21 |
22 | # If upgrade available, write the output to the file
23 | cat > $message_file << EOF
24 |
25 | ** Attention! **
26 | ** A new $image_version_id version is available **
27 | ** In order to apply it run: bootc upgrade --apply
28 | ** Please note that the system will reboot after the upgrade **
29 |
30 | EOF
31 | fi
32 | else
33 | echo "No upgrade was found"
34 | rm $message_file 2> /dev/null
35 | fi
36 |
37 | echo "Finished running upgrade informer"
38 |
--------------------------------------------------------------------------------
/training/nvidia-bootc/nvidia-toolkit-firstboot.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | # For more information see https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/cdi-support.html
3 | # It looks like the podman/CDI integration wants a pre-generated list of hardware
4 | Description=Generate /etc/cdi/nvidia.yaml
5 |
6 | [Service]
7 | Type=oneshot
8 | ExecStart=nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
9 | RemainAfterExit=yes
10 |
11 | [Install]
12 | # TODO: Ensure we have a target that is like "container setup"
13 | WantedBy=multi-user.target
14 |
--------------------------------------------------------------------------------
/training/nvidia-bootc/x509-configuration.ini:
--------------------------------------------------------------------------------
1 | [ req ]
2 | default_bits = 4096
3 | distinguished_name = req_distinguished_name
4 | prompt = no
5 | string_mask = utf8only
6 | x509_extensions = myexts
7 | [ req_distinguished_name ]
8 | O = Project Magma
9 | CN = Project Magma
10 | emailAddress = magma@acme.com
11 | [ myexts ]
12 | basicConstraints=critical,CA:FALSE
13 | keyUsage=digitalSignature
14 | subjectKeyIdentifier=hash
15 | authorityKeyIdentifier=keyid
16 |
--------------------------------------------------------------------------------
/training/tests/ansible.cfg:
--------------------------------------------------------------------------------
1 | [ssh_connection]
2 | ssh_common_args = -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ;
3 | [defaults]
4 | host_key_checking = False
--------------------------------------------------------------------------------
/training/tests/e2e-tests/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Test Environment Provisioning
3 | hosts: test_environments
4 | remote_user: root
5 | become: true
6 | gather_facts: false
7 |
8 | tasks:
9 |
10 | - name: Wait until the instance is ready
11 | ansible.builtin.wait_for_connection:
12 | delay: 15
13 | timeout: 180
14 |
15 | - name: Gather facts for first time
16 | ansible.builtin.setup:
17 |
18 | - name: ilab init
19 | shell: ilab init
20 | environment:
21 | HF_TOKEN: "{{ HF_TOKEN }}"
22 |
23 | - name: ilab pull the models for debug currently
24 | shell: ilab download --repository mistralai/Mixtral-8x7B-Instruct-v0.1
25 | environment:
26 | HF_TOKEN: "{{ HF_TOKEN }}"
27 |
28 | - name: ilab pull the models for debug currently
29 | shell: ilab download --repository ibm/granite-7b-base
30 | environment:
31 | HF_TOKEN: "{{ HF_TOKEN }}"
32 |
33 | - name: Get test script
34 | ansible.builtin.get_url:
35 | url: https://raw.githubusercontent.com/instructlab/instructlab/main/scripts/basic-workflow-tests.sh
36 | dest: /tmp/basic-workflow-tests.sh
37 | mode: 755
38 | environment:
39 | HF_TOKEN: "{{ HF_TOKEN }}"
40 |
41 | # Allow for debugging with tmate
42 | # - name: Wait for 15 minutes
43 | # pause:
44 | # minutes: 15
45 |
46 | - name: Run tests
47 | ansible.builtin.shell: /tmp/basic-workflow-tests.sh
48 | register: out
49 |
50 | - name: Test Results - stdout
51 | debug:
52 | msg: "{{out.stdout_lines}}"
53 |
54 | - name: Test Results - stderr
55 | debug:
56 | msg: "{{out.stderr_lines}}"
57 |
--------------------------------------------------------------------------------
/training/tests/provision/requirements.yml:
--------------------------------------------------------------------------------
1 | ---
2 | collections:
3 | - name: containers.podman
4 | version: 1.13.0
5 |
--------------------------------------------------------------------------------
/training/tests/provision/templates/Containerfile.j2:
--------------------------------------------------------------------------------
1 | FROM quay.io/ai-lab/{{ image_name }}:latest
2 | ARG sshpubkey
3 |
4 | ARG VENDOR=''
5 | LABEL vendor=${VENDOR}
6 | LABEL org.opencontainers.image.vendor=${VENDOR}
7 |
8 | RUN set -eu && mkdir /usr/etc-system && \
9 | echo 'AuthorizedKeysFile /usr/etc-system/%u.keys' > /etc/ssh/sshd_config.d/30-auth-system.conf && \
10 | echo $sshpubkey > /usr/etc-system/root.keys && \
11 | chmod 0600 /usr/etc-system/root.keys
12 |
13 | RUN dnf install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
14 |
--------------------------------------------------------------------------------
/training/vllm/Containerfile:
--------------------------------------------------------------------------------
1 | FROM quay.io/wxpe/tgis-vllm:release.4e3ff78
2 |
3 | ARG VENDOR=''
4 | LABEL vendor=${VENDOR}
5 | LABEL org.opencontainers.image.vendor=${VENDOR}
6 |
7 | USER root
8 | RUN ln -s /usr/lib64/libcuda.so.1 /usr/lib64/libcuda.so
9 | COPY mixtral.jinja .
10 |
--------------------------------------------------------------------------------
/training/vllm/Makefile:
--------------------------------------------------------------------------------
1 | CONTAINER_TOOL ?= podman
2 | SOURCE_DATE_EPOCH ?= $(shell git log -1 --pretty=%ct)
3 | BUILD_ARG_FILE ?=
4 |
5 | default: image
6 |
7 | .PHONY: image
8 | image:
9 | @mkdir -p ../build
10 | rm -rf ../build/vllm
11 | "${CONTAINER_TOOL}" build \
12 | $(ARCH:%=--platform linux/%) \
13 | $(BUILD_ARG_FILE:%=--build-arg-file=%) \
14 | $(SOURCE_DATE_EPOCH:%=--timestamp=%) \
15 | $(VENDOR:%=--build-arg VENDOR=%) \
16 | --file Containerfile \
17 | --squash-all \
18 | --tag oci:../build/vllm \
19 | ${CONTAINER_TOOL_EXTRA_ARGS} .
20 |
--------------------------------------------------------------------------------
/training/vllm/mixtral.jinja:
--------------------------------------------------------------------------------
1 | {% set bos_token = "" %}
2 |
3 | {% set eos_token = "" %}
4 |
5 | {{ bos_token }}
6 | {% for message in messages %}
7 | {% if message['role'] == 'user' %}
8 | {{ '[INST] ' + message['content'] + ' [/INST]' }}
9 | {% elif message['role'] == 'assistant' %}
10 | {{ message['content'] + eos_token}}
11 | {% endif %}
12 | {% endfor %}
13 |
--------------------------------------------------------------------------------
/vector_dbs/README.md:
--------------------------------------------------------------------------------
1 | # Directory to store vector_dbs files
2 | This directory has make files and container files for open source vector databases. The built container images are used by recipes like `rag` to provide required database functions.
3 |
4 | ## Chroma
5 | [Chroma](https://www.trychroma.com/) is an AI-native open-source embedding database.
6 | Chroma makes it easy to build LLM apps by making knowledge, facts, and skills
7 | pluggable for LLMs.
8 |
9 | ## Milvus
10 | [Milvus](https://milvus.io/) is an open-source vector database built to power embedding similarity search and AI applications. It is highly scalable and offers many production ready features for search.
11 |
--------------------------------------------------------------------------------
/vector_dbs/chromadb/Containerfile:
--------------------------------------------------------------------------------
1 | # DO NOT UPVERSION UNTIL APP HAS BEEN UPDATED AS WELL
2 | # AS IT IS THE LAST VERSION THAT WORKS WITH THE RAG RECIPE
3 | FROM docker.io/chromadb/chroma:0.5.23
4 |
--------------------------------------------------------------------------------
/vector_dbs/chromadb/Makefile:
--------------------------------------------------------------------------------
1 | CONTAINER_TOOL ?= podman
2 | APP ?= chromadb
3 | APPIMAGE ?= quay.io/ai-lab/${APP}:latest
4 |
5 | .PHONY: build
6 | build:
7 | "${CONTAINER_TOOL}" build -f Containerfile -t ${APPIMAGE} .
8 |
--------------------------------------------------------------------------------
/vector_dbs/milvus/Containerfile:
--------------------------------------------------------------------------------
1 | FROM docker.io/milvusdb/milvus:master-20240426-bed6363f
2 | ADD embedEtcd.yaml /milvus/configs/embedEtcd.yaml
3 |
--------------------------------------------------------------------------------
/vector_dbs/milvus/Makefile:
--------------------------------------------------------------------------------
1 | CONTAINER_TOOL ?= podman
2 | REGISTRY ?= quay.io
3 | REGISTRY_ORG ?= ai-lab
4 | COMPONENT = vector_dbs
5 |
6 | IMAGE ?= $(REGISTRY)/$(REGISTRY_ORG)/$(COMPONENT)/milvus:latest
7 |
8 | ARCH ?= $(shell uname -m)
9 | PLATFORM ?= linux/$(ARCH)
10 |
11 | gRCP_PORT := 19530
12 | REST_PORT := 9091
13 | CLIENT_PORT := 2379
14 |
15 | LIB_MILVUS_DIR_MOUNTPATH := $(shell pwd)/volumes/milvus
16 |
17 | .PHONY: build
18 | build:
19 | "${CONTAINER_TOOL}" build --platform $(PLATFORM) -f Containerfile -t ${IMAGE} .
20 |
21 | .PHONY: run
22 | run:
23 | podman run -it \
24 | --name milvus-standalone \
25 | --security-opt seccomp:unconfined \
26 | -e ETCD_USE_EMBED=true \
27 | -e ETCD_CONFIG_PATH=/milvus/configs/embedEtcd.yaml \
28 | -e COMMON_STORAGETYPE=local \
29 | -v $(LIB_MILVUS_DIR_MOUNTPATH):/var/lib/milvus \
30 | -p $(gRCP_PORT):$(gRCP_PORT) \
31 | -p $(REST_PORT):$(REST_PORT) \
32 | -p $(CLIENT_PORT):$(CLIENT_PORT) \
33 | --health-cmd="curl -f http://localhost:$(REST_PORT)/healthz" \
34 | --health-interval=30s \
35 | --health-start-period=90s \
36 | --health-timeout=20s \
37 | --health-retries=3 \
38 | $(IMAGE) \
39 | milvus run standalone 1> /dev/null
40 |
41 | .PHONY: stop
42 | stop:
43 | -podman stop milvus-standalone
44 |
45 | .PHONY: delete
46 | delete:
47 | -podman rm milvus-standalone -f
48 |
49 | .PHONY: podman-clean
50 | podman-clean:
51 | @container_ids=$$(podman ps --format "{{.ID}} {{.Image}}" | awk '$$2 == "$(IMAGE)" {print $$1}'); \
52 | echo "removing all containers with IMAGE=$(IMAGE)"; \
53 | for id in $$container_ids; do \
54 | echo "Removing container: $$id,"; \
55 | podman rm -f $$id; \
56 | done
57 |
--------------------------------------------------------------------------------
/vector_dbs/milvus/embedEtcd.yaml:
--------------------------------------------------------------------------------
1 | listen-client-urls: http://0.0.0.0:2379
2 | advertise-client-urls: http://0.0.0.0:2379
3 | quota-backend-bytes: 4294967296
4 | auto-compaction-mode: revision
5 | auto-compaction-retention: '1000'
6 |
--------------------------------------------------------------------------------
/vector_dbs/milvus/volumes/milvus/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/containers/ai-lab-recipes/1bace0e7c5b8aa50d723e80315eeb6a8cdee86c0/vector_dbs/milvus/volumes/milvus/.gitkeep
--------------------------------------------------------------------------------