// 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;
}
}