7. Refactoring chatgpt-send and introducing chatgpt-api-key
In this section, we will refactor the chatgpt-send function. We will create a new function named chatgpt-command to encapsulate the curl command logic. Additionally, we will introduce a variable called chatgpt-api-key to store our OpenAI API key securely.
Refactoring chatgpt-send with chatgpt-command¶
We introduce the chatgpt-command function, which generates the curl command string. This allows us to streamline chatgpt-send by replacing the existing command code with a call to chatgpt-command.
(defun chatgpt-command ()
"Return the curl command."
(concat "curl https://api.openai.com/v1/chat/completions "
"-H 'Content-Type: application/json' "
"-H 'Authorization: Bearer sk-proj-7pQDxN...w-D40A "
"-d @/home/tony/chatgpt-emacs/request.json"))
(defun chatgpt-send ()
"Send the request \"Hello!\" to OpenAI."
(interactive)
(let ((command (chatgpt-command)))
(make-process
:name "chatgpt"
:buffer (generate-new-buffer-name "chatgpt")
:command (list "sh" "-c" command)
:sentinel (lambda (process event) ...))))
After implementing these changes and evaluating these expressions, calling chatgpt-send command should successfully populate the buffer *chatgpt[requests]* with a new response from OpenAI, confirming that the functionality remains intact.
Introducing chatgpt-api-key to hold OpenAI API Key¶
In this update, we refactor the hardcoded API key previously embedded within the chatgpt-command function. Instead, we store it in a new variable, chatgpt-api-key. This approach allows for easier future modifications to the API key. And in upcoming lessons, we will explore a more secure method for storing the API key, rather than embedding it directly in the source code.
Updated Code¶
(defvar chatgpt-api-key "sk-proj-7pQDxN...w-D40A"
"Variable to hold the OpenAI API key.")
(defun chatgpt-command ()
"Construct and return the curl command for OpenAI API."
(format
(concat "curl https://api.openai.com/v1/chat/completions "
"-H 'Content-Type: application/json' "
"-H 'Authorization: Bearer %s' "
"-d @/home/tony/chatgpt-emacs/request.json")
chatgpt-api-key))
Testing with an Incorrect API Key¶
For testing purposes, we can temporarily set the chatgpt-api-key variable to an invalid key, for example, foo-api-key. When invoking the chatgpt-send command, the OpenAI API responded with an error message displayed in the *chatgpt[requests]* buffer:
{
"error": {
"message": "Incorrect API key provided: foo-api-key.
You can find your API key at https://platform.openai.com/acc
ount/api-keys.",
"type": "invalid_request_error",
"param": null,
"code": "invalid_api_key"
}
}
This demonstrates that the API key is validated properly by OpenAI.
Updating chatgpt-command Function Signature¶
Finaly, we modify the chatgpt-command function to accept the absolute path to the request.json file as an argument. This change allows for easier adjustments to the file path in the future.
(defun chatgpt-command (req-path)
"Return the curl command."
(format
(concat "curl https://api.openai.com/v1/chat/completions "
"-H 'Content-Type: application/json' "
"-H 'Authorization: Bearer %s' "
"-d @%s")
chatgpt-api-key req-path))
(defun chatgpt-send ()
"Send the request \"Hello!\" to OpenAI."
(interactive)
(let ((command (chatgpt-command "/home/tony/chatgpt-emacs/request.json")))
(make-process
:name "chatgpt"
:buffer (generate-new-buffer-name "chatgpt")
:command (list "sh" "-c" command)
:sentinel (lambda (process event) ...))))
For testing, we can pass a non-existent file path, such as "/home/tony/chatgpt-emacs/request", to the chatgpt-command function in chatgpt-send. When invoking the chatgpt-send command, the curl command produced warnings, and the OpenAI API returned an error message, both of which were displayed in the *chatgpt[requests]* buffer:
Warning: Couldn't read data from file "/home/tony/chatgpt-emacs/request",
Warning: this makes an empty POST.
{
"error": {
"message": "We could not parse the JSON body of your request.
(HINT: This likely means you aren't using your HTTP library correctly. The
OpenAI API expects a JSON payload, but what was sent was not valid JSON.
If you have trouble figuring out how to fix this, please contact us through
our help center at help.openai.com.)",
"type": "invalid_request_error",
"param": null,
"code": null
}
}