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 = { 人生: `你是一个智慧的导师。请将以下关于人生的句子优化成一句深刻的人生感悟: 要求: - 语言平实却蕴含智慧 - 让人读后有所触动 - 适合作为人生格言 原句:{{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; 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 { 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 { 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 { 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 = {} ): 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;