Skip to content

Commit

Permalink
Merge pull request #132 from alan-turing-institute/pulumi
Browse files Browse the repository at this point in the history
Add pulumi set up for api bot
  • Loading branch information
rchan26 authored Nov 2, 2023
2 parents 04ab741 + 9ac3633 commit d7d37fb
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 67 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,6 @@ cython_debug/
*.swp

# Pulumi
azure/.secrets
azure/Pulumi.production.yaml
azure/*/.secrets
azure/*/Pulumi.*.yaml
data/llama_index_indices/all_data/
File renamed without changes.
89 changes: 89 additions & 0 deletions azure/api_bot/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import pulumi
from pulumi_azure_native import containerinstance, network, resources, storage

# Get some configuration variables
stack_name = pulumi.get_stack()
config = pulumi.Config()


# Create an resource group
resource_group = resources.ResourceGroup(
"resource_group", resource_group_name=f"rg-reginald-{stack_name}-deployment"
)

# Create a network security group
network_security_group = network.NetworkSecurityGroup(
"network_security_group",
network_security_group_name=f"nsg-reginald-{stack_name}-containers",
resource_group_name=resource_group.name,
)

# Create a virtual network and subnet
virtual_network = network.VirtualNetwork(
"virtual_network",
address_space=network.AddressSpaceArgs(
address_prefixes=["10.0.0.0/29"],
),
resource_group_name=resource_group.name,
# Define subnets inline to avoid creation/deletion issues
subnets=[
# Container subnet
network.SubnetArgs(
address_prefix="10.0.0.0/29",
delegations=[
network.DelegationArgs(
name="SubnetDelegationContainerGroups",
service_name="Microsoft.ContainerInstance/containerGroups",
type="Microsoft.Network/virtualNetworks/subnets/delegations",
),
],
name="ContainersSubnet",
network_security_group=network.NetworkSecurityGroupArgs(
id=network_security_group.id
),
),
],
virtual_network_name=f"vnet-reginald-{stack_name}",
virtual_network_peerings=[],
)

# Define the container group
container_group = containerinstance.ContainerGroup(
"container_group",
container_group_name=f"aci-reginald-{stack_name}",
containers=[
containerinstance.ContainerArgs(
image="ghcr.io/alan-turing-institute/reginald_slackbot:main",
name="reginald-llama-cpp", # maximum of 63 characters
environment_variables=[
containerinstance.EnvironmentVariableArgs(
name="REGINALD_MODEL",
value="llama-index-llama-cpp",
),
containerinstance.EnvironmentVariableArgs(
name="SLACK_APP_TOKEN",
secure_value=config.get_secret("LLAMA_CPP_SLACK_APP_TOKEN"),
),
containerinstance.EnvironmentVariableArgs(
name="SLACK_BOT_TOKEN",
secure_value=config.get_secret("LLAMA_CPP_SLACK_BOT_TOKEN"),
),
containerinstance.EnvironmentVariableArgs(
name="REGINALD_API_URL",
secure_value=config.get_secret("REGINALD_API_URL"),
),
],
ports=[],
resources=containerinstance.ResourceRequirementsArgs(
requests=containerinstance.ResourceRequestsArgs(
cpu=1,
memory_in_gb=4,
),
),
),
],
os_type=containerinstance.OperatingSystemTypes.LINUX,
resource_group_name=resource_group.name,
restart_policy=containerinstance.ContainerGroupRestartPolicy.ALWAYS,
sku=containerinstance.ContainerGroupSku.STANDARD,
)
79 changes: 79 additions & 0 deletions azure/api_bot/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#! /usr/bin/env bash

# Arguments
SUBSCRIPTION_NAME=${1:-"Reg Hack Week 2023: Reginald"}
STACK_NAME=${2:-"llama-cpp-api"}

# Fixed values
CONTAINER_NAME="pulumi"
ENCRYPTION_KEY_NAME="pulumi-encryption-key"
KEYVAULT_NAME=$(echo "kv-reginald-${STACK_NAME}" | head -c 24)
LOCATION="uksouth"
RESOURCE_GROUP_NAME="rg-reginald-${STACK_NAME}-backend"

# Ensure that the user is logged in
if ! (az account show > /dev/null); then
az login
fi

# Switch subscription
echo "Creating Pulumi backend resources in '$SUBSCRIPTION_NAME'..."
az account set --subscription "$SUBSCRIPTION_NAME" --only-show-errors > /dev/null || exit 1

# Set up a resource group
az group create --location "$LOCATION" --name "$RESOURCE_GROUP_NAME" --only-show-errors > /dev/null || exit 2
echo "✅ Resource group '$RESOURCE_GROUP_NAME'"

# Create keyvault and encryption key
if ! (az keyvault show --name "$KEYVAULT_NAME" --resource-group "$RESOURCE_GROUP_NAME" --only-show-errors > /dev/null 2>&1); then
az keyvault create --location "$LOCATION" --name "$KEYVAULT_NAME" --resource-group "$RESOURCE_GROUP_NAME" --only-show-errors > /dev/null || exit 5
fi
echo "✅ Keyvault '$KEYVAULT_NAME'"
if ! (az keyvault key show --name "$ENCRYPTION_KEY_NAME" --vault-name "$KEYVAULT_NAME" --only-show-errors > /dev/null 2>&1); then
az keyvault key create --name "$ENCRYPTION_KEY_NAME" --vault-name "$KEYVAULT_NAME" --only-show-errors > /dev/null || exit 6
fi
echo "✅ Encryption key '$ENCRYPTION_KEY_NAME'"

# Check whether this user has access to the storage account
echo "Checking whether this user has appropriate permissions..."
USER_ID=$(az ad signed-in-user show --query "id" | xargs)
if [ "$(az role assignment list --include-inherited --assignee "$USER_ID" --role "Storage Blob Data Contributor")" ]; then
echo "✅ User has 'Storage Blob Data Contributor' permissions on this subscription"
else
echo "You will need 'Storage Blob Data Contributor' access to this subscription in order to continue"
return 0
fi
az keyvault set-policy --name "$KEYVAULT_NAME" --object-id "$USER_ID" --secret-permissions "all" --key-permissions "all" --certificate-permissions "all" --only-show-errors > /dev/null || exit 7
echo "✅ User has read permissions on '$KEYVAULT_NAME'"

# Select the correct stack
if ! (pulumi stack select "$STACK_NAME" > /dev/null); then
echo "Creating new Pulumi stack..."
pulumi stack init "$STACK_NAME" --secrets-provider "azurekeyvault://$KEYVAULT_NAME.vault.azure.net/keys/$ENCRYPTION_KEY_NAME"
fi
echo "✅ Switched to Pulumi stack '$STACK_NAME'"
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi stack change-secrets-provider "azurekeyvault://$KEYVAULT_NAME.vault.azure.net/keys/$ENCRYPTION_KEY_NAME"
echo "✅ Using Azure KeyVault '$KEYVAULT_NAME' for encryption"

# Configure the azure-native plugin
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set azure-native:tenantId "$(az account list --all --query "[?isDefault].tenantId | [0]" --output tsv)"
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set azure-native:subscriptionId "$(az account list --all --query "[?isDefault].id | [0]" --output tsv)"
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set azure-native:location "$LOCATION"
echo "✅ Configured azure-native defaults"

# Set app secrets
LLAMA_CPP_SLACK_APP_TOKEN=""
LLAMA_CPP_SLACK_BOT_TOKEN=""
if [ -e ../.pulumi_env ]; then
LLAMA_CPP_SLACK_APP_TOKEN=$(grep "LLAMA_CPP_SLACK_APP_TOKEN" ../.pulumi_env | grep -v "^#" | cut -d '"' -f 2)
LLAMA_CPP_SLACK_BOT_TOKEN=$(grep "LLAMA_CPP_SLACK_BOT_TOKEN" ../.pulumi_env | grep -v "^#" | cut -d '"' -f 2)
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret LLAMA_CPP_SLACK_APP_TOKEN "$LLAMA_CPP_SLACK_APP_TOKEN"
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret LLAMA_CPP_SLACK_BOT_TOKEN "$LLAMA_CPP_SLACK_BOT_TOKEN"

# Set API url
REGINALD_API_URL=""
if [ -e ../.pulumi_env ]; then
REGINALD_API_URL=$(grep "REGINALD_API_URL" ../.pulumi_env | grep -v "^#" | cut -d '"' -f 2)
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set REGINALD_API_URL "$REGINALD_API_URL"
4 changes: 4 additions & 0 deletions azure/hack_week/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: reginald
runtime:
name: python
description: Slack bot to respond to REG queries
12 changes: 6 additions & 6 deletions azure/__main__.py → azure/hack_week/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
container_group_name=f"aci-reginald-{stack_name}",
containers=[
containerinstance.ContainerArgs(
image="ghcr.io/alan-turing-institute/reginald:main",
image="ghcr.io/alan-turing-institute/reginald_reginald:main",
name="reginald-handbook", # maximum of 63 characters
environment_variables=[
containerinstance.EnvironmentVariableArgs(
Expand Down Expand Up @@ -123,8 +123,8 @@
),
),
containerinstance.ContainerArgs(
image="ghcr.io/alan-turing-institute/reginald:main",
name="reginald-llama", # maximum of 63 characters
image="ghcr.io/alan-turing-institute/reginald_reginald:main",
name="reginald-gpt-azure", # maximum of 63 characters
environment_variables=[
containerinstance.EnvironmentVariableArgs(
name="OPENAI_AZURE_API_BASE",
Expand All @@ -140,15 +140,15 @@
),
containerinstance.EnvironmentVariableArgs(
name="REGINALD_MODEL",
value="llama-gpt-3.5-turbo-azure",
value="llama-index-gpt-azure",
),
containerinstance.EnvironmentVariableArgs(
name="SLACK_APP_TOKEN",
secure_value=config.get_secret("LLAMA_SLACK_APP_TOKEN"),
secure_value=config.get_secret("GPT_AZURE_SLACK_APP_TOKEN"),
),
containerinstance.EnvironmentVariableArgs(
name="SLACK_BOT_TOKEN",
secure_value=config.get_secret("LLAMA_SLACK_BOT_TOKEN"),
secure_value=config.get_secret("GPT_AZURE_SLACK_BOT_TOKEN"),
),
],
ports=[],
Expand Down
95 changes: 42 additions & 53 deletions azure/setup.sh → azure/hack_week/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ STACK_NAME=${2:-"production"}
# Fixed values
CONTAINER_NAME="pulumi"
ENCRYPTION_KEY_NAME="pulumi-encryption-key"
ENCRYPTION_KEY_VERSION="6c74c12825c84362af45973e3e8b38ce"
KEYVAULT_NAME=$(echo "kv-reginald-${STACK_NAME}" | head -c 24)
LOCATION="uksouth"
RESOURCE_GROUP_NAME="rg-reginald-${STACK_NAME}-backend"
Expand Down Expand Up @@ -36,7 +37,7 @@ if ! (az keyvault show --name "$KEYVAULT_NAME" --resource-group "$RESOURCE_GROUP
az keyvault create --location "$LOCATION" --name "$KEYVAULT_NAME" --resource-group "$RESOURCE_GROUP_NAME" --only-show-errors > /dev/null || exit 5
fi
echo "✅ Keyvault '$KEYVAULT_NAME'"
if ! (az keyvault key show --name "$ENCRYPTION_KEY_NAME" --vault-name "$KEYVAULT_NAME" --only-show-errors > /dev/null 2>&1); then
if ! (az keyvault key show --name "$ENCRYPTION_KEY_NAME" --vault-name "$KEYVAULT_NAME" --version "$ENCRYPTION_KEY_VERSION" --only-show-errors > /dev/null 2>&1); then
az keyvault key create --name "$ENCRYPTION_KEY_NAME" --vault-name "$KEYVAULT_NAME" --only-show-errors > /dev/null || exit 6
fi
echo "✅ Encryption key '$ENCRYPTION_KEY_NAME'"
Expand All @@ -62,10 +63,10 @@ pulumi login "azblob://$CONTAINER_NAME?storage_account=$STORAGE_ACCOUNT_NAME"
# Select the correct stack
if ! (pulumi stack select "$STACK_NAME" > /dev/null); then
echo "Creating new Pulumi stack..."
pulumi stack init "$STACK_NAME" --secrets-provider "azurekeyvault://$KEYVAULT_NAME.vault.azure.net/keys/$ENCRYPTION_KEY_NAME"
pulumi stack init "$STACK_NAME" --secrets-provider "azurekeyvault://$KEYVAULT_NAME.vault.azure.net/keys/$ENCRYPTION_KEY_NAME/$ENCRYPTION_KEY_VERSION"
fi
echo "✅ Switched to Pulumi stack '$STACK_NAME'"
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi stack change-secrets-provider "azurekeyvault://$KEYVAULT_NAME.vault.azure.net/keys/$ENCRYPTION_KEY_NAME"
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi stack change-secrets-provider "azurekeyvault://$KEYVAULT_NAME.vault.azure.net/keys/$ENCRYPTION_KEY_NAME/$ENCRYPTION_KEY_VERSION"
echo "✅ Using Azure KeyVault '$KEYVAULT_NAME' for encryption"

# Configure the azure-native plugin
Expand All @@ -78,30 +79,21 @@ echo "✅ Configured azure-native defaults"
OPENAI_AZURE_API_BASE=""
OPENAI_AZURE_API_KEY=""
OPENAI_API_KEY=""
REGINALD_MODEL=""
HANDBOOK_SLACK_APP_TOKEN=""
HANDBOOK_SLACK_BOT_TOKEN=""
LLAMA_SLACK_APP_TOKEN=""
LLAMA_SLACK_BOT_TOKEN=""
if [ -e ../.env ]; then
OPENAI_AZURE_API_BASE=$(grep "OPENAI_AZURE_API_BASE" ../.env | grep -v "^#" | cut -d '"' -f 2)
OPENAI_AZURE_API_KEY=$(grep "OPENAI_AZURE_API_KEY" ../.env | grep -v "^#" | cut -d '"' -f 2)
OPENAI_API_KEY=$(grep "OPENAI_API_KEY" ../.env | grep -v "^#" | cut -d '"' -f 2)
REGINALD_MODEL=$(grep "REGINALD_MODEL" ../.env | grep -v "^#" | cut -d '"' -f 2)
HANDBOOK_SLACK_APP_TOKEN=$(grep "HANDBOOK_SLACK_APP_TOKEN" ../.env | grep -v "^#" | cut -d '"' -f 2)
HANDBOOK_SLACK_BOT_TOKEN=$(grep "HANDBOOK_SLACK_BOT_TOKEN" ../.env | grep -v "^#" | cut -d '"' -f 2)
LLAMA_SLACK_APP_TOKEN=$(grep "LLAMA_SLACK_APP_TOKEN" ../.env | grep -v "^#" | cut -d '"' -f 2)
LLAMA_SLACK_BOT_TOKEN=$(grep "LLAMA_SLACK_BOT_TOKEN" ../.env | grep -v "^#" | cut -d '"' -f 2)
GPT_AZURE_SLACK_APP_TOKEN=""
GPT_AZURE_SLACK_BOT_TOKEN=""
if [ -e ../.pulumi_env ]; then
OPENAI_AZURE_API_BASE=$(grep "OPENAI_AZURE_API_BASE" ../.pulumi_env | grep -v "^#" | cut -d '"' -f 2)
OPENAI_AZURE_API_KEY=$(grep "OPENAI_AZURE_API_KEY" ../.pulumi_env | grep -v "^#" | cut -d '"' -f 2)
OPENAI_API_KEY=$(grep "OPENAI_API_KEY" ../.pulumi_env | grep -v "^#" | cut -d '"' -f 2)
HANDBOOK_SLACK_APP_TOKEN=$(grep "HANDBOOK_SLACK_APP_TOKEN" ../.pulumi_env | grep -v "^#" | cut -d '"' -f 2)
HANDBOOK_SLACK_BOT_TOKEN=$(grep "HANDBOOK_SLACK_BOT_TOKEN" ../.pulumi_env | grep -v "^#" | cut -d '"' -f 2)
GPT_AZURE_SLACK_APP_TOKEN=$(grep "GPT_AZURE_SLACK_APP_TOKEN" ../.pulumi_env | grep -v "^#" | cut -d '"' -f 2)
GPT_AZURE_SLACK_BOT_TOKEN=$(grep "GPT_AZURE_SLACK_BOT_TOKEN" ../.pulumi_env | grep -v "^#" | cut -d '"' -f 2)
fi

# We always need a model name and Slack tokens
if [ -z "$REGINALD_MODEL" ]; then
echo "Please provide a REGINALD_MODEL:"
read -r REGINALD_MODEL
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set REGINALD_MODEL "$REGINALD_MODEL"

# Handbook
# ChatCompletionAzure (handbook) tokens
if [ -z "$HANDBOOK_SLACK_APP_TOKEN" ]; then
echo "Please provide a HANDBOOK_SLACK_APP_TOKEN:"
read -r HANDBOOK_SLACK_APP_TOKEN
Expand All @@ -113,37 +105,34 @@ if [ -z "$HANDBOOK_SLACK_BOT_TOKEN" ]; then
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret HANDBOOK_SLACK_BOT_TOKEN "$HANDBOOK_SLACK_BOT_TOKEN"

# Llama tokens
if [ -z "$LLAMA_SLACK_APP_TOKEN" ]; then
echo "Please provide a LLAMA_SLACK_APP_TOKEN:"
read -r LLAMA_SLACK_APP_TOKEN
# LlamaIndexGPTAzure tokens
if [ -z "$GPT_AZURE_SLACK_APP_TOKEN" ]; then
echo "Please provide a GPT_AZURE_SLACK_APP_TOKEN:"
read -r GPT_AZURE_SLACK_APP_TOKEN
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret LLAMA_SLACK_APP_TOKEN "$LLAMA_SLACK_APP_TOKEN"
if [ -z "$LLAMA_SLACK_BOT_TOKEN" ]; then
echo "Please provide a LLAMA_SLACK_BOT_TOKEN:"
read -r LLAMA_SLACK_BOT_TOKEN
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret LLAMA_SLACK_BOT_TOKEN "$LLAMA_SLACK_BOT_TOKEN"

# The ChatCompletionAzure and LlamaGPTAzure models need an Azure backend
if [[ $REGINALD_MODEL == *azure* ]]; then
if [ -z "$OPENAI_AZURE_API_BASE" ]; then
echo "Please provide a OPENAI_AZURE_API_BASE:"
read -r OPENAI_AZURE_API_BASE
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set OPENAI_AZURE_API_BASE "$OPENAI_AZURE_API_BASE"
if [ -z "$OPENAI_AZURE_API_KEY" ]; then
echo "Please provide a OPENAI_AZURE_API_KEY:"
read -r OPENAI_AZURE_API_KEY
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret OPENAI_AZURE_API_KEY "$OPENAI_AZURE_API_KEY"
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret GPT_AZURE_SLACK_APP_TOKEN "$GPT_AZURE_SLACK_APP_TOKEN"
if [ -z "$GPT_AZURE_SLACK_BOT_TOKEN" ]; then
echo "Please provide a GPT_AZURE_SLACK_BOT_TOKEN:"
read -r GPT_AZURE_SLACK_BOT_TOKEN
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret GPT_AZURE_SLACK_BOT_TOKEN "$GPT_AZURE_SLACK_BOT_TOKEN"

# The ChatCompletionOpenAI and LlamaGPTOpenAI models need an OpenAI key
if [[ $REGINALD_MODEL == *openai* ]]; then
if [ -z "$OPENAI_API_KEY" ]; then
echo "Please provide a OPENAI_API_KEY:"
read -r OPENAI_API_KEY
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret OPENAI_API_KEY "$OPENAI_API_KEY"
# The ChatCompletionAzure and LlamaIndexGPTAzure models need an Azure backend
if [ -z "$OPENAI_AZURE_API_BASE" ]; then
echo "Please provide a OPENAI_AZURE_API_BASE:"
read -r OPENAI_AZURE_API_BASE
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set OPENAI_AZURE_API_BASE "$OPENAI_AZURE_API_BASE"
if [ -z "$OPENAI_AZURE_API_KEY" ]; then
echo "Please provide a OPENAI_AZURE_API_KEY:"
read -r OPENAI_AZURE_API_KEY
fi
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret OPENAI_AZURE_API_KEY "$OPENAI_AZURE_API_KEY"

# The ChatCompletionOpenAI and LlamaIndexGPTOpenAI models need an OpenAI key (not used currently)
# if [ -z "$OPENAI_API_KEY" ]; then
# echo "Please provide a OPENAI_API_KEY:"
# read -r OPENAI_API_KEY
# fi
# AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret OPENAI_API_KEY "$OPENAI_API_KEY"
AZURE_KEYVAULT_AUTH_VIA_CLI=true pulumi config set --secret OPENAI_API_KEY "$OPENAI_API_KEY"
4 changes: 1 addition & 3 deletions docker/reginald/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,4 @@ COPY pyproject.toml .
COPY README.md .
RUN poetry install --all-extras

# Set entrypoint
ENTRYPOINT ["poetry"]
CMD ["run", "python", "reginald_run"]
CMD ["poetry", "run", "reginald_run"]
4 changes: 1 addition & 3 deletions docker/slack_bot/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,4 @@ COPY pyproject.toml .
COPY README.md .
RUN poetry install --extras api_bot

# Set entrypoint
ENTRYPOINT ["poetry"]
CMD ["run", "python", "reginald_run_api_bot"]
CMD ["poetry", "run", "reginald_run_api_bot"]

0 comments on commit d7d37fb

Please sign in to comment.