This commit is contained in:
2026-01-10 16:58:15 +08:00
commit 48e3033639
53 changed files with 41267 additions and 0 deletions

View File

@@ -0,0 +1,396 @@
import { config } from './config.ts';
import { readFileSync, writeFileSync } from 'node:fs';
import { Kevisual } from '@kevisual/ai';
// ============================================
// AI优化提示词配置
// ============================================
// 通用哲理句优化提示词
export const PERFECT_PROMPT = `你是一个深谙人生哲理的作家。请将以下不完整的哲理句补充完整,使其成为一句发人深省的哲理名言。
要求:
1. 保持原句的核心主题和结构
2. 语言要简洁有力,富有哲理深度
3. 让人读后有所思考和共鸣
4. 符合中文表达习惯
5. 字数控制在20-50字之间
原句:{{sentence}}
请直接输出优化后的句子,不需要任何解释。`;
// 不同主题的专项优化提示词
export const THEME_PROMPTS: Record<string, string> = {
: `你是一个智慧的导师。请将以下关于人生的句子优化成一句深刻的人生感悟:
要求:
- 语言平实却蕴含智慧
- 让人读后有所触动
- 适合作为人生格言
原句:{{sentence}}
直接输出优化后的句子。`,
: `你是一个洞察时光的智者。请将以下关于时间的句子优化:
要求:
- 体现时间的珍贵与无情
- 让人珍惜当下
- 富有诗意但不晦涩
原句:{{sentence}}
直接输出优化后的句子。`,
: `你是一个经历过蜕变的智者。请将以下关于成长的句子优化:
要求:
- 体现成长的代价与收获
- 让人对成长有新的理解
- 有力量感但不鸡汤
原句:{{sentence}}
直接输出优化后的句子。`,
: `你是一个深刻理解孤独的人。请将以下关于孤独的句子优化:
要求:
- 准确描述孤独的本质
- 不是消极,而是清醒
- 让人学会与孤独和解
原句:{{sentence}}
直接输出优化后的句子。`,
: `你是一个懂得爱的人。请将以下关于爱的句子优化:
要求:
- 体现爱的真谛
- 不是空洞的情话
- 让人对爱有新的认识
原句:{{sentence}}
直接输出优化后的句子。`,
: `你是一个善于抉择的人。请将以下关于选择的句子优化:
要求:
- 体现选择的重量
- 不是教条,而是智慧
- 让人更慎重地面对选择
原句:{{sentence}}
直接输出优化后的句子。`,
: `你是一个追求自由的人。请将以下关于自由的句子优化:
要求:
- 准确描述自由的真谛
- 让人理解自由的代价
- 有深度但不晦涩
原句:{{sentence}}
直接输出优化后的句子。`,
: `你是一个从痛苦中走过来的人。请将以下关于痛苦的句子优化:
要求:
- 不是宣泄负面情绪
- 而是让人从痛苦中获得力量
- 转化痛苦为成长
原句:{{sentence}}
直接输出优化后的句子。`
};
// ============================================
// AI客户端接口
// ============================================
export interface PerfectOptions {
/** Kevisual AI 实例 */
ai?: Kevisual;
/** 使用的提示词模板 */
promptTemplate?: string;
/** 并发请求数 */
concurrency?: number;
/** 重试次数 */
retryTimes?: number;
/** 成功后回调 */
onSuccess?: (item: PerfectItem) => void;
/** 失败后回调 */
onError?: (item: PerfectError) => void;
/** 进度回调 */
onProgress?: (progress: ProgressInfo) => void;
}
export interface PerfectItem {
index: number;
text: string;
template: string;
templateType: string;
optimized: string;
prompt?: string;
theme: string;
tags: string[];
}
export interface PerfectError {
index: number;
original: string;
error: string;
theme: string;
}
export interface ProgressInfo {
current: number;
total: number;
percentage: number;
successCount: number;
errorCount: number;
}
// ============================================
// 默认AI实例
// ============================================
function createDefaultAI(): Kevisual {
return new Kevisual({
apiKey: config.KEVISUAL_NEW_API_KEY || '',
});
}
// ============================================
// 句子优化器类
// ============================================
export class SentencePerfect {
private options: Required<PerfectOptions>;
private ai: Kevisual;
constructor(options: PerfectOptions = {}) {
this.ai = options.ai || createDefaultAI();
this.options = {
ai: this.ai,
promptTemplate: options.promptTemplate || PERFECT_PROMPT,
concurrency: options.concurrency ?? 5,
retryTimes: options.retryTimes ?? 3,
onSuccess: options.onSuccess || (() => { }),
onError: options.onError || (() => { }),
onProgress: options.onProgress || (() => { })
};
}
/**
* 获取主题对应的提示词
*/
private getThemePrompt(theme: string, sentence: string): string {
const themePrompt = THEME_PROMPTS[theme];
if (themePrompt) {
return themePrompt.replace('{{sentence}}', sentence);
}
return this.options.promptTemplate.replace('{{sentence}}', sentence);
}
/**
* 优化单条句子(带重试)
*/
async perfectOne(item: PerfectItem): Promise<PerfectItem> {
const prompt = this.getThemePrompt(item.theme, item.text);
let lastError: Error | null = null;
for (let i = 0; i < this.options.retryTimes; i++) {
try {
await this.ai.chat([{ role: 'user', content: prompt }]);
let optimized = this.ai.responseText || '';
optimized = optimized.trim().replace(/^["']|["']$/g, '');
const result: PerfectItem = {
...item,
prompt: prompt,
optimized: optimized || item.text
};
this.options.onSuccess(result);
return result;
} catch (error) {
lastError = error as Error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
const error: PerfectError = {
index: item.index,
original: item.text,
error: lastError?.message || '未知错误',
theme: item.theme
};
this.options.onError(error);
return {
...item,
optimized: item.text
};
}
/**
* 批量优化句子
*/
async perfectBatch(
items: PerfectItem[]
): Promise<PerfectItem[]> {
const total = items.length;
let successCount = 0;
let errorCount = 0;
const results: PerfectItem[] = [];
const batchSize = this.options.concurrency;
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
const promises = batch.map(async (item) => {
try {
const result = await this.perfectOne(item);
results.push(result);
successCount++;
} catch {
errorCount++;
}
const current = Math.min(i + batchSize, total);
const percentage = Math.round((current / total) * 100);
this.options.onProgress({
current,
total,
percentage,
successCount,
errorCount
});
});
await Promise.all(promises);
if (i + batchSize < items.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return results;
}
/**
* 从文件加载句子并优化
*/
async perfectFromFile(
inputPath: string,
outputPath: string
): Promise<{ success: number; failed: number; results: any[] }> {
const data = JSON.parse(readFileSync(inputPath, 'utf-8'));
const sentences = data.sentences || data;
const items: PerfectItem[] = sentences.map((s: any, i: number) => ({
index: s.index || i + 1,
text: s.text || s,
template: s.template || '',
templateType: s.templateType || '',
theme: s.theme || '人生',
tags: s.tags || [],
optimized: ''
}));
const results = await this.perfectBatch(items);
// 合并原始数据与优化结果
const mergedResults = results.map((r, i) => {
return {
index: r.index,
text: r.text,
template: r.template,
templateType: r.templateType,
theme: r.theme,
tags: r.tags,
optimized: r.optimized
};
});
const successResults = results.filter(r => r.optimized !== r.text);
const failedResults = results.filter(r => r.optimized === r.text);
const output = {
meta: {
total: results.length,
success: successResults.length,
failed: failedResults.length,
optimizedAt: new Date().toISOString()
},
sentences: mergedResults
};
writeFileSync(outputPath, JSON.stringify(output, null, 2), 'utf-8');
return {
success: successResults.length,
failed: failedResults.length,
results: mergedResults
};
}
/**
* 设置AI实例
*/
setAI(ai: Kevisual): void {
this.ai = ai;
this.options.ai = ai;
}
}
// ============================================
// 便捷函数
// ============================================
/**
* 快速优化单条句子
*/
export async function quickPerfect(
sentence: string,
theme: string = '人生'
): Promise<string> {
const perfect = new SentencePerfect();
const item: PerfectItem = {
index: 0,
text: sentence,
template: '',
templateType: '',
theme,
tags: [],
optimized: ''
};
const result = await perfect.perfectOne(item);
return result.optimized;
}
/**
* 从JSON文件优化句子
*/
export async function perfectFromJSON(
inputPath: string,
outputPath: string,
options: Partial<PerfectOptions> = {}
): Promise<{ success: number; failed: number }> {
const perfect = new SentencePerfect(options);
const result = await perfect.perfectFromFile(inputPath, outputPath);
return { success: result.success, failed: result.failed };
}
export default SentencePerfect;