From ead7abebaee9c4bc88cde2a518b30a93ea5a5059 Mon Sep 17 00:00:00 2001 From: Tristan Druyen Date: Mon, 29 Apr 2024 21:01:10 +0200 Subject: [PATCH] Rework emacs LLM integration using gptel+addons --- ext/doom/config.el | 167 ++++++++---------------------------- ext/doom/packages.el | 19 ++-- home-mods/shell/default.nix | 2 +- 3 files changed, 47 insertions(+), 141 deletions(-) diff --git a/ext/doom/config.el b/ext/doom/config.el index dabfab5..480a238 100644 --- a/ext/doom/config.el +++ b/ext/doom/config.el @@ -78,9 +78,6 @@ ;; ) - - - ;; Whenever you reconfigure a package, make sure to wrap your config in an ;; `after!' block, otherwise Doom's defaults may override your settings. E.g. ;; @@ -135,32 +132,6 @@ (setq! lsp-rust-analyzer-server-display-inlay-hints t) (setq! lsp-rust-analyzer-completion-auto-import-enable t) -;; llama.cpp - - -;; openchat prompt: GPT4 User: {prompt}<|end_of_turn|>GPT4 Assistant: - - -;; (use-package llama-cpp-code) -;; (use-package llama-cpp-chat) - -(use-package! llama-cpp - :config - ;; mixtral - (setq! llama-cpp-host "100.64.0.3" - llama-cpp-params '( - :n_predict -1 - :stop [""] - ) - - llama-cpp-chat-prompt "You are an intelligent programming assistant. - The User is a professional software developer, be concise in your answers and assume technical proficiency. - " - llama-cpp-chat-prompt-prefix "System: [INST]" - llama-cpp-chat-input-prefix "[INST]" - llama-cpp-chat-input-suffix "[/INST]") - ) - ;; Nix @@ -241,10 +212,11 @@ (defvar categories-alist '( - (:name "Terminal" :modes (vterm-mode term-mode) :type per-project) - (:name "Org" :modes (org-mode org-agenda-mode) :type global) - (:name "Misc" :modes (+doom-dashboard-mode native-comp-limple-mode messages-buffer-mode) :type global) - (:name "Misc" :modes (special-mode fundamental-mode) :type per-project) + (:name "org" :modes (org-mode org-agenda-mode) :buffer-name () :type global) + (:name "gptel" :modes nil :buffer-name ("*llama-cpp*" "*gptel*" "*gptel-context*" "*gptel-query*") :type global) + (:name "terminal" :modes (vterm-mode term-mode) :buffer-name () :type per-project) + (:name "misc" :modes (+doom-dashboard-mode native-comp-limple-mode messages-buffer-mode) :buffer-name () :type global) + (:name "misc" :modes (special-mode fundamental-mode) :buffer-name () :type per-project) ) "Mapping of categories to modes with their respective type logic.") @@ -256,23 +228,30 @@ (concat (projectile-project-name) "::" default-name) default-name)) - (defun get-category-name (mode) - "Get category name for the given MODE." + (defun get-category-name (buffer) + "Get category name for the given BUFFER." (let (category-name) (dolist (category categories-alist category-name) - (let ((modes (plist-get category :modes))) - (when (or (null modes) (memq mode modes)) + (let ((buffer-names (plist-get category :buffer-name)) + (modes (plist-get category :modes))) + (cond + ((and buffer-names (member (buffer-name buffer) buffer-names)) (setq category-name (if (eq (plist-get category :type) 'per-project) (get-project-name-or-default (plist-get category :name)) - (plist-get category :name)))))))) + (plist-get category :name)))) + ((and modes (with-current-buffer buffer (memq major-mode modes))) + (setq category-name + (if (eq (plist-get category :type) 'per-project) + (get-project-name-or-default (plist-get category :name)) + (plist-get category :name))))))))) (defun centaur-tabs-group-name-by-category () "Get tab group name based on category." - (let ((mode-category (get-category-name major-mode))) + (let ((mode-category (get-category-name (current-buffer)))) (if mode-category (list mode-category) - (list (get-project-name-or-default "Main"))))) + (list (get-project-name-or-default "main"))))) (defun centaur-tabs-projectile-buffer-groups () "Return the list of group names BUFFER belongs to." @@ -312,105 +291,33 @@ (use-package! gptel :init :config - (setq! gptel-backend (gptel-make-openai "llama-cpp" + (setq! gptel-backend (gptel-make-openai "gptel" :stream t :protocol "http" :host "100.64.0.3:8080" - :models '("test")) - gptel-model "test") + :models '("default")) + gptel-model "default") + (setq! gptel-expert-commands t) + (setq! gptel-temperature 0.2) (add-hook 'gptel-post-response-functions 'gptel-end-of-response) (add-hook 'gptel-post-stream-hook 'gptel-auto-scroll) (map! :leader - "" 'gptel-complete - "TAB" 'gptel-complete) - ) + "" 'gptel-send + "TAB" 'gptel-send)) +(use-package! gptel-extensions + :after gptel) +(use-package magit-gptcommit + :after gptel magit + :config -;; ;; cape ;;;;; + (magit-gptcommit-mode 1) -;; (use-package! cape) - -;; ;; (after! company -;; ;; (setq-default company-frontends '(company-preview-frontend))) - -;; (use-package! codeium -;; :after cape -;; :init -;; ;; use globally -;; (add-to-list 'completion-at-point-functions #'codeium-completion-at-point) -;; ;; or on a hook -;; ;; (add-hook 'python-mode-hook -;; ;; (lambda () -;; ;; (setq-local completion-at-point-functions '(codeium-completion-at-point)))) - -;; ;; if you want multiple completion backends, use cape (https://github.com/minad/cape): -;; ;; (add-hook 'python-mode-hook -;; ;; (lambda () -;; ;; (setq-local completion-at-point-functions -;; ;; (list (cape-super-capf #'codeium-completion-at-point #'lsp-completion-at-point))))) -;; ;; an async company-backend is coming soon! - -;; ;; codeium-completion-at-point is autoloaded, but you can -;; ;; optionally set a timer, which might speed up things as the -;; ;; codeium local language server takes ~0.2s to start up -;; ;; (add-hook 'emacs-startup-hook -;; ;; (lambda () (run-with-timer 0.1 nil #'codeium-init))) - -;; ;; :defer t ;; lazy loading, if you want -;; :config - -;; ;; company conf -;; (setq! company-idle-delay 0.05 -;; company-require-match nil -;; company-minimum-prefix-length 0 -;; company-frontends '(company-pseudo-tooltip-unless-just-one-frontend company-preview-frontend)) - -;; ;;;;;; - -;; (setq use-dialog-box nil) ;; do not use popup boxes - -;; ;; if you don't want to use customize to save the api-key -;; ;; (setq codeium/metadata/api_key "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") -;; (setq codeium/metadata/api_key (with-temp-buffer (insert-file-contents "~/.codeium") -;; (buffer-string))) - -;; ;; (defalias 'my/codeium-complete -;; ;; (cape-interactive-capf #'codeium-completion-at-point)) - - -;; (map! :localleader -;; :map evil-normal-state-map -;; "c e" #'my/codeium-complete) - -;; ;; get codeium status in the modeline -;; (setq codeium-mode-line-enable -;; (lambda (api) (not (memq api '(CancelRequest Heartbeat AcceptCompletion))))) -;; ;; (add-to-list 'mode-line-format '(:eval (car-safe codeium-mode-line)) t) -;; ;; alternatively for a more extensive mode-line -;; (add-to-list 'mode-line-format '(-50 "" codeium-mode-line) t) - -;; ;; use M-x codeium-diagnose to see apis/fields that would be sent to the local language server -;; (setq codeium-api-enabled -;; (lambda (api) -;; (memq api '(GetCompletions Heartbeat CancelRequest GetAuthToken RegisterUser auth-redirect AcceptCompletion)))) -;; ;; you can also set a config for a single buffer like this: -;; ;; (add-hook 'python-mode-hook -;; ;; (lambda () -;; ;; (setq-local codeium/editor_options/tab_size 4))) - -;; ;; You can overwrite all the codeium configs! -;; ;; for example, we recommend limiting the string sent to codeium for better performance -;; (defun my-codeium/document/text () -;; (buffer-substring-no-properties (max (- (point) 3000) (point-min)) (min (+ (point) 1000) (point-max)))) -;; ;; if you change the text, you should also change the cursor_offset -;; ;; warning: this is measured by UTF-8 encoded bytes -;; (defun my-codeium/document/cursor_offset () -;; (codeium-utf8-byte-length -;; (buffer-substring-no-properties (max (- (point) 3000) (point-min)) (point)))) -;; (setq codeium/document/text 'my-codeium/document/text) -;; (setq codeium/document/cursor_offset 'my-codeium/document/cursor_offset)) -;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Add gptcommit transient commands to `magit-commit' + ;; Eval (transient-remove-suffix 'magit-commit '(1 -1)) to remove gptcommit transient commands + (magit-gptcommit-status-buffer-setup) + :bind (:map git-commit-mode-map + ("C-c C-g" . magit-gptcommit-commit-accept))) diff --git a/ext/doom/packages.el b/ext/doom/packages.el index ce53267..9131e7d 100644 --- a/ext/doom/packages.el +++ b/ext/doom/packages.el @@ -39,25 +39,24 @@ ;; Use `:pin' to specify a particular commit to install. -;; llama.cpp -(package! llama-cpp) - ;; tabs (package! centaur-tabs) ;; nix (package! nixpkgs-fmt) -;; codeium -(package! codeium :recipe (:host github :repo "Exafunction/codeium.el")) -(package! cape) - ;; copilot -(package! copilot - :recipe (:host github :repo "zerolfx/copilot.el" :files ("*.el" "dist"))) +;; (package! copilot +;; :recipe (:host github :repo "zerolfx/copilot.el" :files ("*.el" "dist"))) +;;;;;;;;;;;;;;;;;;;;;;;;; ;; gptel -(package! gptel :recipe (:host github :repo "akhil3417/gptel")) +(package! gptel :recipe (:type git :host nil :repo "https://git.vlt81.de/tristan/gptel.git" :branch "master")) +;; gptel-extensions +(package! gptel-extensions :recipe (:host github :repo "kamushadenes/gptel-extensions.el")) +;; gptcommit +(package! magit-gptcommit :recipe (:host github :repo "douo/magit-gptcommit")) +;;;;;;;;;;;;;;;;;;;;;;;;; ;; Doom's packages are pinned to a specific commit and updated from release to ;; release. The `unpin!' macro allows you to unpin single packages... diff --git a/home-mods/shell/default.nix b/home-mods/shell/default.nix index 629085f..6b1f2de 100644 --- a/home-mods/shell/default.nix +++ b/home-mods/shell/default.nix @@ -8,7 +8,7 @@ let doomemacsSrc = builtins.fetchGit { url = "https://github.com/doomemacs/doomemacs"; ref = "master"; - rev = "201051c368cfdabf3f68c372939297380999e28d"; + rev = "9620bb45ac4cd7b0274c497b2d9d93c4ad9364ee"; }; neofetchThemesSrc = builtins.fetchGit { url = "https://github.com/Chick2D/neofetch-themes";