-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Cody completion: Mega bug bash thread #52365
Conversation
client/cody/src/completions/index.ts
Outdated
if (error.message === 'aborted') { | ||
return [] | ||
} | ||
|
||
console.error(error) | ||
debug('CodyCompletionProvider:inline:error', `${error}\n${error.stack()}`) |
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.
client/cody/src/completions/index.ts
Outdated
@@ -28,6 +28,7 @@ export class CodyCompletionItemProvider implements vscode.InlineCompletionItemPr | |||
private maxSuffixTokens: number | |||
private abortOpenInlineCompletions: () => void = () => {} | |||
private abortOpenMultilineCompletion: () => void = () => {} | |||
private lastContentChanges: Map<string, 'add' | 'del'> = new Map() |
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.
Question: This map can grow with the number of files changes in one session. Do you think we should rather use a LRU cache here instead right away or is it fine if we get back to that later?
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.
since I barely ever restart vscode, it could be that this grows unboundedly 🤔 Maybe if it's not a ton of effort rather do it now vs bad surprises later?
// Avoid showing completions when we're deleting code (Cody can only insert code at the | ||
// moment) | ||
const lastChange = this.lastContentChanges.get(document.fileName) ?? 'add' | ||
if (lastChange === 'del') { | ||
// When a line was deleted, only look up cached items and only include them if the | ||
// untruncated prefix matches. This fixes some weird issues where the completion would | ||
// render if you insert whitespace but not on the original place when you delete it | ||
// again | ||
const cachedCompletions = inlineCompletionsCache.get(prefix, false) | ||
if (cachedCompletions) { | ||
return cachedCompletions.map(toInlineCompletionItem) | ||
} | ||
return [] | ||
} |
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.
New heuristics: Avoid showing completions when we're deleting code
There is only one exception and that is when we have a cached completion at exactly the same prompt. This necessary since you could be inserting spaces and then pressing backspace to get back to were you were before (exactly when you triggered the completion) and we currently show the same completion while you insert more backspace but then would hide it when you go back.
Here's a video of the new behavior:
Screen.Recording.2023-05-24.at.14.12.59.mov
Notice there is a bug right now because we add a cache entry for the completion with a trimmed prefix and that is now also matching in this logic. You can see this at the end of the video where removing all indentation from the line reveals the suggestion again. We need some extra bookkeeping to fix this so I decided it's not worth doing it just yet. WDYT?
Todo for myself: Add a todo about that in code
await new Promise<void>(resolve => | ||
setTimeout(() => resolve(), Math.max(0, waitMs - estimatedLLMResponseLatencyMS)) | ||
) |
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.
Bug fix: The previous heuristics would use the waitMs
and subtract the estimated LLM response. I looked at prod data for dotcom and the estimate was overshooting it but also I noticed that the waitMs
was set to 500 before and the latency to 700 so we would not debounce in some situations 😬
I've tweaked the timeouts again. It will unfortunlaty be a bit slower but in most cases it's not noticeable. Start of the line completions are now properly debounced by 200ms though!
if (hasVisibleCompletions(results)) { | ||
const params = { ...LOG_INLINE, latency: Date.now() - start, timeout } | ||
logEvent('CodyVSCodeExtension:completion:suggested', params, params) | ||
inlineCompletionsCache.add(results) | ||
return results.map(toInlineCompletionItem) |
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.
Bug fix: We were recording completions as being suggested even though they might all be empty.
I've also added some logging to get a better understanding of latency and timeouts used.
@@ -213,7 +213,7 @@ export class EndOfLineCompletionProvider extends CompletionProvider { | |||
suffix: string, | |||
injectPrefix: string, | |||
defaultN: number = 1, | |||
protected multiline: boolean = false | |||
protected multilineMode: null | 'block' | 'statement' = null |
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.
Change: While not needed yet, this adds support for a statement delimited multiline request as well. This will use different conditions to truncate the response and will be necessary to allow completions in these scenarios:
const result =
// If odd indentation is detected (i.e Claude adds a space to every line), | ||
// we fix it for the whole multiline block first. | ||
// | ||
// We can skip the first line as it was already corrected above | ||
if (hasOddIndentation) { | ||
for (let i = 1; i < lines.length; i++) { | ||
if (indentation(lines[i]) >= startIndent) { | ||
lines[i] = lines[i].replace(/^\ /, '') | ||
} | ||
} | ||
} |
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.
New heuristics: We already identified "odd" space insertions before. After more trial and error, I noticed that when this case happens (where Claude inserts a space before the response even though the indentation would match), it will actually do so for every line that is part of this indentation in a multiline request.
This tries to fix it. 🤞
@@ -302,7 +323,7 @@ export class EndOfLineCompletionProvider extends CompletionProvider { | |||
if (indentation(line) < startIndent) { | |||
// When we find the first block below the start indentation, only include it if | |||
// it is an end block | |||
if (line.trim() === '}') { | |||
if (line.trim().startsWith('}')) { |
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.
Change: This makes it so that if something closes in e.g. })
, it would also be emitted.
// If a completed line matches the next line of the suffix 1:1, we remove | ||
const lines = completion.split('\n') | ||
const matchedLineIndex = lines.findIndex((line, index) => { | ||
if (index === 0) { | ||
line = currentLinePrefix + line | ||
} | ||
if (line.trim() !== '' && nextLine.trim() !== '') { | ||
// We need a trimRight here because the machine likes to add trailing whitespace. | ||
// | ||
// TODO: Fix this earlier in the post process run but this needs to be careful not | ||
// to alter the meaning | ||
return line.trimRight() === nextLine | ||
} | ||
return false | ||
}) | ||
if (matchedLineIndex !== -1) { | ||
completion = lines.slice(0, matchedLineIndex).join('\n') |
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.
New heuristics: Single and multi-line completions are now being checked to exactly match the next line. In case of a single line completion, they will be removed. In case of multi-line, we truncate the response. See this comparison:
Before:
After:
(added some logging to the second screenshot to show you this actually worked)
// Ignore completions that start with a whitespace. These are handled oddly in VS Code | ||
// since you can't accept them via tab. | ||
// | ||
// TODO: Should we trim the response instead? | ||
if (completion.trimStart().length !== completion.length) { | ||
return null | ||
} |
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.
New heuristics: We have gotten complaints the the suggestions would start with whitespace which will make it impossible to accept them via tab
(since that would instead add a tab character if that is the case).
So for now, filter them out.
client/cody/src/completions/index.ts
Outdated
@@ -28,6 +28,7 @@ export class CodyCompletionItemProvider implements vscode.InlineCompletionItemPr | |||
private maxSuffixTokens: number | |||
private abortOpenInlineCompletions: () => void = () => {} | |||
private abortOpenMultilineCompletion: () => void = () => {} | |||
private lastContentChanges: Map<string, 'add' | 'del'> = new Map() |
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.
since I barely ever restart vscode, it could be that this grows unboundedly 🤔 Maybe if it's not a ton of effort rather do it now vs bad surprises later?
Shipping behind the existing feature flag. |
This PR includes a bunch of fixes regarding #51344 I've not done a good job at splitting this up into commits and I will also need to add some tests for this (I have some ideas for how to make an effective test setup for this already) but for now, I did some extensive explanation of the changes and why they are added inline 🙂 ## Test plan See test plan added to the inline discussions. <!-- All pull requests REQUIRE a test plan: https://docs.sourcegraph.com/dev/background-information/testing_principles -->
This PR includes a bunch of fixes regarding #51344
I've not done a good job at splitting this up into commits and I will also need to add some tests for this (I have some ideas for how to make an effective test setup for this already) but for now, I did some extensive explanation of the changes and why they are added inline 🙂
Test plan
See test plan added to the inline discussions.