7
7
8
8
创建标识:Senparc - 20240524
9
9
10
+ 修改标识:Wang Qian - 20250728
11
+ 修改描述:新增AI对话功能增强特性:
12
+ 1. 新增"lc"命令:支持长对话模式,当对话达到10轮后自动整理记忆并清空历史
13
+ 2. 新增记忆整理功能:在长对话模式下,AI会自动总结对话内容并保存为记忆
14
+ 3. 优化欢迎消息:更新了功能说明,包含新增的命令使用说明
15
+
10
16
----------------------------------------------------------------*/
11
17
12
18
using System ;
@@ -45,6 +51,7 @@ public partial class CustomMessageHandler
45
51
输入“t”可以从多模态进入纯文本对话模式
46
52
输入“img 文字”可以强制生成图片,例如:img 一只猫
47
53
输入“dm”可以关闭Markdown格式输出,使用纯文本回复
54
+ 输入“lc”可以开启长对话模式,开启后,对话每到达最大历史对话轮数(默认10轮)后,会自动整理对话记忆,并清空对话历史,以支持长对话
48
55
49
56
[结果由 AI 生成,仅供参考]" ;
50
57
@@ -118,6 +125,8 @@ private async Task<IResponseMessageBase> AIChatAsync(RequestMessageBase requestM
118
125
bool judgeMultimodel = true ;
119
126
var oldChatStatus = chatStore . Status ;
120
127
128
+
129
+
121
130
if ( requestMessageText . Content . Equals ( "E" , StringComparison . OrdinalIgnoreCase ) )
122
131
{
123
132
prompt = $ "我即将结束对话,请发送一段文字和我告别,并提醒我:输入“AI”可以再次启动对话。";
@@ -172,12 +181,25 @@ private async Task<IResponseMessageBase> AIChatAsync(RequestMessageBase requestM
172
181
173
182
//返回提示
174
183
var responseMessage = base . CreateResponseMessage < ResponseMessageText > ( ) ;
175
- responseMessage . Content = useMarkdown
184
+ responseMessage . Content = useMarkdown
176
185
? "已恢复Markdown格式输出,输入dm可关闭Markdown格式输出"
177
186
: "已关闭Markdown格式输出,使用纯文本回复,输入md可恢复Markdown格式输出" ;
178
187
return responseMessage ;
179
188
}
180
189
190
+ Func < string , bool > longChatFunc = content => requestMessageText . Content . Equals ( content , StringComparison . OrdinalIgnoreCase ) ;
191
+
192
+ // 在对话、暂停状态下、可以切换长对话模式
193
+ if ( chatStore . Status == oldChatStatus && longChatFunc ( "LC" ) )
194
+ {
195
+ chatStore . UseLongChat = chatStore . UseLongChat ? false : true ;
196
+ await UpdateMessageContextAsync ( currentMessageContext , chatStore ) ;
197
+
198
+ var responseMessage = base . CreateResponseMessage < ResponseMessageText > ( ) ;
199
+ responseMessage . Content = chatStore . UseLongChat ? "已开启长对话模式!AI将在对话每到达最大历史对话轮数(默认10轮)后,会自动整理对话记忆,并清空对话历史,再次输入lc以关闭" : "已关闭长对话模式!AI将不再自动整理对话记忆,并清空对话历史,再次输入lc以开启" ;
200
+ return responseMessage ;
201
+ }
202
+
181
203
if ( chatStore . Status == oldChatStatus && chatStore . MultimodelType == MultimodelType . SimpleChat ) // 在文字对话的状态下,才能切换到多模态对话
182
204
{
183
205
if ( requestMessageText . Content . Equals ( "M" , StringComparison . OrdinalIgnoreCase ) )
@@ -421,8 +443,16 @@ private async Task TextChatAsync(string prompt, ChatStore chatStore, bool storeH
421
443
//最大保存 AI 对话记录数
422
444
var maxHistoryCount = 10 ;
423
445
424
- //默认 SystemMessage(可根据自己需要修改)
425
- var systemMessage = Senparc . AI . DefaultSetting . DEFAULT_SYSTEM_MESSAGE ;
446
+ //如果是长对话模式,那么调用整理记忆函数,如果整理了记忆,那么使用整理后的记忆,则否则使用默认系统消息
447
+ //在长对话模式情况下,如果还没有整理过记忆,那么返回值会是null,此时会使用默认系统消息
448
+ //默认系统消息可以自己设置,也可以使用Senparc.AI.DefaultSetting.DEFAULT_SYSTEM_MESSAGE
449
+ var systemMessage = chatStore . UseLongChat ?
450
+ await ConsolidateMemoryAsync ( chatStore , chatStore . LastStoredPrompt ) ?? Senparc . AI . DefaultSetting . DEFAULT_SYSTEM_MESSAGE
451
+ :
452
+ Senparc . AI . DefaultSetting . DEFAULT_SYSTEM_MESSAGE ;
453
+
454
+ //更新上一次prompt
455
+ chatStore . LastStoredPrompt = prompt ;
426
456
427
457
var aiHandler = new SemanticAiHandler ( setting ) ;
428
458
var iWantToRun = aiHandler . ChatConfig ( parameter ,
@@ -505,5 +535,70 @@ public async Task<bool> JudgeMultimodel(RequestMessageText requestMessageText, C
505
535
}
506
536
return false ;
507
537
}
538
+
539
+ /// <summary>
540
+ /// 整理记忆的方法
541
+ /// </summary>
542
+ /// <param name="chatStore"></param>
543
+ /// <returns></returns>
544
+ private async Task < string > ConsolidateMemoryAsync ( ChatStore chatStore , string prompt )
545
+ {
546
+ var assistantMessageCount = chatStore . History . Count ( h => h . Role == AuthorRole . Assistant ) ;
547
+
548
+ //这里不进行是否使用长对话模式判断,因为判断是在TextChatAsync中进行的
549
+ //如果AI消息条数大于等于9,则整理记忆,这里是9是因为Senparc.AI的消息最大条数处理逻辑稍有问题,所以暂时设置为9
550
+ if ( assistantMessageCount >= 9 )
551
+ {
552
+ var memoryPrompt = @"
553
+ 请用简洁的语言总结:
554
+ 1. 用户的主要需求或关注点
555
+ 2. 重要的偏好或习惯
556
+ 3. 关键的信息点
557
+ 4. 之前聊天的内容
558
+ " ;
559
+ /* 模型配置
560
+ * 注意:需要在 appsettings.json 中的 <SenparcAiSetting> 节点配置 AI 模型参数,否则无法使用 AI 能力
561
+ */
562
+ var setting = ( SenparcAiSetting ) Senparc . AI . Config . SenparcAiSetting ; //也可以留空,将自动获取
563
+
564
+ //模型请求参数
565
+ var parameter = new PromptConfigParameter ( )
566
+ {
567
+ MaxTokens = 2000 ,
568
+ Temperature = 0.3 ,
569
+ TopP = 0.3 ,
570
+ } ;
571
+
572
+ //最大保存 AI 对话记录数
573
+ var maxHistoryCount = 10 ;
574
+
575
+ //使用上一轮的记忆作为SystemMessage
576
+ var systemMessage = chatStore . LastStoredMemory == null ? Senparc . AI . DefaultSetting . DEFAULT_SYSTEM_MESSAGE : chatStore . LastStoredMemory ;
577
+
578
+ var aiHandler = new SemanticAiHandler ( setting ) ;
579
+ var iWantToRun = aiHandler . ChatConfig ( parameter ,
580
+ userId : "Jeffrey" ,
581
+ maxHistoryStore : maxHistoryCount ,
582
+ chatSystemMessage : systemMessage ,
583
+ senparcAiSetting : setting ) ;
584
+
585
+ //注入历史记录(也可以把 iWantToRun 对象缓存起来,其中会自动包含 history,不需要每次读取或者保存)
586
+ iWantToRun . StoredAiArguments . Context [ "history" ] = chatStore . GetChatHistory ( ) ; // AIKernl 的 history 为 ChatHistory 类型
587
+
588
+ var result = await aiHandler . ChatAsync ( iWantToRun , memoryPrompt ) ;
589
+
590
+ var memory = "用户之前的对话被概括为" + result . OutputString + "\n 5.用户最近一次提问的内容是:" + prompt ;
591
+
592
+ //更新chatStore中的上一轮记忆
593
+ chatStore . LastStoredMemory = memory ;
594
+
595
+ //清空历史记录
596
+ chatStore . ClearHistory ( ) ;
597
+ return memory ;
598
+ }
599
+ else return chatStore . LastStoredMemory ;
600
+
601
+
602
+ }
508
603
}
509
- }
604
+ }
0 commit comments