// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System.Reflection; using Microsoft.Teams.AI.Annotations; using Microsoft.Teams.AI.Messages; using Microsoft.Teams.AI.Models; using Microsoft.Teams.Common.Extensions; using Microsoft.Teams.Common.Logging; namespace Microsoft.Teams.AI.Prompts; /// /// a prompt that can send/receive text /// messages and expose chat model specific /// features like streaming/functions /// [Obsolete("Microsoft.Teams.AI is deprecated and will be removed by end of summer 2026.")] public interface IChatPrompt : IPrompt { /// /// the message history /// public IList Messages { get; } /// /// the collection of registered functions /// public FunctionCollection Functions { get; } } /// /// a prompt that can send/receive text /// messages and expose chat model specific /// features like streaming/functions /// [Obsolete("Microsoft.Teams.AI is deprecated and will be removed by end of summer 2026.")] public interface IChatPrompt : IChatPrompt { /// /// register an error handler /// public IChatPrompt OnError(Action onError); /// /// register an error handler /// public IChatPrompt OnError(Func onError); /// /// send a message via the prompt using string content /// /// the message text /// the request options /// /// the stream chunk handler (if notnull streaming is enabled) /// /// the models response public Task> Send(string text, RequestOptions? options = null, OnStreamChunk? onChunk = null, CancellationToken cancellationToken = default); /// /// send a message via the prompt using content blocks /// /// the message content /// the request options /// /// the stream chunk handler (if notnull streaming is enabled) /// /// the models response public Task> Send(IContent[] content, RequestOptions? options = null, OnStreamChunk? onChunk = null, CancellationToken cancellationToken = default); /// /// send a message via the prompt /// /// the message to send /// the request options /// /// the stream chunk handler (if notnull streaming is enabled) /// /// the models response public Task> Send(UserMessage message, RequestOptions? options = null, OnStreamChunk? onChunk = null, CancellationToken cancellationToken = default); /// /// send a message via the prompt /// /// the message to send /// the request options /// /// the stream chunk handler (if notnull streaming is enabled) /// /// the models response public Task> Send(UserMessage> message, RequestOptions? options = null, OnStreamChunk? onChunk = null, CancellationToken cancellationToken = default); /// /// options to send when invoking a prompt /// public class RequestOptions { /// /// the conversation history /// public IList? Messages { get; set; } /// /// the model request options /// public TOptions? Request { get; set; } } } /// /// a prompt that can send/receive text /// messages and expose chat model specific /// features like streaming/functions /// [Obsolete("Microsoft.Teams.AI is deprecated and will be removed by end of summer 2026.")] public partial class ChatPrompt : IChatPrompt { public string Name { get; private set; } public string Description { get; private set; } public IList Messages { get; private set; } public FunctionCollection Functions { get; private set; } protected IChatModel Model { get; } protected ITemplate? Template { get; } protected ILogger Logger { get; } protected IList Plugins { get; } protected event EventHandler ErrorEvent; public ChatPrompt(IChatModel model, ChatPromptOptions? options = null) { options ??= new(); Name = options.Name ?? "Chat"; Description = options.Description ?? "an agent you can chat with"; Model = model; Template = options.Instructions; Messages = options.Messages ?? []; Functions = new(); Logger = (options.Logger ?? new ConsoleLogger()).Child($"AI.{Name}"); Plugins = []; ErrorEvent = (_, ex) => Logger.Error(ex); } public ChatPrompt(ChatPrompt prompt) { Name = prompt.Name; Description = prompt.Description; Messages = prompt.Messages; Functions = prompt.Functions; Model = prompt.Model; Template = prompt.Template; Logger = prompt.Logger; Plugins = prompt.Plugins; ErrorEvent = prompt.ErrorEvent; } public ChatPrompt(string name, ChatPrompt prompt) { Name = name; Description = prompt.Description; Messages = prompt.Messages; Functions = prompt.Functions; Model = prompt.Model; Template = prompt.Template; Logger = prompt.Logger.Peer(name); Plugins = prompt.Plugins; ErrorEvent = prompt.ErrorEvent; } /// /// create a ChatPrompt from any class /// utilizing the ChatPromptAttribute /// /// the model to use /// the class instance to use /// a ChatPrompt public static ChatPrompt From(IChatModel model, T value, ChatPromptOptions? options = null) where T : class { var type = value.GetType(); var promptAttribute = type.GetCustomAttribute(); var nameAttribute = type.GetCustomAttribute(); var descriptionAttribute = type.GetCustomAttribute(); var instructionsAttribute = type.GetCustomAttribute(); if (promptAttribute is null) { throw new Exception("only types utilizing the ChatPromptAttribute can be turned into a ChatPrompt"); } var name = promptAttribute.Name ?? nameAttribute?.Name ?? type.Name; var description = promptAttribute.Description ?? descriptionAttribute?.Description; var instructions = promptAttribute.Instructions ?? instructionsAttribute?.Instructions; options ??= new(); options.WithName(name); if (description is not null) { options = options.WithDescription(description); } if (instructions is not null) { options = options.WithInstructions(instructions); } var prompt = new ChatPrompt(model, options); foreach (var method in type.GetMethods()) { var functionAttribute = method.GetCustomAttribute(); var functionDescriptionAttribute = method.GetCustomAttribute(); if (functionAttribute is null) continue; var function = new Function( functionAttribute.Name ?? method.Name, functionAttribute.Description ?? functionDescriptionAttribute?.Description, method.CreateDelegate(value) ); prompt.Function(function); } foreach (var fields in type.GetFields()) { var chatPluginAttribute = fields.GetCustomAttribute(); if (chatPluginAttribute is null) continue; var plugin = fields.GetValue(value); if (plugin is IChatPlugin chatPlugin) { prompt.Plugin(chatPlugin); } } return prompt; } }