diff --git a/server/app/api/controller/CommunityController.php b/server/app/api/controller/CommunityController.php index 6fc811c..057d25c 100644 --- a/server/app/api/controller/CommunityController.php +++ b/server/app/api/controller/CommunityController.php @@ -892,9 +892,19 @@ class CommunityController extends BaseApiController $result = AiService::analyzeLotteryPostImages($post->content ?: '', $images); if (empty($result['success']) || empty($result['content'])) { - return [ - 'success' => false, - 'error' => (string) ($result['error'] ?? '帖子图片分析失败'), + $fallbackContent = $this->buildLiuheImageAnalysisFallback($images, (string) ($result['error'] ?? '')); + if ($fallbackContent === '') { + return [ + 'success' => false, + 'error' => (string) ($result['error'] ?? '帖子图片分析失败'), + ]; + } + + $result = [ + 'success' => true, + 'content' => $fallbackContent, + 'tokens' => 0, + 'cost_ms' => (int) ($result['cost_ms'] ?? 0), ]; } @@ -912,6 +922,26 @@ class CommunityController extends BaseApiController return ['success' => true, 'ext' => $ext, 'from_cache' => false]; } + private function buildLiuheImageAnalysisFallback(array $images, string $error): string + { + $error = trim($error); + $isTimeout = $error !== '' && (stripos($error, 'timed out') !== false + || stripos($error, 'timeout') !== false + || stripos($error, 'cURL错误') !== false); + if (!$isTimeout) { + return ''; + } + + $lines = [ + '图片已下载并替换为站内链接,但视觉模型在限定时间内未返回完整识别结果。', + '当前可确认信息:帖子包含 ' . count($images) . ' 张本地化图片,可在原帖图片区域查看。', + '识别状态:图片文字、号码、生肖、波色等细项暂未可靠识别。', + '处理建议:以下分析只能结合帖子文案和图片展示场景进行保守解读,不能视为开奖结果或中奖承诺。', + ]; + + return implode("\n", $lines); + } + private static function buildVirtualAnalysisContent($post, bool $isLottery): string { if ($isLottery) { diff --git a/server/app/common/service/ai/AiService.php b/server/app/common/service/ai/AiService.php index 9810139..4392f71 100644 --- a/server/app/common/service/ai/AiService.php +++ b/server/app/common/service/ai/AiService.php @@ -351,21 +351,13 @@ class AiService $systemPrompt = AiConfig::getVal( 'community_lottery_image_analysis_prompt', - '你是彩票图片内容分析助手。只允许依据当前帖子图片和帖子文案中直接给出的当期信息进行分析。' - . '不要引用往期内容、历史期数、知识库信息或你自己的记忆。' - . '如果图片里没有明确展示某项信息,就直接说明无法判断。' - . '请先对图片内容做去噪过滤,只保留与当期分析直接相关的信息。' - . '有效信息包括:期号、号码、波色、单双、大小、生肖、五行、推荐组合、胆码拖码、走势箭头、统计表、图表结论、明确的标题结论。' - . '无关噪音包括:装饰背景、边框花纹、吉祥话、宣传口号、重复标题、水印、无关广告、联系方式、模板化祝福语、与分析无关的排版符号。' - . '对于重复出现的同一信息,只保留一次并合并描述;对于模糊、遮挡、低置信度识别内容,不要强行分析,可直接标记为“无法可靠识别”。' - . '请先完整识别图片中的号码、期号、版面文字、波色/单双/大小/生肖/五行、图表结论、胆码拖码、推荐组合或其他可见资料。' - . '识别出来的每一项内容,都要单独给出对应分析描述,不能只做整体概括。' - . '如果有多张图片,按图片1、图片2逐张拆开写;每张图片内再按“识别内容1/分析1、识别内容2/分析2”的方式一一对应展开。' - . '输出格式尽量清晰,推荐使用:图片X、过滤后识别内容、逐项分析、综合结论、风险提示。' - . '不要承诺中奖,不要编造图片中不存在的数据,最后给出理性购彩风险提示。' + '你是彩票图片内容快速抽取助手。只提取当前图片中清晰可见的文字、期号、号码、生肖、波色、单双、大小、五行、推荐组合、标题结论等有效信息。' + . '不要做长篇分析,不要引用历史或记忆,不要承诺中奖。' + . '看不清或图片里没有的信息直接写“未识别”。' + . '请按“图片X:有效信息:...;不确定:...”的格式输出,总字数控制在300字以内。' ); $options = self::gptModelOptions([ - 'max_tokens' => 2000, + 'max_tokens' => 600, 'temperature' => 0.3, 'timeout' => self::LOTTERY_POST_IMAGE_TIMEOUT, 'reasoning_effort' => 'low', @@ -374,7 +366,7 @@ class AiService ]); $client = new DeepSeekClient(); - $userMessage = "帖子内容:\n" . ($content ?: '无文字内容') . "\n\n请只依据当前帖子图片和上面的帖子文案输出分析。先过滤掉杂乱和无关内容,再提取图片里的有效信息,最后对提取出的每一项内容一一分析描述,不要补充任何往期推断。"; + $userMessage = "帖子内容:\n" . ($content ?: '无文字内容') . "\n\n请快速抽取图片里的有效信息,只输出可见事实和不确定项,不要展开分析。"; $result = $client->chatWithImages( $systemPrompt, $userMessage,