-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
feat(ai): Enable Context Variables for Chat Requests #14787
Conversation
99f4536
to
52825d5
Compare
4650527
to
50de13b
Compare
d2b81c4
to
fb4c2b5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the work. I had a first look.
I tested on aea0e4d with the fix from #14942 cherry-picked on top
Sadly I have some usability issues:
Too narrow chat view breaks variable
Text and Variable
Adding variableText, e.g. file:my-path
AND a marker to the chat input is unintuitive. It's not clear to me whether I need to keep the text or whether I can delete it and what the difference is when keeping the text and not. Also sending a message will get rid of the text in the prompt either way for the follow up message, however the context is still rendered.
Not all agents get the content
I would have expected that no matter what agent is used, they would get the content of the file injected in some way. However Universal does not seem to have access / care about the variables
Drag and Drop uses a different variable
Drag and Drop adds files via file-provider:path
instead of file:path
Switching threads
Switching sessions or creating a new one does not clear the context
@sdirix Thank you very much for the review! I've addressed most of your comments (see my direct inline replies). Too narrow chat view breaks variableOh, right, thanks. I've fixed this in a8c2966. Text and VariableThere are two separate things:
Variables in the input get resolved to a Context variables are resolved to a Edit: A variable can be just a plain variable (it doesn't provide a If now a user drags a context variable into the text input, it has two effects: it'll add the variable in the user input (to be replaced by I think this distinction is very valuable, because it allows users to add elements into the context and mention them in the text, while the framework has the flexibility to allow replacing the occurrence in the text input with a different (shorter) value, such as a name or identifier, than in the context. At the example of how a file agent could use this: Of course, I see your point that it is not quite obvious, as both seem equivalent and are synchronously added when I type something, but then not removed when the corresponding text in the input is removed. Not sure how to best improve the situation though. Introducing a flag that remembers which context was added automatically and then remove this too, when we remove the text? But this felt a bit over-complicated. Not all agents get the contentRight, but coder will use it (#14895). (Comment from Jonas: Also universal and workspace: #14945) Drag and Drop uses a different variableRight, I think this was caused by a parallel change. I've fixed this now for consistency. Switching threadsRight, my feeling was this is a good thing. It'd be easy to change, but we also don't clear the text input when switching threads, so I felt is is more consistent this way and opens up further use cases (e.g. starting a new thread with the list of files that I currently work on). But I'm open to what others think! Thanks again for your review! |
This PR introduces support for adding context elements (e.g., files, symbols, or domain-specific concepts) to chat requests, allowing chat agents to leverage additional context without embedding it directly in user input. - Extended the existing *variable* concept with `AIContextVariable`. - Context variables can provide a dedicated `contextValue` that agents can use separately from the chat request text. - Context variables can be included in chat requests in two ways: 1. Providing `AIVariableResolutionRequest` alongside the `ChatRequest`. 2. Mentioning a context variable directly in the chat request text (e.g., `#file:abc.txt`). - Extended the chat input widget to display and manage context variables. - Users can add context variables via: 1. A `+` button, opening a quick pick list of available context variables. 2. Typing a context variable (`#` prefix), with auto-completion support. - Theia’s label provider is used to display context variables in a user-friendly format. - Enhanced support for variable arguments when adding context variables via the UI. - Introduced: - `AIVariableArgPicker` for UI-based argument selection. - `AIVariableArgCompletionProvider` for auto-completion of variable arguments. - Added a new context variable `#file` that accepts a file path as an argument. - Refactored `QuickFileSelectService` for consistent file path selection across argument pickers and completion providers. - `ChatService` now resolves context variables and attaches `ResolvedAIContextVariable` objects to `ChatRequestModel`. - Variables can both: - Replace occurrences in chat text (`ResolvedAIVariable.value`). - Provide a separate `contextValue` for the chat model. Fixes #14839
Don't have the chat-view-language-contribution prefix the completion item, but give the provider full control. This enables triggering the completion also on : and #.
a8c2966
to
6f72322
Compare
@sdirix Sorry for the force-push. I had to rebase and resolve conflicts after #14716. In addition (6f72322), I made the code completion now also trigger at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the detailed explanations. Following them I was able to leverage the context
As far as I understand we will add the ability to understand the context to all agents we offer by default. This is then fine with me as a first implementation.
Some follow ups to consider to improve the UX:
- All agents will always run the tool function to discover the list of context items, no matter whether something is placed there. This pollutes the chat. Maybe there should be a mechanism to dynamically add the context tool functions only if there is actually a context in the request.
- In case an agent has a LLM without tool support configured, we should highlight that the context will not be used, e.g. with a grey transparent overlay
- One step further: If we have a prompt without the context tool functions and without that dynamic behavior outlined above, we should also disable / mark the context as not in use.
I think it's very important for the release that we have a clear and understandable UX for the context as otherwise we will get a lot of issues reported that the feature is not working.
I am not sure I get this. In Workspace and Coder, they will not have to run such as function, as we place the context list in a variable in the prompt, there will be only a tool call if the LLM looks at content.
=> Very valid case, for universal, it will work, as we resolve the context. Coder and Workspace won't actually work at all without functions.
=> Yes, it is a bit tricky, I will track this
|
@sdirix Thank you very much for your review and for adding the translation!
I absolutely agree. Doing this upfront, however, may require a lot of flags that each agent needs to provide. I think one option that is easier to do generically is to add an indicator in the response which context was processed. We could track the variable resolution for a request in the chat service and the tool functions could notify the chat model that they've consumed a specific context. We could add an additional WDYT? |
very interesting idea! if we do this, I believe the notification should happen in the context itself, as we can also consume the context via variables or API, not only via functions. |
I see, I was using the tool function to look a the content which is part of this PR. Using a variable is better 👍 |
Exactly, I think we need the API on the mutable chat response and then have the chat service (on variable resolution) and the tool functions (on invocation) use this API to report that context has been resolved. |
I like the idea! Each response could have a copy of the context including the marker which of it was used. Then we could show for each response what was in the context and what was used, for example in a collapsible section, in a rich hover over etc. |
I've extracted #14961 |
|
||
registerDropHandler(handler: AIVariableDropHandler): Disposable; | ||
unregisterDropHandler(handler: AIVariableDropHandler): void; | ||
getDropResult(event: DragEvent, context: AIVariableContext): Promise<AIVariableDropResult>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@planger With this change, it looks like this file should be moved to the browser
folder, as its types now require DOM typing, and it couldn't reasonably be instantiated on the backend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for raising this issue! You are right, this is an oversight.
I think it'd be best if we could avoid moving the variable service entirely to the frontend. How about adding an additional contribution point with a frontend only binding, and have the variable service on the frontend collect the contributions in addition to what the common variable service does?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've suggested a fix here: #14969 Thanks again for raising this issue!
In #14787 we've introduced a DOM type dependency to the common package, which prevents it from being properly used on the backend. This change moves the parts that depend on the DOM to the frontend.
In #14787 we've introduced a DOM type dependency to the common package, which prevents it from being properly used on the backend. This change moves the parts that depend on the DOM to the frontend.
What it does
This PR introduces the ability for users to add contextual information to chat requests. This allows manually passing elements such as files, symbols, or other variables, which chat agents can then utilize when generating responses.
Context Variables
To represent contextual elements, we extend the existing variables concept. Previously, variables were placeholders within chat request text (e.g.,
#selectedText
), dynamically resolved by the chat service before processing (ResolvedAIVariable.value
), replacing the occurrence of the variable directly in the user input.With this PR, we introduce context variables (
AIContextVariable
), which enhance the existing variables by not only resolving a value for text replacement but also attaching a dedicated context value (ResolvedAIContextVariable.contextValue
) to the chat request. This enables agents to use contextual information without making it a fixed part of the user’s input.Key Benefits:
Context Variable Resolution
Context variable requests (
AIVariableResolutionRequest
) can be passed alongside aChatRequest
to theChatService
. The chat service then resolves context variables and attaches them to theChatRequestModel
under thecontext
property.If a context variable is referenced in the chat request (e.g.,
#file:abc.txt
), it serves a dual purpose:ResolvedAIVariable.value
replaces the variable in the chat text.ResolvedAIContextVariable.contextValue
is added to the chat request model.Attaching Context Variables
Context variables can be added to a chat request in two ways:
AIVariableResolutionRequest
objects toChatService.sendRequest
alongside theChatRequest
.#file:abc.txt
). The chat service automatically parses it into a variable request and attaches it to the context.User Interface Enhancements
To support context variables, the chat input widget now maintains a list of added context variables. This list appears below the text input and utilizes Theia’s label provider mechanism for user-friendly display (including labels, additional information, and icons). Users can add context variables through:
+
button): Opens a selection dialog listing all registered context variables. To improve usability, theAIVariable
interface now includes optionallabel
andicon
properties.#
prefix): Users can type context variables directly into the chat input. The existing code completion mechanism suggests context variables, and selecting one also adds it to the context variable list.Variable Arguments
Variables support arguments (parameters) that influence their resolution. This PR enhances argument handling by introducing:
AIVariableArgPicker
: Invoked when users add context variables via the Quick Pick dialog (+
button).AIVariableArgCompletionProvider
: Invoked when users type context variables manually.With these two mechanisms, variable providers can choose how to support users in selecting the right arguments via a UI or via auto-completion.
Example: File Context Variable (
#file
)To demonstrate these improvements, we introduce a new context variable
#file
, which accepts a file path as an argument. We also register:#file
via the Quick Pick dialog.#
and get file path suggestions directly.Therefore, we've refactored existing code into a
QuickFileSelectService
to provide a consistent file picker experience for both argument pickers and completion providers as well as for the existing file search (Ctrl-p).Utilizing Chat Request Context
Chat agents can determine how they process the provided context. Common approaches include:
Fixes #14839
How to test
Use the
+
icon to add context filesadding-context-plus.webm
Use the context variable auto complete
adding-context-auto-complete.webm
Use the context variable argument auto complete
adding-context-auto-complete-arg.webm
Use drag and drop to add files to the context
adding-context-drop.webm
Follow-ups
Breaking changes
Attribution
Review checklist
Reminder for reviewers