Skip to content

Commit

Permalink
Add AI summary API. (#1996)
Browse files Browse the repository at this point in the history
* Add AI project reference and GetSummary operation.

* Update tools and ai library reference.

* Add features operation.

* Fix parameter order.

* Let signed in users call the summary method.

* Cache feature list.

* Add semantic kernel reference to all web apps.

* Update to the newest sn AI libraries.
  • Loading branch information
tusmester committed Jan 4, 2024
1 parent 9c1b489 commit 7d0334c
Show file tree
Hide file tree
Showing 20 changed files with 199 additions and 10 deletions.
44 changes: 44 additions & 0 deletions src/Services.Core/Operations/AIOperations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using SenseNet.AI.Text;
using SenseNet.ApplicationModel;
using SenseNet.ContentRepository;
using System;
using System.Threading.Tasks;

namespace SenseNet.Services.Core.Operations;

// ReSharper disable once InconsistentNaming
public static class AIOperations
{
/// <summary>
/// Gets the summary of a long text using AI.
/// </summary>
/// <snCategory>AI</snCategory>
/// <param name="content"></param>
/// <param name="maxWordCount">Maximum number of words in the summary.</param>
/// <param name="maxSentenceCount">Maximum number of sentences in the summary.</param>
/// <param name="context"></param>
/// <param name="text">A long text to create summary from.</param>
/// <returns>An object containing the summary.</returns>
[ODataAction]
[ContentTypes(N.CT.PortalRoot)]
[AllowedRoles(N.R.Everyone)]
public static async Task<object> GetSummary(Content content, HttpContext context,
int maxWordCount, int maxSentenceCount, string text)
{
//TODO: limit max parameters and text length by configuration
//TODO: add caller permissions: allowed roles

var summaryProvider = context.RequestServices.GetService<ISummaryProvider>() ??
throw new InvalidOperationException("AI summary provider is not available.");

var summary = await summaryProvider.GetSummary(text, maxWordCount, maxSentenceCount,
context.RequestAborted).ConfigureAwait(false);

return new
{
summary
};
}
}
110 changes: 110 additions & 0 deletions src/Services.Core/Operations/FeatureOperations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SenseNet.ApplicationModel;
using SenseNet.ContentRepository;
using SenseNet.Tools.Features;
using Task = System.Threading.Tasks.Task;

namespace SenseNet.Services.Core.Operations;

// ReSharper disable once InconsistentNaming
public static class FeatureOperations
{
#region Helper classes

/// <summary>
/// View object for feature information.
/// </summary>
internal class FeatureInfo
{
public string Name { get; set; }
public string DisplayName { get; set; }
public FeatureAvailabilityInfo State { get; set; }
}

/// <summary>
/// View object for feature availability.
/// </summary>
internal class FeatureAvailabilityInfo
{
/// <summary>
/// State of the feature.
/// </summary>
public string State { get; private set; }

/// <summary>
/// Reason if the feature is not available.
/// </summary>
public string Reason { get; private set; }

/// <summary>
/// Last time the feature was available.
/// </summary>
public DateTime? LastAvailable { get; private set; }

internal static FeatureAvailabilityInfo FromFeatureAvailability(FeatureAvailability featureAvailability)
{
return new FeatureAvailabilityInfo
{
State = featureAvailability.State.ToString(),
Reason = featureAvailability.Reason,
LastAvailable = featureAvailability.LastAvailable
};
}
}

#endregion

// private in-memory cache for the feature list
private static readonly IMemoryCache FeatureCache = new MemoryCache(new MemoryCacheOptions());

/// <summary>
/// Gets the list of registered features.
/// </summary>
/// <returns></returns>
[ODataFunction]
[ContentTypes(N.CT.PortalRoot)]
[AllowedRoles(N.R.Everyone)]
public static async Task<object> GetFeatures(Content content, HttpContext context)
{
const string cacheKey = "features";

if (FeatureCache.TryGetValue(cacheKey, out var cachedFeatures))
return cachedFeatures;

var logger = context.RequestServices.GetRequiredService<ILogger<FeatureInfo>>();
var snFeatures = context.RequestServices.GetServices<ISnFeature>();

logger.LogTrace("Collecting available features.");

var features = await Task.WhenAll(snFeatures.Select(async snFeature =>
{
var state = await snFeature.GetStateAsync(context.RequestAborted).ConfigureAwait(false);
var featureInfo = new FeatureInfo
{
Name = snFeature.Name,
DisplayName = snFeature.DisplayName,
State = FeatureAvailabilityInfo.FromFeatureAvailability(state)
};
//TODO: permission check for certain features
return featureInfo;
}));

logger.LogTrace("Adding feature list with {count} items to the cache.", features.Length);

FeatureCache.Set(cacheKey, features, TimeSpan.FromSeconds(30));

return new
{
features
};
}
}
3 changes: 2 additions & 1 deletion src/Services.Core/SenseNet.Services.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.0" />
<PackageReference Include="SenseNet.Tools" Version="3.2.12" />
<PackageReference Include="SenseNet.AI.Text" Version="0.0.1.2" />
<PackageReference Include="SenseNet.Tools" Version="3.2.12.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="SenseNet.Tools" Version="3.2.12" />
</ItemGroup>

<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion src/Tests/SenseNet.Tests.Core/SenseNet.Tests.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
<PackageReference Include="SenseNet.Tools" Version="3.2.12" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
Expand All @@ -7,6 +7,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.9" />
<PackageReference Include="SenseNet.AI.Text.SemanticKernel" Version="0.0.1.2" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="Serilog.Sinks.Graylog" Version="2.3.0" />
</ItemGroup>
Expand Down
6 changes: 5 additions & 1 deletion src/WebApps/SnWebApplication.Api.InMem.Admin/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ public void ConfigureServices(IServiceCollection services)
.AddSenseNetInMemoryProviders()
.AddSenseNetOData()
.AddSenseNetWebHooks()
.AddSenseNetWopi();
.AddSenseNetWopi()
.AddSenseNetSemanticKernel(options =>
{
Configuration.Bind("sensenet:ai:SemanticKernel", options);
});
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.9" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="SenseNet.AI.Text.SemanticKernel" Version="0.0.1.2" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="Serilog.Sinks.Graylog" Version="2.3.0" />
</ItemGroup>
Expand Down
6 changes: 5 additions & 1 deletion src/WebApps/SnWebApplication.Api.InMem.TokenAuth/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ public void ConfigureServices(IServiceCollection services)
.AddSenseNetInMemoryProviders()
.AddSenseNetOData()
.AddSenseNetWebHooks()
.AddSenseNetWopi();
.AddSenseNetWopi()
.AddSenseNetSemanticKernel(options =>
{
Configuration.Bind("sensenet:ai:SemanticKernel", options);
});
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.9" />
<PackageReference Include="SenseNet.AI.Text.SemanticKernel" Version="0.0.1.2" />
<PackageReference Include="SenseNet.Search.Lucene29.Local" Version="7.4.10" />
<PackageReference Include="SenseNet.Security.EFCSecurityStore" Version="3.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
Expand Down
6 changes: 5 additions & 1 deletion src/WebApps/SnWebApplication.Api.Sql.Admin/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ public void ConfigureServices(IServiceCollection services)
})
.AddSenseNetOData()
.AddSenseNetWebHooks()
.AddSenseNetWopi();
.AddSenseNetWopi()
.AddSenseNetSemanticKernel(options =>
{
Configuration.Bind("sensenet:ai:SemanticKernel", options);
});

// [sensenet]: statistics overrides
var statOptions = new StatisticsOptions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.9" />
<PackageReference Include="SenseNet.AI.Text.SemanticKernel" Version="0.0.1.2" />
<PackageReference Include="SenseNet.Messaging.RabbitMQ" Version="1.1.2" />
<PackageReference Include="SenseNet.Search.Lucene29.Centralized.GrpcClient" Version="0.0.12" />
<PackageReference Include="SenseNet.Security.EFCSecurityStore" Version="3.1.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ public void ConfigureServices(IServiceCollection services)
})
.AddSenseNetOData()
.AddSenseNetWebHooks()
.AddSenseNetWopi();
.AddSenseNetWopi()
.AddSenseNetSemanticKernel(options =>
{
Configuration.Bind("sensenet:ai:SemanticKernel", options);
});

// [sensenet]: statistics overrides
var statOptions = new StatisticsOptions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.9" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="SenseNet.AI.Text.SemanticKernel" Version="0.0.1.2" />
<PackageReference Include="SenseNet.Preview.Aspose" Version="7.3.6" />
<PackageReference Include="SenseNet.Messaging.RabbitMQ" Version="1.1.2" />
<PackageReference Include="SenseNet.Search.Lucene29.Centralized.GrpcClient" Version="0.0.12" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ public void ConfigureServices(IServiceCollection services)
{
options.SkipLicenseCheck =
Configuration.GetValue("sensenet:AsposePreviewProvider:SkipLicenseCheck", false);
})
.AddSenseNetSemanticKernel(options =>
{
Configuration.Bind("sensenet:ai:SemanticKernel", options);
});

// [sensenet]: statistics overrides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.9" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="SenseNet.AI.Text.SemanticKernel" Version="0.0.1.2" />
<PackageReference Include="SenseNet.Messaging.RabbitMQ" Version="1.1.2" />
<PackageReference Include="SenseNet.Search.Lucene29.Centralized.GrpcClient" Version="0.0.12" />
<PackageReference Include="SenseNet.Security.EFCSecurityStore" Version="3.1.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ public void ConfigureServices(IServiceCollection services)
})
.AddSenseNetOData()
.AddSenseNetWebHooks()
.AddSenseNetWopi();
.AddSenseNetWopi()
.AddSenseNetSemanticKernel(options =>
{
Configuration.Bind("sensenet:ai:SemanticKernel", options);
});

// [sensenet]: statistics overrides
var statOptions = new StatisticsOptions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.9" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="SenseNet.AI.Text.SemanticKernel" Version="0.0.1.2" />
<PackageReference Include="SenseNet.Preview.Aspose" Version="7.3.6" />
<PackageReference Include="SenseNet.Search.Lucene29.Local" Version="7.4.10" />
<PackageReference Include="SenseNet.Security.EFCSecurityStore" Version="3.1.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.9" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="SenseNet.AI.Text.SemanticKernel" Version="0.0.1.2" />
<PackageReference Include="SenseNet.Search.Lucene29.Local" Version="7.4.10" />
<PackageReference Include="SenseNet.Security.EFCSecurityStore" Version="3.1.0" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
Expand Down
6 changes: 5 additions & 1 deletion src/WebApps/SnWebApplication.Api.Sql.TokenAuth/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ public void ConfigureServices(IServiceCollection services)
})
.AddSenseNetOData()
.AddSenseNetWebHooks()
.AddSenseNetWopi();
.AddSenseNetWopi()
.AddSenseNetSemanticKernel(options =>
{
Configuration.Bind("sensenet:ai:SemanticKernel", options);
});

// [sensenet]: statistics overrides
var statOptions = new StatisticsOptions();
Expand Down

0 comments on commit 7d0334c

Please sign in to comment.