像搭积木一样串联 AI 能力,构建智能化工作流!
为什么需要 Chain 链式调用?
在实际 AI 应用开发中,单个模型调用往往无法完成复杂任务。比如,要实现一个"代码审查助手",可能需要:
- 分析代码质量
- 识别潜在 Bug
- 给出优化建议
- 生成修复代码
如果每次都要手动处理中间结果并调用多次 API,代码会变得臃肿且难以维护。**Chain(链)**正是为了解决这个问题而生的。
Chain 的核心价值
| 价值点 | 说明 |
|---|---|
| 任务解耦 | 将复杂任务拆分为多个独立步骤,各司其职 |
| 代码复用 | 一个 Chain 可以在不同场景重复使用 |
| 流程可视化 | 调用逻辑清晰,易于理解和调试 |
| 错误隔离 | 单步失败不影响其他步骤(可配置) |
Chain 核心原理
什么是 Chain?
Chain 是 LangChain 中最核心的抽象概念之一。简单来说,Chain 将一个或多个组件(模型、提示词模板、其他 Chain 等)串联起来,形成端到端的处理流程。
输入 → [组件A] → 中间结果 → [组件B] → 中间结果 → [组件C] → 输出
Chain 的工作原理
- 输入接收:Chain 接收一个对象(包含所有需要的参数)
- 组件执行:按顺序调用内部组件(模型、提示词模板等)
- 结果传递:上一步的输出作为下一步的输入(通过变量名匹配)
- 最终输出:返回处理完成的结果
变量传递机制
这是 Chain 最容易踩坑的地方:Chain 中的变量传递是通过变量名自动匹配的。
// Chain A 输出:{ output: "hello" }
// Chain B 需要:{ text: "hello" }
// ❌ 变量名不匹配,传递失败
// 解决方案:使用变量映射或统一命名
常用基础 Chain 类型详解
1. LLMChain - 最基础的链
LLMChain 是最简单的 Chain,将一个 PromptTemplate 和一个 ChatModel 组合在一起。
import { LLMChain } from "langchain/chains";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";
const prompt = ChatPromptTemplate.fromMessages([
["system", "你是一个{role},回答要{style}"],
["human", "{question}"]
]);
const model = new ChatOpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
configuration: {
baseURL: process.env.DASHSCOPE_API_URL,
},
model: "qwen-plus",
temperature: 0.7,
});
const chain = new LLMChain({
llm: model,
prompt: prompt,
outputKey: "answer" // 输出结果的 key
});
// 调用
const result = await chain.call({
role: "前端技术专家",
style: "通俗易懂",
question: "什么是闭包?"
});
console.log(result.answer);
2. RunnableSequence - 替代 LLMChain
使用 RunnableSequence 配合 pipe 方法,代码更简洁、更灵活。
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";
import { RunnableSequence } from "@langchain/core/runnables";
import { StringOutputParser } from "@langchain/core/output_parsers";
import dotenv from "dotenv";
dotenv.config();
const prompt = ChatPromptTemplate.fromMessages([
["system", "你是一个{role},回答要{style}"],
["human", "{question}"]
]);
const model = new ChatOpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
configuration: {
baseURL: process.env.DASHSCOPE_API_URL,
},
model: "qwen-plus",
temperature: 0.7,
});
// 使用 pipe 方法构建链
const chain = RunnableSequence.from([
prompt,
model,
new StringOutputParser() // 将 AIMessage 转换为字符串
]);
// 调用
const result = await chain.invoke({
role: "前端技术专家",
style: "通俗易懂",
question: "什么是闭包?"
});
console.log(result);
// 输出:闭包(Closure)是 JavaScript 中一个非常经典又容易让人困惑的概念...
更简洁的写法(使用 .pipe())
// .pipe() 方法更加直观
const chain = prompt
.pipe(model)
.pipe(new StringOutputParser());
const result = await chain.invoke({
role: "前端技术专家",
style: "通俗易懂",
question: "什么是闭包?"
});
3. 简单顺序链
当多个链首尾相连,前一个的输出直接作为后一个的输入时,使用 RunnableSequence 连接多个 Runnable。
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";
import { RunnableSequence } from "@langchain/core/runnables";
import { StringOutputParser } from "@langchain/core/output_parsers";
import dotenv from "dotenv";
dotenv.config();
const prompt = ChatPromptTemplate.fromMessages([
["system", "你是一个{role},回答要{style}"],
["human", "{question}"]
]);
const model = new ChatOpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
configuration: {
baseURL: process.env.DASHSCOPE_API_URL,
},
model: "qwen-plus",
temperature: 0.7,
});
// Chain 1:生成问题
const prompt1 = ChatPromptTemplate.fromTemplate(
"请为'{topic}'生成一个面试题,难度{level}"
);
const chain1 = prompt1
.pipe(model)
.pipe(new StringOutputParser());
// Chain 2:回答问题
const prompt2 = ChatPromptTemplate.fromTemplate(
"请回答以下面试题,并提供参考答案:\n{text}"
);
const chain2 = prompt2
.pipe(model)
.pipe(new StringOutputParser());
// 组合成顺序链
const overallChain = RunnableSequence.from([
{
topic: (input: { topic: string; level: string }) => input.topic,
level: (input: { topic: string; level: string }) => input.level
},
chain1,
(generatedQuestion) => ({ text: generatedQuestion }),
chain2
]);
// 或者更清晰的写法
const overallChain2 = RunnableSequence.from([
(input: { topic: string; level: string }) =>
chain1.invoke(input), // 第一步:生成问题
(question) => chain2.invoke({ text: question }) // 第二步:回答问题
]);
const result = await overallChain2.invoke({
topic: "JavaScript 闭包",
level: "中等"
});
console.log(result);
简化版:使用 .pipe() 连接
// 如果需要中间处理,可以自定义转换函数
const pipeline = chain1.pipe(async (question) => {
console.log(`生成的问题:${question}`);
return { text: question };
}).pipe(chain2);
const result = await pipeline.invoke({
topic: "JavaScript 闭包",
level: "中等"
});
4. 复杂顺序链
当需要更复杂的变量传递(多个输入、多个输出)时,使用 RunnableLambda 或自定义函数来处理数据流。
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";
import { RunnableSequence } from "@langchain/core/runnables";
import { StringOutputParser } from "@langchain/core/output_parsers";
import dotenv from "dotenv";
dotenv.config();
const prompt = ChatPromptTemplate.fromMessages([
["system", "你是一个{role},回答要{style}"],
["human", "{question}"]
]);
const model = new ChatOpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
configuration: {
baseURL: process.env.DASHSCOPE_API_URL,
},
model: "qwen-plus",
temperature: 0.7,
});
// Chain 1:分析代码复杂度
const complexityPrompt = ChatPromptTemplate.fromTemplate(`
分析以下代码的复杂度:
\`\`\`
{code}
\`\`\`
输出格式:【复杂度评级:简单/中等/复杂】【建议:xxx】
`);
const complexityChain = complexityPrompt
.pipe(model)
.pipe(new StringOutputParser());
// Chain 2:生成优化建议
const optimizePrompt = ChatPromptTemplate.fromTemplate(`
根据以下代码和复杂度分析,给出具体的优化建议:
【代码】
{code}
【复杂度分析】
{complexityAnalysis}
输出格式:【优化方向】【具体方案】【预期效果】
`);
const optimizeChain = optimizePrompt
.pipe(model)
.pipe(new StringOutputParser());
// 组合成复杂顺序链(支持多变量传递)
const codeReviewChain = RunnableSequence.from([
// 第一步:并行处理?或者顺序处理
async (input: { code: string }) => {
const complexityAnalysis = await complexityChain.invoke({
code: input.code
});
return {
code: input.code,
complexityAnalysis
};
},
// 第二步:生成优化建议
async (state) => {
const suggestions = await optimizeChain.invoke({
code: state.code,
complexityAnalysis: state.complexityAnalysis
});
return {
complexityAnalysis: state.complexityAnalysis,
optimizationSuggestions: suggestions
};
}
]);
// 使用
const result = await codeReviewChain.invoke({
code: `function add(a, b) { return a + b; }`
});
console.log(result.complexityAnalysis);
console.log(result.optimizationSuggestions);
更优雅的实现:使用 RunnablePassthrough 保持状态
import { RunnablePassthrough, RunnableSequence } from "@langchain/core/runnables";
const codeReviewChain2 = RunnableSequence.from([
// 第一步:分析复杂度,同时保留原始代码
{
code: new RunnablePassthrough(), // 传递原始输入
complexityAnalysis: complexityChain
},
// 第二步:使用上一步的结果生成优化建议
{
complexityAnalysis: ({ complexityAnalysis }) => complexityAnalysis,
code: ({ code }) => code,
optimizationSuggestions: optimizeChain
}
]);
const result2 = await codeReviewChain2.invoke({
code: `function add(a, b) { return a + b; }`
});
5. 高级用法:条件分支和并行执行
并行执行多个任务
// 同时分析代码的多个维度
const analyzeCode = RunnableSequence.from([
{
code: new RunnablePassthrough(),
quality: qualityChain, // 质量分析
performance: performanceChain, // 性能分析
security: securityChain // 安全分析
},
async (results) => {
// 汇总所有分析结果
return {
summary: `质量:${results.quality}\n性能:${results.performance}\n安全:${results.security}`,
details: results
};
}
]);
条件分支执行
import { RunnableBranch } from "@langchain/core/runnables";
// 根据代码复杂度决定执行不同的优化策略
const conditionalChain = new RunnableBranch([
// 条件1:如果代码复杂,使用深度优化
(input) => input.complexity === "复杂",
deepOptimizationChain,
// 条件2:如果代码中等,使用标准优化
(input) => input.complexity === "中等",
standardOptimizationChain,
// 默认:简单优化
simpleOptimizationChain
]);
前端业务场景 Chain 应用案例
场景:智能表单处理助手
实现功能:用户输入自然语言描述 → 解析需求 → 生成验证规则 → 输出前端代码
创建 src/form-assistant.ts:
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";
import { RunnableSequence } from "@langchain/core/runnables";
import { StringOutputParser } from "@langchain/core/output_parsers";
import dotenv from "dotenv";
dotenv.config();
async function formAssistant() {
const model = new ChatOpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
configuration: {
baseURL: process.env.DASHSCOPE_API_URL
},
model: "qwen-turbo",
temperature: 0.3,
});
// ========== Chain 1:解析需求,提取字段信息 ==========
const parsePrompt = ChatPromptTemplate.fromMessages([
["system", `你是一个表单需求分析专家。从用户的自然语言描述中,提取需要收集的字段信息。
输出格式必须为 JSON 数组,每个字段包含:
- name: 字段名(英文)
- label: 显示标签(中文)
- type: 类型(text/email/tel/number/select/checkbox/radio)
- required: 是否必填(true/false)
- options: 如果是 select,给出选项数组
- placeholder: 提示文本(可选)
只输出 JSON 数组,不要其他解释。`],
["human", "{requirement}"]
]);
const parseChain = parsePrompt
.pipe(model)
.pipe(new StringOutputParser());
// ========== Chain 2:生成校验规则 ==========
const validatePrompt = ChatPromptTemplate.fromMessages([
["system", `你是表单校验规则生成专家。根据字段定义,为每个字段生成前端校验规则。
输出格式为 JSON 对象,字段名作为 key,规则数组作为 value。
示例:{{"email": [{"type": "email", "message": "请输入正确的邮箱"}, {"required": true, "message": "邮箱不能为空"}]}}
只输出 JSON 对象,不要其他解释。`],
["human", "字段定义:{fieldsJson}"]
]);
const validateChain = validatePrompt
.pipe(model)
.pipe(new StringOutputParser());
// ========== Chain 3:生成前端代码 ==========
const codePrompt = ChatPromptTemplate.fromMessages([
["system", `你是前端代码生成专家。根据字段定义和校验规则,生成 Vue3 + Element Plus 的表单代码。
要求:
- 使用 reactive 管理表单数据
- 完整的校验逻辑
- 提交时的数据格式
- 代码要有注释
- 使用 TypeScript
只输出完整的 Vue 组件代码。`],
["human", `字段定义:{fieldsJson}
校验规则:{validationRules}
用户需求:{requirement}`]
]);
const codeChain = codePrompt
.pipe(model)
.pipe(new StringOutputParser());
// ========== 组合成完整 Chain(使用 RunnableSequence) ==========
const formBuilderChain = RunnableSequence.from([
// 第一步:解析需求,提取字段
async (input) => {
const fieldsJson = await parseChain.invoke({ requirement: input.requirement });
return {
requirement: input.requirement,
fieldsJson
};
},
// 第二步:生成校验规则
async (state) => {
const validationRules = await validateChain.invoke({ fieldsJson: state.fieldsJson });
return {
requirement: state.requirement,
fieldsJson: state.fieldsJson,
validationRules
};
},
// 第三步:生成代码
async (state) => {
const generatedCode = await codeChain.invoke({
fieldsJson: state.fieldsJson,
validationRules: state.validationRules,
requirement: state.requirement
});
return {
fieldsJson: state.fieldsJson,
validationRules: state.validationRules,
generatedCode
};
}
]);
// ========== 执行测试 ==========
const requirement = `
我需要一个用户注册表单,包含以下字段:
- 用户名:必填,3-20个字符
- 邮箱:必填,需要是有效的邮箱格式
- 手机号:选填,11位数字
- 性别:下拉选择(男/女/保密)
- 年龄:数字,18-60岁
`;
console.log("📝 用户需求:\n", requirement);
console.log("\n🔄 开始链式处理...\n");
try {
const result = await formBuilderChain.invoke({ requirement });
console.log("\n📋 提取的字段定义:\n", result.fieldsJson);
console.log("\n🔒 生成的校验规则:\n", result.validationRules);
console.log("\n💻 生成的代码:\n", result.generatedCode);
} catch (error) {
console.error("处理出错:", error);
}
}
formAssistant();
完整 TS 代码实现 - 代码审查流水线
创建 src/code-review-pipeline.ts:
import { PromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";
import dotenv from "dotenv";
dotenv.config();
class CodeReviewPipeline {
private model: ChatOpenAI;
constructor() {
this.model = new ChatOpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
configuration: {
baseURL: process.env.DASHSCOPE_API_URL,
},
model: "qwen-turbo",
temperature: 0.2,
});
}
async review(code: string) {
// 并行执行前三个分析
const [qualityAnalysis, performanceIssues, securityIssues] = await Promise.all([
this.analyzeQuality(code),
this.analyzePerformance(code),
this.analyzeSecurity(code)
]);
// 最后生成优化代码
const optimizedCode = await this.generateOptimizedCode(
code,
qualityAnalysis,
performanceIssues,
securityIssues
);
return {
qualityAnalysis,
performanceIssues,
securityIssues,
optimizedCode
};
}
private async analyzeQuality(code: string): Promise<string> {
const prompt = PromptTemplate.fromTemplate(`
请分析以下 TypeScript 代码的质量问题:
\`\`\`typescript
{code}
\`\`\`
分析维度:
1. 命名规范(变量/函数/类名是否清晰)
2. 代码复杂度(是否过于复杂)
3. 类型安全(是否正确使用 TypeScript)
4. 错误处理(是否有遗漏的异常处理)
输出格式:【维度】【问题】【建议】
`);
const chain = prompt.pipe(this.model);
const response = await chain.invoke({ code });
return response.content as string;
}
private async analyzePerformance(code: string): Promise<string> {
const prompt = PromptTemplate.fromTemplate(`
分析以下代码的性能问题:
\`\`\`typescript
{code}
\`\`\`
重点关注:
- 循环嵌套
- 不必要的重渲染
- 内存泄漏风险
- 异步操作
如果无性能问题,输出"无性能问题"。
`);
const chain = prompt.pipe(this.model);
const response = await chain.invoke({ code });
return response.content as string;
}
private async analyzeSecurity(code: string): Promise<string> {
const prompt = PromptTemplate.fromTemplate(`
检查以下代码是否存在安全风险:
\`\`\`typescript
{code}
\`\`\`
检查项:
- XSS 风险
- SQL 注入(如涉及数据库)
- 敏感信息泄露
- 输入验证
输出格式:【风险等级:高/中/低/无】【具体说明】
`);
const chain = prompt.pipe(this.model);
const response = await chain.invoke({ code });
return response.content as string;
}
private async generateOptimizedCode(
code: string,
qualityAnalysis: string,
performanceIssues: string,
securityIssues: string
): Promise<string> {
const prompt = PromptTemplate.fromTemplate(`
基于以下分析,请对代码进行优化:
【原始代码】
{code}
【质量分析】
{qualityAnalysis}
【性能问题】
{performanceIssues}
【安全问题】
{securityIssues}
请输出优化后的完整代码,并标注主要修改点。
`);
const chain = prompt.pipe(this.model);
const response = await chain.invoke({
code,
qualityAnalysis,
performanceIssues,
securityIssues
});
return response.content as string;
}
}
async function codeReviewPipeline() {
const pipeline = new CodeReviewPipeline();
const testCode = `
function getUserData(id) {
const data = fetch('/api/user/' + id);
return data;
}
// 组件代码
function UserList({ users }) {
const [list, setList] = useState([]);
useEffect(() => {
setList(users);
}, []);
return (
<div>
{list.map(user => (
<div>{user.name}</div>
))}
</div>
);
}
`;
console.log("🔍 开始代码审查...\n");
console.log("📄 原始代码:\n", testCode);
console.log("\n" + "=".repeat(60) + "\n");
const result = await pipeline.review(testCode);
console.log("📊 代码质量分析:\n", result.qualityAnalysis);
console.log("\n⚡ 性能问题:\n", result.performanceIssues);
console.log("\n🔒 安全问题:\n", result.securityIssues);
console.log("\n✨ 优化后的代码:\n", result.optimizedCode);
}
codeReviewPipeline();
链式调用常见问题排查
问题 1:变量名不匹配导致数据传递失败
现象:Chain 执行成功,但后续步骤收不到预期数据
解决:检查数据流中的字段名是否一致
// ❌ 错误示例:字段名不匹配
const step1 = RunnableSequence.from([
(input) => {
const result = { data: "分析结果" };
return { analysis: result }; // 返回 { analysis: ... }
},
(state) => {
// 但这里期望接收 { result: ... }
console.log(state.result); // undefined
return state;
}
]);
// ✅ 正确示例:保持字段名一致
const step1 = RunnableSequence.from([
(input) => {
const analysis = "分析结果";
return { analysis }; // 返回 { analysis }
},
(state) => {
console.log(state.analysis); // ✅ 正确获取
return { suggestion: `基于${state.analysis}的建议` };
}
]);
// 更好的方式:使用 RunnablePassthrough 保持状态
import { RunnablePassthrough } from "@langchain/core/runnables";
const pipeline = RunnableSequence.from([
{
analysis: analysisChain, // 分析结果
original: new RunnablePassthrough() // 保留原始输入
},
{
suggestion: suggestionChain, // 生成建议
analysis: ({ analysis }) => analysis // 传递分析结果
}
]);
问题 2:数据流中的参数传递错误
现象:需要传递多个参数,但链式调用中数据丢失
解决:使用 RunnablePassthrough 或自定义转换函数
// ❌ 错误:参数会被覆盖
const wrongChain = RunnableSequence.from([
step1, // 返回 { result1 }
step2, // 返回 { result2 },丢失了 result1
]);
// ✅ 正确:逐步累积数据
const correctChain = RunnableSequence.from([
async (input) => {
const result1 = await step1.invoke(input);
return { ...input, ...result1 }; // 合并结果
},
async (state) => {
const result2 = await step2.invoke(state);
return { ...state, ...result2 }; // 继续累积
}
]);
// ✅ 更好:使用 RunnablePassthrough
const betterChain = RunnableSequence.from([
{
original: new RunnablePassthrough(),
result1: step1
},
{
original: ({ original }) => original,
result1: ({ result1 }) => result1,
result2: step2
}
]);
问题 3:链式调用超时或卡顿
现象:多个步骤串行执行,总耗时过长
解决:
- 添加日志监控定位耗时步骤
- 将独立步骤并行化
- 选择更快的模型
import { RunnableSequence } from "@langchain/core/runnables";
// 添加性能监控的包装器
function withTiming<T extends RunnableSequence>(chain: T, name: string) {
return RunnableSequence.from([
async (input) => {
console.log(`⏱️ [${name}] 开始执行...`);
const start = Date.now();
const result = await chain.invoke(input);
const duration = Date.now() - start;
console.log(`✅ [${name}] 完成,耗时 ${duration}ms`);
return result;
}
]);
}
// 使用监控
const monitoredChain = withTiming(analysisChain, "代码分析");
// 独立步骤并行执行
const parallelChain = RunnableSequence.from([
async (input) => {
// 并行执行独立的分析任务
const [analysis1, analysis2, analysis3] = await Promise.all([
qualityChain.invoke(input),
performanceChain.invoke(input),
securityChain.invoke(input)
]);
return {
...input,
quality: analysis1,
performance: analysis2,
security: analysis3
};
},
// 汇总结果
async (state) => {
const summary = await summaryChain.invoke({
quality: state.quality,
performance: state.performance,
security: state.security
});
return { ...state, summary };
}
]);
问题 4:中间步骤输出格式问题
现象:后续 Chain 解析前一步输出时失败
解决:强制规定输出格式,添加格式校验和解析器
import { StringOutputParser } from "@langchain/core/output_parsers";
import { StructuredOutputParser } from "@langchain/core/output_parsers";
// 方式1:使用结构化输出解析器
const outputParser = StructuredOutputParser.fromZodSchema(
z.object({
status: z.enum(["success", "error"]),
data: z.string(),
error: z.string().nullable()
})
);
const chain = prompt
.pipe(model)
.pipe(outputParser); // 自动解析为 JSON 对象
// 方式2:手动添加格式校验
const chainWithValidation = RunnableSequence.from([
prompt,
model,
new StringOutputParser(),
async (output) => {
// 验证输出格式
try {
const parsed = JSON.parse(output);
if (!parsed.status || !parsed.data) {
throw new Error("缺少必要字段");
}
return parsed;
} catch (error) {
console.error("格式解析失败:", output);
// 返回默认格式或重试
return {
status: "error",
data: output,
error: "格式不正确"
};
}
}
]);
// 方式3:在 Prompt 中强制格式要求
const promptWithFormat = ChatPromptTemplate.fromMessages([
["system", `你是一个数据分析专家。
任务:{task}
重要:请严格按照以下 JSON 格式输出,不要添加任何其他内容:
{
"status": "success/error",
"data": "...",
"error": null
}
如果处理失败,status 设为 "error" 并填写 error 字段。`],
["human", "内容:{content}"]
]);
Chain 复用技巧(RunnableSequence 版本)
1. 封装可复用的 Chain 工厂
import { RunnableSequence } from "@langchain/core/runnables";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
// 创建可复用的分析 Chain
function createAnalysisChain(analysisType: string, model: ChatOpenAI) {
const prompt = ChatPromptTemplate.fromTemplate(`
你是一个{analysisType}分析专家。
请分析以下内容:{content}
输出格式:【分析结果】【关键发现】【建议】
`);
return prompt
.pipe(model)
.pipe(new StringOutputParser());
}
// 使用
const codeAnalysis = createAnalysisChain("代码", model);
const textAnalysis = createAnalysisChain("文本", model);
const codeResult = await codeAnalysis.invoke({
analysisType: "代码",
content: "function add(a,b){return a+b}"
});
2. 创建可配置的 Chain 工厂
interface ChainConfig {
temperature: number;
maxTokens?: number;
modelName?: string;
}
function createCustomChain(
template: string,
config: ChainConfig
) {
const prompt = ChatPromptTemplate.fromTemplate(template);
const model = new ChatOpenAI({
apiKey: process.env.BAILIAN_API_KEY,
configuration: {
baseURL: process.env.BAILIAN_BASE_URL
},
model: config.modelName || "qwen-turbo",
temperature: config.temperature,
maxTokens: config.maxTokens,
});
return prompt
.pipe(model)
.pipe(new StringOutputParser());
}
// 使用
const strictChain = createCustomChain(
"分析:{input}",
{ temperature: 0.1, maxTokens: 500 }
);
const creativeChain = createCustomChain(
"创作:{input}",
{ temperature: 0.9, modelName: "qwen-plus" }
);
3. 封装带缓存的 Chain
interface CacheEntry {
output: string;
timestamp: number;
}
class CachedChain {
private cache = new Map<string, CacheEntry>();
private ttl: number;
constructor(
private chain: RunnableSequence,
ttlSeconds: number = 300
) {
this.ttl = ttlSeconds * 1000;
}
async invoke(input: any) {
const key = JSON.stringify(input);
const cached = this.cache.get(key);
if (cached && Date.now() - cached.timestamp < this.ttl) {
console.log("✅ 命中缓存");
return cached.output;
}
console.log("🔄 执行 Chain...");
const result = await this.chain.invoke(input);
this.cache.set(key, {
output: result,
timestamp: Date.now()
});
return result;
}
// 清空缓存
clearCache() {
this.cache.clear();
}
// 获取缓存统计
getCacheStats() {
return {
size: this.cache.size,
keys: Array.from(this.cache.keys())
};
}
}
// 使用示例
const analysisChain = createAnalysisChain("代码", model);
const cachedChain = new CachedChain(analysisChain, 600); // 缓存10分钟
// 第一次调用 - 执行 Chain
const result1 = await cachedChain.invoke({ content: "代码内容" });
// 第二次调用相同输入 - 命中缓存
const result2 = await cachedChain.invoke({ content: "代码内容" });
4. 创建可组合的 Chain 构建器
class ChainBuilder {
private steps: Array<(input: any) => Promise<any>> = [];
private model: ChatOpenAI;
constructor(model: ChatOpenAI) {
this.model = model;
}
// 添加 LLM 步骤
addLLMStep(promptTemplate: string, outputKey: string) {
const prompt = ChatPromptTemplate.fromTemplate(promptTemplate);
const chain = prompt
.pipe(this.model)
.pipe(new StringOutputParser());
this.steps.push(async (input) => {
const result = await chain.invoke(input);
return { ...input, [outputKey]: result };
});
return this;
}
// 添加自定义处理步骤
addTransformStep(transform: (input: any) => any) {
this.steps.push(async (input) => {
const result = await transform(input);
return { ...input, ...result };
});
return this;
}
// 添加并行步骤
addParallelStep(steps: Record<string, RunnableSequence>) {
this.steps.push(async (input) => {
const results = await Promise.all(
Object.entries(steps).map(async ([key, chain]) => {
const result = await chain.invoke(input);
return [key, result];
})
);
return {
...input,
...Object.fromEntries(results)
};
});
return this;
}
// 构建最终的 Chain
build() {
return RunnableSequence.from(this.steps);
}
}
// 使用示例
const builder = new ChainBuilder(model);
const pipeline = builder
.addLLMStep("分析代码:{code}", "analysis")
.addParallelStep({
quality: qualityChain,
performance: performanceChain
})
.addTransformStep((state) => ({
...state,
summary: `${state.analysis}\n质量:${state.quality}`
}))
.build();
const result = await pipeline.invoke({ code: "function test() {}" });
5. 创建可重用的 Chain 模板
// 定义通用的 Chain 类型
type ChainInput = Record<string, any>;
type ChainOutput = Record<string, any>;
class ReusableChain {
private chain: RunnableSequence;
constructor(
name: string,
buildChain: () => RunnableSequence
) {
console.log(`🔧 构建 Chain: ${name}`);
this.chain = buildChain();
}
async execute(input: ChainInput): Promise<ChainOutput> {
try {
console.log(`🚀 执行 Chain...`);
const result = await this.chain.invoke(input);
return { success: true, data: result };
} catch (error) {
console.error(`❌ Chain 执行失败:`, error);
return { success: false, error: String(error) };
}
}
}
// 预定义的 Chain 模板
const ChainTemplates = {
// 代码审查模板
codeReview: (model: ChatOpenAI) => {
const prompt = ChatPromptTemplate.fromTemplate(`
审查以下代码:{code}
输出:问题列表和建议
`);
return prompt.pipe(model).pipe(new StringOutputParser());
},
// 文档生成模板
documentGeneration: (model: ChatOpenAI) => {
const prompt = ChatPromptTemplate.fromTemplate(`
为以下代码生成文档:{code}
输出:JSDoc 注释格式
`);
return prompt.pipe(model).pipe(new StringOutputParser());
},
// 测试生成模板
testGeneration: (model: ChatOpenAI) => {
const prompt = ChatPromptTemplate.fromTemplate(`
为以下函数生成单元测试:{function}
输出:Jest 测试代码
`);
return prompt.pipe(model).pipe(new StringOutputParser());
}
};
// 使用模板
const reviewChain = new ReusableChain(
"代码审查",
() => ChainTemplates.codeReview(model)
);
const result = await reviewChain.execute({ code: "function add(a,b){return a+b}" });
结语
通过这篇教程,我们学习了 LangChain 中 Chain 的核心概念和使用方法。Chain 是构建复杂 AI 应用的基石,掌握它就能像搭积木一样灵活组合各种 AI 能力。
对于文章中错误的地方或有任何疑问,欢迎在评论区留言讨论!