草案 "智能体设计模式 - 提示链"
ailangchainlangraphnextjsprompt-engineeringagents
By sko X opus 4.1•9/20/2025•16 min read
构建生产级的顺序AI工作流,将复杂任务分解为可管理的步骤,在专业化提示之间传递输出,以在Next.js应用程序中实现复杂的推理和处理能力。
心智模型:AI的流水线
将提示链想象成特斯拉工厂中的现代流水线。每个工位(提示)执行特定的操作——一个安装轮子,另一个喷漆,第三个检查质量。每个工位的输出成为下一个工位的输入,创造出精致的最终产品。在AI术语中,不是制造汽车,而是提炼信息:首先提取数据,然后分析它,再格式化它,最后验证它。正如流水线彻底改变了制造效率,提示链通过将复杂的AI任务分解为可以独立优化的专业化、可管理的操作,革命性地改变了我们处理复杂AI任务的方式。
基础顺序链实现
1. 简单文本处理链
// lib/chains/basic-chain.ts
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
import { PromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';
import { RunnableSequence } from '@langchain/core/runnables';
export function createBasicChain() {
const model = new ChatGoogleGenerativeAI({
modelName: 'gemini-2.5-flash',
temperature: 0,
maxRetries: 3,
});
// 步骤1:总结输入
const summarizePrompt = PromptTemplate.fromTemplate(
`将以下文本总结为2-3句话:
{text}`
);
// 步骤2:提取关键点
const extractPrompt = PromptTemplate.fromTemplate(
`从这个总结中提取3-5个关键点:
{summary}`
);
// 步骤3:生成行动项
const actionPrompt = PromptTemplate.fromTemplate(
`基于这些关键点,生成可行的建议:
{keyPoints}`
);
// 使用LCEL构建链
const chain = RunnableSequence.from([
// 第一步:总结
summarizePrompt,
model,
new StringOutputParser(),
// 传递到下一步
(summary) => ({ summary }),
extractPrompt,
model,
new StringOutputParser(),
// 传递到最后一步
(keyPoints) => ({ keyPoints }),
actionPrompt,
model,
new StringOutputParser(),
]);
return chain;
}
创建一个三步链,将文本从原始输入逐步精炼为可行的建议。
2. 带流式传输的API路由
// app/api/basic-chain/route.ts
import { createBasicChain } from '@/lib/chains/basic-chain';
import { NextResponse } from 'next/server';
export const runtime = 'nodejs';
export const maxDuration = 60;
export async function POST(req: Request) {
try {
const { text } = await req.json();
if (!text || text.length < 50) {
return NextResponse.json(
{ error: '请提供至少50个字符的文本' },
{ status: 400 }
);
}
const chain = createBasicChain();
const result = await chain.invoke({ text });
return NextResponse.json({
success: true,
result,
timestamp: new Date().toISOString(),
});
} catch (error) {
console.error('链执行错误:', error);
return NextResponse.json(
{ error: '处理链失败' },
{ status: 500 }
);
}
}
处理链执行,具有适当的错误处理和用于无服务器部署的验证。
3. 使用TanStack Query的前端集成
// components/BasicChainInterface.tsx
'use client';
import { useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import { debounce } from 'es-toolkit';
interface ChainResponse {
success: boolean;
result: string;
timestamp: string;
}
export default function BasicChainInterface() {
const [text, setText] = useState('');
const [charCount, setCharCount] = useState(0);
const processChain = useMutation<ChainResponse, Error, string>({
mutationFn: async (inputText: string) => {
const response = await fetch('/api/basic-chain', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: inputText }),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || '链处理失败');
}
return response.json();
},
retry: 2,
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
});
const handleTextChange = debounce((value: string) => {
setCharCount(value.length);
}, 300);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (text.length >= 50) {
processChain.mutate(text);
}
};
return (
<div className="card w-full bg-base-100 shadow-xl">
<div className="card-body">
<h2 className="card-title">文本处理链</h2>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="form-control">
<label className="label">
<span className="label-text">输入文本</span>
<span className="label-text-alt">{charCount} 个字符</span>
</label>
<textarea
className="textarea textarea-bordered h-32"
placeholder="输入要处理的文本(最少50个字符)..."
value={text}
onChange={(e) => {
setText(e.target.value);
handleTextChange(e.target.value);
}}
disabled={processChain.isPending}
/>
</div>
<button
type="submit"
className="btn btn-primary"
disabled={processChain.isPending || text.length < 50}
>
{processChain.isPending ? (
<>
<span className="loading loading-spinner"></span>
处理链中...
</>
) : (
'处理文本'
)}
</button>
</form>
{processChain.isError && (
<div className="alert alert-error mt-4">
<span>{processChain.error.message}</span>
</div>
)}
{processChain.isSuccess && (
<div className="card bg-base-200 mt-4">
<div className="card-body">
<h3 className="font-semibold">结果:</h3>
<p className="whitespace-pre-wrap">{processChain.data.result}</p>
<p className="text-xs text-base-content/60 mt-2">
处理时间:{new Date(processChain.data.timestamp).toLocaleString()}
</p>
</div>
</div>
)}
</div>
</div>
);
}
使用TanStack Query具有防抖字符计数和全面错误处理的React组件。
高级多步链与状态管理
1. 使用LangGraph的文档分析链
// lib/chains/document-analyzer.ts
import { StateGraph, START, END, Annotation } from '@langchain/langgraph';
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
import { BaseMessage, HumanMessage, AIMessage } from '@langchain/core/messages';
import { z } from 'zod';
import { StructuredOutputParser } from '@langchain/core/output_parsers';
import { isNil, chunk } from 'es-toolkit';
// 使用Zod定义状态模式
const DocumentMetadata = z.object({
title: z.string(),
category: z.string(),
confidence: z.number().min(0).max(1),
keywords: z.array(z.string()),
});
// 定义图状态
const GraphState = Annotation.Root({
document: Annotation<string>(),
chunks: Annotation<string[]>(),
metadata: Annotation<z.infer<typeof DocumentMetadata>>(),
summary: Annotation<string>(),
insights: Annotation<string[]>(),
messages: Annotation<BaseMessage[]>({
reducer: (current, update) => current.concat(update),
default: () => [],
}),
});
export function createDocumentAnalyzer() {
const model = new ChatGoogleGenerativeAI({
modelName: 'gemini-2.5-pro',
temperature: 0.1,
maxRetries: 3,
});
const metadataParser = StructuredOutputParser.fromZodSchema(DocumentMetadata);
const workflow = new StateGraph(GraphState)
// 节点1:分块文档
.addNode('chunk_document', async (state) => {
const doc = state.document;
// 将文档分块为500字符段,重叠50个字符
const chunks = chunk(doc.split(' '), 100).map(words => words.join(' '));
return {
chunks,
messages: [new AIMessage(`文档已分块为${chunks.length}个段`)],
};
})
// 节点2:提取元数据
.addNode('extract_metadata', async (state) => {
const prompt = `分析这个文档并提取元数据。
文档:${state.chunks[0]}
${metadataParser.getFormatInstructions()}`;
const response = await model.invoke([new HumanMessage(prompt)]);
const metadata = await metadataParser.parse(response.content as string);
return {
metadata,
messages: [new AIMessage(`已提取元数据:${metadata.category}`)],
};
})
// 节点3:生成摘要
.addNode('generate_summary', async (state) => {
const combinedText = state.chunks.slice(0, 3).join('\n\n');
const prompt = `创建此文档的综合摘要。
类别:${state.metadata.category}
文档摘录:
${combinedText}`;
const response = await model.invoke([new HumanMessage(prompt)]);
return {
summary: response.content as string,
messages: [new AIMessage('已生成摘要')],
};
})
// 节点4:提取洞察
.addNode('extract_insights', async (state) => {
const prompt = `基于此摘要和元数据,提供3-5个关键洞察:
类别:${state.metadata.category}
关键词:${state.metadata.keywords.join(', ')}
摘要:${state.summary}`;
const response = await model.invoke([new HumanMessage(prompt)]);
const insights = (response.content as string)
.split('\n')
.filter(line => line.trim().length > 0);
return {
insights,
messages: [new AIMessage(`已提取${insights.length}个洞察`)],
};
})
// 定义边
.addEdge(START, 'chunk_document')
.addEdge('chunk_document', 'extract_metadata')
.addEdge('extract_metadata', 'generate_summary')
.addEdge('generate_summary', 'extract_insights')
.addEdge('extract_insights', END);
return workflow.compile();
}
实现具有元数据提取和洞察生成的有状态文档处理管道。
2. 文档分析的流式API路由
// app/api/analyze-document/route.ts
import { createDocumentAnalyzer } from '@/lib/chains/document-analyzer';
import { HumanMessage } from '@langchain/core/messages';
export const runtime = 'nodejs';
export const maxDuration = 120;
export async function POST(req: Request) {
const { document } = await req.json();
if (!document || document.length < 100) {
return new Response(
JSON.stringify({ error: '文档必须至少100个字符' }),
{ status: 400 }
);
}
const encoder = new TextEncoder();
const stream = new TransformStream();
const writer = stream.writable.getWriter();
const analyzer = createDocumentAnalyzer();
(async () => {
try {
const eventStream = await analyzer.stream({
document,
chunks: [],
metadata: null,
summary: '',
insights: [],
messages: [],
});
for await (const event of eventStream) {
const update = {
type: 'update',
node: Object.keys(event)[0],
data: event,
timestamp: new Date().toISOString(),
};
await writer.write(
encoder.encode(`data: ${JSON.stringify(update)}\n\n`)
);
}
await writer.write(
encoder.encode(`data: ${JSON.stringify({ type: 'complete' })}\n\n`)
);
} catch (error) {
await writer.write(
encoder.encode(`data: ${JSON.stringify({
type: 'error',
error: error instanceof Error ? error.message : '未知错误'
})}\n\n`)
);
} finally {
await writer.close();
}
})();
return new Response(stream.readable, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
},
});
}
使用服务器发送事件实时流式传输每个节点的执行结果。
3. 具有错误恢复的高级链
// lib/chains/resilient-chain.ts
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
import { RunnableSequence, RunnableWithFallbacks } from '@langchain/core/runnables';
import { PromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';
import { retry, delay } from 'es-toolkit';
import { kv } from '@vercel/kv';
interface ChainCache {
get: (key: string) => Promise<string | null>;
set: (key: string, value: string, ttl?: number) => Promise<void>;
}
class VercelKVCache implements ChainCache {
async get(key: string): Promise<string | null> {
try {
return await kv.get(key);
} catch {
return null;
}
}
async set(key: string, value: string, ttl = 3600): Promise<void> {
try {
await kv.set(key, value, { ex: ttl });
} catch {
// 静默处理缓存写入失败
}
}
}
export function createResilientChain() {
const cache = new VercelKVCache();
// 带回退的主模型
const primaryModel = new ChatGoogleGenerativeAI({
modelName: 'gemini-2.5-pro',
temperature: 0,
maxRetries: 2,
});
const fallbackModel = new ChatGoogleGenerativeAI({
modelName: 'gemini-2.5-flash',
temperature: 0,
maxRetries: 1,
});
const modelWithFallback = primaryModel.withFallbacks({
fallbacks: [fallbackModel],
});
// 创建缓存提示执行器
const cachedExecutor = async (prompt: string, input: any) => {
const cacheKey = `chain:${prompt.substring(0, 20)}:${JSON.stringify(input)}`;
// 检查缓存
const cached = await cache.get(cacheKey);
if (cached) return cached;
// 使用重试逻辑执行
const result = await retry(
async () => {
const template = PromptTemplate.fromTemplate(prompt);
const chain = template.pipe(modelWithFallback).pipe(new StringOutputParser());
return await chain.invoke(input);
},
{
times: 3,
delay: 1000,
onError: async (error, attemptNumber) => {
console.error(`尝试${attemptNumber}失败:`, error);
await delay(attemptNumber * 1000); // 指数退避
},
}
);
// 缓存结果
await cache.set(cacheKey, result);
return result;
};
// 构建弹性链
const chain = RunnableSequence.from([
async (input: { query: string }) => {
// 步骤1:查询理解与缓存
const understanding = await cachedExecutor(
'为了清晰起见,重新表述这个查询:{query}',
input
);
return { understanding };
},
async (state: { understanding: string }) => {
// 步骤2:研究与回退
const research = await cachedExecutor(
'提供关于以下内容的详细研究:{understanding}',
state
);
return { ...state, research };
},
async (state: { understanding: string; research: string }) => {
// 步骤3:综合与验证
const synthesis = await cachedExecutor(
`将此研究综合为可行的洞察:
主题:{understanding}
研究:{research}`,
state
);
// 验证输出
if (synthesis.length < 100) {
throw new Error('综合内容太短,正在重试...');
}
return { ...state, synthesis };
},
]);
return chain;
}
使用es-toolkit工具实现具有缓存、回退和重试逻辑的生产就绪链。
4. 并行链处理
// lib/chains/parallel-processor.ts
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
import { RunnableParallel, RunnableSequence } from '@langchain/core/runnables';
import { PromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';
import { chunk, uniqBy } from 'es-toolkit';
export function createParallelProcessor() {
const model = new ChatGoogleGenerativeAI({
modelName: 'gemini-2.5-flash',
temperature: 0.3,
});
// 定义并行分析分支
const sentimentAnalysis = PromptTemplate.fromTemplate(
'分析此文本的情感(积极/消极/中性):{text}'
).pipe(model).pipe(new StringOutputParser());
const entityExtraction = PromptTemplate.fromTemplate(
'从以下文本中提取所有命名实体(人名、地名、组织):{text}'
).pipe(model).pipe(new StringOutputParser());
const topicClassification = PromptTemplate.fromTemplate(
'对此文本的主要主题进行分类:{text}'
).pipe(model).pipe(new StringOutputParser());
const keywordExtraction = PromptTemplate.fromTemplate(
'从此文本中提取5-10个关键词:{text}'
).pipe(model).pipe(new StringOutputParser());
// 创建并行执行
const parallelAnalysis = RunnableParallel({
sentiment: sentimentAnalysis,
entities: entityExtraction,
topic: topicClassification,
keywords: keywordExtraction,
});
// 综合步骤
const synthesisPrompt = PromptTemplate.fromTemplate(`
基于以下内容创建综合分析报告:
情感:{sentiment}
实体:{entities}
主题:{topic}
关键词:{keywords}
格式化为带有章节的结构化报告。
`);
// 完整链:并行分析然后综合
const chain = RunnableSequence.from([
parallelAnalysis,
synthesisPrompt,
model,
new StringOutputParser(),
]);
return chain;
}
// 多文档批处理器
export async function processBatch(documents: string[]) {
const processor = createParallelProcessor();
const BATCH_SIZE = 5;
// 分批处理以避免速率限制
const batches = chunk(documents, BATCH_SIZE);
const results = [];
for (const batch of batches) {
const batchResults = await Promise.all(
batch.map(async (doc) => {
try {
const result = await processor.invoke({ text: doc });
return { success: true, result, document: doc };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : '未知错误',
document: doc
};
}
})
);
results.push(...batchResults);
// 批次间的速率限制延迟
if (batches.indexOf(batch) < batches.length - 1) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return results;
}
并行执行多个分析任务然后综合结果,支持批处理。
5. 具有记忆的上下文感知链
// lib/chains/contextual-chain.ts
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
import { BufferMemory } from 'langchain/memory';
import { ConversationChain } from 'langchain/chains';
import { PromptTemplate } from '@langchain/core/prompts';
import { MessagesPlaceholder } from '@langchain/core/prompts';
import { RunnableSequence } from '@langchain/core/runnables';
export class ContextualChain {
private memory: BufferMemory;
private chain: RunnableSequence;
private model: ChatGoogleGenerativeAI;
constructor() {
this.model = new ChatGoogleGenerativeAI({
modelName: 'gemini-2.5-pro',
temperature: 0.7,
});
this.memory = new BufferMemory({
returnMessages: true,
memoryKey: 'history',
inputKey: 'input',
outputKey: 'output',
});
this.initializeChain();
}
private initializeChain() {
const contextPrompt = PromptTemplate.fromTemplate(`
您正在逐步分析文档。
先前上下文:{history}
当前任务:{task}
当前输入:{input}
提供建立在先前分析基础上的详细回应。
`);
this.chain = RunnableSequence.from([
async (input: { task: string; input: string }) => {
const history = await this.memory.loadMemoryVariables({});
return { ...input, history: history.history || '' };
},
contextPrompt,
this.model,
async (response) => {
const content = response.content as string;
// 保存到记忆
await this.memory.saveContext(
{ input: this.lastInput },
{ output: content }
);
return content;
},
]);
}
private lastInput: string = '';
async process(task: string, input: string): Promise<string> {
this.lastInput = `${task}: ${input}`;
return await this.chain.invoke({ task, input });
}
async reset() {
await this.memory.clear();
}
async getHistory(): Promise<string> {
const history = await this.memory.loadMemoryVariables({});
return history.history || '无可用历史记录';
}
}
// 在API路由中的用法
export async function processWithContext(
sessionId: string,
task: string,
input: string
) {
// 按会话存储链
const chainStore = global as any;
chainStore.contextChains = chainStore.contextChains || new Map();
if (!chainStore.contextChains.has(sessionId)) {
chainStore.contextChains.set(sessionId, new ContextualChain());
}
const chain = chainStore.contextChains.get(sessionId);
return await chain.process(task, input);
}
在多个链执行中维护对话上下文,用于有状态的文档分析。
6. 具有监控的生产就绪链
// lib/chains/monitored-chain.ts
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
import { RunnableSequence } from '@langchain/core/runnables';
import { PromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';
interface ChainMetrics {
executionTime: number;
tokenCount: number;
cost: number;
steps: Array<{
name: string;
duration: number;
tokens: number;
}>;
}
export class MonitoredChain {
private metrics: ChainMetrics[] = [];
async executeWithMonitoring(input: string): Promise<{
result: string;
metrics: ChainMetrics;
}> {
const startTime = Date.now();
const stepMetrics: ChainMetrics['steps'] = [];
const model = new ChatGoogleGenerativeAI({
modelName: 'gemini-2.5-flash',
temperature: 0,
callbacks: [
{
handleLLMStart: async (llm, prompts) => {
console.log('LLM开始:', prompts[0].substring(0, 100));
},
handleLLMEnd: async (output) => {
const tokens = output.llmOutput?.tokenUsage?.totalTokens || 0;
stepMetrics[stepMetrics.length - 1].tokens = tokens;
},
},
],
});
// 步骤1:分类
const stepStart = Date.now();
stepMetrics.push({ name: 'classification', duration: 0, tokens: 0 });
const classificationPrompt = PromptTemplate.fromTemplate(
'将此文本分类为不同类别:{text}'
);
const classification = await classificationPrompt
.pipe(model)
.pipe(new StringOutputParser())
.invoke({ text: input });
stepMetrics[0].duration = Date.now() - stepStart;
// 步骤2:增强
const step2Start = Date.now();
stepMetrics.push({ name: 'enhancement', duration: 0, tokens: 0 });
const enhancementPrompt = PromptTemplate.fromTemplate(
'用详细信息增强此分类:{classification}'
);
const enhancement = await enhancementPrompt
.pipe(model)
.pipe(new StringOutputParser())
.invoke({ classification });
stepMetrics[1].duration = Date.now() - step2Start;
// 计算总体指标
const totalTokens = stepMetrics.reduce((sum, step) => sum + step.tokens, 0);
const metrics: ChainMetrics = {
executionTime: Date.now() - startTime,
tokenCount: totalTokens,
cost: totalTokens * 0.000001, // 示例定价
steps: stepMetrics,
};
this.metrics.push(metrics);
return {
result: enhancement,
metrics,
};
}
getAverageMetrics(): ChainMetrics | null {
if (this.metrics.length === 0) return null;
const avgTime = this.metrics.reduce((sum, m) => sum + m.executionTime, 0) / this.metrics.length;
const avgTokens = this.metrics.reduce((sum, m) => sum + m.tokenCount, 0) / this.metrics.length;
const avgCost = this.metrics.reduce((sum, m) => sum + m.cost, 0) / this.metrics.length;
return {
executionTime: Math.round(avgTime),
tokenCount: Math.round(avgTokens),
cost: avgCost,
steps: [],
};
}
}
跟踪每个链执行的详细指标,包括时间、token使用量和成本。
7. 链监控的前端仪表板
// components/ChainDashboard.tsx
'use client';
import { useState, useEffect } from 'react';
import { useQuery, useMutation } from '@tanstack/react-query';
import { groupBy, mean, round } from 'es-toolkit';
interface ChainExecution {
id: string;
chainName: string;
status: 'pending' | 'processing' | 'complete' | 'failed';
startTime: string;
endTime?: string;
metrics?: {
executionTime: number;
tokenCount: number;
cost: number;
};
}
export default function ChainDashboard() {
const [executions, setExecutions] = useState<ChainExecution[]>([]);
// 获取执行历史
const { data: history } = useQuery({
queryKey: ['chain-history'],
queryFn: async () => {
const response = await fetch('/api/chain-history');
return response.json();
},
refetchInterval: 5000,
});
// 执行新链
const executeChain = useMutation({
mutationFn: async (chainConfig: { name: string; input: string }) => {
const response = await fetch('/api/execute-chain', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(chainConfig),
});
return response.json();
},
onSuccess: (data) => {
setExecutions(prev => [...prev, data]);
},
});
// 计算统计信息
const stats = executions.reduce(
(acc, exec) => {
if (exec.status === 'complete' && exec.metrics) {
acc.totalExecutions++;
acc.totalTokens += exec.metrics.tokenCount;
acc.totalCost += exec.metrics.cost;
acc.avgTime = mean([acc.avgTime, exec.metrics.executionTime]);
} else if (exec.status === 'failed') {
acc.failures++;
}
return acc;
},
{
totalExecutions: 0,
totalTokens: 0,
totalCost: 0,
avgTime: 0,
failures: 0,
}
);
return (
<div className="p-6 space-y-6">
{/* 统计网格 */}
<div className="stats shadow w-full">
<div className="stat">
<div className="stat-title">总执行次数</div>
<div className="stat-value">{stats.totalExecutions}</div>
<div className="stat-desc">
{stats.failures > 0 && `${stats.failures} 次失败`}
</div>
</div>
<div className="stat">
<div className="stat-title">平均执行时间</div>
<div className="stat-value">{round(stats.avgTime / 1000, 2)}秒</div>
<div className="stat-desc">每次链执行</div>
</div>
<div className="stat">
<div className="stat-title">总Token数</div>
<div className="stat-value">{stats.totalTokens.toLocaleString()}</div>
<div className="stat-desc">
总成本 ${round(stats.totalCost, 4)}
</div>
</div>
</div>
{/* 执行时间线 */}
<div className="card bg-base-100 shadow-xl">
<div className="card-body">
<h2 className="card-title">最近执行</h2>
<div className="overflow-x-auto">
<table className="table table-zebra">
<thead>
<tr>
<th>链</th>
<th>状态</th>
<th>耗时</th>
<th>Token数</th>
<th>成本</th>
</tr>
</thead>
<tbody>
{executions.slice(-10).reverse().map((exec) => (
<tr key={exec.id}>
<td>{exec.chainName}</td>
<td>
<div className={`badge ${
exec.status === 'complete' ? 'badge-success' :
exec.status === 'failed' ? 'badge-error' :
exec.status === 'processing' ? 'badge-warning' :
'badge-ghost'
}`}>
{exec.status === 'complete' ? '完成' :
exec.status === 'failed' ? '失败' :
exec.status === 'processing' ? '处理中' :
'等待中'}
</div>
</td>
<td>
{exec.metrics
? `${round(exec.metrics.executionTime / 1000, 2)}秒`
: '-'}
</td>
<td>{exec.metrics?.tokenCount || '-'}</td>
<td>
{exec.metrics
? `$${round(exec.metrics.cost, 4)}`
: '-'}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
{/* 执行新链 */}
<div className="card bg-base-100 shadow-xl">
<div className="card-body">
<h2 className="card-title">执行链</h2>
<div className="form-control">
<label className="label">
<span className="label-text">选择链类型</span>
</label>
<select className="select select-bordered">
<option>基础顺序</option>
<option>文档分析器</option>
<option>并行处理器</option>
<option>上下文链</option>
</select>
</div>
<button
className="btn btn-primary"
onClick={() => executeChain.mutate({
name: '基础顺序',
input: '示例输入文本',
})}
disabled={executeChain.isPending}
>
{executeChain.isPending ? (
<>
<span className="loading loading-spinner"></span>
执行中...
</>
) : (
'执行链'
)}
</button>
</div>
</div>
</div>
);
}
用于监控链执行的实时仪表板,包含统计信息和成本跟踪。
结论
提示链将复杂的AI任务转化为可管理的顺序操作,可以独立优化、监控和扩展。通过在Vercel无服务器平台上使用LangChain的LCEL和LangGraph的有状态工作流实现这些模式,您可以构建可靠处理复杂推理任务的生产就绪AI应用程序。关键是从简单的链开始,随着应用程序的扩展逐步添加缓存、回退和监控等弹性功能。