Last active
October 9, 2024 07:02
-
-
Save ikitommi/e643713719c3620f943ef34086451c69 to your computer and use it in GitHub Desktop.
OpenAI API Structured Outputs in Clojure with Malli
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns summer.demo | |
(:require [summer.openai :as openai])) | |
(def Step | |
[:map | |
[:explanation :string] | |
[:output :string]]) | |
(def MathResponse | |
[:map {:name "mathresponse"} | |
[:steps [:vector Step]] | |
[:final_answer :string]]) | |
(openai/completion | |
{:model "gpt-4o-2024-08-06", | |
:messages [{:role "system", | |
:content "You are a helpful math tutor. Only use the schema for math responses."}, | |
{:role "user" | |
:content "how can I solve 8x + 7 = -23"}] | |
:response_format (openai/json-schema-response MathResponse)}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns summer.openai | |
(:require [hato.client :as c] | |
[jsonista.core :as j] | |
[malli.core :as m] | |
[malli.json-schema :as json-schema] | |
[malli.util :as mu])) | |
(defn <-json [x] | |
(j/read-value x j/keyword-keys-object-mapper)) | |
(defn <-response [response] | |
(update response :choices (partial mapv #(update-in % [:message :content] <-json)))) | |
(defn json-schema-response [?schema] | |
(let [schema (mu/closed-schema ?schema)] | |
{:type "json_schema" | |
:json_schema {:name (some-> schema (m/properties) :name (or "response")) | |
:schema (json-schema/transform schema) | |
:strict true}})) | |
(defn completion [data] | |
(-> (c/post "https://api.openai.com/v1/chat/completions" | |
{:headers {"Content-Type" "application/json" | |
"Authorization" (str "Bearer " (System/getenv "OPENAI_API_KEY"))} | |
:body (j/write-value-as-string data)}) | |
:body | |
(<-json) | |
(<-response))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{:steps [{:explanation "Start by isolating the term with x. Subtract 7 from both sides of the equation to do this.", | |
:output "8x + 7 - 7 = -23 - 7"} | |
{:explanation "Simplify both sides of the equation. On the left side, 7 - 7 cancels out, and on the right side, -23 - 7 equals -30.", | |
:output "8x = -30"} | |
{:explanation "To solve for x, divide both sides of the equation by 8.", | |
:output "8x/8 = -30/8"} | |
{:explanation "Simplify the right side by performing the division.", | |
:output "x = -3.75"}], | |
:final_answer "x = -3.75"} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice. Got some inspiration to implement one mindmapping graph idea I have wanted to try: https://github.com/tkataja/bb-malli-openai-mindmap
Using recursive Malli schemas etc. was really powerful here.