Skip to content

Commit

Permalink
Upgrade to use built-in configs
Browse files Browse the repository at this point in the history
  • Loading branch information
mythz committed Sep 26, 2023
1 parent f9f8a10 commit df68fa0
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 108 deletions.
34 changes: 0 additions & 34 deletions MusicTypeChat.ServiceInterface/AppConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,12 @@

public class AppConfig
{
public GcpConfig? GcpConfig { get; set; }
public S3Config? AwsConfig { get; set; }
public S3Config? R2Config { get; set; }
public AzureConfig? AzureConfig { get; set; }
public SiteConfig Music { get; set; }
public string? NodePath { get; set; }
public string? FfmpegPath { get; set; }
public string? WhisperPath { get; set; }
public int NodeProcessTimeoutMs { get; set; } = 120 * 1000;

public GcpConfig AssertGcpConfig() => GcpConfig ?? throw new Exception($"{nameof(GcpConfig)} is not configured");
public S3Config AssertAwsConfig() => AwsConfig ?? throw new Exception($"{nameof(AwsConfig)} is not configured");
public S3Config AssertR2Config() => R2Config ?? throw new Exception($"{nameof(R2Config)} is not configured");
public AzureConfig AssertAzureConfig() => AzureConfig ?? throw new Exception($"{nameof(AzureConfig)} is not configured");

public SiteConfig GetSiteConfig(string name)
{
return name.ToLower() switch
Expand All @@ -33,29 +24,4 @@ public class SiteConfig
public string? RecognizerId { get; set; }
public string? PhraseSetId { get; set; }
public string? VocabularyName { get; set; }
}


public class GcpConfig
{
public string Project { get; set; }
public string Location { get; set; }
public string Bucket { get; set; }
}

public class S3Config
{
public string? AccountId { get; set; }
public string? AccessKey { get; set; }
public string? SecretKey { get; set; }
public string? Region { get; set; }
public string Bucket { get; set; }
}

public class AzureConfig
{
public string? SpeechKey { get; set; }
public string? SpeechRegion { get; set; }
public string? ConnectionString { get; set; }
public string ContainerName { get; set; }
}
39 changes: 33 additions & 6 deletions MusicTypeChat/Configure.AppHost.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Funq;
using ServiceStack.Aws;
using ServiceStack.Azure;
using ServiceStack.Configuration;
using ServiceStack.Host;
using ServiceStack.IO;
Expand All @@ -14,16 +16,41 @@ public class AppHost : AppHostBase, IHostingStartup
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices((context,services) => {
// Configure ASP.NET Core IOC Dependencies
var appConfig = new AppConfig();
context.Configuration.Bind(nameof(AppConfig), appConfig);
var appConfig = context.Configuration.GetSection(nameof(AppConfig)).Get<AppConfig>();
services.AddSingleton(appConfig);

var aws = context.Configuration.GetSection(nameof(AwsConfig))?.Get<AwsConfig>();
if (aws != null)
{
aws.AccountId ??= Environment.GetEnvironmentVariable("AWS_ACCOUNT_ID");
aws.AccessKey ??= Environment.GetEnvironmentVariable("AWS_ACCESS_KEY_ID");
aws.SecretKey ??= Environment.GetEnvironmentVariable("AWS_SECRET_ACCESS_KEY");
aws.Region ??= Environment.GetEnvironmentVariable("AWS_REGION");
services.AddSingleton(aws);
}

var r2 = context.Configuration.GetSection(nameof(R2Config))?.Get<R2Config>();
if (r2 != null)
{
r2.AccountId ??= Environment.GetEnvironmentVariable("R2_ACCOUNT_ID");
r2.AccessKey ??= Environment.GetEnvironmentVariable("R2_ACCESS_KEY_ID");
r2.SecretKey ??= Environment.GetEnvironmentVariable("R2_SECRET_ACCESS_KEY");
services.AddSingleton(r2);
}

var azure = context.Configuration.GetSection(nameof(AzureConfig))?.Get<AzureConfig>();
if (azure != null)
{
azure.SpeechKey ??= Environment.GetEnvironmentVariable("SPEECH_KEY");
azure.SpeechRegion ??= Environment.GetEnvironmentVariable("SPEECH_REGION");
azure.ConnectionString ??= Environment.GetEnvironmentVariable("AZURE_BLOB_CONNECTION_STRING");
services.AddSingleton(azure);
}

if (!AppTasks.IsRunAsAppTask())
{
appConfig.NodePath = ProcessUtils.FindExePath("node")
?? throw new Exception("Could not resolve path to node");
appConfig.FfmpegPath = ProcessUtils.FindExePath("ffmpeg");
appConfig.WhisperPath = ProcessUtils.FindExePath("whisper");
appConfig.NodePath ??= ProcessUtils.FindExePath("node") ?? throw new Exception("Could not resolve path to node");
appConfig.FfmpegPath ??= ProcessUtils.FindExePath("ffmpeg");
}
});

Expand Down
83 changes: 47 additions & 36 deletions MusicTypeChat/Configure.Speech.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Amazon;
using Amazon.TranscribeService;
using ServiceStack.AI;
using ServiceStack.AI;
using ServiceStack.IO;
using ServiceStack.GoogleCloud;
using ServiceStack.Aws;
using ServiceStack.Azure;
using Amazon.TranscribeService;
using Google.Cloud.Speech.V2;
using Microsoft.CognitiveServices.Speech;
using MusicTypeChat.ServiceInterface;

[assembly: HostingStartup(typeof(MusicTypeChat.ConfigureSpeech))]
Expand All @@ -22,61 +22,72 @@ public void Configure(IWebHostBuilder builder) => builder
if (speechProvider == nameof(GoogleCloudSpeechToText))
{
GoogleCloudConfig.AssertValidCredentials();
services.AddSingleton<ISpeechToText>(c => {
var config = c.Resolve<AppConfig>();
var google = config.AssertGcpConfig();
return new GoogleCloudSpeechToText(SpeechClient.Create(),
new GoogleCloudSpeechConfig {
Project = google.Project,
Location = google.Location,
Bucket = google.Bucket,
RecognizerId = config.Music.RecognizerId,
PhraseSetId = config.Music.PhraseSetId,
}
);
services.AddSingleton<ISpeechToTextFactory>(c => new SpeechToTextFactory
{
Resolve = feature =>
{
var config = c.Resolve<AppConfig>();
var gcp = c.Resolve<GoogleCloudConfig>();
var siteConfig = config.GetSiteConfig(feature);

return new GoogleCloudSpeechToText(
SpeechClient.Create(),
gcp.ToSpeechToTextConfig(x => {
x.RecognizerId = siteConfig.RecognizerId;
x.PhraseSetId = siteConfig.PhraseSetId;
}))
{
VirtualFiles = HostContext.VirtualFiles
};
}
});
}
else if (speechProvider == nameof(AwsSpeechToText))
{
services.AddSingleton<ISpeechToText>(c => {
var config = c.Resolve<AppConfig>();
var a = config.AssertAwsConfig();
return new AwsSpeechToText(new AmazonTranscribeServiceClient(
a.AccessKey, a.SecretKey, RegionEndpoint.GetBySystemName(a.Region)),
new AwsSpeechToTextConfig {
Bucket = a.Bucket,
VocabularyName = config.Music.VocabularyName,
});
services.AddSingleton<ISpeechToTextFactory>(c => new SpeechToTextFactory
{
Resolve = feature =>
{
var config = c.Resolve<AppConfig>();
var aws = c.Resolve<AwsConfig>();
var siteConfig = config.GetSiteConfig(feature);

return new AwsSpeechToText(
new AmazonTranscribeServiceClient(aws.AccessKey, aws.SecretKey, aws.ToRegionEndpoint()),
aws.ToSpeechToTextConfig(x => x.VocabularyName = siteConfig.VocabularyName))
{
VirtualFiles = HostContext.VirtualFiles
};
}
});
}
else if (speechProvider == nameof(AzureSpeechToText))
{
services.AddSingleton<ISpeechToText>(c => {
var az = c.Resolve<AppConfig>().AssertAzureConfig();
var config = SpeechConfig.FromSubscription(az.SpeechKey, az.SpeechRegion);
config.SpeechRecognitionLanguage = "en-US";
return new AzureSpeechToText(config);
});
services.AddSingleton<ISpeechToText>(c =>
new AzureSpeechToText(c.Resolve<AzureConfig>().ToSpeechConfig()));
}
else if (speechProvider == nameof(WhisperApiSpeechToText))
{
services.AddSingleton<ISpeechToText, WhisperApiSpeechToText>();
}
else if (speechProvider == nameof(WhisperLocalSpeechToText))
{
services.AddSingleton<ISpeechToText>(c => new WhisperLocalSpeechToText {
WhisperPath = c.Resolve<AppConfig>().WhisperPath ?? ProcessUtils.FindExePath("whisper"),
TimeoutMs = c.Resolve<AppConfig>().NodeProcessTimeoutMs,
services.AddSingleton<ISpeechToText>(c => {
var config = c.Resolve<AppConfig>();
return new WhisperLocalSpeechToText {
WhisperPath = config.WhisperPath ?? ProcessUtils.FindExePath("whisper"),
TimeoutMs = config.NodeProcessTimeoutMs,
};
});
}
else throw new NotSupportedException($"Unknown SpeechProvider '{speechProvider}'");
})
.ConfigureAppHost(afterConfigure:appHost => {
if (AppTasks.IsRunAsAppTask()) return;

if (appHost.Resolve<ISpeechToText>() is IRequireVirtualFiles requireVirtualFiles)
if (appHost.TryResolve<ISpeechToText>() is IRequireVirtualFiles requireVirtualFiles)
{
requireVirtualFiles.VirtualFiles = appHost.VirtualFiles;
}
});
}
}
36 changes: 18 additions & 18 deletions MusicTypeChat/Configure.Vfs.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Amazon;
using Amazon.S3;
using Google.Cloud.Storage.V1;
using ServiceStack.IO;
using ServiceStack.Aws;
using ServiceStack.Azure;
using ServiceStack.Azure.Storage;
using ServiceStack.GoogleCloud;
using ServiceStack.IO;
using MusicTypeChat.ServiceInterface;
using Amazon.S3;
using Google.Cloud.Storage.V1;

[assembly: HostingStartup(typeof(MusicTypeChat.ConfigureVfs))]

Expand All @@ -22,31 +22,31 @@ public void Configure(IWebHostBuilder builder) => builder
{
GoogleCloudConfig.AssertValidCredentials();
appHost.VirtualFiles = new GoogleCloudVirtualFiles(
StorageClient.Create(), appHost.Resolve<AppConfig>().AssertGcpConfig().Bucket);
StorageClient.Create(), appHost.Resolve<GoogleCloudConfig>().Bucket!);
}
else if (vfsProvider == nameof(S3VirtualFiles))
{
var awsConfig = appHost.Resolve<AppConfig>().AssertAwsConfig();
var aws = appHost.Resolve<AwsConfig>();
appHost.VirtualFiles = new S3VirtualFiles(new AmazonS3Client(
awsConfig.AccessKey,
awsConfig.SecretKey,
RegionEndpoint.GetBySystemName(awsConfig.Region)), awsConfig.Bucket);
aws.AccessKey,
aws.SecretKey,
aws.ToRegionEndpoint()), aws.Bucket);
}
else if (vfsProvider == nameof(R2VirtualFiles))
{
var r2Config = appHost.Resolve<AppConfig>().AssertR2Config();
var r2 = appHost.Resolve<R2Config>();
appHost.VirtualFiles = new R2VirtualFiles(new AmazonS3Client(
r2Config.AccessKey,
r2Config.SecretKey,
r2.AccessKey,
r2.SecretKey,
new AmazonS3Config {
ServiceURL = $"https://{r2Config.AccountId}.r2.cloudflarestorage.com",
}), r2Config.Bucket);
ServiceURL = r2.ToServiceUrl(),
}), r2.Bucket);
}
else if (vfsProvider == nameof(AzureBlobVirtualFiles))
{
var azureConfig = appHost.Resolve<AppConfig>().AssertAzureConfig();
appHost.VirtualFiles = new AzureBlobVirtualFiles(azureConfig.ConnectionString, azureConfig.ContainerName);
var azure = appHost.Resolve<AzureConfig>();
appHost.VirtualFiles = new AzureBlobVirtualFiles(azure.ConnectionString, azure.ContainerName);
}
//else uses default FileSystemVirtualFiles
});
}
}
28 changes: 14 additions & 14 deletions MusicTypeChat/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@
"VfsProvider": "FileSystemVirtualFiles",
"SpeechProvider": "WhisperApiSpeechToText",
"TypeChatProvider": "NodeTypeChat",
"GoogleCloudConfig": {
"Project": "servicestackdemo",
"Location": "global",
"Bucket": "servicestack-typechat"
},
"AwsConfig": {
"Bucket": "servicestack-typechat"
},
"R2Config": {
"Bucket": "servicestack-typechat"
},
"AzureConfig": {
"ContainerName": "servicestack-typechat"
},
"AppConfig": {
"GcpConfig": {
"Project": "servicestackdemo",
"Location": "global",
"Bucket": "servicestack-typechat"
},
"AwsConfig": {
"Bucket": "servicestack-typechat"
},
"R2Config": {
"Bucket": "servicestack-typechat"
},
"AzureConfig": {
"ContainerName": "servicestack-typechat"
},
"Music": {
"GptPath": "gpt/music"
}
Expand Down

0 comments on commit df68fa0

Please sign in to comment.