From 5d030afe12b6d35ff83025b67b1c0a526747435d Mon Sep 17 00:00:00 2001 From: Joe Corall Date: Fri, 6 Dec 2024 14:38:54 -0500 Subject: [PATCH 1/5] Add OpenAI HTR service --- ci/k8s/htr.yaml | 52 +++++++++++++++++++++++++++++ ci/k8s/ingress.yaml | 7 ++++ examples/openai-htr/Dockerfile | 5 +++ examples/openai-htr/README.md | 14 ++++++++ examples/openai-htr/cmd.sh | 28 ++++++++++++++++ examples/openai-htr/scyllaridae.yml | 7 ++++ 6 files changed, 113 insertions(+) create mode 100644 ci/k8s/htr.yaml create mode 100644 examples/openai-htr/Dockerfile create mode 100644 examples/openai-htr/README.md create mode 100755 examples/openai-htr/cmd.sh create mode 100644 examples/openai-htr/scyllaridae.yml diff --git a/ci/k8s/htr.yaml b/ci/k8s/htr.yaml new file mode 100644 index 0000000..de51390 --- /dev/null +++ b/ci/k8s/htr.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: islandora-openai-htr +spec: + selector: + app: islandora-openai-htr + ports: + - protocol: TCP + port: 8001 + targetPort: 8080 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: islandora-openai-htr +spec: + replicas: 3 + selector: + matchLabels: + app: islandora-openai-htr + template: + metadata: + labels: + app: islandora-openai-htr + spec: + containers: + - name: scyllaridae-tesseract + image: lehighlts/scyllaridae-openai-htr:main + imagePullPolicy: IfNotPresent + env: + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: openai + key: api-key + resources: + requests: + memory: "128Mi" + cpu: "250m" + limits: + memory: "1Gi" + ports: + - hostPort: 8001 + containerPort: 8080 + readinessProbe: + httpGet: + path: /healthcheck + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 10 diff --git a/ci/k8s/ingress.yaml b/ci/k8s/ingress.yaml index 3388c11..20cc491 100644 --- a/ci/k8s/ingress.yaml +++ b/ci/k8s/ingress.yaml @@ -88,3 +88,10 @@ spec: name: islandora-ocrpdf port: number: 8080 + - path: /openai\-htr(/|$)(.*) + pathType: Prefix + backend: + service: + name: islandora-openai-htr + port: + number: 8080 diff --git a/examples/openai-htr/Dockerfile b/examples/openai-htr/Dockerfile new file mode 100644 index 0000000..c99eb76 --- /dev/null +++ b/examples/openai-htr/Dockerfile @@ -0,0 +1,5 @@ +ARG TAG=main +ARG DOCKER_REPOSITORY=lehighlts +FROM ${DOCKER_REPOSITORY}/scyllaridae:${TAG} + +COPY scyllaridae.yml /app/scyllaridae.yml diff --git a/examples/openai-htr/README.md b/examples/openai-htr/README.md new file mode 100644 index 0000000..400db9f --- /dev/null +++ b/examples/openai-htr/README.md @@ -0,0 +1,14 @@ +# openai-htr + +Use OpenAI ChatGPT to transcribe handwritten text. + +## Secrets + +Requires an environment variable `OPENAI_API_KEY` + +If deploying this in kubernetes, you can create the secret via + +``` + kubectl create secret generic openai \ + --from-literal=api-key=$OPENAI_API_KEY +``` diff --git a/examples/openai-htr/cmd.sh b/examples/openai-htr/cmd.sh new file mode 100755 index 0000000..2fcecca --- /dev/null +++ b/examples/openai-htr/cmd.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +set -eou pipefail + +curl https://api.openai.com/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -d '{ + "model": "gpt-4o-mini", + "messages": [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "Transcribe this image that contains handwritten text. Include all text you see in the image. In your response, say absolutely nothing except the text from the image" + }, + { + "type": "image_url", + "image_url": { + "url": "$1" + } + } + ] + } + ], + "max_tokens": 50 + }' | jq -r .choices[0].message.content diff --git a/examples/openai-htr/scyllaridae.yml b/examples/openai-htr/scyllaridae.yml new file mode 100644 index 0000000..a527b7e --- /dev/null +++ b/examples/openai-htr/scyllaridae.yml @@ -0,0 +1,7 @@ +allowedMimeTypes: + - "image/*" +cmdByMimeType: + default: + cmd: /app/cmd.sh + args: + - "%source-uri" From aaf9b36ebf32b19913237aae6bdcdfea4beda573 Mon Sep 17 00:00:00 2001 From: Joe Corall Date: Fri, 6 Dec 2024 14:47:18 -0500 Subject: [PATCH 2/5] Add openai-htr to parry --- examples/parry/scyllaridae.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/parry/scyllaridae.yml b/examples/parry/scyllaridae.yml index 4b1c553..9a264f0 100644 --- a/examples/parry/scyllaridae.yml +++ b/examples/parry/scyllaridae.yml @@ -9,3 +9,6 @@ queueMiddlewares: - queueName: islandora-merge-pdf url: http://mergepdf:8080 consumers: 3 + - queueName: islandora-openai-htr + url: http://openai-htr:8080 + consumers: 3 From 8d837b4495d772e5cc6f25890d074bb45dbe9a54 Mon Sep 17 00:00:00 2001 From: Joe Corall Date: Fri, 6 Dec 2024 14:48:01 -0500 Subject: [PATCH 3/5] shellcheck --- examples/openai-htr/cmd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/openai-htr/cmd.sh b/examples/openai-htr/cmd.sh index 2fcecca..33af4be 100755 --- a/examples/openai-htr/cmd.sh +++ b/examples/openai-htr/cmd.sh @@ -18,7 +18,7 @@ curl https://api.openai.com/v1/chat/completions \ { "type": "image_url", "image_url": { - "url": "$1" + "url": "'"$1"'" } } ] From 086a98bebfd122e4d7d930230739f81d98263e83 Mon Sep 17 00:00:00 2001 From: Joe Corall Date: Fri, 6 Dec 2024 14:57:46 -0500 Subject: [PATCH 4/5] make prompt and model env vars --- examples/openai-htr/Dockerfile | 2 ++ examples/openai-htr/cmd.sh | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/openai-htr/Dockerfile b/examples/openai-htr/Dockerfile index c99eb76..d68a2c1 100644 --- a/examples/openai-htr/Dockerfile +++ b/examples/openai-htr/Dockerfile @@ -2,4 +2,6 @@ ARG TAG=main ARG DOCKER_REPOSITORY=lehighlts FROM ${DOCKER_REPOSITORY}/scyllaridae:${TAG} +ENV OPENAI_MODEL=gpt-4o-mini +ENV PROMPT="Transcribe this image that contains handwritten text. Include all text you see in the image. In your response, say absolutely nothing except the text from the image" COPY scyllaridae.yml /app/scyllaridae.yml diff --git a/examples/openai-htr/cmd.sh b/examples/openai-htr/cmd.sh index 33af4be..c5b2011 100755 --- a/examples/openai-htr/cmd.sh +++ b/examples/openai-htr/cmd.sh @@ -6,14 +6,14 @@ curl https://api.openai.com/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -d '{ - "model": "gpt-4o-mini", + "model": "'"$OPENAI_MODEL"'", "messages": [ { "role": "user", "content": [ { "type": "text", - "text": "Transcribe this image that contains handwritten text. Include all text you see in the image. In your response, say absolutely nothing except the text from the image" + "text": "'"$PROMPT"'" }, { "type": "image_url", From ddfa75e7fa217ef43740ea9e2e9f03fdeea6b0ea Mon Sep 17 00:00:00 2001 From: Joe Corall Date: Fri, 6 Dec 2024 15:11:29 -0500 Subject: [PATCH 5/5] MAX_TOKENS env var --- examples/openai-htr/Dockerfile | 5 +++-- examples/openai-htr/cmd.sh | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/openai-htr/Dockerfile b/examples/openai-htr/Dockerfile index d68a2c1..221f69e 100644 --- a/examples/openai-htr/Dockerfile +++ b/examples/openai-htr/Dockerfile @@ -2,6 +2,7 @@ ARG TAG=main ARG DOCKER_REPOSITORY=lehighlts FROM ${DOCKER_REPOSITORY}/scyllaridae:${TAG} -ENV OPENAI_MODEL=gpt-4o-mini -ENV PROMPT="Transcribe this image that contains handwritten text. Include all text you see in the image. In your response, say absolutely nothing except the text from the image" +ENV OPENAI_MODEL=gpt-4o-mini \ + PROMPT="Transcribe this image that contains handwritten text. Include all text you see in the image. In your response, say absolutely nothing except the text from the image" \ + MAX_TOKENS=300 COPY scyllaridae.yml /app/scyllaridae.yml diff --git a/examples/openai-htr/cmd.sh b/examples/openai-htr/cmd.sh index c5b2011..37e16f3 100755 --- a/examples/openai-htr/cmd.sh +++ b/examples/openai-htr/cmd.sh @@ -24,5 +24,5 @@ curl https://api.openai.com/v1/chat/completions \ ] } ], - "max_tokens": 50 + "max_tokens": '"$MAX_TOKENS"' }' | jq -r .choices[0].message.content