見出し画像

LispからGPT-4を呼び出してリスト処理の基礎を体験する

そもそも目的はLispを使って初心者にもプログラミングを教えることであった。それが本当に正しいことなのかはともかく、僕も多少は実用的にLispを使ってみたいのでLispで遊ぶには合目的的である。

Claude-3と30分くらいすったもんだしていたらコードが出来上がった。

(defun generate-text (prompt &key (max-tokens 100) (json-mode nil))
  (let* ((api-key (uiop:getenv "OPENAI_API_KEY"))
         (url "https://api.openai.com/v1/chat/completions")
         (headers `(("Content-Type" . "application/json")
                    ("Authorization" . ,(format nil "Bearer ~A" api-key))))
         (data `(("model" . "gpt-4-1106-preview")
                 ("messages" . (,(if json-mode
                                     '(("role" . "system")
                                       ("content" . "あなたは返答をすべてJSON形式で出力します。"))
                                     '(("role" . "system")
                                       ("content" . "You are a helpful assistant.")))
                                (("role" . "user")
                                 ("content" . ,prompt))))
                 ("max_tokens" . ,max-tokens)
                 ("temperature" . 0)
                 ,(if json-mode
                      '("response_format" . (("type" . "json_object")))
                      ())))
         (response (handler-case
                       (dex:post url :headers headers :content (json:encode-json-to-string data) :force-string t)
                     (dex:http-request-failed (e)
                       (format t "HTTP request failed: ~A~%" e)
                       (return-from generate-text nil))))
         (response-json (handler-case
                            (json:decode-json-from-string response)
                          (error (e)
                            (format t "Error parsing JSON response: ~A~%" e)
                            (return-from generate-text nil)))))
    (if json-mode
        (let ((json-response (cdr (assoc :content (cdr (assoc :message (car (cdr (assoc :choices response-json)))))))))
          (json:decode-json-from-string json-response))
        (cdr (assoc :content (cdr (assoc :message (car (cdr (assoc :choices response-json))))))))))

僕はLisp初心者なので、何をしてるのかはわからん。これを読むのもまた楽しいのである。
ちなみにコツはPythonコードを見せて「これをLispにしろ」と言うことだった。たぶん最初からそうすれば一発でできた。

これを使うにはこうする

(generate-text "Lispの楽しさをJSONで説明して" :max-tokens 1000 :json-mode t)

するとこんな感じのが返ってきた


((*LISP--*FUN--*FACTORS
  (*CODE--AS--*DATA
   . Lispのコードはリストとして表現され、データとして扱うことができるため、プログラム自体を簡単に操作・変更することができます。)
  (*MACROS . マクロを使用すると、コード生成や言語の拡張が可能になり、非常に強力な抽象化を行うことができます。)
  (*INTERACTIVE--*DEVELOPMENT
   . REPL(Read-Eval-Print Loop)を使用すると、コードの断片を即座に評価し、結果を確認しながら開発を進めることができます。)
  (*FUNCTIONAL--*PROGRAMMING
   . 関数型プログラミングの概念を採用しているため、不変性や関数の第一級オブジェクトとしての扱いにより、バグの少ないコードを書くことができます。)
  (*SIMPLICITY . シンプルな構文と少数の構成要素でプログラムを構築することができ、その結果、コードが読みやすく、保守しやすくなります。)
  (*COMMUNITY--AND--*HISTORY
   . 長い歴史を持ち、熱心なコミュニティによって支えられているため、豊富なリソースと知識が共有されています。)
  (*EXTENSIBILITY . システムを柔軟に拡張できるため、特定の問題に合わせて言語自体をカスタマイズすることが可能です。)
  (*EFFICIENCY . 最適化されたLisp実装では、高いパフォーマンスを実現することができます。)
  (*MULTI--*PARADIGM
   . 複数のプログラミングパラダイム(手続き型、オブジェクト指向、関数型など)をサポートしており、柔軟なアプローチが可能です。)
  (*RICH--*LIBRARIES . 豊富なライブラリが利用可能であり、様々なタスクを容易に実行できます。)))

これ自体がLispのリストになっているので、Lispでコネコネできる
Lispのリスト操作の基本中の基本はcarカーcdrクダラだ。

グローバル変数に保存してcar、cdrしてみる。
carは、「リストの先頭を取り出す」命令で、cdrは「リストの先頭以外を取り出す」命令である。

(defvar *result* nil)
(setf *result* (generate-text "Lispの楽しさをJSONで説明して" :max-tokens 1000 :json-mode t))

これで以下のリストがグローバル変数の*result*に入る

((*LISP--*FUN--*FACTORS
  (*EXPRESSIVENESS . Lispの構文は非常に表現力があり、プログラマーが思考を直接的にコードに変換することを可能にします。)
  (*MACROS . Lispのマクロシステムはコードを生成するコードを書くことを可能にし、非常に強力な抽象化を実現します。)
  (*CODE--AS--*DATA . Lispではコードがデータとして扱われる(ホモイコニック)、これによりコードの変換や解析が容易になります。)
  (*INTERACTIVE--*DEVELOPMENT
   . REPL(Read-Eval-Print Loop)を使用したインタラクティブな開発プロセスは、即時フィードバックを提供し、実験的な開発を促進します。)
  (*FLEXIBILITY . Lispは非常に柔軟で、新しい言語機能やパラダイムを簡単に組み込むことができます。)
  (*COMMUNITY . Lispコミュニティは熱心で、多くのリソース、ライブラリ、サポートが利用可能です。)
  (*HISTORY . Lispは長い歴史を持つ言語であり、多くの重要なコンピュータサイエンスの概念がLispで初めて導入されました。)
  (*EFFICIENCY . 最新のLisp実装は高度な最適化を提供し、効率的な実行が可能です。)
  (*MULTI--*PARADIGM
   . Lispはマルチパラダイム言語であり、手続き型、関数型、オブジェクト指向など、さまざまなスタイルのプログラミングをサポートします。)
  (*RICH--*ECOSYSTEM . 豊富なエコシステムがあり、多様なライブラリやフレームワークが利用可能です。)))

(car *result*)
(*LISP--*FUN--*FACTORS
 (*EXPRESSIVENESS . Lispの構文は非常に表現力があり、プログラマーが思考を直接的にコードに変換することを可能にします。)
 (*MACROS . Lispのマクロシステムはコードを生成するコードを書くことを可能にし、非常に強力な抽象化を実現します。)
 (*CODE--AS--*DATA . Lispではコードがデータとして扱われる(ホモイコニック)、これによりコードの変換や解析が容易になります。)
 (*INTERACTIVE--*DEVELOPMENT
  . REPL(Read-Eval-Print Loop)を使用したインタラクティブな開発プロセスは、即時フィードバックを提供し、実験的な開発を促進します。)
 (*FLEXIBILITY . Lispは非常に柔軟で、新しい言語機能やパラダイムを簡単に組み込むことができます。)
 (*COMMUNITY . Lispコミュニティは熱心で、多くのリソース、ライブラリ、サポートが利用可能です。)
 (*HISTORY . Lispは長い歴史を持つ言語であり、多くの重要なコンピュータサイエンスの概念がLispで初めて導入されました。)
 (*EFFICIENCY . 最新のLisp実装は高度な最適化を提供し、効率的な実行が可能です。)
 (*MULTI--*PARADIGM
  . Lispはマルチパラダイム言語であり、手続き型、関数型、オブジェクト指向など、さまざまなスタイルのプログラミングをサポートします。)
 (*RICH--*ECOSYSTEM . 豊富なエコシステムがあり、多様なライブラリやフレームワークが利用可能です。))

こいつをcarとcdrを組み合わせて情報を取り出したりできる

(car (cdr (car *result*)))
(*EXPRESSIVENESS . Lispの構文は非常に表現力があり、プログラマーが思考を直接的にコードに変換することを可能にします。)

ちなみにcarとcdrとcarを組み合わせる命令もあるので一回で書ける

(cadar *result*)
(*EXPRESSIVENESS . Lispの構文は非常に表現力があり、プログラマーが思考を直接的にコードに変換することを可能にします。)

ウヒョー楽しい!