diff --git a/app/admin/system/integrations/Google.tsx b/app/admin/system/integrations/Google.tsx index 8aea667b..503fd11c 100644 --- a/app/admin/system/integrations/Google.tsx +++ b/app/admin/system/integrations/Google.tsx @@ -18,12 +18,11 @@ import { callApi } from '@lib/callApi'; /** * Google endpoint locations that are available in the Volunteer Manager. - * - * @todo Update the locations once PaLM rolls out beyond us-central1. + * @see https://cloud.google.com/vertex-ai/docs/general/locations#europe */ const kLocationOptions = [ - //{ id: 'europe-west2', label: 'London (europe-west2)' }, - //{ id: 'europe-west4', label: 'Amsterdam (europe-west4)' }, + { id: 'europe-west2', label: 'London (europe-west2)' }, + { id: 'europe-west4', label: 'Amsterdam (europe-west4)' }, { id: 'us-central1', label: 'Iowa (us-central1)' }, { id: 'us-west1', label: 'Oregon (us-west1)' }, ]; diff --git a/app/api/admin/serviceHealth.ts b/app/api/admin/serviceHealth.ts index 60fed6ae..aa6394aa 100644 --- a/app/api/admin/serviceHealth.ts +++ b/app/api/admin/serviceHealth.ts @@ -146,7 +146,9 @@ async function runGoogleHealthCheck(): Promise { async function runVertexAIHealthCheck(): Promise { try { const client = await createVertexAIClient(); - const prediction = await client.predictText('Who is your favourite artist?'); + const prediction = await client.predictText({ + prompt: 'Who is your favourite artist?' + }); if (typeof prediction === 'string') { return { diff --git a/app/api/admin/vertexAi.ts b/app/api/admin/vertexAi.ts index 190107d7..813bbe0f 100644 --- a/app/api/admin/vertexAi.ts +++ b/app/api/admin/vertexAi.ts @@ -90,5 +90,7 @@ export async function vertexAi(request: Request, props: ActionProps): Promise[ ]*/g, '\n').replace(/^>\s*/, ''); return { success: true, context, prompt, result: { subject, message } }; diff --git a/app/lib/integrations/vertexai/VertexAIClient.ts b/app/lib/integrations/vertexai/VertexAIClient.ts index 62f086cf..b92d2868 100644 --- a/app/lib/integrations/vertexai/VertexAIClient.ts +++ b/app/lib/integrations/vertexai/VertexAIClient.ts @@ -6,11 +6,6 @@ import { VertexAI } from '@google-cloud/vertexai'; import { GoogleClient, type GoogleClientSettings } from '../google/GoogleClient'; import { VertexSupportedModels } from './VertexSupportedModels'; -/** - * Publisher of the PaLM 2 model, as it makes no sense to train our own. - */ -const kPublisher = 'google'; - /** * Settings required by the Vertex AI client. */ @@ -67,6 +62,24 @@ export interface VertexAISettings { */ export type VertexAIClientSettings = VertexAISettings & GoogleClientSettings; +/** + * Interface that describes an input prompt to use with the Vertex AI APIs, now that this can be + * richer than a simple string. + */ +export interface VertexPrompt { + /** + * The prompt that should be executed by the generative model. + */ + prompt: string; + + /** + * Instructions to share with the system before the LLM gets exposed to any instructions from + * the model. This can be used to define the persona, output formats, and so on. + * @see https://cloud.google.com/vertex-ai/generative-ai/docs/learn/prompts/system-instructions + */ + systemInstruction?: string; +} + /** * The Vertex AI client allows convenient access to the Google Vertex AI. It builds on top of the * Google client for authentication purposes. @@ -81,28 +94,11 @@ export class VertexAIClient { } /** - * Predicts responses to the given `prompt`, which is the full string that should be fed to the - * LLM, including instructions towards the answer that is expected from the model. - */ - async predictText(prompt: string): Promise { - switch (this.#settings.model) { - case 'text-bison': - case 'text-bison@001': - case 'text-bison@002': - throw new Error('The PaLM models are no longer supported.'); - - case 'gemini-pro': - return this.predictTextGemini(prompt); - } - - throw new Error(`Unrecognised model specified for prediction: ${this.#settings.model}`); - } - - /** - * Predicts responses to the given `prompt` using the Google Gemini model. The response will be - * returned as a string when successful; `undefined` will be returned in all other cases. + * Predicts responses to the given `prompt` using the configured Google Gemini model. The + * response will be returned as a string when successful; `undefined` will be returned in all + * other cases. */ - private async predictTextGemini(prompt: string): Promise { + async predictText(prompt: VertexPrompt): Promise { const client = new VertexAI({ project: this.#googleClient.projectId, location: this.#googleClient.location, @@ -121,6 +117,7 @@ export class VertexAIClient { topP: this.#settings.topP, }, // TODO: `safetySettings` + systemInstruction: prompt.systemInstruction, }); const result = await model.generateContent({ @@ -129,7 +126,7 @@ export class VertexAIClient { role: 'USER', parts: [ { - text: prompt, + text: prompt.prompt, } ] } diff --git a/app/lib/integrations/vertexai/VertexSupportedModels.ts b/app/lib/integrations/vertexai/VertexSupportedModels.ts index d9aca4a6..2987c8bf 100644 --- a/app/lib/integrations/vertexai/VertexSupportedModels.ts +++ b/app/lib/integrations/vertexai/VertexSupportedModels.ts @@ -5,8 +5,7 @@ * Enumeration of the models that are supported by the Vertex AI API. */ export enum VertexSupportedModels { - 'gemini-pro' = 'gemini-pro', - 'text-bison' = 'text-bison', - 'text-bison@001' = 'text-bison@001', - 'text-bison@002' = 'text-bison@002', + 'gemini-1.5-flash-001' = 'gemini-1.5-flash-001', + 'gemini-1.5-pro-001' = 'gemini-1.5-pro-001', + 'gemini-1.0-pro-002' = 'gemini-1.0-pro-002', }