11using BotSharp . Abstraction . Evaluations . Models ;
22using BotSharp . Abstraction . Instructs ;
33using BotSharp . Abstraction . Instructs . Models ;
4+ using BotSharp . Abstraction . Models ;
45
56namespace BotSharp . Core . Evaluations . Services ;
67
@@ -31,15 +32,19 @@ public async Task<EvaluationResult> Evaluate(string conversationId, EvaluationRe
3132 return result ;
3233 }
3334
34- var generatedConvId = await SimulateConversation ( initMessage , refDialogContents , request ) ;
35+ var initialStates = GetInitialStates ( conversationId ) ;
36+ var generatedConvId = await SimulateConversation ( initMessage , refDialogContents , request , initialStates ) ;
37+ var metricResult = await EvaluateMetrics ( generatedConvId , refDialogContents , request ) ;
3538
3639 return new EvaluationResult
3740 {
38- GeneratedConversationId = generatedConvId
41+ GeneratedConversationId = generatedConvId ,
42+ MetricResult = metricResult
3943 } ;
4044 }
4145
42- private async Task < string > SimulateConversation ( string initMessage , IEnumerable < string > refDialogs , EvaluationRequest request )
46+ private async Task < string > SimulateConversation ( string initMessage , IEnumerable < string > refDialogs ,
47+ EvaluationRequest request , IEnumerable < MessageState > ? states = null )
4348 {
4449 var count = 0 ;
4550 var duplicateCount = 0 ;
@@ -49,20 +54,22 @@ private async Task<string> SimulateConversation(string initMessage, IEnumerable<
4954 var prevUserMsg = string . Empty ;
5055 var curBotMsg = string . Empty ;
5156 var prevBotMsg = string . Empty ;
57+ var initialStates = states ? . ToList ( ) ?? [ ] ;
5258
5359 var storage = _services . GetRequiredService < IConversationStorage > ( ) ;
5460 var agentService = _services . GetRequiredService < IAgentService > ( ) ;
5561 var instructService = _services . GetRequiredService < IInstructService > ( ) ;
5662
5763 var query = "Please see yourself as a user and follow the instruction to generate a message." ;
5864 var targetAgentId = request . AgentId ;
59- var evaluatorAgent = await agentService . GetAgent ( BuiltInAgentId . Evaluator ) ;
60- var simulatorPrompt = evaluatorAgent . Templates . FirstOrDefault ( x => x . Name == "instruction.simulator" ) ? . Content ?? string . Empty ;
65+ var evaluator = await agentService . GetAgent ( BuiltInAgentId . Evaluator ) ;
66+ var simulatorPrompt = evaluator . Templates . FirstOrDefault ( x => x . Name == "instruction.simulator" ) ? . Content ?? string . Empty ;
6167
6268 while ( true )
6369 {
6470 curDialogs . Add ( $ "{ AgentRole . User } : { curUserMsg } ") ;
65- var dialog = await SendMessage ( targetAgentId , convId , curUserMsg ) ;
71+ var dialog = await SendMessage ( targetAgentId , convId , curUserMsg , states : initialStates ) ;
72+ initialStates = [ ] ;
6673
6774 prevBotMsg = curBotMsg ;
6875 curBotMsg = dialog ? . RichContent ? . Message ? . Text ?? dialog ? . Content ?? string . Empty ;
@@ -80,30 +87,20 @@ private async Task<string> SimulateConversation(string initMessage, IEnumerable<
8087 {
8188 { "ref_conversation" , refDialogs } ,
8289 { "cur_conversation" , curDialogs } ,
83- { "additional_instruction" , request . AdditionalInstruction } ,
84- { "stop_criteria" , request . StopCriteria }
90+ { "additional_instruction" , request . Chat . AdditionalInstruction } ,
91+ { "stop_criteria" , request . Chat . StopCriteria }
8592 }
8693 } ) ;
8794
8895 _logger . LogInformation ( $ "Generated message: { result ? . GeneratedMessage } , stop: { result ? . Stop } , reason: { result ? . Reason } ") ;
8996
90- if ( count > request . MaxRounds || ( result != null && result . Stop ) )
97+ if ( count > request . Chat . MaxRounds || ( result != null && result . Stop ) )
9198 {
9299 break ;
93100 }
94101
95-
96- if ( curUserMsg . IsEqualTo ( prevUserMsg ) || curBotMsg . IsEqualTo ( prevBotMsg ) )
97- {
98- duplicateCount ++ ;
99- }
100- else
101- {
102- duplicateCount = 0 ;
103- }
104-
105-
106- if ( duplicateCount >= request . DuplicateLimit )
102+ duplicateCount = curBotMsg . IsEqualTo ( prevBotMsg ) ? duplicateCount + 1 : 0 ;
103+ if ( duplicateCount >= request . Chat . DuplicateLimit )
107104 {
108105 break ;
109106 }
@@ -115,6 +112,38 @@ private async Task<string> SimulateConversation(string initMessage, IEnumerable<
115112 return convId ;
116113 }
117114
115+
116+ private async Task < string ? > EvaluateMetrics ( string curConversationId , IEnumerable < string > refDialogs , EvaluationRequest request )
117+ {
118+ var storage = _services . GetRequiredService < IConversationStorage > ( ) ;
119+ var agentService = _services . GetRequiredService < IAgentService > ( ) ;
120+ var instructService = _services . GetRequiredService < IInstructService > ( ) ;
121+
122+ var curDialogs = storage . GetDialogs ( curConversationId ) ;
123+ var curDialogContents = GetConversationContent ( curDialogs ) ;
124+
125+ var evaluator = await agentService . GetAgent ( BuiltInAgentId . Evaluator ) ;
126+ var metricPrompt = evaluator . Templates . FirstOrDefault ( x => x . Name == "instruction.metrics" ) ? . Content ?? string . Empty ;
127+ var query = "Please follow the instruction for evaluation." ;
128+
129+ var result = await instructService . Instruct < JsonDocument > ( metricPrompt , BuiltInAgentId . Evaluator ,
130+ new InstructOptions
131+ {
132+ Provider = request . Provider ,
133+ Model = request . Model ,
134+ Message = query ,
135+ Data = new Dictionary < string , object >
136+ {
137+ { "ref_conversation" , refDialogs } ,
138+ { "cur_conversation" , curDialogs } ,
139+ { "additional_instruction" , request . Metric . AdditionalInstruction } ,
140+ { "metrics" , request . Metric . Metrics }
141+ }
142+ } ) ;
143+
144+ return result != null ? result . RootElement . GetRawText ( ) : null ;
145+ }
146+
118147 private IEnumerable < string > GetConversationContent ( IEnumerable < RoleDialogModel > dialogs )
119148 {
120149 var contents = new List < string > ( ) ;
@@ -134,4 +163,30 @@ private IEnumerable<string> GetConversationContent(IEnumerable<RoleDialogModel>
134163
135164 return contents ;
136165 }
166+
167+ private IEnumerable < MessageState > GetInitialStates ( string conversationId )
168+ {
169+ if ( string . IsNullOrWhiteSpace ( conversationId ) )
170+ {
171+ return [ ] ;
172+ }
173+
174+ var db = _services . GetRequiredService < IBotSharpRepository > ( ) ;
175+ var states = db . GetConversationStates ( conversationId ) ;
176+ var initialStates = new List < MessageState > ( ) ;
177+
178+ foreach ( var state in states )
179+ {
180+ var value = state . Value ? . Values ? . FirstOrDefault ( x => string . IsNullOrEmpty ( x . MessageId ) ) ;
181+
182+ if ( string . IsNullOrEmpty ( value ? . Data ) )
183+ {
184+ continue ;
185+ }
186+
187+ initialStates . Add ( new MessageState ( state . Key , value . Data , value . ActiveRounds ) ) ;
188+ }
189+
190+ return initialStates ;
191+ }
137192}
0 commit comments