第 2 章:AI 应用的基本结构:模型、提示词、工具、记忆、知识库
本章目标
这一章先不急着写页面。我们要先拆清楚一个 AI 应用由哪些部分组成。只有理解这些模块,后面写 Chat、Agent 和 RAG 才不会混乱。
一个 AI 应用的核心链路
最小的 AI 应用只有三步:
用户输入 -> 模型生成 -> 返回答案
但真实应用通常会变成:
用户输入
-> 构造 Prompt
-> 读取会话记忆
-> 检索知识库
-> 决定是否调用工具
-> 模型生成
-> 流式返回
-> 记录日志和成本
这就是本小册要逐步搭起来的结构。
模型
模型是 AI 应用的推理核心。它负责理解输入、生成文本、决定是否调用工具、输出结构化结果。
在 LangChain.js 中,你可以用统一接口初始化模型:
import { initChatModel } from "langchain";
const model = await initChatModel("openai:gpt-5.4", {
temperature: 0.2,
maxTokens: 1000
});
写作时不要绑定死某一个供应商。更好的方式是把模型配置抽出来:
export async function createModel() {
return initChatModel(process.env.CHAT_MODEL ?? "openai:gpt-5.4", {
temperature: 0.2,
timeout: 30000,
maxRetries: 3
});
}
这样读者可以替换成 OpenRouter、Gemini、Anthropic 或兼容 OpenAI API 的模型服务。
Prompt
Prompt 不是“随便写一句提示词”。在应用里,它更像一份运行时协议。
一个知识库助手的系统提示词可以这样设计:
你是企业知识库助手。
你必须优先基于提供的资料回答。
如果资料不足,要明确说明“不确定”。
回答要简洁,并在末尾列出引用来源。
不要编造不存在的制度、链接或数据。
Prompt 的重点不是华丽,而是边界清楚、可测试、可迭代。
工具
工具是模型可以调用的函数。比如:
- 查询订单
- 查询天气
- 计算价格
- 检索数据库
- 读取知识库
- 创建工单
工具调用让模型不只会“说”,还可以“做”。
import { tool } from "langchain";
import * as z from "zod";
export const calculateDiscount = tool(
({ price, rate }) => {
return String(price * rate);
},
{
name: "calculate_discount",
description: "根据原价和折扣率计算折后价格",
schema: z.object({
price: z.number().describe("商品原价"),
rate: z.number().describe("折扣率,例如 0.8 表示八折")
})
}
);
记忆
记忆用来处理多轮对话。
如果没有记忆,用户第二轮说“那它怎么申请”,模型并不知道“它”指什么。
记忆可以分成两类:
- 短期记忆:当前会话里的消息历史
- 长期记忆:跨会话保存的用户偏好、业务资料、历史记录
本小册会先使用短期记忆完成多轮对话,再讨论长期记忆的边界。
知识库
知识库解决的是模型“不知道你的私有资料”的问题。
RAG 的基本流程是:
文档 -> 切分 -> Embedding -> 向量库
用户问题 -> Embedding -> 相似度检索 -> 上下文 -> 模型回答
RAG 不是让模型记住所有文档,而是在回答前把相关片段找出来,塞进上下文。
实战任务
画出本项目的第一版架构:
Next.js 页面
-> /api/chat
-> LangChain model
-> tools
-> retriever
-> streaming response
-> 前端渲染消息、引用、工具状态
后续每一章都会补齐其中一个模块。
常见坑
不要一开始就追求复杂 Agent。先做稳定的模型调用,再做流式输出,再接工具,最后接 RAG。
不要把所有上下文都塞进 Prompt。上下文太长会增加成本,也会降低模型注意力。
不要把记忆和知识库混为一谈。记忆偏会话状态,知识库偏可检索资料。
本章小结
AI 应用不是单次模型调用,而是模型、Prompt、工具、记忆、知识库、日志和前端体验共同组成的系统。理解这个结构后,后面的代码会更清楚。