跳到主要内容

智能内容生成工具开发

构建高效、流畅的 AI 内容生成应用,掌握流式响应处理与 Prompt 模板管理。

目录

📖 概述

智能内容生成工具(AIGC Tools)是目前最常见的 AI 应用形态。从营销文案生成、邮件助手到代码编写辅助,这类应用的核心在于如何优雅地处理用户的输入,将其转化为高质量的 Prompt,并将 AI 的响应实时、准确地呈现给用户。

🎯 核心功能模块

1. Prompt 模板管理系统

将用户的简单输入转换为结构化的 Prompt 是提高生成质量的关键。

// PromptTemplate.ts
interface TemplateVariable {
name: string;
label: string;
placeholder?: string;
}

interface PromptTemplate {
id: string;
title: string;
description: string;
template: string; // 使用 {{variable}} 语法
variables: TemplateVariable[];
}

export const MARKETING_COPY_TEMPLATE: PromptTemplate = {
id: 'marketing-copy',
title: '营销文案生成器',
description: '为你的产品生成吸引人的社交媒体文案',
template: `
请为以下产品撰写一篇{{platform}}平台的营销文案。

产品名称:{{productName}}
核心卖点:{{features}}
目标受众:{{targetAudience}}
语气风格:{{tone}}

要求:
1. 包含适当的 Emoji
2. 结尾包含 3-5 个相关 Hashtag
3. 字数控制在 200 字以内
`,
variables: [
{ name: 'platform', label: '发布平台', placeholder: '小红书/微信/Twitter' },
{ name: 'productName', label: '产品名称', placeholder: '例如:智能咖啡杯' },
{ name: 'features', label: '核心卖点', placeholder: '保温、自动搅拌...' },
{ name: 'targetAudience', label: '目标受众', placeholder: '上班族、学生' },
{ name: 'tone', label: '语气风格', placeholder: '专业、幽默、亲切' }
]
};

export const fillTemplate = (template: string, values: Record<string, string>) => {
return template.replace(/\{\{(\w+)\}\}/g, (_, key) => values[key] || '');
};

2. 流式响应处理 (Stream Handling)

为了提供类似 ChatGPT 的打字机体验,我们需要处理 Server-Sent Events (SSE)。以下是一个基于 React Hooks 的实现。

import { useState, useRef } from 'react';

export const useChatStream = () => {
const [messages, setMessages] = useState<Array<{role: string, content: string}>>([]);
const [isLoading, setIsLoading] = useState(false);
const abortControllerRef = useRef<AbortController | null>(null);

const sendMessage = async (content: string) => {
setIsLoading(true);
// 添加用户消息
setMessages(prev => [...prev, { role: 'user', content }]);
// 添加空的助手消息占位
setMessages(prev => [...prev, { role: 'assistant', content: '' }]);

abortControllerRef.current = new AbortController();

try {
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: content }),
signal: abortControllerRef.current.signal,
});

if (!response.body) throw new Error('No response body');

const reader = response.body.getReader();
const decoder = new TextDecoder();
let assistantMessage = '';

while (true) {
const { done, value } = await reader.read();
if (done) break;

const chunk = decoder.decode(value);
// 简单的 SSE 解析逻辑(实际生产中建议使用专门的库如 eventsource-parser)
const lines = chunk.split('\n');

for (const line of lines) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.slice(6));
if (data.content) {
assistantMessage += data.content;
// 实时更新最后一条消息(助手消息)
setMessages(prev => {
const newMessages = [...prev];
newMessages[newMessages.length - 1] = {
role: 'assistant',
content: assistantMessage
};
return newMessages;
});
}
} catch (e) {
console.log('Parse error', e);
}
}
}
}
} catch (error) {
if (error.name === 'AbortError') {
console.log('Stream aborted');
} else {
console.error('Stream error', error);
}
} finally {
setIsLoading(false);
}
};

const stopGeneration = () => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
abortControllerRef.current = null;
}
};

return { messages, isLoading, sendMessage, stopGeneration };
};

3. Markdown 渲染与代码高亮

生成的文本通常包含 Markdown 格式,需要美观地渲染出来。

import React from 'react';
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';

export const MessageDisplay = ({ content }) => {
return (
<div className="prose prose-slate max-w-none dark:prose-invert">
<ReactMarkdown
components={{
code({node, inline, className, children, ...props}) {
const match = /language-(\w+)/.exec(className || '')
return !inline && match ? (
<SyntaxHighlighter
{...props}
style={vscDarkPlus}
language={match[1]}
PreTag="div"
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code {...props} className={className}>
{children}
</code>
)
}
}}
>
{content}
</ReactMarkdown>
</div>
);
};

🚀 性能与体验优化

  1. 防抖与节流:用户快速输入时,使用防抖减少不必要的渲染或请求检查。
  2. 自动滚动:新内容生成时,聊天窗口应自动滚动到底部,但如果用户手动向上滚动查看历史,则暂停自动滚动。
  3. 输入联想:基于用户的前几次输入,使用简单的 N-gram 模型或调用轻量级 AI 模型提供输入补全。
  4. 复制与导出:提供一键复制代码块、导出完整对话为 Markdown/PDF 的功能。

🔧 后端配合 (Node.js 示例)

前端的流式体验需要后端的配合。以下是使用 OpenAI SDK 的简单流式响应后端代码。

// server.js (Express)
app.post('/api/chat', async (req, res) => {
const { message } = req.body;

res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');

try {
const stream = await openai.chat.completions.create({
model: 'gpt-4o-mini', // 2026 默认小模型,文案/代码生成性价比高
messages: [{ role: 'user', content: message }],
stream: true,
});

for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
if (content) {
res.write(`data: ${JSON.stringify({ content })}\n\n`);
}
}
res.end();
} catch (error) {
console.error(error);
res.status(500).end();
}
});

🔁 用 Vercel AI SDK 重写(2026 推荐,替代手写 SSE)

上面的 useChatStream(手写 ReadableStream + 自己解析 data:)和后端 text/event-stream 都是「为讲原理」的实现。2026 年生产里直接用 Vercel AI SDK,几十行手写流式解析全部消失,还顺带拿到工具调用、结构化输出、多 provider。

前端:useChat 替代手写 useChatStream

'use client';
import { useChat } from '@ai-sdk/react';
import { Streamdown } from 'streamdown';

export function Writer() {
const { messages, sendMessage, status, stop } = useChat();
return (
<div>
{messages.map(m => (
<div key={m.id} className={m.role}>
{m.parts.map((p, i) =>
// streamdown:流式 Markdown 自动补全未闭合的代码块/表格/链接,不闪烁不错版
p.type === 'text' ? <Streamdown key={i}>{p.text}</Streamdown> : null
)}
</div>
))}
{status === 'streaming'
? <button onClick={stop}>停止</button>
: <SendBox onSend={(text) => sendMessage({ text })} />}
</div>
);
}

对照前面那段 useChatStreamreader 循环、TextDecoder、data: 切分、AbortController、占位消息更新——这些 useChat 全部内置。Markdown 渲染也从 react-markdown(流式时残缺语法会错版)升级到 streamdown(自动补全)。

后端:Route Handler + streamText 替代手写 SSE

// app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText, convertToModelMessages } from 'ai';

export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o-mini'),
system: '你是专业中文写作助手。',
messages: convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse(); // 替代手写 res.write(`data: ...`)
}

结构化文案:generateObject 输出可直接用的字段

写营销文案/SEO 元信息这类「要拆成多个字段」的场景,不要让模型吐一大段自由文本再正则切,用 generateObject 一次拿到结构化结果:

import { openai } from '@ai-sdk/openai';
import { generateObject } from 'ai';
import { z } from 'zod';

const { object } = await generateObject({
model: openai('gpt-4o-mini'),
schema: z.object({
title: z.string().describe('不超过 20 字的标题'),
summary: z.string().describe('100 字内摘要'),
hashtags: z.array(z.string()).max(5),
seoKeywords: z.array(z.string()).max(8),
}),
prompt: '为「儿童护眼台灯」生成一篇小红书种草文案的结构化信息。',
});
// object 类型安全:{ title, summary, hashtags, seoKeywords },前端直接渲染各字段

📚 总结

构建智能内容生成工具不仅仅是调用 API,更重要的是精心打磨 Prompt 模板流式交互体验以及结果的呈现方式。2026 年的工程标准是:用 Vercel AI SDK(streamText + useChat)接管流式与多 provider,用 generateObject 拿结构化文案,用 streamdown 渲染流式 Markdown,把精力集中在 Prompt 与产品体验上,而不是重复造流式解析的轮子。