3232import org .b3log .latke .repository .jdbc .JdbcRepository ;
3333import org .b3log .latke .service .ServiceException ;
3434import org .b3log .symphony .ai .AIProviderFactory ;
35+ import org .b3log .symphony .ai .OpenAIProvider ;
36+ import org .b3log .symphony .ai .Provider ;
3537import org .b3log .symphony .model .*;
3638import org .b3log .symphony .processor .ApiProcessor ;
3739import org .b3log .symphony .processor .ChatroomProcessor ;
@@ -1089,6 +1091,7 @@ public static void nightDisableCheck() {
10891091 /**
10901092 * 处理 @马库斯 AI 回复
10911093 * 异步调用 AI 生成回复,不阻塞主线程
1094+ * 支持识别消息中的图片
10921095 *
10931096 * @param userName 发送消息的用户名
10941097 * @param content 消息内容
@@ -1121,9 +1124,70 @@ public static void handleAIChat(String userName, String content, String oId) {
11211124 sendBotMsg ("@" + userName + " 你的对话过于频繁,稍候再试吧~" );
11221125 return ;
11231126 }
1124- // 调用 AI 生成回复
1127+
11251128 String systemPrompt = "你是摸鱼派社区的智能助手马库斯,友好、幽默、乐于助人。回复要简洁明了,不要太长。不要在回复中使用@提及任何用户。" ;
1126- String response = AIProviderFactory .chatSync (systemPrompt , question );
1129+ String response ;
1130+
1131+ // 提取 Markdown 图片 URL: 
1132+ java .util .regex .Pattern imgPattern = java .util .regex .Pattern .compile ("!\\ [[^\\ ]]*\\ ]\\ (([^)]+)\\ )" );
1133+ java .util .regex .Matcher imgMatcher = imgPattern .matcher (question );
1134+ List <String > imageUrls = new ArrayList <>();
1135+ while (imgMatcher .find ()) {
1136+ imageUrls .add (imgMatcher .group (1 ));
1137+ }
1138+
1139+ if (!imageUrls .isEmpty ()) {
1140+ // 有图片,使用多模态消息
1141+ // 移除图片标记,保留纯文本问题
1142+ String textQuestion = question .replaceAll ("!\\ [[^\\ ]]*\\ ]\\ ([^)]+\\ )" , "" ).trim ();
1143+ if (textQuestion .isEmpty ()) {
1144+ textQuestion = "请描述这张图片" ;
1145+ }
1146+
1147+ LOGGER .log (Level .INFO , "Processing image chat for user: {}, images: {}, question: {}" ,
1148+ userName , imageUrls .size (), textQuestion );
1149+
1150+ // 构建多模态内容
1151+ List <Provider .ContentType > contentTypes = new ArrayList <>();
1152+ contentTypes .add (new Provider .ContentType .Text (textQuestion ));
1153+ for (String imageUrl : imageUrls ) {
1154+ LOGGER .log (Level .INFO , "Adding image URL: {}" , imageUrl );
1155+ contentTypes .add (new Provider .ContentType .Image (imageUrl , "image/jpeg" ));
1156+ }
1157+
1158+ var messages = OpenAIProvider .Message .of (
1159+ new OpenAIProvider .Message .System (systemPrompt ),
1160+ new OpenAIProvider .Message .User (new Provider .Content .Array (contentTypes ))
1161+ );
1162+
1163+ // 使用自定义消息调用 AI
1164+ var sb = new StringBuilder ();
1165+ var provider = AIProviderFactory .createProvider (messages );
1166+ AIProviderFactory .send (provider ).forEach (json -> {
1167+ LOGGER .log (Level .DEBUG , "AI response chunk: {}" , json .toString ());
1168+ var choices = json .optJSONArray ("choices" );
1169+ if (choices != null && choices .length () > 0 ) {
1170+ var delta = choices .getJSONObject (0 ).optJSONObject ("delta" );
1171+ if (delta != null ) {
1172+ sb .append (delta .optString ("content" , "" ));
1173+ }
1174+ var message = choices .getJSONObject (0 ).optJSONObject ("message" );
1175+ if (message != null ) {
1176+ sb .append (message .optString ("content" , "" ));
1177+ }
1178+ }
1179+ // 检查是否有错误信息
1180+ if (json .has ("error" )) {
1181+ LOGGER .log (Level .ERROR , "AI API error: {}" , json .optJSONObject ("error" ));
1182+ }
1183+ });
1184+ response = sb .toString ();
1185+ LOGGER .log (Level .INFO , "AI image response length: {}" , response .length ());
1186+ } else {
1187+ // 无图片,使用普通文本对话
1188+ response = AIProviderFactory .chatSync (systemPrompt , question );
1189+ }
1190+
11271191 if (response != null && !response .isEmpty ()) {
11281192 // 清理 AI 回复中可能的 @用户名,避免重复艾特
11291193 response = response .replaceAll ("^@[a-zA-Z0-9_\\ -]+\\ s*" , "" ).trim ();
@@ -1134,9 +1198,12 @@ public static void handleAIChat(String userName, String content, String oId) {
11341198 + "##### 引用 @" + userName + " [↩](" + Latkes .getServePath () + "/cr#chatroom" + oId + " \" 跳转至原消息\" ) \n "
11351199 + quotedContent ;
11361200 sendBotMsg (replyMsg );
1201+ } else {
1202+ LOGGER .log (Level .WARN , "AI returned empty response for user: " + userName );
11371203 }
11381204 } catch (Exception e ) {
11391205 LOGGER .log (Level .ERROR , "AI chat failed for user: " + userName , e );
1206+ sendBotMsg ("@" + userName + " 抱歉,AI 处理失败:" + e .getMessage ());
11401207 }
11411208 });
11421209 }
0 commit comments