5分钟跑通 LangChain,第一个 AI Demo(超详细)

本文主要跑通一个基本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 应用通常是这样的:

ini 复制代码
AI Agent = LLM(大脑) + Memory(记忆) + Planning(规划) + Tools(工具)

👉 而 LangChain,正是帮你把这些能力"拼装起来"的工具。

下面就让我们来开始一个demo 尝尝鲜 😄😄😄

模型申请(阿里云百炼:有免费额度)

点击下方链接,阅读文档,根据文档指引,申请API Key

  • 在模型广场选一个合适的模型即可,这里我们使用 qwen-coder-turbo

开发环境准备

  • 创建项目
bash 复制代码
mkdir langchain-project
cd langchain-project
npm init -y
  • 创建文件入口
js 复制代码
src/langchain-invoke.mjs

说明:

  • .mjsESM 模块格式
  • 支持 import / export
  • 方便我们快速调试

👉 后续工程化后,直接使用 .js 也是完全没问题的

初始化模型

  • 安装依赖
js 复制代码
pnpm install langchain
  • 使用 initChatModel 初始化模型
js 复制代码
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
vbscript 复制代码
const response = await model.invoke("为什么鹦鹉有彩色的羽毛?");
console.log(response);
// console.log(response.content);
返回结果说明

返回值是一个 AIMessage 对象,例如:

css 复制代码
{
  content: "因为羽毛中含有色素和结构色...",
  ...
}

👉 如果你只关心文本内容:

vbscript 复制代码
console.log(response.content);

🎉 小结

到这里,我们已经完成了:

  • 模型初始化
  • 模型调用
  • 获取返回结果

👉 一个最基础的 LangChain Demo 就跑通了,是不是很简单?

进阶补充

❗ 别让你的 API Key "裸奔" ------ 使用.env

直接把 API Key 写死在代码里:

js 复制代码
apiKey: 'sk-xxx'

👉 只适用于临时测试

👉 在生产环境中是非常危险的(会泄露密钥)

使用 dotenv 管理环境变量

  • 安装:
js 复制代码
pnpm install dotenv
  • 创建 .env 文件:
js 复制代码
# 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
  • 在代码中使用
js 复制代码
// 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 忽略敏感信息
bash 复制代码
node_modules
.env
package-lock.json
.DS_Store
为什么有时读取不到 .env ?

我一开始为了图省事,直接 cdsrc 目录,然后执行:

bash 复制代码
node ./langchain-invoke.mjs

结果直接报错:

👉 提示找不到 API Key

🧠 根本原因

问题其实出在这一点:

dotenv 默认是基于 当前执行目录(process.cwd) 去查找 .env 文件

也就是说:

👉 Node 并不知道你的"项目根目录"在哪里

👉 它只知道:你是从哪个目录执行 node 命令的

👉 src 下没有.env, 自然就读取不到了

初始化模型的另一种方式:ChatOpenAI

在早期 LangChain 使用中,我们通常直接使用 ChatOpenAI 这样的模型类。但随着多模型时代的到来,LangChain 提供了 initChatModel 作为统一入口,使开发者可以在不修改业务代码的情况下切换不同模型厂商,从而实现真正的模型解耦。

  • 安装
js 复制代码
pnpm install @langchain/openai
  • 使用
js 复制代码
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 = 模型统一入口(抽象层 + 工厂模式)

架构对比

bash 复制代码
# ChatOpenAI(单一厂商)
你的代码 → ChatOpenAI → OpenAI API

# initChatModel(多模型架构)
你的代码 → initChatModel → Provider Adapter → 任意模型
消息类型

在上面我们已经接触到了 AIMessage,顾名思义,它表示 AI 返回的消息

除此之外,LangChain 中还定义了一系列标准消息类型:

  • HumanMessage:用户输入
  • SystemMessage:系统指令(用于控制 AI 行为)
  • AIMessage:模型输出
  • ToolMessage:工具执行结果
demo
  • 对象列表 (new xxx)
javascript 复制代码
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)
ini 复制代码
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:

arduino 复制代码
"2024新款男士运动鞋,透气舒适"

👉 你还得自己解析 😓


👉 Message + 结构化:

less 复制代码
{
  content: "",
  additional_kwargs: {
    title: "2024新款男士运动鞋",
    keywords: ["透气", "舒适"],
    category: "运动鞋"
  }
}

💥 第三个价值:

天然支持结构化输出(适合业务系统)


3️⃣ 支持多轮对话(上下文)
arduino 复制代码
[
  new SystemMessage("你是电商运营助手"),
  new HumanMessage("帮我优化标题"),
  new AIMessage("请提供商品信息"),
  new HumanMessage("男士跑鞋")
]

👉 如果只是 string:

❌ 上下文全丢


💥 第四个价值:

Message = 对话上下文容器



4️⃣ 支持"中间状态"(非常关键)

在复杂流程里,AI 不止返回最终结果:


👉 比如:

复制代码
思考 → 调工具 → 再思考 → 输出结果

👉 Message 可以承载:

  • 中间推理(部分可见)
  • tool 调用
  • token 消耗
  • trace 信息

模型的其他调用方式

上面我们使用 invoke 来调用模型,可以发现它会在生成完整结果后一次性返回,因此往往需要等待一段时间。

如果希望像"打字机"一样实时看到模型的输出(流式返回),可以使用 stream 方法,让结果边生成边输出,提升交互体验。 除此之外,还有批量处理模型请求的batch

javascript 复制代码
// 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,完成了从 模型初始化 → 输入构建 → 模型调用 → 输出解析 的最小闭环。

主要内容包括:

  1. 为什么使用 LangChain

    通过统一接口抹平不同模型厂商之间的差异,同时提供丰富的组件能力,让我们可以专注于业务开发,而不是处理各种兼容问题。

  2. 模型初始化

    以最常见的 ChatModel 为例,介绍了如何使用 initChatModel 初始化模型,以及 apiKeybaseUrl 等核心参数的配置方式,并补充了 dotenv 环境变量的使用实践。

  3. 消息类型(Message)

    通过模型返回值 AIMessage,引出了 SystemMessageHumanMessage 等消息类型,并讲解了对象形式与字典形式的写法。同时也解释了:

    👉 为什么模型不直接返回字符串,而是使用 Message 结构 ------ 因为 Message 是 AI 执行过程的"状态载体",能够支持工具调用、多轮对话、中间状态以及结构化输出等能力。

  4. 模型调用方式

    对比了 invokestreambatch 三种调用方式:

    • invoke:一次性返回,适合调试
    • stream:流式输出,更适合实际交互场景(主流方式)
    • batch:批量处理请求

至此,一个最基础的 AI Demo 已经完成。相信你已经对 LangChain 的 Model I/O 有了整体认知。

不过,关于 Message 的理解目前还停留在"能用"的阶段。

👉 在下一篇中,我们将深入分析 LangChain 的消息机制,以及它是如何驱动 Tool 和 Agent 执行的。

为了语句通顺,加入了很多ai 代写,希望大家谅解 🐶🐶🐶

入门文章,如有遗漏,还请多多指教 🤝🤝🤝

相关推荐
南蓝2 小时前
【Vibe Coding】Claude Code CLI 本地版与全局版冲突
ai编程
与虾牵手2 小时前
LobeChat 部署后怎么配置 API?2026 完整教程 + 踩坑记录
aigc·ai编程
OpenTiny社区2 小时前
TinyRobot Skills技巧大公开:让 AI 成为你的 “UI 搭建”副驾驶
前端·vue.js·ai编程
console.log('npc')2 小时前
Cursor,Trae,Claude Code如何协作生产出一套前后台app?
前端·人工智能·react.js·设计模式·ai·langchain·ai编程
Cendeal3 小时前
SDD开发者要承担什么角色
ai编程
Cendeal3 小时前
Agentic Coding是啥模式
ai编程
yuanlaile3 小时前
从0到1,AI大模型保姆级学习路线!
人工智能·ai编程·ai大模型·ai大模型应用·ai大模型学习
慧知AI3 小时前
黄仁勋喊出"下一个ChatGPT"后,我用OpenClaw新版ContextEngine给公司Agent系统省了40%的Token费
openai
土豆12504 小时前
AI编程中的SKILL:理论与实践完全指南
llm·ai编程