Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 2 additions & 24 deletions openai-completion.el
Original file line number Diff line number Diff line change
Expand Up @@ -166,28 +166,6 @@ Argument CALLBACK is a function received one argument which is the JSON data."
(lambda (&key data &allow-other-keys)
(funcall callback data)))))

;;
;;; Util

(defun openai-completion--data-choices (data)
"Extract choices from DATA request."
(let ((choices (let-alist data .choices)) ; choices if vector
(texts))
(mapc (lambda (choice)
(let-alist choice
(push .text texts))) ; text is the only important data in there
choices)
texts))

(defun openai-completion--get-choice (choices)
"Return choice from CHOICES."
(cond ((zerop (length choices))
(user-error "No response, please try again"))
((= 1 (length choices))
(car choices))
(t
(completing-read "Response: " choices nil t))))

;;
;;; Application

Expand All @@ -203,8 +181,8 @@ START and END are selected region boundaries."
(lambda (data)
(openai--with-buffer initial-buffer
(openai--pop-to-buffer initial-buffer) ; make sure to stay in that buffer
(let* ((choices (openai-completion--data-choices data))
(result (openai-completion--get-choice choices))
(let* ((choices (openai--data-choices data))
(result (openai--get-choice choices))
original-point)
(when (string-empty-p result)
(user-error "No response, please try again"))
Expand Down
107 changes: 107 additions & 0 deletions openai-edit.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
;;; openai-edit.el --- Edit presented documents with OpenAI API -*- lexical-binding: t; -*-

;; Copyright (C) 2023 Shen, Jen-Chieh

;; This file is not part of GNU Emacs.

;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:
;;
;; Given a prompt and an instruction, the model will return an edited version of
;; the prompt.
;;
;; See https://platform.openai.com/docs/api-reference/edits
;;

;;; Code:

(require 'openai)

(defcustom openai-edit-model "text-davinci-edit-001"
"ID of the model to use.

You can use the `text-davinci-edit-001' or `code-davinci-edit-001' model with
this endpoint."
:type 'string
:group 'openai)

(defcustom openai-edit-n 1
"How many edits to generate for the input and instruction."
:type 'integer
:group 'openai)

(defcustom openai-edit-temperature 1
"What sampling temperature to use, between 0 and 2. Higher values like 0.8
will make the output more random, while lower values like 0.2 will make it more
focused and deterministic.

We generally recommend altering this or `top_p' but not both."
:type 'integer
:group 'openai)

(defcustom openai-edit-top-p 1.0
"An alternative to sampling with temperature, called nucleus sampling, where
the model considers the results of the tokens with top_p probability mass.
So 0.1 means only the tokens comprising the top 10% probability mass are
considered.

We generally recommend altering this or `temperature' but not both."
:type 'number
:group 'openai)

;;
;;; API

(defun openai-edit-create (input instruction callback)
"Creates a new edit for the provided input, instruction, and parameters.

The INPUT is text to use as a starting point for the edit. The INSTRUCTION that
tells the model how to edit the prompt.

The argument CALLBACK is execuated after request is made."
(openai-request "https://api.openai.com/v1/edits"
:type "POST"
:headers `(("Content-Type" . "application/json")
("Authorization" . ,(concat "Bearer " openai-key)))
:data (json-encode
`(("model" . ,openai-edit-model)
("input" . ,input)
("instruction" . ,instruction)
("temperature" . ,openai-edit-temperature)
("top_p" . ,openai-edit-top-p)
("n" . ,openai-edit-n)))
:parser 'json-read
:success (cl-function
(lambda (&key data &allow-other-keys)
(funcall callback data)))))

;;
;;; Application

;;;###autoload
(defun openai-edit-prompt ()
"Prompt to ask for edited version."
(interactive)
(let ((input (read-string "Input: "))
(instruction (read-string "Instruction: ")))
(openai-edit-create input instruction
(lambda (data)
(when-let* ((choices (openai--data-choices data))
(result (openai--get-choice choices)))
(kill-new result)
(message "The result is pasted into kill ring"))))))

(provide 'openai-edit)
;;; openai-edit.el ends here
28 changes: 28 additions & 0 deletions openai.el
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ The URL is the url for `request' function; then BODY is the arguments for rest."
:type 'float
:group 'openai)

;;
;;; General

(defun openai--2str (obj)
"Convert OBJ to string."
(format "%s" obj))
Expand All @@ -106,6 +109,9 @@ Argument OPTIONS ia an alist use to calculate the frame offset."
(max (openai--seq-str-max (mapcar #'cdr options))
(/ (frame-width) openai-annotation-ratio)))

;;
;;; Buffer

(defmacro openai--with-buffer (buffer-or-name &rest body)
"Execute BODY ensure the BUFFER-OR-NAME is alive."
(declare (indent 1))
Expand All @@ -118,5 +124,27 @@ Argument OPTIONS ia an alist use to calculate the frame offset."
`((display-buffer-in-direction)
(dedicated . t))))

;;
;;; Choices

(defun openai--data-choices (data)
"Extract choices from DATA request."
(let ((choices (let-alist data .choices)) ; choices if vector
(texts))
(mapc (lambda (choice)
(let-alist choice
(push .text texts))) ; text is the only important data in there
choices)
texts))

(defun openai--get-choice (choices)
"Return choice from CHOICES."
(cond ((zerop (length choices))
(user-error "No response, please try again"))
((= 1 (length choices))
(car choices))
(t
(completing-read "Response: " choices nil t))))

(provide 'openai)
;;; openai.el ends here