diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 6be4d9d5..8d8e278a 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -21,6 +21,7 @@ Backend bgd bordershadow bugfix +california CarImage cd centric @@ -31,6 +32,7 @@ ChatOps Chris claimdb CLI +CLM cls CMD config @@ -51,6 +53,7 @@ diag dir diy DIY +dmv dotenv drawio ds @@ -60,6 +63,7 @@ dvh eCommerce elyra Elyra +Embeddings eng env EOF @@ -71,6 +75,8 @@ EXAMPLEs FastAPI ffdrf fi +flant +FlanT formatter fromarray frontend @@ -84,6 +90,7 @@ gitignore gitops GitOps Globex +GPUs Grafana Granafa Granger @@ -129,6 +136,8 @@ Lundberg LWBS mAP md +milvus +Milvus minio Minio MinIO @@ -239,6 +248,7 @@ un unopinionated url userX +vectordb venv vscode VSCode diff --git a/bootstrap/ic-rhoai-configuration/images-puller.yaml b/bootstrap/ic-rhoai-configuration/images-puller.yaml index a685ecf0..38d1fb86 100644 --- a/bootstrap/ic-rhoai-configuration/images-puller.yaml +++ b/bootstrap/ic-rhoai-configuration/images-puller.yaml @@ -57,7 +57,7 @@ spec: spec: containers: - name: oauth-proxy - image: registry.redhat.io/openshift4/ose-oauth-proxy@sha256:ab112105ac37352a2a4916a39d6736f5db6ab4c29bad4467de8d613e80e9bb33 + image: registry.redhat.io/openshift4/ose-oauth-proxy@sha256:4bef31eb993feb6f1096b51b4876c65a6fb1f4401fee97fa4f4542b6b7c9bc46 command: ["tail"] args: ["-f", "/dev/null"] resources: @@ -144,6 +144,16 @@ spec: requests: cpu: 10m memory: 10Mi + - name: oauth-proxy + image: registry.redhat.io/openshift4/ose-oauth-proxy@sha256:ab112105ac37352a2a4916a39d6736f5db6ab4c29bad4467de8d613e80e9bb33 + command: ["tail"] + args: ["-f", "/dev/null"] + resources: + limits: + memory: 20Mi + requests: + cpu: 10m + memory: 10Mi - name: ds-pipeline-persistenceagent-pipelines-definition image: registry.redhat.io/rhoai/odh-ml-pipelines-persistenceagent-rhel8@sha256:6fdf2b754aea6732ae0757e099ec69fac1cb32e633342a160546ee5b99604af7 command: ["tail"] diff --git a/bootstrap/ic-user-projects/create-projects-and-resources-job.yaml b/bootstrap/ic-user-projects/create-projects-and-resources-job.yaml index be71da82..e3b6868b 100644 --- a/bootstrap/ic-user-projects/create-projects-and-resources-job.yaml +++ b/bootstrap/ic-user-projects/create-projects-and-resources-job.yaml @@ -25,6 +25,18 @@ spec: # Get user count user_count=$(oc get namespaces | grep showroom | wc -l) + echo -n 'Waiting for minio-root-user secret' + while [ -z "\$(oc get secret -n ic-shared-minio minio-root-user -oname 2>/dev/null)" ]; do + echo -n . + sleep 5 + done; echo + + echo -n 'Waiting for rhods-dashboard route' + while [ -z "\$(oc get route -n redhat-ods-applications rhods-dashboard -oname 2>/dev/null)" ]; do + echo -n . + sleep 5 + done; echo + # Get needed variables MINIO_ROOT_USER=$(oc get secret minio-root-user -n ic-shared-minio -o template --template '{{.data.MINIO_ROOT_USER|base64decode}}') MINIO_ROOT_PASSWORD=$(oc get secret minio-root-user -n ic-shared-minio -o template --template '{{.data.MINIO_ROOT_PASSWORD|base64decode}}') @@ -141,12 +153,6 @@ spec: - args: - -ec - |- - echo -n "Waiting for minio-root-user to exist" - while [ -z "\$(oc get secret -n ic-shared-minio minio-root-user -oname 2>/dev/null)" ]; do - echo -n '.' - sleep 1 - done; echo - echo "Minio user: $MINIO_ROOT_USER" echo "Minio pass: $MINIO_ROOT_PASSWORD" echo "Internal service url: http://minio.ic-shared-minio.svc.cluster.local:9000/" @@ -513,5 +519,8 @@ spec: pod_name=\$(oc get pods --selector=app=$WORKBENCH_NAME -o jsonpath='{.items[0].metadata.name}') && oc exec \$pod_name -- git clone https://github.com/rh-aiservices-bu/parasol-insurance restartPolicy: Never EOF + + sleep 20 + done restartPolicy: Never \ No newline at end of file diff --git a/bootstrap/ic-user-projects/create-projects-and-resources.bash b/bootstrap/ic-user-projects/create-projects-and-resources.bash index ac889e82..537a496b 100644 --- a/bootstrap/ic-user-projects/create-projects-and-resources.bash +++ b/bootstrap/ic-user-projects/create-projects-and-resources.bash @@ -2,6 +2,18 @@ # Get user count user_count=$(oc get namespaces | grep showroom | wc -l) +echo -n 'Waiting for minio-root-user secret' +while [ -z "\$(oc get secret -n ic-shared-minio minio-root-user -oname 2>/dev/null)" ]; do + echo -n . + sleep 5 +done; echo + +echo -n 'Waiting for rhods-dashboard route' +while [ -z "\$(oc get route -n redhat-ods-applications rhods-dashboard -oname 2>/dev/null)" ]; do + echo -n . + sleep 5 +done; echo + # Get needed variables MINIO_ROOT_USER=$(oc get secret minio-root-user -n ic-shared-minio -o template --template '{{.data.MINIO_ROOT_USER|base64decode}}') MINIO_ROOT_PASSWORD=$(oc get secret minio-root-user -n ic-shared-minio -o template --template '{{.data.MINIO_ROOT_PASSWORD|base64decode}}') @@ -119,12 +131,6 @@ spec: - args: - -ec - |- - echo -n "Waiting for minio-root-user to exist" - while [ -z "\$(oc get secret -n ic-shared-minio minio-root-user -oname 2>/dev/null)" ]; do - echo -n '.' - sleep 1 - done; echo - echo "Minio user: $MINIO_ROOT_USER" echo "Minio pass: $MINIO_ROOT_PASSWORD" echo "Internal service url: http://minio.ic-shared-minio.svc.cluster.local:9000/" @@ -491,4 +497,7 @@ spec: pod_name=\$(oc get pods --selector=app=$WORKBENCH_NAME -o jsonpath='{.items[0].metadata.name}') && oc exec \$pod_name -- git clone https://github.com/rh-aiservices-bu/parasol-insurance restartPolicy: Never EOF + +sleep 20 + done \ No newline at end of file diff --git a/bootstrap/ic-user-projects/tools/check-and-recreate-projects.sh b/bootstrap/ic-user-projects/tools/check-and-recreate-projects.sh new file mode 100644 index 00000000..1f20611b --- /dev/null +++ b/bootstrap/ic-user-projects/tools/check-and-recreate-projects.sh @@ -0,0 +1,525 @@ +#!/bin/bash +user_count=$(oc get namespaces | grep showroom | wc -l) + +MINIO_ROOT_USER=$(oc get secret minio-root-user -n ic-shared-minio -o template --template '{{.data.MINIO_ROOT_USER|base64decode}}') +MINIO_ROOT_PASSWORD=$(oc get secret minio-root-user -n ic-shared-minio -o template --template '{{.data.MINIO_ROOT_PASSWORD|base64decode}}') +MINIO_HOST=https://$(oc get route minio-s3 -n ic-shared-minio -o template --template '{{.spec.host}}') +DASHBOARD_ROUTE=https://$(oc get route rhods-dashboard -n redhat-ods-applications -o jsonpath='{.spec.host}') + +# Define some variables +WORKBENCH_NAME="my-workbench" +WORKBENCH_IMAGE="ic-workbench:2.1.2" +PIPELINE_ENGINE="Tekton" +projects_without_running_pods=() + +for i in $(seq 1 $user_count); +do + +# Construct dynamic variables +USER_NAME="user$i" +USER_PROJECT="user$i" + +if [ -z "$(oc get pods -n $USER_PROJECT -l app=$WORKBENCH_NAME -o custom-columns=STATUS:.status.phase --no-headers | grep Running)" ]; then + echo "$USER_PROJECT workbench is not running." + projects_without_running_pods+=("$USER_PROJECT") +fi + +done + +while true; do + read -p "Do you want to recreate the above users? (y/n) " yn + case $yn in + [Yy]* ) break;; + [Nn]* ) exit;; + * ) echo "Please answer yes or no.";; + esac +done + + +for USER_PROJECT in "${projects_without_running_pods[@]}"; +do + +# Assume username and user project is the same +USER_NAME=$USER_PROJECT + +echo "Deleting user $USER_PROJECT..." +oc delete project $USER_PROJECT +echo "Waiting for project $USER_PROJECT to be deleted..." +while oc get project "$USER_PROJECT" &> /dev/null; do + echo -n '.' + sleep 5 +done + +echo "Generating and apply resources for $USER_NAME..." + +# Create projects +cat << EOF | oc apply -f- +apiVersion: project.openshift.io/v1 +kind: Project +metadata: + annotations: + openshift.io/description: '' + openshift.io/display-name: $USER_PROJECT + labels: + kubernetes.io/metadata.name: $USER_PROJECT + # modelmesh-enabled: 'true' + opendatahub.io/dashboard: 'true' + name: $USER_PROJECT +spec: + finalizers: + - kubernetes +EOF + +# Apply role bindings +cat << EOF | oc apply -f- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: admin + namespace: $USER_PROJECT +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: admin +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: User + name: $USER_NAME +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: demo-setup + namespace: $USER_PROJECT +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: demo-setup-edit + namespace: $USER_PROJECT +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: edit +subjects: +- kind: ServiceAccount + name: demo-setup +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: demo-setup-route-reader-binding-$USER_PROJECT +subjects: +- kind: ServiceAccount + name: demo-setup + namespace: $USER_PROJECT +roleRef: + kind: ClusterRole + name: route-reader + apiGroup: rbac.authorization.k8s.io +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: elyra-pipelines-$WORKBENCH_NAME + namespace: $USER_PROJECT + labels: + opendatahub.io/dashboard: 'true' +subjects: + - kind: ServiceAccount + name: $WORKBENCH_NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ds-pipeline-user-access-pipelines-definition +EOF + +# Create Data Science Connections +cat << EOF | oc apply -f- +apiVersion: batch/v1 +kind: Job +metadata: + name: create-ds-connections + namespace: $USER_PROJECT +spec: + selector: {} + template: + spec: + containers: + - args: + - -ec + - |- + echo -n "Waiting for minio-root-user to exist" + while [ -z "\$(oc get secret -n ic-shared-minio minio-root-user -oname 2>/dev/null)" ]; do + echo -n '.' + sleep 1 + done; echo + + echo "Minio user: $MINIO_ROOT_USER" + echo "Minio pass: $MINIO_ROOT_PASSWORD" + echo "Internal service url: http://minio.ic-shared-minio.svc.cluster.local:9000/" + cat << EOF | oc apply -f- + apiVersion: v1 + kind: Secret + metadata: + name: aws-connection-shared-minio---pipelines + labels: + opendatahub.io/dashboard: "true" + opendatahub.io/managed: "true" + annotations: + opendatahub.io/connection-type: s3 + openshift.io/display-name: Shared Minio - pipelines + type: Opaque + stringData: + AWS_ACCESS_KEY_ID: $MINIO_ROOT_USER + AWS_SECRET_ACCESS_KEY: $MINIO_ROOT_PASSWORD + AWS_DEFAULT_REGION: us + AWS_S3_ENDPOINT: http://minio.ic-shared-minio.svc:9000 + AWS_S3_BUCKET: $USER_NAME + EOF + command: + - /bin/bash + image: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:95b359257a7716b5f8d3a672081a84600218d8f58ca720f46229f7bb893af2ab + imagePullPolicy: IfNotPresent + name: create-ds-connections + restartPolicy: Never + serviceAccount: demo-setup + serviceAccountName: demo-setup +EOF + +# Set up the pipeline server +cat << EOF | oc apply -f- +apiVersion: datasciencepipelinesapplications.opendatahub.io/v1alpha1 +kind: DataSciencePipelinesApplication +metadata: + finalizers: + - datasciencepipelinesapplications.opendatahub.io/finalizer + name: pipelines-definition + namespace: $USER_PROJECT +spec: + apiServer: + applyTektonCustomResource: true + archiveLogs: false + autoUpdatePipelineDefaultVersion: true + collectMetrics: true + dbConfigConMaxLifetimeSec: 120 + deploy: true + enableOauth: true + enableSamplePipeline: false + injectDefaultScript: true + stripEOF: true + terminateStatus: Cancelled + trackArtifacts: true + database: + mariaDB: + deploy: true + pipelineDBName: mlpipeline + pvcSize: 10Gi + username: mlpipeline + objectStorage: + externalStorage: + bucket: $USER_NAME + host: minio.ic-shared-minio.svc.cluster.local:9000 + port: '' + s3CredentialsSecret: + accessKey: AWS_ACCESS_KEY_ID + secretKey: AWS_SECRET_ACCESS_KEY + secretName: aws-connection-shared-minio---pipelines + scheme: http + secure: false + persistenceAgent: + deploy: true + numWorkers: 2 + scheduledWorkflow: + cronScheduleTimezone: UTC + deploy: true +EOF + +# Create the Elyra secret +cat << EOF | oc apply -f- +apiVersion: batch/v1 +kind: Job +metadata: + name: create-pipeline-secret + namespace: $USER_PROJECT +spec: + selector: {} + template: + spec: + containers: + - args: + - -ec + - |- + echo -n 'Waiting for ds-pipeline-pipelines-definition route' + while ! oc get route ds-pipeline-pipelines-definition 2>/dev/null; do + echo -n . + sleep 5 + done; echo + + PIPELINE_ROUTE=https://\$(oc get route ds-pipeline-pipelines-definition -o jsonpath='{.spec.host}') + + cat << EOF | oc apply -f- + apiVersion: v1 + kind: Secret + metadata: + name: ds-pipeline-config + namespace: $USER_PROJECT + stringData: + odh_dsp.json: '{"display_name": "Data Science Pipeline", "metadata": {"tags": [], + "display_name": "Data Science Pipeline", "engine": "$PIPELINE_ENGINE", "auth_type": "KUBERNETES_SERVICE_ACCOUNT_TOKEN", + "api_endpoint": "\$PIPELINE_ROUTE", + "public_api_endpoint": "$DASHBOARD_ROUTE/pipelineRuns/$USER_PROJECT/pipelineRun/view/", + "cos_auth_type": "KUBERNETES_SECRET", "cos_secret": "aws-connection-shared-minio---pipelines", + "cos_endpoint": "$MINIO_HOST", "cos_bucket": "$USER_NAME", + "cos_username": "$MINIO_ROOT_USER", "cos_password": "$MINIO_ROOT_PASSWORD", + "runtime_type": "KUBEFLOW_PIPELINES"}, "schema_name": "kfp"}' + type: Opaque + EOF + command: + - /bin/bash + image: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:95b359257a7716b5f8d3a672081a84600218d8f58ca720f46229f7bb893af2ab + imagePullPolicy: IfNotPresent + name: create-ds-connections + restartPolicy: Never + serviceAccount: demo-setup + serviceAccountName: demo-setup +EOF + +# Create the workbench PVC +cat << EOF | oc apply -f- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + annotations: + openshift.io/description: '' + openshift.io/display-name: My Workbench + volume.beta.kubernetes.io/storage-provisioner: openshift-storage.rbd.csi.ceph.com + volume.kubernetes.io/storage-provisioner: openshift-storage.rbd.csi.ceph.com + name: $WORKBENCH_NAME + namespace: $USER_PROJECT + finalizers: + - kubernetes.io/pvc-protection + labels: + opendatahub.io/dashboard: 'true' +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: ocs-storagecluster-ceph-rbd + volumeMode: Filesystem +EOF + +# Create the workbench +cat << EOF | oc apply -f- +apiVersion: kubeflow.org/v1 +kind: Notebook +metadata: + annotations: + notebooks.opendatahub.io/inject-oauth: 'true' + opendatahub.io/image-display-name: CUSTOM - Insurance Claim Processing Lab Workbench + notebooks.opendatahub.io/oauth-logout-url: >- + $DASHBOARD_ROUTE/projects/$USER_PROJECT?notebookLogout=$WORKBENCH_NAME + opendatahub.io/accelerator-name: '' + openshift.io/description: '' + openshift.io/display-name: My Workbench + notebooks.opendatahub.io/last-image-selection: '$WORKBENCH_IMAGE' + notebooks.opendatahub.io/last-size-selection: Standard + opendatahub.io/username: $USER_NAME + name: $WORKBENCH_NAME + namespace: $USER_PROJECT + labels: + app: $WORKBENCH_NAME + opendatahub.io/dashboard: 'true' + opendatahub.io/odh-managed: 'true' + opendatahub.io/user: $USER_NAME +spec: + template: + spec: + affinity: {} + containers: + - resources: + limits: + cpu: '2' + memory: 8Gi + requests: + cpu: '1' + memory: 6Gi + readinessProbe: + failureThreshold: 3 + httpGet: + path: /notebook/$USER_PROJECT/$WORKBENCH_NAME/api + port: notebook-port + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + name: $WORKBENCH_NAME + livenessProbe: + failureThreshold: 3 + httpGet: + path: /notebook/$USER_PROJECT/$WORKBENCH_NAME/api + port: notebook-port + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + env: + - name: NOTEBOOK_ARGS + value: |- + --ServerApp.port=8888 + --ServerApp.token='' + --ServerApp.password='' + --ServerApp.base_url=/notebook/$USER_PROJECT/$WORKBENCH_NAME + --ServerApp.quit_button=False + --ServerApp.tornado_settings={"user":"$USER_NAME","hub_host":"$DASHBOARD_ROUTE","hub_prefix":"/projects/$USER_PROJECT"} + - name: JUPYTER_IMAGE + value: >- + image-registry.openshift-image-registry.svc:5000/redhat-ods-applications/$WORKBENCH_IMAGE + ports: + - containerPort: 8888 + name: notebook-port + protocol: TCP + imagePullPolicy: Always + volumeMounts: + - mountPath: /opt/app-root/src + name: $WORKBENCH_NAME + - mountPath: /opt/app-root/runtimes + name: elyra-dsp-details + - mountPath: /dev/shm + name: shm + image: >- + image-registry.openshift-image-registry.svc:5000/redhat-ods-applications/$WORKBENCH_IMAGE + workingDir: /opt/app-root/src + - resources: + limits: + cpu: 100m + memory: 64Mi + requests: + cpu: 100m + memory: 64Mi + readinessProbe: + failureThreshold: 3 + httpGet: + path: /oauth/healthz + port: oauth-proxy + scheme: HTTPS + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + name: oauth-proxy + livenessProbe: + failureThreshold: 3 + httpGet: + path: /oauth/healthz + port: oauth-proxy + scheme: HTTPS + initialDelaySeconds: 30 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + ports: + - containerPort: 8443 + name: oauth-proxy + protocol: TCP + imagePullPolicy: Always + volumeMounts: + - mountPath: /etc/oauth/config + name: oauth-config + - mountPath: /etc/tls/private + name: tls-certificates + image: >- + registry.redhat.io/openshift4/ose-oauth-proxy@sha256:4bef31eb993feb6f1096b51b4876c65a6fb1f4401fee97fa4f4542b6b7c9bc46 + args: + - '--provider=openshift' + - '--https-address=:8443' + - '--http-address=' + - '--openshift-service-account=$WORKBENCH_NAME' + - '--cookie-secret-file=/etc/oauth/config/cookie_secret' + - '--cookie-expire=24h0m0s' + - '--tls-cert=/etc/tls/private/tls.crt' + - '--tls-key=/etc/tls/private/tls.key' + - '--upstream=http://localhost:8888' + - '--upstream-ca=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt' + - '--email-domain=*' + - '--skip-provider-button' + - >- + --openshift-sar={"verb":"get","resource":"notebooks","resourceAPIGroup":"kubeflow.org","resourceName":"$WORKBENCH_IMAGE","namespace":"$USER_PROJECT"} + - >- + --logout-url=$DASHBOARD_ROUTE/projects/$USER_PROJECT?notebookLogout=$WORKBENCH_IMAGE + enableServiceLinks: false + serviceAccountName: $WORKBENCH_NAME + tolerations: + - effect: NoSchedule + key: notebooksonly + operator: Exists + volumes: + - name: $WORKBENCH_NAME + persistentVolumeClaim: + claimName: $WORKBENCH_NAME + - name: elyra-dsp-details + secret: + secretName: ds-pipeline-config + - emptyDir: + medium: Memory + name: shm + - name: oauth-config + secret: + defaultMode: 420 + secretName: $WORKBENCH_NAME-oauth-config + - name: tls-certificates + secret: + defaultMode: 420 + secretName: $WORKBENCH_NAME-tls + readyReplicas: 1 +EOF + +# Git clone job +cat << EOF | oc apply -f- +apiVersion: batch/v1 +kind: Job +metadata: + name: clone-repo + namespace: $USER_PROJECT +spec: + backoffLimit: 4 + template: + spec: + serviceAccount: demo-setup + serviceAccountName: demo-setup + initContainers: + - name: wait-for-workbench + image: image-registry.openshift-image-registry.svc:5000/openshift/tools:latest + imagePullPolicy: IfNotPresent + command: ["/bin/bash"] + args: + - -ec + - |- + echo -n "Waiting for workbench pod in $USER_PROJECT namespace" + while [ -z "\$(oc get pods -n $USER_PROJECT -l app=$WORKBENCH_NAME -o custom-columns=STATUS:.status.phase --no-headers | grep Running 2>/dev/null)" ]; do + echo -n '.' + sleep 1 + done + echo "Workbench pod is running in $USER_PROJECT namespace" + containers: + - name: git-clone + image: image-registry.openshift-image-registry.svc:5000/openshift/tools:latest + imagePullPolicy: IfNotPresent + command: ["/bin/bash"] + args: + - -ec + - |- + pod_name=\$(oc get pods --selector=app=$WORKBENCH_NAME -o jsonpath='{.items[0].metadata.name}') && oc exec \$pod_name -- git clone https://github.com/rh-aiservices-bu/parasol-insurance + restartPolicy: Never +EOF + +done \ No newline at end of file diff --git a/bootstrap/ic-user-projects/tools/check-projects.sh b/bootstrap/ic-user-projects/tools/check-projects.sh new file mode 100644 index 00000000..ba34abe0 --- /dev/null +++ b/bootstrap/ic-user-projects/tools/check-projects.sh @@ -0,0 +1,16 @@ +user_count=$(oc get namespaces | grep showroom | wc -l) + +WORKBENCH_NAME="my-workbench" + +for i in $(seq 1 $user_count); +do + +# Construct dynamic variables +USER_NAME="user$i" +USER_PROJECT="user$i" + +if [ -z "$(oc get pods -n $USER_PROJECT -l app=$WORKBENCH_NAME -o custom-columns=STATUS:.status.phase --no-headers | grep Running)" ]; then + echo "$USER_PROJECT workbench is not running." +fi + +done \ No newline at end of file diff --git a/bootstrap/ic-user-projects/create-single-user-project.sh b/bootstrap/ic-user-projects/tools/create-single-user-project.sh similarity index 99% rename from bootstrap/ic-user-projects/create-single-user-project.sh rename to bootstrap/ic-user-projects/tools/create-single-user-project.sh index 600b4b18..2dd5ec6d 100644 --- a/bootstrap/ic-user-projects/create-single-user-project.sh +++ b/bootstrap/ic-user-projects/tools/create-single-user-project.sh @@ -2,7 +2,7 @@ while true; do echo "Creating an individual user..." read -p "Please enter the username: " USER_NAME - read -p "Please enter the projectname: " PROJECT_NAME + read -p "Please enter the projectname: " USER_PROJECT echo "" read -p "Is this correct? (y/n) " yn diff --git a/content/modules/ROOT/assets/images/01/proto-claims-processing-app.png b/content/modules/ROOT/assets/images/01/proto-claims-processing-app.png index 94fa9111..5e42922e 100644 Binary files a/content/modules/ROOT/assets/images/01/proto-claims-processing-app.png and b/content/modules/ROOT/assets/images/01/proto-claims-processing-app.png differ diff --git a/content/modules/ROOT/assets/images/02/02-01-login3.png b/content/modules/ROOT/assets/images/02/02-01-login3.png new file mode 100644 index 00000000..e60d87d1 Binary files /dev/null and b/content/modules/ROOT/assets/images/02/02-01-login3.png differ diff --git a/content/modules/ROOT/assets/images/02/02-03-pre-created-workbench-info.png b/content/modules/ROOT/assets/images/02/02-03-pre-created-workbench-info.png index 0132c8f9..73faba16 100644 Binary files a/content/modules/ROOT/assets/images/02/02-03-pre-created-workbench-info.png and b/content/modules/ROOT/assets/images/02/02-03-pre-created-workbench-info.png differ diff --git a/content/modules/ROOT/assets/images/03/03-06-unsaved-changes.png b/content/modules/ROOT/assets/images/03/03-06-unsaved-changes.png new file mode 100644 index 00000000..29dfe31d Binary files /dev/null and b/content/modules/ROOT/assets/images/03/03-06-unsaved-changes.png differ diff --git a/content/modules/ROOT/assets/images/03/06-elyra-menu.png b/content/modules/ROOT/assets/images/03/06-elyra-menu.png new file mode 100644 index 00000000..1c535565 Binary files /dev/null and b/content/modules/ROOT/assets/images/03/06-elyra-menu.png differ diff --git a/content/modules/ROOT/assets/images/05/application-architecture.drawio.svg b/content/modules/ROOT/assets/images/05/application-architecture.drawio.svg index fe47832d..f703033c 100644 --- a/content/modules/ROOT/assets/images/05/application-architecture.drawio.svg +++ b/content/modules/ROOT/assets/images/05/application-architecture.drawio.svg @@ -1,127 +1,4 @@ - - - - - - - - - -
-
-
- LLM Server -
-
-
-
- - LLM Server - -
-
- - - - - -
-
-
- Claims Database -
- (PostgreSQL) -
-
-
-
- - Claims Database... - -
-
- - - - - -
-
-
- Application Backend -
- (Python) -
-
-
-
- - Application Backend... - -
-
- - - - - - - - -
-
-
- Application Frontend -
- (React) -
-
-
-
- - Application Frontend... - -
-
- - - - - -
-
-
- Claims Images -
- (S3 Storage) -
-
-
-
- - Claims Images... - -
-
- - - - - - - - - - - - -
- - - - - Text is not SVG - cannot display - - - -
\ No newline at end of file + + + +
LLM Server
LLM Server
Claims Database
(PostgreSQL)
Claims Database...
Application Backend
(Python)
Application Backend...
Application Frontend
(React)
Application Frontend...
Claims Images
(S3 Storage)
Claims Images...
VectorDB
(Milvus)
VectorDB...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/content/modules/ROOT/pages/02-01-getting-connected.adoc b/content/modules/ROOT/pages/02-01-getting-connected.adoc index 1c2857f6..ecb4fd47 100644 --- a/content/modules/ROOT/pages/02-01-getting-connected.adoc +++ b/content/modules/ROOT/pages/02-01-getting-connected.adoc @@ -16,6 +16,10 @@ In a new window or tab, open the following URL and log in: * The {rhoai} Dashboard URL for our shared environment: ** https://rhods-dashboard-redhat-ods-applications.{openshift_cluster_ingress_domain}/[https://rhods-dashboard-redhat-ods-applications.{openshift_cluster_ingress_domain}/,window=_blank] +* Click on the `Login with OpenShift` button: ++ +[.bordershadow] +image::02/02-01-login3.png[width=50%] * Enter your credentials (as detailed above) * The result should look like: + diff --git a/content/modules/ROOT/pages/02-02-auto-created-project.adoc b/content/modules/ROOT/pages/02-02-auto-created-project.adoc index 28a9eb5b..b145547d 100644 --- a/content/modules/ROOT/pages/02-02-auto-created-project.adoc +++ b/content/modules/ROOT/pages/02-02-auto-created-project.adoc @@ -14,13 +14,13 @@ image::02/02-02-ds-proj-nav.png[] * Then, open the project called {user}. -* Inside the project you should see a few items that already has been pre-created: +* Inside the project you should see a few items that already have been pre-created: + [.bordershadow] image::02/02-02-pre-created-components.png[] * These components are as follows: -** A Workbench - this is your environment that you can experiment and train in. -** A Cluster storage - this is a persistent storage for your workbench. -** A Data Connection - it contains all the information needed to talk with an existing S3 storage, we use that to store models and pipeline artifacts. -** A Pipeline Server - the pipeline server has already been set up here so you can import or run Data Science pipelines right away. +1. A Workbench - this is your environment that you can experiment and train in. +2. A Cluster storage - this is a persistent storage for your workbench. +3. A Data Connection - it contains all the information needed to talk with an existing S3 storage, we use that to store models and pipeline artifacts. +4. A Pipeline Server - the pipeline server has already been set up here so you can import or run data science pipelines right away. diff --git a/content/modules/ROOT/pages/02-05-validating-env.adoc b/content/modules/ROOT/pages/02-05-validating-env.adoc index 587d405f..ddb12b19 100644 --- a/content/modules/ROOT/pages/02-05-validating-env.adoc +++ b/content/modules/ROOT/pages/02-05-validating-env.adoc @@ -29,8 +29,10 @@ The output should look as follows: Success: Minio is reachable on minio.ic-shared-minio.svc.cluster.local:9000 Success: Gitea is reachable on gitea.gitea.svc.cluster.local:3000 Success: Postgres Database is reachable on claimdb.ic-shared-db.svc.cluster.local:5432 -Success: LLM Service is reachable on llm.ic-shared-llm.svc.cluster.local:3000 +Success: LLM Service is reachable on llm.ic-shared-llm.svc.cluster.local:8000 +Success: LLM Service-FlanT5 is reachable on llm-flant5.ic-shared-llm.svc.cluster.local:3000 Success: ModelMesh is reachable on modelmesh-serving.ic-shared-img-det.svc.cluster.local:8033 +Success: Milvus Vector DB is reachable on vectordb-milvus.ic-shared-milvus.svc.cluster.local:19530 ---- If the output of this notebook looks suspicious, please inform the people leading the {ic}. diff --git a/content/modules/ROOT/pages/03-06-confidence-check.adoc b/content/modules/ROOT/pages/03-06-confidence-check.adoc index 5bafe9b8..53ff5191 100644 --- a/content/modules/ROOT/pages/03-06-confidence-check.adoc +++ b/content/modules/ROOT/pages/03-06-confidence-check.adoc @@ -13,6 +13,17 @@ In the `parasol-insurance/lab-materials/03/06` folder there are two pipeline fil The `.pipeline` file can be opened in Elyra to be visually modified and executed, while the `.yaml` file can be imported into the pipeline server through the RHOAI Dashboard. + Here we will be running the pipeline through Elyra. +== What is Elyra? + +Elyra is a visual interface to build out pipelines. Think of it as your standard code editor, but drag-and-drop. This also means that we won't execute anything in/with Elyra, but just produce some code (or more specifically, a json in the case of Elyra) that later will be sent elsewhere for execution. + +In Elyra, you can drag-and-drop in Python, notebook, or R files into the dashboard and then connect them up into a workflow. + +You also have a button on the top-right side that allows you to expand additional settings for the pipeline and each step. + +[.bordershadow] +image::03/06-elyra-menu.png[] + +Using Elyra, you can get started quicly with prototyping and running pipelines. + == Ad-Hoc execution Running it through Elyra is the same as doing an ad-hoc execution of the pipeline, as opposed to importing the pipeline which won't automatically execute it. @@ -30,7 +41,11 @@ Running it through Elyra is the same as doing an ad-hoc execution of the pipelin + [.bordershadow] image::03/07-elyra-pipeline.png[elyra confidence pipeline] -. in the popup, leave the name unchanged and click **OK**: +. You may get a warning that the pipeline is unsaved, this is normal, just press **Save and Submit** if this happens. ++ +[.bordershadow] +image::03/03-06-unsaved-changes.png[] +. In the next popup, leave the name unchanged and click **OK**: + [.bordershadow] image::03/03-07-run-pipeline-ok.png[] diff --git a/content/modules/ROOT/pages/05-01-application.adoc b/content/modules/ROOT/pages/05-01-application.adoc index 3f2bc179..ec881218 100644 --- a/content/modules/ROOT/pages/05-01-application.adoc +++ b/content/modules/ROOT/pages/05-01-application.adoc @@ -15,6 +15,7 @@ The different components are: - The **backend**: a Python FastAPI application, running in a container on {ocp}. It handles the communication with the database, the LLM, and the Object storage. It handles the communication with the frontend by exposing a REST API. - The **database**: a PostgreSQL database, running in a container on {ocp}. It stores the claims. - The **LLM**: the language model used to summarize and extract information from the claims. It is consumed by the backend through its API. +- The **VectorDB**: the vector database used to store documents for retrieval in the RAG part. It's based on Milvus. - The **Object storage**: an S3-compatible object storage. It stores the claim images. == Application Code diff --git a/lab-materials/02/02-05-validating.ipynb b/lab-materials/02/02-05-validating.ipynb index a1e11536..7dec031a 100644 --- a/lab-materials/02/02-05-validating.ipynb +++ b/lab-materials/02/02-05-validating.ipynb @@ -71,10 +71,11 @@ " (\"llm.ic-shared-llm.svc.cluster.local\", 8000, \"LLM Service\"),\n", " (\"llm-flant5.ic-shared-llm.svc.cluster.local\", 3000, \"LLM Service-FlanT5\"),\n", " (\"modelmesh-serving.ic-shared-img-det.svc.cluster.local\", 8033, \"ModelMesh\"),\n", + " (\"vectordb-milvus.ic-shared-milvus.svc.cluster.local\", 19530, \"Milvus Vector DB\"),\n", " # Add more services as needed\n", " ]\n", "\n", - " check_services(services_to_check)\n" + " check_services(services_to_check)" ] } ], @@ -94,7 +95,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.5" + "version": "3.11.7" } }, "nbformat": 4, diff --git a/lab-materials/03/03-04-comparing-model-servers.ipynb b/lab-materials/03/03-04-comparing-model-servers.ipynb index 161e085b..2aab4d42 100644 --- a/lab-materials/03/03-04-comparing-model-servers.ipynb +++ b/lab-materials/03/03-04-comparing-model-servers.ipynb @@ -88,6 +88,9 @@ }, "outputs": [], "source": [ + "import warnings\n", + "warnings.filterwarnings(\"ignore\")\n", + "\n", "# Flan-T5-Small LLM Inference Server URL\n", "inference_server_url_flan_t5 = \"http://llm-flant5.ic-shared-llm.svc.cluster.local:3000/\"\n", "\n", diff --git a/lab-materials/03/03-05-retrieval-augmented-generation.ipynb b/lab-materials/03/03-05-retrieval-augmented-generation.ipynb index ff6c53a0..4228d352 100644 --- a/lab-materials/03/03-05-retrieval-augmented-generation.ipynb +++ b/lab-materials/03/03-05-retrieval-augmented-generation.ipynb @@ -54,7 +54,11 @@ "from langchain_community.vectorstores import Milvus\n", "from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler\n", "from langchain.prompts import PromptTemplate\n", - "from milvus_retriever_with_score_threshold import MilvusRetrieverWithScoreThreshold" + "from milvus_retriever_with_score_threshold import MilvusRetrieverWithScoreThreshold\n", + "\n", + "#Turn off warnings when downloading the embedding model\n", + "import transformers\n", + "transformers.logging.set_verbosity_error()" ] }, { diff --git a/lab-materials/03/claims/claim1.json b/lab-materials/03/claims/claim1.json index eff55736..7a111686 100644 --- a/lab-materials/03/claims/claim1.json +++ b/lab-materials/03/claims/claim1.json @@ -1,5 +1,5 @@ { "claim-number": 1, "subject": "Claim for Recent Car Accident - Policy Number: AC-987654321", - "content": "Dear Pacific Shield Insurance,\n\nI hope this email finds you well. My name is Sarah Turner, and I am writing to file a claim for a recent car accident that occurred on January 2nd, 2024, at approximately 3:30 PM. My policy number is AC-987654321.\n\nThe accident took place at the intersection of Birch Street and Willow Avenue in the city of Evergreen. I was driving my vehicle, a black Toyota Camry with license plate number DEF-456, heading south on Birch Street. At the intersection, the traffic signal was green, and I proceeded through the intersection.\n\nAt the same time, another vehicle, a blue Chevrolet Traverse with license plate number GHI-789, was traveling west on Willow Avenue. Unfortunately, the driver failed to stop at the red traffic signal, resulting in a collision with the front passenger side of my vehicle.\n\nThe impact caused significant damage to both vehicles. The front bumper and right headlight of my Toyota Camry are extensively damaged, and there are also damages to the front driver's side of the Chevrolet Traverse. Fortunately, no injuries were sustained during the accident, and both drivers were able to move their vehicles to the side of the road.\n\nI promptly exchanged information with the other driver, Mr. Daniel Reynolds, including our names, phone numbers, insurance details, and a brief description of the accident. Additionally, I took photos of the accident scene, including the damages to both vehicles and the position of the traffic signal.\n\nI have attached the necessary documents to this email, including the photos, a copy of the police report filed at the Evergreen Police Department, and the estimate for the repair costs from Evergreen Auto Repair, where I have taken my vehicle for assessment.\n\nI kindly request your prompt attention to this matter and would appreciate any guidance on the next steps in the claims process. If you require any additional information or documentation, please do not hesitate to contact me at (555) 123-4567 or sarah.turner@email.com.\n\nThank you for your assistance, and I look forward to a swift resolution of this claim.\n\nSincerely,\n\nSarah Turner\n123 Oak Street\nEvergreen, CA 98765\n(555) 123-4567\nsarah.turner@email.com" + "content": "Dear Parasol Insurance,\n\nI hope this email finds you well. My name is Sarah Turner, and I am writing to file a claim for a recent car accident that occurred on January 2nd, 2024, at approximately 3:30 PM. My policy number is AC-987654321.\n\nThe accident took place at the intersection of Birch Street and Willow Avenue in the city of Evergreen. I was driving my vehicle, a black Toyota Camry with license plate number DEF-456, heading south on Birch Street. At the intersection, the traffic signal was green, and I proceeded through the intersection.\n\nAt the same time, another vehicle, a blue Chevrolet Traverse with license plate number GHI-789, was traveling west on Willow Avenue. Unfortunately, the driver failed to stop at the red traffic signal, resulting in a collision with the front passenger side of my vehicle.\n\nThe impact caused significant damage to both vehicles. The front bumper and right headlight of my Toyota Camry are extensively damaged, and there are also damages to the front driver's side of the Chevrolet Traverse. Fortunately, no injuries were sustained during the accident, and both drivers were able to move their vehicles to the side of the road.\n\nI promptly exchanged information with the other driver, Mr. Daniel Reynolds, including our names, phone numbers, insurance details, and a brief description of the accident. Additionally, I took photos of the accident scene, including the damages to both vehicles and the position of the traffic signal.\n\nI have attached the necessary documents to this email, including the photos, a copy of the police report filed at the Evergreen Police Department, and the estimate for the repair costs from Evergreen Auto Repair, where I have taken my vehicle for assessment.\n\nI kindly request your prompt attention to this matter and would appreciate any guidance on the next steps in the claims process. If you require any additional information or documentation, please do not hesitate to contact me at (555) 123-4567 or sarah.turner@email.com.\n\nThank you for your assistance, and I look forward to a swift resolution of this claim.\n\nSincerely,\n\nSarah Turner\n123 Oak Street\nEvergreen, CA 98765\n(555) 123-4567\nsarah.turner@email.com" } diff --git a/lab-materials/03/claims/claim3.json b/lab-materials/03/claims/claim3.json index 654a98d0..2bfd49c7 100644 --- a/lab-materials/03/claims/claim3.json +++ b/lab-materials/03/claims/claim3.json @@ -1,5 +1,5 @@ { "claim-number": 3, "subject": "Urgent: Car Accident Claim Assistance Needed", - "content": "Dear AssuranceCare Inc.,\n\nI hope this email finds you well. I'm writing to, uh, inform you about, well, something that happened recently. It's, um, about a car accident, and I'm not really sure how to, you know, go about all this. I'm kinda anxious and confused, to be honest.\n\nSo, the accident, uh, occurred on January 15, 2024, at around 3:30 PM. I was driving, or, um, attempting to drive, my car at the intersection of Maple Street and Elm Avenue. It's kinda close to, um, a gas station and a, uh, coffee shop called Brew Haven? I'm not sure if that matters, but, yeah.\n\nSo, I was just, you know, driving along, and suddenly, out of nowhere, another car, a Blue Crest Sedan, crashed into the, uh, driver's side of my car. It was like, whoa, what just happened, you know? There was this screeching noise and, uh, some honking from other cars, and I just felt really, uh, overwhelmed.\n\nThe weather was, um, kinda cloudy that day, but I don't think it was raining. I mean, I can't really remember. Sorry if that's important. Anyway, the road, or, well, maybe the intersection, was kinda busy, with cars going in different directions. I guess that's, you know, a detail you might need?\n\nAs for damages, my car has, uh, significant damage on the driver's side. The front door is all dented, and the side mirror is, like, hanging by a thread. It's not really drivable in its current, uh, state. The Blue Crest Sedan also had some damage, but I'm not exactly sure what because, you know, everything happened so fast.\n\nI did manage to exchange information with the other driver. Their name is Sarah Johnson, and I got their phone number (555-1234), license plate number (ABC123), and insurance information. So, yeah, I hope that's helpful.\n\nI'm not sure what, um, steps I should take now. Do I need to go to a specific, uh, repair shop? Should I get a quote for the repairs? And, uh, how do I, you know, proceed with the insurance claim? I'm kinda lost here, and any guidance or assistance you can provide would be really, um, appreciated.\n\nSorry if this email is a bit all over the place. I'm just really, uh, anxious about the whole situation. Thank you for your understanding.\n\nSincerely,\n\nJane Doe\nPolicy Number: AC987654" + "content": "Dear Parasol Insurance,\n\nI hope this email finds you well. I'm writing to, uh, inform you about, well, something that happened recently. It's, um, about a car accident, and I'm not really sure how to, you know, go about all this. I'm kinda anxious and confused, to be honest.\n\nSo, the accident, uh, occurred on January 15, 2024, at around 3:30 PM. I was driving, or, um, attempting to drive, my car at the intersection of Maple Street and Elm Avenue. It's kinda close to, um, a gas station and a, uh, coffee shop called Brew Haven? I'm not sure if that matters, but, yeah.\n\nSo, I was just, you know, driving along, and suddenly, out of nowhere, another car, a Blue Crest Sedan, crashed into the, uh, driver's side of my car. It was like, whoa, what just happened, you know? There was this screeching noise and, uh, some honking from other cars, and I just felt really, uh, overwhelmed.\n\nThe weather was, um, kinda cloudy that day, but I don't think it was raining. I mean, I can't really remember. Sorry if that's important. Anyway, the road, or, well, maybe the intersection, was kinda busy, with cars going in different directions. I guess that's, you know, a detail you might need?\n\nAs for damages, my car has, uh, significant damage on the driver's side. The front door is all dented, and the side mirror is, like, hanging by a thread. It's not really drivable in its current, uh, state. The Blue Crest Sedan also had some damage, but I'm not exactly sure what because, you know, everything happened so fast.\n\nI did manage to exchange information with the other driver. Their name is Sarah Johnson, and I got their phone number (555-1234), license plate number (ABC123), and insurance information. So, yeah, I hope that's helpful.\n\nI'm not sure what, um, steps I should take now. Do I need to go to a specific, uh, repair shop? Should I get a quote for the repairs? And, uh, how do I, you know, proceed with the insurance claim? I'm kinda lost here, and any guidance or assistance you can provide would be really, um, appreciated.\n\nSorry if this email is a bit all over the place. I'm just really, uh, anxious about the whole situation. Thank you for your understanding.\n\nSincerely,\n\nJane Doe\nPolicy Number: AC987654" } diff --git a/lab-materials/03/optional_claims/claim5.json b/lab-materials/03/optional_claims/claim5.json index c4ac64d3..ad7f2a50 100644 --- a/lab-materials/03/optional_claims/claim5.json +++ b/lab-materials/03/optional_claims/claim5.json @@ -1,5 +1,5 @@ { "claim-number": 5, "subject": "Where is My Money? Urgent Attention Needed for My Car Accident Claim", - "content": "Dear Stoneheart Insurance Claims Department,\n\nI am absolutely *thrilled* (read: infuriated) to be writing yet another heartfelt missive to the void that is your customer service. My recent car accident claim has vanished into the ether, much like my patience and the professionalism I expected from your company. How about we resolve this before the next ice age?\n\nLet's recap the blockbuster event:\nOn March 28, 2023, at around 4:15 PM, at the intersection of 5th Avenue and Main St in Springfield, my car was passionately sideswiped by another vehicle. Why? Because the other driver blasted through a red light and T-boned my car's passenger side. It was a harrowing scene, made worse by your glacial pace of response.\n\nIt's been over two weeks, and your commitment to delay is almost impressive. I demand a comprehensive review and prompt update on my claim within the next 24 hours. This isn't just a request—it's a necessity driven by sheer frustration and the urgent need for resolution.\n\nPlease treat this matter with the urgency it clearly deserves. I expect a detailed plan of action and a swift response, or be assured, further actions including legal recourse will be considered.\n\nLooking forward to an expedited resolution,\nSaul Goodman\n\nCC: My 17 Twitter Followers\n\nAttach: Police Report No. 12345, Photos of the Incident, Documented Calls and Emails" + "content": "Dear Parasol Insurance,\n\nI am absolutely *thrilled* (read: infuriated) to be writing yet another heartfelt missive to the void that is your customer service. My recent car accident claim has vanished into the ether, much like my patience and the professionalism I expected from your company. How about we resolve this before the next ice age?\n\nLet's recap the blockbuster event:\nOn March 28, 2023, at around 4:15 PM, at the intersection of 5th Avenue and Main St in Springfield, my car was passionately sideswiped by another vehicle. Why? Because the other driver blasted through a red light and T-boned my car's passenger side. It was a harrowing scene, made worse by your glacial pace of response.\n\nIt's been over two weeks, and your commitment to delay is almost impressive. I demand a comprehensive review and prompt update on my claim within the next 24 hours. This isn't just a request—it's a necessity driven by sheer frustration and the urgent need for resolution.\n\nPlease treat this matter with the urgency it clearly deserves. I expect a detailed plan of action and a swift response, or be assured, further actions including legal recourse will be considered.\n\nLooking forward to an expedited resolution,\nSaul Goodman\n\nCC: My 17 Twitter Followers\n\nAttach: Police Report No. 12345, Photos of the Incident, Documented Calls and Emails" } \ No newline at end of file diff --git a/lab-materials/03/optional_claims/claim6.json b/lab-materials/03/optional_claims/claim6.json index 5d728609..ae37e895 100644 --- a/lab-materials/03/optional_claims/claim6.json +++ b/lab-materials/03/optional_claims/claim6.json @@ -1,5 +1,5 @@ { "claim-number": 6, "subject": "Urgent Claim Review Required: Collision in King's Landing", - "content": "Dear Westeros Insurance Claims Department,\nThis correspondence is from Tyrion Lannister, currently not in a tavern but rather dealing with the aftermath of an unpleasant vehicular incident. As a man known for resolving conflicts, I find myself ironically embroiled in one that requires your immediate attention.\n\nHere are the distressing details:\nOn April 15, 2023, at about noon, within the confines of King's Landing, my car was struck by another. As I navigated through the bustling streets near the marketplace, a distracted driver—likely admiring the view of the Blackwater Bay instead of the road—rammed into my car's side. This not only caused significant damage to the vehicle but also disrupted my travel plans significantly.\n\nNearly a month has elapsed since the accident, and yet, I've seen more action in the Small Council meetings than in the progress of my claim. Your lack of promptness in handling this matter is both noted and distressing. I require an exhaustive review and a swift update on my claim within the next 48 hours. This is not a mere request, but a necessity fueled by urgent needs and dwindling patience.\n\nPlease address this claim with the seriousness it merits. I expect a detailed response and a rapid resolution, or rest assured, further actions, potentially involving the Crown, will be considered.\n\nI await your expedited action,\nTyrion Lannister\n\nCC: Master of Coin\n\nAttach: Car Damage Photos, Eyewitness Accounts, Incident Report No. KL509" + "content": "Dear Parasol Insurance,\nThis correspondence is from Tyrion Lannister, currently not in a tavern but rather dealing with the aftermath of an unpleasant vehicular incident. As a man known for resolving conflicts, I find myself ironically embroiled in one that requires your immediate attention.\n\nHere are the distressing details:\nOn April 15, 2023, at about noon, within the confines of King's Landing, my car was struck by another. As I navigated through the bustling streets near the marketplace, a distracted driver—likely admiring the view of the Blackwater Bay instead of the road—rammed into my car's side. This not only caused significant damage to the vehicle but also disrupted my travel plans significantly.\n\nNearly a month has elapsed since the accident, and yet, I've seen more action in the Small Council meetings than in the progress of my claim. Your lack of promptness in handling this matter is both noted and distressing. I require an exhaustive review and a swift update on my claim within the next 48 hours. This is not a mere request, but a necessity fueled by urgent needs and dwindling patience.\n\nPlease address this claim with the seriousness it merits. I expect a detailed response and a rapid resolution, or rest assured, further actions, potentially involving the Crown, will be considered.\n\nI await your expedited action,\nTyrion Lannister\n\nCC: Master of Coin\n\nAttach: Car Damage Photos, Eyewitness Accounts, Incident Report No. KL509" } \ No newline at end of file