Add GCP Vertex AI provider

This commit is contained in:
Saoud Rizwan
2024-08-28 05:35:49 -04:00
parent 083005ecef
commit 13af5992af
9 changed files with 314 additions and 10 deletions

View File

@@ -3,6 +3,7 @@ import { ApiConfiguration, ApiModelId, ModelInfo } from "../shared/api"
import { AnthropicHandler } from "./anthropic"
import { AwsBedrockHandler } from "./bedrock"
import { OpenRouterHandler } from "./openrouter"
import { VertexHandler } from "./vertex"
export interface ApiHandlerMessageResponse {
message: Anthropic.Messages.Message
@@ -37,6 +38,8 @@ export function buildApiHandler(configuration: ApiConfiguration): ApiHandler {
return new OpenRouterHandler(options)
case "bedrock":
return new AwsBedrockHandler(options)
case "vertex":
return new VertexHandler(options)
default:
return new AnthropicHandler(options)
}

62
src/api/vertex.ts Normal file
View File

@@ -0,0 +1,62 @@
import { AnthropicVertex } from "@anthropic-ai/vertex-sdk"
import { Anthropic } from "@anthropic-ai/sdk"
import { ApiHandler, ApiHandlerMessageResponse, withoutImageData } from "."
import { ApiHandlerOptions, ModelInfo, vertexDefaultModelId, VertexModelId, vertexModels } from "../shared/api"
// https://docs.anthropic.com/en/api/claude-on-vertex-ai
export class VertexHandler implements ApiHandler {
private options: ApiHandlerOptions
private client: AnthropicVertex
constructor(options: ApiHandlerOptions) {
this.options = options
this.client = new AnthropicVertex({
projectId: this.options.vertexProjectId,
// https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-claude#regions
region: this.options.vertexRegion,
})
}
async createMessage(
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
tools: Anthropic.Messages.Tool[]
): Promise<ApiHandlerMessageResponse> {
const message = await this.client.messages.create({
model: this.getModel().id,
max_tokens: this.getModel().info.maxTokens,
system: systemPrompt,
messages,
tools,
tool_choice: { type: "auto" },
})
return { message }
}
createUserReadableRequest(
userContent: Array<
| Anthropic.TextBlockParam
| Anthropic.ImageBlockParam
| Anthropic.ToolUseBlockParam
| Anthropic.ToolResultBlockParam
>
): any {
return {
model: this.getModel().id,
max_tokens: this.getModel().info.maxTokens,
system: "(see SYSTEM_PROMPT in src/ClaudeDev.ts)",
messages: [{ conversation_history: "..." }, { role: "user", content: withoutImageData(userContent) }],
tools: "(see tools in src/ClaudeDev.ts)",
tool_choice: { type: "auto" },
}
}
getModel(): { id: VertexModelId; info: ModelInfo } {
const modelId = this.options.apiModelId
if (modelId && modelId in vertexModels) {
const id = modelId as VertexModelId
return { id, info: vertexModels[id] }
}
return { id: vertexDefaultModelId, info: vertexModels[vertexDefaultModelId] }
}
}

View File

@@ -20,6 +20,8 @@ type GlobalStateKey =
| "apiProvider"
| "apiModelId"
| "awsRegion"
| "vertexProjectId"
| "vertexRegion"
| "maxRequestsPerTask"
| "lastShownAnnouncementId"
| "customInstructions"
@@ -311,6 +313,8 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
awsAccessKey,
awsSecretKey,
awsRegion,
vertexProjectId,
vertexRegion,
} = message.apiConfiguration
await this.updateGlobalState("apiProvider", apiProvider)
await this.updateGlobalState("apiModelId", apiModelId)
@@ -319,6 +323,8 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
await this.storeSecret("awsAccessKey", awsAccessKey)
await this.storeSecret("awsSecretKey", awsSecretKey)
await this.updateGlobalState("awsRegion", awsRegion)
await this.updateGlobalState("vertexProjectId", vertexProjectId)
await this.updateGlobalState("vertexRegion", vertexRegion)
this.claudeDev?.updateApi(message.apiConfiguration)
}
await this.postStateToWebview()
@@ -598,6 +604,8 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
awsAccessKey,
awsSecretKey,
awsRegion,
vertexProjectId,
vertexRegion,
maxRequestsPerTask,
lastShownAnnouncementId,
customInstructions,
@@ -611,6 +619,8 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
this.getSecret("awsAccessKey") as Promise<string | undefined>,
this.getSecret("awsSecretKey") as Promise<string | undefined>,
this.getGlobalState("awsRegion") as Promise<string | undefined>,
this.getGlobalState("vertexProjectId") as Promise<string | undefined>,
this.getGlobalState("vertexRegion") as Promise<string | undefined>,
this.getGlobalState("maxRequestsPerTask") as Promise<number | undefined>,
this.getGlobalState("lastShownAnnouncementId") as Promise<string | undefined>,
this.getGlobalState("customInstructions") as Promise<string | undefined>,
@@ -641,6 +651,8 @@ export class ClaudeDevProvider implements vscode.WebviewViewProvider {
awsAccessKey,
awsSecretKey,
awsRegion,
vertexProjectId,
vertexRegion,
},
maxRequestsPerTask,
lastShownAnnouncementId,

View File

@@ -1,4 +1,4 @@
export type ApiProvider = "anthropic" | "openrouter" | "bedrock"
export type ApiProvider = "anthropic" | "openrouter" | "bedrock" | "vertex"
export interface ApiHandlerOptions {
apiModelId?: ApiModelId
@@ -7,6 +7,8 @@ export interface ApiHandlerOptions {
awsAccessKey?: string
awsSecretKey?: string
awsRegion?: string
vertexProjectId?: string
vertexRegion?: string
}
export type ApiConfiguration = ApiHandlerOptions & {
@@ -26,7 +28,7 @@ export interface ModelInfo {
cacheReadsPrice?: number
}
export type ApiModelId = AnthropicModelId | OpenRouterModelId | BedrockModelId
export type ApiModelId = AnthropicModelId | OpenRouterModelId | BedrockModelId | VertexModelId
// Anthropic
// https://docs.anthropic.com/en/docs/about-claude/models
@@ -250,3 +252,42 @@ export const openRouterModels = {
// outputPrice: 1.5,
// },
} as const satisfies Record<string, ModelInfo>
// Vertex AI
// https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-claude
export type VertexModelId = keyof typeof vertexModels
export const vertexDefaultModelId: VertexModelId = "claude-3-5-sonnet@20240620"
export const vertexModels = {
"claude-3-5-sonnet@20240620": {
maxTokens: 8192,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 3.0,
outputPrice: 15.0,
},
"claude-3-opus@20240229": {
maxTokens: 4096,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 15.0,
outputPrice: 75.0,
},
"claude-3-sonnet@20240229": {
maxTokens: 4096,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 3.0,
outputPrice: 15.0,
},
"claude-3-haiku@20240307": {
maxTokens: 4096,
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: false,
inputPrice: 0.25,
outputPrice: 1.25,
},
} as const satisfies Record<string, ModelInfo>