Upload latest code and optimized prompts (v6)

This commit is contained in:
tony
2025-12-14 19:52:54 +08:00
commit f5cb1042ae
42 changed files with 15302 additions and 0 deletions

198
lib/vision-extractor.js Normal file
View File

@@ -0,0 +1,198 @@
/**
* Vision产品特征提取器
* 支持超时重试 + 缓存
*/
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const API_KEY = 'G9rXx3Ag2Xfa7Gs8zou6t6HqeZ';
const API_BASE = 'https://api.wuyinkeji.com/api';
// Vision提取Prompt
const VISION_EXTRACT_PROMPT = `Analyze this pet product image in EXTREME detail.
Output ONLY a valid JSON object (no markdown, no explanation, no thinking):
{
"color": {
"primary": "<hex code like #C3E6E8>",
"name": "<descriptive name like 'ice blue', 'mint green'>",
"secondary": "<accent colors>"
},
"shape": {
"type": "<flower/fan/cone/donut>",
"petal_count": <number of segments>,
"opening": "<C-shaped/full-circle/adjustable>",
"description": "<detailed shape description>"
},
"material": {
"type": "<PU/nylon/polyester/fabric>",
"finish": "<glossy/matte/satin>",
"texture": "<smooth/quilted/padded>"
},
"edge_binding": {
"color": "<color of inner neck edge>",
"material": "<ribbed elastic/fabric>"
},
"closure": {
"type": "<velcro/button/snap>",
"color": "<white/matching>",
"position": "<location description>"
},
"logo": {
"text": "<brand name>",
"style": "<embroidered/printed/tag>",
"position": "<location>"
},
"unique_features": ["<list distinctive features>"],
"overall_description": "<2-3 sentence summary for image generation>"
}`;
/**
* 调用Vision API提取产品特征
* @param {string} imageUrl - 图片URL
* @param {object} options - 配置选项
* @returns {object|null} - 提取的产品特征JSON
*/
async function extractProductFeatures(imageUrl, options = {}) {
const {
maxRetries = 3,
timeout = 120000, // 120秒
retryDelay = 5000,
cacheDir = null,
cacheKey = null
} = options;
// 检查缓存
if (cacheDir && cacheKey) {
const cachePath = path.join(cacheDir, `vision-cache-${cacheKey}.json`);
if (fs.existsSync(cachePath)) {
try {
const cached = JSON.parse(fs.readFileSync(cachePath, 'utf-8'));
if (cached && cached.color) {
console.log(' 📦 使用缓存的Vision结果');
return cached;
}
} catch (e) {
// 缓存无效,继续请求
}
}
}
let lastError = null;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
console.log(` 🔍 Vision分析 (尝试 ${attempt}/${maxRetries})...`);
try {
const response = await axios.post(`${API_BASE}/chat/index`, {
key: API_KEY,
model: 'gemini-3-pro',
content: VISION_EXTRACT_PROMPT,
image_url: imageUrl
}, { timeout });
const content = response.data.data?.choices?.[0]?.message?.content ||
response.data.data?.content;
if (!content) {
throw new Error('Vision响应为空');
}
// 提取JSON跳过thinking部分
let jsonStr = content;
// 如果有<think>标签,跳过它
const thinkEnd = content.indexOf('</think>');
if (thinkEnd !== -1) {
jsonStr = content.substring(thinkEnd + 8);
}
// 提取JSON
const jsonMatch = jsonStr.match(/\{[\s\S]*\}/);
if (jsonMatch) {
const parsed = JSON.parse(jsonMatch[0]);
// 验证必要字段
if (parsed.color && parsed.shape) {
console.log(' ✓ Vision提取成功');
// 保存缓存
if (cacheDir && cacheKey) {
const cachePath = path.join(cacheDir, `vision-cache-${cacheKey}.json`);
fs.writeFileSync(cachePath, JSON.stringify(parsed, null, 2));
}
return parsed;
}
}
throw new Error('无法解析有效的JSON');
} catch (error) {
lastError = error;
console.log(` ⚠️ 尝试 ${attempt} 失败: ${error.message}`);
if (attempt < maxRetries) {
console.log(`${retryDelay/1000}秒后重试...`);
await new Promise(r => setTimeout(r, retryDelay));
}
}
}
console.error(` ❌ Vision提取最终失败: ${lastError?.message}`);
return null;
}
/**
* 将Vision结果转换为Golden Description
*/
function buildGoldenDescription(visionResult, productType = 'pet recovery cone') {
if (!visionResult) {
return `
PRODUCT: ${productType}
- Shape: Soft flower/petal shape with C-shaped opening
- Material: Soft waterproof fabric
- Closure: Velcro strap
- Comfortable design for pets
CRITICAL: Follow the reference image EXACTLY for product shape and color.
`;
}
const r = visionResult;
return `
EXACT PRODUCT APPEARANCE (MUST MATCH REFERENCE IMAGE):
- Shape: ${r.shape?.petal_count || '7-8'}-PETAL ${(r.shape?.type || 'flower').toUpperCase()} shape
- Opening: ${r.shape?.opening || 'C-shaped'} (NOT a full circle)
- Color: ${(r.color?.name || 'ice blue').toUpperCase()} (${r.color?.primary || '#C3E6E8'})
- Material: ${r.material?.finish || 'Soft'} ${r.material?.type || 'waterproof fabric'} with ${r.material?.texture || 'padded'} texture
- Edge binding: ${r.edge_binding?.color || 'Matching color'} ${r.edge_binding?.material || 'ribbed elastic'} around inner neck hole
- Closure: ${r.closure?.color || 'White'} ${r.closure?.type || 'velcro'} on ${r.closure?.position || 'one segment'}
- Logo: "${r.logo?.text || 'TOUCHDOG'}" ${r.logo?.style || 'embroidered'} on ${r.logo?.position || 'one petal'}
UNIQUE FEATURES:
${(r.unique_features || ['Scalloped petal edges', 'Radial stitching', 'Soft padded construction']).map(f => `- ${f}`).join('\n')}
OVERALL: ${r.overall_description || 'A soft, comfortable pet recovery cone with flower-petal design.'}
CRITICAL PROHIBITIONS:
- ❌ NO printed colorful patterns (solid color only unless reference shows otherwise)
- ❌ NO hard plastic transparent cones
- ❌ NO fully circular/closed shapes (must match reference C-opening)
- ❌ NO random brand logos
- ❌ MUST match reference image product EXACTLY
`.trim();
}
module.exports = {
extractProductFeatures,
buildGoldenDescription,
VISION_EXTRACT_PROMPT
};