LangChain.js 快速上手指南:模型接入、流式输出打造基础

大模型应用正在从"对话式AI"向"行动式AI"演进。如果说ChatGPT代表了生成式AI的第一阶段 ------理解并生成内容,那么基于Agent的自主系统则标志着第二阶段 ------理解、决策并执行行动

LangChain.js 作为当前最成熟的 TypeScript Agent 开发框架,已经成为构建生产级AI应用的事实标准。但官方文档偏重概念,社区教程零散浅显,从入门到落地之间存在着巨大的工程鸿沟。

本系列将围绕以下问题展开学习讨论

模块 核心内容 产出目标
架构篇 Agent 核心抽象、Runnable 协议、工具链设计 能独立设计复杂 Agent 架构
工具篇 自定义 Tool 开发、Zod Schema 验证、错误处理 封装企业级可复用工具库
记忆篇 BufferMemory、VectorStore 检索、对话状态机 实现长程上下文保持的 Agent
编排篇 LCEL 链式表达、并行执行、条件路由、Fallback 机制 构建高可靠的多 Agent 系统
实战篇 ReAct、Plan-and-Execute、Multi-Agent 协作 完整项目:自动化数据分析 Agent

你需要什么基础?

  • TypeScript/JavaScript(泛型、异步、装饰器)
  • LLM 基础概念(Prompt、Token、上下文窗口)
  • 可选但加分:有 Express/nest 等后端开发经验

不需要你读过 LangChain 文档,我们只需要学习最常用的工具appi,以实战演练为目标,用到什么学什么

技术选型说明

选择 LangChain.js 而非 Python 版本,基于三个现实考量:

  1. 工程化成熟度:TypeScript 的类型系统对大型 Agent 系统的可维护性至关重要
  2. 生态位差异:Python 版在数据科学场景占优,JS/TS 版在企业服务集成、Web 部署场景更成熟
  3. 运行时优势:Edge Computing、Serverless 部署的天然适配

最重要的是,作为前端使用js/ts可以无缝衔接,不需要学习过多新知识,技术债最小化,上手即生产

学前准备

薅国内的大模型羊毛很方便,用来学习agent再合适不过了

阿里、腾讯、字节都有大模型接口的免费额度,我们先以字节为例

字节旗下的豆包模型有50万Token的免费额度,足够我们学习测试了

登录火山引擎,去模型广场选择一个模型

console.volcengine.com/ark/region:...

点击API接入

你会得到一个api key,我们在使用代码调用模型时需要使用到

ark.cn-beijing.volces.com/api/v3

在API KEY管理处可以查看自己的key密钥

langChain.js基础

为了方便演示和快速上手学习,我直接使用js

创建一个 test文件夹用来初始化项目

js 复制代码
mkdir test
cd test
npm init -y

并且修改package.json文件,因为需要使用ES Modules 语法使用import进行导出使用方法,所以要添加

js 复制代码
"type": "module",

豆包模型以及国内的模型大都兼容OpenAI API,所以我们使用@langchain/openai

js 复制代码
npm install @langchain/openai

创建 src/index.js文件,写入以下代码

js 复制代码
import { ChatOpenAI } from '@langchain/openai';

const model = new ChatOpenAI({
    modelName: "模型名字",
    apiKey: '你的密钥 API Key',
    configuration: {
        baseURL: 'https://ark.cn-beijing.volces.com/api/v3',
    },
});

const response = await model.invoke("你是谁?");
console.log(response.content);

这就完成了一个最小可调用的大模型案例,替换掉你申请的模型密钥和模型名字以及豆包的baseURL

在控制台执行

js 复制代码
node ./src/index.js

控制台就会生成回答

密钥放到代码里传到github上不安全,所以我们引入dotenv,将这些重要变量放到 .env

js 复制代码
npm install dotenv --save

创建.env文件,并在代码里引入

js 复制代码
import { ChatOpenAI } from '@langchain/openai';
import 'dotenv/config'

const model = new ChatOpenAI({
    modelName: process.env.MODEL_NAME,
    apiKey: process.env.API_KEY,
    configuration: {
        baseURL: process.env.BASE_URL,
    },
});

const response = await model.invoke("你是谁?");
console.log(response.content);

ChatOpenAI 创建模型对象

ChatOpenAI 是 OpenAI 提供的聊天完成 API 的封装,主要用于与 GPT 模型进行对话交互,配置好模型的基本参数后就可以调用实例进行对话

js 复制代码
// 基础配置
const model = new ChatOpenAI({
    // 必需参数
    apiKey: "API Key",
    
    // 模型配置
    modelName: "模型名字",
    
    // 自定义配置(如使用代理)
    configuration: {
        baseURL: "模型基础地址",
        timeout: 60000,			// 请求超时时间(毫秒)
        maxRetries: 2,			// 最大重试次数
    },
    
    // 请求控制参数
    temperature: 0.7,        // 平衡的创造性
    maxTokens: 1000,         // 限制输出长度
    topP: 0.9,               // 核采样
    frequencyPenalty: 0.3,   // 减少重复词汇
    presencePenalty: 0.3,    // 鼓励新话题
    
    // 高级配置
    streaming: false,        // 非流式输出
});

invoke 与大模型对话

invoke 是 LangChain 中执行模型并获取响应的方法,可以传入单个消息或消息列表

他会将输入字符串 "你是谁?" 转换为 LangChain 的消息格式,并且会返回一个 AIMessage 对象,包含以下属性

js 复制代码
{
    content: "我是 AI 助手...",    // 模型的回复内容
    additional_kwargs: {},         // 额外信息(如 token 使用量)
    response_metadata: {},         // 响应元数据
    tool_calls: [],               // 工具调用信息(如果有)
    usage_metadata: {}            // 使用统计信息
}

使用invoke返回的消息是等大模型将全部的信息都生成后才返回。

大多数模型可以在生成时流式传输其输出内容。通过逐步显示输出,流式传输可以显著改善用户体验,特别是对于较长的响应。此时可以使用 stream方法

stream 输出流

js 复制代码
const response = await model.stream("你是谁?");
for await (const chunk of response) {
    if (chunk.text) {
        console.log(chunk.text)
    }
}

stream()在模型响应后返回单个 AIMessage ,它返回多个 AIMessageChunk 对象,每个对象包含输出文本的一部分。

js 复制代码
AIMessageChunk {
  "id": "021770099910687b6043c5851c0a2627b25b78c406cf3041f4436",
  "content": "呀",
  "additional_kwargs": {},
  "response_metadata": {
    "prompt": 0,
    "completion": 0,
    "model_provider": "openai",
    "usage": {}
  },
  "tool_calls": [],
  "tool_call_chunks": [],
  "invalid_tool_calls": []
}

Messages 消息类型

在使用 model.stream("你是谁?");model.invoke("你是谁?")直接传入文本字符串时,langChain会自动转为 HumanMessage信息格式

js 复制代码
"你是谁?"  →  HumanMessage({ content: "你是谁?" })

在只传入简单的文本字符串时,只适用于不需要保留对话历史的简单的生成任务

langChain有四种消息格式:SystemMessage、HumanMessage、AIMessage、ToolMessage

  • SystemMessage:系统消息 - 告知模型如何行为并提供交互上下文。简单来说就是给AI设置一个角色,能干什么,有什么能力
  • HumanMessage:人类消息 - 代表用户输入和与模型的交互。用户输入的信息
  • AIMessage:AI 消息 - 模型生成的响应,包括文本内容、工具调用和元数据
  • ToolMessage:工具消息 - 表示工具调用的输出

首先安装@langchain/core

js 复制代码
npm install @langchain/core
js 复制代码
import { ChatOpenAI } from '@langchain/openai';
import 'dotenv/config'
import { HumanMessage, SystemMessage } from "@langchain/core/messages";

const model = new ChatOpenAI({
    modelName: process.env.MODEL_NAME,
    apiKey: process.env.API_KEY,
    configuration: {
        baseURL: process.env.BASE_URL,
    },
});

let messages = [
    new SystemMessage({
        content: "你是一个专业的程序员",
    }),
    new HumanMessage({
        content: "你是谁?",
    }),
]
const response = await model.invoke(messages);
console.log(response.content);
js 复制代码
new HumanMessage({
        content: "你是谁?",
    }),

只是一个最基础的信息输入,我们还可以传入更多更详细的信息,还可以传入图片,视频音频作为数据

这是一个图片地址:c-ssl.duitang.com/uploads/blo...

我们把这个图片地址传给大模型,让他描述这个图片

js 复制代码
let messages = [
    new HumanMessage({
        content: [
            { type: "text", text: "描述下这张图片的内容" },
            {
                type: "image",
                source_type: "url",
                url: "https://c-ssl.duitang.com/uploads/blog/202212/04/20221204173347_946b0.jpg"
            },
        ],
    }),
]
const response = await model.invoke(messages);
console.log(response.content);

实战演练

根据上面学习的langChain基础,开发一个可交互的命令行助手

js 复制代码
import { ChatOpenAI } from '@langchain/openai';
import 'dotenv/config'
import { HumanMessage, SystemMessage } from "@langchain/core/messages";
import readline from 'node:readline';

const model = new ChatOpenAI({
    modelName: process.env.MODEL_NAME,
    apiKey: process.env.API_KEY,
    configuration: {
        baseURL: process.env.BASE_URL,
    },
});

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

const messages = [
    new SystemMessage('你是一个有用的助手,可以帮助用户解答问题。')
];

async function chat() {
    console.log('\n=== AI 助手 ===');
    console.log('输入您的问题(输入 "exit" 退出):\n');

    while (true) {
        const userInput = await new Promise((resolve) => {
            rl.question('用户: ', resolve);
        });

        if (userInput.toLowerCase() === 'exit' || userInput.toLowerCase() === 'quit') {
            console.log('\n再见!');
            rl.close();
            break;
        }

        if (userInput.trim() === '') {
            continue;
        }

        messages.push(new HumanMessage(userInput));

        try {
            console.log('助手: ');
            let fullResponse = '';
            
            const stream = await model.stream(messages);
            
            for await (const chunk of stream) {
                const content = chunk.content || '';
                if (content) {
                    process.stdout.write(content);
                    fullResponse += content;
                }
            }
            
            console.log('\n');
            messages.push({ content: fullResponse, role: 'assistant' });
        } catch (error) {
            console.error(`\n错误: ${error.message}\n`);
        }
    }
}

chat().catch(console.error);

readline 是 Node.js 的 内置模块 ,用于从可读流(如标准输入)逐行读取数据。

  • process.stdin : 可以从键盘读取用户输入
  • process.stdout: 向终端显示提示符和输出

我们已经能让 AI "说话"了,但真正的 Agent 需要使用工具

相关推荐
AomanHao1 小时前
基于高德地图JS的旅游足迹,可嵌入个人博客中
前端
用户4099322502121 小时前
Vue3组件开发中如何兼顾复用性、可维护性与性能优化?
前端·vue.js·trae
千寻girling1 小时前
面试官 : “ 请问你实际开发中用过 函数柯理化 吗? 能讲一下吗 ?”
前端·javascript·面试
golang学习记1 小时前
Claude Opus 4.6 正式发布:Agent 时代的编程王者与长上下文革命
前端·人工智能·后端
钟智强2 小时前
QuestDB惊现认证绕过漏洞(CVSS 9.8),大量金融/物联网系统恐成【透明库】
后端
双向332 小时前
RAG实战解密:三步构建你的智能文档问答系统(附开源方案)
前端
树獭叔叔2 小时前
📉 大模型量化 (Quantization) 全维度解析:从哲学到算力
后端·aigc·openai
undefinedType2 小时前
Rails Active Job深度解析
后端
感性的程序员小王2 小时前
拒绝硬编码!利用 Java SPI 打造一个可插拔的代码解析器
java·后端