branch: externals/ellama
commit cb672c6981007916e105695ac1a671cf609409eb
Merge: ac5a793ef5 94bc0224e4
Author: Sergey Kostyaev <[email protected]>
Commit: GitHub <[email protected]>
Merge pull request #180 from s-kostyaev/transient-model-menu
Add transient ollama model menu
---
NEWS.org | 2 +
ellama.el | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 136 insertions(+), 13 deletions(-)
diff --git a/NEWS.org b/NEWS.org
index 4a87a7277f..74ca2e7568 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -1,3 +1,5 @@
+* Version 1.0.2
+- Add ollama model selection to transient menu.
* Version 1.0.1
- Refactor ellama-code-add function for better efficiency. Remove
redundant context handling in ~ellama-code-add~. Simplify the prompt
diff --git a/ellama.el b/ellama.el
index 895f6fab94..5d6ad80a7a 100644
--- a/ellama.el
+++ b/ellama.el
@@ -6,7 +6,7 @@
;; URL: http://github.com/s-kostyaev/ellama
;; Keywords: help local tools
;; Package-Requires: ((emacs "28.1") (llm "0.22.0") (spinner "1.7.4")
(transient "0.7") (compat "29.1") (posframe "1.4.0"))
-;; Version: 1.0.1
+;; Version: 1.0.2
;; SPDX-License-Identifier: GPL-3.0-or-later
;; Created: 8th Oct 2023
@@ -771,6 +771,9 @@ Defaults to md, but supports org. Depends on
\"ellama-major-mode.\""
(cond ((provided-mode-derived-p ellama-major-mode 'org-mode) "org")
(t "md")))
+(defvar ellama--global-context nil
+ "Global context.")
+
(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.
@@ -1015,9 +1018,6 @@ 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)))
-(defvar ellama--global-context nil
- "Global context.")
-
(defvar ellama--context-buffer " *ellama-context*")
;;;###autoload
@@ -2482,20 +2482,25 @@ Call CALLBACK on result list of strings. ARGS contains
keys for fine control.
(lambda (err)
(user-error err)))))
+(defun ellama-get-ollama-model-name ()
+ "Get ollama model name from installed locally."
+ (interactive)
+ (completing-read
+ "Select ollama model: "
+ (mapcar (lambda (s)
+ (car (split-string s)))
+ (seq-drop
+ (process-lines
+ (executable-find ellama-ollama-binary) "ls")
+ 1))))
+
(defun ellama-get-ollama-local-model ()
"Return llm provider for interactively selected ollama model."
(interactive)
(declare-function llm-ollama-p "ext:llm-ollama")
(declare-function llm-ollama-host "ext:llm-ollama")
(declare-function llm-ollama-port "ext:llm-ollama")
- (let ((model-name
- (completing-read "Select ollama model: "
- (mapcar (lambda (s)
- (car (split-string s)))
- (seq-drop
- (process-lines
- (executable-find ellama-ollama-binary) "ls")
- 1))))
+ (let ((model-name (ellama-get-ollama-model-name))
(host (when (llm-ollama-p ellama-provider)
(llm-ollama-host ellama-provider)))
(port (when (llm-ollama-p ellama-provider)
@@ -2506,6 +2511,121 @@ Call CALLBACK on result list of strings. ARGS contains
keys for fine control.
(make-llm-ollama
:chat-model model-name :embedding-model model-name))))
+(defvar ellama-transient-ollama-model-name "")
+(defvar ellama-transient-temperature 0.7)
+(defvar ellama-transient-context-length 4096)
+(defvar ellama-transient-host nil)
+(defvar ellama-transient-port nil)
+
+(transient-define-suffix ellama-transient-set-ollama-model ()
+ "Set ollama model name."
+ (interactive)
+ (setq ellama-transient-ollama-model-name (ellama-get-ollama-model-name)))
+
+(transient-define-suffix ellama-transient-set-temperature ()
+ "Set temperature value."
+ (interactive)
+ (setq ellama-transient-temperature (read-number "Enter temperature: ")))
+
+(transient-define-suffix ellama-transient-set-context-length ()
+ "Set context length."
+ (interactive)
+ (setq ellama-transient-context-length (read-number "Enter context length:
")))
+
+(transient-define-suffix ellama-transient-set-host ()
+ "Set host address."
+ (interactive)
+ (setq ellama-transient-host (read-string "Enter host: ")))
+
+(transient-define-suffix ellama-transient-set-port ()
+ "Set port number."
+ (interactive)
+ (setq ellama-transient-port (read-number "Enter port: ")))
+
+(defvar ellama-provider-list '('ellama-provider
+ 'ellama-coding-provider
+ 'ellama-translation-provider
+ 'ellama-extraction-provider
+ 'ellama-summarization-provider
+ 'ellama-naming-provider)
+ "List of ollama providers.")
+
+(transient-define-suffix ellama-transient-model-get-from-provider ()
+ "Fill transient model from provider."
+ (interactive)
+ (ellama-fill-transient-ollama-model
+ (eval (read
+ (completing-read "Select provider: "
+ (mapcar #'prin1-to-string ellama-provider-list))))))
+
+(transient-define-suffix ellama-transient-set-provider ()
+ "Set transient model to provider."
+ (interactive)
+ (set (read
+ (completing-read "Select provider: "
+ (mapcar #'prin1-to-string ellama-provider-list)))
+ (ellama-construct-ollama-provider-from-transient)))
+
+(transient-define-prefix ellama-select-ollama-model ()
+ "Select ollama model."
+ [["Model"
+ ("f" "Load from provider" ellama-transient-model-get-from-provider
+ :transient t)
+ ("m" "Set Model" ellama-transient-set-ollama-model
+ :transient t
+ :description (lambda () (format "Model (%s)"
ellama-transient-ollama-model-name)))
+ ("t" "Set Temperature" ellama-transient-set-temperature
+ :transient t
+ :description (lambda () (format "Temperature (%.2f)"
ellama-transient-temperature)))
+ ("c" "Set Context Length" ellama-transient-set-context-length
+ :transient t
+ :description (lambda () (format "Context Length (%d)"
ellama-transient-context-length)))
+ ("S" "Set provider" ellama-transient-set-provider
+ :transient t)
+ ("s" "Set provider and quit" ellama-transient-set-provider)]
+ ["Connection"
+ ("h" "Set Host" ellama-transient-set-host
+ :transient t
+ :description (lambda () (if ellama-transient-host
+ (format "Host (%s)" ellama-transient-host)
+ "Host")))
+ ("p" "Set Port" ellama-transient-set-port
+ :transient t
+ :description (lambda () (if ellama-transient-port
+ (format "Port (%s)" ellama-transient-port)
+ "Port")))]
+ ["Quit" ("q" "Quit" transient-quit-one)]])
+
+(defun ellama-fill-transient-ollama-model (provider)
+ "Set transient ollama model from PROVIDER."
+ (declare-function llm-ollama-p "ext:llm-ollama")
+ (declare-function llm-ollama-host "ext:llm-ollama")
+ (declare-function llm-ollama-port "ext:llm-ollama")
+ (declare-function llm-ollama-chat-model "ext:llm-ollama")
+ (declare-function llm-ollama-default-chat-temperature "ext:llm-ollama")
+ (declare-function llm-ollama-default-chat-non-standard-params
"ext:llm-ollama")
+ (when (llm-ollama-p provider)
+ (setq ellama-transient-ollama-model-name (llm-ollama-chat-model provider))
+ (setq ellama-transient-temperature (or
(llm-ollama-default-chat-temperature provider) 0.7))
+ (setq ellama-transient-host (llm-ollama-host provider))
+ (setq ellama-transient-port (llm-ollama-port provider))
+ (let* ((other-params (llm-ollama-default-chat-non-standard-params
provider))
+ (ctx-len (when other-params (alist-get
+ "num_ctx"
+ (seq--into-list other-params)
+ nil nil #'string=))))
+ (setq ellama-transient-context-length (or ctx-len 4096)))))
+
+(defun ellama-construct-ollama-provider-from-transient ()
+ "Make provider with ollama mode in transient menu."
+ (make-llm-ollama
+ :chat-model ellama-transient-ollama-model-name
+ :default-chat-temperature ellama-transient-temperature
+ :host ellama-transient-host
+ :port ellama-transient-port
+ :default-chat-non-standard-params
+ `[("num_ctx" . ,ellama-transient-context-length)]))
+
(transient-define-prefix ellama-transient-code-menu ()
"Code Commands."
[["Code Commands"
@@ -2584,7 +2704,8 @@ Call CALLBACK on result list of strings. ARGS contains
keys for fine control.
("w" "Write" ellama-write)
("P" "Proofread" ellama-proofread)
("a" "Ask Commands" ellama-transient-ask-menu)
- ("C" "Code Commands" ellama-transient-code-menu)]]
+ ("C" "Code Commands" ellama-transient-code-menu)
+ ("o" "Ollama model" ellama-select-ollama-model)]]
[["Text"
("s" "Summarize Commands" ellama-transient-summarize-menu)
("i" "Improve Commands" ellama-transient-improve-menu)