From 05b352a2a6dd83ef47678f44ca37e362c5b56dbc Mon Sep 17 00:00:00 2001 From: Peter Tillemans Date: Tue, 25 Feb 2025 12:32:48 +0100 Subject: [PATCH] use gptel for LLM integration --- abbrev_defs | 6 +- init.org | 172 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 167 insertions(+), 11 deletions(-) diff --git a/abbrev_defs b/abbrev_defs index d0ff8e3..c4966ed 100644 --- a/abbrev_defs +++ b/abbrev_defs @@ -1,9 +1,7 @@ ;;-*-coding: utf-8;-*- (define-abbrev-table 'global-abbrev-table '( - ("brol" "breek riek op ladder" nil :count 1) - ("e-ox" "🐂" nil :count 0) - ("eox" "🐂" nil :count 1) - ("ewave" "👋" nil :count 3) + ("eox" "🐂" nil :count 2) + ("ewave" "👋" nil :count 4) )) diff --git a/init.org b/init.org index 471f20d..804d4c0 100644 --- a/init.org +++ b/init.org @@ -415,6 +415,17 @@ up, which a totally different can of worms). A function #+RESULTS: : [nil 26383 36877 803383 nil elpaca-process-queues nil nil 768000 nil] +** Enable vterm + +#+BEGIN_SRC emacs-lisp + (use-package vterm + :ensure t + :commands vterm) +#+END_SRC + +#+RESULTS: +: [nil 26557 35507 493630 nil elpaca-process-queues nil nil 948000 nil] + * Editor Features #+BEGIN_SRC emacs-lisp @@ -2629,7 +2640,7 @@ whether to put it under writing, comms or programming as it is equally #+RESULTS:g #+BEGIN_SRC emacs-lisp - (use-package ellama + (use-package ellama :tangle no :ensure t :defer t :requires (llm) @@ -2685,7 +2696,150 @@ gcloud beta services identity create --service=aiplatform.googleapis.com --proje However this is not for the Gemini Code Assistant. It is unclear how to use that backend. Gemini Code Assistant is part of the Google Cloud -Tools. +Tools. + + +** GPTel LLM support + +Most of the mind share seems to be around [[https://github.com/karthink/gptel][gptel]] as basis for LLM +integration in Emacs. + +#+BEGIN_SRC emacs-lisp + (use-package gptel + :ensure t + :commands (gptel) + :config + (setq gptel-default-mode 'org-mode) + (setq gptel-api-key openai-api-key) + (gptel-make-gemini "Gemini" :key gemini-api-key :stream t) + (gptel-make-anthropic "Claude" :stream t :key anthropic-api-key) + ;; define some tools for gptel + (gptel-make-tool + :function (lambda (url) + (with-current-buffer (url-retrieve-synchronously url) + (goto-char (point-min)) (forward-paragraph) + (let ((dom (libxml-parse-html-region (point) (point-max)))) + (run-at-time 0 nil #'kill-buffer (current-buffer)) + (with-temp-buffer + (shr-insert-document dom) + (buffer-substring-no-properties (point-min) (point-max)))))) + :name "read_url" + :description "Fetch and read the contents of a URL" + :args (list '(:name "url" + :type "string" + :description "The URL to read")) + :category "web") + + (gptel-make-tool + :function (lambda (buffer text) + (with-current-buffer (get-buffer-create buffer) + (save-excursion + (goto-char (point-max)) + (insert text))) + (format "Appended text to buffer %s" buffer)) + :name "append_to_buffer" + :description "Append text to the an Emacs buffer. If the buffer does not exist, it will be created." + :args (list '(:name "buffer" + :type "string" + :description "The name of the buffer to append text to.") + '(:name "text" + :type "string" + :description "The text to append to the buffer.")) + :category "emacs") + + ;; Message buffer logging tool + (gptel-make-tool + :function (lambda (text) + (message "%s" text) + (format "Message sent: %s" text)) + :name "echo_message" + :description "Send a message to the *Messages* buffer" + :args (list '(:name "text" + :type "string" + :description "The text to send to the messages buffer")) + :category "emacs") + + ;; buffer retrieval tool + (gptel-make-tool + :function (lambda (buffer) + (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)))) + :name "read_buffer" + :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") + + + (gptel-make-tool + :function (lambda (directory) + (mapconcat #'identity + (directory-files directory) + "\n")) + :name "list_directory" + :description "List the contents of a given directory" + :args (list '(:name "directory" + :type "string" + :description "The path to the directory to list")) + :category "filesystem") + + (gptel-make-tool + :function (lambda (parent name) + (condition-case nil + (progn + (make-directory (expand-file-name name parent) t) + (format "Directory %s created/verified in %s" name parent)) + (error (format "Error creating directory %s in %s" name parent)))) + :name "make_directory" + :description "Create a new directory with the given name in the specified parent directory" + :args (list '(:name "parent" + :type "string" + :description "The parent directory where the new directory should be created, e.g. /tmp") + '(:name "name" + :type "string" + :description "The name of the new directory to create, e.g. testdir")) + :category "filesystem") + + (gptel-make-tool + :function (lambda (path filename content) + (let ((full-path (expand-file-name filename path))) + (with-temp-buffer + (insert content) + (write-file full-path)) + (format "Created file %s in %s" filename path))) + :name "create_file" + :description "Create a new file with the specified content" + :args (list '(:name "path" + :type "string" + :description "The directory where to create the file") + '(:name "filename" + :type "string" + :description "The name of the file to create") + '(:name "content" + :type "string" + :description "The content to write to the file")) + :category "filesystem") + + (gptel-make-tool + :function (lambda (filepath) + (with-temp-buffer + (insert-file-contents (expand-file-name filepath)) + (buffer-string))) + :name "read_file" + :description "Read and display the contents of a file" + :args (list '(:name "filepath" + :type "string" + :description "Path to the file to read. Supports relative paths and ~.")) + :category "filesystem") + ) +#+END_SRC + +#+RESULTS: +: [nil 26557 40411 880967 nil elpaca-process-queues nil nil 794000 nil] + ** Copilot Support #+BEGIN_SRC emacs-lisp @@ -2808,8 +2962,8 @@ Aider is a package which works as a pair programming partner to generate code. #+BEGIN_SRC emacs-lisp - (use-package aider - :ensure (:host github :repo "tninja/aider.el" :files ("aider.el")) + (use-package aidermacs + :ensure (:host github :repo "MatthewZMD/aidermacs" :files ("*.el")) :config ;; Use claude-3-5-sonnet cause it is best in aider benchmark ;;(setq aider-args '("--model" "anthropic/claude-3-5-sonnet-20241022")) @@ -2818,17 +2972,21 @@ generate code. ;; (setq aider-args '("--model" "gpt-4o-mini")) ;; (setenv "OPENAI_API_KEY" ) ;; Or use gemini v2 model since it is very good and free - (setq aider-args '("--model" "gemini/gemini-exp-1206")) + (setq aidermacs-default-model "gemini-2.0-flash-thinking-exp-01-21") (setenv "GEMINI_API_KEY" google-gemini-key) + (setq aidermacs-auto-commits t) + (setq aidermacs-use-architect-mode t) + (setq aidermacs-backend 'vterm) ;; ;; Optional: Set a key binding for the transient menu :bind - (" a" . aider-transient-menu) + (" a" . aidermacs-transient-menu) + ("C-c a" . aidermacs-transient-menu) ) #+END_SRC #+RESULTS: -: [nil 26528 35167 709869 nil elpaca-process-queues nil nil 408000 nil] +: [nil 26557 35519 420170 nil elpaca-process-queues nil nil 238000 nil] ** Dired Configuration