Skip to content
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

Attach supplemental context to InlineCompletions request #463

Merged
merged 20 commits into from
Sep 26, 2024

Conversation

viktorsaws
Copy link
Contributor

@viktorsaws viktorsaws commented Sep 20, 2024

Problem

We don't attach cross file context Q InlineCompletion requests.

Solution

Entry point for using supplementalContext changes start in CodewhispererServer.ts. Supplemental context is computed for requested TextDocument, cached in Inline completion Session and attached to generateSuggestions service call. Then, supplemental context fields also added to CodeWhisperer Telemetry events, emitted from the server.

All computation logic and helper functions are ported as is, with only adapting them to work with LSP documents instead of VSCode APIs. Most unit tests also migrated as is, with adding extra tests for coverage.

This PR requires aws/language-server-runtimes#214 to be released in Runtimes.
Diff between original code and new code introduced here can be seen in viktorsaws#5.

TODO

  • Unit tests

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@@ -20,6 +20,10 @@ export interface CodeWhispererServiceInvocationEvent {
codewhispererGettingStartedTask?: string
reason?: string
credentialStartUrl?: string
codewhispererSupplementalContextTimeout?: boolean
Copy link
Contributor

@ege0zcan ege0zcan Sep 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: from the name of this field, it is hard to understand that this is a boolean value showing whether the context collection timed out or not

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but this is a Telemetry object field, as defined by CodeWhisperer service. We don't control the name and expected type here.

* The file distance between A/B/C.java and A/D.java is 1
*/
export function getFileDistance(fileA: string, fileB: string): number {
// TODO: Test how it works with nested folders with spaces (%20 symbol)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This todo is not coming from the toolkit codebase but something we are introducing, why is that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is something I noticed when comparing logs for VSCode Q and Language Server. In Language server, files URIs are encoded and spaces are converted to %20 string. Since this is different from original environment, I wanted to double check that in this case this function works. I added few tests to cover this and will remove this comment,

): CodeWhispererSupplementalContext | undefined {
const timesBeforeFetching = performance.now()

const isUtg = isTestFile(document.uri, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have full context, what does UTG actually stand for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it stands for "unit test generator". I don't know how significant this meaning is, tbh.

@@ -573,6 +605,28 @@ export const CodewhispererServerFactory =

logging.log('Amazon Q Inline Suggestion server has been initialised')

const logSupplementalContext = (supplementalContext: CodeWhispererSupplementalContext | undefined) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this too verbose, i see in vscode toolkit codebase they use debug logging to log this information whereas it seems we log always

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, yeah you're right. I added it as normal log since we don't have different log levels implemented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed excessive logging in last commit

@@ -760,15 +763,15 @@ describe('Telemetry', () => {
aUserTriggerDecision({
codewhispererSessionId: 'cwspr-session-id-0',
codewhispererSuggestionState: 'Discard',
codewhispererTimeToFirstRecommendation: 2520,
codewhispererTimeToFirstRecommendation: 1260,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was this an intentional change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This is caused by changing nested callback in CodeWhispererServer to async and I suspect it changes the chain of async callbacks resolution. The test emulates several inflight requests, and only this time in test environment is impacted.
In my manual E2E testing with compiled server, times are at same rate as before this change. I didn't want to refactor this test as it too complex :(

@viktorsaws viktorsaws force-pushed the crossfile_context_src_only branch from ae70cec to 335a895 Compare September 26, 2024 10:16
@viktorsaws viktorsaws merged commit 813978f into aws:main Sep 26, 2024
5 checks passed
maxResults: 5,
supplementalContexts: [
{ content: 'sample-content', filePath: '/SampleFile.java' },
{ content: 'sample-content', filePath: '/SampleFile.java' },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it send the same file twice?

@@ -467,6 +474,39 @@ describe('CodeWhisperer Server', () => {
assert.deepEqual(result, EMPTY_RESULT)
})

describe('Supplemental Context', () => {
it('should send supplemental context', async () => {
// Open 3 files supporting cross-file context
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: 2 files?

@@ -21,12 +21,13 @@
"compile": "tsc --build",
"postcompile": "npm run copyServiceClient",
"copyServiceClient": "copyfiles -u 1 --error ./src/client/sigv4/*.json out && copyfiles -u 1 --error ./src/client/token/*.json out",
"fix": "npm run fix:prettier",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: do we really need this duplication?

@@ -191,6 +202,9 @@ const emitAggregatedUserTriggerDecisionTelemetry = (
: undefined,
codewhispererTimeToFirstRecommendation: session.timeToFirstRecommendation,
codewhispererPreviousSuggestionState: session.previousTriggerDecision,
codewhispererSupplementalContextTimeout: session.supplementalMetadata?.isProcessTimeout,
codewhispererSupplementalContextIsUtg: session.supplementalMetadata?.isUtg,
codewhispererSupplementalContextLength: session.supplementalMetadata?.contentsLength,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it expected we set 3 props in this metric, but 4 above? The tests are checking for 4 properties, at least.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants