diff --git a/init.el b/init.el index c53ec9d..78adb7f 100644 --- a/init.el +++ b/init.el @@ -3842,6 +3842,7 @@ one of the normal rainbow-delimiters-depth-N-face faces." (keymap-unset auto-highlight-symbol-mode-map "C-x C-a" t)) ;; some AI stuff +;; completion (use-package minuet :bind (("M-y" . #'minuet-complete-with-minibuffer) @@ -3861,17 +3862,133 @@ one of the normal rainbow-delimiters-depth-N-face faces." (minuet-provider 'openai-fim-compatible) (minuet-n-completions 1) (minuet-context-window 512) + (minuet-request-timeout 5) :config - (plist-put minuet-openai-fim-compatible-options - :end-point "http://localhost:11434/v1/completions") - (plist-put minuet-openai-fim-compatible-options - :name "Ollama") - (plist-put minuet-openai-fim-compatible-options - :api-key "TERM") - (plist-put minuet-openai-fim-compatible-options - :model "qwen2.5-coder:1.5b") - (minuet-set-optional-options minuet-openai-fim-compatible-options - :max-tokens 56)) + (defvar my/localai-api-key (auth-source-pass-get 'secret "emacs/localai-api")) + (setq minuet-openai-fim-compatible-options + '(:model "qwen3-32b-coding" + :end-point "https://ai.zander.im/v1/completions" + :api-key (lambda () my/localai-api-key) + :name "LocalAI" + :template (:prompt minuet--default-fim-prompt-function + :suffix minuet--default-fim-suffix-function) + ;; a list of functions to transform the end-point, headers, and body + :transform () + ;; function to extract LLM-generated text from JSON output + :get-text-fn minuet--openai-fim-get-text-fn + :optional (:top_p 0.9 + :max_tokens 1024)))) + +;; chatting +(use-package gptel + :defer t + :init + (defvar-keymap my/gptel-map + :prefix 'my/gptel-prefix-map + "y" #'gptel + ";" #'gptel-preset + "t" #'gptel-menu + "T" #'gptel-tools + "r" #'gptel-rewrite + "s" #'gptel-system-prompt + "a" #'gptel-add + "A" #'gptel-add-file + "q" #'gptel-abort) + (keymap-global-set "C-c y" #'my/gptel-prefix-map) + :config + (evil-define-key '(insert normal) gptel-mode-map + (kbd "C-") #'gptel-send + (kbd "C-RET") #'gptel-send) + (evil-define-key 'normal gptel-mode-map + (kbd "C-k") #'gptel-beginning-of-response + (kbd "C-j") #'gptel-end-of-response) + (require 'gptel-agent) + (defun my/-gptel-list_buffers-tool () + "Function for the \"list_buffers\" for `gptel'." + (with-temp-buffer + (dolist (buffer (buffer-list)) + (when (my/buffer-visible-p buffer) + (insert "- Name: ") + (insert (prin1-to-string (buffer-name buffer))) + (insert ?\n) + (insert " File: ") + (insert (prin1-to-string + (buffer-file-name buffer))) + (insert ?\n) + (insert " Mode: ") + (insert (prin1-to-string + (buffer-local-value 'major-mode buffer))) + (insert ?\n))) + (delete-char -1) + (buffer-substring-no-properties (point-min) (point-max)))) + (gptel-make-tool + :name "list_buffers" + :function #'my/-gptel-list_buffers-tool + :description "return a list of all visible emacs buffers, the files they are +vising, and their major mode" + :args () + :category "emacs") + ;; From the gptel README + (defun my/-gptel-read_buffer-tool (buffer) + "Function for the \"read_buffer\" for `gptel'." + (unless (buffer-live-p (get-buffer buffer)) + (error "Error: buffer %s is not live" buffer)) + (with-current-buffer buffer + (buffer-substring-no-properties (point-min) (point-max)))) + (gptel-make-tool + :name "read_buffer" + :function #'my/-gptel-read_buffer-tool + :description "return the contents of an emacs buffer" + :args (list '(:name "buffer" + :type string + :description + "the name of the buffer whose contents are to be retrieved")) + :category "emacs") + (defvar my/-localai-models + '((gemma-4-31b-it-qat-q4_0 :description "Google Gemma4 (31b)" + :capabilities (media tool-use) + :mime-types (image/jpeg image/png + image/gif image/webp) + :context-window 16 + :cutoff-date "2026-3") + (qwen3.6-27b :description "Alibaba Qwen 2.6 (27b) for coding" + :capabilities (media tool-use) + :mime-types (image/jpeg image/png + image/gif image/webp) + :context-window 32 + :cutoff-date "2024-10"))) + (defvar my/-localai-backend + (gptel-make-openai "LocalAI" + :protocol "https" + :host "ai.zander.im" + :endpoint "/v1/chat/completions" + :stream t + :key (lambda () my/localai-api-key) + :models my/-localai-models)) + (defvar my/-ollama-models + '((gemma4:31b :description "Google Gemma4 (31b)" + :capabilities (media tool-use) + :mime-types (image/jpeg image/png + image/gif image/webp) + :context-window 4 + :cutoff-date "2026-3"))) + (defvar my/-ollama-backend + (gptel-make-ollama "Server Ollama" + :models my/-ollama-models)) + (gptel-make-preset 'localai-chat + :description "LocalAI with Gemma4 (31b) (web search enabled)" + :backend my/-localai-backend + :model 'gemma-4-31b-it-qat-q4_0 + :system 'default + :tools '("WebSearch" "list_buffers" "read_buffer")) + (setq gptel-backend my/-localai-backend) + (setq gptel-model 'gemma-4-31b-it-qat-q4_0)) +(use-package gptel-agent + :after 'gptel + :defer t + :config + (require 'gptel-agent-tools) + (keymap-set my/gptel-map "g" #'gptel-agent)) ;; Theme (doom-themes) (use-package doom-themes