1
- // Package aichat OpenAI聊天
1
+ // Package aichat OpenAI聊天和群聊总结
2
2
package aichat
3
3
4
4
import (
5
5
"math/rand"
6
6
"strconv"
7
7
"strings"
8
+ "time"
8
9
9
10
"github.com/fumiama/deepinfra"
10
11
"github.com/fumiama/deepinfra/model"
11
12
"github.com/sirupsen/logrus"
13
+ "github.com/tidwall/gjson"
12
14
13
15
zero "github.com/wdvxdr1123/ZeroBot"
14
16
"github.com/wdvxdr1123/ZeroBot/message"
@@ -18,6 +20,7 @@ import (
18
20
ctrl "github.com/FloatTech/zbpctrl"
19
21
"github.com/FloatTech/zbputils/chat"
20
22
"github.com/FloatTech/zbputils/control"
23
+ "github.com/FloatTech/zbputils/ctxext"
21
24
)
22
25
23
26
var (
30
33
"- 设置AI聊天温度80\n " +
31
34
"- 设置AI聊天接口类型[OpenAI|OLLaMA|GenAI]\n " +
32
35
"- 设置AI聊天(不)支持系统提示词\n " +
33
- "- 设置AI聊天接口地址https://api.deepseek.com /chat/completions\n " +
36
+ "- 设置AI聊天接口地址https://api.siliconflow.cn/v1 /chat/completions\n " +
34
37
"- 设置AI聊天密钥xxx\n " +
35
- "- 设置AI聊天模型名xxx \n " +
38
+ "- 设置AI聊天模型名Qwen/Qwen3-8B \n " +
36
39
"- 查看AI聊天系统提示词\n " +
37
40
"- 重置AI聊天系统提示词\n " +
38
41
"- 设置AI聊天系统提示词xxx\n " +
41
44
"- 设置AI聊天最大长度4096\n " +
42
45
"- 设置AI聊天TopP 0.9\n " +
43
46
"- 设置AI聊天(不)以AI语音输出\n " +
44
- "- 查看AI聊天配置\n " ,
47
+ "- 查看AI聊天配置\n " +
48
+ "- 重置AI聊天\n " +
49
+ "- 群聊总结 [消息数目]|群聊总结 1000\n " ,
45
50
PrivateDataFolder : "aichat" ,
46
51
})
47
52
)
53
58
"GenAI" : 2 ,
54
59
}
55
60
apilist = [3 ]string {"OpenAI" , "OLLaMA" , "GenAI" }
61
+ limit = ctxext .NewLimiterManager (time .Second * 30 , 1 )
56
62
)
57
63
58
64
func init () {
@@ -305,4 +311,93 @@ func init() {
305
311
}
306
312
ctx .SendChain (message .Text (printConfig (rate , temp , cfg )))
307
313
})
314
+ en .OnFullMatch ("重置AI聊天" , ensureconfig , zero .OnlyPrivate , zero .SuperUserPermission ).SetBlock (true ).Handle (func (ctx * zero.Ctx ) {
315
+ chat .Reset ()
316
+ ctx .SendChain (message .Text ("成功" ))
317
+ })
318
+
319
+ // 添加群聊总结功能
320
+ en .OnRegex (`^群聊总结\s?(\d*)$` , ensureconfig , zero .OnlyGroup , zero .AdminPermission ).SetBlock (true ).Limit (limit .LimitByGroup ).Handle (func (ctx * zero.Ctx ) {
321
+ ctx .SendChain (message .Text ("少女思考中..." ))
322
+ p , _ := strconv .ParseInt (ctx .State ["regex_matched" ].([]string )[1 ], 10 , 64 )
323
+ if p > 1000 {
324
+ p = 1000
325
+ }
326
+ if p == 0 {
327
+ p = 200
328
+ }
329
+ gid := ctx .Event .GroupID
330
+ group := ctx .GetGroupInfo (gid , false )
331
+ if group .MemberCount == 0 {
332
+ ctx .SendChain (message .Text (zero .BotConfig .NickName [0 ], "未加入" , group .Name , "(" , gid , "),无法获取摘要" ))
333
+ return
334
+ }
335
+
336
+ var messages []string
337
+
338
+ h := ctx .GetGroupMessageHistory (gid , 0 , p , false )
339
+ h .Get ("messages" ).ForEach (func (_ , msgObj gjson.Result ) bool {
340
+ nickname := msgObj .Get ("sender.nickname" ).Str
341
+ text := strings .TrimSpace (message .ParseMessageFromString (msgObj .Get ("raw_message" ).Str ).ExtractPlainText ())
342
+ if text != "" {
343
+ messages = append (messages , nickname + ": " + text )
344
+ }
345
+ return true
346
+ })
347
+
348
+ if len (messages ) == 0 {
349
+ ctx .SendChain (message .Text ("ERROR: 历史消息为空或者无法获得历史消息" ))
350
+ return
351
+ }
352
+
353
+ // 调用大模型API进行摘要
354
+ summary , err := summarizeMessages (messages )
355
+ if err != nil {
356
+ ctx .SendChain (message .Text ("ERROR: " , err ))
357
+ return
358
+ }
359
+
360
+ var b strings.Builder
361
+ b .WriteString ("群 " )
362
+ b .WriteString (group .Name )
363
+ b .WriteByte ('(' )
364
+ b .WriteString (strconv .FormatInt (gid , 10 ))
365
+ b .WriteString (") 的 " )
366
+ b .WriteString (strconv .FormatInt (p , 10 ))
367
+ b .WriteString (" 条消息总结:\n \n " )
368
+ b .WriteString (summary )
369
+
370
+ // 分割总结内容为多段
371
+ parts := strings .Split (b .String (), "\n \n " )
372
+ msg := make (message.Message , 0 , len (parts ))
373
+ for _ , part := range parts {
374
+ if part != "" {
375
+ msg = append (msg , ctxext .FakeSenderForwardNode (ctx , message .Text (part )))
376
+ }
377
+ }
378
+ if len (msg ) > 0 {
379
+ ctx .Send (msg )
380
+ }
381
+ })
382
+ }
383
+
384
+ // summarizeMessages 调用大模型API进行消息摘要
385
+ func summarizeMessages (messages []string ) (string , error ) {
386
+ // 使用现有的AI配置进行摘要
387
+ x := deepinfra .NewAPI (cfg .API , cfg .Key )
388
+ mod := model .NewOpenAI (
389
+ cfg .ModelName , cfg .Separator ,
390
+ float32 (70 )/ 100 , 0.9 , 4096 ,
391
+ )
392
+
393
+ // 构造摘要请求提示
394
+ summaryPrompt := "请总结这个群聊内容,要求按发言顺序梳理,明确标注每个发言者的昵称,并完整呈现其核心观点、提出的问题、发表的看法或做出的回应,确保不遗漏关键信息,且能体现成员间的对话逻辑和互动关系:\n \n " +
395
+ strings .Join (messages , "\n ---\n " )
396
+
397
+ data , err := x .Request (mod .User (summaryPrompt ))
398
+ if err != nil {
399
+ return "" , err
400
+ }
401
+
402
+ return strings .TrimSpace (data ), nil
308
403
}
0 commit comments