Skip to content

Commit 8319201

Browse files
authored
feat(core,openai): export message conversion helpers (#9340)
1 parent 5f2dab2 commit 8319201

File tree

21 files changed

+2740
-1848
lines changed

21 files changed

+2740
-1848
lines changed

.changeset/gold-apples-lay.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@langchain/openai": minor
3+
---
4+
5+
hoist message/tool conversion utilities from classes

.changeset/quiet-chicken-wave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@langchain/core": patch
3+
---
4+
5+
Export standard converter function utility

libs/langchain-core/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,17 @@
602602
"default": "./dist/utils/event_source_parse.js"
603603
}
604604
},
605+
"./utils/format": {
606+
"input": "./src/utils/format.ts",
607+
"require": {
608+
"types": "./dist/utils/format.d.cts",
609+
"default": "./dist/utils/format.cjs"
610+
},
611+
"import": {
612+
"types": "./dist/utils/format.d.ts",
613+
"default": "./dist/utils/format.js"
614+
}
615+
},
605616
"./utils/function_calling": {
606617
"input": "./src/utils/function_calling.ts",
607618
"require": {

libs/langchain-core/src/load/import_map.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export * as utils__async_caller from "../utils/async_caller.js";
4444
export * as utils__chunk_array from "../utils/chunk_array.js";
4545
export * as utils__env from "../utils/env.js";
4646
export * as utils__event_source_parse from "../utils/event_source_parse.js";
47+
export * as utils__format from "../utils/format.js";
4748
export * as utils__function_calling from "../utils/function_calling.js";
4849
export * as utils__hash from "../utils/hash.js";
4950
export * as utils__json_patch from "../utils/json_patch.js";
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* A function that converts data from one format to another.
3+
*
4+
* This is commonly used for transforming message content blocks between different
5+
* provider-specific formats and standardized internal representations.
6+
*
7+
* @template T - The input type to convert from
8+
* @template U - The output type to convert to
9+
*
10+
* @param input - The data to convert
11+
* @returns The converted data in the target format
12+
*
13+
* @example
14+
* ```typescript
15+
* // Convert from OpenAI format to standard format
16+
* const converter: Converter<OpenAIBlock, ContentBlock.Standard> = (block) => {
17+
* return { type: "text", text: block.text };
18+
* };
19+
* ```
20+
*/
21+
export type Converter<T, U> = (input: T) => U;
22+
23+
/**
24+
* A pair of bidirectional conversion functions for transforming data between two formats.
25+
*
26+
* This type is used throughout the message system to enable conversion between
27+
* provider-specific message formats (like OpenAI, Anthropic, Google, etc.) and
28+
* standardized internal content block representations. The `encode` function
29+
* typically converts from a standard format to a provider-specific format, while
30+
* `decode` converts from a provider-specific format back to the standard format.
31+
*
32+
* @template T - The first format (typically the standard/internal format)
33+
* @template U - The second format (typically the provider-specific format)
34+
*
35+
* @property encode - Converts from format T to format U
36+
* @property decode - Converts from format U back to format T
37+
*
38+
* @example
39+
* ```typescript
40+
* // Converter pair for OpenAI message blocks
41+
* const openAIConverter: ConverterPair<ContentBlock.Standard, OpenAIBlock> = {
42+
* encode: (standard) => ({ text: standard.text }),
43+
* decode: (openai) => ({ type: "text", text: openai.text })
44+
* };
45+
*
46+
* // Usage
47+
* const standardBlock = { type: "text", text: "Hello" };
48+
* const openaiBlock = openAIConverter.encode(standardBlock);
49+
* const backToStandard = openAIConverter.decode(openaiBlock);
50+
* ```
51+
*/
52+
export type ConverterPair<T, U> = {
53+
encode: Converter<T, U>;
54+
decode: Converter<U, T>;
55+
};

libs/providers/langchain-openai/src/chat_models/base.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ import {
5757
interopZodResponseFormat,
5858
_convertOpenAIResponsesUsageToLangChainUsage,
5959
} from "../utils/output.js";
60-
import { _convertMessagesToOpenAIParams } from "../utils/message_inputs.js";
61-
import { _convertToResponsesMessageFromV1 } from "../utils/standard.js";
6260
import { isReasoningModel, messageToOpenAIRole } from "../utils/misc.js";
6361

6462
interface OpenAILLMOutput {
@@ -615,7 +613,7 @@ export abstract class BaseChatOpenAI<
615613
: this._convertChatOpenAIToolToCompletionsTool(tool, { strict })
616614
),
617615
...kwargs,
618-
});
616+
} as Partial<CallOptions>);
619617
}
620618

621619
override async stream(input: BaseLanguageModelInput, options?: CallOptions) {
@@ -894,7 +892,7 @@ export abstract class BaseChatOpenAI<
894892
kwargs: { method: "json_mode" },
895893
schema: { title: name ?? "extract", ...asJsonSchema },
896894
},
897-
});
895+
} as Partial<CallOptions>);
898896
} else if (method === "jsonSchema") {
899897
const openaiJsonSchemaParams = {
900898
name: name ?? "extract",
@@ -917,7 +915,7 @@ export abstract class BaseChatOpenAI<
917915
...asJsonSchema,
918916
},
919917
},
920-
});
918+
} as Partial<CallOptions>);
921919
if (isInteropZodSchema(schema)) {
922920
const altParser = StructuredOutputParser.fromZodSchema(schema);
923921
outputParser = RunnableLambda.from<AIMessageChunk, RunOutput>(
@@ -960,7 +958,7 @@ export abstract class BaseChatOpenAI<
960958
},
961959
// Do not pass `strict` argument to OpenAI if `config.strict` is undefined
962960
...(config?.strict !== undefined ? { strict: config.strict } : {}),
963-
});
961+
} as Partial<CallOptions>);
964962
outputParser = new JsonOutputKeyToolsParser({
965963
returnSingle: true,
966964
keyName: functionName,
@@ -1004,7 +1002,7 @@ export abstract class BaseChatOpenAI<
10041002
},
10051003
// Do not pass `strict` argument to OpenAI if `config.strict` is undefined
10061004
...(config?.strict !== undefined ? { strict: config.strict } : {}),
1007-
});
1005+
} as Partial<CallOptions>);
10081006
outputParser = new JsonOutputKeyToolsParser<RunOutput>({
10091007
returnSingle: true,
10101008
keyName: functionName,

0 commit comments

Comments
 (0)