chore: harden pick object logging

This commit is contained in:
Your Name 2026-05-27 10:58:43 +08:00
parent a1d59e0db8
commit 9e8aa5a543
2 changed files with 28 additions and 9 deletions

View File

@ -1,12 +1,15 @@
import { NextResponse } from "next/server";
import { auth } from "@/app/(auth)/auth";
import { uploadFile } from "@/lib/storage/service";
import { callQwen3Vl } from "@/lib/ai/qwen3-vl";
import { createLogger } from "@/lib/observability/logger";
import { uploadFile } from "@/lib/storage/service";
import sharp from "sharp";
export const runtime = "nodejs";
export const maxDuration = 30;
const logger = createLogger("pick-object");
// 位置词库
const POSITION_OPTIONS = [
'左上区域', '中央顶部', '右上区域',
@ -106,11 +109,12 @@ async function uploadVisionAnalysisImage(buffer: Buffer, filenamePrefix: string)
const { buffer: processedBuffer, ext, width, height } = await downscaleImageForVision(buffer);
const filename = `${filenamePrefix}-${Date.now()}.${ext}`;
const uploaded = await uploadFile(filename, processedBuffer as any);
console.log("[PickObject] 视觉分析图片已缩放:", {
logger.info("vision image prepared", {
originalWidth: width,
originalHeight: height,
maxSide: MAX_VISION_SIDE,
outputExt: ext,
outputBytes: processedBuffer.length,
});
return uploaded.url;
}
@ -172,7 +176,11 @@ export async function POST(request: Request) {
const body: PickObjectRequest = await request.json();
const { imageData, clickX, clickY } = body;
console.log('[PickObject] 收到请求:', { imageDataLength: imageData?.length, clickX, clickY });
logger.info("request received", {
imageDataLength: imageData?.length,
clickX,
clickY,
});
// 验证参数
if (!imageData) {
@ -198,7 +206,7 @@ export async function POST(request: Request) {
const normalizedImage = await normalizeImageInput(imageData);
console.log("[PickObject] 使用硬编码模型: qwen3-vl");
logger.info("vision model selected", { model: "qwen3-vl" });
// 构建 prompt - AI 通过红色标记来识别用户选择的物品
const prompt = `
@ -225,7 +233,7 @@ export async function POST(request: Request) {
${POSITION_OPTIONS.join('、')}
`.trim();
console.log('[PickObject] 调用视觉模型...');
logger.info("vision model call started");
// 调用视觉模型,发送带红色标记的图片
const { text: responseText, model } = await callQwen3Vl({
@ -235,7 +243,10 @@ ${POSITION_OPTIONS.join('、')}
maxTokens: 300,
});
console.log('[PickObject] 模型返回内容:', model, responseText?.substring(0, 200));
logger.info("vision model call completed", {
model,
responseLength: responseText?.length || 0,
});
if (!responseText) {
return NextResponse.json({
@ -287,7 +298,10 @@ ${POSITION_OPTIONS.join('、')}
};
} catch (parseError) {
console.error('[PickObject] JSON parse error:', parseError, 'Content:', responseText);
logger.warn("model response parse failed", {
error: parseError,
responseLength: responseText.length,
});
// 返回默认结果
const posX = clickX < 0.33 ? '左' : clickX > 0.66 ? '右' : '中央';
@ -304,7 +318,11 @@ ${POSITION_OPTIONS.join('、')}
};
}
console.log('[PickObject] 识别结果:', result);
logger.info("object picked", {
nameLength: result.name.length,
position: result.position,
confidence: result.confidence,
});
return NextResponse.json({
success: true,
@ -317,7 +335,7 @@ ${POSITION_OPTIONS.join('、')}
});
} catch (error) {
console.error('[PickObject] Error:', error);
logger.error("pick object failed", error);
return NextResponse.json({
success: false,
error: `识别失败: ${error instanceof Error ? error.message : '未知错误'}`,

View File

@ -31,6 +31,7 @@ const files = [
"app/api/canvas/text-detect/route.ts",
"app/api/canvas/detail-plan/route.ts",
"app/api/scene-fusion/route.ts",
"app/api/pick-object/route.ts",
];
const consolePattern = /\bconsole\.(log|warn|error|info|debug)\b/g;