-
Notifications
You must be signed in to change notification settings - Fork 256
Add GitHub CI workflow, for running ERT #865
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jwiegley
wants to merge
12
commits into
karthink:feature-augment-buffer
Choose a base branch
from
jwiegley:github-ci-workflow
base: feature-augment-buffer
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Add GitHub CI workflow, for running ERT #865
jwiegley
wants to merge
12
commits into
karthink:feature-augment-buffer
from
jwiegley:github-ci-workflow
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* gptel.el (gptel--with-buffer-copy): In preparation for gptel's switch to fully buffer-oriented prompt preparation (needed for augmentation), make `gptel--with-buffer-copy' - copy all the required state into the prompt preparation buffer. - Keep the buffer alive for current for augmentation and parsing instead of using `with-temp-buffer'. The latter means that the prompt preparation buffer is never cleaned up after a request, and gptel is thus buggy as of this commit. This will be rectified next.
Previously, gptel's prompt construction worked as follows: 1. If the prompt is nil or a string, copy the text to be sent to a temporary buffer, and use it to create the messages array. If the prompt is a list of strings, create the messages array from it directly (with no intermediate buffer). 2. Feed this array along with the specified or environmental parameters like the backend, model, system message and other parameters to `gptel--request-data', which produces the full payload. gptel is now inverting this flow: 1. Whatever the prompt, copy it to a temporary buffer (the "prompt buffer") using `gptel--create-prompt-buffer' or directly with `gptel--with-buffer-copy'. Use the new function `gptel--parse-list-and-insert' to insert a list-of-strings prompt into the prompt buffer. 2. Also copy the environment to this temporary buffer as buffer-local variables. 3. Apply any augmentations/transformations/context injections to this prompt buffer. This can involve changing the buffer contents and/or changing the environment, i.e. buffer-local variables such as the model, backend or system prompt. The ability to do this is the main reason for this inversion. One example of this is the upcoming just-in-time preset feature. NOTE: transformations are not yet implemented. 4. Construct the full payload using `gptel--request-data' inside the prompt buffer. * gptel.el: (gptel--parse-directive): Add FIXME for later (gptel--parse-list-and-insert): Inserts prompts, a list of strings, into the current buffer with user/llm/tool roles applied. (gptel-request, gptel--realize-query): Split the work of `gptel-request' into two functions. `gptel-request' now handles only the creation of the prompt buffer. `gptel--realize-query' runs in the prompt buffer and does the actual payload realization. (gptel--create-prompt): Remove function (gptel--create-prompt-buffer): Renamed from `gptel--create-prompt', now returns the prompt buffer instead of a messages array. No longer handles context injection. * gptel-org.el (gptel-org--create-prompt): Remove function (gptel-org--create-prompt-buffer): Renamed from `gptel-org--create-prompt', now returns a buffer instead of a messages array.
* gptel.el: (gptel-prompt-filter-hook, gptel-prompt-transform-functions): Introduce a hook to hold transformations to apply to the prompt. This will be used to hold functions for context injection, Org property stripping and so on, as well as just-in-time preset application and any RAG plugins. This hook will be passed explicitly to `gptel-request' as an argument, since `gptel-request' is supposed to be a simple function by default, with behavior that depends as little on global variables as possible. Obsolete `gptel-prompt-filter-hook', since it is superseded by `gptel-prompt-transform-functions'. This hook currently does nothing, and will be added to the `gptel-request' pipeline next. (gptel--with-buffer-copy, gptel--create-prompt-buffer): Remove gptel-prompt-filter-hook from the prompt-buffer creation pipeline. * gptel-org.el (gptel-org--create-prompt): Remove gptel-prompt-filter-hook from the prompt-buffer creation pipeline.
Use `gptel-prompt-transform-functions' in `gptel-request', enabling a prompt transformation/augmentation pipeline. This pipeline will be used for just-in-time presets, adding gptel's context to the request and other operations that are critical to `gptel-send'. `gptel-prompt-transform-functions' is not automatically applied to `gptel-request' calls, it must be passed explicitly via the `:transforms' argument. This is so that gptel-request stays closer to a 'pure' function, for use as a library. `gptel-send' passes the transforms explicitly to `gptel-request'. * gptel.el (gptel--create-prompt-buffer, gptel--create-prompt): New function `gptel--create-prompt-buffer', used to create a prompt buffer with the appropriate text to be sent (pre-transform). `gptel--create-prompt' is no longer used but retained for compatibility and testing. (gptel-request): Add the `:transforms' argument and docstring. Run `gptel-prompt-transform-functions' here. In short, create the prompt construction buffer with `gptel--create-prompt-buffer', then run through the transforms. The preset transform is applied first, since it can change the value of `gptel-prompt-transform-functions'. The rest are applied via a wrapped hook that distinguishes between sync and async transforms via function arity, and uses a "gather" method to track completion. TODO: Async transforms end up running in parallel, so there is a race condition involving buffer mutation when there is more than one. This will be fixed in the future. * gptel-transient (gptel--suffix-send): Add `:transforms' to the `gptel-request' call. * gptel-rewrite (gptel--suffix-rewrite): Add `:transforms' to the `gptel-request' call.
* gptel.el (gptel--inspect-query): If there are async prompt augmentors/transformers in the mix, the fsm passed to `gptel--inspect-query' by gptel-request will not yet be ready for consumption. Poll until payload construction is complete. This is an interim solution while I figure out how to modify the call chain to make this expensive timer unnecessary.
Previously, adding context (from gptel-context) to the query payload was a bespoke step, and tied into `gptel-request'. It was carried out by mutating the messages array after buffer parsing. Now that the `gptel-request' pipeline has been inverted, context addition is carried out in the prompt construction buffer, and is handled as a regular transform function in `gptel-prompt-transform-functions'. As a result, the context addition step can now be asynchronous, since the user might want to truncate or augment it depending on its size and content. By default, context addition works by inserting into the prompt construction buffer, or by modifying the system message in the buffer. The only exception to this is handling media files in the context -- there is no universal buffer-oriented method for doing this, so `gptel--wrap-user-prompt' is still used for attaching media from `gptel-context--alist'. TODO: This will be fixed in the future. This deprecates some aspects of the gptel-context API, including `gptel-context-wrap-function'. * gptel-context.el (gptel-context-wrap-function): Obsolete. This is no longer used. Customize `gptel-context-string-function' instead or advise `gptel-context--wrap-in-buffer' if that's insufficient. (gptel-context--wrap): This function serves the same purpose as before, but now works by mutating the prompt construction buffer. It takes a callback and can be asynchronous. (gptel-context--wrap-in-buffer): New function to add the context string to the prompt construction buffer, etiher as text or by modifying the buffer's system message. (gptel-context--wrap-default): Remove, as this is covered by `gptel-context--wrap-in-buffer'. * gptel.el (gptel--transform-add-context): Augmentor for adding context to the request, which calls gptel-context- functions. This will be added to `gptel-prompt-transform-functions' next. (Context addition is currently non-functional in gptel.) (gptel--realize-query): Move context addition step from here back to the transforms/augmentation step. Handling media files in the context is an exception and it still happens here. (gptel--wrap-user-prompt-maybe): Remove, no longer needed.
* gptel.el (gptel-prompt-transform-functions): Set the default transformers/augmentors. They (i) apply any preset included at the beginning of the prompt (via `@preset`) and (ii) add gptel's context to the prompt buffer. Note that `gptel-prompt-transform-functions' (or a list containing augmentors) needs to be passed explicitly to `gptel-request' (via the `:transforms' argument) for it to take effect. `gptel-send' does this. It is not read from the environment as this can have unexpected side-effects when using `gptel-request' as a library.
Catch strings of the form `@preset-name` anywhere in the user prompt and apply the preset in the transform/augment step. This change is experimental, and will be reverted if there are unexpected consequences or performance problems. This change is to make it easy to specify an on-the-fly preset when the user prompt structure is slightly off. Two examples: 1. When the user prompt is structured as ** Some heading *Prompt*: @preset-name ... where the heading is used for structural purposes. Technically the user prompt begins at the heading, but it's clear from context that the user intends to apply preset-name to the message. 2. When the preset specification naturally comes at the end. <long chunk of text> What do you make of the above, @explainer? This also promotes a more conversational preset usage style. * gptel.el (gptel--transform-apply-preset): Scan the entire user prompt for `@preset-name` mentions and apply presets as they are found. (gptel--fontify-preset-keyword): Fontify all `@preset-name` mentions in the user prompt. (gptel--prettify-preset): Adjust for new fontification keyword.
386b349
to
eca523b
Compare
243e824
to
b2679ec
Compare
b2679ec
to
e009fc7
Compare
ed41950
to
40ef63b
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.