mirror of
https://github.com/deepset-ai/haystack.git
synced 2026-01-06 12:07:04 +00:00
Deploy demo (#1837)
* Add GH Actions workflow for demo deployment * update demo ec2 instance type * remove redundant docker-compose build * add custom demo command and env vars * deploy demo on updates to workflow resources
This commit is contained in:
parent
bec14b63c3
commit
4f6dc36869
40
.github/workflows/demo.yaml
vendored
Normal file
40
.github/workflows/demo.yaml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
name: Demo
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- ".github/workflows/demo**"
|
||||
|
||||
env:
|
||||
AWS_REGION: eu-west-1
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: AWS Authentication
|
||||
uses: aws-actions/configure-aws-credentials@master
|
||||
with:
|
||||
aws-region: ${{ env.AWS_REGION }}
|
||||
role-to-assume: ${{ secrets.DEMO_AWS_DEPLOY_ROLE }}
|
||||
|
||||
- name: Deploy demo
|
||||
env:
|
||||
CF_KEY_NAME: ${{ secrets.DEMO_CF_KEY_NAME }}
|
||||
CF_IMAGE_ID: ${{ secrets.DEMO_CF_IMAGE_ID }}
|
||||
CF_IAM_INSTANCE_PROFILE: ${{ secrets.DEMO_CF_IAM_INSTANCE_PROFILE }}
|
||||
run: |
|
||||
aws cloudformation deploy \
|
||||
--template-file .github/workflows/demo/ec2-autoscaling-group.yaml \
|
||||
--stack-name haystack-demo-production-instance \
|
||||
--parameter-overrides CommitShortSHA=${{ github.sha }} KeyName=${CF_KEY_NAME} ImageId=${CF_IMAGE_ID} IamInstanceProfile=${CF_IAM_INSTANCE_PROFILE} \
|
||||
--capabilities CAPABILITY_IAM
|
||||
16
.github/workflows/demo/docker-compose.demo.yml
vendored
Normal file
16
.github/workflows/demo/docker-compose.demo.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
version: "3"
|
||||
services:
|
||||
haystack-api:
|
||||
restart: always
|
||||
environment:
|
||||
CONCURRENT_REQUEST_PER_WORKER: 16
|
||||
command: "/bin/bash -c 'sleep 10 && gunicorn rest_api.application:app -b 0.0.0.0 -k uvicorn.workers.UvicornWorker --workers 3 --timeout 180'"
|
||||
|
||||
elasticsearch:
|
||||
restart: always
|
||||
ui:
|
||||
restart: always
|
||||
environment:
|
||||
DEFAULT_DOCS_FROM_RETRIEVER: 7
|
||||
DEFAULT_NUMBER_OF_ANSWERS: 5
|
||||
DISABLE_FILE_UPLOAD: 1
|
||||
158
.github/workflows/demo/ec2-autoscaling-group.yaml
vendored
Normal file
158
.github/workflows/demo/ec2-autoscaling-group.yaml
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/awslabs/goformation/v5.2.11/schema/cloudformation.schema.json
|
||||
|
||||
|
||||
Parameters:
|
||||
Project:
|
||||
Description: A project name that is used for resource names
|
||||
Type: String
|
||||
Default: haystack-demo
|
||||
|
||||
Environment:
|
||||
Description: An environment name that is suffixed to resource names
|
||||
Type: String
|
||||
Default: production
|
||||
|
||||
VPCStack:
|
||||
Description: VPC stack name
|
||||
Type: String
|
||||
Default: haystack-demo-production-vpc
|
||||
|
||||
CommitShortSHA:
|
||||
Description: Commit short reference that triggered this deployment
|
||||
Type: String
|
||||
|
||||
InstanceType:
|
||||
Description: EC2 instance type
|
||||
Type: String
|
||||
Default: p3.2xlarge
|
||||
|
||||
ImageId:
|
||||
Description: AMI to use for the EC2 instance
|
||||
Type: String
|
||||
|
||||
IamInstanceProfile:
|
||||
Description: IAM instance profile to attach to the EC2 instance
|
||||
Type: String
|
||||
|
||||
KeyName:
|
||||
Description: EC2 key pair to add to the EC2 instance
|
||||
Type: String
|
||||
|
||||
Resources:
|
||||
AutoScalingGroup:
|
||||
Type: AWS::AutoScaling::AutoScalingGroup
|
||||
CreationPolicy:
|
||||
ResourceSignal:
|
||||
Count: "1"
|
||||
Timeout: PT45M
|
||||
UpdatePolicy:
|
||||
AutoScalingRollingUpdate:
|
||||
MinInstancesInService: "1"
|
||||
MaxBatchSize: "1"
|
||||
PauseTime: PT45M
|
||||
WaitOnResourceSignals: true
|
||||
SuspendProcesses:
|
||||
- HealthCheck
|
||||
- ReplaceUnhealthy
|
||||
- AZRebalance
|
||||
- AlarmNotification
|
||||
- ScheduledActions
|
||||
Properties:
|
||||
LaunchConfigurationName: !Ref InstanceConfiguration
|
||||
VPCZoneIdentifier:
|
||||
- !ImportValue
|
||||
"Fn::Sub": "${VPCStack}-PublicSubnet1"
|
||||
- !ImportValue
|
||||
"Fn::Sub": "${VPCStack}-PublicSubnet2"
|
||||
MaxSize: "2"
|
||||
DesiredCapacity: "1"
|
||||
MinSize: "1"
|
||||
TargetGroupARNs:
|
||||
- !ImportValue
|
||||
"Fn::Sub": "${VPCStack}-DefaultTargetGroup"
|
||||
Tags:
|
||||
- Key: Name
|
||||
Value: !Sub ${Project}-${Environment}
|
||||
PropagateAtLaunch: true
|
||||
- Key: Environment
|
||||
Value: !Ref Project
|
||||
PropagateAtLaunch: true
|
||||
- Key: Project
|
||||
Value: !Ref Environment
|
||||
PropagateAtLaunch: true
|
||||
- Key: CommitShortSHA
|
||||
Value: !Ref CommitShortSHA
|
||||
PropagateAtLaunch: true
|
||||
|
||||
InstanceConfiguration:
|
||||
Type: AWS::AutoScaling::LaunchConfiguration
|
||||
Properties:
|
||||
LaunchConfigurationName: !Sub ${Project}-${Environment}-${CommitShortSHA}
|
||||
InstanceType: !Ref InstanceType
|
||||
ImageId: !Ref ImageId
|
||||
IamInstanceProfile: !Ref IamInstanceProfile
|
||||
KeyName: !Ref KeyName
|
||||
AssociatePublicIpAddress: true
|
||||
SecurityGroups:
|
||||
- !ImportValue
|
||||
"Fn::Sub": "${VPCStack}-InstanceSecurityGroup"
|
||||
EbsOptimized: true
|
||||
BlockDeviceMappings:
|
||||
- DeviceName: /dev/sda1
|
||||
Ebs:
|
||||
VolumeSize: 200
|
||||
|
||||
UserData:
|
||||
Fn::Base64: !Sub |
|
||||
#!/bin/bash -ex
|
||||
mkdir -p /opt/aws/bin
|
||||
wget https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz
|
||||
python3 -m easy_install --script-dir /opt/aws/bin aws-cfn-bootstrap-py3-latest.tar.gz
|
||||
|
||||
trap '/opt/aws/bin/cfn-signal --exit-code 1 --stack ${AWS::StackId} --resource AutoScalingGroup --region ${AWS::Region}' ERR
|
||||
|
||||
echo "Deploying Haystack demo, commit ${CommitShortSHA}"
|
||||
|
||||
echo 'APT::Periodic::Update-Package-Lists "0";
|
||||
APT::Periodic::Unattended-Upgrade "0";' > /etc/apt/apt.conf.d/20auto-upgrades
|
||||
|
||||
apt update
|
||||
apt install -y curl git ca-certificates curl gnupg lsb-release
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
|
||||
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
apt update
|
||||
apt install -y docker-ce docker-ce-cli containerd.io
|
||||
|
||||
# Install Docker compose
|
||||
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/bin/docker-compose
|
||||
chmod +x /usr/bin/docker-compose
|
||||
|
||||
# Install Nvidia container runtime
|
||||
curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | \
|
||||
apt-key add -
|
||||
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
|
||||
curl -s -L https://nvidia.github.io/nvidia-container-runtime/$distribution/nvidia-container-runtime.list | \
|
||||
tee /etc/apt/sources.list.d/nvidia-container-runtime.list
|
||||
apt-get update
|
||||
apt-get install -y nvidia-container-runtime
|
||||
|
||||
# Setup and start Docker
|
||||
groupadd docker || true
|
||||
usermod -aG docker $USER || true
|
||||
newgrp docker || true
|
||||
systemctl unmask docker
|
||||
systemctl restart docker
|
||||
|
||||
# Exposes the GPUs to Docker
|
||||
docker run --rm --gpus all ubuntu nvidia-smi
|
||||
|
||||
# Clone and start Haystack
|
||||
git clone --branch deploy-demo https://github.com/askainet/haystack.git /opt/haystack
|
||||
cd /opt/haystack
|
||||
export COMPOSE_FILE=docker-compose-gpu.yml:.github/workflows/demo/docker-compose.demo.yml
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
|
||||
/opt/aws/bin/cfn-signal --exit-code $? --stack ${AWS::StackId} --resource AutoScalingGroup --region ${AWS::Region}
|
||||
@ -32,7 +32,7 @@ services:
|
||||
elasticsearch:
|
||||
# This will start an empty elasticsearch instance (so you have to add your documents yourself)
|
||||
#image: "elasticsearch:7.9.2"
|
||||
# If you want a demo image instead that is "ready-to-query" with some indexed articles
|
||||
# If you want a demo image instead that is "ready-to-query" with some indexed articles
|
||||
# about countries and capital cities from Wikipedia:
|
||||
image: "deepset/elasticsearch-countries-and-capitals"
|
||||
ports:
|
||||
|
||||
@ -22,7 +22,7 @@ services:
|
||||
elasticsearch:
|
||||
# This will start an empty elasticsearch instance (so you have to add your documents yourself)
|
||||
#image: "elasticsearch:7.9.2"
|
||||
# If you want a demo image instead that is "ready-to-query" with some indexed articles
|
||||
# If you want a demo image instead that is "ready-to-query" with some indexed articles
|
||||
# about countries and capital cities from Wikipedia:
|
||||
image: "deepset/elasticsearch-countries-and-capitals"
|
||||
ports:
|
||||
|
||||
34
ui/webapp.py
34
ui/webapp.py
@ -36,7 +36,7 @@ def main():
|
||||
|
||||
# Persistent state
|
||||
state = SessionState.get(
|
||||
random_question=DEFAULT_QUESTION_AT_STARTUP,
|
||||
random_question=DEFAULT_QUESTION_AT_STARTUP,
|
||||
random_answer="",
|
||||
last_question=DEFAULT_QUESTION_AT_STARTUP,
|
||||
results=None,
|
||||
@ -51,7 +51,7 @@ def main():
|
||||
# Title
|
||||
st.write("# Haystack Demo - Explore the world")
|
||||
st.markdown("""
|
||||
This demo takes its data from a selection of Wikipedia pages crawled in November 2021 on the topic of
|
||||
This demo takes its data from a selection of Wikipedia pages crawled in November 2021 on the topic of
|
||||
|
||||
<h3 style='text-align:center;padding: 0 0 1rem;'>Countries and capital cities</h3>
|
||||
|
||||
@ -63,18 +63,18 @@ Ask any question on this topic and see if Haystack can find the correct answer t
|
||||
# Sidebar
|
||||
st.sidebar.header("Options")
|
||||
top_k_reader = st.sidebar.slider(
|
||||
"Max. number of answers",
|
||||
min_value=1,
|
||||
max_value=10,
|
||||
value=DEFAULT_NUMBER_OF_ANSWERS,
|
||||
step=1,
|
||||
"Max. number of answers",
|
||||
min_value=1,
|
||||
max_value=10,
|
||||
value=DEFAULT_NUMBER_OF_ANSWERS,
|
||||
step=1,
|
||||
on_change=reset_results)
|
||||
top_k_retriever = st.sidebar.slider(
|
||||
"Max. number of documents from retriever",
|
||||
min_value=1,
|
||||
max_value=10,
|
||||
value=DEFAULT_DOCS_FROM_RETRIEVER,
|
||||
step=1,
|
||||
"Max. number of documents from retriever",
|
||||
min_value=1,
|
||||
max_value=10,
|
||||
value=DEFAULT_DOCS_FROM_RETRIEVER,
|
||||
step=1,
|
||||
on_change=reset_results)
|
||||
eval_mode = st.sidebar.checkbox("Evaluation mode")
|
||||
debug = st.sidebar.checkbox("Show debug info")
|
||||
@ -107,7 +107,7 @@ Ask any question on this topic and see if Haystack can find the correct answer t
|
||||
text-align: center;
|
||||
}}
|
||||
.haystack-footer h4 {{
|
||||
margin: 0.1rem;
|
||||
margin: 0.1rem;
|
||||
padding:0;
|
||||
}}
|
||||
footer {{
|
||||
@ -132,7 +132,7 @@ Ask any question on this topic and see if Haystack can find the correct answer t
|
||||
# Search bar
|
||||
question = st.text_input("",
|
||||
value=state.random_question,
|
||||
max_chars=100,
|
||||
max_chars=100,
|
||||
on_change=reset_results
|
||||
)
|
||||
col1, col2 = st.columns(2)
|
||||
@ -147,7 +147,7 @@ Ask any question on this topic and see if Haystack can find the correct answer t
|
||||
#state.get_next_question = col2.button("Random question")
|
||||
if col2.button("Random question"):
|
||||
reset_results()
|
||||
new_row = df.sample(1)
|
||||
new_row = df.sample(1)
|
||||
while new_row["Question Text"].values[0] == state.random_question: # Avoid picking the same question twice (the change is not visible on the UI)
|
||||
new_row = df.sample(1)
|
||||
state.random_question = new_row["Question Text"].values[0]
|
||||
@ -200,7 +200,7 @@ Ask any question on this topic and see if Haystack can find the correct answer t
|
||||
answer, context = result["answer"], result["context"]
|
||||
start_idx = context.find(answer)
|
||||
end_idx = start_idx + len(answer)
|
||||
# Hack due to this bug: https://github.com/streamlit/streamlit/issues/3190
|
||||
# Hack due to this bug: https://github.com/streamlit/streamlit/issues/3190
|
||||
st.write(markdown(context[:start_idx] + str(annotation(answer, "ANSWER", "#8ef")) + context[end_idx:]), unsafe_allow_html=True)
|
||||
source = ""
|
||||
url, title = get_backlink(result)
|
||||
@ -213,7 +213,7 @@ Ask any question on this topic and see if Haystack can find the correct answer t
|
||||
else:
|
||||
st.info("🤔 Haystack is unsure whether any of the documents contain an answer to your question. Try to reformulate it!")
|
||||
st.write("**Relevance:** ", result["relevance"])
|
||||
|
||||
|
||||
if eval_mode and result["answer"]:
|
||||
# Define columns for buttons
|
||||
is_correct_answer = None
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user