RSS Amplifier

Mark Watson’s Artificial Intelligence Books and Blog · Aug 24, 2025

Gerbil Scheme OpenAI, Google Gemini, and Ollama Local Model Clients

0
Sign in to vote or save

Mark Watson · Mark Watson’s Artificial Intelligence Books and Blog

Gerbil Scheme is a modern Lisp with a “batteries included” library. Here we look at three simple examples that demonstrate network IO and handling JSON responses.

September 19, 2025 update: I have released a book about Gerbil Scheme: Gerbil Scheme in Action - AI Applications, Network Programming, and Utilities

Let’s start with local model (Ollama must be installed and ‘ollama serve’ should be running):

(import :std/net/request :std/text/json)
(export ollama)
(def (ollama prompt
             model: (model "gemma3:latest")) ;; "gpt-oss:20b")) ;; "qwen3:0.6b"))
  (let* ((endpoint "http://localhost:11434/api/generate")
         (headers '(("Content-Type". "application/json")))
         (body-data
           (list->hash-table
             `(("model". ,model) ("prompt". ,prompt) ("stream". #f))))
         (body-string (json-object->string body-data)))
    (let ((response
            (http-post endpoint headers: headers data: body-string)))
      (if (= (request-status response) 200)
          (let* ((response-json (request-json response)))
            ;;(displayln (hash-keys response-json))
            (hash-ref response-json 'response))
          (error "Ollama API request failed"
                 status: (request-status response)
                 body: (request-text response))))))
;;  (ollama "why is the sky blue? Be very concise.")

You would run this example using:

$ gcx ollama.ss
$ gxi
Gerbil v0.18.1-78-gc5546da0 on Gambit v4.9.5-124-g6d1a9a9b
> (import :ollama/ollama)
> (ollama "why is the sky blue?")
"The blue color of the sky is a...."

The Gemini example is similar except the web service call must be authenticated:

;; File gemini.ss
(import :std/net/request
        :std/text/json)
(export gemini)
(def uri2 "https://generativelanguage.googleapis.com/v1beta/models/")
(def (gemini prompt
             model: (model "gemini-2.5-flash")
             system-prompt:
             (system-prompt "You are a helpful assistant."))
     (let ((api-key (get-environment-variable "GOOGLE_API_KEY")))
       (unless api-key
         (error "GEMINI_API_KEY environment variable not set."))
       (let* ((headers `(("Content-Type". "application/json")
                         ("x-goog-api-key". ,api-key)))
              (body-data
               (list->hash-table
                `(("contents".
                   ,(list
                      (list->hash-table
                         `(("role". "user")
                           ("parts".
                             ,(list
                               (list->hash-table
                                `(("text". ,prompt))))))))))))
              (body-string (json-object->string body-data))
              (endpoint
               (string-append
                 uri2
                 model ":generateContent?key=" api-key)))
         (let ((response
                (http-post
                  endpoint headers: headers data: body-string)))
           (if (= (request-status response) 200)
               (let* ((response-json (request-json response))
                      (candidate
                        (car (hash-ref response-json 'candidates)))
                      (content (hash-ref candidate 'content))
                      (p1 (car (hash-ref content 'parts))))
                 (hash-ref p1 'text)))))))
;;   (gemini "why is the sky blue? be very concise")

The OpenAI example is similar:

(import :std/net/request
        :std/text/json)
(export openai)
(def (openai
       prompt
       model: (model "gpt-5-mini")
       system-prompt: (system-prompt "You are a helpful assistant."))
     (let ((api-key (get-environment-variable "OPENAI_API_KEY")))
    (unless api-key
      (error "OPENAI_API_KEY environment variable not set."))
    (let* ((headers `(("Content-Type". "application/json")
                      ("Authorization".
                       ,(string-append "Bearer " api-key))))
           (body-data
            (list->hash-table
             `(("model". ,model)
               ("messages".
                ,(list
                   (list->hash-table
                    `(("role". "system")
                      ("content". ,system-prompt)))
                   (list->hash-table `(("role". "user")
                                       ("content". ,prompt))))))))
           (body-string (json-object->string body-data))
           (endpoint "https://api.openai.com/v1/chat/completions"))
      (let ((response
              (http-post
                endpoint headers: headers data: body-string)))
        (if (= (request-status response) 200)
            (let* ((response-json (request-json response))
                   (choices (hash-ref response-json 'choices))
                   (first-choice (and (pair? choices) (car choices)))
                   (message (hash-ref first-choice 'message))
                   (content (hash-ref message 'content)))
              content)
            (error "OpenAI API request failed"
                   status: (request-status response)
                   body: (request-text response)))))))
;;  (openai "why is the sky blue? be very concise")

Gerbil Scheme is useful for general network and concurrent programming tasks.

No posts

Read the original on marklwatson.substack.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.