import { NextResponse } from 'next/server'; import { db } from '@/drizzle/db'; import { promptOptimizations, userSettings } from '@/drizzle/schema'; import { eq } from 'drizzle-orm'; import { getCurrentUser } from '@/lib/auth'; import { decryptApiKey } from '@/lib/crypto'; // 简洁版系统提示词 const CONCISE_SYSTEM_PROMPT = `你是一个提示词优化专家。用户会给你一个原始的想法或问题,请帮助优化成简洁明了的提示词。 要求: 1. 保持核心意图不变 2. 去除冗余和模糊的表达 3. 使用清晰、准确的语言 4. 输出应该简短精炼(不超过150字) 5. 直接输出优化后的提示词,不要解释或添加其他内容`; // 详细版系统提示词 const DETAILED_SYSTEM_PROMPT = `你是一个提示词优化专家。用户会给你一个原始的想法或问题,请帮助优化成结构化的详细提示词。 优化后的提示词应包含以下要素(根据实际情况选择): 1. **任务目标**:明确说明要完成什么 2. **背景上下文**:提供必要的背景信息 3. **具体要求**:列出详细的要求和约束 4. **输出格式**:说明期望的输出格式 5. **示例**(如有必要):提供参考示例 要求: - 使用清晰的结构和层次 - 语言准确、专业 - 保持原始意图的完整性 - 直接输出优化后的提示词,不要解释或添加额外的说明文字`; // 规范化 URL function normalizeBaseUrl(url: string): string { return url.replace(/\/+$/, ''); } // POST /api/prompt/optimize - 优化提示词 export async function POST(request: Request) { try { // 获取当前用户 const user = await getCurrentUser(); if (!user) { return NextResponse.json( { error: '请先登录' }, { status: 401 } ); } const body = await request.json(); const { originalPrompt, mode } = body; if (!originalPrompt || !mode) { return NextResponse.json( { error: '缺少必要参数' }, { status: 400 } ); } if (!['concise', 'detailed'].includes(mode)) { return NextResponse.json( { error: '无效的优化模式' }, { status: 400 } ); } // 获取用户设置 const settings = await db.query.userSettings.findFirst({ where: eq(userSettings.userId, user.userId), }); if (!settings?.cchApiKey) { return NextResponse.json( { error: '请先在设置中配置 API Key' }, { status: 400 } ); } // 解密 API Key const apiKey = decryptApiKey(settings.cchApiKey); const cchUrl = settings.cchUrl || process.env.CCH_DEFAULT_URL || 'https://claude.leocoder.cn/'; const apiFormat = (settings.apiFormat as 'claude' | 'openai') || 'claude'; // 选择系统提示词 const systemPrompt = mode === 'concise' ? CONCISE_SYSTEM_PROMPT : DETAILED_SYSTEM_PROMPT; // 调用 AI 进行优化 let optimizedPrompt: string; if (apiFormat === 'openai') { // OpenAI 兼容格式 const response = await fetch(`${normalizeBaseUrl(cchUrl)}/v1/chat/completions`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}`, }, body: JSON.stringify({ model: 'claude-sonnet-4-5-20250929', messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: `请优化以下提示词:\n\n${originalPrompt}` }, ], temperature: 0.7, }), }); if (!response.ok) { const errorText = await response.text(); throw new Error(`API 调用失败: ${errorText}`); } const data = await response.json(); optimizedPrompt = data.choices?.[0]?.message?.content || ''; } else { // Claude 原生格式 const response = await fetch(`${normalizeBaseUrl(cchUrl)}/v1/messages`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', }, body: JSON.stringify({ model: 'claude-sonnet-4-5-20250929', max_tokens: 2048, system: systemPrompt, messages: [ { role: 'user', content: `请优化以下提示词:\n\n${originalPrompt}` }, ], }), }); if (!response.ok) { const errorText = await response.text(); throw new Error(`API 调用失败: ${errorText}`); } const data = await response.json(); optimizedPrompt = data.content?.[0]?.text || ''; } // 清理 标签(如果有) optimizedPrompt = optimizedPrompt.replace(/[\s\S]*?<\/think>/g, '').trim(); // 保存到数据库 await db.insert(promptOptimizations).values({ userId: user.userId, originalPrompt, optimizedPrompt, mode, }); return NextResponse.json({ success: true, optimizedPrompt, }); } catch (error) { console.error('提示词优化失败:', error); return NextResponse.json( { error: error instanceof Error ? error.message : '优化失败,请稍后重试' }, { status: 500 } ); } }