Files
services/routes/ai.js
T
董海洋 26deb0738d ai
2026-05-24 11:18:31 +08:00

154 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const Router = require('koa-router');
const fetch = require('node-fetch');
const router = new Router();
// NVIDIA API 配置(NVCF 云 API
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 {
const { imageUrl, keywords } = ctx.request.body;
if (!imageUrl && !keywords) {
ctx.status = 400;
ctx.body = {
code: 400,
message: '请提供商品图片或关键词'
};
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 += `
请生成商品的详细信息,返回JSON格式,不要包含其他内容:
{
"name": "商品名称(简洁明了,2-10字)",
"category": "商品分类(请从以下选择:饮料,零食,日用品,食品,烟酒,其他)",
"description": "商品详细描述(50-100字,突出产品特点)",
"suggestedPrice": 建议售价(数字)
}`;
try {
// 调用 NVIDIA NVCF 云 APIOpenAI 兼容格式)
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秒超时
});
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;
}
}
// 使用 Mock 数据
if (useMock) {
productInfo = getMockProduct(keywords);
}
ctx.body = {
code: 200,
message: useMock ? '使用模拟数据生成' : '生成成功',
data: productInfo
};
} catch (error) {
console.error('生成商品信息失败:', error);
ctx.status = 500;
ctx.body = {
code: 500,
message: error.message || '生成失败,请稍后重试'
};
}
});
module.exports = router.routes();