2 Using Large Language Models from Clojure
ns llms
(:require
(:as hk-client]
[org.httpkit.client :as json])) [cheshire.core
LLMs often come as APIs, as they require computing power (GPUs), which most users do not have locally. OpenAI offers their models behind an (paid) API for example. In the following we will see three different ways to use the GPT-4 model from OpenAI
Get the openai API key either from environment or a specific file
def open-ai-key
(or (System/getenv "OPEN_AI_KEY")
(slurp "open_ai_secret.txt")
(
) )
2.1 Use OpenAI API directly
OpenAI offers a rather simple API, text-in text-out for “chatting” with GPT
The following shows how to ask a simple question, and getting the answer using an http library, http-kit. The API is based on JSON, so easy to use from Clojure
->
("https://api.openai.com/v1/chat/completions"
@(hk-client/post :headers
{"content-type" "application/json"
{"authorization" (format "Bearer %s" open-ai-key)}
:body
(json/encode:model "gpt-4"
{:messages [{:role "system",
:content "You are a helpful assistant."},
:role "user",
{:content "What is Clojure ?"}]})})
:body
keyword)) (json/decode
:id "chatcmpl-AeLIWh2l733ziLLu6CJoxPXDTPTD4",
{:object "chat.completion",
:created 1734178352,
:model "gpt-4-0613",
:choices
:index 0,
[{:message
:role "assistant",
{:content
"Clojure is a modern, dynamic, and functional dialect of the Lisp programming language on the Java platform. It is designed to be a general-purpose language, combining the approachability and interactive development of a scripting language with an efficient and robust infrastructure for multithreaded programming. \n\nClojure features a rich set of immutable, persistent data structures, first-class functions and dynamic typing. It supports a software transactional memory system and promotes a functional programming style. It is widely used for a variety of tasks, from web development to data analysis and artificial intelligence.",
:refusal nil},
:logprobs nil,
:finish_reason "stop"}],
:usage
:prompt_tokens 22,
{:completion_tokens 111,
:total_tokens 133,
:prompt_tokens_details {:cached_tokens 0, :audio_tokens 0},
:completion_tokens_details
:reasoning_tokens 0,
{:audio_tokens 0,
:accepted_prediction_tokens 0,
:rejected_prediction_tokens 0}},
:system_fingerprint nil}
2.2 use Bosquet
Bosquet abstracts some of the concepts of LLMs on a higher level API. Its has further notions of “memory” and “tools” and has other features we find for example in python “LangChain”
Bosque wants the API key in a config file
"secrets.edn"
(spit pr-str
(:openai {:api-key open-ai-key}})) {
nil
require '[bosquet.llm.generator :refer [generate llm]]) (
Call GPT from Bosquet
(generate:user "What is Clojure"]
[[:assistant (llm :openai
[:llm/model-params {:model :gpt-4
})]])
:bosquet{:conversation
#:user "What is Clojure"]
[[:assistant
["Clojure is a high-level, dynamic, functional programming language. It is designed to be a general-purpose language, combining the approachability and interactive development of a scripting language with an efficient and robust infrastructure for multithreaded programming. Clojure is a dialect of Lisp, and shares with Lisp the code-as-data philosophy and a powerful macro system. It runs on the Java Virtual Machine (JVM), the Common Language Runtime (CLR), and JavaScript platforms."]],
:completions
nil
{"Clojure is a high-level, dynamic, functional programming language. It is designed to be a general-purpose language, combining the approachability and interactive development of a scripting language with an efficient and robust infrastructure for multithreaded programming. Clojure is a dialect of Lisp, and shares with Lisp the code-as-data philosophy and a powerful macro system. It runs on the Java Virtual Machine (JVM), the Common Language Runtime (CLR), and JavaScript platforms."},
:usage
nil {:prompt 11, :completion 92, :total 103},
{:bosquet/total {:prompt 11, :completion 92, :total 103}},
:time 3790}
2.3 Use langchain4j
We can use LLMs as well via a Java Interop and the library lnagchain4j which aims to be a copy of the python library langchain, and offers support or building blocks for several concepts around LLMs (model, vector stores, document loaders, etc.) We see it used in the following chapters
import '[dev.langchain4j.model.openai OpenAiChatModel OpenAiChatModelName]) (
dev.langchain4j.model.openai.OpenAiChatModelName
For now just the simplest call to an GPT model, asking it the same question:
def open-ai-chat-model
(
(.. (OpenAiChatModel/builder)
(apiKey open-ai-key)
(modelName OpenAiChatModelName/GPT_4) build))
"What is Clojure ?") (.generate open-ai-chat-model
"Clojure is a modern, dynamic, and functional dialect of the Lisp programming language on the Java platform. It is designed to be a general-purpose language, combining the approachability and interactive development of a scripting language with an efficient and robust infrastructure for multithreaded programming."