use gptel for LLM integration

This commit is contained in:
Peter Tillemans 2025-02-25 12:32:48 +01:00
parent bc989e3106
commit 05b352a2a6
2 changed files with 167 additions and 11 deletions

View file

@ -1,9 +1,7 @@
;;-*-coding: utf-8;-*- ;;-*-coding: utf-8;-*-
(define-abbrev-table 'global-abbrev-table (define-abbrev-table 'global-abbrev-table
'( '(
("brol" "breek riek op ladder" nil :count 1) ("eox" "🐂" nil :count 2)
("e-ox" "🐂" nil :count 0) ("ewave" "👋" nil :count 4)
("eox" "🐂" nil :count 1)
("ewave" "👋" nil :count 3)
)) ))

172
init.org
View file

@ -415,6 +415,17 @@ up, which a totally different can of worms). A function
#+RESULTS: #+RESULTS:
: [nil 26383 36877 803383 nil elpaca-process-queues nil nil 768000 nil] : [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 * Editor Features
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@ -2629,7 +2640,7 @@ whether to put it under writing, comms or programming as it is equally
#+RESULTS:g #+RESULTS:g
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package ellama (use-package ellama :tangle no
:ensure t :ensure t
:defer t :defer t
:requires (llm) :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 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 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 ** Copilot Support
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@ -2808,8 +2962,8 @@ Aider is a package which works as a pair programming partner to
generate code. generate code.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(use-package aider (use-package aidermacs
:ensure (:host github :repo "tninja/aider.el" :files ("aider.el")) :ensure (:host github :repo "MatthewZMD/aidermacs" :files ("*.el"))
:config :config
;; Use claude-3-5-sonnet cause it is best in aider benchmark ;; Use claude-3-5-sonnet cause it is best in aider benchmark
;;(setq aider-args '("--model" "anthropic/claude-3-5-sonnet-20241022")) ;;(setq aider-args '("--model" "anthropic/claude-3-5-sonnet-20241022"))
@ -2818,17 +2972,21 @@ generate code.
;; (setq aider-args '("--model" "gpt-4o-mini")) ;; (setq aider-args '("--model" "gpt-4o-mini"))
;; (setenv "OPENAI_API_KEY" <your-openai-api-key>) ;; (setenv "OPENAI_API_KEY" <your-openai-api-key>)
;; Or use gemini v2 model since it is very good and free ;; 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) (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 ;; Optional: Set a key binding for the transient menu
:bind :bind
("<leader> a" . aider-transient-menu) ("<leader> a" . aidermacs-transient-menu)
("C-c a" . aidermacs-transient-menu)
) )
#+END_SRC #+END_SRC
#+RESULTS: #+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 ** Dired Configuration