fix(Basic LLM Chain Node): Prevent stringifying of structured output on previous versions (#14200)

This commit is contained in:
oleg
2025-03-27 11:48:17 +01:00
committed by GitHub
parent a4a34a2745
commit bbd6e8ee41
6 changed files with 375 additions and 19 deletions

View File

@@ -9,6 +9,21 @@ import { getTracingConfig } from '@utils/tracing';
import { createPromptTemplate } from './promptUtils';
import type { ChainExecutionParams } from './types';
export class NaiveJsonOutputParser<
T extends Record<string, any> = Record<string, any>,
> extends JsonOutputParser<T> {
async parse(text: string): Promise<T> {
// First try direct JSON parsing
try {
const directParsed = JSON.parse(text);
return directParsed as T;
} catch (e) {
// If fails, fall back to JsonOutputParser parser
return await super.parse(text);
}
}
}
/**
* Type guard to check if the LLM has a modelKwargs property(OpenAI)
*/
@@ -39,11 +54,11 @@ export function getOutputParserForLLM(
llm: BaseLanguageModel,
): BaseLLMOutputParser<string | Record<string, unknown>> {
if (isModelWithResponseFormat(llm) && llm.modelKwargs?.response_format?.type === 'json_object') {
return new JsonOutputParser();
return new NaiveJsonOutputParser();
}
if (isModelWithFormat(llm) && llm.format === 'json') {
return new JsonOutputParser();
return new NaiveJsonOutputParser();
}
return new StringOutputParser();

View File

@@ -3,7 +3,7 @@ import type { IDataObject } from 'n8n-workflow';
/**
* Formats the response from the LLM chain into a consistent structure
*/
export function formatResponse(response: unknown, version: number): IDataObject {
export function formatResponse(response: unknown, returnUnwrappedObject: boolean): IDataObject {
if (typeof response === 'string') {
return {
text: response.trim(),
@@ -17,10 +17,12 @@ export function formatResponse(response: unknown, version: number): IDataObject
}
if (response instanceof Object) {
if (version >= 1.6) {
if (returnUnwrappedObject) {
return response as IDataObject;
}
// If the response is an object and we are not unwrapping it, we need to stringify it
// to be backwards compatible with older versions of the chain(< 1.6)
return {
text: JSON.stringify(response),
};