gptel [51/83]
Table of Contents
- 1. PROJECT Tool use
[28/33]
ATTACH - 2. TODO Review gptel-openai-assistant by Ahmed Shariff ATTACH
- 3. TODO gptel-rewrite: Launch by prompting for the rewrite instruction
- 4. PROJECT Make gptel-request standalone
- 5. PROJECT Write a user manual and developer manual
- 6. TODO auto-update models for a backend
- 7. TODO Make
gptel-backend
easier to specify - 8. PROJECT Dynamic system messages and template support
[6/8]
- 9. PROJECT Buffer-local context sets via links
- 10. PROJECT Customizable/Org-aware prompt processing
- 11. TODO Robustly distinguish between prompts and responses
- 12. PROJECT Structured/JSON output
- 13. PROJECT Add better per-run processing support
- 14. MAYBE Use transient levels instead of gptel-expert-commands
- 15. TODO Make it possible to attach description or instructions to context chunks
- 16. TODO Perplexity citation support
- 17. PROJECT gptel: Editing other buffers from the chat buffer
- 18. PROJECT RAG solution for gptel
- 19. TODO gptel: Replace crowdsourced prompts with fabric prompts
- 20. TODO Stop tokens
- 21. TODO If redirecting to new gptel session, write entire template to it
- 22. TODO Read the MCP examples and spec
- 23. WAITING gptel-claude still losing data chunks ATTACH
- 24. MAYBE gptel: Add an undo boundary before the response
- 25. MAYBE Add a gptel-curl-extra-args for global extra Curl args
- 26. MAYBE gptel: Put region pulsing in the after-response-hook.
- 27. MAYBE Good rewrite directives for gptel by madmacs
- 28. erts files for testing
- 29. PROJECT Vision
- 30. CLOSED Process chain executor (FSM) for gptel
[8/8]
- 31. CLOSED Better diff interface
[3/3]
- 32. CLOSED gptel model-specific behavior framework
- 33. SUSPENDED gptel-tasks
- 34. SUSPENDED Move to overlay tracking
- 35. SUSPENDED Implement gptel-complete
- 36. SUSPENDED Function calling demos with Anthropic
- 37. SUSPENDED gptel: stateless design
- 38. CANCELLED gptel: more context options
[1/2]
- 39. CANCELLED Add support for older versions of curl (< 1.8)
- 40. CANCELLED gptel editing prompt: use
string-edit
- 41. CANCELLED Use the :around cl-defmethod extra param to handle Org
- 42. CANCELLED Reset ollama context after changing model
- 43. CANCELLED gptel & nixos: Write expression for Emacs 27.1 to test
- 44. CANCELLED azure backend with multiple models
- 45. CANCELLED gptel: copilot-style completion UI
- 46. DONE Claude error: text content blocks must contain non-whitespace text ATTACH
- 47. DONE Check out evedel
- 48. DONE Composable menus for gptel
- 49. DONE jwiegely change the behavior of M-x gptel
- 50. DONE Fix gptel oneshot (non-streaming) Markdown -> Org converter
- 51. DONE markdown -> org stream converter: handling backticks
- 52. DONE gptel: handle headings in the markdown converter
- 53. DONE Update Joao Tavora about commits I added
- 54. DONE gptel: always-available diffing
- 55. DONE gptel: Add logging
- 56. DONE gptel-request: the
:buffer
and =:position keyword args aren’t clear - 57. DONE gptel: multi-line directive writing
- 58. DONE gptel: Google gemini support
- 59. DONE
defgeneric
system for querying other APIs? - 60. DONE Stateless design + save state
- 61. DONE Tag new
gptel
release - 62. DONE Add algal and d1egoaz to the gptel acknowledgments section
- 63. DONE gptel error handling for local llms
- 64. DONE gptel: Add kill-ring as source of prompt
- 65. DONE gptel: make defining openai backends easier
- 66. DONE Reply to ahyatt’s proposal for llm actions
- 67. DONE file-local-var storage with newlines: reply to Eli
- 68. DONE LLM UI experiments – reply to Andrew
- 69. DONE gptel: post-response hook’s beginning position is wrong
- 70. DONE gptel-anthropic parser losing text ATTACH
- 71. DONE Reply to Jan Rychter’s email
- 72. DONE Make gptel bugfix release
- 73. DONE gptel: Add a non-chat boolean for regular buffers
- 74. DONE gptel: context indicator in header-line
- 75. DONE Reply to tarsius
- 76. DONE Further fix gptel org formatter ATTACH
- 77. WAITING Fontification malfunction when streaming responses
- 78. DONE gptel-gemini parser:
:parts
can have multiple:text
blocks - 79. DONE purpose-mode interferes with gptel’s display
- 80. DONE Improve docs around :key
- 81. TODO Find a better way to handle Ollama tool use + no-stream
- 82. TODO gptel-rewrite tweaks suggested by mike olson
Exported at: Jan 26 2025, 17:38
1. PROJECT Tool use [28/33]
ATTACH
Jester7’s minimal gptel tools Jester7’s gptel tools
[ ]
Allow editing tool calls from the confirmation prompt[ ]
Support(gptel-get-tool '(("emacs" ("read_buffer" "open_file"))))
[ ]
If stop reason in maxtokens, send a message.[ ]
README: Add instructions for tool-use with OpenWebUI.[X]
Go through the model list and assign tool capabilities correctly.[ ]
Then ensure that the tool options in the menu only show up when appropriate.[X]
Log arguments as well: (truncated arguments)
Changed the tool call API:
- tool call confirmation: callback called with ((tool arg-values callback) …)
- tool call result: callback called with ((name arg-values result) …)
[X]
Decide on whether we want t, auto and nil, or force, t and nil for tool-use options.[X]
Ollama: Turn off streaming automatically if tools are used This is done in a hacky way right now. Eventually I need a better method.[X]
Tool call failures for async calls, should we handle them? This is difficult to handle.[X]
PrivateGPT tool use with/without streaming Doesn’t support, AFAICT[X]
README: Add demos for tool use.[X]
README: Add explanation of tool use.[X]
Handle tool use confirmation and result inclusion in the custom callbacks used by
gptel--suffix-send
. Perhaps we can pop up a buffer that displays the confirmation? Or just use the minibuffer? We can try to reuse the existing mechanism used in dedicated chat buffers, perhaps with some temporary function advice.Ended up using the minibuffer. It’s good enough for now.
[X]
Handle non-string, structured return values from tools. Tools can return only simple types or JSON objects/arrays. These are returned as plists/arrays, processed viagptel--json-read
.[X]
tool specification for tools that don’t need to be run We just specify:confirm t
in the tool specification. You can still send it if required that way.[X]
How do we control including tools in gptel? (gptel-use-tools
)[X]
Configuring tool calls: auto, always, any etc[X]
Handle tool call failures (wrap withcondition-case-unless-debug
?)[X]
Test OpenAI compatible APIs like Groq[X]
Don’t run post response hook etc when a request ends and we’re waiting on a tool call[X]
Ollama tool path with streaming This is not supported, but we need to turn off streaming automatically when tools are used. (Ollama returns a non-streaming JSON response.)[X]
Tool creation/appending code ingptel-request
- Check for model-tool capability
[X]
Ollama tool path without streaming (see note) Gives me the following error:
"message": "tools.0.type: Extra inputs are not permitted"
But it works once in a while! What the hell: Error in tool object construction, now fixed.[X]
Gemini tool path without streaming[X]
Gemini tool path with streaming[X]
Anthropic tool path without streaming[X]
Anthropic tool path with streaming[X]
OpenAI tool path without streaming[X]
OpenAI tool path with streaming[X]
Kagi tool path without streaming: No Kagi support[X]
Kagi tool path with streaming: No Kagi support
TODO Chat with Armin Darvish
Email from Armin Darvish: Re: gptel tool-use
gptel-get-backend
,gptel-get-tool
vsgptel-backend
,gptel-tool
- Tool use discussion
DONE Ask @ahyatt about using symbol :type
in tool specs
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWU1MTQ=]
2. TODO Review gptel-openai-assistant by Ahmed Shariff ATTACH
3. TODO gptel-rewrite: Launch by prompting for the rewrite instruction
So that the user doesn’t need to press “d” to get started.
4. PROJECT Make gptel-request standalone
- Move all the networking code to gptel-request.el (renamed from gptel-curl.el) and make it standalone.
- gptel.el will contain all the non-transient UI code.
This will make it easier for third party packages to use only gptel-request
via (require 'gptel-request)
, and they can safely ignore the rest of gptel. This can be spun out into another package at some point, although naming issues will cause trouble.
No change to the other files.
5. PROJECT Write a user manual and developer manual
These are intended to be different sections of the same manual (single document).
The user manual should contain
[ ]
a brief explanation of what gptel is[ ]
a brief overview of how LLM APIs work[ ]
explanations of gptel’s features[ ]
along with customization relevant to each feature[ ]
explanation of (WIP) RAG and tool use
The developer manual should include
[ ]
building on gptel: examples of gptel-request usage[ ]
a brief explanation of gptel’s design goals, focusing on- its scope: what kinds of features will/won’t be added
- philosophy: integrate with Emacs, reduce cognitive burden, don’t introduce syntax
[ ]
a brief overview of gptel’s main control flow and state management[ ]
data structures (plists, plists everywhere!)
Resources:
- Uniline for drawing line diagrams for info?
6. TODO auto-update models for a backend
Since I don’t want to make automatic network requests to fetch model information from the API,
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWU0NDc=] [BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWU1Njc=]
here’s an idea.
- Define a cl-defgeneric that dispatches on the backend type, and updates the model list for
gptel-backend
or any backend. - Define a new command,
gptel-update-models
, that calls these methods.
Now the user can run this whenever/wherever they want to update the list of models, like in a hook.
7. TODO Make gptel-backend
easier to specify
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWU1NTY=] [BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6cHVsbHJlcTUyOQ==]
The idea is to allow gptel-backend
to be a string (that’s the name of the backend). In gptel-request
, we can check the type of the variable:
(let ((backend (or (cl-etypecase gptel-backend (gptel-backend gptel-backend) (string (alist-get gptel-backend gptel--known-backends nil nil #'equal))) (user-error "Backend \"%s\" is not known to be defined" gptel-backend)))) ...)
We just have to be sure that we do this everywhere gptel-backend
is let-bound. Alternatively, we can use gptel--backend
as the actual backend and gptel-backend
can always be a string.
We may also need a gv-settable gptel-get-backend
that can be used in situations like:
(push 'gpt-4o (gptel-backend-models (gptel-get-backend "ChatGPT")))
8. PROJECT Dynamic system messages and template support [6/8]
The idea is to allow entries in gptel-directives
to be
- strings (as usual)
- lists (for templates)
- functions that return strings or lists of strings
This allows for
- DONE Dynamically generated system messages
This is useful for constructing a system message that has many parts. Depending on the context, we might want a system message to set
- the general tenor and tone of the conversation,
- instructions about formatting, control characters and special cases,
- instructions for the specific task in the next message,
- additional context strings from other buffers etc (already handled by
gptel-context
)
and possibly more. Instead of providing specific templates to do these things, which will always be inadequate, allowing the directive to be a function lets the user fine-tune their system message to the situation however they’d like.
- DONE Templates (Lists of strings)
The idea is to shove the initial part of the conversation into the directive as a template. The reason is that the LLM response can be guided more by providing a conversation history, and that the responses are often better this way.
For example, instead of:
You are an emacs-lisp programmer. Follow instructions and provide code and only code as output, without any explanations or markdown code fences. Refactor the provided code to do X, Y. Here is code for context: <code here>
in the system message, followed by
user: ;; Code to be refactored here
in the selected region, we use
You are an emacs-lisp programmer. Follow instructions and provide code and only code as output, without any explanations or markdown code fences. Here is code for context: <code here>
in the system message, followed by the templated exchange
user: ;; Code to be refactored here assistant: What is the required change user: Refactor this code to do X, Y.
In this case, the directive will be a function like this:
(defun gptel--rewrite-message (rewrite-text message) "Create a rewrite template with text and system message" `("You are an emacs-lisp programmer. Follow..." ;system message, can be nil (concat "The code is the following:" ,rewrite-text) ;user "What is the required change?" ;assistant ,message)) ;user
The question is how this should be implemented.
- Option 1:
gptel--system-message
can be a function
This is possibly simpler to implement. Somewhere in
gptel-request
we can let-bindgptel--system-message
to the final system message string, prepending the rest to the full user prompt. But the:system
arg ofgptel-request
makes less sense this way.It also makes updating the transient menu for the system message easier.
Maybe we can rename
gptel--system-message
to something more descriptive, likegptel--directive
? Where a “directive” can include the template like before. - Option 2:
gptel--system-message
is always the final system message string
and we use a new variable,
gptel-directive
orgptel-template
, to hold the function or list of strings.This makes sense since the
:system
arg togptel-request
should be the system message itself for clarity. It’ll also be easier to understand the code and to debug it.The question is where in the chain involving
gptel-request
we can do the required processing.
- Option 1:
- MAYBE template support for system prompt editor (accessed via the transient menu)
Done, but there’s no support for editing functions or lists, only static system message strings.
- DONE template support for
gptel-rewrite
How to split up the task into the prompt and the system message: Now that
gptel-request
supports a list of strings as a prompt, we can split it up this way:Let the system message be a string, customizable maybe?
(setq gptel-rewrite-directive "You are a %s programmer. Rewrite without comments or explanations, ...")
Let the prompt be the exchange that looks like:
(setq prompt '("<code here>" ;user "What is the required change?")) ;llm
Feed it to gptel request as
(gptel-request prompt :system gptel-rewrite-directive)
[ ]
Handle the case where the system message isn’t supported by the model?
- DONE template support for persistence (
gptel--save-state
)
Right now it expects the system message to be a string.Done, but it only saves the system message as a string. Saving lists and functions is… difficult.
- DONE template support for header-line in gptel-mode
Right now it expects the system message to be a string.
- DONE No system message
For models that don’t support system messages, or when the user does not want to supply one at all, we need to allow this by allowing the directive to be
nil
.
9. PROJECT Buffer-local context sets via links
Different context sets are useful in different chat buffers (or regular buffers), so it would be good to have a way to specify this. With a single global set of contexts, you often have to engage in the add-context/dump-context dance.
- [BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWU0ODE=]
- [BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWU0NzU=]
The plan we’ve arrived on is to add buffer-local context via links to files in Org/Markdown mode buffers – this doesn’t work for buffers or regions, unfortunately, unless we add a link type.
[ ]
Add buffer-local context support[ ]
Find a way to indicate that a link will be included in the context, perhaps theactivate-func
Org link property, and something bespoke for Markdown?[ ]
Send text file links along with media files
10. PROJECT Customizable/Org-aware prompt processing
To allow for features like https://github.com/karthink/gptel/issues/328, always create the prompt in a temp buffer. That way, we can add a list of filters to transform the text before sending, like Org’s export filters.
One commonly requested feature is removing the PROPERTIES drawers from the prompt in Org buffers before sending the request.
11. TODO Robustly distinguish between prompts and responses
Disadvantages of using text-properties for this:
- Roles are invisible
- If the text-properties are sticky, self-inserted text in a response region is assigned the response role, but yanked or otherwise inserted text isn’t.
- If the text-properties are non-sticky, there’s no way to modify the response text at all.
- Persistence across Emacs sessions is fragile (requires gptel-mode to be turned on)
There are several proposals for improving this:
- #321 How should gptel distinguish between LLM responses and user text?
- [BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6cHVsbHJlcTM0Mw==]
- [BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWU1NjU=]
- [BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWU1NDY=]
In short, they suggest:
- Using syntax, i.e. user-defined prompt and response prefixes in chat buffers.
- Using zero-width delimiters
- Providing response-highlighting and role-setting commands
- Using overlays
12. PROJECT Structured/JSON output
- Claude
- Via tool-use
- OpenAI
- Via tool-use or a “structured-output” mode
13. PROJECT Add better per-run processing support
We need a way to specify per-run pre- and post-response hooks, as well as transformation hooks.
TODO gptel-rewrite: Add post-rewrite hook that is called with the overlay
To apply custom user logic after the rewrite is ready, we could add a gptel-post-rewrite-functions
hook that is called with the overlay.
But anything added to this hook is buffer-local at best, and cannot be tailored to individual rewrite regions. An alternative is to add some kind of post-response callback behavior to gptel-request (or the gptel-rewrite command) itself.
This latter approach will solve a problem where we cannot modify gptel-request
’s callback for just one call.
14. MAYBE Use transient levels instead of gptel-expert-commands
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWUyODg=]
15. TODO Make it possible to attach description or instructions to context chunks
The idea is to allow a little before-string
before each context overlay, then incldue that before the chunk when creating the context. I’m not sure yet how to make this feature discoverable.
- Calling
gptel-add
with a prefix arg, or using a keybinding at the context overlay, should allow us to attach a description or instructionsgptel-context-annotate
bound toC-c C-a
gptel-context-clear
bound toC-c C-k
- This annotation should then be included with the chunk when creating the context string.
- This annotation doesn’t need to be stored as a variable, we can store it in the overlay and display it as a before string, maybe.
16. TODO Perplexity citation support
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWUyOTk=]
Instead of writing new response parsers wholesale for Perplexity, it might be possible to piggyback on the OpenAI parsers using cl-call-next-method
. Writing a response parser is significantly more work now that we support tool-use.
17. PROJECT gptel: Editing other buffers from the chat buffer
This is an oft-requested feature.
18. PROJECT RAG solution for gptel
Retrieval Augmented Generation, i.e. automatically fetching context for gptel requests.
It’s not clear yet how to do this. Just like we want to make gptel-tools
work with externally defined tool collections, I think it will be good to make RAG a plug-in option. There are many sources for RAG.
RAG brief explanation
providing the LLM with global and local context for gptel-complete
https://www.youtube.com/watch?v=wS1si5Lh9lA
Constructs the global context from files in the directory and LSP symbols. Can use imenu.
TODO starhugger: fim completions – check how context is found.
19. TODO gptel: Replace crowdsourced prompts with fabric prompts
20. TODO Stop tokens
- Claude
- JSON array of strings that will cause the model to stop generating text if encountered, specified at the top level of the API request(?)
21. TODO If redirecting to new gptel session, write entire template to it
[BROKEN LINK: No match for fuzzy expression: I don't want to populate the menu with even more options, at least for now. Dumping the full prompt if it's a new gptel session sounds like a good compromise to me, I]
22. TODO Read the MCP examples and spec
23. WAITING gptel-claude still losing data chunks ATTACH
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWUyNjE=]
24. MAYBE gptel: Add an undo boundary before the response
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWUyMzU=]
The problem with this is coordinating async insertions into the undo change group – it’s tough to do.
25. MAYBE Add a gptel-curl-extra-args for global extra Curl args
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWUyODM=]
26. MAYBE gptel: Put region pulsing in the after-response-hook.
27. MAYBE Good rewrite directives for gptel by madmacs
We can ask them if they want to contribute it to gptel.
https://github.com/certainty/madmacs/blob/main/modules/tools/madmacs-tools-ai.el
28. erts files for testing
29. PROJECT Vision
TODO Allow adding images from image data, not just image files
TODO Clean up gptel--wrap-user-prompt
, it’s a mess
This function is brittle and hardcodes the context.
Use the newly added gptel--inject-prompt
to make this more generic. The data model is simple: messages is just a list/array of prompts, and we want to add a prompt containing the context string to it at the right place. Work at this level of abstraction instead of what gptel--wrap-user-prompt
does right now.
30. CLOSED Process chain executor (FSM) for gptel [8/8]
To handle multi-turn requests, like those required for tool-use, we need something more robust than shoving function calls into callbacks. Unfortunately we don’t have access to a good promise API or to org-async right now1.
I may need to write a process executor ☹️.
[X]
Merge![X]
Create agptel-send
/gptel--suffix-send
specific transition table[X]
Separate the user messaging in gptel-send from the callbacks Almost – only the “Typing…” instruction is part of the process filter.[X]
Reuse the WAIT state after calling a tool[X]
Make gptel-request return just the fsm, no callback.[X]
Make gptel-request standalone.[X]
Rename fsm callbacks to fsm handlers[X]
Use a Finite State Machine (fsm) to drive gptel-request.
31. CLOSED Better diff interface [3/3]
There are a few things we need.
DONE A better default refactoring message and a better way to construct a refactoring message. Something that constrains the model more to output only code, without further questions or qualifications.
You are a % programmer. Generate ONLY code, with NO explanations. Do not ask for further qualifications, make assumptions as necessary. Do not use markdown code fences.
Refactor the following code.
Next, we add a hook where you can add functions to find a suitable initial refactoring message. For example, one of the hook functions can search the buffer for the string COMMITMSG, and provide a suitable one, and so on. The last one in the chain will produce a generic refactoring directive. We call this hook with run-hook-with-args-until-success
.
Next, this message should be editable in a temporary buffer. We want to reuse the system message editing buffer for this, so that needs to be made more generic. (Too bad string-edit
is not provided by compat
.)
CANCELLED A better system for entering the refactor message. Ideally we’d like to just add the message to an overlay at the location of the region being refactored.
The current system (minibuffer entry with extra context) is fine.
DONE A way to deal with the response that’s not immediate. Something like this:
- After selecting the region and specifying the refactoring message, we run gptel–rewrite
- We check heuristically to see if the output makes sense. i.e. it shouldn’t look like “What would you like to know.”
- When the LLM output is ready, we message the user with “Rewrite ready, M-x gptel-rewrite to apply”. This should also be available from the rewrite transient menu.
- What we do is: store the LLM output in a global variable.
- Now the user can choose to apply the output, or (e)diff or inline-diff against the original.
32. CLOSED gptel model-specific behavior framework
This is a collection of features supported by different APIs that I’d like to support on a model-level basis in gptel. I need to figure out how to structure the symbol-plist
of gptel models (which will now be symbols, not strings)
If all APIs support a feature (like stoptokens) we don’t need specialized behavior for it, we can just add it to the transient menu directly.
Feature | Global | Anthropic | OpenAI | Gemini | Ollama |
---|---|---|---|---|---|
stop tokens | Yes | ||||
Vision | |||||
Audio | |||||
Prompt caching | Yes | ||||
Function calling | Yes | ||||
JSON output | |||||
Fill-In-Middle |
As a precursor to adding vision support, function calling support, fill-in-middle support etc, we need a more granular way to specify model capabilities. The idea is to
- make
gptel-model
a symbol instead of a string, - whose
symbol-plist
will list the capabilities of that model, - which will be consulted when preparing the prompt
This will also require more prompt construction method for the various APIs.
33. SUSPENDED gptel-tasks
TODO Add JSON reply support
34. SUSPENDED Move to overlay tracking
WAITING Testing overlay tracking (gh issues/edge cases)
DONE Write some tests to check if promps are generated correctly.
35. SUSPENDED Implement gptel-complete
TODO gptel-complete: reimplement using completions
Using the chat API to generate completions is more or less unworkable. Need to use the completions APIs provided by LLMs instead and see how that fares.
36. SUSPENDED Function calling demos with Anthropic
37. SUSPENDED gptel: stateless design
TODO When gptel properties (like the system message or model) are set for a heading, use them under that heading instead of the buffer-local values.
MAYBE Store model, temperature etc as markdown front matter
- Note taken on
Just going to use file local vars for these for now. I might change my mind if I can find a simple toml parser eventually.
Should they be file-local vars instead? This is easier to handle, I don’t need to write a toml reader.
DONE Store response boundary marker positions as file local vars in markdown
Should it be file-local header line vars?
DONE How do I look up an org property/tag in the AST using org-element
?
Note taken on
(org-entry-get (point) "ID" 'inherit)
(org-entry-put (point) "testprop" "testvalue")
DONE Add prompts from awesome chatgpt prompts
The csv file is at https://github.com/f/awesome-chatgpt-prompts/raw/main/prompts.csv
DONE Add support for context from Org heading
DONE Store model, temperature, etc as top level Org properties
DONE Store response boundary marker positions in an org drawer or property
DONE When gptel-mode
is on, add to the buffer-local before-save-hook
to update these quantities.
38. CANCELLED gptel: more context options [1/2]
[-]
Integration with gptel-complete[X]
Branching conversations in Org
Sending other files/buffers
The options are:
- Send the full buffer
- Specify file(s) to include
- All open project buffers?
39. CANCELLED Add support for older versions of curl (< 1.8)
40. CANCELLED gptel editing prompt: use string-edit
- Note taken on
string-edit is Emacs 29.1+ only.
41. CANCELLED Use the :around cl-defmethod extra param to handle Org
Note taken on
Unfortunately this doesn’t work: there are too many places in the call chain that refer to gptel-backend et al, so it’s not sufficient to add extra defmethods forgptel--parse-buffer
andgptel--request-data
. Some of the other places includegptel-send
andgptel--suffix-send
(for messaging the user), andgptel--url-get-response
andgptel-curl--get-response
.Another problem with this approach: The org properties will have to be scanned for again by each defmethod.
The advice method is probably the best we can do.
In the feature-org branch: Currently the prompt parsing functions in gptel are advised to find the gptel parameters as Org properties if in Org mode. We can do away with this by using the qualifiers provided by cl-defmethod, see elisp#Generic Functions. This does the same thing as advice but is cleaner in the code. Might be harder to debug though.
42. CANCELLED Reset ollama context after changing model
- Note taken on
Switched to the Ollama chat API so there is no longer a context vector.
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWUyNzk=]
43. CANCELLED gptel & nixos: Write expression for Emacs 27.1 to test
44. CANCELLED azure backend with multiple models
45. CANCELLED gptel: copilot-style completion UI
This can be an add-on package – gptel-copilot
.
The main challenge is going to be finding a way to include enough context.
C-g
will abort the whole thing.C-=
will launch a diff/ediff.- Doing anything else will accept the completion.
46. DONE Claude error: text content blocks must contain non-whitespace text ATTACH
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWU0NTI=]
47. DONE Check out evedel
48. DONE Composable menus for gptel
Other packages can find it very useful to pick and choose components from gptel menus for their own purposes. However there doesn’t seem to be a way to do it.
50. DONE Fix gptel oneshot (non-streaming) Markdown -> Org converter
51. DONE markdown -> org stream converter: handling backticks
Here’s how the backtick parsing works in Markdown:
- A verbatim/src block can begin with any number of backticks.
- If it begins with one backtick
- this backtick is not followed by another backtick.
- The contents of the verbatim block can include any number of backticks.
- The end of the block is signalled by a backtick that is not next to a backtick.
- If it begins with multiple backticks
- Any sequence of fewer backticks is part of the verbatim block
- A sequence of as many backticks ends the verbatim block
So here’s how we set in-src-block:
If we see a backtick, check if the char-after is a backtick
If yes,
- hold on until we see something other than a backtick,
- then set in-src-block. Keep count of the number of backticks.
- If we see this many backticks again, turn off in-src-block.
If no,
- set in-src-block.
- If we see another backtick, wait to make sure that it’s isolated – i.e. not preceeded/followed by a backtick.
- When this is the case, turn off in-src-block
52. DONE gptel: handle headings in the markdown converter
gpt-4 has started using ###
headings in its answers. Convert to Org headings or do something with them.
53. DONE Update Joao Tavora about commits I added
https://github.com/karthink/gptel/issues/184
And the ones I’m not adding and why.
54. DONE gptel: always-available diffing
It would be great to be able to (e)diff the last thing added to the buffer by the LLM. It would be even better to ediff across all previous states, but I’m not sure how to do this – some kind of integration with undo?
For one-step ediffs, here’s the info we need:
- state of the buffer before gptel killed some text, if any.
- state of the buffer after the response.
Other options: hook into after-change-functions – bad idea?
Since gptel’s edits to the buffer are local: (optionally) kills text and adds text at point, we can get away without diffing the whole buffer. (There may be user-driven edits in other parts of the buffer in the meantime that we don’t care about anyway.)
So:
- If killing text: keep the text in a buffer-local var
- In post-response-functions, add (at the end, at position 99), store the text in another buffer-local var. Or it could be a single cons containing the previous string (if any), along with other metadata.
- In the transient menu, we provide an option to (e)diff last LLM response in this buffer. When called… ?
To implement the feature described, the strategy seems plausibly efficient. Here are some potential steps:
- The functionality to (e)diff between two content states can be implemented as a separate function, perhaps
gptel-ediff-last-response()
. - You can make use of two buffer-local variables to keep track of the content state before and after the LLM’s edit. You can name these variables as
gptel-last-pre-edit-content
andgptel-last-post-edit-content
respectively. Be aware to accurately update these variables whenever an edit operation happens. - You would probably want a third buffer-local variable to keep track of the position where the LLM made its last edit (e.g.,
gptel-last-edit-position
). - Additionally, you might want to make these states persistent across emacs sessions for the users. You can use standard emacs lisp constructs like
save-excursion
to preserve point and other state in the process. - In the
gptel-ediff-last-response()
, create two temporary buffers (ordiff
buffers). You can insert the content ofgptel-last-pre-edit-content
into the first buffer, andgptel-last-post-edit-content
into the second buffer. - After storing the content, use
ediff-buffers
or similar functionality to perform the diffing.
It will also be nice to have a mechanism to clear the tracked state, maybe a function gptel-clear-diff-state()
. Also, consider adding a new key to the gptel’s transient menu which can be used to trigger this ediff operation. Users can also bind this function to a keystroke if they use it frequently.
By allowing users to trigger this diff function it would make it easier for them to visually see and understand what the LLM has changed in their content.
Remember to handle error states and edge cases gracefully - for example, what happens if a user tries to ediff when no edit operation has been made by the LLM yet (i.e., the buffer-local variables are null or undefined)? Effective user feedback and good documentation will be key to making this feature successful.
Finally, an additional feature to consider for the future might be to allow users to ediff between any two arbitrary past states, not just the most recent one. For this feature, a history of past states must be maintained. That could be a more significant design and performance endeavor, but it could also be a powerful tool for users.
55. DONE gptel: Add logging
56. DONE gptel-request: the :buffer
and =:position keyword args aren’t clear
- Note taken on
- buffer
- the buffer where the response is inserted
- position
- the position in :buffer= where the response is inserted
It’s not clear what these keyword args do, or even what they should do exactly.
57. DONE gptel: multi-line directive writing
58. DONE gptel: Google gemini support
Documentation: Rest API: https://ai.google.dev/tutorials/rest_quickstart Model parameters: https://ai.google.dev/docs/concepts#model_parameters
59. DONE defgeneric
system for querying other APIs?
- Note taken on
Settled for using cl-structs instead. Might still use defgeneric if the parsing differs considerably between backends.
This will make it easier to add support for
- Azure
- Dall-E
- Local LLMs, etc
60. DONE Stateless design + save state
61. DONE Tag new gptel
release
62. DONE Add algal and d1egoaz to the gptel acknowledgments section
63. DONE gptel error handling for local llms
[BROKEN LINK: No match for fuzzy expression: ;; TODO: Handle this for ollama, see the new code in `gptel-curl–stream-cleanup']
64. DONE gptel: Add kill-ring as source of prompt
65. DONE gptel: make defining openai backends easier
Mainly the :header (lambda () bearer-token-stuff)
needs to be automated, so that it can work with and without a specified key for that backend.
66. DONE Reply to ahyatt’s proposal for llm actions
67. DONE file-local-var storage with newlines: reply to Eli
68. DONE LLM UI experiments – reply to Andrew
69. DONE gptel: post-response hook’s beginning position is wrong
It includes the response prefix.
70. DONE gptel-anthropic parser losing text ATTACH
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWUyNjE=] Raw data from filter-function reads
71. DONE Reply to Jan Rychter’s email
Email from Jan Rychter: Re: [karthink/gptel] Separate system prompts and directives (Issue #249)
How is gptel more complex than the web UI?
72. DONE Make gptel bugfix release
73. DONE gptel: Add a non-chat boolean for regular buffers
See this issue.
74. DONE gptel: context indicator in header-line
75. DONE Reply to tarsius
76. DONE Further fix gptel org formatter ATTACH
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWUyOTY=]
77. WAITING Fontification malfunction when streaming responses
78. DONE gptel-gemini parser: :parts
can have multiple :text
blocks
[BROKEN LINK: No match for fuzzy expression: :parts 0 :text)))]
79. DONE purpose-mode interferes with gptel’s display
[BROKEN LINK: orgit-topic:Z2l0aHViLmNvbTpSX2tnRE9KRngwZGc6aXNzdWUyMzc=]
80. DONE Improve docs around :key
Thank you, didnt know that. Mind you add this as an example to the docs, please? The docs are a bit misleading as it says:
The :key can be a function that returns the key (more secure).
So i was thinking i had to develop my own function.
81. TODO Find a better way to handle Ollama tool use + no-stream
82. TODO gptel-rewrite tweaks suggested by mike olson
Footnotes:
Org-async wouldn’t work anyway since running down the process tree depends on more than just the success/failure of the previous process.