diff --git a/routes/ai.js b/routes/ai.js index e25cd29..50f45a8 100644 --- a/routes/ai.js +++ b/routes/ai.js @@ -7,40 +7,6 @@ const router = new Router(); const NVIDIA_API_KEY = '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'; const NVIDIA_API_URL = 'https://integrate.api.nvidia.com/v1/chat/completions'; - -// 启用/禁用 AI API(当网络不可用时设为 false) -const ENABLE_AI_API = false; // 由于服务器网络无法访问 NVIDIA,暂时禁用 - -// Mock 数据(用于测试或网络不可用时) -const mockProducts = [ - { name: '可口可乐', category: '饮料', description: '经典碳酸饮料,清爽解渴,330ml罐装', suggestedPrice: 3.5 }, - { name: '乐事薯片', category: '零食', description: '香脆可口,原味薯片,75g包装', suggestedPrice: 8.9 }, - { name: '维达纸巾', category: '日用品', description: '三层加厚,柔软亲肤,10包家庭装', suggestedPrice: 25.9 }, - { name: '康师傅方便面', category: '食品', description: '红烧牛肉面口味,12桶整箱装', suggestedPrice: 39.9 }, - { name: '农夫山泉', category: '饮料', description: '天然矿泉水,550ml瓶装,12瓶/箱', suggestedPrice: 24.0 }, - { name: '奥利奥饼干', category: '零食', description: '夹心饼干,巧克力口味,388g家庭装', suggestedPrice: 18.9 }, - { name: '旺仔牛奶', category: '饮料', description: '香甜可口,儿童喜爱,245ml罐装', suggestedPrice: 5.5 }, - { name: '益达口香糖', category: '零食', description: '清新口气,薄荷口味,40粒装', suggestedPrice: 12.9 }, - { name: '舒肤佳香皂', category: '日用品', description: '有效除菌,纯白清香,125g', suggestedPrice: 6.9 }, - { name: '金龙鱼食用油', category: '食品', description: '调和油,健康烹饪,1.8L', suggestedPrice: 45.9 }, -]; - -// 获取随机 Mock 数据 -function getMockProduct(keywords) { - let product = mockProducts[Math.floor(Math.random() * mockProducts.length)]; - - if (keywords) { - const keyword = keywords.toLowerCase(); - const matched = mockProducts.find(p => - p.name.toLowerCase().includes(keyword) || - p.category.toLowerCase().includes(keyword) - ); - if (matched) product = matched; - } - - return { ...product }; -} - // 生成商品信息的 API router.post('/generate-product', async (ctx) => { try { @@ -55,22 +21,17 @@ router.post('/generate-product', async (ctx) => { return; } - let productInfo; - let useMock = !ENABLE_AI_API; // 如果禁用 API,直接使用 Mock - - if (!useMock) { - // 构建提示词 - let prompt = '你是一个专业的便利店商品管理助手。'; - - if (imageUrl) { - prompt += `\n请分析这张商品图片:${imageUrl}`; - } - - if (keywords) { - prompt += `\n关键词:${keywords}`; - } - - prompt += ` + let prompt = '你是一个专业的便利店商品管理助手。'; + + if (imageUrl) { + prompt += `\n请分析这张商品图片:${imageUrl}`; + } + + if (keywords) { + prompt += `\n关键词:${keywords}`; + } + + prompt += ` 请生成商品的详细信息,返回JSON格式,不要包含其他内容: { "name": "商品名称(简洁明了,2-10字)", @@ -79,64 +40,64 @@ router.post('/generate-product', async (ctx) => { "suggestedPrice": 建议售价(数字) }`; - try { - // 调用 NVIDIA NVCF 云 API(OpenAI 兼容格式) - const response = await fetch(NVIDIA_API_URL, { - method: 'POST', - headers: { - 'Authorization': `Bearer ${NVIDIA_API_KEY}`, - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - model: 'deepseek-ai/deepseek-v4-pro', - messages: [ - { - role: 'user', - content: prompt - } - ], - temperature: 0.7, - max_tokens: 500 - }), - timeout: 30000 // 30秒超时 - }); + const response = await fetch(NVIDIA_API_URL, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${NVIDIA_API_KEY}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + model: 'deepseek-ai/deepseek-v4-pro', + messages: [ + { + role: 'user', + content: prompt + } + ], + temperature: 0.7, + max_tokens: 500 + }), + timeout: 60000 + }); - if (!response.ok) { - const errorText = await response.text(); - console.error('NVIDIA API Error:', response.status, errorText); - throw new Error(`API 调用失败: ${response.status}`); - } - - const data = await response.json(); - const aiResponse = data.choices?.[0]?.message?.content; - - if (!aiResponse) { - throw new Error('API 返回为空'); - } - - // 解析 JSON 响应 - const jsonMatch = aiResponse.match(/\{[\s\S]*\}/); - if (jsonMatch) { - productInfo = JSON.parse(jsonMatch[0]); - } else { - throw new Error('无法解析 AI 响应'); - } - - } catch (apiError) { - console.error('NVIDIA API 调用异常:', apiError.message); - console.log('切换到 Mock 模式'); - useMock = true; - } + if (!response.ok) { + const errorText = await response.text(); + console.error('NVIDIA API Error:', response.status, errorText); + ctx.status = 502; + ctx.body = { + code: 502, + message: 'AI 服务调用失败,请稍后重试' + }; + return; } - // 使用 Mock 数据 - if (useMock) { - productInfo = getMockProduct(keywords); + const data = await response.json(); + const aiResponse = data.choices?.[0]?.message?.content; + + if (!aiResponse) { + ctx.status = 500; + ctx.body = { + code: 500, + message: 'AI 服务返回为空' + }; + return; } + const jsonMatch = aiResponse.match(/\{[\s\S]*\}/); + if (!jsonMatch) { + ctx.status = 500; + ctx.body = { + code: 500, + message: '无法解析 AI 响应' + }; + return; + } + + const productInfo = JSON.parse(jsonMatch[0]); + ctx.body = { code: 200, - message: useMock ? '使用模拟数据生成' : '生成成功', + message: '生成成功', data: productInfo }; @@ -150,4 +111,4 @@ router.post('/generate-product', async (ctx) => { } }); -module.exports = router.routes(); +module.exports = router.routes(); \ No newline at end of file