This commit is contained in:
董海洋
2026-05-24 21:07:51 +08:00
parent 1e583dc1a3
commit 970c00001b
+44 -12
View File
@@ -150,7 +150,7 @@ router.post('/recognize-product', async (ctx) => {
const imageUrl = `data:image/jpeg;base64,${imageBase64}`; const imageUrl = `data:image/jpeg;base64,${imageBase64}`;
console.log('Calling Qwen API with image...'); console.log('Calling Qwen Omni API with image...');
const response = await fetch(AI_API_URL, { const response = await fetch(AI_API_URL, {
method: 'POST', method: 'POST',
headers: { headers: {
@@ -158,7 +158,7 @@ router.post('/recognize-product', async (ctx) => {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },
body: JSON.stringify({ body: JSON.stringify({
model: 'qwen3.7-max-2026-05-20', model: 'qwen3.5-omni-flash',
messages: [ messages: [
{ {
role: 'user', role: 'user',
@@ -176,17 +176,20 @@ router.post('/recognize-product', async (ctx) => {
] ]
} }
], ],
modalities: ['text'],
temperature: 0.3, temperature: 0.3,
max_tokens: 500 max_tokens: 500,
stream: true,
stream_options: { include_usage: true }
}), }),
timeout: 60000 timeout: 60000
}); });
console.log('Qwen VL response status:', response.status); console.log('Qwen Omni response status:', response.status);
if (!response.ok) { if (!response.ok) {
const errorText = await response.text(); const errorText = await response.text();
console.error('Qwen VL API Error:', response.status, errorText); console.error('Qwen Omni API Error:', response.status, errorText);
let errorMsg = 'AI 服务调用失败'; let errorMsg = 'AI 服务调用失败';
if (response.status === 401) { if (response.status === 401) {
@@ -209,9 +212,26 @@ router.post('/recognize-product', async (ctx) => {
return; return;
} }
const data = await response.json(); // 解析 SSE 流式响应
console.log('Qwen response data:', JSON.stringify(data, null, 2)); const text = await response.text();
const aiResponse = data.choices?.[0]?.message?.content; const lines = text.split('\n');
let aiResponse = '';
for (const line of lines) {
if (line.startsWith('data: ')) {
const dataStr = line.slice(6).trim();
if (dataStr === '[DONE]') break;
try {
const parsed = JSON.parse(dataStr);
const content = parsed.choices?.[0]?.delta?.content;
if (content) {
aiResponse += content;
}
} catch (e) {
// 跳过解析失败的行
}
}
}
if (!aiResponse) { if (!aiResponse) {
ctx.status = 500; ctx.status = 500;
@@ -222,8 +242,22 @@ router.post('/recognize-product', async (ctx) => {
return; return;
} }
const jsonMatch = aiResponse.match(/\{[\s\S]*\}/); // 尝试提取 JSON(可能被 markdown 代码块包裹)
if (!jsonMatch) { let jsonStr = aiResponse;
const mdMatch = aiResponse.match(/```(?:json)?\s*([\s\S]*?)```/);
if (mdMatch) {
jsonStr = mdMatch[1].trim();
} else {
const jsonMatch = aiResponse.match(/\{[\s\S]*\}/);
if (jsonMatch) {
jsonStr = jsonMatch[0];
}
}
let productInfo;
try {
productInfo = JSON.parse(jsonStr);
} catch (e) {
ctx.status = 500; ctx.status = 500;
ctx.body = { ctx.body = {
code: 500, code: 500,
@@ -232,8 +266,6 @@ router.post('/recognize-product', async (ctx) => {
return; return;
} }
const productInfo = JSON.parse(jsonMatch[0]);
ctx.body = { ctx.body = {
code: 200, code: 200,
message: '识别成功', message: '识别成功',