diff --git a/libs/langchain-anthropic/src/output_parsers.ts b/libs/langchain-anthropic/src/output_parsers.ts index c5608900b4b9..866c5b947f82 100644 --- a/libs/langchain-anthropic/src/output_parsers.ts +++ b/libs/langchain-anthropic/src/output_parsers.ts @@ -39,10 +39,27 @@ export class AnthropicToolsOutputParser< } protected async _validateResult(result: unknown): Promise { + let parsedResult = result; + if (typeof result === "string") { + try { + parsedResult = JSON.parse(result); + } catch (e: any) { + throw new OutputParserException( + `Failed to parse. Text: "${JSON.stringify( + result, + null, + 2 + )}". Error: ${JSON.stringify(e.message)}`, + result + ); + } + } else { + parsedResult = result; + } if (this.zodSchema === undefined) { - return result as T; + return parsedResult as T; } - const zodParsedResult = await this.zodSchema.safeParseAsync(result); + const zodParsedResult = await this.zodSchema.safeParseAsync(parsedResult); if (zodParsedResult.success) { return zodParsedResult.data; } else { @@ -52,7 +69,7 @@ export class AnthropicToolsOutputParser< null, 2 )}". Error: ${JSON.stringify(zodParsedResult.error.errors)}`, - JSON.stringify(result, null, 2) + JSON.stringify(parsedResult, null, 2) ); } } diff --git a/libs/langchain-anthropic/src/tests/chat_models-tools.int.test.ts b/libs/langchain-anthropic/src/tests/chat_models-tools.int.test.ts index 3af61e38f04e..dfe63e849743 100644 --- a/libs/langchain-anthropic/src/tests/chat_models-tools.int.test.ts +++ b/libs/langchain-anthropic/src/tests/chat_models-tools.int.test.ts @@ -38,7 +38,7 @@ class WeatherTool extends StructuredTool { } const model = new ChatAnthropic({ - modelName: "claude-3-sonnet-20240229", + modelName: "claude-3-haiku-20240307", temperature: 0, }); @@ -440,3 +440,24 @@ test("llm token callbacks can handle tool calls", async () => { if (!args) return; expect(args).toEqual(JSON.parse(tokens)); }); + +test.only("streaming with structured output", async () => { + const stream = await model + .withStructuredOutput(zodSchema) + .stream("weather in london"); + // Currently, streaming yields a single chunk + let finalChunk; + for await (const chunk of stream) { + finalChunk = chunk; + } + expect(typeof finalChunk).toEqual("object"); + const stream2 = await model + .withStructuredOutput(zodToJsonSchema(zodSchema)) + .stream("weather in london"); + // Currently, streaming yields a single chunk + let finalChunk2; + for await (const chunk of stream2) { + finalChunk2 = chunk; + } + expect(typeof finalChunk2).toEqual("object"); +});