From 79d34f17c5bec4fcb140bb3f5ebe707987f1e092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E6=B5=B7=E6=B4=8B?= Date: Sun, 24 May 2026 11:04:24 +0800 Subject: [PATCH] AI --- routes/ai.js | 119 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 42 deletions(-) diff --git a/routes/ai.js b/routes/ai.js index 644927a..4f08cd6 100644 --- a/routes/ai.js +++ b/routes/ai.js @@ -3,10 +3,36 @@ const fetch = require('node-fetch'); const router = new Router(); -// NVIDIA API 配置 +// NVIDIA API 配置(NVCF 云 API) const NVIDIA_API_KEY = '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'; const NVIDIA_API_URL = 'https://integrate.api.nvidia.com/v1/chat/completions'; +// 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 }, +]; + +// 获取随机 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 { @@ -41,59 +67,68 @@ router.post('/generate-product', async (ctx) => { "suggestedPrice": 建议售价(数字) }`; - // 调用 NVIDIA API - 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 - }) - }); - - 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; - - // 解析 JSON 响应 let productInfo; + let useMock = false; + try { - // 清理响应文本,只保留 JSON 部分 + // 调用 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: 60000 // 60秒超时 + }); + + 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) { + console.log('API 返回为空'); + throw new Error('API 返回为空'); + } + + // 解析 JSON 响应 const jsonMatch = aiResponse.match(/\{[\s\S]*\}/); if (jsonMatch) { productInfo = JSON.parse(jsonMatch[0]); } else { + console.log('无法解析 JSON'); throw new Error('无法解析 AI 响应'); } - } catch (parseError) { - console.error('JSON 解析失败:', aiResponse); - // 如果解析失败,提供默认值 - productInfo = { - name: keywords || '新商品', - category: '其他', - description: '商品描述', - suggestedPrice: 0 - }; + + } catch (apiError) { + console.error('NVIDIA API 调用异常:', apiError.message); + console.log('切换到 Mock 模式'); + useMock = true; + } + + // 使用 Mock 数据作为备用 + if (useMock) { + productInfo = getMockProduct(keywords); } ctx.body = { code: 200, - message: '生成成功', + message: useMock ? '使用模拟数据生成' : '生成成功', data: productInfo };