Learn
Langchain.js/15-nextjs-integration

与 Next.js 集成

Next.js 是构建 LLM 应用的天然搭档:用 API Route(服务端) 跑 Langchain,前端只拿结果。关键是把密钥永远留在服务端。

1. 项目结构与密钥

# .env.local(Next.js 默认不提交,且只在服务端可用)
OPENAI_API_KEY=sk-xxxxxxxx
// app/api/chat/route.ts
import { NextRequest, NextResponse } from "next/server";
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
 
export const runtime = "nodejs"; // 必须 nodejs,不能用 edge(部分包不兼容)
 
const chain = ChatPromptTemplate.fromTemplate("用一句话解释 {topic}")
  .pipe(new ChatOpenAI({ model: "gpt-4o-mini" }))
  .pipe(new StringOutputParser());
 
export async function POST(req: NextRequest) {
  const { topic } = await req.json();
  const answer = await chain.invoke({ topic });
  return NextResponse.json({ answer });
}
⚠️绝不在客户端 import 模型包

浏览器代码里出现 @langchain/openai 会打包进前端、泄露 Key。所有模型调用都放在 app/api/**/route.ts 等服务端文件。前端只 fetch('/api/chat')。

2. 复用单例,避免冷启动重复初始化

// lib/chain.ts
import "server-only"; // 防止被误 import 到客户端
import { ChatOpenAI } from "@langchain/openai";
 
let cached: ChatOpenAI | null = null;
export function getModel() {
  if (!cached) cached = new ChatOpenAI({ model: "gpt-4o-mini" });
  return cached;
}
ℹ️server-only 包

npm i server-only 后,任何客户端组件 import 该模块都会直接构建报错,是一道安全防线。

3. 前端调用

// app/page.tsx(客户端组件)
async function ask(topic: string) {
  const res = await fetch("/api/chat", {
    method: "POST",
    body: JSON.stringify({ topic }),
  });
  const { answer } = await res.json();
  console.log(answer);
}

4. 部署注意

项建议
运行时export const runtime = "nodejs"
超时长链设 export const maxDuration = 60(Vercel 付费才更长)
并发模型调用走流式(下章),避免请求堆积
密钥用平台环境变量,勿提交 .env.local
💡用流式提升体验

同步等待完整回复会让用户盯着转圈。第 16 章讲如何用 .stream() 把字一个个推到前端。

🎯练习

新建一个 Next.js App Router 项目,写 /api/summary 接口,接收 { text } 返回摘要;前端放一个 textarea 调用它。

小结

  • 模型调用只放在 API Route(服务端),密钥永不进前端
  • 用 runtime = "nodejs" 与 server-only 加固安全边界
  • 复用模型/链单例,减少冷启动开销
  • 前端只 fetch 接口拿结果
  • 下章实现流式逐字输出 →