共用方式為


使用指南:ChatCompletionAgent

這很重要

這項功能處於實驗階段。 在這個階段的功能正在開發中,在前進到預覽或發行候選階段之前,可能會變更。

概觀

在這個範例中,我們將探索如何設定外掛程式以存取 GitHub API,並提供模板化指示給ChatCompletionAgent,以回答有關 GitHub 儲存庫的問題。 此方法將逐步細分,以突顯編程過程的關鍵部分。 作為工作的一部分,代理程式會在回應中提供文件引文。

串流將用來傳遞代理程序的回應。 這會在工作進行時提供即時更新。

快速入門

繼續進行功能程式代碼撰寫之前,請確定您的開發環境已完全設定和設定。

從建立 主控台 項目開始。 然後,包含下列套件參考,以確保所有必要的相依性都可供使用。

為了從命令列新增套件相依性,請使用命令:dotnet

dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Binder
dotnet add package Microsoft.Extensions.Configuration.UserSecrets
dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables
dotnet add package Microsoft.SemanticKernel.Connectors.AzureOpenAI
dotnet add package Microsoft.SemanticKernel.Agents.Core --prerelease

這很重要

如果在 Visual Studio 中管理 NuGet 套件,請確定 Include prerelease 已核取 。

項目檔 (.csproj) 應包含下列 PackageReference 定義:

  <ItemGroup>
    <PackageReference Include="Azure.Identity" Version="<stable>" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="<stable>" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="<stable>" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="<stable>" />
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="<stable>" />
    <PackageReference Include="Microsoft.SemanticKernel.Agents.Core" Version="<latest>" />
    <PackageReference Include="Microsoft.SemanticKernel.Connectors.AzureOpenAI" Version="<latest>" />
  </ItemGroup>

Agent Framework 是實驗性的,需要抑制警告。 在項目檔案中(.csproj)將此作為屬性來處理。

  <PropertyGroup>
    <NoWarn>$(NoWarn);CA2007;IDE1006;SKEXP0001;SKEXP0110;OPENAI001</NoWarn>
  </PropertyGroup>

此外,請從GitHubPlugin.cs複製 GitHub 外掛程式和模型 (GitHubModels.csLearnResources) 。 在項目資料夾中新增這些檔案。

首先,建立一個資料夾來保存您的腳本(.py 檔案)和範例資源。 在你的 .py 檔案頂端,包含下列匯入:

import asyncio
import os
import sys
from datetime import datetime

from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.functions import KernelArguments
from semantic_kernel.kernel import Kernel

# Adjust the sys.path so we can use the GitHubPlugin and GitHubSettings classes
# This is so we can run the code from the samples/learn_resources/agent_docs directory
# If you are running code from your own project, you may not need need to do this.
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from plugins.GithubPlugin.github import GitHubPlugin, GitHubSettings  # noqa: E402

此外,從github.py複製 GitHub 外掛程式和模型 (LearnResources)。 在項目資料夾中新增這些檔案。

從建立 Maven 主控台項目開始。 然後,包含下列套件參考,以確保所有必要的相依性都可供使用。

項目 pom.xml 應該包含下列相依性:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.microsoft.semantic-kernel</groupId>
            <artifactId>semantickernel-bom</artifactId>
            <version>[LATEST]</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.microsoft.semantic-kernel</groupId>
        <artifactId>semantickernel-agents-core</artifactId>
    </dependency>

    <dependency>
        <groupId>com.microsoft.semantic-kernel</groupId>
        <artifactId>semantickernel-aiservices-openai</artifactId>
    </dependency>
</dependencies>

此外,請從GitHubPlugin.java複製 GitHub 外掛程式和模型 (GitHubModels.javaLearnResources) 。 在項目資料夾中新增這些檔案。

組態

此範例需要組態設定,才能連線到遠端服務。 您必須定義 OpenAI 或 Azure OpenAI 以及 GitHub 的設定。

備註

如需 GitHub 個人存取令牌的資訊,請參閱: 管理您的個人存取令牌

# OpenAI
dotnet user-secrets set "OpenAISettings:ApiKey" "<api-key>"
dotnet user-secrets set "OpenAISettings:ChatModel" "gpt-4o"

# Azure OpenAI
dotnet user-secrets set "AzureOpenAISettings:ApiKey" "<api-key>" # Not required if using token-credential
dotnet user-secrets set "AzureOpenAISettings:Endpoint" "<model-endpoint>"
dotnet user-secrets set "AzureOpenAISettings:ChatModelDeployment" "gpt-4o"

# GitHub
dotnet user-secrets set "GitHubSettings:BaseUrl" "https://api.github.com"
dotnet user-secrets set "GitHubSettings:Token" "<personal access token>"

下列類別用於所有 Agent 範例中。 請務必將它包含在專案中,以確保適當的功能。 這個類別可作為後續範例的基礎元件。

using System.Reflection;
using Microsoft.Extensions.Configuration;

namespace AgentsSample;

public class Settings
{
    private readonly IConfigurationRoot configRoot;

    private AzureOpenAISettings azureOpenAI;
    private OpenAISettings openAI;

    public AzureOpenAISettings AzureOpenAI => this.azureOpenAI ??= this.GetSettings<Settings.AzureOpenAISettings>();
    public OpenAISettings OpenAI => this.openAI ??= this.GetSettings<Settings.OpenAISettings>();

    public class OpenAISettings
    {
        public string ChatModel { get; set; } = string.Empty;
        public string ApiKey { get; set; } = string.Empty;
    }

    public class AzureOpenAISettings
    {
        public string ChatModelDeployment { get; set; } = string.Empty;
        public string Endpoint { get; set; } = string.Empty;
        public string ApiKey { get; set; } = string.Empty;
    }

    public TSettings GetSettings<TSettings>() =>
        this.configRoot.GetRequiredSection(typeof(TSettings).Name).Get<TSettings>()!;

    public Settings()
    {
        this.configRoot =
            new ConfigurationBuilder()
                .AddEnvironmentVariables()
                .AddUserSecrets(Assembly.GetExecutingAssembly(), optional: true)
                .Build();
    }
}

若要開始使用適當的組態來執行範例程序代碼,最快的方式是在專案的根目錄建立 .env 檔案(執行腳本的位置)。

.env 檔案中設定以下選項,以適用於 Azure OpenAI 或 OpenAI:

AZURE_OPENAI_API_KEY="..."
AZURE_OPENAI_ENDPOINT="https://<resource-name>.openai.azure.com/"
AZURE_OPENAI_CHAT_DEPLOYMENT_NAME="..."
AZURE_OPENAI_API_VERSION="..."

OPENAI_API_KEY="sk-..."
OPENAI_ORG_ID=""
OPENAI_CHAT_MODEL_ID=""

設定之後,個別的 AI 服務類別會挑選必要的變數,並在具現化期間使用這些變數。

在您的系統中定義下列環境變數。

# Azure OpenAI
AZURE_OPENAI_API_KEY=""
AZURE_OPENAI_ENDPOINT="https://<resource-name>.openai.azure.com/"
AZURE_CHAT_MODEL_DEPLOYMENT=""

# OpenAI
OPENAI_API_KEY=""
OPENAI_MODEL_ID=""

在檔案頂端,您可以依下列方式擷取其值。

// Azure OpenAI
private static final String AZURE_OPENAI_API_KEY = System.getenv("AZURE_OPENAI_API_KEY");
private static final String AZURE_OPENAI_ENDPOINT = System.getenv("AZURE_OPENAI_ENDPOINT");
private static final String AZURE_CHAT_MODEL_DEPLOYMENT = System.getenv().getOrDefault("AZURE_CHAT_MODEL_DEPLOYMENT", "gpt-4o");

// OpenAI
private static final String OPENAI_API_KEY = System.getenv("OPENAI_API_KEY");
private static final String OPENAI_MODEL_ID = System.getenv().getOrDefault("OPENAI_MODEL_ID", "gpt-4o");

撰寫程式碼

這個範例的編碼程式牽涉到:

  1. 安裝程式 - 初始化設定和外掛程式。
  2. Agent 定義 - 使用範本化指示和外掛程式建立 ChatCompletionAgent
  3. 聊天迴圈 - 撰寫驅動使用者/代理程序互動的迴圈。

完整範例程式代碼會在 Final 區段中提供。 如需完整的實作,請參閱該區段。

設定

建立 ChatCompletionAgent之前,必須初始化組態設定、外掛程式和 Kernel

初始化上一Settings節中所參考的類別。

Settings settings = new();

使用外掛程式的設定來初始化外掛程式。

在這裡,會顯示訊息以指出進度。

Console.WriteLine("Initialize plugins...");
GitHubSettings githubSettings = settings.GetSettings<GitHubSettings>();
GitHubPlugin githubPlugin = new(githubSettings);
gh_settings = GitHubSettings(
    token="<PAT value>"
)
kernel.add_plugin(GitHubPlugin(settings=gh_settings), plugin_name="github")
var githubPlugin = new GitHubPlugin(GITHUB_PAT);

現在,初始化一個 Kernel 實例,使用 IChatCompletionService 和先前建立的 GitHubPlugin

Console.WriteLine("Creating kernel...");
IKernelBuilder builder = Kernel.CreateBuilder();

builder.AddAzureOpenAIChatCompletion(
    settings.AzureOpenAI.ChatModelDeployment,
    settings.AzureOpenAI.Endpoint,
    new AzureCliCredential());

builder.Plugins.AddFromObject(githubPlugin);

Kernel kernel = builder.Build();
kernel = Kernel()

# Add the AzureChatCompletion AI Service to the Kernel
service_id = "agent"
kernel.add_service(AzureChatCompletion(service_id=service_id))

settings = kernel.get_prompt_execution_settings_from_service_id(service_id=service_id)
# Configure the function choice behavior to auto invoke kernel functions
settings.function_choice_behavior = FunctionChoiceBehavior.Auto()
OpenAIAsyncClient client = new OpenAIClientBuilder()
    .credential(new AzureKeyCredential(AZURE_OPENAI_API_KEY))
    .endpoint(AZURE_OPENAI_ENDPOINT)
    .buildAsyncClient();

ChatCompletionService chatCompletion = OpenAIChatCompletion.builder()
    .withModelId(AZURE_CHAT_MODEL_DEPLOYMENT)
    .withOpenAIAsyncClient(client)
    .build();

Kernel kernel = Kernel.builder()
    .withAIService(ChatCompletionService.class, chatCompletion)
    .withPlugin(KernelPluginFactory.createFromObject(githubPlugin, "GitHubPlugin"))
    .build();

代理程式定義

最後,我們已準備好使用其指令、相關聯的 ChatCompletionAgent和預設自變數和執行設定來具現化 Kernel 。 在此情況下,我們想要自動執行任何外掛程式函式。

Console.WriteLine("Defining agent...");
ChatCompletionAgent agent =
    new()
    {
        Name = "SampleAssistantAgent",
        Instructions =
            """
            You are an agent designed to query and retrieve information from a single GitHub repository in a read-only manner.
            You are also able to access the profile of the active user.

            Use the current date and time to provide up-to-date details or time-sensitive responses.

            The repository you are querying is a public repository with the following name: {{$repository}}

            The current date and time is: {{$now}}. 
            """,
        Kernel = kernel,
        Arguments =
            new KernelArguments(new AzureOpenAIPromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() })
            {
                { "repository", "microsoft/semantic-kernel" }
            }
    };

Console.WriteLine("Ready!");
agent = ChatCompletionAgent(
    kernel=kernel,
    name="SampleAssistantAgent",
    instructions=f"""
        You are an agent designed to query and retrieve information from a single GitHub repository in a read-only 
        manner.
        You are also able to access the profile of the active user.

        Use the current date and time to provide up-to-date details or time-sensitive responses.

        The repository you are querying is a public repository with the following name: microsoft/semantic-kernel

        The current date and time is: {{$now}}. 
        """,
    arguments=KernelArguments(
        settings=settings,
    ),
)
// Invocation context for the agent
InvocationContext invocationContext = InvocationContext.builder()
    .withFunctionChoiceBehavior(FunctionChoiceBehavior.auto(true))
    .build()

ChatCompletionAgent agent = ChatCompletionAgent.builder()
    .withName("SampleAssistantAgent")
    .withKernel(kernel)
    .withInvocationContext(invocationContext)
    .withTemplate(
        DefaultPromptTemplate.build(
            PromptTemplateConfig.builder()
                .withTemplate(
                    """
                    You are an agent designed to query and retrieve information from a single GitHub repository in a read-only manner.
                    You are also able to access the profile of the active user.

                    Use the current date and time to provide up-to-date details or time-sensitive responses.

                    The repository you are querying is a public repository with the following name: {{$repository}}

                    The current date and time is: {{$now}}.
                    """)
                .build()))
    .withKernelArguments(
        KernelArguments.builder()
            .withVariable("repository", "microsoft/semantic-kernel-java")
            .withExecutionSettings(PromptExecutionSettings.builder()
                    .build())
            .build())
    .build();

聊天迴圈

最後,我們能夠協調使用者與 Agent之間的互動。 從建立 ChatHistoryAgentThread 對象開始,以維護交談狀態並建立空迴圈。

ChatHistoryAgentThread agentThread = new();
bool isComplete = false;
do
{
    // processing logic here
} while (!isComplete);
thread: ChatHistoryAgentThread = None
is_complete: bool = False
while not is_complete:
    # processing logic here
AgentThread agentThread = new ChatHistoryAgentThread();
boolean isComplete = false;

while (!isComplete) {
    // processing logic here
}

現在讓我們在上一個迴圈中擷取用戶輸入。 在此情況下,將會忽略空的輸入,而字詞 EXIT 會發出交談已完成的訊號。

Console.WriteLine();
Console.Write("> ");
string input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input))
{
    continue;
}
if (input.Trim().Equals("EXIT", StringComparison.OrdinalIgnoreCase))
{
    isComplete = true;
    break;
}

var message = new ChatMessageContent(AuthorRole.User, input);

Console.WriteLine();
user_input = input("User:> ")
if not user_input:
    continue

if user_input.lower() == "exit":
    is_complete = True
    break
Scanner scanner = new Scanner(System.in);

while (!isComplete) {
    System.out.print("> ");

    String input = scanner.nextLine();
    if (input.isEmpty()) {
        continue;
    }

    if (input.equalsIgnoreCase("exit")) {
        isComplete = true;
        break;
    }

}

若要產生使用者輸入的 Agent 回應,請使用 Arguments 叫用代理程式,以提供指定目前日期和時間的最終範本參數。

然後,Agent 回應會顯示給使用者。

DateTime now = DateTime.Now;
KernelArguments arguments =
    new()
    {
        { "now", $"{now.ToShortDateString()} {now.ToShortTimeString()}" }
    };
await foreach (ChatMessageContent response in agent.InvokeAsync(message, agentThread, options: new() { KernelArguments = arguments }))
{
    Console.WriteLine($"{response.Content}");
}
arguments = KernelArguments(
    now=datetime.now().strftime("%Y-%m-%d %H:%M")
)

async for response in agent.invoke(messages=user_input, thread=thread, arguments=arguments):
    print(f"{response.content}")
    thread = response.thread
var options = AgentInvokeOptions.builder()
    .withKernelArguments(KernelArguments.builder()
            .withVariable("now", OffsetDateTime.now())
            .build())
    .build();

for (var response : agent.invokeAsync(message, agentThread, options).block()) {
    System.out.println(response.getMessage());
    agentThread = response.getThread();
}

最終

將所有步驟結合在一起,我們有此範例的最終程序代碼。 以下提供完整的實作。

請嘗試使用這些建議的輸入:

  1. 我的使用者名稱為何?
  2. 描述存放庫。
  3. 描述儲存庫中新建立的問題。
  4. 列出過去一週內關閉的前 10 個問題。
  5. 這些問題的標籤方式如何?
  6. 列出 「代理程式」標籤最近開啟的 5 個問題
using System;
using System.Threading.Tasks;
using Azure.Identity;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.AzureOpenAI;
using Plugins;

namespace AgentsSample;

public static class Program
{
    public static async Task Main()
    {
        // Load configuration from environment variables or user secrets.
        Settings settings = new();

        Console.WriteLine("Initialize plugins...");
        GitHubSettings githubSettings = settings.GetSettings<GitHubSettings>();
        GitHubPlugin githubPlugin = new(githubSettings);

        Console.WriteLine("Creating kernel...");
        IKernelBuilder builder = Kernel.CreateBuilder();

        builder.AddAzureOpenAIChatCompletion(
            settings.AzureOpenAI.ChatModelDeployment,
            settings.AzureOpenAI.Endpoint,
            new AzureCliCredential());

        builder.Plugins.AddFromObject(githubPlugin);

        Kernel kernel = builder.Build();

        Console.WriteLine("Defining agent...");
        ChatCompletionAgent agent =
            new()
            {
                Name = "SampleAssistantAgent",
                Instructions =
                        """
                        You are an agent designed to query and retrieve information from a single GitHub repository in a read-only manner.
                        You are also able to access the profile of the active user.

                        Use the current date and time to provide up-to-date details or time-sensitive responses.

                        The repository you are querying is a public repository with the following name: {{$repository}}

                        The current date and time is: {{$now}}. 
                        """,
                Kernel = kernel,
                Arguments =
                    new KernelArguments(new AzureOpenAIPromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() })
                    {
                        { "repository", "microsoft/semantic-kernel" }
                    }
            };

        Console.WriteLine("Ready!");

        ChatHistoryAgentThread agentThread = new();
        bool isComplete = false;
        do
        {
            Console.WriteLine();
            Console.Write("> ");
            string input = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(input))
            {
                continue;
            }
            if (input.Trim().Equals("EXIT", StringComparison.OrdinalIgnoreCase))
            {
                isComplete = true;
                break;
            }

            var message = new ChatMessageContent(AuthorRole.User, input);

            Console.WriteLine();

            DateTime now = DateTime.Now;
            KernelArguments arguments =
                new()
                {
                    { "now", $"{now.ToShortDateString()} {now.ToShortTimeString()}" }
                };
            await foreach (ChatMessageContent response in agent.InvokeAsync(message, agentThread, options: new() { KernelArguments = arguments }))
            {
                // Display response.
                Console.WriteLine($"{response.Content}");
            }

        } while (!isComplete);
    }
}
import asyncio
import os
import sys
from datetime import datetime

from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.functions import KernelArguments
from semantic_kernel.kernel import Kernel

# Adjust the sys.path so we can use the GitHubPlugin and GitHubSettings classes
# This is so we can run the code from the samples/learn_resources/agent_docs directory
# If you are running code from your own project, you may not need need to do this.
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from plugins.GithubPlugin.github import GitHubPlugin, GitHubSettings  # noqa: E402

async def main():
    kernel = Kernel()

    # Add the AzureChatCompletion AI Service to the Kernel
    service_id = "agent"
    kernel.add_service(AzureChatCompletion(service_id=service_id))

    settings = kernel.get_prompt_execution_settings_from_service_id(service_id=service_id)
    # Configure the function choice behavior to auto invoke kernel functions
    settings.function_choice_behavior = FunctionChoiceBehavior.Auto()

    # Set your GitHub Personal Access Token (PAT) value here
    gh_settings = GitHubSettings(token="")  # nosec
    kernel.add_plugin(plugin=GitHubPlugin(gh_settings), plugin_name="GithubPlugin")

    current_time = datetime.now().isoformat()

    # Create the agent
    agent = ChatCompletionAgent(
        kernel=kernel,
        name="SampleAssistantAgent",
        instructions=f"""
            You are an agent designed to query and retrieve information from a single GitHub repository in a read-only 
            manner.
            You are also able to access the profile of the active user.

            Use the current date and time to provide up-to-date details or time-sensitive responses.

            The repository you are querying is a public repository with the following name: microsoft/semantic-kernel

            The current date and time is: {current_time}. 
            """,
        arguments=KernelArguments(settings=settings),
    )

    thread: ChatHistoryAgentThread = None
    is_complete: bool = False
    while not is_complete:
        user_input = input("User:> ")
        if not user_input:
            continue

        if user_input.lower() == "exit":
            is_complete = True
            break

        arguments = KernelArguments(now=datetime.now().strftime("%Y-%m-%d %H:%M"))

        async for response in agent.invoke(messages=user_input, thread=thread, arguments=arguments):
            print(f"{response.content}")
            thread = response.thread


if __name__ == "__main__":
    asyncio.run(main())

您可能會在存放庫中找到完整的 程式代碼,如上所示。

import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.agents.AgentInvokeOptions;
import com.microsoft.semantickernel.agents.AgentThread;
import com.microsoft.semantickernel.agents.chatcompletion.ChatCompletionAgent;
import com.microsoft.semantickernel.agents.chatcompletion.ChatHistoryAgentThread;
import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion;
import com.microsoft.semantickernel.contextvariables.ContextVariableTypeConverter;
import com.microsoft.semantickernel.functionchoice.FunctionChoiceBehavior;
import com.microsoft.semantickernel.implementation.templateengine.tokenizer.DefaultPromptTemplate;
import com.microsoft.semantickernel.orchestration.InvocationContext;
import com.microsoft.semantickernel.orchestration.PromptExecutionSettings;
import com.microsoft.semantickernel.plugin.KernelPluginFactory;
import com.microsoft.semantickernel.samples.plugins.github.GitHubModel;
import com.microsoft.semantickernel.samples.plugins.github.GitHubPlugin;
import com.microsoft.semantickernel.semanticfunctions.KernelArguments;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.services.chatcompletion.AuthorRole;
import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService;
import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent;
import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential;

import java.time.OffsetDateTime;
import java.util.Scanner;

public class CompletionAgent {
    // Azure OpenAI
    private static final String AZURE_OPENAI_API_KEY = System.getenv("AZURE_OPENAI_API_KEY");
    private static final String AZURE_OPENAI_ENDPOINT = System.getenv("AZURE_OPENAI_ENDPOINT");
    private static final String AZURE_CHAT_MODEL_DEPLOYMENT = System.getenv().getOrDefault("AZURE_CHAT_MODEL_DEPLOYMENT", "gpt-4o");

    // GitHub Personal Access Token
    private static final String GITHUB_PAT = System.getenv("GITHUB_PAT");

    public static void main(String[] args) {
        System.out.println("======== ChatCompletion Agent ========");

        OpenAIAsyncClient client = new OpenAIClientBuilder()
                .credential(new AzureKeyCredential(AZURE_OPENAI_API_KEY))
                .endpoint(AZURE_OPENAI_ENDPOINT)
                .buildAsyncClient();

        var githubPlugin = new GitHubPlugin(GITHUB_PAT);

        ChatCompletionService chatCompletion = OpenAIChatCompletion.builder()
                .withModelId(AZURE_CHAT_MODEL_DEPLOYMENT)
                .withOpenAIAsyncClient(client)
                .build();

        Kernel kernel = Kernel.builder()
            .withAIService(ChatCompletionService.class, chatCompletion)
            .withPlugin(KernelPluginFactory.createFromObject(githubPlugin, "GitHubPlugin"))
            .build();

        InvocationContext invocationContext = InvocationContext.builder()
            .withFunctionChoiceBehavior(FunctionChoiceBehavior.auto(true))
            .withContextVariableConverter(new ContextVariableTypeConverter<>(
                    GitHubModel.Issue.class,
                    o -> (GitHubModel.Issue) o,
                    o -> o.toString(),
                    s -> null))
            .build();

        ChatCompletionAgent agent = ChatCompletionAgent.builder()
            .withName("SampleAssistantAgent")
            .withKernel(kernel)
            .withInvocationContext(invocationContext)
            .withTemplate(
                DefaultPromptTemplate.build(
                    PromptTemplateConfig.builder()
                        .withTemplate(
                            """
                            You are an agent designed to query and retrieve information from a single GitHub repository in a read-only manner.
                            You are also able to access the profile of the active user.

                            Use the current date and time to provide up-to-date details or time-sensitive responses.

                            The repository you are querying is a public repository with the following name: {{$repository}}

                            The current date and time is: {{$now}}.
                            """)
                        .build()))
            .withKernelArguments(
                KernelArguments.builder()
                    .withVariable("repository", "microsoft/semantic-kernel-java")
                    .withExecutionSettings(PromptExecutionSettings.builder()
                            .build())
                    .build())
            .build();

        AgentThread agentThread = new ChatHistoryAgentThread();
        boolean isComplete = false;

        Scanner scanner = new Scanner(System.in);

        while (!isComplete) {
            System.out.print("> ");

            String input = scanner.nextLine();
            if (input.isEmpty()) {
                continue;
            }

            if (input.equalsIgnoreCase("EXIT")) {
                isComplete = true;
                break;
            }

            var message = new ChatMessageContent<>(AuthorRole.USER, input);

            var options = AgentInvokeOptions.builder()
                .withKernelArguments(KernelArguments.builder()
                        .withVariable("now", OffsetDateTime.now())
                        .build())
                .build();

            for (var response : agent.invokeAsync(message, agentThread, options).block()) {
                System.out.println(response.getMessage());
                agentThread = response.getThread();
            }
        }
    }
}

後續步驟