diff --git a/langchain/src/output_parsers/structured.ts b/langchain/src/output_parsers/structured.ts index a1c3226f7563..1b0e6766945d 100644 --- a/langchain/src/output_parsers/structured.ts +++ b/langchain/src/output_parsers/structured.ts @@ -104,15 +104,23 @@ ${JSON.stringify(zodToJsonSchema(this.schema))} const json = text.includes("```") ? text.trim().split(/```(?:json)?/)[1] : text.trim(); + return await this.schema.parseAsync(JSON.parse(json)); } catch (e) { - try { - return await this.schema.parseAsync(JSON.parse(text.trim())); - } catch (e2) { - throw new OutputParserException( - `Failed to parse. Text: "${text}". Error: ${e2}`, - text - ); + // eslint-disable-next-line no-instanceof/no-instanceof + if (e instanceof SyntaxError && e.message.includes("JSON")) { + // In case the error is JSON.parse related, try to parse the text directly + try { + return await this.schema.parseAsync(JSON.parse(text.trim())); + } catch (e2) { + throw new OutputParserException( + `Failed to parse. Text: "${text}". Error: ${e2}`, + text + ); + } + } else { + // Otherwise, throw the original error (e.g. ZodError) + throw e; } } } diff --git a/langchain/src/output_parsers/tests/structured.test.ts b/langchain/src/output_parsers/tests/structured.test.ts index 95970830b3c9..7b408af3bce8 100644 --- a/langchain/src/output_parsers/tests/structured.test.ts +++ b/langchain/src/output_parsers/tests/structured.test.ts @@ -99,3 +99,31 @@ test("StructuredOutputParser throws error for JSON with backticks both inside an await expect(parser.parse(text)).rejects.toThrow("Failed to parse"); }); + +test("StructuredOutputParser handles valid JSON without triple backticks not conforming to schema", async () => { + const parser = StructuredOutputParser.fromZodSchema( + z.object({ + name: z.string().describe("Human name"), + age: z.number().describe("Human age"), + }) + ); + const text = '{"name": "John Doe", "age": null}'; + + await expect(parser.parse(text)).rejects.toThrow( + "Expected number, received null" + ); +}); + +test("StructuredOutputParser handles valid JSON with backticks and not conforming to schema", async () => { + const parser = StructuredOutputParser.fromZodSchema( + z.object({ + name: z.string().describe("Human name"), + age: z.number().describe("Human age"), + }) + ); + const text = '```json\n{"name": "John Doe", "age": null }```'; + + await expect(parser.parse(text)).rejects.toThrow( + "Expected number, received null" + ); +});