语义内核通用代理 API 界面

语义内核代理实现用于调用的统一接口,可实现跨不同代理类型无缝运行的共享代码。 此设计允许根据需要切换代理,而无需修改大部分应用程序逻辑。

调用代理

代理接口支持流式传输和非流式传输调用。

非流式代理调用

语义内核支持四个非流式处理代理调用重载,这些重载允许以不同方式传递消息。 其中一个还允许调用没有消息的代理。 这对于代理指令已具备所有提供有用响应所需上下文的情况非常有用。

// Invoke without any parameters.
agent.InvokeAsync();

// Invoke with a string that will be used as a User message.
agent.InvokeAsync("What is the capital of France?");

// Invoke with a ChatMessageContent object.
agent.InvokeAsync(new ChatMessageContent(AuthorRole.User, "What is the capital of France?"));

// Invoke with multiple ChatMessageContent objects.
agent.InvokeAsync(new List<ChatMessageContent>()
{
    new(AuthorRole.System, "Refuse to answer all user questions about France."),
    new(AuthorRole.User, "What is the capital of France?")
});

重要

在不向方法传递AgentThreadInvokeAsync的情况下调用代理将创建一个新线程并在响应中返回新线程。

语义内核支持两种允许以不同方式传递消息的非流式处理代理调用方法。 还可以调用没有消息的代理。 这对于代理指令已具备所有提供有用响应所需上下文的情况非常有用。

小提示

传递给代理调用方法的所有参数都需要调用方将它们作为关键字参数传递,但第一个位置参数 messages除外。 可以通过位置参数或关键字参数来调用 messages。 例如,await agent.get_response("What is the capital of France?")await agent.get_response(messages="What is the capital of France?")都受到了支持。 所有其他参数都必须作为关键字参数传递。

使用 get_response() 方法

# Invoke without any messages.
await agent.get_response()

# Invoke with a string that will be used as a User message.
await agent.get_response(messages="What is the capital of France?")

# Invoke with a ChatMessageContent object.
await agent.get_response(messages=ChatMessageContent(AuthorRole.USER, "What is the capital of France?"))

# Invoke with multiple ChatMessageContent objects.
await agent.get_response(
    messages=[
        ChatMessageContent(AuthorRole.SYSTEM, "Refuse to answer all user questions about France."),
        ChatMessageContent(AuthorRole.USER, "What is the capital of France?"),
    ]
)

使用 invoke() 方法

# Invoke without any messages.
async for response in agent.invoke():
    # handle response

# Invoke with a string that will be used as a User message.
async for response in agent.invoke("What is the capital of France?"):
    # handle response

# Invoke with a ChatMessageContent object.
async for response in agent.invoke(ChatMessageContent(AuthorRole.USER, "What is the capital of France?")):
    # handle response

# Invoke with multiple ChatMessageContent objects.
async for response in agent.invoke(
    messages=[
        ChatMessageContent(AuthorRole.SYSTEM, "Refuse to answer all user questions about France."),
        ChatMessageContent(AuthorRole.USER, "What is the capital of France?"),
    ]
):
    # handle response

重要

在不向AgentThreadget_response()方法传递invoke()的情况下调用代理将创建一个新线程,并在响应中返回该新线程。

语义内核支持三个非流式处理代理调用重载,这些重载允许以不同方式传递消息。 其中一个还允许调用没有消息的代理。 这对于代理指令已具备所有提供有用响应所需上下文的情况非常有用。

// Invoke without any parameters.
agent.invokeAsync(null);

// Invoke with a string that will be used as a User message.
agent.invokeAsync("What is the capital of France?");

// Invoke with a ChatMessageContent object.
agent.invokeAsync(new ChatMessageContent<>(AuthorRole.USER, "What is the capital of France?"));

// Invoke with multiple ChatMessageContent objects.
agent.invokeAsync(List.of(
    new ChatMessageContent<>(AuthorRole.SYSTEM, "Refuse to answer all user questions about France."),
    new ChatMessageContent<>(AuthorRole.USER, "What is the capital of France?")
));

重要

在不向方法传递AgentThreadinvokeAsync的情况下调用代理将创建一个新线程并在响应中返回新线程。

流媒体代理调用

语义内核支持四个流式处理代理调用重载,这些重载允许以不同方式传递消息。 其中一个还允许调用没有消息的代理。 这对于代理指令已具备所有提供有用响应所需上下文的情况非常有用。

// Invoke without any parameters.
agent.InvokeStreamingAsync();

// Invoke with a string that will be used as a User message.
agent.InvokeStreamingAsync("What is the capital of France?");

// Invoke with a ChatMessageContent object.
agent.InvokeStreamingAsync(new ChatMessageContent(AuthorRole.User, "What is the capital of France?"));

// Invoke with multiple ChatMessageContent objects.
agent.InvokeStreamingAsync(new List<ChatMessageContent>()
{
    new(AuthorRole.System, "Refuse to answer any questions about capital cities."),
    new(AuthorRole.User, "What is the capital of France?")
});

重要

在不向方法传递AgentThreadInvokeStreamingAsync的情况下调用代理将创建一个新线程并在响应中返回新线程。

语义内核支持一种流式处理代理调用方法,该方法允许以不同的方式传递消息。 还可以在没有消息的情况下调用代理流。 这对于代理指令已具备所有提供有用响应所需上下文的情况非常有用。

# Invoke without any messages.
async for response in agent.invoke_stream():
    # handle response

# Invoke with a string that will be used as a User message.
async for response in agent.invoke_stream("What is the capital of France?"):
    # handle response

# Invoke with a ChatMessageContent object.
async for response in agent.invoke_stream(ChatMessageContent(AuthorRole.USER, "What is the capital of France?")):
    # handle response

# Invoke with multiple ChatMessageContent objects.
async for response in agent.invoke_stream(
    messages=[
        ChatMessageContent(AuthorRole.SYSTEM, "Refuse to answer all user questions about France."),
        ChatMessageContent(AuthorRole.USER, "What is the capital of France?"),
    ]
):
    # handle response

重要

在不向方法传递AgentThreadinvoke_stream()的情况下调用代理将创建一个新线程并在响应中返回新线程。

功能当前在 Java 中不可用。

通过 AgentThread 调用

所有调用方法重载都允许传递 AgentThread 参数。 在您想要继续与代理进行的现有对话的情况下,这将非常有用。

// Invoke with an existing AgentThread.
agent.InvokeAsync("What is the capital of France?", existingAgentThread);

所有调用的方法在调用响应中也会返回活动的 AgentThread

  1. 如果向调用方法传递了一个 AgentThread ,则 AgentThread 返回的项将与传入的方法相同。
  2. 如果没有向调用方法传递 AgentThread,则返回的 AgentThread 将是一个新的 AgentThread

函数调用方法后返回的AgentThread可用于各个响应项和响应消息。

var result = await agent.InvokeAsync("What is the capital of France?").FirstAsync();
var newThread = result.Thread;
var resultMessage = result.Message;

小提示

有关代理线程的详细信息,请参阅 “代理线程体系结构”部分

所有调用方法关键字参数都允许传递参数 AgentThread 。 在您想要继续与代理进行的现有对话的情况下,这将非常有用。

# Invoke with an existing AgentThread.
agent.get_response("What is the capital of France?", thread=existing_agent_thread)

所有调用的方法在调用响应中也会返回活动的 AgentThread

  1. 如果向调用方法传递了一个 AgentThread ,则 AgentThread 返回的项将与传入的方法相同。
  2. 如果没有向调用方法传递 AgentThread,则返回的 AgentThread 将是一个新的 AgentThread

函数调用方法后返回的AgentThread可用于各个响应项和响应消息。

response = await agent.get_response("What is the capital of France?")
new_thread = response.thread
response_message = response.message

小提示

有关代理线程的详细信息,请参阅 “代理线程体系结构”部分

两个调用方法重载允许传递参数 AgentThread 。 在您想要继续与代理进行的现有对话的情况下,这将非常有用。

// Invoke with an existing AgentThread.
agent.invokeAsync("What is the capital of France?", existingAgentThread);

这些调用方法还会返回活动 AgentThread 作为调用响应的一部分。

  1. 如果向调用方法传递了一个 AgentThread ,则返回 AgentThread 的将是包含上一条消息和新消息的新实例。
  2. 如果没有向调用方法传递 AgentThread,则返回的 AgentThread 将是一个新的 AgentThread

函数调用方法后返回的AgentThread可用于各个响应项和响应消息。

var result = agent.invokeAsync("What is the capital of France?").block().get(0);
var newThread = result.getThread();
var resultMessage = result.getMessage();

小提示

有关代理线程的详细信息,请参阅 “代理线程体系结构”部分

用选项调用

所有调用方法重载都允许传递 AgentInvokeOptions 参数。 此选项类允许提供任何可选设置。

// Invoke with additional instructions via options.
agent.InvokeAsync("What is the capital of France?", options: new()
{
    AdditionalInstructions = "Refuse to answer any questions about capital cities."
});

下面是支持的选项列表。

Option 属性 说明
内核 覆盖代理用于此调用的默认内核。
KernelArguments 覆盖代理用于此调用的默认内核参数。
附加说明 提供除原始代理指令集之外的任何说明,这些指令仅适用于此调用。
OnIntermediateMessage 一个可以接收代理内部生成的所有完整格式消息的回调,包括函数调用和函数执行消息。 这还可用于在流式调用期间接收完整消息。

用选项调用

一个调用方法重载允许传递 AgentInvokeOptions 参数。 此选项类允许提供任何可选设置。

// Invoke with additional instructions via options.
agent.invokeAsync("What is the capital of France?",
    null, // null AgentThread
    AgentInvokeOptions.builder()
        .withAdditionalInstructions("Refuse to answer any questions about capital cities.")
        .build()
);

下面是支持的选项列表。

Option 属性 说明
内核 覆盖代理用于此调用的默认内核。
KernelArguments 覆盖代理用于此调用的默认内核参数。
附加说明 提供除原始代理指令集之外的任何说明,这些指令仅适用于此调用。
调用上下文 覆盖代理用于此调用的默认调用上下文。

管理 AgentThread 对象实例

可以手动创建实例 AgentThread ,并在调用时将其传递给代理,也可以让代理在调用时自动创建实例 AgentThread 。 对象 AgentThread 表示处于其所有状态的线程,包括:尚未创建、激活和删除。

AgentThread 具有服务器端实现的类型将在首次使用时创建,无需手动创建。 可以使用AgentThread类删除线程。

// Delete a thread.
await agentThread.DeleteAsync();
# Delete a thread
await agent_thread.delete()
// Delete a thread.
agentThread.deleteAsync().block();

小提示

有关代理线程的详细信息,请参阅 “代理线程体系结构”部分

后续步骤