feat: 5级情感分析、日志UI优化、页面链接支持、v1.0.0-b26cea
This commit is contained in:
@@ -47,6 +47,8 @@ public class CommentAiAutopilotPlugin extends BasePlugin {
|
||||
.indexFunc(ext -> ext.getSpec().getSentiment()));
|
||||
indexSpecs.add(IndexSpecs.<AiCommentReply, String>single("spec.published", String.class)
|
||||
.indexFunc(ext -> String.valueOf(ext.getSpec().getPublished())));
|
||||
indexSpecs.add(IndexSpecs.<AiCommentReply, String>single("spec.postKind", String.class)
|
||||
.indexFunc(ext -> ext.getSpec().getPostKind()));
|
||||
});
|
||||
schemeManager.register(AiPersona.class);
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@ public class AiCommentReply extends AbstractExtension {
|
||||
@Schema(description = "关联文章Slug,用于生成文章链接")
|
||||
private String postSlug;
|
||||
|
||||
@Schema(description = "关联内容类型: Post/SinglePage")
|
||||
private String postKind;
|
||||
|
||||
@Schema(description = "AI回复内容")
|
||||
private String reply;
|
||||
|
||||
|
||||
@@ -525,6 +525,7 @@ public class AiReplyOrchestrator {
|
||||
record.getSpec().setCommentId(context.commentId());
|
||||
record.getSpec().setPostId(context.postId());
|
||||
record.getSpec().setPostSlug(context.postSlug());
|
||||
record.getSpec().setPostKind(context.postKind());
|
||||
record.getSpec().setReply("");
|
||||
record.getSpec().setScore(0);
|
||||
record.getSpec().setStatus("PENDING");
|
||||
|
||||
@@ -10,6 +10,7 @@ import run.halo.app.content.ContentWrapper;
|
||||
import run.halo.app.content.PostContentService;
|
||||
import run.halo.app.core.extension.content.Comment;
|
||||
import run.halo.app.core.extension.content.Post;
|
||||
import run.halo.app.core.extension.content.SinglePage;
|
||||
import run.halo.app.core.extension.content.Reply;
|
||||
import run.halo.app.extension.ReactiveExtensionClient;
|
||||
|
||||
@@ -113,7 +114,8 @@ public class ContextExtractor {
|
||||
isAiConversation,
|
||||
formatPostDate(post),
|
||||
commentCount,
|
||||
""
|
||||
"",
|
||||
"Post"
|
||||
))
|
||||
)
|
||||
)
|
||||
@@ -129,7 +131,47 @@ public class ContextExtractor {
|
||||
isAiConversation,
|
||||
"",
|
||||
0,
|
||||
""
|
||||
"",
|
||||
"Post"
|
||||
));
|
||||
}
|
||||
|
||||
if (subjectRef != null && "SinglePage".equals(subjectRef.getKind())) {
|
||||
String postName = subjectRef.getName();
|
||||
return client.fetch(SinglePage.class, postName)
|
||||
.flatMap(singlePage -> getPostContent(postName)
|
||||
.flatMap(content -> getCommentCount(comment.getMetadata().getName())
|
||||
.map(commentCount -> new CommentContext(
|
||||
comment.getMetadata().getName(),
|
||||
postName,
|
||||
singlePage.getSpec().getSlug(),
|
||||
commentContent,
|
||||
commentOwner,
|
||||
singlePage.getSpec().getTitle(),
|
||||
content,
|
||||
null,
|
||||
isAiConversation,
|
||||
formatSinglePageDate(singlePage),
|
||||
commentCount,
|
||||
"",
|
||||
"SinglePage"
|
||||
))
|
||||
)
|
||||
)
|
||||
.defaultIfEmpty(new CommentContext(
|
||||
comment.getMetadata().getName(),
|
||||
postName,
|
||||
"",
|
||||
commentContent,
|
||||
commentOwner,
|
||||
"",
|
||||
"",
|
||||
null,
|
||||
isAiConversation,
|
||||
"",
|
||||
0,
|
||||
"",
|
||||
"SinglePage"
|
||||
));
|
||||
}
|
||||
|
||||
@@ -145,6 +187,7 @@ public class ContextExtractor {
|
||||
isAiConversation,
|
||||
"",
|
||||
0,
|
||||
"",
|
||||
""
|
||||
));
|
||||
}
|
||||
@@ -179,7 +222,8 @@ public class ContextExtractor {
|
||||
isAiConversation,
|
||||
formatPostDate(post),
|
||||
commentCount,
|
||||
history
|
||||
history,
|
||||
"Post"
|
||||
))
|
||||
)
|
||||
)
|
||||
@@ -196,7 +240,49 @@ public class ContextExtractor {
|
||||
isAiConversation,
|
||||
"",
|
||||
0,
|
||||
""
|
||||
"",
|
||||
"Post"
|
||||
));
|
||||
}
|
||||
|
||||
if (subjectRef != null && "SinglePage".equals(subjectRef.getKind())) {
|
||||
String postName = subjectRef.getName();
|
||||
return client.fetch(SinglePage.class, postName)
|
||||
.flatMap(singlePage -> getPostContent(postName)
|
||||
.flatMap(content -> getCommentCount(commentName)
|
||||
.flatMap(commentCount -> historyMono
|
||||
.map(history -> new CommentContext(
|
||||
commentName,
|
||||
postName,
|
||||
singlePage.getSpec().getSlug(),
|
||||
replyContent,
|
||||
replyOwner,
|
||||
singlePage.getSpec().getTitle(),
|
||||
content,
|
||||
replyName,
|
||||
isAiConversation,
|
||||
formatSinglePageDate(singlePage),
|
||||
commentCount,
|
||||
history,
|
||||
"SinglePage"
|
||||
))
|
||||
)
|
||||
)
|
||||
)
|
||||
.defaultIfEmpty(new CommentContext(
|
||||
commentName,
|
||||
postName,
|
||||
"",
|
||||
replyContent,
|
||||
replyOwner,
|
||||
"",
|
||||
"",
|
||||
replyName,
|
||||
isAiConversation,
|
||||
"",
|
||||
0,
|
||||
"",
|
||||
"SinglePage"
|
||||
));
|
||||
}
|
||||
|
||||
@@ -213,7 +299,8 @@ public class ContextExtractor {
|
||||
isAiConversation,
|
||||
"",
|
||||
0,
|
||||
history
|
||||
history,
|
||||
""
|
||||
));
|
||||
}
|
||||
|
||||
@@ -290,6 +377,18 @@ public class ContextExtractor {
|
||||
return "";
|
||||
}
|
||||
|
||||
private String formatSinglePageDate(SinglePage singlePage) {
|
||||
var publishTime = singlePage.getSpec().getPublishTime();
|
||||
if (publishTime != null) {
|
||||
return publishTime.toString().substring(0, 10);
|
||||
}
|
||||
var creationTimestamp = singlePage.getMetadata().getCreationTimestamp();
|
||||
if (creationTimestamp != null) {
|
||||
return creationTimestamp.toString().substring(0, 10);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private Mono<Integer> getCommentCount(String commentName) {
|
||||
return client.list(Reply.class,
|
||||
reply -> commentName.equals(reply.getSpec().getCommentName()),
|
||||
@@ -311,6 +410,7 @@ public class ContextExtractor {
|
||||
boolean isAiConversation,
|
||||
String postDate,
|
||||
int commentCount,
|
||||
String conversationHistory
|
||||
String conversationHistory,
|
||||
String postKind
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -142,8 +142,10 @@ public class PromptBuilder {
|
||||
return prompt;
|
||||
}
|
||||
String sentimentHint = switch (sentiment) {
|
||||
case "VERY_POSITIVE" -> "\n\n【情感提示】评论者情绪非常正面积极,请用热情洋溢的语气回复,表达真诚的感谢和共鸣。";
|
||||
case "POSITIVE" -> "\n\n【情感提示】评论者情绪正面积极,请用热情友好的语气回复,可以表达感谢和共鸣。";
|
||||
case "NEGATIVE" -> "\n\n【情感提示】评论者情绪偏负面,请用理性温和的语气回复,避免激化矛盾,展现理解和包容。";
|
||||
case "VERY_NEGATIVE" -> "\n\n【情感提示】评论者情绪非常负面,请用非常温和、理性的语气回复,避免任何可能激化矛盾的表达,展现充分的理解和耐心。";
|
||||
default -> "";
|
||||
};
|
||||
return prompt + sentimentHint;
|
||||
|
||||
@@ -17,13 +17,17 @@ public class SentimentService {
|
||||
}
|
||||
|
||||
public record SentimentResult(String sentiment, double confidence) {
|
||||
public static final String VERY_POSITIVE = "VERY_POSITIVE";
|
||||
public static final String POSITIVE = "POSITIVE";
|
||||
public static final String NEUTRAL = "NEUTRAL";
|
||||
public static final String NEGATIVE = "NEGATIVE";
|
||||
public static final String VERY_NEGATIVE = "VERY_NEGATIVE";
|
||||
}
|
||||
|
||||
private static final List<String> CHOICES = List.of(
|
||||
SentimentResult.POSITIVE, SentimentResult.NEUTRAL, SentimentResult.NEGATIVE
|
||||
SentimentResult.VERY_POSITIVE, SentimentResult.POSITIVE,
|
||||
SentimentResult.NEUTRAL, SentimentResult.NEGATIVE,
|
||||
SentimentResult.VERY_NEGATIVE
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -31,7 +35,15 @@ public class SentimentService {
|
||||
* ({@code OutputSpec.choice}) for reliable classification.
|
||||
*/
|
||||
public Mono<SentimentResult> analyzeSentiment(String commentContent, String modelName) {
|
||||
String systemPrompt = "你是一个情感分析助手。请分析评论的情感倾向,只返回 POSITIVE、NEUTRAL 或 NEGATIVE 之一。";
|
||||
String systemPrompt = "你是一个专业的情感分析助手。请根据以下标准分析评论的情感倾向:\n"
|
||||
+ "\n"
|
||||
+ "- VERY_POSITIVE:非常正面,包含强烈的感谢、赞美或认同(如\"太棒了\"、\"非常感谢\"、\"写得太好了\")\n"
|
||||
+ "- POSITIVE:正面,友好、肯定或支持的态度(如\"不错\"、\"学习了\"、\"支持\")\n"
|
||||
+ "- NEUTRAL:中性,提问、讨论、陈述事实,无明显情感倾向(如\"请问...\"、\"这个怎么用\"、\"我觉得\")\n"
|
||||
+ "- NEGATIVE:负面,不满、质疑或批评(如\"不好用\"、\"有问题\"、\"不太行\")\n"
|
||||
+ "- VERY_NEGATIVE:非常负面,攻击、辱骂或极端负面情绪(如\"垃圾\"、\"骗子\"、\"太差了\")\n"
|
||||
+ "\n"
|
||||
+ "只返回 VERY_POSITIVE、POSITIVE、NEUTRAL、NEGATIVE 或 VERY_NEGATIVE 之一。";
|
||||
String userPrompt = "分析以下评论的情感倾向:\n\n" + commentContent;
|
||||
|
||||
return aiFoundationClient.classify(systemPrompt, userPrompt, CHOICES, modelName)
|
||||
|
||||
@@ -30,4 +30,4 @@ spec:
|
||||
url: "https://github.com/sunny-335/plugin-comment-ai-autopilot/blob/main/LICENSE"
|
||||
settingName: "comment-ai-autopilot-settings"
|
||||
configMapName: "comment-ai-autopilot-configmap"
|
||||
version: "1.0.0-beta.3"
|
||||
version: "1.0.0-b26cea"
|
||||
|
||||
Reference in New Issue
Block a user