使用 Teams AI 库进行生成

Teams AI 库简化了使用 AI 组件生成智能Microsoft Teams 应用程序。 它提供用于数据访问、自定义 UI 创建、提示管理和安全审查的 API。 可以使用 OpenAI 或 Azure OpenAI 轻松创建机器人,以提供 AI 驱动的体验。

初始设置

Teams AI 库基于 Bot Framework SDK 构建。 它通过导入核心功能来扩展 Bot Framework 的功能。 作为初始设置的一部分,导入 Bot Framework SDK 组件。 处理与通道连接的适配器类是从 Bot Framework SDK 导入的。

示例代码参考

.NET Code:初始配置和适配器设置

using Microsoft.Teams.AI;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.TeamsFx.Conversation;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddHttpClient("WebClient", client => client.Timeout = TimeSpan.FromSeconds(600));
builder.Services.AddHttpContextAccessor();

// Prepare Configuration for ConfigurationBotFrameworkAuthentication
var config = builder.Configuration.Get<ConfigOptions>();
builder.Configuration["MicrosoftAppType"] = "MultiTenant";
builder.Configuration["MicrosoftAppId"] = config.BOT_ID;
builder.Configuration["MicrosoftAppPassword"] = config.BOT_PASSWORD;

// Create the Bot Framework Authentication to be used with the Bot Adapter.
builder.Services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();

// Create the Cloud Adapter with error handling enabled.
// Note: some classes expect a BotAdapter and some expect a BotFrameworkHttpAdapter, so
// register the same adapter instance for all types.
builder.Services.AddSingleton<CloudAdapter, AdapterWithErrorHandler>();
builder.Services.AddSingleton<IBotFrameworkHttpAdapter>(sp => sp.GetService<CloudAdapter>());
builder.Services.AddSingleton<BotAdapter>(sp => sp.GetService<CloudAdapter>());

导入 Teams AI 库

@microsoft/teams-ai 中导入所有类以生成机器人并使用 Teams AI 库功能。

示例代码参考

JavaScript 代码:导入 Teams AI 库

// import Teams AI library
import {
    AI,
    Application,
    ActionPlanner,
    OpenAIModerator,
    OpenAIModel,
    PromptManager,
    TurnState
} from '@microsoft/teams-ai';
import { addResponseFormatter } from './responseFormatter';
import { VectraDataSource } from './VectraDataSource';

创建 AI 组件

可以在现有机器人应用或新的 Bot Framework 应用中创建 AI 组件。 main组件包括:

  • OpenAIModel:提供对 OpenAI API 或遵循 OpenAI REST 格式的任何服务的访问权限。 它适用于 OpenAI 和 Azure OpenAI 语言模型。
  • 提示管理器:管理提示创建。 它将函数、会话状态和用户状态自动插入提示符中。
  • ActionPlanner: (LLM) 调用大型语言模型,并包含用于增强和自定义模型的功能。 此组件根据用户输入和可用作生成和执行计划。

示例代码参考

.NET Code:创建 AI 组件

    // Create model
    
    OpenAIModel? model = null;
    
    if (!string.IsNullOrEmpty(config.OpenAI?.ApiKey))
    {
        model = new(new OpenAIModelOptions(config.OpenAI.ApiKey, "gpt-3.5-turbo"));
    }
    else if (!string.IsNullOrEmpty(config.Azure?.OpenAIApiKey) && !string.IsNullOrEmpty(config.Azure.OpenAIEndpoint))
    {
        model = new(new AzureOpenAIModelOptions(
            config.Azure.OpenAIApiKey,
            "gpt-35-turbo",
            config.Azure.OpenAIEndpoint
        ));
    }
    
    if (model == null)
    {
        throw new Exception("please configure settings for either OpenAI or Azure");
    }

    // Create prompt manager
    PromptManager prompts = new(new()
    {
        PromptFolder = "./Prompts",
    });

    // Add function to be referenced in the prompt template

    prompts.AddFunction("getLightStatus", async (context, memory, functions, tokenizer, args) =>
    {
        bool lightsOn = (bool)(memory.GetValue("conversation.lightsOn") ?? false);
        return await Task.FromResult(lightsOn ? "on" : "off");
    });

    // Create ActionPlanner
    ActionPlanner<AppState> planner = new(
        options: new(
            model: model,
            prompts: prompts,
            defaultPrompt: async (context, state, planner) =>
            {
                PromptTemplate template = prompts.GetPrompt("sequence");
                return await Task.FromResult(template);
            }
        )
        { LogRepairs = true },
        loggerFactory: loggerFactory
    );

定义存储和应用程序

应用程序对象自动管理机器人的聊天和用户状态。 其中包括:

  • 存储:存储提供程序存储聊天和用户状态。
  • 应用程序:类 Application 为应用注册作或活动处理程序。 它包含所有必要的信息和机器人逻辑。

示例代码参考

.NET 代码:定义存储和应用程序

 return new TeamsLightBot(new()
    {
        Storage = sp.GetService<IStorage>(),
        AI = new(planner),
        LoggerFactory = loggerFactory,
        TurnStateFactory = () =>
        {
            return new AppState();
        }
    });

属性 TurnStateFactory 允许创建自定义状态类来存储其他信息或逻辑。 通过创建一个类来扩展默认轮次状态,该类包含其他属性 ((例如用户输入、机器人输出或聊天历史记录) ),并将创建类实例的函数传递给应用构造函数。

注册数据源

矢量数据源简化了向任何提示添加 Retrieval-Augmented 代 (RAG) 。 向规划器注册命名数据源,并在提示 config.json 文件中指定它以增加提示。 这允许 AI 将来自外部源 ((例如矢量数据库或认知搜索) )的相关信息注入提示。

示例代码参考

JavaScript 代码:向 Planner 注册数据源

// Register your data source with planner
planner.prompts.addDataSource(new VectraDataSource({
    name: 'teams-ai',
    apiKey:  process.env.OPENAI_API_KEY!,
    indexFolder: path.join(__dirname, '../index'),
}));

嵌入

嵌入是 LLM 生成的矢量,用于表示文本,捕获其语义含义。 嵌入用于文本分类、情绪分析、搜索等。 例如,OpenAI 的 text-embedding-ada-002 模型返回表示输入文本的 1536 个数字的列表。 这些嵌入存储在矢量数据库中。 在自定义引擎代理中,RAG 模式可以从矢量数据库检索相关数据并增加提示符。


示例:VectraDataSource 和 OpenAIEmbeddings
import { DataSource, Memory, RenderedPromptSection, Tokenizer } from '@microsoft/teams-ai';
import { OpenAIEmbeddings, LocalDocumentIndex } from 'vectra';
import * as path from 'path';
import { TurnContext } from 'botbuilder';

/**
 * Options for creating a `VectraDataSource`.
 */
export interface VectraDataSourceOptions {
    /**
     * Name of the data source and local index.
     */
    name: string;

    /**
     * OpenAI API key to use for generating embeddings.
     */
    apiKey: string;

    /**
     * Path to the folder containing the local index.
     * @remarks
     * This should be the root folder for all local indexes and the index itself
     * needs to be in a subfolder under this folder.
     */
    indexFolder: string;

    /**
     * Optional. Maximum number of documents to return.
     * @remarks
     * Defaults to `5`.
     */
    maxDocuments?: number;

    /**
     * Optional. Maximum number of chunks to return per document.
     * @remarks
     * Defaults to `50`.
     */
    maxChunks?: number;

    /**
     * Optional. Maximum number of tokens to return per document.
     * @remarks
     * Defaults to `600`.
     */
    maxTokensPerDocument?: number;
}

/**
 * A data source that uses a local Vectra index to inject text snippets into a prompt.
 */
export class VectraDataSource implements DataSource {
    private readonly _options: VectraDataSourceOptions;
    private readonly _index: LocalDocumentIndex;

    /**
     * Name of the data source.
     * @remarks
     * This is also the name of the local Vectra index.
     */
    public readonly name: string;

    /**
     * Creates a new `VectraDataSource` instance.
     * @param options Options for creating the data source.
     */
    public constructor(options: VectraDataSourceOptions) {
        this._options = options;
        this.name = options.name;

        // Create embeddings model
        const embeddings = new OpenAIEmbeddings({
            model: 'text-embedding-ada-002',
            apiKey: options.apiKey,
        });

        // Create local index
        this._index = new LocalDocumentIndex({
            embeddings,
            folderPath: path.join(options.indexFolder, options.name),
        });
    }

    /**
     * Renders the data source as a string of text.
     * @param context Turn context for the current turn of conversation with the user.
     * @param memory An interface for accessing state values.
     * @param tokenizer Tokenizer to use when rendering the data source.
     * @param maxTokens Maximum number of tokens allowed to be rendered.
     */
    public async renderData(context: TurnContext, memory: Memory, tokenizer: Tokenizer, maxTokens: number): Promise<RenderedPromptSection<string>> {
        // Query index
        const query = memory.getValue('temp.input') as string;
        const results = await this._index.queryDocuments(query, {
            maxDocuments: this._options.maxDocuments ?? 5,
            maxChunks: this._options.maxChunks ?? 50,
        });

        // Add documents until you run out of tokens
        let length = 0;
        let output = '';
        let connector = '';
        for (const result of results) {
            // Start a new doc
            let doc = `${connector}url: ${result.uri}\n`;
            let docLength = tokenizer.encode(doc).length;
            const remainingTokens = maxTokens - (length + docLength);
            if (remainingTokens <= 0) {
                break;
            }

            // Render document section
            const sections = await result.renderSections(Math.min(remainingTokens, this._options.maxTokensPerDocument ?? 600), 1);
            docLength += sections[0].tokenCount;
            doc += sections[0].text;

            // Append doc to output
            output += doc;
            length += docLength;
            connector = '\n\n';
        }

        return { output, length, tooLong: length > maxTokens };
    }

}

提示

提示是用于创建对话体验的文本段,例如启动对话、提问和生成响应。 新的基于对象的提示系统将提示划分为多个部分,每个部分都有自己的令牌预算 (固定或成比例的剩余令牌) 。 可以为文本完成和聊天完成样式 API 生成提示。

按照以下准则创建有效提示:

  • 提供明确的说明和示例。
  • 确保具有足够示例的高质量校对数据。
  • 使用 temperaturetop_p 调整提示设置,以控制模型的输出。 更高的值 (例如,0.8) 产生随机输出;较低的值 (例如,0.2) 创建集中的确定性响应。

若要实现提示,请执行以下命令:

  1. 创建名为 的文件夹 prompts
  2. 在专用文件中定义提示模板和设置:
    • skprompt.txt:包含支持模板变量和函数的提示文本。
    • config.json:包含提示模型设置,确保机器人的响应满足你的要求。

示例代码参考

示例: config.json 对于“提示设置”

 {
    "schema": 1.1,
    "description": "A bot that can turn the lights on and off",
    "type": "completion",
    "completion": {
        "model": "gpt-3.5-turbo",
        "completion_type": "chat",
        "include_history": true,
        "include_input": true,
        "max_input_tokens": 2800,
        "max_tokens": 1000,
        "temperature": 0.2,
        "top_p": 0.0,
        "presence_penalty": 0.6,
        "frequency_penalty": 0.0,
        "stop_sequences": []
    },
    "augmentation": {
        "augmentation_type": "sequence"
        "data_sources": {
             "teams-ai": 1200
     }
    }
  }

查询参数

下表详细介绍了查询参数:

说明
model 要使用的模型的 ID。
completion_type 要使用的完成类型。 该模型返回一个或多个预测完成和替代令牌的概率。 支持的选项: chattext。 默认值:chat
include_history Boolean 值。 指示是否包含历史记录。 每个提示都会获取自己的对话历史记录,以避免混淆。
include_input Boolean 值。 如果设置为 true,则提示中包含用户的输入。
max_input_tokens 允许输入的最大令牌数。 (支持的最大令牌数:4000)
max_tokens 要生成的令牌的最大数目。 提示标记和 的总和 max_tokens 不能超过模型的上下文长度。
temperature 采样温度 (范围:0 到 2) 。 更高的值 (例如,0.8) 产生更多的随机输出;较低的值 (例如,0.2) 生成焦点输出。
top_p 温度采样的替代方法,称为核采样。 例如,值 0.1 表示仅考虑概率质量前 10% 的令牌。
presence_penalty 介于 -2.0 和 2.0 之间的数字。 正值根据新令牌是否出现在文本中来惩罚新令牌,从而鼓励讨论新主题。
frequency_penalty 介于 -2.0 和 2.0 之间的数字。 正值根据令牌的频率惩罚令牌,从而降低重复的可能性。
stop_sequences API 停止生成令牌的最多四个序列。 返回的文本不包括停止序列。
augmentation_type 扩充的类型。 支持的值为 sequencemonologuetools

提示管理

提示管理根据令牌预算和可用数据源动态调整提示大小和内容。 例如,对于具有 4,000 个令牌限制的机器人 (输入限制为 2,800,输出限制为 1,000) ,该模型为来自外部源的聊天历史记录、输入和任何扩充数据保留令牌。

提示作

提示作允许模型执行作或响应用户输入。 可以使用相应的参数创建一个架构,列出支持的作。 OpenAI 终结点提取实体并将其作为参数传递给作处理程序。

例如:

The following is a conversation with an AI assistant.
The assistant can turn a light on or off.

context:
The lights are currently {{getLightStatus}}.

提示模板

提示模板使用纯文本定义和撰写 AI 函数。 它允许你:

  • 创建自然语言提示。
  • 生成响应。
  • 提取信息。
  • 调用其他提示。

该语言支持使用大括号 {{...}}嵌入变量和函数。 一些关键表达式包括:

  • {{function}}:调用已注册的函数并插入其返回值。
  • {{$input}}:插入从 state.temp.input获取的用户消息文本。
  • {{$state.[property]}}:插入状态属性。

操作

作处理由 AI 组件触发的事件。 内置 FlaggedInputActionFlaggedOutputAction 句柄审查器标志。 标记消息时,机器人会通过 context.sendActivity通知用户。 若要停止作,请返回 AI.StopCommandName

示例代码参考

JavaScript 代码:注册已标记的输入和输出作

// Register other AI actions
app.ai.action(
    AI.FlaggedInputActionName,
    async (context: TurnContext, state: ApplicationTurnState, data: Record<string, any>) => {
        await context.sendActivity(`I'm sorry your message was flagged: ${JSON.stringify(data)}`);
        return AI.StopCommandName;
    }
);

app.ai.action(AI.FlaggedOutputActionName, async (context: TurnContext, state: ApplicationTurnState, data: any) => {
    await context.sendActivity(`I'm not allowed to talk about such things.`);
    return AI.StopCommandName;
});

注册作处理程序

作处理程序可帮助机器人执行特定任务。 首先,在提示符中注册作,然后为每个作实现处理程序,包括未知作。

在以下轻型机器人示例中,作包括 LightsOnLightsOffPause。 每个作处理程序返回一个 string。 对于返回时间 (例如暂停持续时间) 的作, PauseParameters 属性可确保时间采用数字格式。

示例代码参考

.NET 代码:LightBot 的作处理程序

public class LightBotActions
    {
        [Action("LightsOn")]
        public async Task<string> LightsOn([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] AppState turnState)
        {
            turnState.Conversation!.LightsOn = true;
            await turnContext.SendActivityAsync(MessageFactory.Text("[lights on]"));
            return "the lights are now on";
        }

        [Action("LightsOff")]
        public async Task<string> LightsOff([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] AppState turnState)
        {
            turnState.Conversation!.LightsOn = false;
            await turnContext.SendActivityAsync(MessageFactory.Text("[lights off]"));
            return "the lights are now off";
        }

        [Action("Pause")]
        public async Task<string> LightsOff([ActionTurnContext] ITurnContext turnContext, [ActionParameters] Dictionary<string, object> args)
        {
            // Try to parse entities returned by the model.
            // Expecting "time" to be a number of milliseconds to pause.
            if (args.TryGetValue("time", out object? time))
            {
                if (time != null && time is string timeString)
                {
                    if (int.TryParse(timeString, out int timeInt))
                    {
                        await turnContext.SendActivityAsync(MessageFactory.Text($"[pausing for {timeInt / 1000} seconds]"));
                        await Task.Delay(timeInt);
                    }
                }
            }

            return "done pausing";
        }

        [Action("LightStatus")]
        public async Task<string> LightStatus([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] AppState turnState)
        {
            await turnContext.SendActivityAsync(ResponseGenerator.LightStatus(turnState.Conversation!.LightsOn));
            return turnState.Conversation!.LightsOn ? "the lights are on" : "the lights are off";
        }

        [Action(AIConstants.UnknownActionName)]
        public async Task<string> UnknownAction([ActionTurnContext] TurnContext turnContext, [ActionName] string action)
        {
            await turnContext.SendActivityAsync(ResponseGenerator.UnknownAction(action ?? "Unknown"));
            return "unknown action";
        }
    }
}

使用序列、独白或工具扩充可防止模型产生无效函数名称、作名称或参数的幻觉。 创建作文件以:

  • 定义用于提示扩充的作。
  • 指示何时执行作。

例如,在轻型机器人中 actions.json ,该文件可能会列出如下所示的作:

[
    {
        "name": "LightsOn",
        "description": "Turns on the lights"
    },
    {
        "name": "LightsOff",
        "description": "Turns off the lights"
    },
    {
        "name": "Pause",
        "description": "Delays for a period of time",
        "parameters": {
            "type": "object",
            "properties": {
                "time": {
                    "type": "number",
                    "description": "The amount of time to delay in milliseconds"
                }
            },
            "required": [
                "time"
            ]
        }
    }
]
  • name:需要) (作的名称。
  • description:可选) (作的说明。
  • parameters:定义所需参数的 JSON 架构。

反馈循环有助于验证、更正和优化机器人的交互。 对于 sequence 扩充,请在实现中将 设置为 allow_looping?falseAIOptionsmax_repair_attempts0 设置为 来禁用循环。

管理历史记录

MaxHistoryMessages使用 和 MaxConversationHistoryTokens 设置允许 AI 库自动管理对话历史记录。

反馈循环

反馈循环监视和改进机器人交互。 其中包括:

  • 修复Loop:当响应不足以尝试备用解决方案时,创建对话历史记录分支。
  • 验证:验证更正的响应,然后再将其合并回对话。
  • 学习:根据正确的行为示例调整机器人的性能。
  • 复杂命令处理:增强模型随时间推移处理复杂命令的能力。

将传统机器人升级到自定义引擎代理

如果 Teams 上已有机器人,则可以将其升级到支持流式处理、引文和 AI 标签的自定义引擎代理。 此升级使机器人与对话式 AI UX 范例保持一致,并提供声明性代理的一致体验。

注意

Python 不支持自定义引擎代理。

升级步骤:

To-Do 列表 支持文档
更新 AI SDK 版本 • 对于 JavaScript,请更新到 v1.6.1
• 对于 C#,请更新到 v1.8.1
为机器人启用流式处理。 Stream机器人消息
使用 AI 标签指示 AI 生成的消息。 AI 标签
对源引用使用引文。 引文

添加对智能 Microsoft 365 Copilot 副驾驶® 对话助手的支持

可以在 智能 Microsoft 365 Copilot 副驾驶® 对话助手 中添加对自定义引擎代理的支持。 这包括对异步模式的支持,例如后续消息和长时间运行的任务。 有关详细信息,请参阅 异步模式

若要支持智能 Microsoft 365 Copilot 副驾驶® 对话助手,请更新应用清单:

  1. copilotAgents 具有子属性的属性 customEngineAgents 添加到 应用清单

    "copilotAgents": { 
        "customEngineAgents": [ 
          { 
            "type": "bot", 
            "id": "<Bot-Id-Guid>" 
          } 
        ] 
      }
    
  2. scopes personal在应用清单中将 botscommandLists 设置为 :

    "bots": [ 
        { 
          "botId": "<Bot-Id-Guid>", 
          "scopes": [
              "personal",
              "team",
              "groupChat"
          ], 
          "commandLists": [ 
            { 
              "scopes": ["personal"], 
              "commands": [ 
                { 
                  "title": "Sample prompt title", 
                  "description": "Description of sample prompt" 
                } 
              ] 
            }, 
            { 
              "scopes": ["personal"], 
              "commands": [ 
                { 
                  "title": "Sample prompt title", 
                  "description": "Description of sample prompt" 
                } 
              ] 
            } 
          ], 
        } 
      ], 
    

注意

  • 智能 Microsoft 365 Copilot 副驾驶® 对话助手将 AI 生成的标签添加到每个自定义引擎代理响应。
  • 对于使用 Microsoft 365 Agents Toolkit (以前是 Teams 工具包) 构建 智能 Microsoft 365 Copilot 副驾驶® 对话助手的机器人,请遵循分步指南
  • 自定义引擎代理的单一登录 (SSO) 可用,但 Outlook 客户端不支持。 请参阅更新 sso Microsoft Entra应用注册

提升传统机器人以使用 AI

可以将现有传统机器人更新为 AI 提供支持。 添加 AI 层可增强机器人的 LLM 驱动功能。 下面是使用 Bot Framework 适配器和 对象集成 AI 层的示例 app

JavaScript 代码:提升传统机器人以使用 AI

// Create AI components
const model = new OpenAIModel({
    // OpenAI Support
    apiKey: process.env.OPENAI_KEY!,
    defaultModel: 'gpt-4o',

    // Azure OpenAI Support
    azureApiKey: process.env.AZURE_OPENAI_KEY!,
    azureDefaultDeployment: 'gpt-4o',
    azureEndpoint: process.env.AZURE_OPENAI_ENDPOINT!,
    azureApiVersion: '2023-03-15-preview',

    // Request logging
    logRequests: true
});

const prompts = new PromptManager({
    promptsFolder: path.join(__dirname, '../src/prompts')
});

// Define a prompt function for getting the current status of the lights
prompts.addFunction('getLightStatus', async (context: TurnContext, memory: Memory) => {
    return memory.getValue('conversation.lightsOn') ? 'on' : 'off';
});

const planner = new ActionPlanner({
    model,
    prompts,
    defaultPrompt: 'tools'
});

// Define storage and application
const storage = new MemoryStorage();
const app = new Application<ApplicationTurnState>({
    storage,
    ai: {
        planner
    }
});

app.ai.action('LightStatus', async (context: TurnContext, state: ApplicationTurnState) => {
    const status = state.conversation.lightsOn ? 'on' : 'off';
    return `the lights are ${status}`;
});

// Register action handlers
app.ai.action('LightsOn', async (context: TurnContext, state: ApplicationTurnState) => {
    state.conversation.lightsOn = true;
    await context.sendActivity(`[lights on]`);
    return `the lights are now on`;
});

app.ai.action('LightsOff', async (context: TurnContext, state: ApplicationTurnState) => {
    state.conversation.lightsOn = false;
    await context.sendActivity(`[lights off]`);
    return `the lights are now off`;
});

interface PauseParameters {
    time: number;
}

app.ai.action('Pause', async (context: TurnContext, state: ApplicationTurnState, parameters: PauseParameters) => {
    await context.sendActivity(`[pausing for ${parameters.time / 1000} seconds]`);
    await new Promise((resolve) => setTimeout(resolve, parameters.time));
    return `done pausing`;
});

// Listen for incoming server requests.
server.post('/api/messages', async (req, res) => {
    // Route received a request to adapter for processing
    await adapter.process(req, res as any, async (context) => {
        // Dispatch to application for routing
        await app.run(context);
    });
});

迁移机器人以使用 Teams AI 库

如果使用 Bot Framework SDK 构建机器人,则可以迁移到 Teams AI 库来解锁高级 AI 功能。 迁移具有以下优势:

  • 用于构建由 LLM 提供支持的复杂 Teams 应用程序的高级 AI 系统。
  • 用于访问第三方用户数据的集成用户身份验证。
  • 利用熟悉的 Bot Framework SDK 工具和概念。
  • 支持最新的 LLM 工具和 API。

选择机器人语言的相关迁移指南:

迁移 Bot Framework SDK 应用... 若要使用 Teams AI 库...
使用 JavaScript 生成的机器人应用 迁移
使用 C 生成的机器人应用# 迁移
使用 Python 的机器人应用 迁移

代码示例

示例名称 说明 .NET Node.js
作映射 lightbot 演示 LightBot 如何理解用户意图并根据命令控制轻型机器人。 View View

后续步骤

如果要尝试使用代理工具包和 Teams AI 库创建基于方案的自定义引擎代理,请选择以下选项:
高级分步指南

若要了解 Teams AI 库的核心功能,请选择以下项:
了解 Teams AI 库