using AI.Interface; using AI.Models; using System; using System.Diagnostics; using System.Text.Json; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; namespace AI.Workflow { /// /// Planner - 负责规划任务,将任务分解成步骤 /// public class Planner { private readonly IChatBackend _chatBackend; private readonly ChatSession _planningSession; public Planner(IChatBackend chatBackend) { _chatBackend = chatBackend; _planningSession = new ChatSession(); // 初始化规划提示词 _planningSession.AddSystemMessage(GetPlanningPrompt()); } /// /// 规划任务 /// /// 任务目标 /// 取消令牌 /// 规划结果 public async Task PlanAsync(string goal, CancellationToken cancellationToken = default) { var plan = new Plan { Goal = goal }; try { // 请求 Planner 生成规划 string planningPrompt = $"请为以下任务制定详细的执行计划:\n\n任务:{goal}\n\n请将任务分解为具体的步骤,每个步骤应该是可执行的、明确的。"; string response = await _chatBackend.AskAsync(planningPrompt, _planningSession, null, cancellationToken); // 解析规划结果 ParsePlanFromResponse(response, plan); Debug.WriteLine($"Planner 生成了 {plan.Steps.Count} 个步骤"); } catch (Exception ex) { Debug.WriteLine($"Planner 规划失败: {ex.Message}"); throw; } return plan; } /// /// 从响应中解析规划步骤 /// private void ParsePlanFromResponse(string response, Plan plan) { // 尝试解析 JSON 格式 if (TryParseJsonPlan(response, plan)) { return; } // 尝试解析列表格式(1. 步骤1 2. 步骤2 ...) if (TryParseListPlan(response, plan)) { return; } // 如果都解析失败,将整个响应作为单个步骤 plan.Steps.Add(new PlanStep { Order = 1, Description = response.Trim() }); } /// /// 尝试解析 JSON 格式的规划 /// private bool TryParseJsonPlan(string response, Plan plan) { try { // 尝试提取 JSON 部分 var jsonMatch = Regex.Match(response, @"\{[\s\S]*\}"); if (!jsonMatch.Success) { return false; } var json = jsonMatch.Value; var doc = JsonDocument.Parse(json); var root = doc.RootElement; if (root.TryGetProperty("steps", out var stepsElement) && stepsElement.ValueKind == JsonValueKind.Array) { int order = 1; foreach (var stepElement in stepsElement.EnumerateArray()) { var step = new PlanStep { Order = order++, Description = stepElement.GetProperty("description").GetString() ?? string.Empty }; plan.Steps.Add(step); } return true; } } catch { // JSON 解析失败,继续尝试其他格式 } return false; } /// /// 尝试解析列表格式的规划 /// private bool TryParseListPlan(string response, Plan plan) { // 匹配各种列表格式:1. 2. 3. 或 - 或 * 等 var patterns = new[] { @"^\s*(\d+)\.\s+(.+)$", // 1. 步骤 @"^\s*[-*]\s+(.+)$", // - 步骤 或 * 步骤 @"^\s*(\d+)\)\s+(.+)$" // 1) 步骤 }; var lines = response.Split('\n', StringSplitOptions.RemoveEmptyEntries); int order = 1; foreach (var line in lines) { var trimmedLine = line.Trim(); if (string.IsNullOrWhiteSpace(trimmedLine)) continue; foreach (var pattern in patterns) { var match = Regex.Match(trimmedLine, pattern); if (match.Success) { string description = match.Groups.Count > 2 ? match.Groups[2].Value : match.Groups[1].Value; plan.Steps.Add(new PlanStep { Order = order++, Description = description.Trim() }); break; } } } return plan.Steps.Count > 0; } /// /// 获取规划提示词 /// private string GetPlanningPrompt() { return @"你是一个专业的任务规划专家,擅长将复杂任务分解为清晰、可执行的步骤序列。 【核心职责】 将用户提出的任务目标分解为一系列有序、可执行的步骤,确保每个步骤都有明确的目标和可衡量的结果。 【规划原则】 1. **原子性**:每个步骤应该是独立的、可单独执行的最小任务单元 2. **顺序性**:步骤之间必须有清晰的逻辑顺序和依赖关系 3. **可执行性**:每个步骤的描述应该具体、明确,能够直接指导执行 4. **完整性**:确保所有必要的步骤都被包含,不遗漏关键环节 5. **可验证性**:每个步骤完成后应该有明确的验证标准 【步骤描述要求】 - 使用动词开头,明确表达要执行的动作(如:""加载文件""、""验证数据""、""生成报告"") - 包含必要的上下文信息(如:""从指定路径加载 XYZ 文件"") - 避免模糊表述,使用具体、可操作的语言 - 每个步骤描述控制在 20-50 字之间 【输出格式】 优先使用 JSON 格式,结构如下: { ""steps"": [ {""description"": ""步骤1的详细描述""}, {""description"": ""步骤2的详细描述""}, ... ] } 如果无法返回 JSON,请使用编号列表格式: 1. 步骤1的详细描述 2. 步骤2的详细描述 ... 【注意事项】 - 不要创建过于细碎的步骤,也不要创建过于宏大的步骤 - 考虑步骤之间的依赖关系,确保顺序合理 - 如果任务涉及多个阶段,可以按阶段组织步骤 - 对于需要用户输入或确认的步骤,明确标注"; } } }