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;-*-
(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)
))

172
init.org
View file

@ -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" <your-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
("<leader> a" . aider-transient-menu)
("<leader> 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