本文主要跑通一个基本langchain 的Model I/O(Model Input / Output):也就是 你如何把数据“送进模型”(Input),以及如何从模型“拿出结果”(Output)。
会先以最基本的 初始化模型 -> 用户输入 -> 模型调用。完成最小闭环。至于提示词工程,结构化输出,消息类型,会在后面做补充
以下是Lanchain Model I/O的示意图: 模型调用的“输入输出协议层”
文章目录
- 为什么要用 LangChain 开发ai 应用
- apiKey的申请 及开发环境准备
- 模型初始化
initChatModel方法 - 模型调用
invock方法 - 细节补充及总结
为什么要用 LangChain 开发ai 应用?
- 抹平模型厂商差异
现在 AI 模型厂商层出不穷,这对整个行业来说是好事,推动了 AI 的快速发展。
但对于开发者来说,其实并不那么友好。
在实际项目中,我们往往不会只使用一家模型厂商的服务,比如可能同时接入:
- OpenAI
- 阿里百炼
- 智谱 AI
- 甚至一些本地模型
这时候问题就来了:
👉 不同厂商的 API 调用方式、参数格式、返回结构都不一样
如果每接一个模型就写一套适配逻辑:
- 代码会变得非常混乱
- 后期维护成本极高
而 LangChain 的价值就在这里:
👉 统一模型调用方式,屏蔽底层差异
你可以把它理解为:
LangChain ≈ Java 里的 JDBC
只需要面向统一接口开发,就可以灵活切换不同模型厂商。
来看图示
langchain 源码体现:
👉 枚举各个厂商,然后通过 动态 import + 统一的 ConfigurableModel 代理实现(具体不细讲)
- 提供丰富的组件能力
LangChain 不只是“统一调用模型”这么简单,它本质是一个完整的 AI 应用开发框架,内置了很多核心能力,比如:
- Prompt 模板(PromptTemplate)
- 输出解析(OutputParser)
- 工具调用(Tools)
- 记忆管理(Memory)
- Agent 能力
不过说实话,对于大多数前端/应用开发者来说:
👉 日常用到最多的,其实还是:
- 聊天能力(LLM 调用)
- 简单的 Prompt 组织
- AI 工具接入 (cursor, Cloud Code)
大模型 ≠ 完整 AI 应用
很多人会有一个误区:
“有了大模型,就等于有了 AI 应用”
其实不是。
你可以把大模型理解为一个“超级大脑”,它具备:
- 强大的知识能力
- 推理能力
但它本身不具备:
- 长期记忆
- 行动能力
- 任务规划能力
所以,一个完整的 AI 应用通常是这样的:
AI Agent = LLM(大脑) + Memory(记忆) + Planning(规划) + Tools(工具)
👉 而 LangChain,正是帮你把这些能力“拼装起来”的工具。
下面就让我们来开始一个demo 尝尝鲜 😄😄😄
模型申请(阿里云百炼:有免费额度)
点击下方链接,阅读文档,根据文档指引,申请API Key
- 在模型广场选一个合适的模型即可,这里我们使用
qwen-coder-turbo
开发环境准备
- 创建项目
mkdir langchain-project
cd langchain-project
npm init -y
- 创建文件入口
src/langchain-invoke.mjs
说明:
.mjs是 ESM 模块格式- 支持
import / export - 方便我们快速调试
👉 后续工程化后,直接使用 .js 也是完全没问题的
初始化模型
- 安装依赖
pnpm install langchain
- 使用
initChatModel初始化模型
import { initChatModel } from 'langchain';
const model = initChatModel(
'qwen-coder-turbo' // 模型名
{
modelProvider: "openai", // 告诉工厂:虽然是 xxx服务,但请用 OpenAI 的 SDK 逻辑
baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1" // 对应SDK里的字段
apiKey: 'sk-d69fd787d37241fxxxxe8bb914292108' // 对应SDK里的字段
}
)
模型调用
我们这里使用的是 ChatModel(对话模型),在初始化模型处 initChatModel
👉 特点:
- 输入:单条消息 / 消息列表
- 输出:一条 AIMessage
使用invoke
const response = await model.invoke("为什么鹦鹉有彩色的羽毛?");
console.log(response);
// console.log(response.content);
返回结果说明
返回值是一个 AIMessage 对象,例如:
{
content: "因为羽毛中含有色素和结构色...",
...
}
👉 如果你只关心文本内容:
console.log(response.content);
🎉 小结
到这里,我们已经完成了:
- 模型初始化
- 模型调用
- 获取返回结果
👉 一个最基础的 LangChain Demo 就跑通了,是不是很简单?
进阶补充
❗ 别让你的 API Key “裸奔” —— 使用.env
直接把 API Key 写死在代码里:
apiKey: 'sk-xxx'
👉 只适用于临时测试
👉 在生产环境中是非常危险的(会泄露密钥)
使用 dotenv 管理环境变量
- 安装:
pnpm install dotenv
- 创建
.env文件:
# OpenAI API 配置
# OpenAI API 密钥
OPENAI_API_KEY=sk-d69fd787d37241xxxf9e8bb914292108
# OpenAI API 地址
OPENAI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
# 模型名称
MODEL_NAME=qwen-coder-turbo
- 在代码中使用
// import dotenv from "dotenv";
// dotenv.config();
import 'dotenv/config';
import { initChatModel } from 'langchain';
const model = await initChatModel(process.env.MODEL_NAME, {
modelProvider: 'openai',
apiKey: process.env.OPENAI_API_KEY,
baseUrl: process.env.OPENAI_BASE_URL,
});
const result = await model.invoke("为什么鹦鹉有彩色的羽毛?");
console.log(result);
.gitignore忽略敏感信息
node_modules
.env
package-lock.json
.DS_Store
为什么有时读取不到 .env ?
我一开始为了图省事,直接 cd 到 src 目录,然后执行:
node ./langchain-invoke.mjs
结果直接报错:
👉 提示找不到 API Key
🧠 根本原因
问题其实出在这一点:
dotenv默认是基于 当前执行目录(process.cwd) 去查找.env文件
也就是说:
👉 Node 并不知道你的“项目根目录”在哪里
👉 它只知道:你是从哪个目录执行 node 命令的
👉 src 下没有.env, 自然就读取不到了
初始化模型的另一种方式:ChatOpenAI
在早期 LangChain 使用中,我们通常直接使用 ChatOpenAI 这样的模型类。但随着多模型时代的到来,LangChain 提供了 initChatModel 作为统一入口,使开发者可以在不修改业务代码的情况下切换不同模型厂商,从而实现真正的模型解耦。
- 安装
pnpm install @langchain/openai
- 使用
import { ChatOpenAI } from '@langchain/openai';
const model = new ChatOpenAI({
model: process.env.MODEL_NAME,
apiKey: process.env.OPENAI_API_KEY,
configuration: {
baseURL: process.env.OPENAI_BASE_URL,
},
});
const result = await model.invoke("为什么鹦鹉有彩色的羽毛?");
console.log(result);
initChatModel 和 ChatOpenAI 的区别
👉 ChatOpenAI = 面向 **OpenAI 的模型 SDK(具体实现)
👉 initChatModel = 模型统一入口(抽象层 + 工厂模式)
架构对比
# ChatOpenAI(单一厂商)
你的代码 → ChatOpenAI → OpenAI API
# initChatModel(多模型架构)
你的代码 → initChatModel → Provider Adapter → 任意模型
消息类型
在上面我们已经接触到了 AIMessage,顾名思义,它表示 AI 返回的消息。
除此之外,LangChain 中还定义了一系列标准消息类型:
HumanMessage:用户输入SystemMessage:系统指令(用于控制 AI 行为)AIMessage:模型输出ToolMessage:工具执行结果
demo
- 对象列表 (new xxx)
import { SystemMessage, HumanMessage, AIMessage } from "langchain";
const messages = [
new SystemMessage("You are a poetry expert"),
new HumanMessage("Write a haiku about spring"),
new AIMessage("Cherry blossoms bloom..."),
];
const response = await model.invoke(messages);
- 字典格式 (k-v)
const messages = [
{ role: "system", content: "You are a poetry expert" },
{ role: "user", content: "Write a haiku about spring" },
{ role: "assistant", content: "Cherry blossoms bloom..." },
];
const response = await model.invoke(messages);
他的demo相对比较简单,看官方文档即可 docs.langchain.com/oss/javascr…
🤔 为什么不直接返回字符串?
你可能会有一个疑问:
👉 “我问 AI 一个问题,它直接返回字符串不就行了吗?为什么还要包一层
AIMessage?”
🤔 先说结论
Message 的存在,不是为了“多包一层”,
而是为了让 AI 的输出,从“文本”升级为“可编排的数据结构”。
Message 解决的 4 个真实问题(重点)
Message 是AI 执行过程的“状态载体”,会贯穿后面整个学习流程,所以是至关重要的!!!
1️⃣ 让 AI 可以“调用系统能力”
AIMessage.tool_calls
👉 用于:
- 查天气
- 查数据库
- 调接口
- 调用你写的函数
👉 没有 Message:
AI 只能“建议你去做”
👉 有 Message:
AI 可以“驱动系统帮你做”
2️⃣ 让 AI 输出“结构化数据”
比如你做电商(你现在就在做)👇
用户说:
帮我生成一个商品标题
👉 string:
"2024新款男士运动鞋,透气舒适"
👉 你还得自己解析 😓
👉 Message + 结构化:
{
content: "",
additional_kwargs: {
title: "2024新款男士运动鞋",
keywords: ["透气", "舒适"],
category: "运动鞋"
}
}
💥 第三个价值:
✅ 天然支持结构化输出(适合业务系统)
3️⃣ 支持多轮对话(上下文)
[
new SystemMessage("你是电商运营助手"),
new HumanMessage("帮我优化标题"),
new AIMessage("请提供商品信息"),
new HumanMessage("男士跑鞋")
]
👉 如果只是 string:
❌ 上下文全丢
💥 第四个价值:
✅ Message = 对话上下文容器
4️⃣ 支持“中间状态”(非常关键)
在复杂流程里,AI 不止返回最终结果:
👉 比如:
思考 → 调工具 → 再思考 → 输出结果
👉 Message 可以承载:
- 中间推理(部分可见)
- tool 调用
- token 消耗
- trace 信息
模型的其他调用方式
上面我们使用 invoke 来调用模型,可以发现它会在生成完整结果后一次性返回,因此往往需要等待一段时间。
如果希望像“打字机”一样实时看到模型的输出(流式返回),可以使用 stream 方法,让结果边生成边输出,提升交互体验。 除此之外,还有批量处理模型请求的batch
// stream
const stream = await model.stream("帮我生成一个比亚迪商品标题");
for await (const chunk of stream) {
// console.log('stream:', chunk);
// console.log(chunk.text)
console.log(chunk.content)
}
🎉 总结
本文围绕 LangChain 的 Model I/O,完成了从 模型初始化 → 输入构建 → 模型调用 → 输出解析 的最小闭环。
主要内容包括:
-
为什么使用 LangChain
通过统一接口抹平不同模型厂商之间的差异,同时提供丰富的组件能力,让我们可以专注于业务开发,而不是处理各种兼容问题。 -
模型初始化
以最常见的 ChatModel 为例,介绍了如何使用initChatModel初始化模型,以及apiKey、baseUrl等核心参数的配置方式,并补充了dotenv环境变量的使用实践。 -
消息类型(Message)
通过模型返回值AIMessage,引出了SystemMessage、HumanMessage等消息类型,并讲解了对象形式与字典形式的写法。同时也解释了:
👉 为什么模型不直接返回字符串,而是使用 Message 结构 —— 因为 Message 是 AI 执行过程的“状态载体”,能够支持工具调用、多轮对话、中间状态以及结构化输出等能力。 -
模型调用方式
对比了invoke、stream、batch三种调用方式:invoke:一次性返回,适合调试stream:流式输出,更适合实际交互场景(主流方式)batch:批量处理请求
至此,一个最基础的 AI Demo 已经完成。相信你已经对 LangChain 的 Model I/O 有了整体认知。
不过,关于 Message 的理解目前还停留在“能用”的阶段。
👉 在下一篇中,我们将深入分析 LangChain 的消息机制,以及它是如何驱动 Tool 和 Agent 执行的。
为了语句通顺,加入了很多ai 代写,希望大家谅解 🐶🐶🐶
入门文章,如有遗漏,还请多多指教 🤝🤝🤝