├── .gitignore ├── stack.png ├── ui-demo.gif ├── .env ├── spellbook ├── environment.ts └── Dockerfile ├── vault ├── config.json ├── Dockerfile └── unseal.sh ├── rabbitmq ├── Dockerfile └── amqp-init.sh ├── mariadb ├── Dockerfile ├── db-init.sh └── spellbook.sql ├── docker-compose-worker-nogpu.yml ├── docker-compose-worker.yml ├── elemental-golem ├── Dockerfile-nogpu └── Dockerfile ├── arcane-bridge └── Dockerfile ├── docker-compose-nogpu.yml ├── docker-compose.yml ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | elemental-golem/noco-ai.tar.gz -------------------------------------------------------------------------------- /stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noco-ai/spellbook-docker/HEAD/stack.png -------------------------------------------------------------------------------- /ui-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noco-ai/spellbook-docker/HEAD/ui-demo.gif -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | GOLEM_VAULT_HOST=http://10.23.82.2:8200 2 | GOLEM_AMQP_HOST=10.23.82.4 3 | GOLEM_ID=golem1 -------------------------------------------------------------------------------- /spellbook/environment.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false, 3 | apiUrl: 'http://localhost:3000/' 4 | }; -------------------------------------------------------------------------------- /vault/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "listener": [{ 3 | "tcp": { 4 | "address": "0.0.0.0:8200", 5 | "tls_disable": 1 6 | } 7 | }], 8 | "storage": { 9 | "file": { 10 | "path": "/vault/file" 11 | } 12 | }, 13 | "ui": true 14 | } 15 | -------------------------------------------------------------------------------- /vault/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM hashicorp/vault:latest 2 | 3 | RUN mkdir /vault_data 4 | RUN mkdir /vault_share 5 | RUN apk add --no-cache jq 6 | ADD vault/unseal.sh /usr/local/bin/unseal.sh 7 | ADD vault/config.json /vault_data/config.json 8 | RUN chmod +x /usr/local/bin/unseal.sh 9 | 10 | ENTRYPOINT ["unseal.sh"] 11 | -------------------------------------------------------------------------------- /rabbitmq/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rabbitmq:3-management 2 | RUN apt-get update && apt-get install -y openssl curl && apt-get clean 3 | ADD rabbitmq/amqp-init.sh /amqp-init.sh 4 | RUN chmod +x /amqp-init.sh 5 | RUN mkdir /credentials 6 | RUN chown rabbitmq:rabbitmq credentials 7 | ENV RABBITMQ_PID_FILE /var/lib/rabbitmq/mnesia/rabbitmq 8 | CMD ["/amqp-init.sh"] -------------------------------------------------------------------------------- /mariadb/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mariadb:latest 2 | RUN apt-get update && apt-get install -y openssl curl && apt-get clean 3 | COPY mariadb/spellbook.sql /docker-entrypoint-initdb.d/0-spellbook.sql 4 | COPY mariadb/db-init.sh /docker-entrypoint-initdb.d/1-db-init.sh 5 | RUN chmod +x /docker-entrypoint-initdb.d/1-db-init.sh 6 | RUN mkdir /credentials 7 | RUN chown mysql:mysql credentials -------------------------------------------------------------------------------- /docker-compose-worker-nogpu.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | 5 | golem: 6 | build: 7 | dockerfile: elemental-golem/Dockerfile-nogpu 8 | container_name: spellbook_golem_nogpu 9 | volumes: 10 | - vault_share:/vault_share 11 | - models_share:/server/data 12 | environment: 13 | - GOLEM_ID=${GOLEM_ID} 14 | - GOLEM_AMQP_HOST=${GOLEM_AMQP_HOST} 15 | - GOLEM_VAULT_HOST=${GOLEM_VAULT_HOST} 16 | networks: 17 | spellbook-net: 18 | ipv4_address: 10.23.82.5 19 | 20 | volumes: 21 | vault_share: 22 | models_share: 23 | 24 | networks: 25 | spellbook-net: 26 | ipam: 27 | config: 28 | - subnet: 10.23.82.0/16 29 | -------------------------------------------------------------------------------- /docker-compose-worker.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | 5 | golem: 6 | build: 7 | dockerfile: elemental-golem/Dockerfile 8 | container_name: spellbook_golem 9 | volumes: 10 | - vault_share:/vault_share 11 | - models_share:/server/data 12 | environment: 13 | - GOLEM_ID=${GOLEM_ID} 14 | - GOLEM_AMQP_HOST=${GOLEM_AMQP_HOST} 15 | - GOLEM_VAULT_HOST=${GOLEM_VAULT_HOST} 16 | deploy: 17 | resources: 18 | reservations: 19 | devices: 20 | - driver: nvidia 21 | count: all 22 | capabilities: [gpu] 23 | networks: 24 | spellbook-net: 25 | ipv4_address: 10.23.82.5 26 | 27 | volumes: 28 | vault_share: 29 | models_share: 30 | 31 | networks: 32 | spellbook-net: 33 | ipam: 34 | config: 35 | - subnet: 10.23.82.0/16 36 | -------------------------------------------------------------------------------- /spellbook/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y curl git ca-certificates gnupg sass 5 | 6 | RUN mkdir -p /etc/apt/keyrings 7 | RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg 8 | RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list 9 | RUN apt-get update 10 | RUN apt-get install nodejs -y 11 | RUN npm install -g @angular/cli@latest 12 | RUN echo "Install v0.3.0 of Spellbook UI" 13 | RUN git clone --depth 1 --branch v0.3.0 https://github.com/noco-ai/spellbook-ui.git /app 14 | WORKDIR /app 15 | RUN npm install 16 | ADD spellbook/environment.ts /app/environments/environment.ts 17 | CMD ["ng", "serve", "--host", "0.0.0.0", "--port", "4200"] 18 | # CMD tail -f /dev/null 19 | -------------------------------------------------------------------------------- /elemental-golem/Dockerfile-nogpu: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update && apt-get upgrade -y \ 4 | && apt-get install -y git build-essential \ 5 | python3 python3-pip gcc tar wget \ 6 | ocl-icd-opencl-dev opencl-headers clinfo ffmpeg 7 | 8 | COPY . . 9 | RUN groupadd -r golem && useradd -r -m -g golem golem && mkdir /server && chown -R golem:golem /server 10 | RUN python3 -m pip install --upgrade pip pytest cmake scikit-build setuptools fastapi uvicorn sse-starlette pydantic-settings starlette-context 11 | RUN pip install llama-cpp-python 12 | RUN echo "Installing v0.3.1 of Elemental Golem" 13 | RUN git clone --depth 1 --branch v0.3.1 https://github.com/noco-ai/elemental-golem.git /server 14 | RUN pip install -r /server/requirements-nogpu.txt 15 | RUN mkdir -p /server/data/loras/ 16 | WORKDIR /server 17 | CMD python3 server.py --server-id $GOLEM_ID --amqp-ip $GOLEM_AMQP_HOST --vault-host $GOLEM_VAULT_HOST --vault-token-file /vault_share/read-token --vault-root spellbook --shared-models true --gpu-type nogpu 18 | # CMD tail -f /dev/null 19 | # python3 server.py --server-id golem1 --vault-host http://10.23.82.2:8200 --vault-token-file /vault_share/read-token --vault-root spellbook --shared-models true 20 | -------------------------------------------------------------------------------- /elemental-golem/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nvidia/cuda:12.1.1-devel-ubuntu22.04 2 | 3 | RUN apt-get update && apt-get upgrade -y \ 4 | && apt-get install -y git build-essential \ 5 | python3 python3-pip gcc tar wget \ 6 | ocl-icd-opencl-dev opencl-headers clinfo ffmpeg \ 7 | libclblast-dev libopenblas-dev \ 8 | && mkdir -p /etc/OpenCL/vendors && echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd 9 | 10 | COPY . . 11 | ENV CUDA_DOCKER_ARCH=all 12 | ENV LLAMA_CUBLAS=1 13 | RUN groupadd -r golem && useradd -r -m -g golem golem && mkdir /server && chown -R golem:golem /server 14 | RUN python3 -m pip install --upgrade pip pytest cmake scikit-build setuptools fastapi uvicorn sse-starlette pydantic-settings starlette-context 15 | RUN CMAKE_ARGS="-DLLAMA_CUBLAS=on" pip install llama-cpp-python 16 | RUN echo "Installing v0.3.1 of Elemental Golem" 17 | RUN git clone --depth 1 --branch v0.3.1 https://github.com/noco-ai/elemental-golem.git /server 18 | RUN pip install -r /server/requirements.txt 19 | RUN mkdir -p /server/data/loras/ 20 | WORKDIR /server 21 | CMD python3 server.py --server-id $GOLEM_ID --amqp-ip $GOLEM_AMQP_HOST --vault-host $GOLEM_VAULT_HOST --vault-token-file /vault_share/read-token --vault-root spellbook --shared-models true 22 | #CMD tail -f /dev/null 23 | #python3 server.py --server-id golem1 --vault-host http://10.23.82.2:8200 --vault-token-file /vault_share/read-token --vault-root spellbook --shared-models true 24 | -------------------------------------------------------------------------------- /arcane-bridge/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y curl git ca-certificates gnupg sass && \ 5 | apt-get install -y chromium-browser && \ 6 | apt-get install -y libx11-xcb1 libxcomposite1 libasound2 libatk1.0-0 libatk-bridge2.0-0 libcairo2 libcups2 libdbus-1-3 \ 7 | libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 \ 8 | libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \ 9 | libnss3 10 | RUN mkdir -p /etc/apt/keyrings && \ 11 | curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ 12 | echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ 13 | apt-get update && \ 14 | apt-get install nodejs -y 15 | RUN groupadd -r arcane && useradd -r -m -g arcane arcane && \ 16 | mkdir -p /app && chown arcane:arcane /app 17 | WORKDIR /app 18 | RUN echo "Installing 0.3.0 of Arcane Bridge" 19 | RUN git clone --depth 1 --branch v0.3.0 https://github.com/noco-ai/arcane-bridge.git /app 20 | RUN chown -R arcane:arcane /app 21 | ENV NPM_CONFIG_PREFIX=/app/.npm-global 22 | ENV PATH=$PATH:/app/.npm-global/bin 23 | USER arcane 24 | RUN npm install && npm run compile 25 | CMD ["npm", "run", "start", "--", "-vh", "http://10.23.82.2:8200", "-vt", "/vault_share/write-token", "-cs"] 26 | # CMD tail -f /dev/null 27 | # npm run start -- -vh http://10.23.82.2:8200 -vt /vault_share/write-token -------------------------------------------------------------------------------- /rabbitmq/amqp-init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VAULT_ADDR=http://10.23.82.2:8200 4 | MAX_RETRIES=50 5 | RETRY_INTERVAL=5 6 | 7 | configure_rabbitmq() { 8 | 9 | USERNAME="user_$(openssl rand -hex 4)" 10 | PASSWORD="$(openssl rand -hex 8)" 11 | 12 | ( rabbitmqctl wait --timeout 60 $RABBITMQ_PID_FILE ; \ 13 | rabbitmqctl add_vhost spellbook ; \ 14 | rabbitmqctl add_user $USERNAME $PASSWORD 2>/dev/null ; \ 15 | rabbitmqctl set_user_tags $USERNAME administrator ; \ 16 | rabbitmqctl set_permissions -p spellbook $USERNAME ".*" ".*" ".*" ; \ 17 | rabbitmqctl delete_user guest ) & 18 | 19 | echo "RabbitMQ user ${USERNAME} created and permissions set." 20 | 21 | RETRY_COUNT=0 22 | while true; do 23 | curl --fail -X GET "${VAULT_ADDR}/v1/sys/health" 24 | if [ $? -eq 0 ]; then 25 | # Get the write token from the tokens file in Vault container 26 | TOKEN=$(cat /vault_share/write-token) 27 | curl \ 28 | --header "X-Vault-Token: ${TOKEN}" \ 29 | --header "Content-Type: application/json" \ 30 | --request POST \ 31 | --data '{"data": { "vhost":"spellbook", "host": "10.23.82.4", "username":"'"${USERNAME}"'", "password":"'"${PASSWORD}"'" }}' \ 32 | ${VAULT_ADDR}/v1/spellbook/data/core/amqp 33 | echo "Credentials saved to Vault successfully!" 34 | break 35 | else 36 | RETRY_COUNT=$((RETRY_COUNT+1)) 37 | if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then 38 | echo "Failed to connect to Vault after $MAX_RETRIES retries. Credentials are not saved!" 39 | break 40 | fi 41 | 42 | echo "Failed to connect to Vault. Retrying in $RETRY_INTERVAL seconds..." 43 | sleep $RETRY_INTERVAL 44 | fi 45 | done 46 | 47 | } 48 | 49 | if [ ! -f "/credentials/credentials_initialized" ]; then 50 | configure_rabbitmq 51 | touch /credentials/credentials_initialized 52 | fi 53 | 54 | rabbitmq-server $@ 55 | -------------------------------------------------------------------------------- /vault/unseal.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Start vault in server mode in the background 4 | export VAULT_API_ADDR='http://0.0.0.0:8200' 5 | 6 | vault server --config=/vault_data/config.json & 7 | 8 | VAULT_READY=0 9 | MAX_RETRIES=30 10 | RETRY_COUNT=0 11 | 12 | while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do 13 | vault status | grep -q 'Sealed' 14 | if [ $? -eq 0 ]; then 15 | break # Exit the loop if 'Sealed' is found in the output 16 | else 17 | RETRY_COUNT=$((RETRY_COUNT+1)) 18 | sleep 2 # Wait 2 seconds before retrying 19 | fi 20 | done 21 | 22 | if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then 23 | echo "Vault server is not ready. Exiting." 24 | exit 1 25 | fi 26 | 27 | # Check if vault is already initialized 28 | VAULT_STATUS=$(vault status) 29 | if echo "$VAULT_STATUS" | grep "Sealed" | awk '{print $NF}' | grep -q "true"; then 30 | if /usr/bin/test ! -f "/vault_data/unseal_info.txt"; then 31 | # If vault is not initialized and no unseal_info.txt exists, initialize it 32 | echo "Initializing vault server..." 33 | vault operator init > /vault_data/unseal_info.txt 34 | fi 35 | 36 | # Unseal using the keys from unseal_info.txt 37 | cat /vault_data/unseal_info.txt | grep "Unseal Key" | cut -d ":" -f2 | tr -d " " | while read -r line ; do 38 | vault operator unseal $line 39 | done 40 | fi 41 | 42 | ROOT_TOKEN=$(cat /vault_data/unseal_info.txt | grep "Root Token:" | cut -d ":" -f2 | tr -d ' ') 43 | export VAULT_TOKEN=${ROOT_TOKEN} 44 | 45 | # Enable the KV secrets engine at the spellbook path if it's not already enabled 46 | if ! vault secrets list | grep -q 'spellbook'; then 47 | vault secrets enable -path=spellbook kv-v2 48 | echo "KV secrets engine enabled at path spellbook" 49 | fi 50 | 51 | if ! vault policy list | grep -q 'read-policy'; then 52 | 53 | echo 'path "spellbook/*" { 54 | capabilities = ["read"] 55 | }' | vault policy write read-policy - 56 | echo "Creating vault read policy" 57 | fi 58 | 59 | if ! vault policy list | grep -q 'write-policy'; then 60 | echo 'path "spellbook/*" { 61 | capabilities = ["create", "update", "read"] 62 | }' | vault policy write write-policy - 63 | echo "Creating vault write policy" 64 | fi 65 | 66 | if /usr/bin/test ! -f "/vault_share/read-token"; then 67 | echo "$(vault token create -policy=read-policy -format=json | jq -r .auth.client_token)" > /vault_share/read-token 68 | echo "$(vault token create -policy=write-policy -format=json | jq -r .auth.client_token)" >> /vault_share/write-token 69 | fi 70 | 71 | # Keep the container running 72 | echo "Vault started" 73 | 74 | tail -f /dev/null 75 | -------------------------------------------------------------------------------- /docker-compose-nogpu.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | vault: 5 | build: 6 | dockerfile: vault/Dockerfile 7 | container_name: spellbook_vault 8 | ports: 9 | - "8200:8200" 10 | environment: 11 | VAULT_ADDR: http://0.0.0.0:8200 12 | volumes: 13 | - vault_share:/vault_share 14 | cap_add: 15 | - IPC_LOCK 16 | networks: 17 | spellbook-net: 18 | ipv4_address: 10.23.82.2 19 | 20 | mariadb: 21 | build: 22 | dockerfile: mariadb/Dockerfile 23 | container_name: spellbook_mariadb 24 | environment: 25 | MARIADB_ROOT_PASSWORD: "spellBOOK.temp.321" 26 | MARIADB_DATABASE: "spellbook" 27 | volumes: 28 | - vault_share:/vault_share 29 | ports: 30 | - "3306:3306" 31 | depends_on: 32 | - vault 33 | networks: 34 | spellbook-net: 35 | ipv4_address: 10.23.82.3 36 | 37 | spellbook_ui: 38 | build: 39 | dockerfile: spellbook/Dockerfile 40 | container_name: spellbook_ui 41 | volumes: 42 | - vault_share:/vault_share 43 | ports: 44 | - "4200:4200" 45 | depends_on: 46 | - vault 47 | - mariadb 48 | - rabbitmq 49 | networks: 50 | spellbook-net: 51 | ipv4_address: 10.23.82.6 52 | 53 | arcane_bridge: 54 | build: 55 | dockerfile: arcane-bridge/Dockerfile 56 | container_name: spellbook_arcane_bridge 57 | volumes: 58 | - vault_share:/vault_share 59 | ports: 60 | - "3000:3000" 61 | depends_on: 62 | - vault 63 | - mariadb 64 | - rabbitmq 65 | networks: 66 | spellbook-net: 67 | ipv4_address: 10.23.82.7 68 | 69 | golem: 70 | build: 71 | dockerfile: elemental-golem/Dockerfile-nogpu 72 | container_name: spellbook_golem 73 | environment: 74 | - GOLEM_ID=${GOLEM_ID} 75 | - GOLEM_AMQP_HOST=${GOLEM_AMQP_HOST} 76 | - GOLEM_VAULT_HOST=${GOLEM_VAULT_HOST} 77 | volumes: 78 | - vault_share:/vault_share 79 | - models_share:/server/data 80 | depends_on: 81 | - vault 82 | - rabbitmq 83 | networks: 84 | spellbook-net: 85 | ipv4_address: 10.23.82.5 86 | 87 | rabbitmq: 88 | build: 89 | dockerfile: rabbitmq/Dockerfile 90 | container_name: spellbook_rabbitmq 91 | depends_on: 92 | - vault 93 | ports: 94 | - "15672:15672" 95 | - "5672:5672" 96 | - "5671:5671" 97 | volumes: 98 | - vault_share:/vault_share 99 | networks: 100 | spellbook-net: 101 | ipv4_address: 10.23.82.4 102 | 103 | volumes: 104 | vault_share: 105 | models_share: 106 | 107 | networks: 108 | spellbook-net: 109 | ipam: 110 | config: 111 | - subnet: 10.23.82.0/16 112 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | vault: 5 | build: 6 | dockerfile: vault/Dockerfile 7 | container_name: spellbook_vault 8 | ports: 9 | - "8200:8200" 10 | environment: 11 | VAULT_ADDR: http://0.0.0.0:8200 12 | volumes: 13 | - vault_share:/vault_share 14 | cap_add: 15 | - IPC_LOCK 16 | networks: 17 | spellbook-net: 18 | ipv4_address: 10.23.82.2 19 | 20 | mariadb: 21 | build: 22 | dockerfile: mariadb/Dockerfile 23 | container_name: spellbook_mariadb 24 | environment: 25 | MARIADB_ROOT_PASSWORD: "spellBOOK.temp.321" 26 | MARIADB_DATABASE: "spellbook" 27 | volumes: 28 | - vault_share:/vault_share 29 | ports: 30 | - "3306:3306" 31 | depends_on: 32 | - vault 33 | networks: 34 | spellbook-net: 35 | ipv4_address: 10.23.82.3 36 | 37 | spellbook_ui: 38 | build: 39 | dockerfile: spellbook/Dockerfile 40 | container_name: spellbook_ui 41 | volumes: 42 | - vault_share:/vault_share 43 | ports: 44 | - "4200:4200" 45 | depends_on: 46 | - vault 47 | - mariadb 48 | - rabbitmq 49 | networks: 50 | spellbook-net: 51 | ipv4_address: 10.23.82.6 52 | 53 | arcane_bridge: 54 | build: 55 | dockerfile: arcane-bridge/Dockerfile 56 | container_name: spellbook_arcane_bridge 57 | volumes: 58 | - vault_share:/vault_share 59 | ports: 60 | - "3000:3000" 61 | depends_on: 62 | - vault 63 | - mariadb 64 | - rabbitmq 65 | networks: 66 | spellbook-net: 67 | ipv4_address: 10.23.82.7 68 | 69 | golem: 70 | build: 71 | dockerfile: elemental-golem/Dockerfile 72 | container_name: spellbook_golem 73 | volumes: 74 | - vault_share:/vault_share 75 | - models_share:/server/data 76 | environment: 77 | - GOLEM_ID=${GOLEM_ID} 78 | - GOLEM_AMQP_HOST=${GOLEM_AMQP_HOST} 79 | - GOLEM_VAULT_HOST=${GOLEM_VAULT_HOST} 80 | depends_on: 81 | - vault 82 | - rabbitmq 83 | deploy: 84 | resources: 85 | reservations: 86 | devices: 87 | - driver: nvidia 88 | count: all 89 | capabilities: [gpu] 90 | networks: 91 | spellbook-net: 92 | ipv4_address: 10.23.82.5 93 | 94 | rabbitmq: 95 | build: 96 | dockerfile: rabbitmq/Dockerfile 97 | container_name: spellbook_rabbitmq 98 | depends_on: 99 | - vault 100 | ports: 101 | - "15672:15672" 102 | - "5672:5672" 103 | - "5671:5671" 104 | volumes: 105 | - vault_share:/vault_share 106 | networks: 107 | spellbook-net: 108 | ipv4_address: 10.23.82.4 109 | 110 | volumes: 111 | vault_share: 112 | models_share: 113 | 114 | networks: 115 | spellbook-net: 116 | ipam: 117 | config: 118 | - subnet: 10.23.82.0/16 119 | -------------------------------------------------------------------------------- /mariadb/db-init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VAULT_ADDR=http://10.23.82.2:8200 4 | SQL_ADDR=10.23.82.3 5 | MAX_RETRIES=50 6 | RETRY_INTERVAL=5 # Time in seconds 7 | 8 | wait_for_mariadb() { 9 | RETRY_COUNT=0 10 | while true; do 11 | mariadb -u root -pspellBOOK.temp.321 -e "SELECT 1;" >/dev/null 2>&1 12 | if [ $? -eq 0 ]; then 13 | echo "MariaDB is ready!" 14 | return 0 15 | else 16 | RETRY_COUNT=$((RETRY_COUNT+1)) 17 | if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then 18 | echo "Failed to connect to MariaDB after $MAX_RETRIES retries." 19 | return 1 20 | fi 21 | echo "Waiting for MariaDB to be ready. Retrying in $RETRY_INTERVAL seconds..." 22 | sleep $RETRY_INTERVAL 23 | fi 24 | done 25 | } 26 | 27 | change_root_password() { 28 | NEW_ROOT_PASSWORD="$(openssl rand -hex 12)" 29 | mariadb -u root -pspellBOOK.temp.321 -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '${NEW_ROOT_PASSWORD}';" 30 | echo $NEW_ROOT_PASSWORD > /credentials/root_password 31 | } 32 | 33 | # Check if the credentials file already exists which indicates if the DB has been initialized before 34 | if [ ! -f "/credentials/credentials_initialized" ]; then 35 | wait_for_mariadb 36 | 37 | # Generate random username and password 38 | USERNAME="user_$(openssl rand -hex 4)" 39 | PASSWORD="$(openssl rand -hex 8)" 40 | 41 | # Create the new user in MariaDB 42 | mariadb -u root -pspellBOOK.temp.321 -e "CREATE USER '${USERNAME}'@'%' IDENTIFIED BY '${PASSWORD}';" 43 | mariadb -u root -pspellBOOK.temp.321 -e "GRANT ALL PRIVILEGES ON spellbook.* TO '${USERNAME}'@'%' WITH GRANT OPTION;" 44 | 45 | # Check Vault connection with retries 46 | echo "CHECKING VAULT" 47 | RETRY_COUNT=0 48 | while true; do 49 | curl --fail -X GET "${VAULT_ADDR}/v1/sys/health" 50 | if [ $? -eq 0 ]; then 51 | # Get the write token from the tokens file in Vault container 52 | TOKEN=$(cat /vault_share/write-token) 53 | READ_TOKEN=$(cat /vault_share/read-token) 54 | 55 | # Write the credentials to Vault 56 | curl \ 57 | --header "X-Vault-Token: ${TOKEN}" \ 58 | --header "Content-Type: application/json" \ 59 | --request POST \ 60 | --data '{"data": { "database": "spellbook", "dialect": "mysql", "host": "'"${SQL_ADDR}"'", "port": 3306, "username":"'"${USERNAME}"'", "password":"'"${PASSWORD}"'" }}' \ 61 | ${VAULT_ADDR}/v1/spellbook/data/core/sequelize 62 | 63 | echo "Credentials saved to Vault successfully!" 64 | 65 | curl \ 66 | --header "X-Vault-Token: ${TOKEN}" \ 67 | --header "Content-Type: application/json" \ 68 | --request POST \ 69 | --data '{"data": { "base_url": "http://localhost:3000/", "workspace_url": "http://10.23.82.7:3000/" } }' \ 70 | ${VAULT_ADDR}/v1/spellbook/data/core/settings 71 | 72 | echo "Base URL saved to Vault successfully!" 73 | 74 | echo "WRITE TOKEN: $TOKEN" 75 | echo "READ TOKEN: $READ_TOKEN" 76 | break 77 | else 78 | RETRY_COUNT=$((RETRY_COUNT+1)) 79 | if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then 80 | echo "Failed to connect to Vault after $MAX_RETRIES retries. Credentials are not saved!" 81 | break 82 | fi 83 | 84 | echo "Failed to connect to Vault. Retrying in $RETRY_INTERVAL seconds..." 85 | sleep $RETRY_INTERVAL 86 | fi 87 | done 88 | 89 | change_root_password 90 | 91 | # Create a file to mark the credentials have been initialized 92 | touch /credentials/credentials_initialized 93 | fi -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spellbook Docker Compose 2 | 3 | The repository contains the Docker Compose files for running the Spellbook AI Assistant stack. The function calling features 4 | require ExLlama and a Nvidia Ampere or better GPU for real-time results. 5 | 6 | ![UI demo](https://github.com/noco-ai/spellbook-docker/blob/master/ui-demo.gif) 7 | 8 | ## Stack Architecture 9 | 10 | ![Software stack diagram](https://github.com/noco-ai/spellbook-docker/blob/master/stack.png) 11 | 12 | ## Ubuntu 22 Install Instructions 13 | 14 | These instructions should work to get the SpellBook framework up and running on Ubuntu 22. A Nvidia video card supported by ExLlama is required for routing. 15 | 16 | - Default username: admin 17 | - Default password: admin 18 | 19 | ### Docker Installation 20 | 21 | ```bash 22 | # add Dockers official GPG key: 23 | sudo apt-get update 24 | sudo apt-get install ca-certificates curl gnupg 25 | sudo install -m 0755 -d /etc/apt/keyrings 26 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg 27 | sudo chmod a+r /etc/apt/keyrings/docker.gpg 28 | 29 | # add the repository to apt sources: 30 | echo \ 31 | "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ 32 | "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ 33 | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null 34 | sudo apt-get update 35 | 36 | # install docker, create user and let current user access docker 37 | sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 38 | sudo groupadd docker 39 | sudo usermod -aG docker $USER 40 | sudo newgrp docker 41 | sudo shutdown -r now 42 | ``` 43 | 44 | ### Build and Start Containers (No GPU) 45 | 46 | The docker-compose-nogpu.yml is useful for running the UI and middleware in a situation where you want another backend handling you GPUs and LLMs. For example 47 | if you are also using Text Generation UI and do not want to mess with it settings this compose file can be used to just run the UI, allowing you then to then connect it to the endpoint provided by Oobabooga or any other OpenAI compatible backend. 48 | 49 | ```bash 50 | docker compose -f docker-compose-nogpu.yml build 51 | docker compose -f docker-compose-nogpu.yml up 52 | ``` 53 | 54 | ### Build and Start Additional Workers (No GPU) 55 | 56 | If you have more than one server you can run additional Elemental Golem workers to give the UI access to more resources. A few steps need to be taken on the 57 | primary Spellbook server that is running the UI, middleware and other resources like Vault. 58 | 59 | - Run these command on the primary server that is running the UI and middleware software in Docker. 60 | - Copy the read token to a temp file to copy it to the worker server. 61 | - Make note of the LAN IP address of the primary server. It is needed for the GOLEM_VAULT_HOST and GOLEM_VAULT_HOST variables. 62 | - Make sure ports for RabbitMQ and Vault are open. 63 | 64 | ```bash 65 | sudo more /var/lib/docker/volumes/spellbook-docker_vault_share/_data/read-token 66 | ip address 67 | sudo ufw allow 5671 68 | sudo ufw allow 5672 69 | sudo ufw allow 8200 70 | ``` 71 | 72 | - Run these command on the server running the worker. The GOLEM_ID needs to be unique for every server and golem1 is used by the primary. 73 | - The first time you run the container it will timeout, git CTL + C or wait then copy the Vault token. 74 | ```bash 75 | docker compose -f docker-compose-worker-nogpu.yml build 76 | GOLEM_VAULT_HOST=10.10.10.X GOLEM_AMQP_HOST=10.10.10.X GOLEM_ID=golem2 docker compose -f docker-compose-worker-nogpu.yml up 77 | sudo su 78 | echo "TOKEN FROM PRIMARY SERVER" > /var/lib/docker/volumes/spellbook-docker_vault_share/_data/read-token 79 | exit 80 | GOLEM_VAULT_HOST=10.10.10.X GOLEM_AMQP_HOST=10.10.10.X GOLEM_ID=golem2 docker compose -f docker-compose-worker-nogpu.yml up 81 | ``` 82 | 83 | ### Nvidia Driver Installation 84 | 85 | ```bash 86 | # make sure system see's the Nvidia graphic(s) card 87 | lspci | grep -e VGA 88 | 89 | # check available drivers 90 | ubuntu-drivers devices 91 | 92 | # install the latest driver 93 | sudo apt install nvidia-driver-535 94 | 95 | # restart the server 96 | sudo shutdown -h now 97 | 98 | # confirm driver was installed 99 | nvidia-smi 100 | 101 | # install the Nvidia docker toolkit 102 | curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ 103 | && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ 104 | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ 105 | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list \ 106 | && \ 107 | sudo apt-get update 108 | 109 | sudo apt-get install -y nvidia-container-toolkit 110 | sudo nvidia-ctk runtime configure --runtime=docker 111 | sudo systemctl restart docker 112 | 113 | # verify see the output of nvidia-smi for inside a container 114 | sudo docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi 115 | ``` 116 | 117 | ### Build and Start Containers (Nvidia GPU) 118 | 119 | ```bash 120 | docker compose build 121 | docker compose up 122 | ``` 123 | 124 | ### Build and Start Additional Workers (Nvidia GPU) 125 | 126 | Follow the directions under the *Build and Start Additional Workers (No GPU)* section substituting the build and up lines for the ones found below. 127 | ```bash 128 | docker compose -f docker-compose-worker.yml build 129 | GOLEM_VAULT_HOST=10.10.10.X GOLEM_AMQP_HOST=10.10.10.X GOLEM_ID=golem2 docker compose -f docker-compose-worker.yml up 130 | ``` 131 | 132 | ### Port Forwarding 133 | 134 | This repository assumes you are running the docker containers on your local system if this is not the case make sure ports **3000** and **4200** are forwarded to the host running the docker containers. 135 | 136 | ### Fresh Install 137 | 138 | For a fresh install of the stack run the following commands, this will remove all downloaded models and all conversation and configuration records. 139 | 140 | ```bash 141 | cd spellbook-docker 142 | docker compose down 143 | docker volume rm spellbook-docker_models_share 144 | docker volume rm spellbook-docker_vault_share 145 | git pull origin master 146 | docker compose build 147 | docker compose up 148 | ``` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Open Software License ("OSL") v. 3.0 2 | 3 | This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: 4 | 5 | Licensed under the Open Software License version 3.0 6 | 7 | 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: 8 | 9 | 1. to reproduce the Original Work in copies, either alone or as part of a collective work; 10 | 11 | 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; 12 | 13 | 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License; 14 | 15 | 4. to perform the Original Work publicly; and 16 | 17 | 5. to display the Original Work publicly. 18 | 19 | 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. 20 | 21 | 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. 22 | 23 | 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. 24 | 25 | 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). 26 | 27 | 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. 28 | 29 | 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. 30 | 31 | 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. 32 | 33 | 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including 'fair use' or 'fair dealing'). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). 34 | 35 | 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. 36 | 37 | 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. 38 | 39 | 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. 40 | 41 | 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. 42 | 43 | 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 44 | 45 | 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. 46 | 47 | 16. Modification of This License. This License is Copyright (C) 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. -------------------------------------------------------------------------------- /mariadb/spellbook.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 5.7.32, for Linux (x86_64) 2 | -- 3 | -- Host: localhost Database: spellbook 4 | -- ------------------------------------------------------ 5 | -- Server version 5.7.32 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!40101 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `chat_ability` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `chat_ability`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!40101 SET character_set_client = utf8 */; 25 | CREATE TABLE `chat_ability` ( 26 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 27 | `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, 28 | `uses` json NOT NULL, 29 | `module` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, 30 | `version` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, 31 | `is_published` int(11) NOT NULL DEFAULT '0', 32 | `description` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, 33 | `author` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, 34 | `published_version` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, 35 | `created_at` datetime NOT NULL, 36 | `updated_at` datetime NOT NULL, 37 | PRIMARY KEY (`id`) 38 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 39 | /*!40101 SET character_set_client = @saved_cs_client */; 40 | 41 | DROP TABLE IF EXISTS `chat_conversation`; 42 | /*!40101 SET @saved_cs_client = @@character_set_client */; 43 | /*!40101 SET character_set_client = utf8 */; 44 | CREATE TABLE `chat_conversation` ( 45 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 46 | `user_id` int(10) unsigned NOT NULL, 47 | `ally_id` int(10) unsigned DEFAULT 0, 48 | `first_message_id` int(10) unsigned DEFAULT 0, 49 | `is_private` tinyint(1) NOT NULL, 50 | `is_shared` tinyint(1) NOT NULL, 51 | `system_message` text COLLATE utf8mb4_unicode_ci, 52 | `use_model` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 53 | `topic` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 54 | `seed` bigint(10) DEFAULT '-1', 55 | `temperature` float DEFAULT '1', 56 | `top_k` int(10) DEFAULT 50, 57 | `top_p` float DEFAULT '0.9', 58 | `min_p` float DEFAULT '0.05', 59 | `mirostat` int(10) DEFAULT 0, 60 | `mirostat_tau` float DEFAULT '5.0', 61 | `mirostat_eta` float DEFAULT '0.1', 62 | `created_at` datetime NOT NULL, 63 | `updated_at` datetime NOT NULL, 64 | `locked` int(10) unsigned DEFAULT '0', 65 | `router_config` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT 'function_calling,model_routing,pin_functions,pin_models', 66 | PRIMARY KEY (`id`) 67 | ) ENGINE=InnoDB AUTO_INCREMENT=2052 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 68 | /*!40101 SET character_set_client = @saved_cs_client */; 69 | 70 | DROP TABLE IF EXISTS `chat_conversation_message`; 71 | /*!40101 SET @saved_cs_client = @@character_set_client */; 72 | /*!40101 SET character_set_client = utf8 */; 73 | CREATE TABLE `chat_conversation_message` ( 74 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 75 | `user_id` int(10) unsigned NOT NULL, 76 | `content` text COLLATE utf8mb4_unicode_ci NOT NULL, 77 | `role` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, 78 | `conversation_id` int(10) unsigned NOT NULL, 79 | `parent_id` int(10) unsigned DEFAULT NULL, 80 | `active_child_id` int(10) unsigned DEFAULT NULL, 81 | `num_children` int(11) DEFAULT '0', 82 | `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 83 | `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 84 | `icon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 85 | `shortcuts` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 86 | `files` text COLLATE utf8mb4_unicode_ci, 87 | PRIMARY KEY (`id`) 88 | ) ENGINE=InnoDB AUTO_INCREMENT=7503 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 89 | /*!40101 SET character_set_client = @saved_cs_client */; 90 | 91 | -- 92 | -- Table structure for table `dynamic_functions` 93 | -- 94 | 95 | DROP TABLE IF EXISTS `dynamic_functions`; 96 | /*!40101 SET @saved_cs_client = @@character_set_client */; 97 | /*!40101 SET character_set_client = utf8 */; 98 | CREATE TABLE `dynamic_functions` ( 99 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 100 | `definition` text COLLATE utf8mb4_unicode_ci NOT NULL, 101 | `code` text COLLATE utf8mb4_unicode_ci NOT NULL, 102 | `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 103 | `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 104 | PRIMARY KEY (`id`) 105 | ) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 106 | /*!40101 SET character_set_client = @saved_cs_client */; 107 | 108 | -- 109 | -- Dumping data for table `dynamic_functions` 110 | -- 111 | 112 | LOCK TABLES `dynamic_functions` WRITE; 113 | /*!40000 ALTER TABLE `dynamic_functions` DISABLE KEYS */; 114 | INSERT INTO `dynamic_functions` VALUES (5,'{\n \"function_description\": \"Calculates the product of two numbers.\",\n \"parameters\": {\n \"num1\": {\n \"description\": \"The first number to be multiplied.\",\n \"type\": \"number\"\n },\n \"num2\": {\n \"description\": \"The second number to be multiplied.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { num1, num2 } = params;\n const result = num1 * num2;\n return `The product of ${num1} and ${num2} is ${result}.`;\n}','2023-10-23 21:52:47','2023-10-23 21:52:47'),(6,'{\n \"function_description\": \"Calculates the square root of a given number.\",\n \"parameters\": {\n \"num\": {\n \"description\": \"The number to calculate the square root of.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { num } = params;\n const result = Math.sqrt(num);\n return `The square root of ${num} is ${result}.`;\n}','2023-10-23 21:56:13','2023-10-23 21:56:13'),(7,'{\n \"function_description\": \"This function counts the number of occurrences of a given word in a given text.\",\n \"parameters\": {\n \"word\": {\n \"description\": \"The word to count the occurrences for.\",\n \"type\": \"string\"\n },\n \"text\": {\n \"description\": \"The text from which to count the occurrences.\",\n \"type\": \"string\"\n }\n }\n}','function executeFunction(params) {\n const { word, text } = params;\n const count = (text.match(new RegExp(word, \"gi\")) || []).length;\n return `The word \'${word}\' appears ${count} times in the given text.`;\n}','2023-10-23 22:29:42','2023-10-23 22:29:42'),(9,'{\n \"function_description\": \"This function calculates the sum of two numbers.\",\n \"parameters\": {\n \"num1\": {\n \"description\": \"The first number to be added.\",\n \"type\": \"number\"\n },\n \"num2\": {\n \"description\": \"The second number to be added.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { num1, num2 } = params;\n const result = num1 + num2;\n return `The sum of ${num1} and ${num2} is ${result}.`;\n}','2023-10-24 06:25:43','2023-10-24 06:25:43'),(12,'{\n \"function_description\": \"Calculates the factorial of a given number.\",\n \"parameters\": {\n \"num\": {\n \"description\": \"The number to calculate the factorial for.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { num } = params;\n let result = 1;\n\n for (let i = 2; i <= num; i++) {\n result *= i;\n }\n\n return `The factorial of ${num} is ${result}.`;\n}','2023-10-24 21:23:30','2023-10-24 21:23:30'),(13,'{\n \"function_description\": \"This function checks if a given word is a palindrome.\",\n \"parameters\": {\n \"word\": {\n \"description\": \"The word to check for palindromicity.\",\n \"type\": \"string\"\n }\n }\n}','function executeFunction(params) {\n const { word } = params;\n const isPalindrome = word.toLowerCase() === word.toLowerCase().split(\'\').reverse().join(\'\');\n return isPalindrome ? `${word} is a palindrome.` : `${word} is not a palindrome.`;\n}','2023-10-24 21:24:39','2023-10-24 21:24:39'),(14,'{\n \"function_description\": \"This function checks if a given number is a prime number or not.\",\n \"parameters\": {\n \"number\": {\n \"description\": \"The number to be checked for primality.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { number } = params;\n \n let isPrime = true;\n\n if (number === 1) {\n isPrime = false;\n } else if (number > 1) {\n for (let i = 2; i < number; i++) {\n if (number % i === 0) {\n isPrime = false;\n break;\n }\n }\n }\n\n return isPrime \n ? `${number} is a prime number.` \n : `${number} is not a prime number.`;\n}','2023-10-24 21:25:31','2023-10-24 21:25:31'),(15,'{\n \"function_description\": \"This function calculates the greatest common divisor (GCD) of two numbers.\",\n \"parameters\": {\n \"num1\": {\n \"description\": \"The first number to calculate GCD with.\",\n \"type\": \"number\"\n },\n \"num2\": {\n \"description\": \"The second number to calculate GCD with.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n let num1 = params.num1, num2 = params.num2;\n while(num2) {\n let t = num2;\n num2 = num1 % num2;\n num1 = t;\n }\n return `The greatest common divisor of ${params.num1} and ${params.num2} is ${num1}.`;\n}','2023-10-24 21:26:32','2023-10-24 21:26:32'),(16,'{\n \"function_description\": \"This function calculates the least common multiple (LCM) of two numbers.\",\n \"parameters\": {\n \"num1\": {\n \"description\": \"The first number to calculate LCM with.\",\n \"type\": \"number\"\n },\n \"num2\": {\n \"description\": \"The second number to calculate LCM with.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { num1, num2 } = params;\n let lcm;\n let max = Math.max(num1, num2);\n let min = Math.min(num1, num2);\n for (let i = max; ; i += max) {\n if (i % min === 0) {\n lcm = i;\n break;\n }\n }\n return `The least common multiple of ${num1} and ${num2} is ${lcm}.`;\n}','2023-10-24 21:27:00','2023-10-24 21:27:00'),(18,'{\n \"function_description\": \"This function takes an array as input and returns a list of duplicate numbers.\",\n \"parameters\": {\n \"array\": {\n \"description\": \"The array containing the elements to search for duplicates.\",\n \"type\": \"list\"\n }\n }\n}','function executeFunction(params) {\n const { array } = params;\n let duplicates = [];\n array.sort();\n \n for (let i = 0; i < array.length; i++) {\n if (array[i + 1] === array[i]) {\n duplicates.push(array[i]);\n }\n }\n \n duplicates = [...new Set(duplicates)];\n return `The duplicate numbers in the given array are ${duplicates.join(\", \")}.`;\n}','2023-10-24 21:29:31','2023-10-24 21:29:31'),(20,'{\n \"function_description\": \"This function takes an integer as input and returns its reverse.\",\n \"parameters\": {\n \"num\": {\n \"description\": \"The number to be reversed.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { num } = params;\n const reversed = parseInt(num.toString().split(\'\').reverse().join(\'\')) * Math.sign(num);\n return `The reverse of ${num} is ${reversed}.`;\n}','2023-10-24 21:31:51','2023-10-24 21:31:51'),(21,'{\n \"function_description\": \"This function takes a list of numbers as input and returns the third highest number.\",\n \"parameters\": {\n \"numbers\": {\n \"description\": \"The list of numbers to find the third highest from.\",\n \"type\": \"array\"\n }\n }\n}','function executeFunction(params) {\n const { numbers } = params;\n const sortedNumbers = numbers.sort((a, b) => b - a);\n const thirdHighestNumber = sortedNumbers[2];\n return `The third highest number in the list [${numbers}] is ${thirdHighestNumber}.`;\n}','2023-10-24 21:32:17','2023-10-24 21:32:17'),(22,'{\n \"function_description\": \"This function finds all the prime numbers in a given range.\",\n \"parameters\": {\n \"start\": {\n \"description\": \"The starting number of the range.\",\n \"type\": \"number\"\n },\n \"end\": {\n \"description\": \"The ending number of the range.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { start, end } = params;\n let primes = [];\n \n for(let i = start; i <= end; i++) {\n if(isPrime(i)) {\n primes.push(i);\n }\n }\n\n function isPrime(num) {\n for(let i = 2, sqrt = Math.sqrt(num); i <= sqrt; i++)\n if(num % i === 0) return false; \n return num > 1;\n }\n\n return `The prime numbers between ${start} and ${end} are ${primes.join(\", \")}.`;\n}','2023-10-24 21:33:12','2023-10-24 21:33:12'),(24,'{\n \"function_description\": \"This function calculates the voltage across a given resistor based on its resistance and current.\",\n \"parameters\": {\n \"resistance\": {\n \"description\": \"The resistance value of the resistor in Ohms (Ω).\",\n \"type\": \"number\"\n },\n \"current\": {\n \"description\": \"The current flowing through the resistor in Amperes (A).\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { resistance, current } = params;\n const voltage = resistance * current;\n return `The voltage across a resistor with a resistance of ${resistance} Ohms and current of ${current} Amperes is ${voltage} Volts.`;\n}','2023-10-24 21:35:46','2023-10-24 21:35:46'),(25,'{\n \"function_description\": \"This function calculates the amount of power dissipated in a resistive element given its resistance and current.\",\n \"parameters\": {\n \"resistance\": {\n \"description\": \"The resistance value of the resistive element in ohms (Ω).\",\n \"type\": \"number\"\n },\n \"current\": {\n \"description\": \"The current flowing through the resistive element in amps (A).\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { resistance, current } = params;\n const power = Math.pow(current, 2) * resistance;\n return `The power dissipated in a resistive element with resistance ${resistance} ohms and current ${current} amps is ${power} watts.`;\n}','2023-10-24 21:36:24','2023-10-24 21:36:24'),(28,'{\n \"function_description\": \"This function calculates the kinetic energy of an object given its mass and velocity.\",\n \"parameters\": {\n \"mass\": {\n \"description\": \"The mass of the object in kilograms.\",\n \"type\": \"number\"\n },\n \"velocity\": {\n \"description\": \"The velocity of the object in meters per second.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { mass, velocity } = params;\n const result = 0.5 * mass * velocity * velocity;\n return `The kinetic energy of an object with mass ${mass} kg and velocity ${velocity} m/s is ${result} joules.`;\n}','2023-10-24 21:39:51','2023-10-24 21:39:51'),(31,'{\n \"function_description\": \"This function calculates the mean of a given set of numbers.\",\n \"parameters\": {\n \"numbers\": {\n \"description\": \"The list of numbers to calculate the mean from.\",\n \"type\": \"array\"\n }\n }\n}','function executeFunction(params) {\n const { numbers } = params;\n const sum = numbers.reduce((a, b) => a + b, 0);\n const mean = sum / numbers.length;\n return `The mean of the numbers ${numbers.join(\', \')} is ${mean}.`;\n}','2023-10-24 21:43:50','2023-10-24 21:43:50'),(32,'{\n \"function_description\": \"Calculates the standard deviation of a given set of numbers.\",\n \"parameters\": {\n \"numbers\": {\n \"description\": \"The list of numbers to calculate the standard deviation from.\",\n \"type\": \"array\"\n }\n }\n}','function executeFunction(params) {\n const { numbers } = params;\n const mean = numbers.reduce((acc, val) => acc + val, 0) / numbers.length;\n const variance = numbers.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) / numbers.length;\n const result = Math.sqrt(variance);\n return `The standard deviation of [${numbers}] is ${result}.`;\n}','2023-10-24 21:44:21','2023-10-24 21:44:21'),(34,'{\n \"function_description\": \"Calculates the number of calories in a given meal.\",\n \"parameters\": {\n \"carbs\": {\n \"description\": \"The amount of carbohydrates in the meal (in grams).\",\n \"type\": \"number\"\n },\n \"protein\": {\n \"description\": \"The amount of protein in the meal (in grams).\",\n \"type\": \"number\"\n },\n \"fat\": {\n \"description\": \"The amount of fat in the meal (in grams).\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { carbs, protein, fat } = params;\n const calories = (carbs * 4) + (protein * 4) + (fat * 9);\n return `The meal with ${carbs}g of carbs, ${protein}g of protein, and ${fat}g of fat has ${calories} calories.`;\n}','2023-10-24 21:48:59','2023-10-24 21:48:59'),(35,'{\n \"function_description\": \"Calculates the Body Mass Index (BMI) for a given weight and height.\",\n \"parameters\": {\n \"weight\": {\n \"description\": \"The weight in kilograms.\",\n \"type\": \"number\"\n },\n \"height\": {\n \"description\": \"The height in meters.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { weight, height } = params;\n const bmi = weight / (height * height);\n return `For a weight of ${weight}kg and a height of ${height}m, the Body Mass Index (BMI) is ${bmi.toFixed(2)}.`;\n}','2023-10-24 21:49:32','2023-10-24 21:49:32'),(36,'{\n \"function_description\": \"Calculates the estimated point per game (PER) for a given basketball player.\",\n \"parameters\": {\n \"points_per_game\": {\n \"description\": \"The number of points scored by the basketball player on average per game.\",\n \"type\": \"number\"\n },\n \"assists_per_game\": {\n \"description\": \"The number of assists made by the basketball player on average per game.\",\n \"type\": \"number\"\n },\n \"rebounds_per_game\": {\n \"description\": \"The number of rebounds made by the basketball player on average per game.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { points_per_game, assists_per_game, rebounds_per_game } = params;\n const estimated_PER = (points_per_game + assists_per_game + rebounds_per_game) / 3;\n return `The estimated point per game (PER) for a basketball player who scores ${points_per_game} points, makes ${assists_per_game} assists, and ${rebounds_per_game} rebounds per game on average is ${estimated_PER.toFixed(2)}.`;\n}','2023-10-24 21:50:00','2023-10-24 21:50:00'),(38,'{\n \"function_description\": \"This function calculates the height of a building based on its shadow length and angle of elevation.\",\n \"parameters\": {\n \"shadow_length\": {\n \"description\": \"The length of the shadow in meters.\",\n \"type\": \"number\"\n },\n \"angle_of_elevation\": {\n \"description\": \"The angle of elevation in degrees.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { shadow_length, angle_of_elevation } = params;\n const building_height = Math.tan(angle_of_elevation * Math.PI / 180) * shadow_length;\n return `The height of the building with a shadow length of ${shadow_length} meters and an angle of elevation of ${angle_of_elevation} degrees is ${building_height} meters.`;\n}','2023-10-24 21:53:27','2023-10-24 21:53:27'),(39,'{\n \"function_description\": \"This function calculates the maximum allowable floor area based on the given plot area and FAR.\",\n \"parameters\": {\n \"plot_area\": {\n \"description\": \"The total size of the plot in square feet.\",\n \"type\": \"number\"\n },\n \"far\": {\n \"description\": \"The Floor Area Ratio (FAR) of the plot.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { plot_area, far } = params;\n const result = plot_area * far;\n return `The maximum allowable floor area for a plot size of ${plot_area} square feet with a FAR of ${far} is ${result} square feet.`;\n}','2023-10-24 21:55:55','2023-10-24 21:55:55'),(41,'{\n \"function_description\": \"This function retrieves the current time.\",\n \"parameters\": {}\n}','function executeFunction(params) {\n const current_time = new Date();\n return `The current time is ${current_time}.`;\n}','2023-10-24 21:59:43','2023-10-24 21:59:43'),(42,'{\n \"function_description\": \"This function compares two numbers and returns the larger one.\",\n \"parameters\": {\n \"num1\": {\n \"description\": \"The first number to compare.\",\n \"type\": \"number\"\n },\n \"num2\": {\n \"description\": \"The second number to compare.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { num1, num2 } = params;\n let result;\n if (num1 > num2) {\n result = num1;\n } else {\n result = num2;\n }\n return `The larger number between ${num1} and ${num2} is ${result}.`;\n}','2023-10-24 22:00:38','2023-10-24 22:00:38'),(43,'{\n \"function_description\": \"Calculates the quotient of two numbers.\",\n \"parameters\": {\n \"dividend\": {\n \"description\": \"The dividend number.\",\n \"type\": \"number\"\n },\n \"divisor\": {\n \"description\": \"The divisor number.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { dividend, divisor } = params;\n const result = dividend / divisor;\n return `The quotient of ${dividend} divided by ${divisor} is ${result}.`;\n}','2023-10-25 16:25:52','2023-10-25 16:25:52'),(44,'{\n \"function_description\": \"This function divides two numbers and returns the result.\",\n \"parameters\": {\n \"dividend\": {\n \"description\": \"The dividend number to be divided.\",\n \"type\": \"number\"\n },\n \"divisor\": {\n \"description\": \"The divisor number to divide the dividend.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { dividend, divisor } = params;\n if (divisor === 0) {\n return \"Error: Division by zero is undefined.\";\n }\n const result = dividend / divisor;\n return `The result of dividing ${dividend} by ${divisor} is ${result}.`;\n}','2023-10-25 16:30:15','2023-10-25 16:30:15'),(45,'{\n \"function_description\": \"Calculates a number raised to a given exponent.\",\n \"parameters\": {\n \"base\": {\n \"description\": \"The base of the calculation.\",\n \"type\": \"number\"\n },\n \"exponent\": {\n \"description\": \"The exponent for which to raise the number.\",\n \"type\": \"number\"\n }\n }\n}','function executeFunction(params) {\n const { base, exponent } = params;\n const result = Math.pow(base, exponent);\n return `The result of ${base} raised to the power of ${exponent} is ${result}.`;\n}','2023-10-25 20:39:17','2023-10-25 20:39:17'); 115 | /*!40000 ALTER TABLE `dynamic_functions` ENABLE KEYS */; 116 | UNLOCK TABLES; 117 | 118 | -- 119 | -- Table structure for table `pinned_embeddings` 120 | -- 121 | 122 | DROP TABLE IF EXISTS `pinned_embeddings`; 123 | /*!40101 SET @saved_cs_client = @@character_set_client */; 124 | /*!40101 SET character_set_client = utf8 */; 125 | CREATE TABLE `pinned_embeddings` ( 126 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 127 | `pinned_to` text COLLATE utf8mb4_unicode_ci NOT NULL, 128 | `pinned_string` text COLLATE utf8mb4_unicode_ci NOT NULL, 129 | `pinned_type` text COLLATE utf8mb4_unicode_ci NOT NULL, 130 | `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 131 | `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 132 | PRIMARY KEY (`id`) 133 | ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 134 | /*!40101 SET character_set_client = @saved_cs_client */; 135 | 136 | -- 137 | -- Dumping data for table `pinned_embeddings` 138 | -- 139 | 140 | LOCK TABLES `pinned_embeddings` WRITE; 141 | /*!40000 ALTER TABLE `pinned_embeddings` DISABLE KEYS */; 142 | INSERT INTO `pinned_embeddings` VALUES (3,'image_generator_0','This function generates an image of a specific object.','chat_ability_function','2023-10-24 05:27:00','2023-10-24 05:27:00'),(4,'llama_v2_code_instruct_7b','System Administration: Management and maintenance of computer systems.','skill_knowledge_domain','2023-10-24 05:27:44','2023-10-24 05:27:44'),(6,'music_generator_0','This function generates dramatic entrance music for theater performances.','chat_ability_function','2023-11-08 21:57:22','2023-11-08 21:57:22'),(7,'music_generator_0','This function generates dramatic entrance music for theater performances.','chat_ability_function','2023-11-09 01:53:02','2023-11-09 01:53:02'); 143 | /*!40000 ALTER TABLE `pinned_embeddings` ENABLE KEYS */; 144 | UNLOCK TABLES; 145 | 146 | -- 147 | -- Table structure for table `spellbook_module` 148 | -- 149 | 150 | DROP TABLE IF EXISTS `spellbook_module`; 151 | /*!40101 SET @saved_cs_client = @@character_set_client */; 152 | /*!40101 SET character_set_client = utf8 */; 153 | CREATE TABLE `spellbook_module` ( 154 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 155 | `unique_key` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, 156 | `current_version` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 157 | `status` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, 158 | `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 159 | `created_at` datetime NOT NULL, 160 | PRIMARY KEY (`id`) 161 | ) ENGINE=InnoDB AUTO_INCREMENT=68 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 162 | /*!40101 SET character_set_client = @saved_cs_client */; 163 | 164 | -- 165 | -- Dumping data for table `spellbook_module` 166 | -- 167 | 168 | LOCK TABLES `spellbook_module` WRITE; 169 | /*!40000 ALTER TABLE `spellbook_module` DISABLE KEYS */; 170 | INSERT INTO `spellbook_module` VALUES (51,'app_image_generator','1.0.0','installed','2023-09-22 22:39:37','2023-09-22 21:17:46'),(52,'spellbook_core','1.0.0','installed','2023-09-22 21:17:46','2023-09-22 21:17:46'),(53,'spellbook_prompt','1.0.0','installed','2023-09-22 21:17:46','2023-09-22 21:17:46'),(54,'spellbook_chat_ability','1.0.0','available','2023-09-26 00:28:46','2023-09-22 21:17:46'),(55,'text_to_speech','1.0.0','available','2023-10-28 17:53:59','2023-09-22 21:17:46'),(56,'music_generator','1.0.0','available','2023-11-10 21:11:28','2023-09-22 21:17:48'),(57,'magento2_module_maker','1.0.0','available','2023-09-25 20:08:24','2023-09-22 21:17:48'),(59,'news_search','1.0.0','available','2023-11-10 21:11:17','2023-09-22 21:17:48'),(60,'current_weather','1.0.0','available','2023-11-10 21:11:19','2023-09-22 21:17:48'),(61,'language_translator','1.0.0','available','2023-10-28 17:53:52','2023-09-25 19:53:00'),(62,'apps_skill_builder','1.0.0','installed','2023-10-04 21:50:58','2023-09-26 06:25:47'),(63,'apps_chat_ability_builder','1.0.0','installed','2023-10-06 20:29:51','2023-09-26 06:25:47'),(64,'ftp_transfer','1.0.0','available','2023-10-28 17:54:53','2023-09-28 19:00:35'),(65,'telynx_sms','1.0.0','available','2023-10-28 17:53:56','2023-09-28 22:04:44'),(66,'image_analyzer','1.0.0','available','2023-10-28 17:55:02','2023-10-04 09:06:32'),(67,'wizards_wand','1.0.0','available','2023-11-10 21:11:21','2023-10-23 06:26:48'),(68,'app_sound_studio','1.0.0','installed','2023-09-22 22:39:37','2023-09-22 21:17:46'),(69,'app_library','1.0.0','installed','2023-09-22 22:39:37','2023-09-22 21:17:46'),(70,'app_llm_explorer','1.0.0','installed','2023-09-22 22:39:37','2023-09-22 21:17:46'),(71,'spellbook_digital_ally','1.0.0','installed','2023-09-22 22:39:37','2023-09-22 21:17:46'); 171 | /*!40000 ALTER TABLE `spellbook_module` ENABLE KEYS */; 172 | UNLOCK TABLES; 173 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 174 | 175 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 176 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 177 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 178 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 179 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 180 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 181 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 182 | 183 | -- Dump completed on 2023-11-10 14:14:47 184 | --------------------------------------------------------------------------------