Skip to content

Commit

Permalink
make Deep Cody tooglable instead of model
Browse files Browse the repository at this point in the history
  • Loading branch information
abeatrix committed Nov 5, 2024
1 parent a0057c8 commit 3c4018f
Show file tree
Hide file tree
Showing 19 changed files with 236 additions and 164 deletions.
6 changes: 6 additions & 0 deletions lib/shared/src/misc/rpc/webviewAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ export interface WebviewToExtensionAPI {
* The current user's product subscription information (Cody Free/Pro).
*/
userProductSubscription(): Observable<UserProductSubscription | null>

/**
* Enable / Disable Deep Cody on toggler switch.
*/
toogleDeepCody(): Observable<boolean>
}

export function createExtensionAPI(
Expand Down Expand Up @@ -129,6 +134,7 @@ export function createExtensionAPI(
transcript: proxyExtensionAPI(messageAPI, 'transcript'),
userHistory: proxyExtensionAPI(messageAPI, 'userHistory'),
userProductSubscription: proxyExtensionAPI(messageAPI, 'userProductSubscription'),
toogleDeepCody: proxyExtensionAPI(messageAPI, 'toogleDeepCody'),
}
}

Expand Down
32 changes: 0 additions & 32 deletions lib/shared/src/models/client.ts

This file was deleted.

67 changes: 1 addition & 66 deletions lib/shared/src/models/sync.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { mockAuthStatus } from '../auth/authStatus'
import { AUTH_STATUS_FIXTURE_AUTHED, type AuthStatus } from '../auth/types'
import { CLIENT_CAPABILITIES_FIXTURE, mockClientCapabilities } from '../configuration/clientCapabilities'
import type { ResolvedConfiguration } from '../configuration/resolver'
import { FeatureFlag, featureFlagProvider } from '../experimentation/FeatureFlagProvider'
import { featureFlagProvider } from '../experimentation/FeatureFlagProvider'
import {
firstValueFrom,
readValuesFrom,
Expand All @@ -16,7 +16,6 @@ import type { CodyClientConfig } from '../sourcegraph-api/clientConfig'
import type { CodyLLMSiteConfiguration } from '../sourcegraph-api/graphql/client'
import * as userProductSubscriptionModule from '../sourcegraph-api/userProductSubscription'
import type { PartialDeep } from '../utils'
import { getExperimentalClientModelByFeatureFlag } from './client'
import {
type Model,
type ServerModel,
Expand Down Expand Up @@ -458,68 +457,4 @@ describe('syncModels', () => {
await done
}
)

it('sets DeepCody as default chat model when feature flag is enabled', async () => {
const serverOpus: ServerModel = {
modelRef: 'anthropic::unknown::anthropic.claude-3-opus',
displayName: 'Opus',
modelName: 'anthropic.claude-3-opus',
capabilities: ['chat'],
category: 'balanced' as ModelCategory,
status: 'stable',
tier: 'enterprise' as ModelTier,
contextWindow: {
maxInputTokens: 9000,
maxOutputTokens: 4000,
},
}

const SERVER_MODELS: ServerModelConfiguration = {
schemaVersion: '0.0',
revision: '-',
providers: [],
models: [serverOpus],
defaultModels: {
chat: serverOpus.modelRef,
fastChat: serverOpus.modelRef,
codeCompletion: serverOpus.modelRef,
},
}

const mockFetchServerSideModels = vi.fn(() => Promise.resolve(SERVER_MODELS))
vi.mocked(featureFlagProvider).evaluatedFeatureFlag.mockReturnValue(Observable.of(true))

const DEEPCODY_MODEL = getExperimentalClientModelByFeatureFlag(FeatureFlag.DeepCody)!

const result = await firstValueFrom(
syncModels({
resolvedConfig: Observable.of({
configuration: {},
clientState: { modelPreferences: {} },
} satisfies PartialDeep<ResolvedConfiguration> as ResolvedConfiguration),
authStatus: Observable.of(AUTH_STATUS_FIXTURE_AUTHED),
configOverwrites: Observable.of(null),
clientConfig: Observable.of({
modelsAPIEnabled: true,
} satisfies Partial<CodyClientConfig> as CodyClientConfig),
fetchServerSideModels_: mockFetchServerSideModels,
}).pipe(skipPendingOperation())
)

const storage = new TestLocalStorageForModelPreferences()
modelsService.storage = storage
mockAuthStatus(AUTH_STATUS_FIXTURE_AUTHED)
expect(storage.data?.[AUTH_STATUS_FIXTURE_AUTHED.endpoint]!.selected.chat).toBe(undefined)
vi.spyOn(modelsService, 'modelsChanges', 'get').mockReturnValue(Observable.of(result))

// Check if DeepCody model is in the primary models
expect(result.primaryModels.some(model => model.id === DEEPCODY_MODEL.modelRef)).toBe(true)

// Check if DeepCody is set as the default chat model
expect(result.preferences.defaults.chat).toBe(DEEPCODY_MODEL.modelRef)

// user preference should not be affected and remains unchanged as this is handled in a later step.
expect(result.preferences.selected.chat).toBe(undefined)
expect(storage.data?.[AUTH_STATUS_FIXTURE_AUTHED.endpoint]!.selected.chat).toBe(undefined)
})
})
32 changes: 2 additions & 30 deletions lib/shared/src/models/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import type { CodyLLMSiteConfiguration } from '../sourcegraph-api/graphql/client
import { RestClient } from '../sourcegraph-api/rest/client'
import { CHAT_INPUT_TOKEN_BUDGET } from '../token/constants'
import { isError } from '../utils'
import { getExperimentalClientModelByFeatureFlag } from './client'
import { type Model, type ServerModel, createModel, createModelFromServerModel } from './model'
import type {
DefaultsAndUserPreferencesForEndpoint,
Expand Down Expand Up @@ -195,10 +194,9 @@ export function syncModels({
return combineLatest(
featureFlagProvider.evaluatedFeatureFlag(
FeatureFlag.CodyEarlyAccess
),
featureFlagProvider.evaluatedFeatureFlag(FeatureFlag.DeepCody)
)
).pipe(
switchMap(([hasEarlyAccess, deepCodyEnabled]) => {
switchMap(([hasEarlyAccess]) => {
// TODO(sqs): remove waitlist from localStorage when user has access
const isOnWaitlist = config.clientState.waitlist_o1
if (isDotComUser && (hasEarlyAccess || isOnWaitlist)) {
Expand All @@ -218,32 +216,6 @@ export function syncModels({
})
}

// DEEP CODY - available to users with feature flag enabled only.
// TODO(bee): remove once deepCody is enabled for all users.
if (deepCodyEnabled && serverModelsConfig) {
const DEEPCODY_MODEL =
getExperimentalClientModelByFeatureFlag(
FeatureFlag.DeepCody
)!
data.primaryModels.push(
...maybeAdjustContextWindows([DEEPCODY_MODEL]).map(
createModelFromServerModel
)
)
// Update model preferences for chat to DEEP CODY once on first sync.
data.preferences!.defaults.edit =
data.preferences!.defaults.chat
data.preferences!.defaults.chat = DEEPCODY_MODEL.modelRef
return userModelPreferences.pipe(
take(1),
tap(preferences => {
preferences.selected[ModelUsage.Chat] =
DEEPCODY_MODEL.modelRef
}),
map(() => data)
)
}

return Observable.of(data)
})
)
Expand Down
69 changes: 69 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,7 @@
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.1.1",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-tooltip": "^1.0.7",
"@sentry/browser": "^7.107.0",
Expand Down
10 changes: 5 additions & 5 deletions vscode/src/chat/agentic/DeepCody.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import type { CodyTool } from './CodyTool'
import { CodyToolProvider } from './CodyToolProvider'
import { DeepCodyAgent } from './DeepCody'

const DeepCodyModel = DeepCodyAgent.ModelRef

describe('DeepCody', () => {
const codyProAuthStatus: AuthenticatedAuthStatus = {
...AUTH_STATUS_FIXTURE_AUTHED,
Expand All @@ -49,11 +47,11 @@ describe('DeepCody', () => {
mockClientCapabilities(CLIENT_CAPABILITIES_FIXTURE)
mockAuthStatus(codyProAuthStatus)
mockChatBuilder = {
selectedModel: 'anthropic::2023-06-01::deep-cody',
selectedModel: 'anthropic::2023-06-01::claude-3.5-sonnet',
changes: {
pipe: vi.fn(),
},
resolvedModelForChat: vi.fn().mockReturnValue('anthropic::2023-06-01::deep-cody'),
resolvedModelForChat: vi.fn().mockReturnValue('anthropic::2023-06-01::claude-3.5-sonnet'),
addHumanMessage: vi.fn(),
addBotMessage: vi.fn(),
contextWindowForChat: vi.fn().mockReturnValue({ input: 10000, output: 1000 }),
Expand Down Expand Up @@ -89,7 +87,9 @@ describe('DeepCody', () => {

vi.spyOn(featureFlagProvider, 'evaluatedFeatureFlag').mockReturnValue(Observable.of(false))
vi.spyOn(modelsService, 'isStreamDisabled').mockReturnValue(false)
vi.spyOn(ChatBuilder, 'resolvedModelForChat').mockReturnValue(Observable.of(DeepCodyModel))
vi.spyOn(ChatBuilder, 'resolvedModelForChat').mockReturnValue(
Observable.of('anthropic::2023-06-01::claude-3.5-sonnet')
)
vi.spyOn(ChatBuilder, 'contextWindowForChat').mockReturnValue(
Observable.of({ input: 10000, output: 1000 })
)
Expand Down
18 changes: 13 additions & 5 deletions vscode/src/chat/agentic/DeepCody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ import { CODYAGENT_PROMPTS } from './prompts'
* It is responsible for reviewing the retrieved context, and perform agentic context retrieval for the chat request.
*/
export class DeepCodyAgent extends CodyChatAgent {
public static readonly ModelRef = 'sourcegraph::2023-06-01::deep-cody'
private static toggledOn = true

protected getModelRef(): string {
return DeepCodyAgent.ModelRef
public static setToggler(): boolean {
DeepCodyAgent.toggledOn = !DeepCodyAgent.toggledOn
return DeepCodyAgent.toggledOn
}

public static get isToggledOn(): boolean {
return DeepCodyAgent.toggledOn
}

protected buildPrompt(): PromptString {
Expand Down Expand Up @@ -64,10 +69,13 @@ export class DeepCodyAgent extends CodyChatAgent {
private async review(span: Span, chatAbortSignal: AbortSignal): Promise<ContextItem[]> {
const model = 'anthropic::2023-06-01::claude-3-haiku'
const prompter = this.getPrompter(this.context)
const promptData = await prompter.makePrompt(this.chatBuilder, 1, this.promptMixins)
const promptData = await prompter.makePrompt(this.chatBuilder, 1, this.promptMixins, true)

try {
await this.processStream(promptData.prompt, chatAbortSignal, model)
const res = await this.processStream(promptData.prompt, chatAbortSignal, model)
if (res?.toString().includes('CONTEXT_SUFFICIENT')) {
return []
}
const results = await Promise.all(
Array.from(this.toolHandlers.values()).map(tool => tool.execute(span))
)
Expand Down
Loading

0 comments on commit 3c4018f

Please sign in to comment.