diff --git a/.gitignore b/.gitignore
index f6904bc1da..bd14707eef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,6 +38,7 @@ bld/
# Visual Studio 2015/2017 cache/options directory
.vs/
+.cr/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
diff --git a/docs/media/foundationallm-highlevel-architecture.png b/docs/media/foundationallm-highlevel-architecture.png
index a6e1f27167..856843b768 100644
Binary files a/docs/media/foundationallm-highlevel-architecture.png and b/docs/media/foundationallm-highlevel-architecture.png differ
diff --git a/docs/release-notes/breaking-changes.md b/docs/release-notes/breaking-changes.md
index 5c83ca97d5..73a1eb72dc 100644
--- a/docs/release-notes/breaking-changes.md
+++ b/docs/release-notes/breaking-changes.md
@@ -53,6 +53,13 @@ Authorization API | `FoundationaLLM-Authorization-API` | `api://FoundationaLLM-A
User Portal | `FoundationaLLM-Core-Portal` | `api://FoundationaLLM-Core-Portal` | N/A
Management Portal | `FoundationaLLM-Management-Portal` | `api://FoundationaLLM-Management-Portal` | N/A
+#### Changes in app configuration settings
+
+The `FoundationaLLM:APIs` and `FoundationaLLM:ExternalAPIs` configuration namespaces have been replaced with the `FoundationaLLM:APIEndpoints` configuration namespace.
+
+> [!IMPORTANT]
+> All existing API registrations need to be updated to reflect these changes. The only setting that will exist under `FoundationaLLM:APIEndpoints` is `APIKey` (for those API enpoints which use API key authentication), all the other settings are now part of the `APIEndpoint` artifact managed by the `FoundationaLLM.Configuration` resource provider.
+
### Pre-0.8.0
1. Vectorization resource stores use a unique collection name, `Resources`. They also add a new top-level property named `DefaultResourceName`.
diff --git a/src/FoundationaLLM.sln b/src/FoundationaLLM.sln
index 768515e1ec..8faaad2998 100644
--- a/src/FoundationaLLM.sln
+++ b/src/FoundationaLLM.sln
@@ -113,6 +113,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagementClient", "dotnet\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Management.Client.Tests", "..\tests\dotnet\Management.Client.Tests\Management.Client.Tests.csproj", "{2B369949-0297-485E-9455-E8F54D078DB3}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AIModel", "dotnet\AIModel\AIModel.csproj", "{58D9C40B-3BE6-42CC-9FAB-ECF20FDA2E84}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GatewayAdapterAPI", "dotnet\GatewayAdapterAPI\GatewayAdapterAPI.csproj", "{F826A354-9DF5-4DE5-97CB-F8F0D4566C0F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "State", "dotnet\State\State.csproj", "{BF7614CE-4E64-4E69-A56D-A7E72EDA8ABD}"
@@ -292,6 +294,10 @@ Global
{2B369949-0297-485E-9455-E8F54D078DB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B369949-0297-485E-9455-E8F54D078DB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B369949-0297-485E-9455-E8F54D078DB3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {58D9C40B-3BE6-42CC-9FAB-ECF20FDA2E84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {58D9C40B-3BE6-42CC-9FAB-ECF20FDA2E84}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {58D9C40B-3BE6-42CC-9FAB-ECF20FDA2E84}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {58D9C40B-3BE6-42CC-9FAB-ECF20FDA2E84}.Release|Any CPU.Build.0 = Release|Any CPU
{F826A354-9DF5-4DE5-97CB-F8F0D4566C0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F826A354-9DF5-4DE5-97CB-F8F0D4566C0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F826A354-9DF5-4DE5-97CB-F8F0D4566C0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -358,6 +364,7 @@ Global
{95676184-9498-465C-B4FE-C67AA09A0397} = {C757E76C-AE42-4700-A92C-ED321D9CDB39}
{69E631C8-3266-4D40-9A7A-D67C07972BE2} = {B6DC1190-2873-44A3-85B3-63D7BDE99231}
{2B369949-0297-485E-9455-E8F54D078DB3} = {C757E76C-AE42-4700-A92C-ED321D9CDB39}
+ {58D9C40B-3BE6-42CC-9FAB-ECF20FDA2E84} = {B6DC1190-2873-44A3-85B3-63D7BDE99231}
{F826A354-9DF5-4DE5-97CB-F8F0D4566C0F} = {B6DC1190-2873-44A3-85B3-63D7BDE99231}
{BF7614CE-4E64-4E69-A56D-A7E72EDA8ABD} = {B6DC1190-2873-44A3-85B3-63D7BDE99231}
{B0D4EBB4-2057-4081-8A80-65390BFBA654} = {B6DC1190-2873-44A3-85B3-63D7BDE99231}
diff --git a/src/dotnet/AIModel/AIModel.csproj b/src/dotnet/AIModel/AIModel.csproj
new file mode 100644
index 0000000000..cdd3b3b8c8
--- /dev/null
+++ b/src/dotnet/AIModel/AIModel.csproj
@@ -0,0 +1,16 @@
+
+
+
+ net8.0
+ enable
+ enable
+ FoundationaLLM.AIModel
+ FoundationaLLM.AIModel
+ True
+
+
+
+
+
+
+
diff --git a/src/dotnet/AIModel/Models/AIModelReference.cs b/src/dotnet/AIModel/Models/AIModelReference.cs
new file mode 100644
index 0000000000..6e5f70159a
--- /dev/null
+++ b/src/dotnet/AIModel/Models/AIModelReference.cs
@@ -0,0 +1,27 @@
+using FoundationaLLM.Common.Constants.ResourceProviders;
+using FoundationaLLM.Common.Exceptions;
+using FoundationaLLM.Common.Models.ResourceProviders;
+using FoundationaLLM.Common.Models.ResourceProviders.AIModel;
+using System.Text.Json.Serialization;
+
+namespace FoundationaLLM.AIModel.Models
+{
+ ///
+ /// Contains a reference to an AIModel
+ ///
+ public class AIModelReference : ResourceReference
+ {
+ ///
+ /// The object type of the data source.
+ ///
+ [JsonIgnore]
+ public Type AIModelType =>
+ Type switch
+ {
+ AIModelTypes.Basic => typeof(AIModelBase),
+ AIModelTypes.Completion => typeof(CompletionAIModel),
+ AIModelTypes.Embedding => typeof(EmbeddingAIModel),
+ _ => throw new ResourceProviderException($"The data source type {Type} is not supported.")
+ };
+ }
+}
diff --git a/src/dotnet/AIModel/ResourceProviders/AIModelResourceProviderService.cs b/src/dotnet/AIModel/ResourceProviders/AIModelResourceProviderService.cs
new file mode 100644
index 0000000000..25cfc93556
--- /dev/null
+++ b/src/dotnet/AIModel/ResourceProviders/AIModelResourceProviderService.cs
@@ -0,0 +1,403 @@
+using Azure.Messaging;
+using FluentValidation;
+using FoundationaLLM.AIModel.Models;
+using FoundationaLLM.Common.Constants;
+using FoundationaLLM.Common.Constants.Configuration;
+using FoundationaLLM.Common.Constants.ResourceProviders;
+using FoundationaLLM.Common.Exceptions;
+using FoundationaLLM.Common.Interfaces;
+using FoundationaLLM.Common.Models.Authentication;
+using FoundationaLLM.Common.Models.Configuration.Instance;
+using FoundationaLLM.Common.Models.Events;
+using FoundationaLLM.Common.Models.ResourceProviders;
+using FoundationaLLM.Common.Models.ResourceProviders.AIModel;
+using FoundationaLLM.Common.Services.ResourceProviders;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System.Collections.Concurrent;
+using System.Text;
+using System.Text.Json;
+
+namespace FoundationaLLM.AIModel.ResourceProviders
+{
+ ///
+ /// Implements the FoundationaLLM.AIModel resource provider.
+ ///
+ /// The options providing the with instance settings.
+ /// The providing authorization services.
+ /// The providing storage services.
+ /// The providing event services.
+ /// The providing the factory to create resource validators.
+ /// The of the main dependency injection container.
+ /// The used to provide loggers for logging.
+ public class AIModelResourceProviderService(
+ IOptions instanceOptions,
+ IAuthorizationService authorizationService,
+ [FromKeyedServices(DependencyInjectionKeys.FoundationaLLM_ResourceProvider_AIModel)] IStorageService storageService,
+ IEventService eventService,
+ IResourceValidatorFactory resourceValidatorFactory,
+ IServiceProvider serviceProvider,
+ ILoggerFactory loggerFactory)
+ : ResourceProviderServiceBase(
+ instanceOptions.Value,
+ authorizationService,
+ storageService,
+ eventService,
+ resourceValidatorFactory,
+ serviceProvider,
+ loggerFactory.CreateLogger(),
+ [
+ EventSetEventNamespaces.FoundationaLLM_ResourceProvider_AIModel
+ ])
+ {
+ ///
+ protected override Dictionary GetResourceTypes() =>
+ AIModelResourceProviderMetadata.AllowedResourceTypes;
+
+ private ConcurrentDictionary _aiModelReferences;
+
+ ///
+ protected override string _name => ResourceProviderNames.FoundationaLLM_AIModel;
+ private const string AIMODEL_REFERENCES_FILE_NAME = "_aiModel-references.json";
+ private const string AIMODEL_REFERENCES_FILE_PATH =
+ $"/{ResourceProviderNames.FoundationaLLM_AIModel}/{AIMODEL_REFERENCES_FILE_NAME}";
+
+ ///
+ protected override async Task InitializeInternal()
+ {
+ _logger.LogInformation("Starting to initialize the {ResourceProvider} resource provider...", _name);
+
+ if (await _storageService.FileExistsAsync(_storageContainerName, AIMODEL_REFERENCES_FILE_PATH, default))
+ {
+ var fileContent = await _storageService.ReadFileAsync(
+ _storageContainerName,
+ AIMODEL_REFERENCES_FILE_PATH,
+ default);
+
+ var resourceReferenceStore =
+ JsonSerializer.Deserialize>(
+ Encoding.UTF8.GetString(fileContent.ToArray()));
+
+ _aiModelReferences = new ConcurrentDictionary(
+ resourceReferenceStore!.ToDictionary());
+ }
+ else
+ {
+ await _storageService.WriteFileAsync(
+ _storageContainerName,
+ AIMODEL_REFERENCES_FILE_PATH,
+ JsonSerializer.Serialize(new ResourceReferenceStore
+ {
+ ResourceReferences = []
+ }),
+ default,
+ default);
+ }
+
+ _logger.LogInformation("The {ResourceProvider} resource provider was successfully initialized.", _name);
+ }
+
+ #region Support for Management API
+
+ ///
+ protected override async Task