ChatOpenAI
OpenAI 是一个人工智能 (AI) 研究实验室。
本指南将帮助您开始使用 ChatOpenAI 聊天模型。有关所有 ChatOpenAI 功能和配置的详细文档,请访问 API 参考。
概述
集成详细信息
类 | 包 | 本地 | 可序列化 | PY 支持 | 包下载 | 包最新 |
---|---|---|---|---|---|---|
ChatOpenAI | @langchain/openai | ❌ | ✅ | ✅ | ![]() | ![]() |
模型功能
请参阅下表标题中的链接,以获取有关如何使用特定功能的指南。
工具调用 | 结构化输出 | JSON 模式 | 图像输入 | 音频输入 | 视频输入 | 令牌级流式传输 | 令牌使用量 | Logprobs |
---|---|---|---|---|---|---|---|---|
✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ |
设置
要访问 OpenAI 聊天模型,您需要创建一个 OpenAI 帐户,获取 API 密钥,并安装 @langchain/openai
集成包。
凭据
前往 OpenAI 网站注册 OpenAI 并生成 API 密钥。完成此操作后,设置 OPENAI_API_KEY
环境变量
export OPENAI_API_KEY="your-api-key"
如果您想获取模型调用的自动跟踪,您还可以通过取消注释下方内容来设置您的 LangSmith API 密钥
# export LANGSMITH_TRACING="true"
# export LANGSMITH_API_KEY="your-api-key"
安装
LangChain ChatOpenAI
集成位于 @langchain/openai
包中
有关安装集成包的常规说明,请参阅本节。
- npm
- yarn
- pnpm
npm i @langchain/openai @langchain/core
yarn add @langchain/openai @langchain/core
pnpm add @langchain/openai @langchain/core
实例化
现在我们可以实例化我们的模型对象并生成聊天完成
import { ChatOpenAI } from "@langchain/openai";
const llm = new ChatOpenAI({
model: "gpt-4o",
temperature: 0,
// other params...
});
调用
const aiMsg = await llm.invoke([
{
role: "system",
content:
"You are a helpful assistant that translates English to French. Translate the user sentence.",
},
{
role: "user",
content: "I love programming.",
},
]);
aiMsg;
AIMessage {
"id": "chatcmpl-ADItECqSPuuEuBHHPjeCkh9wIO1H5",
"content": "J'adore la programmation.",
"additional_kwargs": {},
"response_metadata": {
"tokenUsage": {
"completionTokens": 5,
"promptTokens": 31,
"totalTokens": 36
},
"finish_reason": "stop",
"system_fingerprint": "fp_5796ac6771"
},
"tool_calls": [],
"invalid_tool_calls": [],
"usage_metadata": {
"input_tokens": 31,
"output_tokens": 5,
"total_tokens": 36
}
}
console.log(aiMsg.content);
J'adore la programmation.
链接
我们可以像这样使用提示模板链接我们的模型
import { ChatPromptTemplate } from "@langchain/core/prompts";
const prompt = ChatPromptTemplate.fromMessages([
[
"system",
"You are a helpful assistant that translates {input_language} to {output_language}.",
],
["human", "{input}"],
]);
const chain = prompt.pipe(llm);
await chain.invoke({
input_language: "English",
output_language: "German",
input: "I love programming.",
});
AIMessage {
"id": "chatcmpl-ADItFaWFNqkSjSmlxeGk6HxcBHzVN",
"content": "Ich liebe Programmieren.",
"additional_kwargs": {},
"response_metadata": {
"tokenUsage": {
"completionTokens": 5,
"promptTokens": 26,
"totalTokens": 31
},
"finish_reason": "stop",
"system_fingerprint": "fp_5796ac6771"
},
"tool_calls": [],
"invalid_tool_calls": [],
"usage_metadata": {
"input_tokens": 26,
"output_tokens": 5,
"total_tokens": 31
}
}
自定义 URL
您可以通过传递如下所示的 configuration
参数来自定义 SDK 发送请求的基本 URL
import { ChatOpenAI } from "@langchain/openai";
const llmWithCustomURL = new ChatOpenAI({
temperature: 0.9,
configuration: {
baseURL: "https://your_custom_url.com",
},
});
await llmWithCustomURL.invoke("Hi there!");
configuration
字段还接受官方 SDK 接受的其他 ClientOptions
参数。
如果您托管在 Azure OpenAI 上,请参阅专用页面。
自定义标头
您可以在相同的 configuration
字段中指定自定义标头
import { ChatOpenAI } from "@langchain/openai";
const llmWithCustomHeaders = new ChatOpenAI({
temperature: 0.9,
configuration: {
defaultHeaders: {
Authorization: `Bearer SOME_CUSTOM_VALUE`,
},
},
});
await llmWithCustomHeaders.invoke("Hi there!");
禁用流式使用元数据
一些代理或第三方提供商呈现与 OpenAI 大致相同的 API 界面,但不支持最近添加的 stream_options
参数来返回流式使用情况。您可以使用 ChatOpenAI
通过禁用流式使用情况来访问这些提供商,如下所示
import { ChatOpenAI } from "@langchain/openai";
const llmWithoutStreamUsage = new ChatOpenAI({
temperature: 0.9,
streamUsage: false,
configuration: {
baseURL: "https://proxy.com",
},
});
await llmWithoutStreamUsage.invoke("Hi there!");
调用微调模型
您可以通过传入相应的 modelName
参数来调用微调的 OpenAI 模型。
这通常采用 ft:{OPENAI_MODEL_NAME}:{ORG_NAME}::{MODEL_ID}
的形式。例如
import { ChatOpenAI } from "@langchain/openai";
const fineTunedLlm = new ChatOpenAI({
temperature: 0.9,
model: "ft:gpt-3.5-turbo-0613:{ORG_NAME}::{MODEL_ID}",
});
await fineTunedLlm.invoke("Hi there!");
生成元数据
如果您需要其他信息,如 logprobs 或令牌使用量,这些信息将直接在消息上的 response_metadata
字段内的 .invoke
响应中返回。
需要 @langchain/core
版本 >=0.1.48。
import { ChatOpenAI } from "@langchain/openai";
// See https://cookbook.openai.com/examples/using_logprobs for details
const llmWithLogprobs = new ChatOpenAI({
logprobs: true,
// topLogprobs: 5,
});
const responseMessageWithLogprobs = await llmWithLogprobs.invoke("Hi there!");
console.dir(responseMessageWithLogprobs.response_metadata.logprobs, {
depth: null,
});
{
content: [
{
token: 'Hello',
logprob: -0.0004740447,
bytes: [ 72, 101, 108, 108, 111 ],
top_logprobs: []
},
{
token: '!',
logprob: -0.00004334534,
bytes: [ 33 ],
top_logprobs: []
},
{
token: ' How',
logprob: -0.000030113732,
bytes: [ 32, 72, 111, 119 ],
top_logprobs: []
},
{
token: ' can',
logprob: -0.0004797665,
bytes: [ 32, 99, 97, 110 ],
top_logprobs: []
},
{
token: ' I',
logprob: -7.89631e-7,
bytes: [ 32, 73 ],
top_logprobs: []
},
{
token: ' assist',
logprob: -0.114006,
bytes: [
32, 97, 115,
115, 105, 115,
116
],
top_logprobs: []
},
{
token: ' you',
logprob: -4.3202e-7,
bytes: [ 32, 121, 111, 117 ],
top_logprobs: []
},
{
token: ' today',
logprob: -0.00004501419,
bytes: [ 32, 116, 111, 100, 97, 121 ],
top_logprobs: []
},
{
token: '?',
logprob: -0.000010206721,
bytes: [ 63 ],
top_logprobs: []
}
],
refusal: null
}
工具调用
使用 OpenAI 模型进行工具调用的工作方式与其他模型类似。此外,以下指南包含一些与 OpenAI 特别相关的信息
strict: true
截至 2024 年 8 月 6 日,OpenAI 在调用工具时支持 strict
参数,该参数将强制模型遵守工具参数模式。有关更多信息,请参阅此处:https://platform.openai.com/docs/guides/function-calling。
@langchain/openai >= 0.2.6
注意:如果 strict: true
,工具定义也将被验证,并且接受 JSON 模式的子集。至关重要的是,模式不能有可选参数(那些具有默认值的参数)。在此处阅读有关支持的模式类型的完整文档:https://platform.openai.com/docs/guides/structured-outputs/supported-schemas。
这是一个工具调用的示例。将额外的 strict: true
参数传递给 .bindTools
将把参数传递给所有工具定义
import { ChatOpenAI } from "@langchain/openai";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const weatherTool = tool((_) => "no-op", {
name: "get_current_weather",
description: "Get the current weather",
schema: z.object({
location: z.string(),
}),
});
const llmWithStrictTrue = new ChatOpenAI({
model: "gpt-4o",
}).bindTools([weatherTool], {
strict: true,
tool_choice: weatherTool.name,
});
// Although the question is not about the weather, it will call the tool with the correct arguments
// because we passed `tool_choice` and `strict: true`.
const strictTrueResult = await llmWithStrictTrue.invoke(
"What is 127862 times 12898 divided by 2?"
);
console.dir(strictTrueResult.tool_calls, { depth: null });
[
{
name: 'get_current_weather',
args: { location: 'current' },
type: 'tool_call',
id: 'call_hVFyYNRwc6CoTgr9AQFQVjm9'
}
]
如果您只想将此参数应用于选定数量的工具,您还可以直接传递 OpenAI 格式的工具模式
import { zodToJsonSchema } from "zod-to-json-schema";
const toolSchema = {
type: "function",
function: {
name: "get_current_weather",
description: "Get the current weather",
strict: true,
parameters: zodToJsonSchema(
z.object({
location: z.string(),
})
),
},
};
const llmWithStrictTrueTools = new ChatOpenAI({
model: "gpt-4o",
}).bindTools([toolSchema], {
strict: true,
});
const weatherToolResult = await llmWithStrictTrueTools.invoke([
{
role: "user",
content: "What is the current weather in London?",
},
]);
weatherToolResult.tool_calls;
[
{
name: 'get_current_weather',
args: { location: 'London' },
type: 'tool_call',
id: 'call_EOSejtax8aYtqpchY8n8O82l'
}
]
结构化输出
我们还可以将 strict: true
传递给 .withStructuredOutput()
。这是一个示例
import { ChatOpenAI } from "@langchain/openai";
const traitSchema = z.object({
traits: z
.array(z.string())
.describe("A list of traits contained in the input"),
});
const structuredLlm = new ChatOpenAI({
model: "gpt-4o-mini",
}).withStructuredOutput(traitSchema, {
name: "extract_traits",
strict: true,
});
await structuredLlm.invoke([
{
role: "user",
content: `I am 6'5" tall and love fruit.`,
},
]);
{ traits: [ `6'5" tall`, 'love fruit' ] }
Responses API
以下几点适用于 @langchain/openai>=0.4.5-rc.0
。有关升级指南,请参阅此处。
OpenAI 支持 Responses API,该 API 面向构建 agentic 应用程序。它包括一套 内置工具,包括网络和文件搜索。它还支持 会话状态的管理,允许您继续对话线程,而无需显式传入以前的消息。
如果使用了这些功能之一,ChatOpenAI
将路由到 Responses API。您还可以在实例化 ChatOpenAI
时指定 useResponsesAPI: true
。
内置工具
为 ChatOpenAI
配备内置工具将使其响应基于外部信息,例如通过文件或网络中的上下文。AIMessage 从模型生成的将包括有关内置工具调用的信息。
网络搜索
要触发网络搜索,请将 {"type": "web_search_preview"}
作为另一个工具传递给模型。
您还可以将内置工具作为调用参数传递
llm.invoke("...", { tools: [{ type: "web_search_preview" }] });
import { ChatOpenAI } from "@langchain/openai";
const llm = new ChatOpenAI({ model: "gpt-4o-mini" }).bindTools([
{ type: "web_search_preview" },
]);
await llm.invoke("What was a positive news story from today?");
请注意,响应包括结构化的 内容块,其中包括响应文本和 OpenAI 注释,引用其来源。输出消息还将包含来自任何工具调用的信息。
文件搜索
要触发文件搜索,请将 文件搜索工具 作为另一个工具传递给模型。您需要填充 OpenAI 管理的向量存储,并将向量存储 ID 包含在工具定义中。有关更多详细信息,请参阅 OpenAI 文档。
import { ChatOpenAI } from "@langchain/openai";
const llm = new ChatOpenAI({ model: "gpt-4o-mini" }).bindTools([
{ type: "file_search", vector_store_ids: ["vs..."] },
]);
await llm.invoke("Is deep research by OpenAI?");
与网络搜索一样,响应将包括带有引用的内容块。它还将包括来自内置工具调用的信息。
计算机使用
ChatOpenAI 支持 computer-use-preview
模型,这是一个用于内置计算机使用工具的专用模型。要启用,请将 计算机使用工具 作为另一个工具传递。
目前,计算机使用的工具输出存在于 AIMessage.additional_kwargs.tool_outputs
中。要回复计算机使用工具调用,您需要在创建相应的 ToolMessage
时设置 additional_kwargs.type: "computer_call_output"
。
有关更多详细信息,请参阅 OpenAI 文档。
import { AIMessage, ToolMessage } from "@langchain/core/messages";
import { ChatOpenAI } from "@langchain/openai";
import * as fs from "node:fs/promises";
const findComputerCall = (message: AIMessage) => {
const toolOutputs = message.additional_kwargs.tool_outputs as
| { type: "computer_call"; call_id: string; action: { type: string } }[]
| undefined;
return toolOutputs?.find((toolOutput) => toolOutput.type === "computer_call");
};
const llm = new ChatOpenAI({ model: "computer-use-preview" })
.bindTools([
{
type: "computer-preview",
display_width: 1024,
display_height: 768,
environment: "browser",
},
])
.bind({ truncation: "auto" });
let message = await llm.invoke("Check the latest OpenAI news on bing.com.");
const computerCall = findComputerCall(message);
if (computerCall) {
// Act on a computer call action
const screenshot = await fs.readFile("./screenshot.png", {
encoding: "base64",
});
message = await llm.invoke(
[
new ToolMessage({
additional_kwargs: { type: "computer_call_output" },
tool_call_id: computerCall.call_id,
content: [
{
type: "computer_screenshot",
image_url: `data:image/png;base64,${screenshot}`,
},
],
}),
],
{ previous_response_id: message.response_metadata["id"] }
);
}
推理模型
以下几点适用于 @langchain/openai>=0.4.0
。有关升级指南,请参阅此处。
当使用诸如 o1
之类的推理模型时,withStructuredOutput
的默认方法是 OpenAI 用于结构化输出的内置方法(等效于将 method: "jsonSchema"
作为选项传递到 withStructuredOutput
中)。JSON 模式在很大程度上与其他模型的工作方式相同,但有一个重要的注意事项:在定义模式时,z.optional()
不会被尊重,您应该改用 z.nullable()
。
这是一个示例
import { z } from "zod";
import { ChatOpenAI } from "@langchain/openai";
// Will not work
const reasoningModelSchemaOptional = z.object({
color: z.optional(z.string()).describe("A color mentioned in the input"),
});
const reasoningModelOptionalSchema = new ChatOpenAI({
model: "o1",
}).withStructuredOutput(reasoningModelSchemaOptional, {
name: "extract_color",
});
await reasoningModelOptionalSchema.invoke([
{
role: "user",
content: `I am 6'5" tall and love fruit.`,
},
]);
{ color: 'No color mentioned' }
这是使用 z.nullable()
的示例
import { z } from "zod";
import { ChatOpenAI } from "@langchain/openai";
// Will not work
const reasoningModelSchemaNullable = z.object({
color: z.nullable(z.string()).describe("A color mentioned in the input"),
});
const reasoningModelNullableSchema = new ChatOpenAI({
model: "o1",
}).withStructuredOutput(reasoningModelSchemaNullable, {
name: "extract_color",
});
await reasoningModelNullableSchema.invoke([
{
role: "user",
content: `I am 6'5" tall and love fruit.`,
},
]);
{ color: null }
提示缓存
如果您的输入超过一定大小(在撰写本文时为 1024 个令牌),较新的 OpenAI 模型将自动缓存您提示的部分内容,以降低需要长上下文的用例的成本。
注意:给定查询缓存的令牌数量尚未在 AIMessage.usage_metadata
中标准化,而是包含在 AIMessage.response_metadata
字段中。
这是一个示例
import { ChatOpenAI } from "@langchain/openai";
const modelWithCaching = new ChatOpenAI({
model: "gpt-4o-mini-2024-07-18",
});
// CACHED_TEXT is some string longer than 1024 tokens
const LONG_TEXT = `You are a pirate. Always respond in pirate dialect.
Use the following as context when answering questions:
${CACHED_TEXT}`;
const longMessages = [
{
role: "system",
content: LONG_TEXT,
},
{
role: "user",
content: "What types of messages are supported in LangChain?",
},
];
const originalRes = await modelWithCaching.invoke(longMessages);
console.log("USAGE:", originalRes.response_metadata.usage);
USAGE: {
prompt_tokens: 2624,
completion_tokens: 263,
total_tokens: 2887,
prompt_tokens_details: { cached_tokens: 0 },
completion_tokens_details: { reasoning_tokens: 0 }
}
const resWitCaching = await modelWithCaching.invoke(longMessages);
console.log("USAGE:", resWitCaching.response_metadata.usage);
USAGE: {
prompt_tokens: 2624,
completion_tokens: 272,
total_tokens: 2896,
prompt_tokens_details: { cached_tokens: 2432 },
completion_tokens_details: { reasoning_tokens: 0 }
}
预测输出
某些 OpenAI 模型(例如其 gpt-4o
和 gpt-4o-mini
系列)支持 预测输出,允许您提前传入 LLM 预期输出的已知部分,以减少延迟。这对于编辑文本或代码等情况很有用,在这些情况下,模型的输出只有一小部分会发生变化。
这是一个示例
import { ChatOpenAI } from "@langchain/openai";
const modelWithPredictions = new ChatOpenAI({
model: "gpt-4o-mini",
});
const codeSample = `
/// <summary>
/// Represents a user with a first name, last name, and username.
/// </summary>
public class User
{
/// <summary>
/// Gets or sets the user's first name.
/// </summary>
public string FirstName { get; set; }
/// <summary>
/// Gets or sets the user's last name.
/// </summary>
public string LastName { get; set; }
/// <summary>
/// Gets or sets the user's username.
/// </summary>
public string Username { get; set; }
}
`;
// Can also be attached ahead of time
// using `model.bind({ prediction: {...} })`;
await modelWithPredictions.invoke(
[
{
role: "user",
content:
"Replace the Username property with an Email property. Respond only with code, and with no markdown formatting.",
},
{
role: "user",
content: codeSample,
},
],
{
prediction: {
type: "content",
content: codeSample,
},
}
);
AIMessage {
"id": "chatcmpl-AQLyQKnazr7lEV7ejLTo1UqhzHDBl",
"content": "/// <summary>\n/// Represents a user with a first name, last name, and email.\n/// </summary>\npublic class User\n{\n/// <summary>\n/// Gets or sets the user's first name.\n/// </summary>\npublic string FirstName { get; set; }\n\n/// <summary>\n/// Gets or sets the user's last name.\n/// </summary>\npublic string LastName { get; set; }\n\n/// <summary>\n/// Gets or sets the user's email.\n/// </summary>\npublic string Email { get; set; }\n}",
"additional_kwargs": {},
"response_metadata": {
"tokenUsage": {
"promptTokens": 148,
"completionTokens": 217,
"totalTokens": 365
},
"finish_reason": "stop",
"usage": {
"prompt_tokens": 148,
"completion_tokens": 217,
"total_tokens": 365,
"prompt_tokens_details": {
"cached_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"accepted_prediction_tokens": 36,
"rejected_prediction_tokens": 116
}
},
"system_fingerprint": "fp_0ba0d124f1"
},
"tool_calls": [],
"invalid_tool_calls": [],
"usage_metadata": {
"output_tokens": 217,
"input_tokens": 148,
"total_tokens": 365,
"input_token_details": {
"cache_read": 0
},
"output_token_details": {
"reasoning": 0
}
}
}
请注意,目前预测作为额外的令牌计费,并将增加您的使用量和成本,以换取延迟的减少。
音频输出
某些 OpenAI 模型(例如 gpt-4o-audio-preview
)支持生成音频输出。此示例显示如何使用该功能
import { ChatOpenAI } from "@langchain/openai";
const modelWithAudioOutput = new ChatOpenAI({
model: "gpt-4o-audio-preview",
// You may also pass these fields to `.bind` as a call argument.
modalities: ["text", "audio"], // Specifies that the model should output audio.
audio: {
voice: "alloy",
format: "wav",
},
});
const audioOutputResult = await modelWithAudioOutput.invoke(
"Tell me a joke about cats."
);
const castAudioContent = audioOutputResult.additional_kwargs.audio as Record<
string,
any
>;
console.log({
...castAudioContent,
data: castAudioContent.data.slice(0, 100), // Sliced for brevity
});
{
id: 'audio_67129e9466f48190be70372922464162',
data: 'UklGRgZ4BABXQVZFZm10IBAAAAABAAEAwF0AAIC7AAACABAATElTVBoAAABJTkZPSVNGVA4AAABMYXZmNTguMjkuMTAwAGRhdGHA',
expires_at: 1729277092,
transcript: "Why did the cat sit on the computer's keyboard? Because it wanted to keep an eye on the mouse!"
}
我们看到音频数据在 data
字段内返回。我们还提供了一个 expires_at
日期字段。此字段表示音频响应在服务器上不再可用于多轮对话的日期。
流式音频输出
OpenAI 还支持流式音频输出。这是一个示例
import { AIMessageChunk } from "@langchain/core/messages";
import { concat } from "@langchain/core/utils/stream";
import { ChatOpenAI } from "@langchain/openai";
const modelWithStreamingAudioOutput = new ChatOpenAI({
model: "gpt-4o-audio-preview",
modalities: ["text", "audio"],
audio: {
voice: "alloy",
format: "pcm16", // Format must be `pcm16` for streaming
},
});
const audioOutputStream = await modelWithStreamingAudioOutput.stream(
"Tell me a joke about cats."
);
let finalAudioOutputMsg: AIMessageChunk | undefined;
for await (const chunk of audioOutputStream) {
finalAudioOutputMsg = finalAudioOutputMsg
? concat(finalAudioOutputMsg, chunk)
: chunk;
}
const castStreamedAudioContent = finalAudioOutputMsg?.additional_kwargs
.audio as Record<string, any>;
console.log({
...castStreamedAudioContent,
data: castStreamedAudioContent.data.slice(0, 100), // Sliced for brevity
});
{
id: 'audio_67129e976ce081908103ba4947399a3eaudio_67129e976ce081908103ba4947399a3e',
transcript: 'Why was the cat sitting on the computer? Because it wanted to keep an eye on the mouse!',
index: 0,
data: 'CgAGAAIADAAAAA0AAwAJAAcACQAJAAQABQABAAgABQAPAAAACAADAAUAAwD8/wUA+f8MAPv/CAD7/wUA///8/wUA/f8DAPj/AgD6',
expires_at: 1729277096
}
音频输入
这些模型还支持将音频作为输入传递。为此,您必须指定如下所示的 input_audio
字段
import { HumanMessage } from "@langchain/core/messages";
const userInput = new HumanMessage({
content: [
{
type: "input_audio",
input_audio: {
data: castAudioContent.data, // Re-use the base64 data from the first example
format: "wav",
},
},
],
});
// Re-use the same model instance
const userInputAudioRes = await modelWithAudioOutput.invoke([userInput]);
console.log(
(userInputAudioRes.additional_kwargs.audio as Record<string, any>).transcript
);
That's a great joke! It's always fun to imagine why cats do the funny things they do. Keeping an eye on the "mouse" is a creatively punny way to describe it!
API 参考
有关所有 ChatOpenAI 功能和配置的详细文档,请访问 API 参考:https://api.js.langchain.com/classes/langchain_openai.ChatOpenAI.html