深入浅出 LangChain —— 第三章:模型抽象层

📖 本章学习目标

完成本章后,你将能够:

  • ✅ 理解模型抽象层的设计理念和核心价值
  • ✅ 掌握两种模型配置方式及其适用场景
  • ✅ 接入主流 LLM Provider(OpenAI/Anthropic/Google/Ollama)
  • ✅ 理解消息格式和多轮对话的工作原理
  • ✅ 实现流式输出提升用户体验
  • ✅ 使用结构化输出获取类型安全的数据
  • ✅ 根据业务场景选择合适的模型

一、为什么需要模型抽象层

在实际开发中,你可能会遇到这样的困境:

场景: 你的团队正在用 OpenAI 的 GPT-4o 开发一个 AI 助手。突然有一天:

  • OpenAI 涨价了 50%
  • 或者某个功能在 Claude 上表现更好
  • 或者公司要求数据不能出境,必须用本地模型

如果没有抽象层,你需要重写大量代码来切换模型。这就是 LangChain.js 模型抽象层要解决的问题。

1、传统方式的痛点

如果直接使用各家的原生 SDK,代码会是这样:

ts 复制代码
// ❌ 直接绑定 OpenAI SDK
import OpenAI from "openai";
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [{ role: "user", content: "你好" }]
});

想切换到 Anthropic?需要完全重写:

ts 复制代码
// ❌ 切换到 Anthropic,API 完全不同
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
const response = await anthropic.messages.create({
  model: "claude-3-opus",
  messages: [{ role: "user", content: "你好" }]
});

问题所在:

  • API 格式不同(参数名、返回结构都不一样)
  • 认证方式不同
  • 错误处理逻辑不同
  • 流式输出的实现方式不同

2、LangChain.js 的解决方案

LangChain.js 提供统一的接口层,无论底层用什么模型,调用方式完全一致:
各 Provider SDK
LangChain.js 抽象层
你的应用代码

createAgent({ model: '...' })
统一接口

ChatModel
@langchain/openai

GPT-4o, o1...
@langchain/anthropic

Claude Opus/Sonnet...
@langchain/google-genai

Gemini 2.0...
@langchain/ollama

本地模型

核心优势:

优势 说明 实际价值
快速切换 在不同模型间做对比测试,只需改一个字符串 节省数小时的重构时间
避免供应商锁定 即使某个 Provider 涨价或出故障,迁移成本极低 降低商业风险
统一的流式接口 不用为每个 Provider 写不同的解析逻辑 代码复用率提升 80%+
统一的错误处理 所有 Provider 的错误格式标准化 简化异常处理逻辑

二、两种模型配置方式

LangChain.js 支持两种方式配置模型,分别适用于不同场景。

1、字符串标识符(推荐用于大多数场景)

在 v1.x 中,最简洁的方式是直接传 "provider:model-name" 格式的字符串:

(1)OpenAI 系列
ts 复制代码
import { createAgent } from "langchain";

// GPT-4o:综合能力最强,适合复杂任务
const agent1 = createAgent({ model: "openai:gpt-4o" });

// GPT-4o-mini:性价比高,适合简单任务
const agent2 = createAgent({ model: "openai:gpt-4o-mini" });

// o1-mini:专门优化的推理模型,适合数学和逻辑
const agent3 = createAgent({ model: "openai:o1-mini" });
(2)Anthropic 系列
ts 复制代码
// Claude Opus:最强推理能力,适合复杂分析
const agent4 = createAgent({ model: "anthropic:claude-opus-4-5" });

// Claude Sonnet:平衡性能和成本
const agent5 = createAgent({ model: "anthropic:claude-sonnet-4-6" });

// Claude Haiku:速度最快,成本最低
const agent6 = createAgent({ model: "anthropic:claude-haiku-3-5" });
(3)Google 系列
ts 复制代码
// Gemini 2.0 Flash:免费额度高,响应速度快
const agent7 = createAgent({ model: "google:gemini-2.0-flash" });
(4)本地模型(Ollama)
ts 复制代码
// Llama 3.2:Meta 开源模型,可在本地运行
const agent8 = createAgent({ model: "ollama:llama3.2" });

这种方式的优势:

  • ✅ 代码简洁,一行搞定
  • ✅ 自动处理认证和配置
  • ✅ 适合快速原型开发和大多数生产场景

2、显式实例化(需要精细配置时)

当你需要配置温度、超时、最大 Token 等参数时,直接实例化 ChatModel 类:

ts 复制代码
import { ChatOpenAI } from "@langchain/openai";
import { createAgent } from "langchain";

// 精细配置 OpenAI 模型
const model = new ChatOpenAI({
  model: "gpt-4o",       // 模型名称
  temperature: 0.1,      // 输出随机性(0: 最确定,1: 最随机)
  maxTokens: 2000,       // 限制输出长度
  timeout: 30000,        // 超时时间(毫秒)
  maxRetries: 3,         // 失败自动重试次数
});

const agent = createAgent({ model, tools: [] });

常用配置参数详解:

参数 说明 建议值 影响
temperature 控制输出随机性 工具调用:0~0.2 创意写作:0.7~1.0 值越高,输出越有创造性但也越不可控
maxTokens 最大输出 Token 数 根据任务设置 一般 1000~4000 限制输出长度,控制成本
timeout 单次调用超时时间 30000~60000 ms 防止网络问题导致长时间挂起
maxRetries 失败自动重试次数 2~3 次 处理网络抖动和临时故障
topP 核采样参数 0.8~0.95 与 temperature 配合控制多样性

💡 何时使用显式实例化?

  • 需要精确控制温度(如结构化输出时必须用低温度)
  • 需要自定义超时和重试策略
  • 需要使用 Provider 特有的高级参数
  • 需要在运行时动态调整配置

三、主流 Provider 接入详解

1、OpenAI(GPT 系列)

OpenAI 是最成熟的 LLM Provider,工具调用能力最强。

(1)安装
bash 复制代码
pnpm add @langchain/openai
(2)基础用法
ts 复制代码
import { ChatOpenAI } from "@langchain/openai";

// 创建模型实例
const model = new ChatOpenAI({
  model: "gpt-4o",
  temperature: 0,  // 确定性输出
});

// 直接调用模型(不经过 Agent)
const response = await model.invoke([
  { role: "system", content: "你是一个有帮助的助手。" },
  { role: "user", content: "用一句话解释什么是递归。" },
]);

console.log(response.content);
// 输出:递归是函数调用自身来解决更小规模同类问题的编程技巧。

代码解读:

  • 第 4-7 行:创建模型实例,指定模型和温度
  • 第 10-13 行:构建消息列表(系统消息 + 用户消息)
  • 第 15 行:调用模型并等待响应
  • 第 17 行:输出响应内容
(3)OpenAI 特有参数
ts 复制代码
const model = new ChatOpenAI({
  model: "gpt-4o",
  
  // 强制开启 JSON 输出模式
  // 注意:这只是保证输出是合法 JSON,不保证字段结构
  responseFormat: { type: "json_object" },
  
  // 指定使用的 API Base URL
  // 适用于代理服务器或兼容 OpenAI 接口的服务
  configuration: {
    baseURL: "https://your-proxy.com/v1",
  },
});

⚠️ 注意responseFormat: { type: "json_object" } 只能保证输出是合法的 JSON,但不能保证字段名称和类型符合预期。如果需要严格的结构化输出,应该使用后面介绍的 withStructuredOutput() 方法。

2、Anthropic(Claude 系列)

Claude 系列在长文本处理和复杂推理方面表现优秀。

(1)安装
bash 复制代码
pnpm add @langchain/anthropic
(2)基础用法
ts 复制代码
import { ChatAnthropic } from "@langchain/anthropic";

const model = new ChatAnthropic({
  model: "claude-opus-4-5",  // Claude 最强模型
  temperature: 0,
  maxTokens: 4096,           // Claude 需要显式指定 maxTokens
});

const response = await model.invoke([
  { role: "user", content: "用一句话解释什么是递归。" },
]);

console.log(response.content);

Claude 的特点:

特点 说明 适用场景
超长上下文 Opus/Sonnet 支持 200K tokens 处理整本书、大型代码库
优秀的代码理解 对代码结构和逻辑把握准确 代码审查、重构建议
复杂的推理能力 在多步推理任务中表现出色 数据分析、逻辑推导
自然的对话风格 回答更加流畅和人性化 客服、教育应用

💡 重要提示 :Anthropic 的 API 要求必须设置 maxTokens 参数,否则会报错。这与 OpenAI 不同(OpenAI 有默认值)。

3、Google(Gemini 系列)

Gemini 的优势是免费额度高,多模态能力强。

(1)安装
bash 复制代码
pnpm add @langchain/google-genai
(2)基础用法
ts 复制代码
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";

const model = new ChatGoogleGenerativeAI({
  model: "gemini-2.0-flash",
  temperature: 0,
});

const response = await model.invoke([
  { role: "user", content: "介绍一下你自己。" },
]);

console.log(response.content);

Gemini 的优势:

  • 每月有大量免费额度(适合个人开发者和小团队)
  • 原生支持图像、音频等多模态输入
  • 响应速度快

4、Ollama(本地模型)

Ollama 允许你在本地运行开源模型,数据不离开你的机器。

(1)安装 Ollama
bash 复制代码
# macOS/Linux
curl -fsSL https://ollama.ai/install.sh | sh

# Windows
# 从 https://ollama.ai/download 下载安装包
(2)下载并运行模型
bash 复制代码
# 下载 Llama 3.2 模型(约 2GB)
ollama pull llama3.2

# 测试运行
ollama run llama3.2

# 查看已安装的模型
ollama list
(3)安装 LangChain 集成
bash 复制代码
pnpm add @langchain/ollama
(4)使用本地模型
ts 复制代码
import { ChatOllama } from "@langchain/ollama";

const model = new ChatOllama({
  model: "llama3.2",
  baseUrl: "http://localhost:11434",  // Ollama 默认地址
  temperature: 0,
});

const response = await model.invoke([
  { role: "user", content: "你好!" },
]);

console.log(response.content);

💡 什么时候用本地模型?

优势:

  • ✅ 数据隐私:敏感数据不会发送到外部 API
  • ✅ 零成本:本地运行完全免费
  • ✅ 离线可用:不需要网络连接

劣势:

  • ❌ 硬件要求高:需要较好的 GPU(至少 8GB 显存)
  • ❌ 推理速度慢:比 API 慢 5-10 倍
  • ❌ 质量稍逊:开源模型在复杂推理上通常不如 GPT-4o 或 Claude

典型场景:

  • 企业内部文档问答(数据敏感)
  • 开发阶段高频测试(控制成本)
  • 边缘设备部署(无网络环境)

四、消息格式:理解多角色对话

LangChain.js 的消息系统与 OpenAI 的 Chat Completion 格式对齐。理解消息类型对于写好 Prompt 至关重要。

1、四种消息角色

system

系统消息

设定角色和规则
human

用户消息

用户的输入
tool

工具返回的信息
assistant

助手消息

模型的历史回复

消息类型 角色 用途 示例
SystemMessage system 设定模型的角色、行为规范、背景知识 "你是一个专业的 Python 程序员"
HumanMessage human/user 用户的输入 "如何排序一个列表?"
AIMessage assistant 模型的历史回复(多轮对话中用到) "你可以使用 sorted() 函数..."
ToolMessage tool 工具调用的返回结果(Agent 内部使用) "{result: [1,2,3]}"

2、构建多轮对话

ts 复制代码
import { ChatOpenAI } from "@langchain/openai";
import { 
  HumanMessage, 
  AIMessage, 
  SystemMessage 
} from "@langchain/core/messages";

const model = new ChatOpenAI({ model: "gpt-4o" });

// 构建多轮对话历史
const messages = [
  // 第一步:系统消息(设定角色)
  new SystemMessage("你是一个专业的 TypeScript 开发助手。"),
  
  // 第二步:第一轮对话
  new HumanMessage("什么是泛型?"),
  new AIMessage("泛型是 TypeScript 中允许类型作为参数的机制,可以编写适用于多种类型的通用代码。"),
  
  // 第三步:当前问题(基于上下文的追问)
  new HumanMessage("能给一个实际的例子吗?"),
];

const response = await model.invoke(messages);
console.log(response.content);
// 输出会基于上下文,给出泛型的具体代码示例

执行流程:

  1. 系统消息告诉模型它的角色和专业领域
  2. 第一轮对话建立了基础知识
  3. 第二轮问题基于第一轮的上下文,模型会给出更深入的回答

💡 实际应用提示

在实际 Agent 开发中,你不需要手动管理这个消息列表------LangChain.js 会自动维护对话历史。但理解消息格式,对于调试 Prompt 和理解 Agent 的工作原理很有帮助。

3、使用对象简写(推荐)

除了使用消息类,你也可以直接用对象表示(更简洁):

ts 复制代码
const messages = [
  { role: "system", content: "你是一个助手。" },
  { role: "user", content: "你好!" },
  { role: "assistant", content: "你好!有什么可以帮助你的?" },
  { role: "user", content: "谢谢!" },
];

const response = await model.invoke(messages);

两种方式的区别:

  • 消息类(HumanMessage 等):提供更多元数据和方法,适合复杂场景
  • 对象简写:代码更简洁,适合大多数场景

五、流式输出:提升用户体验

LLM 生成文本是逐 Token 的过程(类似打字机逐个字符输出),等全部生成完才返回会有明显的等待感。

举例: 如果模型要生成 500 个 token,可能需要 5-10 秒。如果等全部生成完再显示,用户会觉得"卡住了"。

流式输出(Streaming) 可以让用户实时看到生成的内容,大幅改善体验。

1、基础流式调用

ts 复制代码
import { ChatOpenAI } from "@langchain/openai";

const model = new ChatOpenAI({ model: "gpt-4o" });

// 使用 stream() 方法替代 invoke()
const stream = await model.stream([
  { role: "user", content: "用 100 字介绍一下 TypeScript。" },
]);

// 逐块处理输出
process.stdout.write("回答:");
for await (const chunk of stream) {
  // chunk.content 是当前块的文本内容
  process.stdout.write(chunk.content as string);
}
process.stdout.write("\n");

代码解读:

  • 第 5 行:使用 stream() 方法,返回一个异步迭代器
  • 第 10-13 行:使用 for await...of 循环遍历流式数据
  • 第 12 行:每收到一块数据就立即输出(实现打字机效果)

效果:打字机效果

复制代码
回答:TypeScript是JavaScript的超集,添加了静态类型系统。它能在编译时发现类型错误,提高代码可维护性。TypeScript支持接口、泛型、装饰器等高级特性,被广泛应用于大型前端项目。→

2、在 Agent 中获取流式输出

ts 复制代码
import { createAgent, tool } from "langchain";
import { z } from "zod";

const agent = createAgent({
  model: "openai:gpt-4o",
  tools: [],
});

// streamMode: "messages" 可以获取逐 Token 的流式输出
const stream = await agent.stream(
  { messages: [{ role: "user", content: "写一首关于编程的短诗。" }] },
  { streamMode: "messages" }
);

for await (const [message, _metadata] of stream) {
  // 只处理 AI 的文本输出块
  if (message.role === "assistant" && typeof message.content === "string") {
    process.stdout.write(message.content);
  }
}

streamMode 的三种模式:

模式 返回格式 适用场景
"messages" [message, metadata] 元组 对话界面,逐 Token 显示
"values" 完整状态对象 需要了解 Agent 的中间思考过程
"updates" 增量变化部分 只关心状态变化的场景

⚠️ 注意 :不同 streamMode 的返回格式不同,需要根据你的需求选择合适的模式。

3、Web 应用中的流式输出

在真实的 Web 应用中,你会通过 Server-Sent Events (SSE)WebSocket 将流式数据推送到前端:

ts 复制代码
// Express.js 示例
app.get("/chat", async (req, res) => {
  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");
  
  const stream = await agent.stream({
    messages: [{ role: "user", content: req.query.q }]
  }, { streamMode: "messages" });
  
  for await (const [message] of stream) {
    if (message.role === "assistant") {
      res.write(`data: ${JSON.stringify({ content: message.content })}\n\n`);
    }
  }
  
  res.end();
});

六、结构化输出:让模型返回可靠的数据

LLM 默认返回自由格式的文本,但在实际应用中,我们往往需要模型输出结构化的数据。

典型场景:

  • 从文章中提取人名、地点、时间等实体
  • 将用户描述解析为 JSON 格式的配置
  • 对文本进行分类并返回固定类别
  • 生成符合特定 Schema 的代码

1、为什么需要结构化输出?

问题场景: 假设你要从新闻中提取信息:

ts 复制代码
// ❌ 不使用结构化输出
const response = await model.invoke([
  { role: "user", content: "提取这篇文章的标题、摘要和标签" }
]);

// 返回的是自由文本,难以解析
console.log(response.content);
// "标题:AI技术突破\n摘要:最近AI领域...\n标签:AI, 技术"

// 你需要写复杂的正则表达式来解析
const title = response.content.match(/标题:(.*)/)?.[1];

解决方案: 使用 withStructuredOutput() + Zod Schema

ts 复制代码
// ✅ 使用结构化输出
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";

// 定义期望的输出结构
const ArticleSchema = z.object({
  title: z.string().describe("文章标题"),
  summary: z.string().describe("文章摘要,不超过 100 字"),
  tags: z.array(z.string()).describe("文章标签列表,3-5 个"),
  difficulty: z.enum(["入门", "中级", "高级"]).describe("文章难度"),
});

const model = new ChatOpenAI({ model: "gpt-4o" });

// 绑定结构化输出 Schema
const structuredModel = model.withStructuredOutput(ArticleSchema);

const result = await structuredModel.invoke([
  {
    role: "user",
    content: `分析这篇文章并提取信息:
    "本文介绍了如何使用 React Hooks 优化组件性能,包括 useMemo、useCallback 和 memo 的使用场景与最佳实践,适合有 React 基础的开发者。"`,
  },
]);

// result 是完全类型安全的!TypeScript 知道它的结构
console.log(result.title);      // string
console.log(result.summary);    // string
console.log(result.tags);       // string[]
console.log(result.difficulty); // "入门" | "中级" | "高级"

优势对比:

方式 返回值类型 类型安全 可靠性 易用性
自由文本 string ❌ 需要手动解析
JSON 模式 any ⚠️ 部分 ⚠️ 字段可能缺失 ⚠️
结构化输出 定义的 Schema ✅ 完全 ✅ 字段保证存在

2、提取多个实体

ts 复制代码
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";

// 定义联系人 Schema
const ContactSchema = z.object({
  contacts: z.array(
    z.object({
      name: z.string().describe("姓名"),
      email: z.string().email().optional().describe("邮箱,如果有的话"),
      phone: z.string().optional().describe("电话号码,如果有的话"),
      company: z.string().optional().describe("公司名称,如果有的话"),
    })
  ).describe("提取出的联系人列表"),
});

const model = new ChatOpenAI({ model: "gpt-4o" });
const extractor = model.withStructuredOutput(ContactSchema);

const text = `
  本次会议参与者:
  张三(zhangsan@example.com,18800001111,来自 ABC 科技)
  李四(lisi@company.com,来自 XYZ 集团)
  王五(13900002222)
`;

const result = await extractor.invoke([
  { role: "user", content: `从以下文本中提取联系人信息:\n${text}` }
]);

console.log(result.contacts);
// [
//   { name: "张三", email: "zhangsan@example.com", phone: "18800001111", company: "ABC 科技" },
//   { name: "李四", email: "lisi@company.com", company: "XYZ 集团" },
//   { name: "王五", phone: "13900002222" }
// ]

关键点:

  • 使用 .optional() 标记可选字段
  • 使用 .email() 等验证器确保格式正确
  • describe() 中详细说明每个字段的含义

3、strict 模式(v1.2.0 新增)

v1.2.0 中新增了 strict 参数,强制模型严格按照 Schema 输出:

ts 复制代码
const structuredModel = model.withStructuredOutput(ArticleSchema, {
  strict: true,  // 严格模式
});

strict 模式的作用:

  • ✅ 减少字段遗漏的概率
  • ✅ 减少格式错误的概率
  • ✅ 提高输出的可靠性
  • ⚠️ 可能会略微增加延迟

💡 最佳实践 :在生产环境中,始终开启 strict: true,除非你有特殊理由。

4、结构化输出 vs JSON 模式

一些 Provider(如 OpenAI)支持 responseFormat: { type: "json_object" } 的 JSON 模式,但这只能保证输出是合法的 JSON,不能保证字段名称和类型符合预期。

对比:

ts 复制代码
// ❌ JSON 模式:只保证是合法 JSON
const model1 = new ChatOpenAI({
  model: "gpt-4o",
  responseFormat: { type: "json_object" }
});
// 返回可能是:{"title": "..."} 或 {"Title": "..."} 或 {"name": "..."}
// 字段名不确定!

// ✅ 结构化输出:保证字段名和类型都符合 Schema
const model2 = new ChatOpenAI({ model: "gpt-4o" });
const structured = model2.withStructuredOutput(ArticleSchema);
// 返回一定是:{ title: string, summary: string, tags: string[], ... }
// 字段名和类型都确定!

结论: 在需要精确数据的场景,始终优先使用 withStructuredOutput()


七、动态模型选择(高级用法)

在某些场景下,你可能希望根据任务复杂度动态切换模型------简单任务用便宜的小模型,复杂任务用性能更强的大模型,以此平衡效果和成本。

实现思路

LangChain.js 通过中间件实现这一点:

ts 复制代码
import { ChatOpenAI } from "@langchain/openai";
import { createAgent, createMiddleware } from "langchain";

// 定义两个不同档次的模型
const basicModel = new ChatOpenAI({ 
  model: "gpt-4o-mini"     // 低成本
});
const advancedModel = new ChatOpenAI({ 
  model: "gpt-4o"          // 高质量
});

// 创建动态模型选择中间件
const dynamicModelMiddleware = createMiddleware({
  name: "DynamicModelSelection",
  
  // 拦截模型调用请求
  wrapModelCall: (request, handler) => {
    const messageCount = request.messages.length;
    
    // 超过 10 条消息时,认为任务较复杂,切换到高级模型
    const selectedModel = messageCount > 10 ? advancedModel : basicModel;
    
    console.log(`选择模型: ${selectedModel.model} (消息数: ${messageCount})`);
    
    // 用选中的模型处理请求
    return handler({ ...request, model: selectedModel });
  },
});

// 创建 Agent 并注册中间件
const agent = createAgent({
  model: basicModel,  // 默认模型
  tools: [],
  middleware: [dynamicModelMiddleware],
});

工作原理:

  1. 中间件拦截每次模型调用请求
  2. 根据请求内容(如消息数量)决定使用哪个模型
  3. 用选中的模型处理请求

💡 实际应用场景:

  • 客服系统:简单问题用 mini 模型,复杂投诉用完整版
  • 代码助手:语法查询用 mini,架构设计用完整版
  • 成本控制:90% 的请求用便宜模型,只有 10% 用昂贵模型

注意: 中间件系统会在第七章详细讲解,这里只是展示一个直觉性的例子。


八、模型选型建议

在实际项目中,如何选择合适的模型?以下是一份参考矩阵:

场景化推荐

场景 推荐模型 理由 成本参考
工具调用密集的 Agent openai:gpt-4o 工具调用准确率高,多工具并行能力强 $$$
长文档分析(>50K tokens) anthropic:claude-opus-4-5 超长上下文窗口,长文阅读理解优秀 $$$$
高频低延迟场景 openai:gpt-4o-mini anthropic:claude-haiku-3-5 响应快(<1s),成本低 $
复杂推理 / 数学 openai:o1-mini anthropic:claude-opus-4-5 推理能力专门优化 − - −$
代码生成 anthropic:claude-sonnet-4-6 openai:gpt-4o 代码质量高,理解上下文能力强 − - −$
本地部署 / 数据敏感 ollama:llama3.2 ollama:qwen2.5 数据不出本地,免费使用 免费
开发调试阶段 任何 *-mini / *-flash 版本 响应快、成本低,适合高频测试 $

成本对比(每 1M tokens)

模型 输入价格 输出价格 相对成本
GPT-4o $2.50 $10.00 基准
GPT-4o-mini $0.15 $0.60 6%
Claude Opus $15.00 $75.00 600%
Claude Sonnet $3.00 $15.00 120%
Claude Haiku $0.25 $1.25 10%
Gemini 2.0 Flash $0.10 $0.40 4%

💡 实践建议:

  1. 开发阶段:优先用便宜的 mini 模型,功能跑通后再切换到高质量模型做效果对比
  2. A/B 测试:同时用两个模型处理相同任务,对比质量和成本
  3. 监控成本:接入 LangSmith,实时监控 Token 消耗和费用
  4. 缓存策略:对重复问题使用缓存,避免重复调用 LLM

九、本章小结

模型抽象层是 LangChain.js 的基础设施之一。这一章我们学习了:

📝 核心知识点回顾

  1. 统一接口的价值:无论哪家 Provider,调用方式一致,避免供应商锁定
  2. 两种配置方式
    • 字符串标识符:简洁,适合大多数场景
    • 显式实例化:灵活,适合需要精细控制的场景
  3. 四大 Provider:OpenAI、Anthropic、Google、Ollama 的特点和接入方式
  4. 消息格式system / human / assistant / tool 四种消息类型的作用
  5. 流式输出stream() 方法和三种 streamMode 的选择
  6. 结构化输出withStructuredOutput() + Zod Schema实现类型安全的结构化返回
  7. 模型选型:根据场景选择合适模型的参考框架

🎯 动手练习

尝试完成以下练习,巩固所学知识:

练习 1:切换模型对比

创建一个简单的问答 Agent,分别用 gpt-4ogpt-4o-mini 回答同一个复杂问题,对比响应时间和质量差异。

练习 2:结构化输出实战

设计一个 Schema,从电影评论中提取:评分(1-5)、情感倾向(正面/负面/中性)、提到的演员名单。

练习 3:流式输出 Web 应用

创建一个简单的 Express.js 应用,实现 SSE 流式输出,在前端页面上实现打字机效果。

练习 4:本地模型测试

安装 Ollama 和 Llama 3.2,对比本地模型和 GPT-4o 在代码生成任务上的表现。

📚 延伸阅读


下一章:《第四章 ------ 提示词工程(Prompt Engineering)》

相关推荐
givemeacar2 小时前
spring-boot-starter和spring-boot-starter-web的关联
前端
Destiny_where2 小时前
Langgraph基础(4)-中断interrupt.实现图执行的动态暂停与外部交互
人工智能·python·langchain·langgraph
147API2 小时前
多模型时代,如何根据任务轻重合理分配模型资源?
人工智能·大模型api·api中转·ai架构
boonya2 小时前
一文读懂MCP:AI连接万物的“USB-C接口”
c语言·开发语言·人工智能
石榴树下的七彩鱼2 小时前
图片去水印 API 哪个好?5种方案实测对比(附避坑指南 + 免费在线体验)
图像处理·人工智能·后端·python·api接口·图片去水印·电商自动化
liliangcsdn2 小时前
多轮对话长上下文-向量检索和混合召回示例
开发语言·数据库·人工智能·python
MFXWW22 小时前
特斯拉 Optimus Gen3 手臂设计解析:从 “能抓“ 到 “会用“ 的工程革命
人工智能·机器人
user_admin_god2 小时前
OpenCode入门到入坑
java·人工智能·spring boot·语言模型