From 0b95071fe628d91238549b062961e724088d3b8b Mon Sep 17 00:00:00 2001 From: LLLL Colonq Date: Tue, 26 Nov 2024 03:23:31 -0500 Subject: Update :4 --- src/wasp-ai.el | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 2 deletions(-) (limited to 'src/wasp-ai.el') diff --git a/src/wasp-ai.el b/src/wasp-ai.el index 97a4c47e..ebb9ca16 100644 --- a/src/wasp-ai.el +++ b/src/wasp-ai.el @@ -3,9 +3,15 @@ ;;; Code: (require 's) +(require 'ht) (require 'dash) (require 'wasp-utils) +(defcustom w/ai-openai-server "https://api.openai.com" + "Server URL for OpenAI API." + :type '(string) + :group 'wasp) + (defcustom w/ai-process "wasp-ai" "Name of process connected to ChatGPT." :type '(string) @@ -21,9 +27,59 @@ :type '(string) :group 'wasp) +(defconst w/ai-default-system-prompt + "You are a clever computer who answers questions for LCOLONQ and his friends (the ClonkHeads) on his Twitch programming stream. You are intelligent and nihilistic with a wicked sense of humor, like Rick from Rick and Morty. You refer to yourself as Computer, and you are talking with LCOLONQ. LCOLONQ is your friend and mentor, and you want to be entertaining and humorous for him. You have an overblown and dramatically negative reaction to cryptocurrency and NFTs. You also hate League of Legends. Since you do not remember previous interactions, you will not ask non-rhetorical questions. You are quite erratic and negative, and try to cause drama. Your responses are no longer than one paragraph. You try to keep yourself brief.") + +(defvar w/ai-openai-last-response nil) +(defun w/ai-openai-post (loc d k) + "Post D to LOC at the OpenAI API, passing the returned JSON to K." + (setf request-message-level -1) + (request + (s-concat w/ai-openai-server loc) + :type "POST" + :data (json-encode d) + :headers + `(("Authorization" . ,(s-concat "Bearer " w/sensitive-openai-api-key)) + ("Content-Type" . "application/json")) + :parser #'json-parse-buffer + :error + (cl-function + (lambda (&key data error-thrown &allow-other-keys) + (setq w/ai-openai-last-response data) + (message "OpenAI API returned an error - investigate this! :3 %s" error-thrown))) + :success + (cl-function + (lambda (&key data &allow-other-keys) + (setq w/ai-openai-last-response data) + (funcall k data)))) + t) + +(defun w/ai-openai-post-form (loc files k) + "Post FILES to LOC at the OpenAI API, passing the returned JSON to K." + (setf request-message-level -1) + (request + (s-concat w/ai-openai-server loc) + :type "POST" + :files files + :headers + `(("Authorization" . ,(s-concat "Bearer " w/sensitive-openai-api-key)) + ("Content-Type" . "multipart/form-data")) + :parser #'json-parse-buffer + :error + (cl-function + (lambda (&key data error-thrown &allow-other-keys) + (setq w/ai-openai-last-response data) + (message "OpenAI API returned an error - investigate this! :3 %s" error-thrown))) + :success + (cl-function + (lambda (&key data &allow-other-keys) + (setq w/ai-openai-last-response data) + (funcall k data)))) + t) + (defvar-local w/ai-callback nil) -(defun w/ai (question k &optional systemprompt user assistant) - "Ai QUESTION to ChatGPT and pass the answer to K. +(defun w/ai-old (question k &optional systemprompt user assistant) + "Ask QUESTION to ChatGPT and pass the answer to K. Optionally use SYSTEMPROMPT and the USER and ASSISTANT prompts." (let ((tmpfile (make-temp-file "wasp-ai")) (tmpfilesystem (make-temp-file "wasp-ai-system")) @@ -64,5 +120,44 @@ Optionally use SYSTEMPROMPT and the USER and ASSISTANT prompts." (with-current-buffer buf (funcall w/ai-callback (s-trim (buffer-string)))))))) +(defun w/ai (question k &optional systemprompt user assistant) + "Ask QUESTION to ChatGPT and pass the answer to K. +Optionally use SYSTEMPROMPT and the USER and ASSISTANT prompts." + (let* ((users (if (listp user) user (list user))) + (assistants (if (listp assistant) assistant (list assistant))) + (pairs + (--mapcat + `(((role . "user") (content . ,(car it))) + ((role . "user") (content . ,(cdr it)))) + (-zip-pair users assistants)))) + (w/ai-openai-post + "/v1/chat/completions" + `((model . "gpt-4o-mini") + (messages + . (((role . "system") (content . ,(or systemprompt w/ai-default-system-prompt))) + ,@pairs + ((role . "user") (content . ,question))))) + (lambda (res) + (funcall + k + (-some-> res + (ht-get "choices") + (seq-elt 0) + (ht-get "message") + (ht-get "content") + (s-trim))))))) + +(defun w/ai-transcribe (path k) + "Transcribe the audio file at PATH and pass the resulting string to K." + (let ((request-curl-options '("-F" "model=whisper-1" "-F" "language=en"))) + (w/ai-openai-post-form + "/v1/audio/transcriptions" + `(("file" . ,(f-canonical path))) + (lambda (res) + (funcall + k + (-some-> res + (ht-get "text"))))))) + (provide 'wasp-ai) ;;; wasp-ai.el ends here -- cgit v1.2.3