in firestore-genai-chatbot/functions/src/generative-client/vertex_ai.ts [65:135]
async generateResponse(
history: Message[],
latestApiMessage: ApiMessage,
options: GeminiChatOptions
) {
if (!this.client) {
throw new Error('Client not initialized.');
}
let result;
const generativeModel = this.client.preview.getGenerativeModel({
model: this.modelName,
});
const contents = [...this.messagesToApi(history), latestApiMessage];
const request: GenerateContentRequest = {
contents,
generationConfig: {
topK: options.topK,
topP: options.topP,
temperature: options.temperature,
candidateCount: options.candidateCount,
maxOutputTokens: options.maxOutputTokens,
},
safetySettings: options.safetySettings,
};
try {
const responseStream =
await generativeModel.generateContentStream(request);
// TODO: we can stream now!
const aggregatedResponse = await responseStream.response;
result = aggregatedResponse;
// result = await chatSession.sendMessage(latestApiMessage.parts[0].text);
} catch (e) {
logger.error(e);
// TODO: the error message provided exposes the API key, so we should handle this/ get the Gemini team to fix it their side.
throw new Error(
'Failed to generate response, see function logs for more details.'
);
}
if (
!result.candidates ||
!Array.isArray(result.candidates) ||
result.candidates.length === 0
) {
// TODO: handle blocked responses
throw new Error('No candidates returned');
}
const candidates = result.candidates.filter(c => {
return (
c &&
c.content &&
c.content.parts &&
c.content.parts.length > 0 &&
c.content.parts[0].text &&
typeof c.content.parts[0].text === 'string'
);
});
return {
response: candidates[0]!.content!.parts![0].text!,
candidates: candidates?.map(c => c.content!.parts![0].text!) ?? [],
safetyMetadata: result.promptFeedback,
history,
};
}