Skip to content

refine stop condition #736

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,4 @@ public class EvaluationRequest : LlmBaseRequest

[JsonPropertyName("max_rounds")]
public int MaxRounds { get; set; } = 20;

[JsonPropertyName("ref_conversation_id")]
public string RefConversationId { get; set; } = null!;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public class SimulationResult
[JsonPropertyName("generated_message")]
public string GeneratedMessage { get; set; }

[JsonPropertyName("stop")]
[JsonPropertyName("stop_conversation")]
public bool Stop { get; set; }

[JsonPropertyName("reason")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,28 @@ public partial class EvaluatingService
{
public async Task<EvaluationResult> Evaluate(string conversationId, EvaluationRequest request)
{
var result = new EvaluationResult();
if (string.IsNullOrEmpty(conversationId))
{
return result;
}

var storage = _services.GetRequiredService<IConversationStorage>();
var refDialogs = storage.GetDialogs(request.RefConversationId);
var refDialogContents = GetConversationContent(refDialogs);
var refDialogs = storage.GetDialogs(conversationId);

if (refDialogs.IsNullOrEmpty())
{
return result;
}

var refDialogContents = GetConversationContent(refDialogs);
var initDialog = refDialogs.FirstOrDefault(x => x.Role == AgentRole.User);
var initMessage = initDialog?.RichContent?.Message?.Text ?? initDialog?.Content ?? "Hello";
var initMessage = initDialog?.RichContent?.Message?.Text ?? initDialog?.Content;

if (string.IsNullOrWhiteSpace(initMessage))
{
return result;
}

var generatedConvId = await SimulateConversation(initMessage, refDialogContents, request);

Expand All @@ -23,28 +39,34 @@ public async Task<EvaluationResult> Evaluate(string conversationId, EvaluationRe
};
}

private async Task<string> SimulateConversation(string initMessage, IEnumerable<string> refConversation, EvaluationRequest request)
private async Task<string> SimulateConversation(string initMessage, IEnumerable<string> refDialogs, EvaluationRequest request)
{
var count = 0;
var curConvId = Guid.NewGuid().ToString();
var curConversation = new List<string>();
var curMessage = initMessage;
var convId = Guid.NewGuid().ToString();
var curDialogs = new List<string>();
var curUserMsg = initMessage;
var prevUserMsg = string.Empty;
var curBotMsg = string.Empty;
var prevBotMsg = string.Empty;

var storage = _services.GetRequiredService<IConversationStorage>();
var agentService = _services.GetRequiredService<IAgentService>();
var instructService = _services.GetRequiredService<IInstructService>();

var query = "Please take yourself as a user and follow the instruction to generate a message in the user tone.";
var query = "Please see yourself as a user and follow the instruction to generate a message.";
var targetAgentId = request.AgentId;
var evaluatorAgent = await agentService.GetAgent(BuiltInAgentId.Evaluator);
var simulatorPrompt = evaluatorAgent.Templates.FirstOrDefault(x => x.Name == "instruction.simulator")?.Content ?? string.Empty;

while (true)
{
curConversation.Add($"{AgentRole.User}: {curMessage}");
var dialog = await SendMessage(targetAgentId, curConvId, curMessage);
var botMessage = dialog?.RichContent?.Message?.Text ?? dialog?.Content ?? string.Empty;
curConversation.Add($"{AgentRole.Assistant}: {botMessage}");
curDialogs.Add($"{AgentRole.User}: {curUserMsg}");
var dialog = await SendMessage(targetAgentId, convId, curUserMsg);

prevBotMsg = curBotMsg;
curBotMsg = dialog?.RichContent?.Message?.Text ?? dialog?.Content ?? string.Empty;
curDialogs.Add($"{AgentRole.Assistant}: {curBotMsg}");

count++;

var result = await instructService.Instruct<SimulationResult>(simulatorPrompt, BuiltInAgentId.Evaluator,
Expand All @@ -55,20 +77,24 @@ private async Task<string> SimulateConversation(string initMessage, IEnumerable<
Message = query,
Data = new Dictionary<string, object>
{
{ "ref_conversation", refConversation },
{ "cur_conversation", curConversation },
{ "ref_conversation", refDialogs },
{ "cur_conversation", curDialogs },
}
});

if (count > request.MaxRounds || (result != null && result.Stop))
_logger.LogInformation($"Generated message: {result?.GeneratedMessage}, stop: {result?.Stop}, reason: {result?.Reason}");

if (curUserMsg.IsEqualTo(prevUserMsg) || curBotMsg.IsEqualTo(prevBotMsg)
|| count > request.MaxRounds || (result != null && result.Stop))
{
break;
}

curMessage = result?.GeneratedMessage ?? string.Empty;
prevUserMsg = curUserMsg;
curUserMsg = result?.GeneratedMessage ?? string.Empty;
}

return curConvId;
return convId;
}

private IEnumerable<string> GetConversationContent(IEnumerable<RoleDialogModel> dialogs)
Expand All @@ -85,7 +111,7 @@ private IEnumerable<string> GetConversationContent(IEnumerable<RoleDialogModel>
role = AgentRole.Assistant;
}

contents.Add($"{role}: {dialog.RichContent?.Message?.Text ?? dialog.Content}");
contents.Add($"{role}: {dialog.RichContent?.Message?.Text ?? dialog.Content ?? string.Empty}");
}

return contents;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ You are a conversaton simulator.
Please take the content in the [REFERENCE CONVERSATION] section as a reference, and focus on the [ONGOING CONVERSATION] section to generate a message based on the context.

** You need to take a close look at the content in both [REFERENCE CONVERSATION] and [ONGOING CONVERSATION], and determine whether to generate a text message or stop the ongoing conversation.
** When you generate a message, please assume you as the user and reply as the user perceptive.
** Please do not generate or append messages with similar meaning that you have already mentioned in the [ONGOING CONVERSATION].
** If you see the assistant replies two or more than two similar messages in the [ONGOING CONVERSATION], please stop the [ONGOING CONVERSATION] immediately and turn the "stop" to true in the output json.
** When you generate a message, please assume you are the user and reply in the user perceptive.
** Please do not generate or append a message with similar meaning that you have already mentioned in the [ONGOING CONVERSATION].
** If you see the assistant replies two or more than two similar messages in the [ONGOING CONVERSATION], please stop the conversation immediately.
** The output must be in JSON format:
{
"generated_message": the generated text message as the user tone,
"stop": a boolean to indicate whether to stop the [ONGOING CONVERSATION],
"reason": the reason why you generate the message or stop the [ONGOING CONVERSATION]
"generated_message": the generated text message using the user tone,
"stop_conversation": the boolean value to indicate whether to stop the conversation,
"reason": the reason why you generate the message or stop the conversation
}


Expand Down