[Loop Engineering在MAF中的实现-05]MAF预定义的评估器
除了利用AIJudgeLoopEvaluator让LLM当评委介绍的AIJudgeLoopEvaluatorMAF还提供了其他几种继承自LoopEvaluator的评估器类型接下来我们会逐个介绍它们。1. DelegateLoopEvaluatorDelegateLoopEvaluator非常简单就是利用提供的FuncLoopContext, CancellationToken, ValueTaskLoopEvaluation类型的委托来实现EvaluateAsync方法的评估工作。publicsealedclassDelegateLoopEvaluator:LoopEvaluator{privatereadonlyFuncLoopContext,CancellationToken,ValueTaskLoopEvaluation_evaluate;publicDelegateLoopEvaluator(FuncLoopContext,CancellationToken,ValueTaskLoopEvaluationevaluate)_evaluateevaluate;publicoverrideValueTaskLoopEvaluationEvaluateAsync(LoopContextcontext,CancellationTokencancellationTokendefault)_evaluate(context,cancellationToken);}2. CompletionMarkerLoopEvaluatorCompletionMarkerLoopEvaluator旨在确定任务是否结束来决定循环调用是否继续。它的做法很简单在调用Agent提供的提示词中明确告诉LLM如果它认为任务已经完成就在返回的响应文本中包含指定的完成标记Completion Marker。CompletionMarkerLoopEvaluator通过确定最终的响应文本是否包含此标记来生成最终的LoopEvaluation。publicsealedclassCompletionMarkerLoopEvaluator:LoopEvaluator{publicCompletionMarkerLoopEvaluator(stringcompletionMarker,CompletionMarkerLoopEvaluatorOptions?optionsnull);publicoverrideValueTaskLoopEvaluationEvaluateAsync(LoopContextcontext,CancellationTokencancellationTokendefault);}publicsealedclassCompletionMarkerLoopEvaluatorOptions{publicstring?FeedbackMessageTemplate{get;set;}}我们在调用构造函数的时候通过completionMarker参数指定上述的完成标记并通过提供可选的配置选项CompletionMarkerLoopEvaluatorOptions提供一个格式化反馈文本的模板。如果没有提供此配置选项则使用如下这个默认模板这就是我们上面介绍的让LLM在认为推理任务结束时在响应文本放置完成标记的提示词。如果原始的请求中没有类似的提示词意味着针对首次迭代的评估必然会失败。Continue working on the request. When you have fully completed the task, end your response with the marker {completion_marker} to indicate completion.下面的演示程序很好地体现了CompletionMarkerLoopEvaluator的评估逻辑。该程序同时指明了CompletionMarkerLoopEvaluator在进行字符比较时针对大小写是敏感的。varevaluator1newCompletionMarkerLoopEvaluator(completionMarker:DONE);varevaluator2newCompletionMarkerLoopEvaluator(completionMarker:done);varcontextnewLoopContext(agent:newFakeAgent(),session:newFakeSession(),initialMessages:[],lastResponse:newAgentResponse(newChatMessage(ChatRole.Assistant,DONE)));varevaluationawaitevaluator1.EvaluateAsync(context);Debug.Assert(!evaluation.ShouldReinvoke);Debug.Assert(evaluation.Feedbackisnull);evaluationawaitevaluator2.EvaluateAsync(context);Debug.Assert(evaluation.ShouldReinvoke);Debug.Assert(evaluation.FeedbackContinue working on the request. When you have fully completed the task, end your response with the marker done to indicate completion.);3. TodoCompletionLoopEvaluatorTodoCompletionLoopEvaluator会结合TodoProvider和AgentModeProvider一起使用它们都是MAF两个自定义的AIContextProvider类型。前者利用提供的系统指令和工具指导和帮助LLM采用TodoList的模式执行任务后者则为根据不同阶段的任务特性指定针对性的推理模式。在我的文章TodoProvider用TodoList驱动Agent的任务执行和AgentModeProvider自由切换行为模式具有这对这两个AIContextProvider类型的详细介绍。如果采用TodoCompletionLoopEvaluator意味着在执行任务的之前会制定一份TodoList并按部就班地按照它来实施。TodoCompletionLoopEvaluator旨在避免在某些事项尚未执行就停止循环。如果同时还同时使用了AgentModeProvider并且只希望LoopAgent只在指定的模式下才进行后续迭代我们还可以利用TodoCompletionLoopEvaluatorOptions设置这个模式列表。publicsealedclassTodoCompletionLoopEvaluatorOptions{publicIEnumerablestring?Modes{get;set;}publicstring?FeedbackMessageTemplate{get;set;}}除了用于指定允许继续迭代的模式列表的Modes属性外配置选项类型TodoCompletionLoopEvaluatorOptions还提供了FeedbackMessageTemplate属性用来定义评估反馈的文本模板。如果没有显式指定默认采用如下的模板文本占位符{remaining_todos}表示尚未完成的Todo事项。You still have incomplete todo items. Continue working until every item is complete, marking each item as complete when finished. The following items are still open: {remaining_todos}TodoCompletionLoopEvaluator的构造函数具有唯一的可选参数options。如果没有通过这个参数显式指定一个TodoCompletionLoopEvaluatorOptions对象意味着TodoCompletionLoopEvaluator的评估将不会考虑推理模式的因素。publicsealedclassTodoCompletionLoopEvaluator:LoopEvaluator{publicTodoCompletionLoopEvaluator(TodoCompletionLoopEvaluatorOptions?optionsnull);publicoverrideasyncValueTaskLoopEvaluationEvaluateAsync(LoopContextcontext,CancellationTokencancellationTokendefault);}重写的EvaluateAsync会采用如下的方式实施评估如果设置了运行继续迭代的推理模式列表利用LoopContext上下文获取当前AIAgent并调用其GetServiceAgentModeProvider方法获取注册的AgentModeProvider:如果AgentModeProvider不存在直接抛出异常否则则继续调用它的GetMode方法得到当前的推理模式如果此推理模式不在设定的模式列表中直接返回一个ShouldReinvoke为false的LoopEvaluation终止循环按照相同的方式得到注册的TodoProvider如果TodoProvider不存在直接抛出异常否则调用其GetRemainingTodosAsync方法返回尚未完成的Todo事项如果存在利用设置的或者默认的模板生成反馈文本并封装在返回的ShouldReinvoke为true的LoopEvaluation中否则返回一个ShouldReinvoke为false的LoopEvaluation终止循环。4. BackgroundTaskCompletionLoopEvaluatorBackgroundTaskCompletionLoopEvaluator和TodoCompletionLoopEvaluator其实有点类似它们的目的都是为了避免在有些必要的任务尚未执行前就终止循环。具体来说BackgroundTaskCompletionLoopEvaluator与BackgroundAgentsProvider这个AIContextProvider有关。BackgroundAgentsProvider提供了一系列的工具使我们可以采用后台任务的形式执行指定的AIAgent在我的文章BackgroundAgentsProvider异步执行SubAgent对进行了详细介绍。BackgroundTaskCompletionLoopEvaluator的目的在于如果当前具有还在后台执行的任务就不能终止循环。如下面的代码所示我们创建BackgroundTaskCompletionLoopEvaluator时可以通过指定对应的BackgroundTaskCompletionLoopEvaluatorOptions并利用后者的FeedbackMessageTemplate提供一个用于格式化反馈文本的模板。publicsealedclassBackgroundTaskCompletionLoopEvaluator:LoopEvaluator{publicBackgroundTaskCompletionLoopEvaluator(BackgroundTaskCompletionLoopEvaluatorOptions?optionsnull);publicoverrideasyncValueTaskLoopEvaluationEvaluateAsync(LoopContextcontext,CancellationTokencancellationTokendefault);}publicsealedclassBackgroundTaskCompletionLoopEvaluatorOptions{publicstring?FeedbackMessageTemplate{get;set;}}如果反馈文本模板没有显示指定默认会采用如下所示的模板文本占位符{incomplete_task_count}表示尚未完成的后台任务的数量。You still have {incomplete_task_count} background task(s) running that must finish before you can complete the work:\ {incomplete_tasks} Wait for these tasks to complete, retrieve their results, and incorporate them. Only stop once every background task has finished.重写的EvaluateAsync会按照如下的方式实施评估利用LoopContext上下文获取当前AIAgent并调用其GetServiceBackgroundAgentsProvider方法获取注册的BackgroundAgentsProvider如果BackgroundAgentsProvider不存在直接抛出异常否则调用BackgroundAgentsProvider的GetIncompleteTasks方法的到尚未完成的后台任务如果任务列表不为空利用模板格式化反馈文本并封装在返回的ShouldReinvoke为true的LoopEvaluation中否则返回一个ShouldReinvoke为false的LoopEvaluation终止循环。