branch: externals/ellama
commit cb672c6981007916e105695ac1a671cf609409eb
Merge: ac5a793ef5 94bc0224e4
Author: Sergey Kostyaev <s-kosty...@users.noreply.github.com>
Commit: GitHub <nore...@github.com>

    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)

Reply via email to