[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/ellama d30ba7a964 8/9: Merge pull request #70 from s-ko
From: |
ELPA Syncer |
Subject: |
[elpa] externals/ellama d30ba7a964 8/9: Merge pull request #70 from s-kostyaev/add-context-management |
Date: |
Sun, 11 Feb 2024 12:58:09 -0500 (EST) |
branch: externals/ellama
commit d30ba7a964fc0a23c1e45ded71dec32918935c06
Merge: 28b0022708 0200858cfb
Author: Sergey Kostyaev <s-kostyaev@users.noreply.github.com>
Commit: GitHub <noreply@github.com>
Merge pull request #70 from s-kostyaev/add-context-management
Add context management
---
README.org | 64 +++++++++++++++++----------
ellama.el | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 170 insertions(+), 41 deletions(-)
diff --git a/README.org b/README.org
index f58fa83166..708a377c98 100644
--- a/README.org
+++ b/README.org
@@ -12,6 +12,9 @@ review, summarization, enhancing grammar/spelling or wording
and
more through the Emacs interface. Ellama natively supports streaming
output, making it effortless to use with your preferred text editor.
+The name "ellama" is derived from "Emacs Large LAnguage Model
+Assistant". Previous sentence was written by Ellama itself.
+
** Installation
Just ~M-x~ ~package-install~ @@html:<kbd>@@Enter@@html:</kbd>@@ ~ellama~
@@ -180,34 +183,49 @@ Change current active session.
Rename current ellama session.
+*** ellama-context-add-file
+
+Add file to context.
+
+*** ellama-context-add-buffer
+
+Add buffer to context.
+
+*** ellama-context-add-selection
+
+Add selected region to context.
+
** Keymap
Here is a table of keybindings and their associated functions in
Ellama, using the ~C-c e~ prefix:
-| Keymap | Function | Description |
-|--------+----------------------------+------------------------------|
-| "c c" | ellama-code-complete | Code complete |
-| "c a" | ellama-code-add | Code add |
-| "c e" | ellama-code-edit | Code edit |
-| "c i" | ellama-code-improve | Code improve |
-| "c r" | ellama-code-review | Code review |
-| "s s" | ellama-summarize | Summarize |
-| "s w" | ellama-summarize-webpage | Summarize webpage |
-| "i w" | ellama-improve-wording | Improve wording |
-| "i g" | ellama-improve-grammar | Improve grammar and spelling |
-| "i c" | ellama-improve-conciseness | Improve conciseness |
-| "m l" | ellama-make-list | Make list |
-| "m t" | ellama-make-table | Make table |
-| "m f" | ellama-make-format | Make format |
-| "a a" | ellama-ask-about | Ask about |
-| "a i" | ellama-chat | Chat (ask interactively) |
-| "a l" | ellama-ask-line | Ask about current line |
-| "a s" | ellama-ask-selection | Ask about selection |
-| "t t" | ellama-translate | Text translate |
-| "t c" | ellama-complete | Text complete |
-| "d w" | ellama-define-word | Define word |
-| "p s" | ellama-provider-select | Provider select |
+| Keymap | Function | Description |
+|--------+------------------------------+------------------------------|
+| "c c" | ellama-code-complete | Code complete |
+| "c a" | ellama-code-add | Code add |
+| "c e" | ellama-code-edit | Code edit |
+| "c i" | ellama-code-improve | Code improve |
+| "c r" | ellama-code-review | Code review |
+| "s s" | ellama-summarize | Summarize |
+| "s w" | ellama-summarize-webpage | Summarize webpage |
+| "i w" | ellama-improve-wording | Improve wording |
+| "i g" | ellama-improve-grammar | Improve grammar and spelling |
+| "i c" | ellama-improve-conciseness | Improve conciseness |
+| "m l" | ellama-make-list | Make list |
+| "m t" | ellama-make-table | Make table |
+| "m f" | ellama-make-format | Make format |
+| "a a" | ellama-ask-about | Ask about |
+| "a i" | ellama-chat | Chat (ask interactively) |
+| "a l" | ellama-ask-line | Ask current line |
+| "a s" | ellama-ask-selection | Ask selection |
+| "t t" | ellama-translate | Text translate |
+| "t c" | ellama-complete | Text complete |
+| "d w" | ellama-define-word | Define word |
+| "x b" | ellama-context-add-buffer | Context add buffer |
+| "x f" | ellama-context-add-file | Context add file |
+| "x s" | ellama-context-add-selection | Context add selection |
+| "p s" | ellama-provider-select | Provider select |
** Configuration
diff --git a/ellama.el b/ellama.el
index 471fb81c2d..b2deaad88c 100644
--- a/ellama.el
+++ b/ellama.el
@@ -125,6 +125,10 @@
("t c" ellama-complete "Text complete")
;; define
("d w" ellama-define-word "Define word")
+ ;; context
+ ("x b" ellama-context-add-buffer "Context add buffer")
+ ("x f" ellama-context-add-file "Context add file")
+ ("x s" ellama-context-add-selection "Context add selection")
;; provider
("p s" ellama-provider-select "Provider select"))))
(dolist (key-command key-commands)
@@ -163,11 +167,6 @@
:group 'ellama
:type 'integer)
-(defcustom ellama-ask-about-prompt-template "Text:\n%s\nRegarding this text,
%s"
- "Prompt template for `ellama-ask-about'."
- :group 'ellama
- :type 'string)
-
(defcustom ellama-translate-word-prompt-template "Translate %s to %s"
"Promp template for `ellama-translate' with single word."
:group 'ellama
@@ -403,8 +402,10 @@ 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)
+PROMPT is a variable contains last prompt in this session.
+
+CONTEXT contains context for next request."
+ id provider file prompt context)
(defun ellama-get-session-buffer (id)
"Return ellama session buffer by provided ID."
@@ -424,6 +425,8 @@ PROMPT is a variable contains last prompt in this session."
(format "(%s)" (llm-name provider))))
" ")))
+(defvar ellama--new-session-context nil)
+
(defun ellama-new-session (provider prompt &optional ephemeral)
"Create new ellama session with unique id.
Provided PROVIDER and PROMPT will be used in new session.
@@ -443,12 +446,13 @@ If EPHEMERAL non nil new session will not be associated
with any file."
ellama-sessions-directory
(concat id "." ellama-session-file-extension))))
(session (make-ellama-session
- :id id :provider provider :file file-name))
+ :id id :provider provider :file file-name :context
ellama--new-session-context))
(buffer (if file-name
(progn
(make-directory ellama-sessions-directory t)
(find-file-noselect file-name))
(get-buffer-create id))))
+ (setq ellama--new-session-context nil)
(setq ellama--current-session-id id)
(puthash id buffer ellama--active-sessions)
(with-current-buffer buffer
@@ -541,7 +545,15 @@ If EPHEMERAL non nil new session will not be associated
with any file."
(save-buffer)
(goto-char (point-min))))
(with-current-buffer buffer
- (setq ellama--current-session (read session-buffer))
+ (let ((session (read session-buffer)))
+ (setq ellama--current-session
+ (make-ellama-session
+ :id (ellama-session-id session)
+ :provider (ellama-session-provider session)
+ :file (ellama-session-file session)
+ :prompt (ellama-session-prompt session)
+ :context ellama--new-session-context)))
+ (setq ellama--new-session-context nil)
(setq ellama--current-session-id (ellama-session-id
ellama--current-session))
(puthash (ellama-session-id ellama--current-session)
buffer ellama--active-sessions)
@@ -608,6 +620,102 @@ If EPHEMERAL non nil new session will not be associated
with any file."
(remhash id ellama--active-sessions)
(puthash new-id buffer ellama--active-sessions)))
+;;;###autoload
+(defun ellama-context-add-file ()
+ "Add file to context."
+ (interactive)
+ (if-let* ((id ellama--current-session-id)
+ (session (with-current-buffer (ellama-get-session-buffer id)
+ ellama--current-session))
+ (file-name (read-file-name "Select file: " nil nil t)))
+ (push (cons 'file file-name) (ellama-session-context session))
+ (push (cons 'file file-name) ellama--new-session-context)))
+
+;;;###autoload
+(defun ellama-context-add-buffer (buf)
+ "Add BUF to context."
+ (interactive "bSelect buffer: ")
+ (if-let* ((id ellama--current-session-id)
+ (session (with-current-buffer (ellama-get-session-buffer id)
+ ellama--current-session)))
+ (push (cons 'buffer buf) (ellama-session-context session))
+ (push (cons 'buffer buf) ellama--new-session-context)))
+
+;;;###autoload
+(defun ellama-context-add-selection ()
+ "Add file to context."
+ (interactive)
+ (if-let* ((id ellama--current-session-id)
+ (session (with-current-buffer (ellama-get-session-buffer id)
+ ellama--current-session))
+ ((region-active-p))
+ (content (buffer-substring-no-properties (region-beginning)
(region-end))))
+ (push (cons 'text content) (ellama-session-context session))
+ (push (cons 'text content) ellama--new-session-context)))
+
+(defun ellama--org-format-context-element (elt)
+ "Format context ELT for org mode."
+ (pcase (car elt)
+ ('file
+ (format "file:%s" (cdr elt)))
+ ('buffer
+ (format "elisp:(display-buffer \"%s\")" (cdr elt)))
+ ('text
+ (cdr elt))
+ (_
+ (user-error "Unsupported context element"))))
+
+(defun ellama--md-format-context-element (elt)
+ "Format context ELT for org mode."
+ (pcase (car elt)
+ ('file
+ (format "[%s](<%s>)"
+ (cdr elt)
+ (cdr elt)))
+ ('buffer
+ (format "```emacs-lisp\n(display-buffer \"%s\")\n```\n" (cdr elt)))
+ ('text
+ (cdr elt))
+ (_
+ (user-error "Unsupported context element"))))
+
+(defun ellama--extract-context-element (elt)
+ "Extract context ELT content."
+ (pcase (car elt)
+ ('text (cdr elt))
+ ('buffer (with-current-buffer (cdr elt)
+ (buffer-substring-no-properties (point-min) (point-max))))
+ ('file (with-temp-buffer
+ (find-file-literally (cdr elt))
+ (buffer-substring-no-properties (point-min) (point-max))))
+ (_
+ (user-error "Unsupported context element"))))
+
+(defun ellama--format-context ()
+ "Format current session context for chat buffer."
+ (if-let* ((session ellama--current-session)
+ (context (ellama-session-context session)))
+ (concat (string-join
+ (cons "Context:"
+ (if (derived-mode-p 'org-mode)
+ (mapcar #'ellama--org-format-context-element context)
+ (mapcar #'ellama--md-format-context-element context)))
+ "\n")
+ "\n\n")
+ ""))
+
+(defun ellama--prompt-with-context (prompt)
+ "Add context to PROMPT for sending to llm."
+ (if-let* ((session ellama--current-session)
+ (context (ellama-session-context session)))
+ (concat (string-join
+ (cons "Context:"
+ (mapcar #'ellama--extract-context-element context))
+ "\n")
+ "\n\n"
+ prompt)
+ prompt))
+
(defun ellama-stream (prompt &rest args)
"Query ellama for PROMPT.
ARGS contains keys for fine control.
@@ -645,16 +753,17 @@ when the request completes (with BUFFER current)."
(lambda (msg)
(error "Error calling the LLM: %s" msg))))
(donecb (or (plist-get args :on-done) #'ignore))
+ (prompt-with-ctx (ellama--prompt-with-context prompt))
(llm-prompt (if session
(if (llm-chat-prompt-p (ellama-session-prompt session))
(progn
(llm-chat-prompt-append-response
(ellama-session-prompt session)
- prompt)
+ prompt-with-ctx)
(ellama-session-prompt session))
(setf (ellama-session-prompt session)
- (llm-make-simple-chat-prompt prompt)))
- (llm-make-simple-chat-prompt prompt))))
+ (llm-make-simple-chat-prompt prompt-with-ctx)))
+ (llm-make-simple-chat-prompt prompt-with-ctx))))
(with-current-buffer buffer
(ellama-request-mode +1)
(let* ((start (make-marker))
@@ -690,6 +799,7 @@ when the request completes (with BUFFER current)."
(set-marker-insertion-type start nil)
(set-marker-insertion-type end t)
(spinner-start ellama-spinner-type)
+ (setf (ellama-session-context session) nil)
(setq ellama--current-request
(llm-chat-streaming provider
llm-prompt
@@ -756,7 +866,8 @@ If CREATE-SESSION set, creates new session even if there is
an active session."
(with-current-buffer buffer
(save-excursion
(goto-char (point-max))
- (insert ellama-nick-prefix " " ellama-user-nick ":\n" prompt "\n\n"
+ (insert ellama-nick-prefix " " ellama-user-nick ":\n"
+ (ellama--format-context) prompt "\n\n"
ellama-nick-prefix " " ellama-assistant-nick ":\n")
(ellama-stream prompt
:session session
@@ -768,11 +879,11 @@ If CREATE-SESSION set, creates new session even if there
is an active session."
(defun ellama-ask-about ()
"Ask ellama about selected region or current buffer."
(interactive)
- (let ((input (read-string "Ask ellama about this text: "))
- (text (if (region-active-p)
- (buffer-substring-no-properties (region-beginning)
(region-end))
- (buffer-substring-no-properties (point-min) (point-max)))))
- (ellama-chat (format ellama-ask-about-prompt-template text input))))
+ (let ((input (read-string "Ask ellama about this text: ")))
+ (if (region-active-p)
+ (ellama-context-add-selection)
+ (ellama-context-add-buffer (buffer-name (current-buffer))))
+ (ellama-chat input)))
;;;###autoload
(defun ellama-ask-selection ()
- [elpa] externals/ellama updated (28b0022708 -> 9c145514f1), ELPA Syncer, 2024/02/11
- [elpa] externals/ellama 328586ea43 2/9: Add project name explanation to readme, ELPA Syncer, 2024/02/11
- [elpa] externals/ellama 59e5bdeb8d 1/9: Add context to session struct and helper functions, ELPA Syncer, 2024/02/11
- [elpa] externals/ellama 305624f50d 5/9: Support old sessions, ELPA Syncer, 2024/02/11
- [elpa] externals/ellama a986604649 4/9: Add context to future session, ELPA Syncer, 2024/02/11
- [elpa] externals/ellama 0d094be756 3/9: Implement context management, ELPA Syncer, 2024/02/11
- [elpa] externals/ellama 9c145514f1 9/9: Bump version, ELPA Syncer, 2024/02/11
- [elpa] externals/ellama 0200858cfb 7/9: Improve docs, ELPA Syncer, 2024/02/11
- [elpa] externals/ellama 0d9ab0ee25 6/9: Add key bindings for context management, ELPA Syncer, 2024/02/11
- [elpa] externals/ellama d30ba7a964 8/9: Merge pull request #70 from s-kostyaev/add-context-management,
ELPA Syncer <=