summaryrefslogtreecommitdiff
path: root/llm-chat-openai.el
blob: a093dde35aa5238f0cbba49ac674fdbd72b0d2b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
;;; llm-chat-openai.el --- Implements openai llm intergration -*- lexical-binding: t; -*-

;; This file is not part of GNU Emacs.

;;; Code:

(require 'llm-chat-api)

(defvar llm-chat-openai-models '("gpt-4.1" "gpt-3.5-turbo" "gpt-5"))

(cl-defgeneric llm-chat-resolve-model-backend ((backend (eql 'openai))
					       model)
  (if (member model llm-chat-openai-models)
      t))

(defun llm-chat-openai-get-model ()
  (if (member (llm-chat-get-model) llm-chat-openai-models)
      (llm-chat-get-model)
    "gpt-3.5-turbo"))

(defun llm-chat-make-openai-backend ()
  (make-llm-chat-backend
   :api-endpoint "https://api.openai.com/v1/responses"
   :api-key (auth-source-pick-first-password :host "api.openai.com")
   :headers-fn #'llm-chat-openai-headers
   :json-fn #'llm-chat-openai-json
   :filter-fn #'llm-chat-openai-filter))

(defun llm-chat-openai-json ()
  (let ((json-object `((model . ,(llm-chat-openai-get-model))
		       (input . ,(llm-chat-get-history))
		       (temperature . ,(llm-chat-get-temperature))
		       (stream . ,(llm-chat-get-stream?)))))
    (json-encode json-object)))

(defun llm-chat-openai-headers (backend)
  (list "-H" (concat "Authorization: " (concat "Bearer "
					       (llm-chat-backend-api-key backend)))))
(defun llm-chat-openai-filter (proc string)
  (llm-chat-data-filter proc string
			#'llm-chat-openai-finished-p
			#'llm-chat-openai-parse-content))

(defun llm-chat-openai-finished-p (string)
  (when-let* ((json-object (json-read-from-string string))
	      (type (alist-get 'type json-object)))
    (string= type "response.output_item.done")))

(defun llm-chat-openai-parse-content (string)
  (when-let* ((json-object (json-read-from-string string))
	      (type (alist-get 'type json-object))
	      (text (alist-get 'delta json-object)))
    (when (string-equal type "response.output_text.delta")
      text)))

(provide 'llm-chat-openai)

;;; llm-chat-openai.el ends here