Skip to content

Commit

Permalink
google-common[patch]: Fix removing all instances of additionalPropert…
Browse files Browse the repository at this point in the history
…ies (#6110)

* google-common[patch]: Fix removing all instances of additionalProperties

* add tests
  • Loading branch information
bracesproul authored Jul 17, 2024
1 parent 1d79eca commit 8848c7d
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 4 deletions.
74 changes: 74 additions & 0 deletions libs/langchain-google-common/src/tests/chat_models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import {
ToolMessage,
} from "@langchain/core/messages";

import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
import { ChatGoogleBase, ChatGoogleBaseInput } from "../chat_models.js";
import { authOptions, MockClient, MockClientAuthInfo, mockId } from "./mock.js";
import { GeminiTool, GoogleAIBaseLLMInput } from "../types.js";
import { GoogleAbstractedClient } from "../auth.js";
import { GoogleAISafetyError } from "../utils/safety.js";
import { removeAdditionalProperties } from "../utils/zod_to_gemini_parameters.js";

class ChatGoogle extends ChatGoogleBase<MockClientAuthInfo> {
constructor(fields?: ChatGoogleBaseInput<MockClientAuthInfo>) {
Expand Down Expand Up @@ -840,3 +843,74 @@ describe("Mock ChatGoogle", () => {
console.log(JSON.stringify(record?.opts?.data, null, 1));
});
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function extractKeys(obj: Record<string, any>, keys: string[] = []) {
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
keys.push(key);
if (typeof obj[key] === "object" && obj[key] !== null) {
extractKeys(obj[key], keys);
}
}
}
return keys;
}

test("removeAdditionalProperties can remove all instances of additionalProperties", async () => {
const idealResponseSchema = z.object({
idealResponse: z
.string()
.optional()
.describe("The ideal response to the question"),
});
const questionSchema = z.object({
question: z.string().describe("Question text"),
type: z.enum(["singleChoice", "multiChoice"]).describe("Question type"),
options: z.array(z.string()).describe("List of possible answers"),
correctAnswer: z
.string()
.optional()
.describe("correct answer from the possible answers"),
idealResponses: z
.array(idealResponseSchema)
.describe("Array of ideal responses to the question"),
});

const schema = z.object({
questions: z.array(questionSchema).describe("Array of question objects"),
});

const parsedSchemaArr = removeAdditionalProperties(zodToJsonSchema(schema));
const arrSchemaKeys = extractKeys(parsedSchemaArr);
expect(
arrSchemaKeys.find((key) => key === "additionalProperties")
).toBeUndefined();
const parsedSchemaObj = removeAdditionalProperties(
zodToJsonSchema(questionSchema)
);
const arrSchemaObj = extractKeys(parsedSchemaObj);
expect(
arrSchemaObj.find((key) => key === "additionalProperties")
).toBeUndefined();

const analysisSchema = z.object({
decision: z.enum(["UseAPI", "UseFallback"]),
explanation: z.string(),
apiDetails: z
.object({
serviceName: z.string(),
endpointName: z.string(),
parameters: z.record(z.unknown()),
extractionPath: z.string(),
})
.optional(),
});
const parsedAnalysisSchema = removeAdditionalProperties(
zodToJsonSchema(analysisSchema)
);
const analysisSchemaObj = extractKeys(parsedAnalysisSchema);
expect(
analysisSchemaObj.find((key) => key === "additionalProperties")
).toBeUndefined();
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ export function removeAdditionalProperties(
if (typeof obj === "object" && obj !== null) {
const newObj = { ...obj };

if (
"additionalProperties" in newObj &&
typeof newObj.additionalProperties === "boolean"
) {
if ("additionalProperties" in newObj) {
delete newObj.additionalProperties;
}

Expand Down

0 comments on commit 8848c7d

Please sign in to comment.