بناء سير عمل الوكيل باستخدام Microsoft Agent Framework

· 7 دقيقة قراءة

مقدمة

إذا كنت قد قرأت منشوراتي السابقة حول Microsoft Agent Framework، فأنت تعرف كيفية إنشاء وكلاء فرديين وحتى محادثات جماعية متعددة الوكلاء. ولكن في سيناريوهات العالم الحقيقي، غالبًا ما تحتاج إلى شيء أكثر تنظيماً - سير عمل حيث ينفذ الوكلاء بترتيب معين، ويمررون النتائج لبعضهم البعض، ويتعاملون مع منطق التفرع بناءً على النتائج.

هذا هو بالضبط ما توفره لك إمكانيات سير العمل في Agent Framework. بدلاً من إدخال الوكلاء في محادثة جماعية والأمل في اكتشاف ذلك، يمكنك تحديد خطوات وتبعيات وتدفق بيانات صريحة بين الوكلاء.

ما هي مسارات عمل الوكيل؟

فكر في سير عمل الوكيل مثل خط الأنابيب. يتم التعامل مع كل خطوة بواسطة وكيل متخصص، ويتم تغذية ناتج خطوة واحدة إلى الخطوة التالية. يمكنك تنفيذ الخطوات بشكل تسلسلي، أو بالتوازي، أو بشكل مشروط بناءً على النتائج.

بعض الأمثلة:

  • خط أنابيب المحتوى: بحث ← مسودة ← مراجعة ← نشر
  • معالجة البيانات: استخراج ← تحويل ← التحقق من الصحة ← تحميل
  • دعم العملاء: التصنيف ← المسار ← الاستجابة ← المتابعة

المتطلبات الأساسية

تأكد من حصولك على أحدث حزم Agent Framework:

dotnet add package Microsoft.SemanticKernel
dotnet add package Microsoft.SemanticKernel.Agents.Core

وتم تكوين نقطة نهاية Azure OpenAI أو OpenAI.

بناء سير عمل متسلسل

لنقم ببناء سير عمل لإنشاء المحتوى باستخدام ثلاثة وكلاء: باحث، وكاتب، ومحرر.

تعريف الوكلاء

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;

var kernel = Kernel.CreateBuilder()
    .AddAzureOpenAIChatCompletion(
        deploymentName: "gpt-4o",
        endpoint: config["AzureOpenAI:Endpoint"],
        apiKey: config["AzureOpenAI:ApiKey"])
    .Build();

var researcher = new ChatCompletionAgent
{
    Name = "Researcher",
    Instructions = """
        You are a research specialist. Given a topic, find key facts, statistics,
        and talking points. Return a structured research brief with bullet points.
        Be thorough but concise.
        """,
    Kernel = kernel
};

var writer = new ChatCompletionAgent
{
    Name = "Writer",
    Instructions = """
        You are a technical blog writer. Given a research brief, write a clear
        and engaging blog post. Use a conversational tone, include code examples
        where relevant, and structure the post with clear headings.
        """,
    Kernel = kernel
};

var editor = new ChatCompletionAgent
{
    Name = "Editor",
    Instructions = """
        You are a senior editor. Review the blog post for clarity, accuracy,
        grammar, and flow. Return the corrected version with a summary of
        changes made at the end.
        """,
    Kernel = kernel
};

التنفيذ بالتسلسل

أبسط سير عمل هو سير عمل تسلسلي، حيث يقوم كل وكيل بمعالجة مخرجات الوكيل السابق:

using Microsoft.SemanticKernel.Agents.Chat;
using Microsoft.SemanticKernel.ChatCompletion;

async Task<string> RunSequentialWorkflow(string topic)
{
    var history = new ChatHistory();
    string currentInput = $"Research the following topic: {topic}";

    var agents = new[] { researcher, writer, editor };

    foreach (var agent in agents)
    {
        history.AddUserMessage(currentInput);

        var response = new System.Text.StringBuilder();
        await foreach (var message in agent.InvokeAsync(history))
        {
            response.Append(message.Content);
        }

        currentInput = response.ToString();
        Console.WriteLine($"✅ {agent.Name} completed");
    }

    return currentInput;
}

var result = await RunSequentialWorkflow("Blazor render modes in .NET 9");
Console.WriteLine(result);

يحصل كل وكيل على السياق المتراكم، ويعالجه، وتنتقل النتيجة إلى الخطوة التالية.

التنفيذ الموازي

في بعض الأحيان يمكن للوكلاء العمل بشكل مستقل. على سبيل المثال، قد ترغب في البحث عن موضوعات فرعية متعددة في نفس الوقت:

async Task<List<string>> RunParallelResearch(string[] topics)
{
    var tasks = topics.Select(async topic =>
    {
        var history = new ChatHistory();
        history.AddUserMessage($"Research: {topic}");

        var response = new System.Text.StringBuilder();
        await foreach (var message in researcher.InvokeAsync(history))
        {
            response.Append(message.Content);
        }

        Console.WriteLine($"✅ Research completed: {topic}");
        return response.ToString();
    });

    var results = await Task.WhenAll(tasks);
    return results.ToList();
}

var topics = new[]
{
    "Blazor SSR streaming",
    "Enhanced navigation in .NET 9",
    "Render mode boundaries"
};

var briefs = await RunParallelResearch(topics);

بعد ذلك يمكنك تغذية جميع ملخصات البحث إلى وكيل كاتب واحد لإنتاج مشاركة واحدة متماسكة.

التفرع المشروط

سير العمل الحقيقي يحتاج إلى قرارات. ربما تريد خطوة فحص الجودة التي تعيدك إلى الكاتب إذا لم يكن المنشور جيدًا بما فيه الكفاية:

var qualityChecker = new ChatCompletionAgent
{
    Name = "QualityChecker",
    Instructions = """
        You are a quality assurance reviewer. Evaluate the blog post on:
        1. Technical accuracy
        2. Clarity and readability
        3. Completeness

        Respond with either:
        - "APPROVED" if the post meets all criteria
        - "REVISION NEEDED: [specific feedback]" if changes are required

        Be strict. Only approve posts that are truly ready to publish.
        """,
    Kernel = kernel
};

async Task<string> RunWithQualityLoop(string topic, int maxRevisions = 3)
{
    var history = new ChatHistory();

    // Step 1: Research
    history.AddUserMessage($"Research: {topic}");
    string research = await InvokeAgent(researcher, history);

    // Step 2: Write
    history.AddUserMessage(research);
    string draft = await InvokeAgent(writer, history);

    // Step 3: Quality loop
    for (int i = 0; i < maxRevisions; i++)
    {
        var qaHistory = new ChatHistory();
        qaHistory.AddUserMessage($"Review this post:\n\n{draft}");
        string qaResult = await InvokeAgent(qualityChecker, qaHistory);

        if (qaResult.Contains("APPROVED", StringComparison.OrdinalIgnoreCase))
        {
            Console.WriteLine($"✅ Approved after {i + 1} review(s)");
            return draft;
        }

        Console.WriteLine($"🔄 Revision {i + 1}: {qaResult[..Math.Min(100, qaResult.Length)]}...");

        // Send back to writer with feedback
        history.AddUserMessage($"Please revise based on this feedback:\n{qaResult}");
        draft = await InvokeAgent(writer, history);
    }

    Console.WriteLine("⚠️ Max revisions reached, returning latest draft");
    return draft;
}

async Task<string> InvokeAgent(ChatCompletionAgent agent, ChatHistory history)
{
    var response = new System.Text.StringBuilder();
    await foreach (var message in agent.InvokeAsync(history))
    {
        response.Append(message.Content);
    }
    return response.ToString();
}

هذا النمط مفيد للغاية. يعمل مدقق الجودة كبوابة، ويتكرر سير العمل حتى يصبح الإخراج جيدًا بدرجة كافية أو يصل إلى الحد الأقصى للمراجعة.

إضافة المكونات الإضافية إلى وكلاء سير العمل

يمكن للوكلاء في سير العمل استخدام المكونات الإضافية تمامًا مثل الوكلاء المستقلين. هذا هو المكان الذي تصبح فيه الأمور قوية حقًا - يمكن للوكلاء الاتصال بواجهات برمجة التطبيقات أو الاستعلام عن قواعد البيانات أو إجراء عمليات الملفات كجزء من خطوة سير العمل الخاصة بهم:

var researcherWithTools = new ChatCompletionAgent
{
    Name = "Researcher",
    Instructions = "Research the topic using available tools. Summarize findings.",
    Kernel = kernel
};

// Add a web search plugin
kernel.Plugins.AddFromType<WebSearchPlugin>();

// Add a database plugin
kernel.Plugins.AddFromObject(new DatabasePlugin(connectionString), "Database");
public class WebSearchPlugin
{
    [KernelFunction, Description("Search the web for information")]
    public async Task<string> SearchAsync(
        [Description("The search query")] string query)
    {
        // Your search implementation
        using var httpClient = new HttpClient();
        var response = await httpClient.GetStringAsync(
            $"https://api.search.example.com?q={Uri.EscapeDataString(query)}");
        return response;
    }
}

معالجة الأخطاء في سير العمل

عندما تقوم بربط عدة وكلاء، تصبح معالجة الأخطاء أمرًا بالغ الأهمية. لا تريد أن تؤدي خطوة واحدة فاشلة إلى تعطل سير العمل بأكمله بصمت:

async Task<WorkflowResult> RunResilientWorkflow(string input)
{
    var result = new WorkflowResult();

    try
    {
        result.Research = await InvokeAgent(researcher, new ChatHistory(input));
    }
    catch (Exception ex)
    {
        result.Errors.Add($"Research failed: {ex.Message}");
        return result;
    }

    try
    {
        var writeHistory = new ChatHistory(result.Research);
        result.Draft = await InvokeAgent(writer, writeHistory);
    }
    catch (Exception ex)
    {
        result.Errors.Add($"Writing failed: {ex.Message}");
        result.Draft = result.Research; // Fallback to research output
    }

    result.Success = result.Errors.Count == 0;
    return result;
}

class WorkflowResult
{
    public string Research { get; set; } = "";
    public string Draft { get; set; } = "";
    public List<string> Errors { get; set; } = new();
    public bool Success { get; set; }
}

أفضل الممارسات

بعد إنشاء العديد من مسارات عمل الوكيل، إليك ما تعلمته:- حافظ على تركيز تعليمات الوكيل — يجب على كل وكيل أن يفعل شيئًا واحدًا بشكل جيد. لا تحاول أن تصنع عميلاً بسكين الجيش السويسري.

  • السياق المحدد — لا تمرر سجل المحادثة بالكامل إلى كل وكيل. أعط كل خطوة ما تحتاجه فقط.
  • تعيين حدود للمراجعة — تعتبر حلقات الجودة رائعة ولكن يمكن تشغيلها إلى الأبد إذا لم تكن حذرًا. دائمًا ما يكون لديك حد أقصى للتكرارات.
  • تسجيل كل شيء — يمكن أن تكون مخرجات الوكيل غير متوقعة. قم بتسجيل مدخلات ومخرجات كل خطوة لتصحيح الأخطاء.
  • استخدم التنفيذ الموازي بحكمة — فهو يعمل على تسريع الأمور ولكن انتبه إلى حدود معدل واجهة برمجة التطبيقات (API) وتكاليف الرمز المميز.
  • اختبر النماذج الأصغر أولاً - قم بتطوير واختبار منطق سير العمل الخاص بك باستخدام GPT-3.5 قبل التبديل إلى GPT-4o للإنتاج.

الخلاصة

تتيح لك مسارات عمل الوكيل إنشاء خطوط أنابيب معقدة ومتعددة الخطوات للذكاء الاصطناعي حيث يكون كل وكيل متخصصًا. ابدأ بسير العمل المتسلسل، وأضف التنفيذ المتوازي حيث تكون الخطوات مستقلة، واستخدم التفرع المشروط لبوابات الجودة. الأنماط قابلة للتركيب - بمجرد أن تتقنها، يمكنك إنشاء بعض الأتمتة المتطورة جدًا.

ترميز سعيد!

الموارد