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)