fix(ts): handle empty Google chat candidates (#5817)

This commit is contained in:
冯基魁
2026-06-29 17:38:44 +08:00
committed by GitHub
parent f59320df65
commit 4c0ea22d31
2 changed files with 60 additions and 10 deletions
+19 -10
View File
@@ -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",
};
}
}
+41
View File
@@ -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" });
});
});