Skip to content

Commit

Permalink
Move context warnings from the UI to the debug log (#2891)
Browse files Browse the repository at this point in the history
The context warnings in the UI are creating more confusion than they're
worth, so we'll move them to the debug output and work on better ways of
surfacing these issues as necessary in the transcript view.

## Test plan

- Recreate each warning scenario
- Verify code behaves well
  • Loading branch information
toolmantim authored Jan 25, 2024
1 parent ad9c9a6 commit e62ca32
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 101 deletions.
1 change: 0 additions & 1 deletion lib/shared/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ export type {
export { DOTCOM_URL, LOCAL_APP_URL, isDotCom } from './sourcegraph-api/environments'
export {
AbortError,
ContextWindowLimitError,
NetworkError,
RateLimitError,
TimeoutError,
Expand Down
9 changes: 0 additions & 9 deletions lib/shared/src/sourcegraph-api/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,3 @@ export function isAbortError(error: unknown): error is AbortError {
}

export class TimeoutError extends Error {}

export class ContextWindowLimitError extends Error {
public static readonly errorName = 'ContextWindowLimitError'
public readonly name = ContextWindowLimitError.errorName

constructor(public readonly message: string) {
super(message)
}
}
50 changes: 1 addition & 49 deletions lib/ui/src/chat/ErrorItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useCallback } from 'react'

import { ContextWindowLimitError, RateLimitError, type ChatError } from '@sourcegraph/cody-shared'
import { RateLimitError, type ChatError } from '@sourcegraph/cody-shared'

import type { ApiPostMessage, ChatButtonProps, UserAccountInfo } from '../Chat'

Expand All @@ -26,16 +26,6 @@ export const ErrorItem: React.FunctionComponent<{
)
}

if (typeof error !== 'string' && error.name === ContextWindowLimitError.errorName && postMessage) {
return (
<ContextWindowLimitErrorItem
error={error as ContextWindowLimitError}
ChatButtonComponent={ChatButtonComponent}
postMessage={postMessage}
/>
)
}

return <RequestErrorItem error={error.message} />
})

Expand All @@ -53,44 +43,6 @@ export const RequestErrorItem: React.FunctionComponent<{
)
})

const ContextWindowLimitErrorItem: React.FunctionComponent<{
error: ContextWindowLimitError
ChatButtonComponent?: React.FunctionComponent<ChatButtonProps>
postMessage: ApiPostMessage
}> = React.memo(function ContextWindowLimitErrorItemContent({
error,
ChatButtonComponent,
postMessage,
}) {
const onClick = useCallback(() => {
postMessage({ command: 'reset' })
}, [postMessage])

return (
<div className={styles.errorItem}>
<div className={styles.icon}>
<span className="codicon codicon-warning" />
</div>
<div className={styles.body}>
<header>
<h1>Context Limit Reached</h1>
<p>{error.message}</p>
</header>
{ChatButtonComponent && (
<div className={styles.actions}>
<ChatButtonComponent
label="Start New Chat"
action=""
appearance="primary"
onClick={onClick}
/>
</div>
)}
</div>
</div>
)
})

/**
* An error message shown in the chat.
*/
Expand Down
1 change: 1 addition & 0 deletions vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ This is a log of all notable changes to Cody for VS Code. [Unreleased] changes a
- Autocomplete: Better cancellation of requests that are no longer relevant. [pull/2855](https://github.com/sourcegraph/cody/pull/2855)
- Updated Enhanced Context popover copy and added a link to the docs. [pull/2864](https://github.com/sourcegraph/cody/pull/2864)
- Include meta information about unit test files in Autocomplete analytics. [pull/2868](https://github.com/sourcegraph/cody/pull/2868)
- Moved the Context Limit errors in chat into the deboug log output. [pull/2891](https://github.com/sourcegraph/cody/pull/2891)

## [1.1.3]

Expand Down
15 changes: 1 addition & 14 deletions vscode/src/chat/chat-view/SimpleChatPanelProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import * as vscode from 'vscode'
import {
ChatModelProvider,
ConfigFeaturesSingleton,
ContextWindowLimitError,
hydrateAfterPostMessage,
isDefined,
isDotCom,
Expand Down Expand Up @@ -766,25 +765,13 @@ export class SimpleChatPanelProvider implements vscode.Disposable, ChatSession {
prompter: IPrompter,
sendTelemetry?: (contextSummary: any) => void
): Promise<Message[]> {
const { prompt, contextLimitWarnings, newContextUsed } = await prompter.makePrompt(
const { prompt, newContextUsed } = await prompter.makePrompt(
this.chatModel,
getContextWindowForModel(this.authProvider.getAuthStatus(), this.chatModel.modelID)
)

// Update UI based on prompt construction
this.chatModel.setNewContextUsed(newContextUsed)
if (contextLimitWarnings.length > 0) {
const warningMsg = contextLimitWarnings
.map(w => {
w = w.trim()
if (!w.endsWith('.')) {
w += '.'
}
return w
})
.join(' ')
this.postError(new ContextWindowLimitError(warningMsg), 'transcript')
}

if (sendTelemetry) {
// Create a summary of how many code snippets of each context source are being
Expand Down
18 changes: 6 additions & 12 deletions vscode/src/chat/chat-view/prompt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ describe('DefaultPrompter', () => {
const chat = new SimpleChatModel('a-model-id')
chat.addHumanMessage({ text: 'Hello' })

const {
prompt,
contextLimitWarnings: warnings,
newContextUsed,
} = await new DefaultPrompter([], () => Promise.resolve([])).makePrompt(chat, 100000)
const { prompt, newContextUsed } = await new DefaultPrompter([], () =>
Promise.resolve([])
).makePrompt(chat, 100000)

expect(prompt).toMatchInlineSnapshot(`
[
Expand All @@ -34,7 +32,6 @@ describe('DefaultPrompter', () => {
},
]
`)
expect(warnings).toMatchInlineSnapshot('[]')
expect(newContextUsed).toMatchInlineSnapshot('[]')
})

Expand All @@ -50,11 +47,9 @@ describe('DefaultPrompter', () => {
const chat = new SimpleChatModel('a-model-id')
chat.addHumanMessage({ text: 'Hello' })

const {
prompt,
contextLimitWarnings: warnings,
newContextUsed,
} = await new DefaultPrompter([], () => Promise.resolve([])).makePrompt(chat, 100000)
const { prompt, newContextUsed } = await new DefaultPrompter([], () =>
Promise.resolve([])
).makePrompt(chat, 100000)

expect(prompt).toMatchInlineSnapshot(`
[
Expand All @@ -72,7 +67,6 @@ describe('DefaultPrompter', () => {
},
]
`)
expect(warnings).toMatchInlineSnapshot('[]')
expect(newContextUsed).toMatchInlineSnapshot('[]')
})
})
32 changes: 16 additions & 16 deletions vscode/src/chat/chat-view/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export interface IContextProvider {

interface PromptInfo {
prompt: Message[]
contextLimitWarnings: string[]
newContextUsed: ContextItem[]
}

Expand All @@ -41,7 +40,6 @@ export class CommandPrompter implements IPrompter {
public async makePrompt(chat: SimpleChatModel, byteLimit: number): Promise<PromptInfo> {
const promptBuilder = new PromptBuilder(byteLimit)
const newContextUsed: ContextItem[] = []
const warnings: string[] = []
const preInstruction: string | undefined = vscode.workspace
.getConfiguration('cody.chat')
.get('preInstruction')
Expand All @@ -58,12 +56,12 @@ export class CommandPrompter implements IPrompter {
const messageWithContext = reverseTranscript[i]
const contextLimitReached = promptBuilder.tryAdd(messageWithContext.message)
if (!contextLimitReached) {
warnings.push(
logDebug(
'CommandPrompter.makePrompt',
`Ignored ${reverseTranscript.length - i} transcript messages due to context limit`
)
return {
prompt: promptBuilder.build(),
contextLimitWarnings: warnings,
newContextUsed,
}
}
Expand All @@ -87,7 +85,6 @@ export class CommandPrompter implements IPrompter {

return {
prompt: promptBuilder.build(),
contextLimitWarnings: warnings,
newContextUsed,
}
}
Expand All @@ -101,19 +98,17 @@ export class DefaultPrompter implements IPrompter {
// Constructs the raw prompt to send to the LLM, with message order reversed, so we can construct
// an array with the most important messages (which appear most important first in the reverse-prompt.
//
// Returns the reverse prompt, a list of warnings that indicate that the prompt was truncated, and
// the new context that was used in the prompt for the current message.
// Returns the reverse prompt and the new context that was used in the
// prompt for the current message.
public async makePrompt(
chat: SimpleChatModel,
byteLimit: number
): Promise<{
prompt: Message[]
contextLimitWarnings: string[]
newContextUsed: ContextItem[]
}> {
const promptBuilder = new PromptBuilder(byteLimit)
const newContextUsed: ContextItem[] = []
const warnings: string[] = []
const preInstruction: string | undefined = vscode.workspace
.getConfiguration('cody.chat')
.get('preInstruction')
Expand All @@ -130,12 +125,12 @@ export class DefaultPrompter implements IPrompter {
const messageWithContext = reverseTranscript[i]
const contextLimitReached = promptBuilder.tryAdd(messageWithContext.message)
if (!contextLimitReached) {
warnings.push(
logDebug(
'DefaultPrompter.makePrompt',
`Ignored ${reverseTranscript.length - i} transcript messages due to context limit`
)
return {
prompt: promptBuilder.build(),
contextLimitWarnings: warnings,
newContextUsed,
}
}
Expand All @@ -146,8 +141,11 @@ export class DefaultPrompter implements IPrompter {
const { limitReached, used } = promptBuilder.tryAddContext(this.explicitContext)
newContextUsed.push(...used)
if (limitReached) {
warnings.push('Ignored current user-specified context items due to context limit')
return { prompt: promptBuilder.build(), contextLimitWarnings: warnings, newContextUsed }
logDebug(
'DefaultPrompter.makePrompt',
'Ignored current user-specified context items due to context limit'
)
return { prompt: promptBuilder.build(), newContextUsed }
}
}

Expand All @@ -159,8 +157,11 @@ export class DefaultPrompter implements IPrompter {
reverseTranscript.flatMap((message: MessageWithContext) => message.newContextUsed || [])
)
if (limitReached) {
warnings.push('Ignored prior context items due to context limit')
return { prompt: promptBuilder.build(), contextLimitWarnings: warnings, newContextUsed }
logDebug(
'DefaultPrompter.makePrompt',
'Ignored prior context items due to context limit'
)
return { prompt: promptBuilder.build(), newContextUsed }
}
}

Expand Down Expand Up @@ -189,7 +190,6 @@ export class DefaultPrompter implements IPrompter {

return {
prompt: promptBuilder.build(),
contextLimitWarnings: warnings,
newContextUsed,
}
}
Expand Down

0 comments on commit e62ca32

Please sign in to comment.