[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/ellama 839814129c 01/11: Begin session implementation
|
From: |
ELPA Syncer |
|
Subject: |
[elpa] externals/ellama 839814129c 01/11: Begin session implementation |
|
Date: |
Thu, 18 Jan 2024 15:57:52 -0500 (EST) |
branch: externals/ellama
commit 839814129c8a83501ca8d2ba38f4f0c4eb09831c
Author: Sergey Kostyaev <sskostyaev@gmail.com>
Commit: Sergey Kostyaev <sskostyaev@gmail.com>
Begin session implementation
---
ellama.el | 144 +++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 109 insertions(+), 35 deletions(-)
diff --git a/ellama.el b/ellama.el
index 7171578e20..9933de0aa9 100644
--- a/ellama.el
+++ b/ellama.el
@@ -44,11 +44,6 @@
"Tool for interacting with LLMs."
:group 'tools)
-(defcustom ellama-buffer "*ellama*"
- "Default ellama buffer."
- :group 'ellama
- :type 'string)
-
(defcustom ellama-user-nick "User"
"User nick in logs."
:group 'ellama
@@ -265,8 +260,6 @@ It should be a function with single argument generated text
string."
:group 'ellama
:type 'function)
-(defvar-local ellama--chat-prompt nil)
-
(defvar-local ellama--change-group nil)
(defvar-local ellama--current-request nil)
@@ -295,6 +288,41 @@ It should be a function with single argument generated
text string."
;; If ellama-enable-keymap is nil, remove the key bindings
(define-key global-map (kbd ellama-keymap-prefix) nil))))
+(defcustom ellama-session-file-extension "md"
+ "File extension for saving ellama session."
+ :type 'string
+ :group 'ellama)
+
+(defcustom ellama-sessions-directory (file-truename
+ (file-name-concat
+ user-emacs-directory
+ "ellama-sessions"))
+ "Directory for saved ellama sessions."
+ :type 'string
+ :group 'ellama)
+
+(defvar-local ellama--current-session nil)
+
+(defvar ellama--current-session-id nil)
+
+(defvar ellama--active-sessions (make-hash-table :test #'equal))
+
+(cl-defstruct ellama-session
+ "A structure represent ellama session.
+
+ID is an unique identifier of session, string.
+
+PROVIDER is an llm provider of session.
+
+FILE is a path to file contains string representation of this session, string.
+
+PROMPT is a variable contains last prompt in this session."
+ id provider file prompt)
+
+(defun ellama-get-session-buffer (id)
+ "Return ellama session buffer by provided ID."
+ (gethash id ellama--active-sessions))
+
(defun ellama-generate-name (provider action prompt)
"Generate name for ellama ACTION by PROVIDER according to PROMPT."
(let ((prompt-words (split-string prompt)))
@@ -308,6 +336,30 @@ It should be a function with single argument generated
text string."
(format "(%s)" (llm-name provider))))
" ")))
+(defun ellama-new-session (provider prompt)
+ "Create new ellama session with provided PROVIDER and PROMPT and unique id."
+ (let* ((name (ellama-generate-name provider 'ellama prompt))
+ (count 1)
+ (name-with-suffix (format "%s %d" name count))
+ (id (if (not (ellama-get-session-buffer name))
+ name
+ (while (ellama-get-session-buffer name-with-suffix)
+ (setq count (+ count 1))
+ (setq name-with-suffix (format "%s %d" name count)))
+ name-with-suffix))
+ (file-name (file-name-concat
+ ellama-sessions-directory
+ (concat id "." ellama-session-file-extension)))
+ (session (make-ellama-session :id id :provider provider :file
file-name))
+ (buffer (progn
+ (make-directory ellama-sessions-directory t)
+ (find-file-noselect file-name))))
+ (setq ellama--current-session-id id)
+ (puthash id buffer ellama--active-sessions)
+ (with-current-buffer buffer
+ (setq ellama--current-session session))
+ session))
+
(defun ellama--cancel-current-request (&rest _)
"Cancel current running request."
(when ellama--current-request
@@ -335,26 +387,38 @@ failure (with BUFFER current).
:on-done ON-DONE -- ON-DONE a function that's called with the full response
text
when the request completes (with BUFFER current)."
- (let* ((buffer (or (plist-get args :buffer) (current-buffer)))
+ (let* ((provider (or (plist-get args :provider) ellama-provider))
+ (session (plist-get args :session))
+ (buffer (or (plist-get args :buffer)
+ (when (ellama-session-p session)
+ (ellama-get-session-buffer (ellama-session-id session)))
+ (current-buffer)))
(point (or (plist-get args :point)
(with-current-buffer buffer (point))))
(filter (or (plist-get args :filter) #'identity))
- (session (plist-get args :session))
- (errcb (or (plist-get args :on-error) (lambda (msg) (error "Error
calling the LLM: %s" msg))))
- (donecb (or (plist-get args :on-done) #'ignore)))
+ (errcb (or (plist-get args :on-error)
+ (lambda (msg)
+ (error "Error calling the LLM: %s" msg))))
+ (donecb (or (plist-get args :on-done) #'ignore))
+ (llm-prompt (if session
+ (if (llm-chat-prompt-p (ellama-session-prompt session))
+ (progn
+ (llm-chat-prompt-append-response
+ (ellama-session-prompt session)
+ prompt)
+ (ellama-session-prompt session))
+ (setf (ellama-session-prompt session)
+ (llm-make-simple-chat-prompt prompt)))
+ (llm-make-simple-chat-prompt prompt))))
(with-current-buffer buffer
- (if (and session ellama--chat-prompt)
- (llm-chat-prompt-append-response
- ellama--chat-prompt prompt)
- (setq ellama--chat-prompt (llm-make-simple-chat-prompt prompt)))
(let* ((start (make-marker))
(end (make-marker))
(insert-text
(lambda (text)
;; Erase and insert the new text between the marker cons.
(with-current-buffer buffer
- ;; Manually save/restore point as save-excursion doesn't
restore the point into
- ;; the middle of replaced text.
+ ;; Manually save/restore point as save-excursion doesn't
+ ;; restore the point into the middle of replaced text.
(let ((pt (point)))
(goto-char start)
(delete-region start end)
@@ -362,7 +426,8 @@ when the request completes (with BUFFER current)."
(when (pcase ellama-fill-paragraphs
((cl-type function) (funcall
ellama-fill-paragraphs))
((cl-type boolean) ellama-fill-paragraphs)
- ((cl-type list) (apply #'derived-mode-p
ellama-fill-paragraphs)))
+ ((cl-type list) (apply #'derived-mode-p
+ ellama-fill-paragraphs)))
(fill-region start (point)))
(goto-char pt))
(when-let ((ellama-auto-scroll)
@@ -378,8 +443,8 @@ when the request completes (with BUFFER current)."
(set-marker-insertion-type end t)
(spinner-start ellama-spinner-type)
(setq ellama--current-request
- (llm-chat-streaming ellama-provider
- ellama--chat-prompt
+ (llm-chat-streaming provider
+ llm-prompt
insert-text
(lambda (text)
(funcall insert-text text)
@@ -406,22 +471,31 @@ Will call `ellama-chat-done-callback' on TEXT."
(funcall ellama-chat-done-callback text)))
;;;###autoload
-(defun ellama-chat (prompt)
- "Send PROMPT to ellama chat with conversation history."
+(defun ellama-chat (prompt &optional create-session)
+ "Send PROMPT to ellama chat with conversation history.
+
+If CREATE-SESSION set, creates new session even if there is an active session."
(interactive "sAsk ellama: ")
- (when (not (buffer-live-p (get-buffer ellama-buffer)))
- (get-buffer-create ellama-buffer)
- (with-current-buffer ellama-buffer
- (funcall ellama-buffer-mode)))
- (display-buffer ellama-buffer)
- (with-current-buffer ellama-buffer
- (save-excursion
- (goto-char (point-max))
- (insert ellama-nick-prefix " " ellama-user-nick ":\n" prompt "\n\n"
- ellama-nick-prefix " " ellama-assistant-nick ":\n")
- (ellama-stream prompt
- :session t
- :on-done #'ellama-chat-done))))
+ (let* ((session (if (or create-session
+ current-prefix-arg
+ (and (not ellama--current-session)
+ (not ellama--current-session-id)))
+ (ellama-new-session ellama-provider prompt)
+ (or ellama--current-session
+ (with-current-buffer (ellama-get-session-buffer
+ ellama--current-session-id)
+ ellama--current-session))))
+ (buffer (ellama-get-session-buffer
+ (ellama-session-id session))))
+ (display-buffer buffer)
+ (with-current-buffer buffer
+ (save-excursion
+ (goto-char (point-max))
+ (insert ellama-nick-prefix " " ellama-user-nick ":\n" prompt "\n\n"
+ ellama-nick-prefix " " ellama-assistant-nick ":\n")
+ (ellama-stream prompt
+ :session session
+ :on-done #'ellama-chat-done)))))
;;;###autoload
(defun ellama-ask-about ()
- [elpa] externals/ellama updated (35a398b63e -> b301ed87f5), ELPA Syncer, 2024/01/18
- [elpa] externals/ellama 839814129c 01/11: Begin session implementation,
ELPA Syncer <=
- [elpa] externals/ellama 39b0a6cc92 10/11: Update documentation, ELPA Syncer, 2024/01/18
- [elpa] externals/ellama 150e0664e8 08/11: Add rename session, ELPA Syncer, 2024/01/18
- [elpa] externals/ellama 38c6d5e4da 03/11: Add save and load session, ELPA Syncer, 2024/01/18
- [elpa] externals/ellama 078ae47dd5 05/11: Add directory selection for load session if needed, ELPA Syncer, 2024/01/18
- [elpa] externals/ellama b301ed87f5 11/11: Merge pull request #49 from s-kostyaev/session-management, ELPA Syncer, 2024/01/18
- [elpa] externals/ellama 6bc04eff78 02/11: Deactivate session on session buffer kill, ELPA Syncer, 2024/01/18
- [elpa] externals/ellama c23a04d287 09/11: Remove unused custom variable ellama-buffer-mode, ELPA Syncer, 2024/01/18
- [elpa] externals/ellama 7f309375d0 07/11: Add switch between active sessions, ELPA Syncer, 2024/01/18
- [elpa] externals/ellama 1a2c428506 06/11: Add session remove, ELPA Syncer, 2024/01/18
- [elpa] externals/ellama c783125b53 04/11: Add provider selection in new session if needed, ELPA Syncer, 2024/01/18