diff --git a/lib/ai/auto-agent-graph.ts b/lib/ai/auto-agent-graph.ts index da6054068..c37234594 100644 --- a/lib/ai/auto-agent-graph.ts +++ b/lib/ai/auto-agent-graph.ts @@ -92,15 +92,19 @@ async function generateAgentConversation( : "用户本轮没有上传图片。"; const systemPrompt = `你是一个真实执行中的 AI 生图/修图 Agent。 -请根据用户需求和分析结果,给出“正在执行前”的简短汇报。 +请根据用户需求和本轮输入图片,给出“执行前”的分析汇报。 要求: -1) 不要说“我无法看到图片”;按系统提供的信息做合理分析。 -2) 必须看起来是本轮真实分析结果,避免空泛套话。 +1) 不要说“我看不到图片”或“无法访问图片”,必须基于给定图片做真实分析。 +2) 语气自然、专业,不要模板腔,不要空话。 3) 不暴露内部实现、模型路由、算法细节。 -4) 输出 4-7 行 Markdown,语气专业自然。 -5) 如果是图像任务,包含以下小节标题:需求理解、分析结论、执行计划、交付说明。 -6) 每一行尽量具体,不要重复。`; +4) 输出 Markdown,控制在 8-14 行。 +5) 有图片时,必须包含以下小节标题且按顺序输出: + - 需求理解 + - 图片分析 + - 执行计划 + - 输出设置 +6) “图片分析”要结合每张参考图差异,给出风格/构图/材质/光影等具体观察。`; const prompt = [ `【用户原始需求】${state.text || "(无文本)"}`, @@ -108,18 +112,43 @@ async function generateAgentConversation( `【图片信息】${imageInfo}`, state.context ? `【画布上下文】${compactText(state.context, 300)}` : "", history ? `【最近对话】\n${history}` : "", - "请输出本轮执行前汇报:", + state.hasImage + ? "请先做本轮图片分析,再输出执行前汇报。" + : "请输出本轮执行前汇报。", ] .filter(Boolean) .join("\n\n"); - const { text } = await generateText({ - model, - system: systemPrompt, - prompt, - temperature: 0.35, - maxTokens: 420, - } as any); + const imageInputs = state.imageUrls + .filter((url) => /^https?:\/\//i.test(url)) + .slice(0, 4) + .map((url) => ({ type: "image" as const, image: url })); + + const requestPayload = state.hasImage && imageInputs.length > 0 + ? { + model, + system: systemPrompt, + messages: [ + { + role: "user" as const, + content: [ + { type: "text" as const, text: prompt }, + ...imageInputs, + ], + }, + ], + temperature: 0.35, + maxTokens: 520, + } + : { + model, + system: systemPrompt, + prompt, + temperature: 0.35, + maxTokens: 420, + }; + + const { text } = await generateText(requestPayload as any); const cleaned = text.trim(); if (cleaned.length < 10) { diff --git a/lib/ai/smart-analyzer.ts b/lib/ai/smart-analyzer.ts index bc05d9b92..091b4c20c 100644 --- a/lib/ai/smart-analyzer.ts +++ b/lib/ai/smart-analyzer.ts @@ -167,7 +167,7 @@ export async function analyzeIntent(params: { // 尝试使用 Qwen3 VL 进行深度分析(传入历史对话) try { - const llmResult = await analyzWithLLM(text, hasImage, historyMessages, context); + const llmResult = await analyzWithLLM(text, hasImage, imageUrls, historyMessages, context); if (llmResult) { console.log("[Smart Analyzer] LLM analysis result:", llmResult); return llmResult; @@ -201,6 +201,7 @@ function quickKeywordMatch(text: string, hasImage: boolean): AnalysisResult { async function analyzWithLLM( text: string, hasImage: boolean, + imageUrls?: string[], historyMessages?: HistoryMessage[], context?: string ): Promise { @@ -254,14 +255,37 @@ ${historyText} console.log("[Smart Analyzer] Calling Qwen3 VL for analysis with", historyMessages?.length || 0, "history messages"); - // 调用模型分析 - const { text: responseText } = await generateText({ - model, - system: ANALYZER_SYSTEM_PROMPT, - prompt: userMessage, - temperature: 0.1, - maxTokens: 300, - } as any); + const visionImages = (imageUrls || []) + .filter((url) => /^https?:\/\//i.test(url)) + .slice(0, 4) + .map((url) => ({ type: "image" as const, image: url })); + + // 调用模型分析(有图时携带图片,确保真实视觉分析) + const requestPayload = hasImage && visionImages.length > 0 + ? { + model, + system: ANALYZER_SYSTEM_PROMPT, + messages: [ + { + role: "user" as const, + content: [ + { type: "text" as const, text: userMessage }, + ...visionImages, + ], + }, + ], + temperature: 0.1, + maxTokens: 360, + } + : { + model, + system: ANALYZER_SYSTEM_PROMPT, + prompt: userMessage, + temperature: 0.1, + maxTokens: 300, + }; + + const { text: responseText } = await generateText(requestPayload as any); // 解析JSON响应 const jsonMatch = responseText.match(/\{[\s\S]*\}/);