Skip to content

Commit

Permalink
feature
Browse files Browse the repository at this point in the history
  • Loading branch information
singhk97 committed Jan 23, 2025
1 parent 6ee2b26 commit 4f70e7f
Show file tree
Hide file tree
Showing 12 changed files with 326 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.Bot.Connector;
using Microsoft.Bot.Schema;
using Microsoft.Bot.Schema.Teams;
using Microsoft.Teams.AI.Application;
using Microsoft.Teams.AI.State;
using Microsoft.Teams.AI.Tests.TestUtils;
using Moq;
Expand Down Expand Up @@ -1946,6 +1947,58 @@ void CaptureSend(Activity[] arg)
Assert.Equivalent(expectedInvokeResponse, activitiesToSend[0].Value);
}

[Fact]
public async Task Test_OnMessageFetchTask()
{
// Arrange
Activity[]? activitiesToSend = null;
void CaptureSend(Activity[] arg)
{
activitiesToSend = arg;
}
var adapter = new SimpleAdapter(CaptureSend);
var activity1 = new Activity
{
Type = ActivityTypes.Invoke,
Name = "message/fetchTask",
ChannelId = Channels.Msteams,
Recipient = new() { Id = "recipientId" },
Conversation = new() { Id = "conversationId" },
From = new() { Id = "fromId" },
};
var turnContext1 = new TurnContext(adapter, activity1);
var messageFetchTaskResponse = new Mock<MessageFetchTaskResponse>();
var expectedInvokeResponse = new InvokeResponse()
{
Status = 200,
Body = messageFetchTaskResponse.Object
};
var turnState = TurnStateConfig.GetTurnStateWithConversationStateAsync(turnContext1);
var app = new Application<TurnState>(new()
{
RemoveRecipientMention = false,
StartTypingTimer = false,
TurnStateFactory = () => turnState.Result,
});
var names = new List<string>();
app.OnMessageFetchTask((turnContext, _, _, _) =>
{
names.Add(turnContext.Activity.Name);
return Task.FromResult(messageFetchTaskResponse.Object);
});

// Act
await app.OnTurnAsync(turnContext1);

// Assert
Assert.Single(names);
Assert.Equal("message/fetchTask", names[0]);
Assert.NotNull(activitiesToSend);
Assert.Single(activitiesToSend);
Assert.Equal("invokeResponse", activitiesToSend[0].Type);
Assert.Equivalent(expectedInvokeResponse, activitiesToSend[0].Value);
}

[Fact]
public async Task Test_OnConfigSubmit()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public AI(AIOptions<TState> options, ILoggerFactory? loggerFactory = null)
_actions = new ActionCollection<TState>();

// Import default actions
ImportActions(new DefaultActions<TState>(options.EnableFeedbackLoop, loggerFactory));
ImportActions(new DefaultActions<TState>(options.EnableFeedbackLoop, options.FeedbackLoopType, loggerFactory));
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public sealed class AIOptions<TState> where TState : TurnState
/// </summary>
public bool EnableFeedbackLoop { get; set; } = false;

/// <summary>
/// Represents the type of feedback loop. Set to "default" by default. It can be set to one of "default" or "custom".
/// </summary>
public string FeedbackLoopType { get; set; } = "default";

/// <summary>
/// Initializes a new instance of the <see cref="AIOptions{TState}"/> class.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public class ClientCitation
/// Required. Number and position of the citation.
/// </summary>
[JsonProperty(PropertyName = "position")]
public string Position { get; set; } = string.Empty;
public int Position { get; set; }

/// <summary>
/// The citation's appearance.
Expand All @@ -88,7 +88,7 @@ public class ClientCitationAppearance
public string AtType = "DigitalDocument";

/// <summary>
/// Name of the document.
/// Name of the document (max length 80).
/// </summary>
[JsonProperty(PropertyName = "name")]
public string Name { get; set; } = string.Empty;
Expand All @@ -106,13 +106,14 @@ public class ClientCitationAppearance
public string? Url { get; set; }

/// <summary>
/// Content of the citation. Must be clipped if longer than 480 characters.
/// Extract of the referenced content (max length 160).
/// </summary>
[JsonProperty(PropertyName = "abstract")]
public string Abstract { get; set; } = string.Empty;

/// <summary>
/// Optional. Encoding format of the `citation.appearance.text` field.
/// Optional. Encoding format of the `citation.appearance.text` field.
/// It should be one of "text/html" or "application/vnd.microsoft.card.adaptive".
/// </summary>
[JsonProperty(PropertyName = "encodingFormat")]
public string? EncodingFormat { get; set; }
Expand All @@ -121,7 +122,7 @@ public class ClientCitationAppearance
/// The icon provided in the citation ui.
/// </summary>
[JsonProperty(PropertyName = "image")]
public string? Image { get; set; }
public AppearanceImage? Image { get; set; }

/// <summary>
/// Optional. Set the keywords.
Expand Down Expand Up @@ -207,4 +208,123 @@ public class SensitivityUsageInfoPattern
[JsonProperty(PropertyName = "termCode")]
public string? TermCode { get; set; }
}

/// <summary>
/// Represents how the citation will be rendered.
/// </summary>
public class AppearanceImage
{
/// <summary>
/// Required. Must be "ImageObject".
/// </summary>
[JsonProperty(PropertyName = "@type")]
public string Type { get; set; } = "ImageObject";

/// <summary>
/// The image/icon name. It should be one of <see cref="ClientCitationIconName"/>
/// </summary>
[JsonProperty(PropertyName = "name")]
public string Name { get; set; } = string.Empty;
}

/// <summary>
/// Represents the different possible values for the client citation icon name.
/// </summary>
public static class ClientCitationIconName
{
/// <summary>
/// Represents the Microsoft Word icon name.
/// </summary>
public static readonly string MicrosoftWord = "Microsoft Word";

/// <summary>
/// Represents the Microsoft Excel icon name.
/// </summary>
public static readonly string MicrosoftExcel = "Microsoft Excel";

/// <summary>
/// Represents the Microsoft PowerPoint icon name.
/// </summary>
public static readonly string MicrosoftPowerPoint = "Microsoft PowerPoint";

/// <summary>
/// Represents the Microsoft Visio icon name.
/// </summary>
public static readonly string MicrosoftVisio = "Microsoft Visio";

/// <summary>
/// Represents the Microsoft Loop icon name.
/// </summary>
public static readonly string MicrosoftLoop = "Microsoft Loop";

/// <summary>
/// Represents the Microsoft Whiteboard icon name.
/// </summary>
public static readonly string MicrosoftWhiteboard = "Microsoft Whiteboard";

/// <summary>
/// Represents the Adobe Illustrator icon name.
/// </summary>
public static readonly string AdobeIllustrator = "Adobe Illustrator";

/// <summary>
/// Represents the Adobe Photoshop icon name.
/// </summary>
public static readonly string AdobePhotoshop = "Adobe Photoshop";

/// <summary>
/// Represents the Adobe InDesign icon name.
/// </summary>
public static readonly string AdobeInDesign = "Adobe InDesign";

/// <summary>
/// Represents the Adobe Flash icon name.
/// </summary>
public static readonly string AdobeFlash = "Adobe Flash";

/// <summary>
/// Represents the Sketch icon name.
/// </summary>
public static readonly string Sketch = "Sketch";

/// <summary>
/// Represents the Source Code icon name.
/// </summary>
public static readonly string SourceCode = "Source Code";

/// <summary>
/// Represents the Image icon name.
/// </summary>
public static readonly string Image = "Image";

/// <summary>
/// Represents the GIF icon name.
/// </summary>
public static readonly string GIF = "GIF";

/// <summary>
/// Represents the Video icon name.
/// </summary>
public static readonly string Video = "Video";

/// <summary>
/// Represents the Sound icon name.
/// </summary>
public static readonly string Sound = "Sound";

/// <summary>
/// Represents the ZIP icon name.
/// </summary>
public static readonly string ZIP = "ZIP";

/// <summary>
/// Represents the Text icon name.
/// </summary>
public static readonly string Text = "Text";

/// <summary>
/// Represents the PDF icon name.
/// </summary>
public static readonly string PDF = "PDF";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ internal class DefaultActions<TState> where TState : TurnState
{
private readonly ILogger _logger;
private readonly bool _enableFeedbackLoop;
private readonly string _feedbackLoopType;

public DefaultActions(bool enableFeedbackLoop = false, ILoggerFactory? loggerFactory = null)
public DefaultActions(bool enableFeedbackLoop = false, string feedbackLoopType = "default", ILoggerFactory? loggerFactory = null)
{
_feedbackLoopType = feedbackLoopType;
_enableFeedbackLoop = enableFeedbackLoop;
_logger = loggerFactory is null ? NullLogger.Instance : loggerFactory.CreateLogger(typeof(DefaultActions<TState>));
}
Expand Down Expand Up @@ -113,7 +115,7 @@ public async Task<string> SayCommandAsync([ActionTurnContext] ITurnContext turnC

citations.Add(new ClientCitation()
{
Position = $"{i + 1}",
Position = i + 1,
Appearance = new ClientCitationAppearance()
{
Name = citation.Title,
Expand All @@ -130,10 +132,26 @@ public async Task<string> SayCommandAsync([ActionTurnContext] ITurnContext turnC
// If there are citations, filter out the citations unused in content.
List<ClientCitation>? referencedCitations = citations.Count > 0 ? CitationUtils.GetUsedCitations(contentText, citations) : new List<ClientCitation>();

object? channelData = isTeamsChannel ? new
object? channelData = null;
if (isTeamsChannel)
{
feedbackLoopEnabled = _enableFeedbackLoop
} : null;
if (_enableFeedbackLoop)
{
channelData = new
{
feedbackLoopEnabled = true,
feedbackLoopType = _feedbackLoopType
};
}
else
{
channelData = new
{
feedbackLoopEnabled = false

};
}
}

AIEntity entity = new();
if (referencedCitations != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public class LLMClient<TContent>
private readonly string? _startStreamingMessage;
private ResponseReceivedHandler? _endStreamHandler;
private bool? _enableFeedbackLoop;
private string? _feedbackLoopType;

/// <summary>
/// Creates a new `LLMClient` instance.
Expand All @@ -87,6 +88,7 @@ public LLMClient(LLMClientOptions<TContent> options, ILoggerFactory? loggerFacto
this._startStreamingMessage = Options.StartStreamingMessage;
this._endStreamHandler = Options.EndStreamHandler;
this._enableFeedbackLoop = Options.EnableFeedbackLoop;
this._feedbackLoopType = Options.FeedbackLoopType;
}

/// <summary>
Expand Down Expand Up @@ -180,6 +182,11 @@ public async Task<PromptResponse> CompletePromptAsync(
if (this._enableFeedbackLoop != null)
{
streamer.EnableFeedbackLoop = this._enableFeedbackLoop;

if (streamer.EnableFeedbackLoop == true && this._feedbackLoopType != null)
{
streamer.FeedbackLoopType = this._feedbackLoopType;
}
}

streamer.EnableGeneratedByAILabel = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ public class LLMClientOptions<TContent>
/// </summary>
public bool? EnableFeedbackLoop { get; set; }

/// <summary>
/// Optional. Represents the type of feedback loop. It can be set to one of "default" or "custom".
/// </summary>
public string? FeedbackLoopType { get; set; }

/// <summary>
/// Creates an instance of `LLMClientOptions`
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public class ActionPlanner<TState> : IPlanner<TState> where TState : TurnState

private bool _enableFeedbackLoop;

private string? _feedbackLoopType;

/// <summary>
/// Creates a new `ActionPlanner` instance.
/// </summary>
Expand Down Expand Up @@ -108,6 +110,10 @@ public async Task<Plan> ContinueTaskAsync(ITurnContext context, TState state, AI
PromptTemplate template = await this.Options.DefaultPrompt(context, state, this);

this._enableFeedbackLoop = ai.Options.EnableFeedbackLoop;
if (this._enableFeedbackLoop)
{
this._feedbackLoopType = ai.Options.FeedbackLoopType;
}

PromptResponse response = await this.CompletePromptAsync(context, state, template, template.Augmentation, cancellationToken);

Expand Down Expand Up @@ -182,6 +188,7 @@ public async Task<PromptResponse> CompletePromptAsync(
StartStreamingMessage = this.Options.StartStreamingMessage,
EndStreamHandler = this.Options.EndStreamHandler,
EnableFeedbackLoop = this._enableFeedbackLoop,
FeedbackLoopType = this._feedbackLoopType
}, this._logger);

return await client.CompletePromptAsync(context, memory, this.Prompts, cancellationToken);
Expand Down
Loading

0 comments on commit 4f70e7f

Please sign in to comment.