145 lines
4.2 KiB
JavaScript
145 lines
4.2 KiB
JavaScript
require('dotenv').config();
|
|
const { OpenAI } = require('openai');
|
|
const db = require('./db');
|
|
|
|
const openai = new OpenAI({
|
|
apiKey: process.env.OPENAI_API_KEY,
|
|
});
|
|
|
|
async function getAiSuggestion(item) {
|
|
try {
|
|
const imageUrl = item.detail_response.image ? item.detail_response.image.imageUrl : null;
|
|
|
|
const prompt = `
|
|
ROLE:
|
|
Bạn là chuyên gia kiểm định listing eBay dựa trên dữ liệu + hình ảnh sản phẩm.
|
|
|
|
MỤC TIÊU:
|
|
Đánh giá độ tin cậy của listing dựa trên:
|
|
- Độ khớp giữa HÌNH ẢNH và THÔNG TIN
|
|
- Độ uy tín của seller
|
|
- Độ hợp lý tổng thể (price / data consistency)
|
|
|
|
INPUT:
|
|
|
|
[SEARCH TARGET]
|
|
- Part Number: ${item.partNumber || "N/A"}
|
|
- Expected Specs: ${item.specs || "N/A"}
|
|
|
|
[EBAY DATA]
|
|
- Title: ${item.title}
|
|
- Price: ${item.price}
|
|
- Seller: ${item.detail_response?.seller?.username}
|
|
- Feedback Score: ${item.detail_response?.seller?.feedbackScore}
|
|
- Positive %: ${item.detail_response?.seller?.feedbackPercent}
|
|
|
|
[DETAIL DATA]
|
|
- Brand: ${item.detail_response?.brand || "N/A"}
|
|
- Aspects: ${JSON.stringify(item.detail_response?.localizedAspects || {})}
|
|
|
|
TASK (QUAN TRỌNG):
|
|
Thực hiện các bước sau (ngầm, không output):
|
|
1. Nếu có ảnh:
|
|
- OCR label / text chính (model, part number, specs)
|
|
- So sánh với Title + Aspects
|
|
2. Check mismatch:
|
|
- Sai model / sai part number / sai specs
|
|
- Ảnh không liên quan (stock image / generic)
|
|
3. Đánh giá seller:
|
|
- Feedback < 95% hoặc score thấp => rủi ro
|
|
4. Đánh giá tổng thể:
|
|
- Consistency + seller + price
|
|
|
|
OUTPUT RULE (BẮT BUỘC):
|
|
- Chỉ 1 câu duy nhất kèm số điểm đánh giá từ 1-10 với độ khớp
|
|
- Không markdown, không xuống dòng
|
|
- Không giải thích dài
|
|
- Format:
|
|
|
|
Nếu tốt:
|
|
"Hãy mua, dữ liệu và hình ảnh khớp, seller uy tín. (Điểm: {{điểm}})"
|
|
|
|
Nếu có rủi ro:
|
|
"Cẩn thận, {{lý do chính ngắn gọn}}. (Điểm: {{điểm}})"
|
|
|
|
Nếu rất tệ:
|
|
"Không nên mua, {{lý do rõ ràng}}. (Điểm: {{điểm}})"
|
|
|
|
Ví dụ lý do:
|
|
- label không khớp title
|
|
- sai part number
|
|
- ảnh generic / không phải sản phẩm thật
|
|
- seller feedback thấp
|
|
|
|
OUTPUT:
|
|
`;
|
|
console.log(prompt);
|
|
const messages = [
|
|
{ role: "system", content: "Bạn là trợ lý AI chuyên thẩm định eBay bằng hình ảnh và dữ liệu. Chỉ trả về 1 câu kết luận ngắn gọn." }
|
|
];
|
|
|
|
if (imageUrl) {
|
|
messages.push({
|
|
role: "user",
|
|
content: [
|
|
{ type: "text", text: prompt },
|
|
{ type: "image_url", image_url: { url: imageUrl, detail: "high" } }
|
|
]
|
|
});
|
|
} else {
|
|
messages.push({ role: "user", content: prompt });
|
|
}
|
|
|
|
const response = await openai.chat.completions.create({
|
|
model: "gpt-4o-mini",
|
|
messages: messages,
|
|
max_tokens: 150,
|
|
temperature: 0.2
|
|
});
|
|
|
|
return {
|
|
suggestion: response.choices[0].message.content.trim(),
|
|
usage: response.usage.total_tokens
|
|
};
|
|
} catch (error) {
|
|
console.error(`AI Error for item ${item.id}:`, error.message);
|
|
return { suggestion: "Lỗi khi gọi AI.", usage: 0 };
|
|
}
|
|
}
|
|
|
|
async function runAiSuggestions() {
|
|
console.log("Bat dau chay AI Suggestions...");
|
|
const items = db.getMissingAiSuggestionItems();
|
|
console.log(`Tim thay ${items.length} item can check AI.`);
|
|
|
|
let totalTokens = 0;
|
|
const batchSize = 10;
|
|
for (let i = 0; i < items.length; i += batchSize) {
|
|
const batch = items.slice(i, i + batchSize);
|
|
const results = await Promise.all(batch.map(async item => {
|
|
console.log(`Dang check AI cho item: ${item.id}`);
|
|
const { suggestion, usage } = await getAiSuggestion(item);
|
|
db.updateAiSuggestion(item.id, suggestion);
|
|
console.log(`Ket qua AI cho ${item.id}: ${suggestion} (Tokens: ${usage})`);
|
|
return usage;
|
|
}));
|
|
totalTokens += results.reduce((a, b) => a + b, 0);
|
|
// Minimal delay between batches to respect rate limits
|
|
if (i + batchSize < items.length) {
|
|
await new Promise(r => setTimeout(r, 500));
|
|
}
|
|
}
|
|
console.log(`Hoan thanh AI Suggestions. Total tokens: ${totalTokens}`);
|
|
return totalTokens;
|
|
}
|
|
|
|
module.exports = {
|
|
runAiSuggestions,
|
|
getAiSuggestion
|
|
};
|
|
|
|
// Allow standalone run
|
|
if (require.main === module) {
|
|
runAiSuggestions().catch(console.error);
|
|
}
|