fix(ts): handle empty Google chat candidates (#5817)
This commit is contained in:
@@ -11,12 +11,8 @@ export class GoogleLLM implements LLM {
|
||||
this.model = config.model || "gemini-2.0-flash";
|
||||
}
|
||||
|
||||
async generateResponse(
|
||||
messages: Message[],
|
||||
responseFormat?: { type: string },
|
||||
tools?: any[],
|
||||
): Promise<string | LLMResponse> {
|
||||
const contents = messages.map((msg) => ({
|
||||
private formatContents(messages: Message[]) {
|
||||
return messages.map((msg) => ({
|
||||
parts: [
|
||||
{
|
||||
text:
|
||||
@@ -27,6 +23,14 @@ export class GoogleLLM implements LLM {
|
||||
],
|
||||
role: msg.role === "system" ? "model" : "user",
|
||||
}));
|
||||
}
|
||||
|
||||
async generateResponse(
|
||||
messages: Message[],
|
||||
responseFormat?: { type: string },
|
||||
tools?: any[],
|
||||
): Promise<string | LLMResponse> {
|
||||
const contents = this.formatContents(messages);
|
||||
|
||||
// Build config with tools if provided
|
||||
const config: Record<string, any> = {};
|
||||
@@ -69,13 +73,18 @@ export class GoogleLLM implements LLM {
|
||||
|
||||
async generateChat(messages: Message[]): Promise<LLMResponse> {
|
||||
const completion = await this.google.models.generateContent({
|
||||
contents: messages,
|
||||
contents: this.formatContents(messages),
|
||||
model: this.model,
|
||||
});
|
||||
const response = completion.candidates![0].content;
|
||||
const response = completion.candidates?.[0]?.content;
|
||||
const content =
|
||||
response?.parts?.map((part) => part.text || "").join("") ||
|
||||
completion.text ||
|
||||
"";
|
||||
|
||||
return {
|
||||
content: response!.parts![0].text || "",
|
||||
role: response!.role!,
|
||||
content,
|
||||
role: response?.role || "assistant",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,4 +184,45 @@ describe("GoogleLLM (unit)", () => {
|
||||
expect(response.toolCalls[0].name).toBe("add_graph_memory");
|
||||
expect(response.toolCalls[1].name).toBe("add_graph_memory");
|
||||
});
|
||||
|
||||
it("formats generateChat messages and joins Gemini response parts", async () => {
|
||||
mockGenerateContent.mockResolvedValueOnce({
|
||||
candidates: [
|
||||
{
|
||||
content: {
|
||||
role: "model",
|
||||
parts: [{ text: "Hello" }, { text: ", world" }],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const llm = new GoogleLLM({ apiKey: "test-key" });
|
||||
const result = await llm.generateChat([
|
||||
{ role: "system", content: "Be concise" },
|
||||
{ role: "user", content: "Say hello" },
|
||||
]);
|
||||
|
||||
expect(mockGenerateContent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
contents: [
|
||||
{ role: "model", parts: [{ text: "Be concise" }] },
|
||||
{ role: "user", parts: [{ text: "Say hello" }] },
|
||||
],
|
||||
}),
|
||||
);
|
||||
expect(result).toEqual({ content: "Hello, world", role: "model" });
|
||||
});
|
||||
|
||||
it("returns an empty assistant response when generateChat has no candidates", async () => {
|
||||
mockGenerateContent.mockResolvedValueOnce({
|
||||
candidates: [],
|
||||
text: "",
|
||||
});
|
||||
|
||||
const llm = new GoogleLLM({ apiKey: "test-key" });
|
||||
const result = await llm.generateChat([{ role: "user", content: "Hi" }]);
|
||||
|
||||
expect(result).toEqual({ content: "", role: "assistant" });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user