Clarify LLM-facing descriptions

This commit is contained in:
Phil Bajsicki 2025-04-16 14:54:54 +02:00
parent c781b00be4
commit de14a8d066
2 changed files with 110 additions and 61 deletions

View file

@ -76,9 +76,6 @@ I change models a lot, and this /just works/ for most models, even if some aren'
(require 'gptel)
#+end_src
#+RESULTS:
: gptel
With that out of the way, let's get to the tools.
* Usage options:
I only use Doom Emacs, so here's how I do it.
@ -168,7 +165,40 @@ Collects into =gptel-org-tools= list, distinct from =gptel-tools=
#+begin_src elisp
(defvar gptel-org-tools '())
#+end_src
** Helper Functions
These abstract away some of the tool definitions.
Both of these clear the org-ql-cache to work around issues where a file may be updated between tool calls.
*** Retrieve heading and body (without subheadings)
#+begin_src elisp
(defun gptel-org-tools--heading-body ()
(concat
(buffer-substring-no-properties
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))
"---\n"))
#+end_src
*** Retrieve heading and subheadings (until next same-level heading)
#+begin_src elisp
(defun gptel-org-tools--heading-subtree ()
(concat
(buffer-substring-no-properties
(line-beginning-position)
(org-end-of-subtree))
"---\n"))
#+end_src
** Note on org-ql
Given that there isn't (yet?) a built-in way of disabling caching, every (org-ql-select) call is wrapped like so.
See [[https://github.com/alphapapa/org-ql/issues/437][this issue]] for details.
#+begin_src elisp :tangle no
(let ((org-ql-cache (make-hash-table)))
(org-ql-select ...))
#+end_src
** The tools
*** Emacs
These tools are primarily concerned with Emacs, Emacs Lisp, and files-or-buffers.
@ -430,13 +460,7 @@ Currently *not* tangled, as I'm testing breaking out each type of query into its
(if (stringp query)
(read query)
query)
:action #'(lambda ()
(concat
(buffer-substring-no-properties
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
:action #'gptel-org-tools--heading-body
(add-to-list 'gptel-org-tools
(gptel-make-tool
@ -477,10 +501,7 @@ But, any customizations to tweak this is left to the user, as everyone has their
(org-ql-select
(get-buffer buf)
`(heading ,date)
:action #'(lambda ()
(buffer-substring-no-properties
(line-beginning-position)
(org-end-of-subtree)))))
:action #'gptel-org-tools--heading-subtree))
(add-to-list 'gptel-org-tools
@ -525,14 +546,15 @@ The following tools are still very much WIP, and I think they're self-explanator
Retrieve the headings where the heading matches query..
#+begin_src elisp
(defun gptel-org-tools--org-ql-select-headings (buf query)
(org-ql-select
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(get-buffer buf)
`(heading ,query)
:action #'(lambda ()
(concat
(buffer-substring-no-properties
(line-beginning-position)
(line-end-position))))))
(line-end-position)))))))
(add-to-list 'gptel-org-tools
@ -545,7 +567,7 @@ Retrieve the headings where the heading matches query..
:description "The name of the buffer. See the NAME column in ~emacs-list-buffers~.")
'(:name "query"
:type string
:description "The string to pass into org-ql-select-headings. This is a bare string. Example: \"searchterm\""))
:description "The string to match entry headings against."))
:category "org-ql"))
#+end_src
@ -553,14 +575,15 @@ Retrieve the headings where the heading matches query..
Retrieve all the headings where either heading or content matches query.
#+begin_src elisp
(defun gptel-org-tools--org-ql-select-headings-rifle (buf query)
(org-ql-select
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(get-buffer buf)
`(rifle ,query)
:action #'(lambda ()
(concat
(buffer-substring-no-properties
(line-beginning-position)
(line-end-position))))))
(line-end-position)))))))
(add-to-list 'gptel-org-tools
@ -573,7 +596,7 @@ Retrieve all the headings where either heading or content matches query.
:description "The name of the buffer. See the NAME column in ~emacs-list-buffers~.")
'(:name "query"
:type string
:description "The string to pass into org-ql-select-headings-rifle. This is a bare string. Example: \"searchterm\""))
:description "The string to match entry headings against."))
:category "org-ql"))
#+end_src
@ -581,7 +604,8 @@ Retrieve all the headings where either heading or content matches query.
This pulls all the headings (and their contents) when they match tags (without inheritance.)
#+begin_src elisp
(defun gptel-org-tools--org-ql-select-tags-local (buf query)
(org-ql-select
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(get-buffer buf)
`(tags-local ,query)
:action #'(lambda ()
@ -590,7 +614,7 @@ This pulls all the headings (and their contents) when they match tags (without i
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
(line-beginning-position))))))))
(add-to-list 'gptel-org-tools
@ -603,7 +627,7 @@ This pulls all the headings (and their contents) when they match tags (without i
:description "The name of the buffer. See the NAME column in `emacs-list-buffers`. Using filename fails.")
'(:name "query"
:type string
:description "The tags to match entry headings against. Example: \"tag1\" \"tag2\""))
:description "The string match entry tags against."))
:category "org-ql"))
#+end_src
@ -611,7 +635,8 @@ This pulls all the headings (and their contents) when they match tags (without i
This pulls all the headings (and their contents) when they match tags (with inheritance; if a parent entry has the tag, descendant entries do, too.)
#+begin_src elisp
(defun gptel-org-tools--org-ql-select-tags (buf query)
(org-ql-select
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(get-buffer buf)
`(tags ,query)
:action #'(lambda ()
@ -620,7 +645,7 @@ This pulls all the headings (and their contents) when they match tags (with inhe
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
(line-beginning-position))))))))
(add-to-list 'gptel-org-tools
@ -633,15 +658,16 @@ This pulls all the headings (and their contents) when they match tags (with inhe
:description "The name of the buffer. See the NAME column in `emacs-list-buffers`. Using filename fails.")
'(:name "query"
:type string
:description "The tags to match entry headings against. Example: \"tag1\" \"tag2\""))
:description "The string to match entry headings against."))
:category "org-ql"))
#+end_src
***** org-ql-select-rifle
And, the "grab everything that matches" tool.
#+begin_src elisp
(defun gptel-org-tools--org-ql-select-rifle (buf query)
(let ((buffer (get-buffer buf)))
(defun hash-gptl-org-tools--org-ql-select-rifle ()
(let ((org-ql-cache (make-hash-table))
(buffer (get-buffer buf)))
(if buffer
(org-ql-select
buffer
@ -665,15 +691,15 @@ And, the "grab everything that matches" tool.
:description "The name of the buffer. See the NAME column in `emacs-list-buffers`. Using filename fails.")
'(:name "query"
:type string
:description "The strings to match entry headings and content against. Example: \"tag1\" \"tag2\""))
:description "The string to match entry headings and content against."))
:category "org-ql"))
#+end_src
***** org-ql-select-agenda-tags-local
This pulls all the headings (and their contents) when they match tags (without inheritance.)
#+begin_src elisp
(defun gptel-org-tools--org-ql-select-agenda-tags (query)
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(org-agenda-files)
`(tags-local ,query)
@ -683,7 +709,7 @@ This pulls all the headings (and their contents) when they match tags (without i
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
(line-beginning-position))))))))
(add-to-list 'gptel-org-tools
@ -693,7 +719,7 @@ This pulls all the headings (and their contents) when they match tags (without i
:description "Run simple word query against all files in (org-agenda-files). WITHOUT tag inheritance, only directly tagged headings."
:args (list '(:name "query"
:type string
:description "Plain list of strings to match entry headings and content against. Example: \"tag1\" \"tag2\""))
:description "The string to match entry tags against."))
:category "org-ql"))
#+end_src
@ -701,6 +727,7 @@ This pulls all the headings (and their contents) when they match tags (without i
This pulls all the headings (and their contents) when they match tags (with inheritance; if a parent entry has the tag, descendant entries do, too.)
#+begin_src elisp
(defun gptel-org-tools--org-ql-select-agenda-tags (query)
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(org-agenda-files)
`(tags ,query)
@ -710,7 +737,7 @@ This pulls all the headings (and their contents) when they match tags (with inhe
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
(line-beginning-position))))))))
(add-to-list 'gptel-org-tools
@ -720,7 +747,7 @@ This pulls all the headings (and their contents) when they match tags (with inhe
:description "Run simple word query against all files in (org-agenda-files). WITH tag inheritance."
:args (list '(:name "query"
:type string
:description "Plain list of strings to match entry headings and content against. Example: \"tag1\" \"tag2\""))
:description "The string to match entry tags against."))
:category "org-ql"))
#+end_src
@ -737,6 +764,7 @@ This means that /every org-mode file I have/ is part of this search.
#+begin_src elisp
(defun gptel-org-tools--org-ql-select-agenda-rifle (query)
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(org-agenda-files)
`(rifle ,query)
@ -746,7 +774,7 @@ This means that /every org-mode file I have/ is part of this search.
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
(line-beginning-position))))))))
(add-to-list 'gptel-org-tools
(gptel-make-tool
@ -755,7 +783,7 @@ This means that /every org-mode file I have/ is part of this search.
:description "Run simple word query against all files in (org-agenda-files)"
:args (list '(:name "query"
:type string
:description "Plain list of strings to match entry headings and content against. Example: \"tag1\" \"tag2\""))
:description "The string to match entry headings and content against."))
:category "org-ql"))
#+end_src

View file

@ -38,6 +38,22 @@
(defvar gptel-org-tools '())
(defun gptel-org-tools--heading-body ()
(concat
(buffer-substring-no-properties
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))
"---\n"))
(defun gptel-org-tools--heading-subtree ()
(concat
(buffer-substring-no-properties
(line-beginning-position)
(org-end-of-subtree))
"---\n"))
(add-to-list 'gptel-org-tools
(gptel-make-tool
:function (lambda (arg)
@ -167,10 +183,7 @@
(org-ql-select
(get-buffer buf)
`(heading ,date)
:action #'(lambda ()
(buffer-substring-no-properties
(line-beginning-position)
(org-end-of-subtree)))))
:action #'gptel-org-tools--heading-subtree))
(add-to-list 'gptel-org-tools
@ -202,14 +215,15 @@
:category "org"))
(defun gptel-org-tools--org-ql-select-headings (buf query)
(org-ql-select
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(get-buffer buf)
`(heading ,query)
:action #'(lambda ()
(concat
(buffer-substring-no-properties
(line-beginning-position)
(line-end-position))))))
(line-end-position)))))))
(add-to-list 'gptel-org-tools
@ -222,18 +236,19 @@
:description "The name of the buffer. See the NAME column in ~emacs-list-buffers~.")
'(:name "query"
:type string
:description "The string to pass into org-ql-select-headings. This is a bare string. Example: \"searchterm\""))
:description "The string to match entry headings against."))
:category "org-ql"))
(defun gptel-org-tools--org-ql-select-headings-rifle (buf query)
(org-ql-select
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(get-buffer buf)
`(rifle ,query)
:action #'(lambda ()
(concat
(buffer-substring-no-properties
(line-beginning-position)
(line-end-position))))))
(line-end-position)))))))
(add-to-list 'gptel-org-tools
@ -246,11 +261,12 @@
:description "The name of the buffer. See the NAME column in ~emacs-list-buffers~.")
'(:name "query"
:type string
:description "The string to pass into org-ql-select-headings-rifle. This is a bare string. Example: \"searchterm\""))
:description "The string to match entry headings against."))
:category "org-ql"))
(defun gptel-org-tools--org-ql-select-tags-local (buf query)
(org-ql-select
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(get-buffer buf)
`(tags-local ,query)
:action #'(lambda ()
@ -259,7 +275,7 @@
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
(line-beginning-position))))))))
(add-to-list 'gptel-org-tools
@ -272,11 +288,12 @@
:description "The name of the buffer. See the NAME column in `emacs-list-buffers`. Using filename fails.")
'(:name "query"
:type string
:description "The tags to match entry headings against. Example: \"tag1\" \"tag2\""))
:description "The string match entry tags against."))
:category "org-ql"))
(defun gptel-org-tools--org-ql-select-tags (buf query)
(org-ql-select
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(get-buffer buf)
`(tags ,query)
:action #'(lambda ()
@ -285,7 +302,7 @@
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
(line-beginning-position))))))))
(add-to-list 'gptel-org-tools
@ -298,11 +315,12 @@
:description "The name of the buffer. See the NAME column in `emacs-list-buffers`. Using filename fails.")
'(:name "query"
:type string
:description "The tags to match entry headings against. Example: \"tag1\" \"tag2\""))
:description "The string to match entry headings against."))
:category "org-ql"))
(defun gptel-org-tools--org-ql-select-rifle (buf query)
(let ((buffer (get-buffer buf)))
(defun hash-gptl-org-tools--org-ql-select-rifle ()
(let ((org-ql-cache (make-hash-table))
(buffer (get-buffer buf)))
(if buffer
(org-ql-select
buffer
@ -326,10 +344,11 @@
:description "The name of the buffer. See the NAME column in `emacs-list-buffers`. Using filename fails.")
'(:name "query"
:type string
:description "The strings to match entry headings and content against. Example: \"tag1\" \"tag2\""))
:description "The string to match entry headings and content against."))
:category "org-ql"))
(defun gptel-org-tools--org-ql-select-agenda-tags (query)
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(org-agenda-files)
`(tags-local ,query)
@ -339,7 +358,7 @@
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
(line-beginning-position))))))))
(add-to-list 'gptel-org-tools
@ -349,10 +368,11 @@
:description "Run simple word query against all files in (org-agenda-files). WITHOUT tag inheritance, only directly tagged headings."
:args (list '(:name "query"
:type string
:description "Plain list of strings to match entry headings and content against. Example: \"tag1\" \"tag2\""))
:description "The string to match entry tags against."))
:category "org-ql"))
(defun gptel-org-tools--org-ql-select-agenda-tags (query)
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(org-agenda-files)
`(tags ,query)
@ -362,7 +382,7 @@
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
(line-beginning-position))))))))
(add-to-list 'gptel-org-tools
@ -372,10 +392,11 @@
:description "Run simple word query against all files in (org-agenda-files). WITH tag inheritance."
:args (list '(:name "query"
:type string
:description "Plain list of strings to match entry headings and content against. Example: \"tag1\" \"tag2\""))
:description "The string to match entry tags against."))
:category "org-ql"))
(defun gptel-org-tools--org-ql-select-agenda-rifle (query)
(let ((org-ql-cache (make-hash-table)))
(org-ql-select
(org-agenda-files)
`(rifle ,query)
@ -385,7 +406,7 @@
(line-beginning-position)
(progn
(outline-next-heading)
(line-beginning-position)))))))
(line-beginning-position))))))))
(add-to-list 'gptel-org-tools
(gptel-make-tool
@ -394,7 +415,7 @@
:description "Run simple word query against all files in (org-agenda-files)"
:args (list '(:name "query"
:type string
:description "Plain list of strings to match entry headings and content against. Example: \"tag1\" \"tag2\""))
:description "The string to match entry headings and content against."))
:category "org-ql"))
(provide 'gptel-org-tools)