Initial commit for git.lain.church

This commit is contained in:
Bubblegumdrop 2024-09-09 20:58:41 -04:00
commit 28761a5fa2
12 changed files with 350 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
systems/
bin/

30
audio.lisp Normal file
View File

@ -0,0 +1,30 @@
(in-package #:cl-openai)
(defun make-audio/speech-json-data (model input voice &optional response-format speed)
(cl-json:encode-json-to-string
(remove nil
`(("model" . ,model)
("input" . ,input)
("voice" . ,voice)
,(when response-format `("response_format" . ,response-format))
,(when speed `("speed" . ,speed))))))
(defun audio/speech (model input voice &optional response-format speed)
(let ((json-data (make-audio/speech-json-data model input voice response-format speed))
(uri (server-path "v1/audio/speech")))
(apply #'drakma:http-request uri
(additional-api-args
:method :post
:content json-data))))
(defun save-audio (path response)
(with-open-file (f path :direction :output
:element-type '(unsigned-byte 8)
:if-exists :supersede
:if-does-not-exist :create)
(loop :for byte :across response
:do (write-byte byte f))))
(defun audio/speech-and-save (path model input voice &optional response-format speed)
(let ((response (audio/speech model input voice response-format speed)))
(save-audio path response)))

8
auth.lisp Normal file
View File

@ -0,0 +1,8 @@
(in-package #:cl-openai)
(defparameter +openai-api-key+
(string-trim '(#\Newline #\Return)
(uiop:read-file-string "~/.openai-api-key.txt")))
(defun bearer-auth ()
`((Authorization . ,(format nil "Bearer ~a" +openai-api-key+))))

41
cl-openai.asd Normal file
View File

@ -0,0 +1,41 @@
(asdf:defsystem "cl-openai"
:description "OpenAI interface for Common Lisp"
:author "Bubblegumdrop <staticsunn@gmail.com>"
:version "0.1.0"
:license "WTFPL 2+"
:defsystem-depends-on (:deploy)
:depends-on (:cl-json
:drakma)
:components ((:file "package")
(:file "auth")
(:file "server")
(:file "list-models")
(:file "audio")
(:file "prompt"))
:in-order-to ((test-op (test-op "cl-openai/tests")))
:build-pathname "cl-openai"
:entry-point "cl-openai:main"
:build-operation "deploy-op")
(asdf:defsystem "cl-openai/tests"
:description "Test system for cl-openai"
:author "Bubblegumdrop <staticsunn@gmail.com>"
:license "WTFPL 2+"
:depends-on ("cl-openai"
"rove")
:components ((:module "tests"
:components
(
(:file "cl-openai")
(:file "toolkit")
(:module "models"
:components
((:file "tags"))))))
:perform (asdf:test-op (op c) (symbol-call :rove :run c)))
;; https://lisp-journey.gitlab.io/blog/lisp-for-the-web-build-standalone-binaries-foreign-libraries-templates-static-assets/
;; (deploy:define-hook (:deploy asdf) (directory)
;; ;; Thanks again to Shinmera.
;; (declare (ignorable directory))
;; #+asdf (asdf:clear-source-registry)
;; #+asdf (defun asdf:upgrade-asdf () nil))

11
list-models.lisp Normal file
View File

@ -0,0 +1,11 @@
(in-package #:cl-openai)
;;;; https://platform.openai.com/docs/api-reference/models/list
;;;; https://github.com/edicl/drakma/issues/136
(defun models/list ()
(json-decode-http-request-to-string
(server-path "v1/models")))
(defun models/retrieve (model)
(json-decode-http-request-to-string
(server-path (format nil "v1/models/~a" model))))

11
package.lisp Normal file
View File

@ -0,0 +1,11 @@
(in-package #:cl-user)
(defpackage #:cl-openai
(:use #:cl)
(:local-nicknames (:cl-json :cl-json)
(:drakma :drakma))
(:export #:+openai-api-key+
#:+openai-base-url+
#:server-path
#:models/list
#:models/retrieve))

66
prompt.lisp Normal file
View File

@ -0,0 +1,66 @@
(in-package #:cl-openai)
(defun chat/completion-messages-to-prompts (model messages)
(cl-json:encode-json-to-string
(remove nil
`(("model" . ,model)
("messages" . ,messages)))))
(defun prompt (model messages)
(let ((json-data (chat/completion-messages-to-prompts model messages)))
(json-decode-http-request-to-string
(server-path "v1/chat/completions")
:content json-data
:method :post)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#|
(defclass chat-completion ()
((model :initarg :model :accessor model)
(messages :initarg :messages :accessor messages)
(response :initarg :response :accessor response)))
(defun create-chat-completion (model messages)
(make-instance 'chat-completion
:model model
:messages messages
:response nil))
(defun add-user-message (chat-completion user-message)
(push `(:role "user" :content ,user-message) (messages chat-completion)))
(defun add-assistant-response (chat-completion assistant-response)
(setf (response chat-completion) assistant-response)
(push `(:role "assistant" :content ,assistant-response) (messages chat-completion)))
(defun chat/completion-messages-to-prompts (chat-completion)
(let ((model (model chat-completion))
(messages (messages chat-completion)))
(cl-json:encode-json-to-string
(remove nil
`(("model" . ,model)
("messages" . ,messages))))))
(defun prompt (chat-completion)
(let ((json-data (chat/completion-messages-to-prompts chat-completion)))
(json-decode-http-request-to-string
(server-path "v1/chat/completions")
:content json-data
:method :post)))
;; Example usage:
(let ((chat (create-chat-completion "gpt-4o-mini"
'((:role "system" :content "You are a helpful assistant.")))))
(add-user-message chat "What is a LLM?")
(let ((response (prompt chat)))
(add-assistant-response chat response))
(add-user-message chat "Who won the world series in 2020?")
(let ((response (prompt chat)))
(add-assistant-response chat response))
(add-user-message chat "Where was it played?")
(let ((response (prompt chat)))
(add-assistant-response chat response))
;; Now you can access the chat history and responses
(format t "Chat history: ~a~%" (messages chat))
(format t "Last assistant response: ~a~%" (response chat)))
|#

27
readme.md Normal file
View File

@ -0,0 +1,27 @@
# Common Lisp OpenAI interface
We're currently using DRAKMA. Dexador is supported probably. Is there
something like Clack for http clients yet?
Anyway, it's an OpenAI client library. You can currently:
- Prompt
- Text To Speech (TTS)
- List available models
- Authenticate with bearer token
# Voices
Experiment with different voices:
- alloy
- echo
- fable
- onyx
- nova
# TODO
- Conversations API (WIP)
- Store conversations in local DB?
- Vision (WIP)

26
server.lisp Normal file
View File

@ -0,0 +1,26 @@
(in-package #:cl-openai)
(defvar +openai-base-uri+ "api.openai.com")
;; How to remove this "REMOVE NIL" instruction? I'm pretty sure I've
;; seen it before in this macro `(when ,thing ,@(thing)) thingy.
(defun additional-api-args (&rest args &key (content-type "application/json") &allow-other-keys)
(remove nil
`(:additional-headers ,(bearer-auth)
:content-type ,content-type
:external-format-in :utf-8
:external-format-out :utf-8
:force-binary t
,@args)))
(defun decode-json-from-octets-string (octets)
(cl-json:decode-json-from-string
(flex:octets-to-string octets)))
(defun json-decode-http-request-to-string (uri &rest args)
(decode-json-from-octets-string
(apply #'drakma:http-request uri
(apply #'additional-api-args args))))
(defun server-path (&optional path)
(format nil "https://~a~:[~;/~a~]" +openai-base-uri+ path path))

66
systems.csv Normal file
View File

@ -0,0 +1,66 @@
deploy, ghcr.io/ocicl/deploy@sha256:e08c14d46ca07126e19a447b27d948dfa2de2ee9ed9bd9e4d106db08990bb716, deploy-20240824-f9b41f3/deploy.asd
deploy-test, ghcr.io/ocicl/deploy@sha256:e08c14d46ca07126e19a447b27d948dfa2de2ee9ed9bd9e4d106db08990bb716, deploy-20240824-f9b41f3/deploy-test.asd
uffi, ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742, cffi-20240811-32c90d4/uffi-compat/uffi.asd
cffi, ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742, cffi-20240811-32c90d4/cffi.asd
cffi-uffi-compat, ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742, cffi-20240811-32c90d4/cffi-uffi-compat.asd
cffi-toolchain, ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742, cffi-20240811-32c90d4/cffi-toolchain.asd
cffi-tests, ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742, cffi-20240811-32c90d4/cffi-tests.asd
cffi-libffi, ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742, cffi-20240811-32c90d4/cffi-libffi.asd
cffi-grovel, ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742, cffi-20240811-32c90d4/cffi-grovel.asd
cffi-examples, ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742, cffi-20240811-32c90d4/cffi-examples.asd
alexandria, ghcr.io/ocicl/alexandria@sha256:e433c2e076ed3bcf8641b97b00192680db2201d305efac9293539dee88c7fbf7, alexandria-20240503-8514d8e/alexandria.asd
trivial-features, ghcr.io/ocicl/trivial-features@sha256:e278e24d39060fc7d3715531b16ddd9ab7f93f22ade53e436c0b86dbae3aa065, trivial-features-1.0/trivial-features.asd
trivial-features-tests, ghcr.io/ocicl/trivial-features@sha256:e278e24d39060fc7d3715531b16ddd9ab7f93f22ade53e436c0b86dbae3aa065, trivial-features-1.0/trivial-features-tests.asd
babel, ghcr.io/ocicl/babel@sha256:b505136744213e6b953913780a4b647da40e83818a10f41004846863b5037810, babel-20240606-23c1440/babel.asd
babel-tests, ghcr.io/ocicl/babel@sha256:b505136744213e6b953913780a4b647da40e83818a10f41004846863b5037810, babel-20240606-23c1440/babel-tests.asd
babel-streams, ghcr.io/ocicl/babel@sha256:b505136744213e6b953913780a4b647da40e83818a10f41004846863b5037810, babel-20240606-23c1440/babel-streams.asd
sha3, ghcr.io/ocicl/sha3@sha256:556fcc3d3fcba08185de62f7bb090fa233af4f8c68a4d7401992a32e03fb9a70, sha3-20240503-a4baa05/sha3.asd
multilang-documentation-utils, ghcr.io/ocicl/documentation-utils@sha256:b2a1b3f3bcd1a738af85ae2b0168d408c177661eab6d6bbebb254e394d983f54, documentation-utils-20230511-98630dd/multilang-documentation-utils.asd
documentation-utils, ghcr.io/ocicl/documentation-utils@sha256:b2a1b3f3bcd1a738af85ae2b0168d408c177661eab6d6bbebb254e394d983f54, documentation-utils-20230511-98630dd/documentation-utils.asd
trivial-indent, ghcr.io/ocicl/trivial-indent@sha256:f1ae624eb2ca37133912e9920587488ea6e2f1d6419ba4a1776e63c2bdff0fd9, trivial-indent-20240503-b5d490f/trivial-indent.asd
cl-json, ghcr.io/ocicl/cl-json@sha256:54c4d00901c2c5b0ea9da11eed8f0104fc5819e1ed9a29d1f3364503a720a868, cl-json-20240907-994dd38/cl-json.asd
drakma, ghcr.io/ocicl/drakma@sha256:9b9883fa280fae200d34951395011df3765ed73cfcebf551a44ff246a756b576, drakma-2.0.10/drakma.asd
drakma-test, ghcr.io/ocicl/drakma@sha256:9b9883fa280fae200d34951395011df3765ed73cfcebf551a44ff246a756b576, drakma-2.0.10/drakma-test.asd
puri, ghcr.io/ocicl/puri@sha256:f6aa091a4d8eb5bdc91466daddc90dadd5b0fcf247370df237a223dc0588f29d, puri-4bbab9/puri.asd
cl-base64, ghcr.io/ocicl/cl-base64@sha256:702412dbc1ed825e275fb23e22c29527eb786bf644e47c7621bf0dbb34e17c7e, cl-base64-20240503-80496b7/cl-base64.asd
cl-base64-tests, ghcr.io/ocicl/cl-base64@sha256:702412dbc1ed825e275fb23e22c29527eb786bf644e47c7621bf0dbb34e17c7e, cl-base64-20240503-80496b7/cl-base64-tests.asd
chunga, ghcr.io/ocicl/chunga@sha256:b3b986951e2fbd881f038194563c74b235705c4259e9206902e314fdd3933cb3, chunga-20240503-fab9bd3/chunga.asd
trivial-gray-streams, ghcr.io/ocicl/trivial-gray-streams@sha256:d0cc9fb73876100ee60647524f98b5b22566fa1c3a985d79548b0d2b228f8b51, trivial-gray-streams-20240503-a7ead68/trivial-gray-streams.asd
trivial-gray-streams-test, ghcr.io/ocicl/trivial-gray-streams@sha256:d0cc9fb73876100ee60647524f98b5b22566fa1c3a985d79548b0d2b228f8b51, trivial-gray-streams-20240503-a7ead68/trivial-gray-streams-test.asd
flexi-streams, ghcr.io/ocicl/flexi-streams@sha256:95005b06a8a95c82780c75ead53810bcb273d07fcf5fe76b527f1856df9923f2, flexi-streams-20240503-4951d57/flexi-streams.asd
flexi-streams-test, ghcr.io/ocicl/flexi-streams@sha256:95005b06a8a95c82780c75ead53810bcb273d07fcf5fe76b527f1856df9923f2, flexi-streams-20240503-4951d57/flexi-streams-test.asd
cl-ppcre, ghcr.io/ocicl/cl-ppcre@sha256:584907e0683621973579f397115945ef73e9d5b7afa77fae7cacecb3ad272f89, cl-ppcre-20240503-80fb19d/cl-ppcre.asd
cl-ppcre-unicode, ghcr.io/ocicl/cl-ppcre@sha256:584907e0683621973579f397115945ef73e9d5b7afa77fae7cacecb3ad272f89, cl-ppcre-20240503-80fb19d/cl-ppcre-unicode.asd
chipz, ghcr.io/ocicl/chipz@sha256:fae0fae0c93199ba57c92d9102245a55c8a2c12af4442e0b141d5670bef4f2f0, chipz-20240503-6f80368/chipz.asd
usocket, ghcr.io/ocicl/usocket@sha256:015b8cdb91cdc25aefd08054e8ede6a5d054d10bc87916904cf0d0670b3f4a68, usocket-0.8.8/usocket.asd
usocket-test, ghcr.io/ocicl/usocket@sha256:015b8cdb91cdc25aefd08054e8ede6a5d054d10bc87916904cf0d0670b3f4a68, usocket-0.8.8/usocket-test.asd
usocket-server, ghcr.io/ocicl/usocket@sha256:015b8cdb91cdc25aefd08054e8ede6a5d054d10bc87916904cf0d0670b3f4a68, usocket-0.8.8/usocket-server.asd
split-sequence, ghcr.io/ocicl/split-sequence@sha256:3a37662eedd99c42995587b9d443c4631f25c4c523091bcca31a27b880585b8e, split-sequence-2.0.1/split-sequence.asd
cl_plus_ssl.test, ghcr.io/ocicl/cl_plus_ssl@sha256:acb61e8e4d3efcb23f4d86405ad22fdca2d685268c664735c962646a09706ab6, cl-plus-ssl-20240505-17d5cdd/cl+ssl.test.asd
cl_plus_ssl, ghcr.io/ocicl/cl_plus_ssl@sha256:acb61e8e4d3efcb23f4d86405ad22fdca2d685268c664735c962646a09706ab6, cl-plus-ssl-20240505-17d5cdd/cl+ssl.asd
bordeaux-threads, ghcr.io/ocicl/bordeaux-threads@sha256:bbb32afe3987e102149cc019f4f7366a05f7a37d1503f5f86a27745e671c320a, bordeaux-threads-0.9.4/bordeaux-threads.asd
global-vars, ghcr.io/ocicl/global-vars@sha256:d197e871c9c9abc4bf31b1186f5fd28f0ca848ebe2e9dddf2d82ecee01dbdc65, global-vars-20240503-c749f32/global-vars.asd
global-vars-test, ghcr.io/ocicl/global-vars@sha256:d197e871c9c9abc4bf31b1186f5fd28f0ca848ebe2e9dddf2d82ecee01dbdc65, global-vars-20240503-c749f32/global-vars-test.asd
trivial-garbage, ghcr.io/ocicl/trivial-garbage@sha256:a85dcf4110ad60ae9f6c70970acceb2bf12402ce5326891643d35506059afb1d, trivial-garbage-20240503-3474f64/trivial-garbage.asd
dexador, ghcr.io/ocicl/dexador@sha256:538d1a96f5c090d4793fde903f343790eef50c3e9c64413ebd3ee77799221faf, dexador-20240711-d2717a4/dexador.asd
dexador-usocket, ghcr.io/ocicl/dexador@sha256:538d1a96f5c090d4793fde903f343790eef50c3e9c64413ebd3ee77799221faf, dexador-20240711-d2717a4/dexador-usocket.asd
dexador-test, ghcr.io/ocicl/dexador@sha256:538d1a96f5c090d4793fde903f343790eef50c3e9c64413ebd3ee77799221faf, dexador-20240711-d2717a4/dexador-test.asd
fast-http, ghcr.io/ocicl/fast-http@sha256:44e98b5239c0ded4921dc0b04ae272cff00583d93797a657543db782979eb50c, fast-http-20240503-2232fc9/fast-http.asd
fast-http-test, ghcr.io/ocicl/fast-http@sha256:44e98b5239c0ded4921dc0b04ae272cff00583d93797a657543db782979eb50c, fast-http-20240503-2232fc9/fast-http-test.asd
cl-utilities, ghcr.io/ocicl/cl-utilities@sha256:e5e0676a4e0627332a0fe64d56ed4f1890f0466d715a11e8d95561b4c2baa38f, cl-utilities-20240503-6b4de39/cl-utilities.asd
proc-parse, ghcr.io/ocicl/proc-parse@sha256:0880f9acb35eb9efbe1f77a981e36e84e8f29a22b14f680c7686eb381fa87bd6, proc-parse-20240503-3afe2b7/proc-parse.asd
proc-parse-test, ghcr.io/ocicl/proc-parse@sha256:0880f9acb35eb9efbe1f77a981e36e84e8f29a22b14f680c7686eb381fa87bd6, proc-parse-20240503-3afe2b7/proc-parse-test.asd
xsubseq, ghcr.io/ocicl/xsubseq@sha256:7605d14f7cc7fd2f63190ad81fe7bd65daef105d6728ee6bb59baef49da2aa51, xsubseq-20240503-5ce430b/xsubseq.asd
xsubseq-test, ghcr.io/ocicl/xsubseq@sha256:7605d14f7cc7fd2f63190ad81fe7bd65daef105d6728ee6bb59baef49da2aa51, xsubseq-20240503-5ce430b/xsubseq-test.asd
smart-buffer, ghcr.io/ocicl/smart-buffer@sha256:b8d194f5881c415fd7f0099b88dfd9e2158405c2966de15c716b155a364bf0f7, smart-buffer-20240503-619759d/smart-buffer.asd
smart-buffer-test, ghcr.io/ocicl/smart-buffer@sha256:b8d194f5881c415fd7f0099b88dfd9e2158405c2966de15c716b155a364bf0f7, smart-buffer-20240503-619759d/smart-buffer-test.asd
quri, ghcr.io/ocicl/quri@sha256:e2559f91600e4895e115b42dde88fcaac3677f051335d73431888dcf7af99f95, quri-0.7.0/quri.asd
quri-test, ghcr.io/ocicl/quri@sha256:e2559f91600e4895e115b42dde88fcaac3677f051335d73431888dcf7af99f95, quri-0.7.0/quri-test.asd
fast-io, ghcr.io/ocicl/fast-io@sha256:7ba35a0eddf00b3c25656b3c5a93e95460f6cb8f807afbc04ef4f50076d95aff, fast-io-20240503-a4c5ad6/fast-io.asd
fast-io-test, ghcr.io/ocicl/fast-io@sha256:7ba35a0eddf00b3c25656b3c5a93e95460f6cb8f807afbc04ef4f50076d95aff, fast-io-20240503-a4c5ad6/fast-io-test.asd
static-vectors, ghcr.io/ocicl/static-vectors@sha256:53e11e5689c3dbea6a3017760b55f052588003d774913539930ddc4330a69970, static-vectors-20240624-3d9d89b/static-vectors.asd
cl-cookie, ghcr.io/ocicl/cl-cookie@sha256:85cd8aa7f1379d041fae9530609cd68d5214fb978bc87faa7fd9ad5ad7e08a83, cl-cookie-20240703-6bcb74a/cl-cookie.asd
cl-cookie-test, ghcr.io/ocicl/cl-cookie@sha256:85cd8aa7f1379d041fae9530609cd68d5214fb978bc87faa7fd9ad5ad7e08a83, cl-cookie-20240703-6bcb74a/cl-cookie-test.asd
local-time, ghcr.io/ocicl/local-time@sha256:f6b11fc15cf92adb87a847d3af918ada947c2648660e74133db9183e7da0db70, local-time-20240817-5a09552/local-time.asd
cl-postgres_plus_local-time, ghcr.io/ocicl/local-time@sha256:f6b11fc15cf92adb87a847d3af918ada947c2648660e74133db9183e7da0db70, local-time-20240817-5a09552/cl-postgres+local-time.asd
trivial-mimes, ghcr.io/ocicl/trivial-mimes@sha256:b33ae6d62bcd666d046e4ae1625b8e8b46a548fe2c4f18b4899ce1ecf581c17b, trivial-mimes-20240503-1a80193/trivial-mimes.asd
1 deploy ghcr.io/ocicl/deploy@sha256:e08c14d46ca07126e19a447b27d948dfa2de2ee9ed9bd9e4d106db08990bb716 deploy-20240824-f9b41f3/deploy.asd
2 deploy-test ghcr.io/ocicl/deploy@sha256:e08c14d46ca07126e19a447b27d948dfa2de2ee9ed9bd9e4d106db08990bb716 deploy-20240824-f9b41f3/deploy-test.asd
3 uffi ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742 cffi-20240811-32c90d4/uffi-compat/uffi.asd
4 cffi ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742 cffi-20240811-32c90d4/cffi.asd
5 cffi-uffi-compat ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742 cffi-20240811-32c90d4/cffi-uffi-compat.asd
6 cffi-toolchain ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742 cffi-20240811-32c90d4/cffi-toolchain.asd
7 cffi-tests ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742 cffi-20240811-32c90d4/cffi-tests.asd
8 cffi-libffi ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742 cffi-20240811-32c90d4/cffi-libffi.asd
9 cffi-grovel ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742 cffi-20240811-32c90d4/cffi-grovel.asd
10 cffi-examples ghcr.io/ocicl/cffi@sha256:fe1246d11c4c067daefdb143e1252e0f3e99046909185d2c920adb8323318742 cffi-20240811-32c90d4/cffi-examples.asd
11 alexandria ghcr.io/ocicl/alexandria@sha256:e433c2e076ed3bcf8641b97b00192680db2201d305efac9293539dee88c7fbf7 alexandria-20240503-8514d8e/alexandria.asd
12 trivial-features ghcr.io/ocicl/trivial-features@sha256:e278e24d39060fc7d3715531b16ddd9ab7f93f22ade53e436c0b86dbae3aa065 trivial-features-1.0/trivial-features.asd
13 trivial-features-tests ghcr.io/ocicl/trivial-features@sha256:e278e24d39060fc7d3715531b16ddd9ab7f93f22ade53e436c0b86dbae3aa065 trivial-features-1.0/trivial-features-tests.asd
14 babel ghcr.io/ocicl/babel@sha256:b505136744213e6b953913780a4b647da40e83818a10f41004846863b5037810 babel-20240606-23c1440/babel.asd
15 babel-tests ghcr.io/ocicl/babel@sha256:b505136744213e6b953913780a4b647da40e83818a10f41004846863b5037810 babel-20240606-23c1440/babel-tests.asd
16 babel-streams ghcr.io/ocicl/babel@sha256:b505136744213e6b953913780a4b647da40e83818a10f41004846863b5037810 babel-20240606-23c1440/babel-streams.asd
17 sha3 ghcr.io/ocicl/sha3@sha256:556fcc3d3fcba08185de62f7bb090fa233af4f8c68a4d7401992a32e03fb9a70 sha3-20240503-a4baa05/sha3.asd
18 multilang-documentation-utils ghcr.io/ocicl/documentation-utils@sha256:b2a1b3f3bcd1a738af85ae2b0168d408c177661eab6d6bbebb254e394d983f54 documentation-utils-20230511-98630dd/multilang-documentation-utils.asd
19 documentation-utils ghcr.io/ocicl/documentation-utils@sha256:b2a1b3f3bcd1a738af85ae2b0168d408c177661eab6d6bbebb254e394d983f54 documentation-utils-20230511-98630dd/documentation-utils.asd
20 trivial-indent ghcr.io/ocicl/trivial-indent@sha256:f1ae624eb2ca37133912e9920587488ea6e2f1d6419ba4a1776e63c2bdff0fd9 trivial-indent-20240503-b5d490f/trivial-indent.asd
21 cl-json ghcr.io/ocicl/cl-json@sha256:54c4d00901c2c5b0ea9da11eed8f0104fc5819e1ed9a29d1f3364503a720a868 cl-json-20240907-994dd38/cl-json.asd
22 drakma ghcr.io/ocicl/drakma@sha256:9b9883fa280fae200d34951395011df3765ed73cfcebf551a44ff246a756b576 drakma-2.0.10/drakma.asd
23 drakma-test ghcr.io/ocicl/drakma@sha256:9b9883fa280fae200d34951395011df3765ed73cfcebf551a44ff246a756b576 drakma-2.0.10/drakma-test.asd
24 puri ghcr.io/ocicl/puri@sha256:f6aa091a4d8eb5bdc91466daddc90dadd5b0fcf247370df237a223dc0588f29d puri-4bbab9/puri.asd
25 cl-base64 ghcr.io/ocicl/cl-base64@sha256:702412dbc1ed825e275fb23e22c29527eb786bf644e47c7621bf0dbb34e17c7e cl-base64-20240503-80496b7/cl-base64.asd
26 cl-base64-tests ghcr.io/ocicl/cl-base64@sha256:702412dbc1ed825e275fb23e22c29527eb786bf644e47c7621bf0dbb34e17c7e cl-base64-20240503-80496b7/cl-base64-tests.asd
27 chunga ghcr.io/ocicl/chunga@sha256:b3b986951e2fbd881f038194563c74b235705c4259e9206902e314fdd3933cb3 chunga-20240503-fab9bd3/chunga.asd
28 trivial-gray-streams ghcr.io/ocicl/trivial-gray-streams@sha256:d0cc9fb73876100ee60647524f98b5b22566fa1c3a985d79548b0d2b228f8b51 trivial-gray-streams-20240503-a7ead68/trivial-gray-streams.asd
29 trivial-gray-streams-test ghcr.io/ocicl/trivial-gray-streams@sha256:d0cc9fb73876100ee60647524f98b5b22566fa1c3a985d79548b0d2b228f8b51 trivial-gray-streams-20240503-a7ead68/trivial-gray-streams-test.asd
30 flexi-streams ghcr.io/ocicl/flexi-streams@sha256:95005b06a8a95c82780c75ead53810bcb273d07fcf5fe76b527f1856df9923f2 flexi-streams-20240503-4951d57/flexi-streams.asd
31 flexi-streams-test ghcr.io/ocicl/flexi-streams@sha256:95005b06a8a95c82780c75ead53810bcb273d07fcf5fe76b527f1856df9923f2 flexi-streams-20240503-4951d57/flexi-streams-test.asd
32 cl-ppcre ghcr.io/ocicl/cl-ppcre@sha256:584907e0683621973579f397115945ef73e9d5b7afa77fae7cacecb3ad272f89 cl-ppcre-20240503-80fb19d/cl-ppcre.asd
33 cl-ppcre-unicode ghcr.io/ocicl/cl-ppcre@sha256:584907e0683621973579f397115945ef73e9d5b7afa77fae7cacecb3ad272f89 cl-ppcre-20240503-80fb19d/cl-ppcre-unicode.asd
34 chipz ghcr.io/ocicl/chipz@sha256:fae0fae0c93199ba57c92d9102245a55c8a2c12af4442e0b141d5670bef4f2f0 chipz-20240503-6f80368/chipz.asd
35 usocket ghcr.io/ocicl/usocket@sha256:015b8cdb91cdc25aefd08054e8ede6a5d054d10bc87916904cf0d0670b3f4a68 usocket-0.8.8/usocket.asd
36 usocket-test ghcr.io/ocicl/usocket@sha256:015b8cdb91cdc25aefd08054e8ede6a5d054d10bc87916904cf0d0670b3f4a68 usocket-0.8.8/usocket-test.asd
37 usocket-server ghcr.io/ocicl/usocket@sha256:015b8cdb91cdc25aefd08054e8ede6a5d054d10bc87916904cf0d0670b3f4a68 usocket-0.8.8/usocket-server.asd
38 split-sequence ghcr.io/ocicl/split-sequence@sha256:3a37662eedd99c42995587b9d443c4631f25c4c523091bcca31a27b880585b8e split-sequence-2.0.1/split-sequence.asd
39 cl_plus_ssl.test ghcr.io/ocicl/cl_plus_ssl@sha256:acb61e8e4d3efcb23f4d86405ad22fdca2d685268c664735c962646a09706ab6 cl-plus-ssl-20240505-17d5cdd/cl+ssl.test.asd
40 cl_plus_ssl ghcr.io/ocicl/cl_plus_ssl@sha256:acb61e8e4d3efcb23f4d86405ad22fdca2d685268c664735c962646a09706ab6 cl-plus-ssl-20240505-17d5cdd/cl+ssl.asd
41 bordeaux-threads ghcr.io/ocicl/bordeaux-threads@sha256:bbb32afe3987e102149cc019f4f7366a05f7a37d1503f5f86a27745e671c320a bordeaux-threads-0.9.4/bordeaux-threads.asd
42 global-vars ghcr.io/ocicl/global-vars@sha256:d197e871c9c9abc4bf31b1186f5fd28f0ca848ebe2e9dddf2d82ecee01dbdc65 global-vars-20240503-c749f32/global-vars.asd
43 global-vars-test ghcr.io/ocicl/global-vars@sha256:d197e871c9c9abc4bf31b1186f5fd28f0ca848ebe2e9dddf2d82ecee01dbdc65 global-vars-20240503-c749f32/global-vars-test.asd
44 trivial-garbage ghcr.io/ocicl/trivial-garbage@sha256:a85dcf4110ad60ae9f6c70970acceb2bf12402ce5326891643d35506059afb1d trivial-garbage-20240503-3474f64/trivial-garbage.asd
45 dexador ghcr.io/ocicl/dexador@sha256:538d1a96f5c090d4793fde903f343790eef50c3e9c64413ebd3ee77799221faf dexador-20240711-d2717a4/dexador.asd
46 dexador-usocket ghcr.io/ocicl/dexador@sha256:538d1a96f5c090d4793fde903f343790eef50c3e9c64413ebd3ee77799221faf dexador-20240711-d2717a4/dexador-usocket.asd
47 dexador-test ghcr.io/ocicl/dexador@sha256:538d1a96f5c090d4793fde903f343790eef50c3e9c64413ebd3ee77799221faf dexador-20240711-d2717a4/dexador-test.asd
48 fast-http ghcr.io/ocicl/fast-http@sha256:44e98b5239c0ded4921dc0b04ae272cff00583d93797a657543db782979eb50c fast-http-20240503-2232fc9/fast-http.asd
49 fast-http-test ghcr.io/ocicl/fast-http@sha256:44e98b5239c0ded4921dc0b04ae272cff00583d93797a657543db782979eb50c fast-http-20240503-2232fc9/fast-http-test.asd
50 cl-utilities ghcr.io/ocicl/cl-utilities@sha256:e5e0676a4e0627332a0fe64d56ed4f1890f0466d715a11e8d95561b4c2baa38f cl-utilities-20240503-6b4de39/cl-utilities.asd
51 proc-parse ghcr.io/ocicl/proc-parse@sha256:0880f9acb35eb9efbe1f77a981e36e84e8f29a22b14f680c7686eb381fa87bd6 proc-parse-20240503-3afe2b7/proc-parse.asd
52 proc-parse-test ghcr.io/ocicl/proc-parse@sha256:0880f9acb35eb9efbe1f77a981e36e84e8f29a22b14f680c7686eb381fa87bd6 proc-parse-20240503-3afe2b7/proc-parse-test.asd
53 xsubseq ghcr.io/ocicl/xsubseq@sha256:7605d14f7cc7fd2f63190ad81fe7bd65daef105d6728ee6bb59baef49da2aa51 xsubseq-20240503-5ce430b/xsubseq.asd
54 xsubseq-test ghcr.io/ocicl/xsubseq@sha256:7605d14f7cc7fd2f63190ad81fe7bd65daef105d6728ee6bb59baef49da2aa51 xsubseq-20240503-5ce430b/xsubseq-test.asd
55 smart-buffer ghcr.io/ocicl/smart-buffer@sha256:b8d194f5881c415fd7f0099b88dfd9e2158405c2966de15c716b155a364bf0f7 smart-buffer-20240503-619759d/smart-buffer.asd
56 smart-buffer-test ghcr.io/ocicl/smart-buffer@sha256:b8d194f5881c415fd7f0099b88dfd9e2158405c2966de15c716b155a364bf0f7 smart-buffer-20240503-619759d/smart-buffer-test.asd
57 quri ghcr.io/ocicl/quri@sha256:e2559f91600e4895e115b42dde88fcaac3677f051335d73431888dcf7af99f95 quri-0.7.0/quri.asd
58 quri-test ghcr.io/ocicl/quri@sha256:e2559f91600e4895e115b42dde88fcaac3677f051335d73431888dcf7af99f95 quri-0.7.0/quri-test.asd
59 fast-io ghcr.io/ocicl/fast-io@sha256:7ba35a0eddf00b3c25656b3c5a93e95460f6cb8f807afbc04ef4f50076d95aff fast-io-20240503-a4c5ad6/fast-io.asd
60 fast-io-test ghcr.io/ocicl/fast-io@sha256:7ba35a0eddf00b3c25656b3c5a93e95460f6cb8f807afbc04ef4f50076d95aff fast-io-20240503-a4c5ad6/fast-io-test.asd
61 static-vectors ghcr.io/ocicl/static-vectors@sha256:53e11e5689c3dbea6a3017760b55f052588003d774913539930ddc4330a69970 static-vectors-20240624-3d9d89b/static-vectors.asd
62 cl-cookie ghcr.io/ocicl/cl-cookie@sha256:85cd8aa7f1379d041fae9530609cd68d5214fb978bc87faa7fd9ad5ad7e08a83 cl-cookie-20240703-6bcb74a/cl-cookie.asd
63 cl-cookie-test ghcr.io/ocicl/cl-cookie@sha256:85cd8aa7f1379d041fae9530609cd68d5214fb978bc87faa7fd9ad5ad7e08a83 cl-cookie-20240703-6bcb74a/cl-cookie-test.asd
64 local-time ghcr.io/ocicl/local-time@sha256:f6b11fc15cf92adb87a847d3af918ada947c2648660e74133db9183e7da0db70 local-time-20240817-5a09552/local-time.asd
65 cl-postgres_plus_local-time ghcr.io/ocicl/local-time@sha256:f6b11fc15cf92adb87a847d3af918ada947c2648660e74133db9183e7da0db70 local-time-20240817-5a09552/cl-postgres+local-time.asd
66 trivial-mimes ghcr.io/ocicl/trivial-mimes@sha256:b33ae6d62bcd666d046e4ae1625b8e8b46a548fe2c4f18b4899ce1ecf581c17b trivial-mimes-20240503-1a80193/trivial-mimes.asd

42
vision.lisp Normal file
View File

@ -0,0 +1,42 @@
(in-package #:cl-openai)
#|
payload = {
"model": "gpt-4o-mini",
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Whats in this image?"
},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{base64_image}"
}
}
]
}
],
"max_tokens": 300
}
The Chat Completions API, unlike the Assistants API, is not stateful. That means you have to manage the messages (including images) you pass to the model yourself. If you want to pass the same image to the model multiple times, you will have to pass the image each time you make a request to the API.
For long running conversations, we suggest passing images via URL's instead of base64. The latency of the model can also be improved by downsizing your images ahead of time to be less than the maximum size they are expected them to be. For low res mode, we expect a 512px x 512px image. For high res mode, the short side of the image should be less than 768px and the long side should be less than 2,000px.
|#
(defun read-binary-file (filespec)
(with-open-file (stream filespec
:element-type '(unsigned-byte 8))
(let ((buffer (make-array (file-length stream)
:element-type '(unsigned-byte 8))))
(read-sequence buffer stream) buffer)))
(defun base64-stream-string (filespec)
(let ((binary-data (read-binary-file filespec)))
(with-output-to-string (s)
(base64:usb8-array-to-base64-stream binary-data s))))

20
whisper.lisp Normal file
View File

@ -0,0 +1,20 @@
(in-package #:cl-openai)
#|
curl --request POST \
--url https://api.openai.com/v1/audio/transcriptions \
--header "Authorization: Bearer $OPENAI_API_KEY" \
--header 'Content-Type: multipart/form-data' \
--form file=@/path/to/file/audio.mp3 \
--form model=whisper-1
|#
(defun transcribe-audio (file &optional (model "whisper-1"))
(let ((args `(:method :post
:content-type "multipart/form-data"
:parameters (("file" . ,file)
("model" . ,model))))
(uri (server-path "v1/audio/transcriptions")))
(decode-json-from-octets-string
(apply #'drakma:http-request uri
(apply #'additional-api-args args)))))