-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c66fa4b
commit 133d39a
Showing
51 changed files
with
1,128 additions
and
1,218 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
name: todo-java-mongo-aca | ||
name: azure-transcript-search-openai | ||
services: | ||
web: | ||
project: ./webui | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
211 changes: 102 additions & 109 deletions
211
webapi/TranscriptCopilot/Bots/TeamsBot.cs → webapi/Bots/TeamsBot.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,109 +1,102 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
// | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Bot.Builder; | ||
using Microsoft.Bot.Schema; | ||
using Microsoft.SemanticKernel; | ||
using Microsoft.SemanticKernel.AI; | ||
using Microsoft.SemanticKernel.Orchestration; | ||
using Microsoft.SemanticKernel.SkillDefinition; | ||
using SemanticKernel.Service.CopilotChat.Controllers; | ||
using SemanticKernel.Service.CopilotChat.Skills.ChatSkills; | ||
using SemanticKernel.Service.Models; | ||
|
||
namespace TeamsBot.Bots | ||
{ | ||
public class TeamsBot : ActivityHandler | ||
{ | ||
private readonly ChatService _chatService; | ||
private readonly BotState _conversationState; | ||
|
||
public TeamsBot(ChatService chatService, ConversationState conversationState) | ||
{ | ||
_chatService = chatService ?? throw new ArgumentNullException(nameof(chatService)); | ||
_conversationState = conversationState; | ||
} | ||
|
||
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken) | ||
{ | ||
var conversationStateAccessors = _conversationState.CreateProperty<ConversationData>(nameof(ConversationData)); | ||
var conversationData = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData()); | ||
|
||
conversationData.ConversationHistory.Add(turnContext.Activity.Text); | ||
var variables = new List<KeyValuePair<string, string>> | ||
{ | ||
new KeyValuePair<string, string>("History", string.Join("\n\n", conversationData.ConversationHistory)) | ||
}; | ||
|
||
var chatRequest = new ChatRequest { Input = turnContext.Activity.Text, Variables = variables }; | ||
|
||
await turnContext.SendActivitiesAsync(new Activity[] { new Activity { Type = ActivityTypes.Typing } }, cancellationToken); | ||
|
||
SKContext chatResult; | ||
try | ||
{ | ||
chatResult = await _chatService.ExecuteChatAsync(chatRequest); | ||
} | ||
catch | ||
{ | ||
await turnContext.SendActivityAsync("An error occurred while processing the request.", cancellationToken: cancellationToken); | ||
return; | ||
} | ||
|
||
ChatResponse reply = _chatService.CreateChatResponse(chatResult); | ||
var links = reply.Variables.FirstOrDefault(kvp => kvp.Key == "link").Value; | ||
var replyText = reply.Value; | ||
replyText = ConvertLinksToMarkdown(replyText); | ||
|
||
await turnContext.SendActivityAsync(MessageFactory.Text(replyText), cancellationToken); | ||
|
||
if (!string.IsNullOrEmpty(links) && !links.Contains("QH2-TGUlwu4")) | ||
{ | ||
links = links.Replace(" ", Environment.NewLine); | ||
links = links.Replace("/embed", "/v"); | ||
var youtubeLinks = links.Split(Environment.NewLine); | ||
|
||
var card = new HeroCard | ||
{ | ||
Title = "Sources", | ||
Subtitle = "Relevant YouTube Links", | ||
Buttons = youtubeLinks.Select(link => new CardAction(ActionTypes.OpenUrl, link, value: link)).ToList() | ||
}; | ||
|
||
var attachment = MessageFactory.Attachment(card.ToAttachment()); | ||
await turnContext.SendActivityAsync(attachment, cancellationToken); | ||
} | ||
|
||
await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); | ||
} | ||
public static string ConvertLinksToMarkdown(string html) | ||
{ | ||
if (string.IsNullOrEmpty(html)) | ||
{ | ||
return string.Empty; | ||
} | ||
|
||
string pattern = "<a [^>]*href=[“\"](https?[^“\"]+)[“\"][^>]*>([^<]+)<\\/a>"; | ||
return Regex.Replace(html, pattern, "[$2]($1)"); | ||
} | ||
|
||
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken) | ||
{ | ||
var welcomeText = "Hello and welcome!"; | ||
foreach (var member in membersAdded) | ||
{ | ||
if (member.Id != turnContext.Activity.Recipient.Id) | ||
{ | ||
await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText, welcomeText), cancellationToken); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Bot.Builder; | ||
using Microsoft.Bot.Schema; | ||
using AzureVideoChat.Controllers; | ||
using AzureVideoChat.Models; | ||
using AzureVideoChat.Services; | ||
|
||
namespace AzureVideoChat.Bots | ||
{ | ||
public class TeamsBot : ActivityHandler | ||
{ | ||
private readonly ChatService _chatService; | ||
private readonly BotState _conversationState; | ||
|
||
public TeamsBot(ChatService chatService, ConversationState conversationState) | ||
{ | ||
_chatService = chatService ?? throw new ArgumentNullException(nameof(chatService)); | ||
_conversationState = conversationState; | ||
} | ||
|
||
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken) | ||
{ | ||
var conversationStateAccessors = _conversationState.CreateProperty<ConversationData>(nameof(ConversationData)); | ||
var conversationData = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData()); | ||
|
||
conversationData.ConversationHistory.Add(turnContext.Activity.Text); | ||
var variables = new List<KeyValuePair<string, string>> | ||
{ | ||
new KeyValuePair<string, string>("History", string.Join("\n\n", conversationData.ConversationHistory)) | ||
}; | ||
|
||
var chatRequest = new ChatRequest { Input = turnContext.Activity.Text, Variables = variables }; | ||
|
||
await turnContext.SendActivitiesAsync(new Activity[] { new Activity { Type = ActivityTypes.Typing } }, cancellationToken); | ||
|
||
ChatServiceResponse chatResult; | ||
try | ||
{ | ||
chatResult = await _chatService.ExecuteChatAsync(chatRequest); | ||
} | ||
catch | ||
{ | ||
await turnContext.SendActivityAsync("An error occurred while processing the request.", cancellationToken: cancellationToken); | ||
return; | ||
} | ||
|
||
ChatResponse reply = _chatService.CreateChatResponse(chatResult.Result, chatResult.ContextVariables); | ||
var links = reply.Variables.FirstOrDefault(kvp => kvp.Key == "link").Value; | ||
var replyText = reply.Value; | ||
replyText = ConvertLinksToMarkdown(replyText); | ||
|
||
await turnContext.SendActivityAsync(MessageFactory.Text(replyText), cancellationToken); | ||
|
||
if (!string.IsNullOrEmpty(links)) | ||
{ | ||
var references = links.Split(Environment.NewLine); | ||
|
||
var card = new HeroCard | ||
{ | ||
Title = "Sources", | ||
Subtitle = "Relevant Links", | ||
Buttons = references.Select(link => new CardAction(ActionTypes.OpenUrl, link, value: link)).ToList() | ||
}; | ||
|
||
var attachment = MessageFactory.Attachment(card.ToAttachment()); | ||
await turnContext.SendActivityAsync(attachment, cancellationToken); | ||
} | ||
|
||
await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); | ||
} | ||
public static string ConvertLinksToMarkdown(string html) | ||
{ | ||
if (string.IsNullOrEmpty(html)) | ||
{ | ||
return string.Empty; | ||
} | ||
|
||
string pattern = "<a [^>]*href=[“\"](https?[^“\"]+)[“\"][^>]*>([^<]+)<\\/a>"; | ||
return Regex.Replace(html, pattern, "[$2]($1)"); | ||
} | ||
|
||
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken) | ||
{ | ||
var welcomeText = "Hello and welcome!"; | ||
foreach (var member in membersAdded) | ||
{ | ||
if (member.Id != turnContext.Activity.Recipient.Id) | ||
{ | ||
await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText, welcomeText), cancellationToken); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
using System; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using AzureVideoChat.Options; | ||
using AzureVideoChat.Extensions; | ||
|
||
internal static class ConfigServicesExtensions | ||
{ | ||
|
||
internal static IServiceCollection AddOptions(this IServiceCollection services, ConfigurationManager configuration) | ||
{ | ||
// General configuration | ||
services.AddOptions<ServiceOptions>() | ||
.Bind(configuration.GetSection(ServiceOptions.PropertyName)) | ||
.ValidateDataAnnotations() | ||
.ValidateOnStart() | ||
.PostConfigure(options => PropertyTrimmer.TrimStringProperties(options)); | ||
|
||
return services; | ||
} | ||
|
||
internal static IServiceCollection AddCors(this IServiceCollection services) | ||
{ | ||
IConfiguration configuration = services.BuildServiceProvider().GetRequiredService<IConfiguration>(); | ||
string[] allowedOrigins = configuration.GetSection("AllowedOrigins").Get<string[]>() ?? Array.Empty<string>(); | ||
if (allowedOrigins.Length > 0) | ||
{ | ||
services.AddCors(options => | ||
{ | ||
options.AddDefaultPolicy( | ||
policy => | ||
{ | ||
policy.WithOrigins(allowedOrigins) | ||
.AllowAnyHeader(); | ||
}); | ||
}); | ||
} | ||
|
||
return services; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using Azure; | ||
using Azure.Search.Documents; | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Net.Http; | ||
using Azure.Search.Documents.Indexes; | ||
using Azure.Core.Pipeline; | ||
|
||
namespace AzureVideoChat.Connectors.Memory.AzureCognitiveSearchVector | ||
{ | ||
public class AISearchClientManager | ||
{ | ||
private readonly SearchIndexClient _searchIndexClient; | ||
private readonly ConcurrentDictionary<string, SearchClient> _clientsByIndex = new(); | ||
|
||
public AISearchClientManager(string endpoint, string apiKey, HttpClient? httpClient = null) | ||
{ | ||
if (string.IsNullOrEmpty(endpoint)) | ||
throw new ArgumentNullException(nameof(endpoint)); | ||
if (string.IsNullOrEmpty(apiKey)) | ||
throw new ArgumentNullException(nameof(apiKey)); | ||
|
||
AzureKeyCredential credentials = new AzureKeyCredential(apiKey); | ||
|
||
var options = new SearchClientOptions(); | ||
if (httpClient != null) | ||
{ | ||
options.Transport = new HttpClientTransport(httpClient); | ||
} | ||
|
||
_searchIndexClient = new SearchIndexClient(new Uri(endpoint), credentials, options); | ||
} | ||
|
||
public SearchClient GetSearchClient(string indexName) | ||
{ | ||
if (string.IsNullOrEmpty(indexName)) | ||
throw new ArgumentNullException(nameof(indexName)); | ||
|
||
if (!_clientsByIndex.TryGetValue(indexName, out SearchClient client)) | ||
{ | ||
client = _searchIndexClient.GetSearchClient(indexName); | ||
|
||
_clientsByIndex[indexName] = client; | ||
} | ||
|
||
return client; | ||
} | ||
} | ||
} |
Oops, something went wrong.