AI辅助技术写作:从提纲到初稿的协作流水线完整方案
一、技术写作的核心痛点与AI机遇
技术写作是程序员和技术人员的基本技能,但面临诸多痛点:写作耗时长、结构组织难、语言表达不够清晰、技术深度与可读性难以平衡。
核心痛点:
AI辅助的核心价值:
- 提速:从12小时缩短至3-4小时
- 结构化:自动生成合理的内容结构
- 优化表达:提升文字清晰度和可读性
- 多视角:模拟不同读者背景提供建议
- 持续迭代:快速生成多个版本供选择
graph TD
A[写作意图] –> B[AI生成提纲]
B –> C[人工审核调整]
C –> D[AI生成初稿]
D –> E[人工深度编辑]
E –> F[AI辅助润色]
F –> G[最终定稿]
G –> H[发布反馈]
H –> A
AI辅助写作的三大原则:
二、提纲生成与结构优化系统
高质量的提纲是优秀文章的基础。AI可以根据主题、受众、字数要求自动生成合理的提纲。
提纲生成系统架构:
// 提纲生成器
class OutlineGenerator {
private aiModel: AIModel;
private templateLibrary: TemplateLibrary;
constructor() {
this.aiModel = new AIModel();
this.templateLibrary = new TemplateLibrary();
}
// 生成提纲
public async generateOutline(
request: OutlineRequest
): Promise<Outline> {
try {
// 1. 分析写作意图
const intent = await this.analyzeIntent(request.topic);
// 2. 选择合适模板
const template = this.templateLibrary.getTemplate(
intent.category,
request.audienceLevel
);
// 3. 生成提纲
const outline = await this.generateWithAI(request, template);
// 4. 优化结构
const optimized = await this.optimizeStructure(outline);
// 5. 估计字数分配
const withWordCount = this.estimateWordCount(optimized, request.targetWordCount);
return withWordCount;
} catch (error) {
console.error('提纲生成失败:', error);
// 返回基础提纲
return this.generateBasicOutline(request);
}
}
// 分析写作意图
private async analyzeIntent(topic: string): Promise<WritingIntent> {
try {
const prompt = `
分析以下技术写作主题,提取关键信息:
主题:${topic}
请输出JSON:
{
"category": "tutorial | opinion | deep-dive | comparison | case-study",
"mainTechnology": "主要技术栈",
"audience": "目标读者描述",
"keyPoints": ["关键点1", "关键点2", …],
"difficulty": "beginner | intermediate | advanced"
}
`;
const response = await this.aiModel.complete({
prompt,
temperature: 0.3,
maxTokens: 500
});
return JSON.parse(response);
} catch (error) {
console.error('意图分析失败:', error);
return {
category: 'tutorial',
mainTechnology: 'General',
audience: 'Developers',
keyPoints: [],
difficulty: 'intermediate'
};
}
}
// 使用AI生成提纲
private async generateWithAI(
request: OutlineRequest,
template: ArticleTemplate
): Promise<Outline> {
try {
const prompt = this.buildOutlinePrompt(request, template);
const response = await this.aiModel.complete({
prompt,
temperature: 0.7,
maxTokens: 2000
});
const outline = this.parseOutline(response);
// 验证提纲完整性
this.validateOutline(outline, request);
return outline;
} catch (error) {
console.error('AI提纲生成失败:', error);
throw error;
}
}
// 构建提纲生成prompt
private buildOutlinePrompt(
request: OutlineRequest,
template: ArticleTemplate
): string {
return `
作为技术写作专家,为主题生成详细提纲。
## 主题
${request.topic}
## 目标读者
${request.audienceDescription}
## 字数要求
${request.targetWordCount} 字
## 特殊要求
${request.specialRequirements || '无'}
## 参考模板
${template.structure}
## 提纲要求
1. 包含引言、主体、总结三大部分
2. 主体部分至少5个二级标题
3. 每个二级标题下有2-4个三级标题
4. 标注每个部分的建议字数
5. 标注需要代码示例的位置
6. 标注需要图表的位置
输出JSON格式。
`;
}
// 解析提纲
private parseOutline(aiResponse: string): Outline {
try {
// 尝试直接解析JSON
return JSON.parse(aiResponse);
} catch (error) {
// 如果失败,尝试从文本中提取
console.warn('JSON解析失败,尝试文本提取');
return this.extractOutlineFromText(aiResponse);
}
}
// 优化提纲结构
private async optimizeStructure(outline: Outline): Promise<Outline> {
// 1. 检查逻辑流
const logicalFlow = this.checkLogicalFlow(outline);
if (!logicalFlow.valid) {
// 调整结构
outline = this.rearrangeSections(outline, logicalFlow.suggestions);
}
// 2. 平衡字数分配
outline = this.balanceWordCount(outline);
// 3. 添加过渡建议
outline = this.addTransitionSuggestions(outline);
return outline;
}
// 检查逻辑流
private checkLogicalFlow(outline: Outline): LogicalFlowCheck {
const suggestions: string[] = [];
let valid = true;
// 检查是否有引言
if (!outline.sections.some(s => s.type === 'introduction')) {
valid = false;
suggestions.push('缺少引言部分');
}
// 检查是否有总结
if (!outline.sections.some(s => s.type === 'conclusion')) {
valid = false;
suggestions.push('缺少总结部分');
}
// 检查主体部分是否足够详细
const mainSections = outline.sections.filter(s => s.type === 'body');
for (const section of mainSections) {
if (!section.subsections || section.subsections.length < 2) {
valid = false;
suggestions.push(`部分"${section.title}"需要更多子章节`);
}
}
return { valid, suggestions };
}
// 估计字数分配
private estimateWordCount(
outline: Outline,
target: number
): Outline {
const totalSections = outline.sections.length;
let allocated = 0;
for (let i = 0; i < outline.sections.length; i++) {
const section = outline.sections[i];
// 根据类型分配字数比例
let ratio: number;
if (section.type === 'introduction') {
ratio = 0.1; // 10%
} else if (section.type === 'conclusion') {
ratio = 0.1; // 10%
} else {
// 主体部分平均分配
const bodyCount = outline.sections.filter(s => s.type === 'body').length;
ratio = 0.8 / bodyCount; // 80%分给主体
}
section.estimatedWordCount = Math.floor(target * ratio);
allocated += section.estimatedWordCount;
// 递归处理子章节
if (section.subsections) {
this.estimateWordCountRecursive(
section.subsections,
section.estimatedWordCount
);
}
}
// 调整误差
const remaining = target – allocated;
if (Math.abs(remaining) > 50) {
// 调整到最后一个主体部分
const lastBody = […outline.sections].reverse()
.find(s => s.type === 'body');
if (lastBody) {
lastBody.estimatedWordCount += remaining;
}
}
return outline;
}
// 递归估计字数
private estimateWordCountRecursive(
subsections: Section[],
parentWordCount: number
): void {
const perSection = Math.floor(parentWordCount / subsections.length);
let allocated = 0;
for (let i = 0; i < subsections.length; i++) {
const subsection = subsections[i];
if (i === subsections.length – 1) {
// 最后一个子章节获得剩余字数
subsection.estimatedWordCount = parentWordCount – allocated;
} else {
subsection.estimatedWordCount = perSection;
allocated += perSection;
}
// 递归处理
if (subsection.subsections) {
this.estimateWordCountRecursive(
subsection.subsections,
subsection.estimatedWordCount
);
}
}
}
// 生成基础提纲(fallback)
private generateBasicOutline(request: OutlineRequest): Outline {
return {
topic: request.topic,
targetWordCount: request.targetWordCount,
sections: [
{
title: '一、引言',
type: 'introduction',
estimatedWordCount: Math.floor(request.targetWordCount * 0.1)
},
{
title: '二、背景与动机',
type: 'body',
estimatedWordCount: Math.floor(request.targetWordCount * 0.2)
},
{
title: '三、核心内容',
type: 'body',
estimatedWordCount: Math.floor(request.targetWordCount * 0.4)
},
{
title: '四、实战案例',
type: 'body',
estimatedWordCount: Math.floor(request.targetWordCount * 0.2)
},
{
title: '五、总结',
type: 'conclusion',
estimatedWordCount: Math.floor(request.targetWordCount * 0.1)
}
]
};
}
}
// 类型定义
interface OutlineRequest {
topic: string;
audienceLevel: 'beginner' | 'intermediate' | 'advanced';
audienceDescription: string;
targetWordCount: number;
specialRequirements?: string;
}
interface Outline {
topic: string;
targetWordCount: number;
sections: Section[];
}
interface Section {
title: string;
type: 'introduction' | 'body' | 'conclusion';
estimatedWordCount: number;
subsections?: Section[];
codeExamples?: boolean;
diagrams?: boolean;
notes?: string;
}
interface WritingIntent {
category: string;
mainTechnology: string;
audience: string;
keyPoints: string[];
difficulty: string;
}
interface LogicalFlowCheck {
valid: boolean;
suggestions: string[];
}
interface ArticleTemplate {
name: string;
category: string;
structure: string;
}
class AIModel {
async complete(request: { prompt: string; temperature: number; maxTokens: number }): Promise<string> {
// 调用AI API
return '{}';
}
}
class TemplateLibrary {
getTemplate(category: string, level: string): ArticleTemplate {
return {
name: 'Default',
category,
structure: 'Standard'
};
}
}
// 导出
export const outlineGenerator = new OutlineGenerator();
提纲审核与调整界面(伪代码):
// 提纲审核工具
class OutlineReviewer {
// 可视化提纲
public renderOutline(outline: Outline): string {
let md = `# ${outline.topic}\\n\\n`;
md += `目标字数: ${outline.targetWordCount}\\n\\n`;
for (const section of outline.sections) {
md += this.renderSection(section, 1);
}
return md;
}
private renderSection(section: Section, depth: number): string {
let md = `${'#'.repeat(depth)} ${section.title}\\n\\n`;
md += `建议字数: ${section.estimatedWordCount}\\n\\n`;
if (section.codeExamples) {
md += `> 建议包含代码示例\\n\\n`;
}
if (section.diagrams) {
md += `> 建议包含图表\\n\\n`;
}
if (section.notes) {
md += `> ${section.notes}\\n\\n`;
}
if (section.subsections) {
for (const subsection of section.subsections) {
md += this.renderSection(subsection, depth + 1);
}
}
return md;
}
// 调整提纲
public adjustOutline(
outline: Outline,
adjustments: OutlineAdjustment[]
): Outline {
for (const adj of adjustments) {
switch (adj.type) {
case 'merge':
outline = this.mergeSections(outline, adj.section1, adj.section2);
break;
case 'split':
outline = this.splitSection(outline, adj.section, adj.newTitles);
break;
case 'reorder':
outline = this.reorderSections(outline, adj.order);
break;
case 'resize':
outline = this.resizeSection(outline, adj.section, adj.newWordCount);
break;
}
}
return outline;
}
// 省略调整方法的实现…
private mergeSections(outline: Outline, s1: string, s2: string): Outline {
return outline;
}
private splitSection(outline: Outline, section: string, newTitles: string[]): Outline {
return outline;
}
private reorderSections(outline: Outline, order: string[]): Outline {
return outline;
}
private resizeSection(outline: Outline, section: string, newWordCount: number): Outline {
return outline;
}
}
interface OutlineAdjustment {
type: 'merge' | 'split' | 'reorder' | 'resize';
section?: string;
section1?: string;
section2?: string;
newTitles?: string[];
order?: string[];
newWordCount?: number;
}
提纲生成的实战场景:
在使用 AI 生成提纲时,我们遇到一个典型误区:AI 生成的提纲往往"太完美"——结构工整、理论完备,但缺乏"一针见血"的实战洞察。比如 AI 会把"如何优化 React 性能"拆成"内存管理、渲染优化、网络请求优化"三类,但实际开发中最痛的点是"某个第三方组件库依赖导致 80% 的渲染开销",这种洞察是 AI 很难从通用知识中推导出来的。
解决方案是在调用 generateOutline 之前,先让开发者输入 3-5 条"我知道的坑"或"我希望重点讲的内容",作为 specialRequirements 强制注入到提纲的生成 prompt 中,确保提纲不脱离实际经验。同时,提纲审核阶段不要只看结构,还要检查每个章节下是否有"可落地的代码示例"和"可量化的数据支持"——缺少这两者的章节往往会在写作时卡壳。
三、初稿生成与协作编辑系统
有了提纲后,可以基于提纲生成初稿。关键是保持技术准确性和文字流畅性。
初稿生成系统:
// 初稿生成器
class DraftGenerator {
private aiModel: AIModel;
private codeGenerator: CodeGenerator;
private diagramGenerator: DiagramGenerator;
constructor() {
this.aiModel = new AIModel();
this.codeGenerator = new CodeGenerator();
this.diagramGenerator = new DiagramGenerator();
}
// 生成完整初稿
public async generateDraft(
outline: Outline,
styleGuide?: StyleGuide
): Promise<Draft> {
try {
const sections: DraftSection[] = [];
// 逐节生成
for (const section of outline.sections) {
const generated = await this.generateSection(
section,
styleGuide
);
sections.push(generated);
// 实时保存(防止丢失)
this.autoSave(sections);
}
// 生成代码示例
await this.addCodeExamples(sections);
// 生成图表
await this.addDiagrams(sections);
// 生成摘要
const summary = await this.generateSummary(sections);
return {
outline,
sections,
summary,
metadata: {
generatedAt: new Date(),
wordCount: this.countWords(sections),
readingTime: this.estimateReadingTime(sections)
}
};
} catch (error) {
console.error('初稿生成失败:', error);
throw error;
}
}
// 生成单个章节
private async generateSection(
section: Section,
styleGuide?: StyleGuide
): Promise<DraftSection> {
try {
// 构建prompt
const prompt = this.buildSectionPrompt(section, styleGuide);
// 调用AI生成
const content = await this.aiModel.complete({
prompt,
temperature: 0.7,
maxTokens: section.estimatedWordCount * 2 // token通常比字数多
});
// 后处理
const processed = this.postProcessContent(content, styleGuide);
// 验证字数
const wordCount = this.countWordsInText(processed);
if (Math.abs(wordCount – section.estimatedWordCount) > section.estimatedWordCount * 0.3) {
console.warn(`章节"${section.title}"字数偏差较大: ${wordCount} vs ${section.estimatedWordCount}`);
}
return {
title: section.title,
content: processed,
wordCount,
subsections: section.subsections
? await Promise.all(
section.subsections.map(sub => this.generateSection(sub, styleGuide))
)
: []
};
} catch (error) {
console.error(`生成章节失败: ${section.title}`, error);
// 返回占位符
return {
title: section.title,
content: `[待撰写: ${section.title}]`,
wordCount: 0,
subsections: []
};
}
}
// 构建章节生成prompt
private buildSectionPrompt(
section: Section,
styleGuide?: StyleGuide
): string {
let prompt = `
作为技术写作专家,撰写以下章节。
## 章节标题
${section.title}
## 建议字数
${section.estimatedWordCount} 字
## 写作要求
`;
if (styleGuide) {
prompt += `
– 文风: ${styleGuide.tone}
– 句子长度: ${styleGuide.sentenceLength}
– 专业术语: ${styleGuide.terminology}
– 代码示例: ${styleGuide.codeExampleStyle}
`;
}
prompt += `
– 使用简体中文
– 短句为主,不超过35字
– 技术术语首次出现时给出解释
– 包含实际代码示例(如适用)
– 使用Markdown格式
输出Markdown格式内容。
`;
return prompt;
}
// 后处理内容
private postProcessContent(
content: string,
styleGuide?: StyleGuide
): string {
let processed = content;
// 1. 清理多余空行
processed = processed.replace(/\\n{3,}/g, '\\n\\n');
// 2. 修复代码块格式
processed = this.fixCodeBlocks(processed);
// 3. 检查句子长度
if (styleGuide?.sentenceLength === 'short') {
processed = this.breakLongSentences(processed, 35);
}
// 4. 统一术语
if (styleGuide?.terminology) {
processed = this.unifyTerminology(processed, styleGuide.terminology);
}
return processed;
}
// 添加代码示例
private async addCodeExamples(
sections: DraftSection[]
): Promise<void> {
for (const section of sections) {
// 检测是否需要代码示例
if (this.needsCodeExample(section.content)) {
try {
const code = await this.codeGenerator.generate(
section.content,
this.extractLanguage(section.content)
);
// 插入代码到合适位置
section.content = this.insertCodeAtRightPlace(
section.content,
code
);
} catch (error) {
console.error(`生成代码示例失败: ${section.title}`, error);
}
}
// 递归处理子章节
if (section.subsections) {
await this.addCodeExamples(section.subsections);
}
}
}
// 添加图表
private async addDiagrams(
sections: DraftSection[]
): Promise<void> {
for (const section of sections) {
// 检测是否需要图表
if (this.needsDiagram(section.content)) {
try {
const diagram = await this.diagramGenerator.generate(
section.content
);
// 插入图表
section.content = this.insertDiagramAtRightPlace(
section.content,
diagram
);
} catch (error) {
console.error(`生成图表失败: ${section.title}`, error);
}
}
// 递归处理子章节
if (section.subsections) {
await this.addDiagrams(section.subsections);
}
}
}
// 省略辅助方法…
private autoSave(sections: DraftSection[]): void {
// 自动保存到本地存储
console.log('自动保存…');
}
private countWords(sections: DraftSection[]): number {
return sections.reduce(
(sum, s) => sum + s.wordCount + this.countWords(s.subsections),
0
);
}
private countWordsInText(text: string): number {
// 中文字数统计
const chineseChars = (text.match(/[\\u4e00-\\u9fff]/g) || []).length;
const englishWords = (text.match(/[a-zA-Z]+/g) || []).length;
return chineseChars + englishWords;
}
private estimateReadingTime(sections: DraftSection[]): number {
const words = this.countWords(sections);
return Math.ceil(words / 300); // 假设每分钟阅读300字
}
private generateSummary(sections: DraftSection[]): Promise<string> {
return Promise.resolve('文章摘要…');
}
private postProcessContent(content: string, styleGuide?: StyleGuide): string {
return content;
}
private fixCodeBlocks(content: string): string {
return content;
}
private breakLongSentences(content: string, maxLength: number): string {
return content;
}
private unifyTerminology(content: string, terminology: any): string {
return content;
}
private needsCodeExample(content: string): boolean {
return content.includes('[代码示例]') || content.includes('```');
}
private needsDiagram(content: string): boolean {
return content.includes('[图表]') || content.includes('```mermaid');
}
private extractLanguage(content: string): string {
return 'typescript';
}
private insertCodeAtRightPlace(content: string, code: string): string {
return content.replace('[代码示例]', code);
}
private insertDiagramAtRightPlace(content: string, diagram: string): string {
return content.replace('[图表]', diagram);
}
}
// 类型定义
interface Draft {
outline: Outline;
sections: DraftSection[];
summary: string;
metadata: DraftMetadata;
}
interface DraftSection {
title: string;
content: string;
wordCount: number;
subsections: DraftSection[];
}
interface DraftMetadata {
generatedAt: Date;
wordCount: number;
readingTime: number; // 分钟
}
interface StyleGuide {
tone: string;
sentenceLength: 'short' | 'medium' | 'long';
terminology: Record<string, string>;
codeExampleStyle: string;
}
class CodeGenerator {
async generate(context: string, language: string): Promise<string> {
return '```\\ncode example\\n```';
}
}
class DiagramGenerator {
async generate(context: string): Promise<string> {
return '```mermaid\\ngraph TD\\n```';
}
}
// 导出
export const draftGenerator = new DraftGenerator();
人机协作编辑界面(概念):
// 协作编辑器
class CollaborativeEditor {
private draft: Draft;
private suggestions: Suggestion[] = [];
// 人工编辑
public editSection(
sectionId: string,
newContent: string
): void {
const section = this.findSection(this.draft.sections, sectionId);
if (section) {
// 记录修改历史
this.recordHistory(section);
// 更新内容
section.content = newContent;
section.wordCount = this.countWordsInText(newContent);
// 触发AI审查
this.requestAIReview(section);
}
}
// AI辅助润色
public async polishSection(
sectionId: string
): Promise<void> {
const section = this.findSection(this.draft.sections, sectionId);
if (!section) return;
try {
const prompt = `
作为技术写作编辑,润色以下内容。
要求:
– 提升文字流畅性
– 修正语法错误
– 保持技术准确性
– 短句为主
内容:
${section.content}
`;
const polished = await this.aiModel.complete({
prompt,
temperature: 0.5,
maxTokens: section.content.length * 2
});
// 提供对比
this.showComparison(section.content, polished, sectionId);
} catch (error) {
console.error('润色失败:', error);
}
}
// AI审查
private async requestAIReview(section: DraftSection): Promise<void> {
try {
const prompt = `
审查以下技术文章内容,提供改进建议。
内容:
${section.content}
输出JSON格式的审查结果:
{
"score": 分数(0-100),
"issues": [
{
"type": "grammar | clarity | accuracy | style",
"location": "问题位置",
"problem": "问题描述",
"suggestion": "改进建议"
}
],
"overallSuggestion": "总体建议"
}
`;
const review = await this.aiModel.complete({
prompt,
temperature: 0.3,
maxTokens: 1000
});
const reviewResult = JSON.parse(review);
// 添加建议
this.suggestions.push({
sectionId: section.title,
score: reviewResult.score,
issues: reviewResult.issues,
overallSuggestion: reviewResult.overallSuggestion
});
} catch (error) {
console.error('AI审查失败:', error);
}
}
// 省略辅助方法…
private findSection(sections: DraftSection[], id: string): DraftSection | null {
return null;
}
private recordHistory(section: DraftSection): void {
// 记录历史版本
}
private showComparison(original: string, polished: string, sectionId: string): void {
// 显示对比界面
}
private countWordsInText(text: string): number {
return text.length;
}
}
interface Suggestion {
sectionId: string;
score: number;
issues: ReviewIssue[];
overallSuggestion: string;
}
interface ReviewIssue {
type: string;
location: string;
problem: string;
suggestion: string;
}
初稿生成的质量把控经验:
逐节生成初稿时,最容易出现的问题是"前后不连贯"——第 2 节提到"接下来我们将使用 X 方法",但第 3 节实际上用了 Y 方法。这是因为 AI 没有全局记忆,每节独立生成。一个有效的解决方案是在 buildSectionPrompt 中注入"上下文摘要":生成每节之前,先让 AI 生成前几节的 50 字摘要,将这个摘要传递给新章节的生成 prompt。
另一个踩坑:postProcessContent 中打断长句的逻辑如果过于激进,会把代码注释、命令行示例等内容也拆分掉。应该在处理前先通过正则排除代码块和行内代码。
四、质量评估与迭代优化系统
生成初稿后,需要建立质量评估体系,指导迭代优化。
质量评估维度:
// 质量评估器
class QualityEvaluator {
private evaluationCriteria: EvaluationCriteria[];
constructor() {
this.evaluationCriteria = [
{
name: '技术准确性',
weight: 0.3,
evaluator: 'ai' // AI评估
},
{
name: '文字流畅性',
weight: 0.2,
evaluator: 'ai'
},
{
name: '结构合理性',
weight: 0.15,
evaluator: 'ai'
},
{
name: '代码质量',
weight: 0.2,
evaluator: 'hybrid' // AI + 规则
},
{
name: '可读性',
weight: 0.15,
evaluator: 'ai'
}
];
}
// 评估整篇文章
public async evaluateDraft(draft: Draft): Promise<QualityReport> {
try {
const sectionScores: SectionScore[] = [];
// 评估每个章节
for (const section of draft.sections) {
const score = await this.evaluateSection(section);
sectionScores.push(score);
}
// 计算总分
const overallScore = this.calculateOverallScore(sectionScores);
// 生成改进建议
const suggestions = await this.generateImprovementSuggestions(
draft,
sectionScores
);
return {
draftId: draft.metadata.generatedAt.getTime().toString(),
overallScore,
sectionScores,
suggestions,
strengths: this.identifyStrengths(sectionScores),
weaknesses: this.identifyWeaknesses(sectionScores)
};
} catch (error) {
console.error('质量评估失败:', error);
throw error;
}
}
// 评估单个章节
private async evaluateSection(
section: DraftSection
): Promise<SectionScore> {
const criterionScores: CriterionScore[] = [];
for (const criterion of this.evaluationCriteria) {
const score = await this.evaluateCriterion(section, criterion);
criterionScores.push(score);
}
// 递归评估子章节
const subsectionScores = section.subsections
? await Promise.all(
section.subsections.map(sub => this.evaluateSection(sub))
)
: [];
return {
sectionId: section.title,
criterionScores,
subsectionScores,
overallScore: this.calculateSectionScore(criterionScores, subsectionScores)
};
}
// 评估单个标准
private async evaluateCriterion(
section: DraftSection,
criterion: EvaluationCriteria
): Promise<CriterionScore> {
if (criterion.evaluator === 'ai') {
return this.evaluateWithAI(section, criterion);
} else if (criterion.evaluator === 'rule') {
return this.evaluateWithRules(section, criterion);
} else {
// hybrid
const aiScore = await this.evaluateWithAI(section, criterion);
const ruleScore = this.evaluateWithRules(section, criterion);
return this.mergeScores(aiScore, ruleScore);
}
}
// 使用AI评估
private async evaluateWithAI(
section: DraftSection,
criterion: EvaluationCriteria
): Promise<CriterionScore> {
try {
const prompt = `
作为技术写作评审专家,评估以下内容的"${criterion.name}"。
内容:
${section.content}
请输出JSON:
{
"score": 分数(0-100),
"reason": "评分理由",
"issues": ["问题1", "问题2", …],
"suggestions": ["建议1", "建议2", …]
}
`;
const response = await this.aiModel.complete({
prompt,
temperature: 0.3,
maxTokens: 1000
});
const result = JSON.parse(response);
return {
criterionName: criterion.name,
score: result.score,
weight: criterion.weight,
reason: result.reason,
issues: result.issues,
suggestions: result.suggestions
};
} catch (error) {
console.error(`AI评估失败(${criterion.name}):`, error);
// 返回默认分数
return {
criterionName: criterion.name,
score: 70, // 默认中等分数
weight: criterion.weight,
reason: '评估失败,使用默认分数',
issues: [],
suggestions: []
};
}
}
// 使用规则评估
private evaluateWithRules(
section: DraftSection,
criterion: EvaluationCriteria
): CriterionScore {
// 基于规则的评估
const issues: string[] = [];
let score = 100;
if (criterion.name === '代码质量') {
// 检查代码块格式
const codeBlocks = section.content.match(/```[\\s\\S]*?```/g) || [];
for (const block of codeBlocks) {
// 检查是否有语言标识
if (!block.startsWith('```')) {
issues.push('代码块缺少语言标识');
score -= 10;
}
// 检查是否有错误处理
if (block.includes('try') && !block.includes('catch')) {
issues.push('代码示例缺少错误处理');
score -= 5;
}
}
}
if (criterion.name === '可读性') {
// 检查句子长度
const sentences = section.content.split(/[。!?]/);
const longSentences = sentences.filter(s => s.length > 35);
if (longSentences.length > 0) {
issues.push(`有${longSentences.length}个句子超过35字`);
score -= longSentences.length * 2;
}
}
return {
criterionName: criterion.name,
score: Math.max(0, score),
weight: criterion.weight,
reason: issues.length > 0 ? '发现一些问题' : '符合规范',
issues,
suggestions: issues.map(i => `建议修改: ${i}`)
};
}
// 省略其他辅助方法…
private calculateOverallScore(sectionScores: SectionScore[]): number {
return 85; // 简化
}
private calculateSectionScore(
criterionScores: CriterionScore[],
subsectionScores: SectionScore[]
): number {
return 85; // 简化
}
private mergeScores(score1: CriterionScore, score2: CriterionScore): CriterionScore {
return score1; // 简化
}
private async generateImprovementSuggestions(
draft: Draft,
sectionScores: SectionScore[]
): Promise<string[]> {
return []; // 简化
}
private identifyStrengths(sectionScores: SectionScore[]): string[] {
return []; // 简化
}
private identifyWeaknesses(sectionScores: SectionScore[]): string[] {
return []; // 简化
}
}
// 类型定义
interface EvaluationCriteria {
name: string;
weight: number;
evaluator: 'ai' | 'rule' | 'hybrid';
}
interface QualityReport {
draftId: string;
overallScore: number;
sectionScores: SectionScore[];
suggestions: string[];
strengths: string[];
weaknesses: string[];
}
interface SectionScore {
sectionId: string;
criterionScores: CriterionScore[];
subsectionScores: SectionScore[];
overallScore: number;
}
interface CriterionScore {
criterionName: string;
score: number;
weight: number;
reason: string;
issues: string[];
suggestions: string[];
}
class AIModel {
async complete(request: { prompt: string; temperature: number; maxTokens: number }): Promise<string> {
return '{}';
}
}
迭代优化工作流:
// 迭代优化器
class IterativeOptimizer {
private draftGenerator: DraftGenerator;
private qualityEvaluator: QualityEvaluator;
private maxIterations: number = 3;
constructor() {
this.draftGenerator = draftGenerator;
this.qualityEvaluator = new QualityEvaluator();
}
// 迭代优化
public async optimizeDraft(
draft: Draft,
targetScore: number = 85
): Promise<OptimizedDraft> {
let currentDraft = draft;
const history: IterationRecord[] = [];
for (let i = 0; i < this.maxIterations; i++) {
console.log(`开始第 ${i + 1} 轮优化…`);
// 1. 评估当前草稿
const evaluation = await this.qualityEvaluator.evaluateDraft(currentDraft);
// 2. 记录迭代历史
history.push({
iteration: i + 1,
score: evaluation.overallScore,
suggestions: evaluation.suggestions
});
// 3. 检查是否达到目标
if (evaluation.overallScore >= targetScore) {
console.log(`达到目标分数: ${evaluation.overallScore}`);
break;
}
// 4. 应用改进建议
currentDraft = await this.applySuggestions(
currentDraft,
evaluation
);
}
return {
finalDraft: currentDraft,
iterations: history,
improved: history[history.length – 1].score > history[0].score
};
}
// 应用改进建议
private async applySuggestions(
draft: Draft,
evaluation: QualityReport
): Promise<Draft> {
// 针对每个低分章节进行优化
for (const sectionScore of evaluation.sectionScores) {
if (sectionScore.overallScore < 75) {
// 找到对应章节
const section = this.findSection(draft.sections, sectionScore.sectionId);
if (section) {
// 根据建议优化
section.content = await this.optimizeSection(
section,
sectionScore
);
}
}
}
return draft;
}
// 优化单个章节
private async optimizeSection(
section: DraftSection,
score: SectionScore
): Promise<string> {
try {
const prompt = `
作为技术写作优化专家,根据评审意见优化以下内容。
## 原始内容
${section.content}
## 评审意见
${score.criterionScores.map(c => `- ${c.criterionName}: ${c.issues.join(', ')}`).join('\\n')}
## 改进建议
${score.criterionScores.map(c => c.suggestions.join('\\n')).join('\\n')}
请输出优化后的内容(保持Markdown格式)。
`;
const optimized = await this.aiModel.complete({
prompt,
temperature: 0.5,
maxTokens: section.content.length * 2
});
return optimized;
} catch (error) {
console.error(`优化章节失败: ${section.title}`, error);
return section.content; // 返回原始内容
}
}
// 省略辅助方法…
private findSection(sections: DraftSection[], id: string): DraftSection | null {
return null;
}
}
interface OptimizedDraft {
finalDraft: Draft;
iterations: IterationRecord[];
improved: boolean;
}
interface IterationRecord {
iteration: number;
score: number;
suggestions: string[];
}
class AIModel {
async complete(request: { prompt: string; temperature: number; maxTokens: number }): Promise<string> {
return '';
}
}
质量评估与迭代的实战心得:
质量评估系统最大的坑在于"评估标准与读者感知的差距"。AI 给文章打了 92 分(满分 100),但读者反馈说"看不懂"。原因是 AI 的评估侧重"技术准确性"和"结构完整性",而读者关心的是"能不能 10 分钟理解核心概念"。
引入"读者画像测试"机制可以弥补这个缺陷:将草稿发给 2-3 个目标读者的 AI 模拟(比如 "三年经验的 React 开发者"和"刚入行的前端新人"),让 AI 分别以这些角色阅读并标记"看不懂"的地方,将这些标记作为权重纳入 QualityEvaluator。这样迭代优化的方向更贴近真实读者体验。
另外,IterativeOptimizer 的 maxIterations 设置为 3 是有道理的——经过测试,第 4 轮以上的优化带来的提升通常小于 2%,边际收益太低,反而可能引入"过度润色"导致内容失真。建议在迭代中如果连续两轮提升小于 5%,就自动停止。
五、总结
AI辅助技术写作通过提纲生成、初稿生成、质量评估、迭代优化的完整流水线,将写作效率提升3-4倍。
核心收获:
- 提纲先行:合理的结构是好文章的基础
- 人机协作:AI负责效率和结构,人负责深度和判断
- 迭代优化:通过多轮评估和改进提升质量
- 质量保证:建立多维度评估体系
实施建议:
未来方向:
- 多模态生成:自动生成配图、视频讲解
- 个性化适配:根据读者背景动态调整内容深度
- 协作平台:多人+AI协同写作平台
AI不会取代技术写作者,但会用AI的技术写作者将取代不会用的。
技术栈标签:#AI辅助写作 #技术写作 #内容生成 #人机协作 #质量评估


