Public Access
fix: unify pyannote validation toggle
PR and Push Build/Test / build-and-test (push) Successful in 12m8s
PR and Push Build/Test / build-and-test (push) Successful in 12m8s
This commit is contained in:
@@ -18,31 +18,8 @@ public sealed class PyannoteDiarizationWarmupHostedServiceTests
|
||||
NullLogger<PyannoteTranscriptFinalizer>.Instance);
|
||||
var service = new PyannoteDiarizationWarmupHostedService(
|
||||
finalizer,
|
||||
new FakeLaunchProfileOptionsProvider(new MeetingAssistantOptions
|
||||
{
|
||||
Recording = { TranscriptionProvider = "azure-speech" },
|
||||
SpeakerIdentification =
|
||||
{
|
||||
PyannoteValidation =
|
||||
{
|
||||
Enabled = true,
|
||||
Diarization =
|
||||
{
|
||||
Enabled = true,
|
||||
DockerCommand = "docker",
|
||||
Image = "meeting-assistant-pyannote-validation:local",
|
||||
ModelsFolder = Path.Combine(
|
||||
Path.GetTempPath(),
|
||||
"meeting-assistant-tests",
|
||||
Guid.NewGuid().ToString("N"),
|
||||
"models"),
|
||||
Token = "hf_test",
|
||||
TokenEnv = "",
|
||||
CommandTimeout = TimeSpan.FromMinutes(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
new FakeLaunchProfileOptionsProvider(
|
||||
CreateValidationOptions("meeting-assistant-pyannote-validation:local")),
|
||||
NullLogger<PyannoteDiarizationWarmupHostedService>.Instance);
|
||||
|
||||
await service.StartAsync(CancellationToken.None).WaitAsync(TimeSpan.FromSeconds(1));
|
||||
@@ -54,23 +31,87 @@ public sealed class PyannoteDiarizationWarmupHostedServiceTests
|
||||
Assert.True(commandRunner.RunCancellationWasObserved);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HostedServiceUsesApplicationValidationRuntimeInsteadOfNamedProfileOverride()
|
||||
{
|
||||
var commandRunner = new BlockingCommandRunner();
|
||||
var finalizer = new PyannoteTranscriptFinalizer(
|
||||
commandRunner,
|
||||
Options.Create(new MeetingAssistantOptions()),
|
||||
NullLogger<PyannoteTranscriptFinalizer>.Instance);
|
||||
var defaultOptions = CreateValidationOptions("meeting-assistant-pyannote-default:local");
|
||||
var namedOptions = CreateValidationOptions("meeting-assistant-pyannote-named:local");
|
||||
var service = new PyannoteDiarizationWarmupHostedService(
|
||||
finalizer,
|
||||
new FakeLaunchProfileOptionsProvider(
|
||||
[
|
||||
new LaunchProfile("english", namedOptions),
|
||||
new LaunchProfile(ConfigurationLaunchProfileOptionsProvider.DefaultProfileName, defaultOptions)
|
||||
]),
|
||||
NullLogger<PyannoteDiarizationWarmupHostedService>.Instance);
|
||||
|
||||
await service.StartAsync(CancellationToken.None).WaitAsync(TimeSpan.FromSeconds(1));
|
||||
await commandRunner.WaitForRunAsync();
|
||||
|
||||
await service.StopAsync(CancellationToken.None);
|
||||
|
||||
Assert.Contains(commandRunner.Commands, command => command.Arguments.Contains("meeting-assistant-pyannote-default:local"));
|
||||
Assert.DoesNotContain(commandRunner.Commands, command => command.Arguments.Contains("meeting-assistant-pyannote-named:local"));
|
||||
}
|
||||
|
||||
private static MeetingAssistantOptions CreateValidationOptions(string image)
|
||||
{
|
||||
return new MeetingAssistantOptions
|
||||
{
|
||||
Recording = { TranscriptionProvider = "azure-speech" },
|
||||
SpeakerIdentification =
|
||||
{
|
||||
PyannoteValidation =
|
||||
{
|
||||
Enabled = true,
|
||||
Diarization =
|
||||
{
|
||||
DockerCommand = "docker",
|
||||
Image = image,
|
||||
ModelsFolder = Path.Combine(
|
||||
Path.GetTempPath(),
|
||||
"meeting-assistant-tests",
|
||||
Guid.NewGuid().ToString("N"),
|
||||
"models"),
|
||||
Token = "hf_test",
|
||||
TokenEnv = "",
|
||||
CommandTimeout = TimeSpan.FromMinutes(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private sealed class FakeLaunchProfileOptionsProvider : ILaunchProfileOptionsProvider
|
||||
{
|
||||
private readonly MeetingAssistantOptions options;
|
||||
private readonly IReadOnlyList<LaunchProfile> profiles;
|
||||
|
||||
public FakeLaunchProfileOptionsProvider(MeetingAssistantOptions options)
|
||||
: this([new LaunchProfile(ConfigurationLaunchProfileOptionsProvider.DefaultProfileName, options)])
|
||||
{
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public FakeLaunchProfileOptionsProvider(IReadOnlyList<LaunchProfile> profiles)
|
||||
{
|
||||
this.profiles = profiles;
|
||||
}
|
||||
|
||||
public LaunchProfile GetRequiredProfile(string? name)
|
||||
{
|
||||
return new LaunchProfile(ConfigurationLaunchProfileOptionsProvider.DefaultProfileName, options);
|
||||
var profileName = string.IsNullOrWhiteSpace(name)
|
||||
? ConfigurationLaunchProfileOptionsProvider.DefaultProfileName
|
||||
: name;
|
||||
return profiles.Single(profile => profile.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
public IReadOnlyList<LaunchProfile> GetProfiles()
|
||||
{
|
||||
return [GetRequiredProfile(null)];
|
||||
return profiles;
|
||||
}
|
||||
|
||||
public IReadOnlyList<LaunchProfileHotkey> GetHotkeys()
|
||||
|
||||
@@ -2,6 +2,7 @@ using MeetingAssistant;
|
||||
using MeetingAssistant.Recording;
|
||||
using MeetingAssistant.Speakers;
|
||||
using MeetingAssistant.Transcription;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NAudio.Wave;
|
||||
@@ -57,17 +58,49 @@ public sealed class PyannoteSpeakerIdentityMatchValidatorTests
|
||||
Assert.Empty(commandRunner.Commands);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OuterToggleControlsValidationWhenLegacyNestedToggleIsFalse()
|
||||
{
|
||||
var commandRunner = new CapturingCommandRunner(
|
||||
"""
|
||||
__MEETING_ASSISTANT_PYANNOTE_JSON_START__
|
||||
[{"start":0.0,"end":20.0,"speaker":"SPEAKER_00"}]
|
||||
__MEETING_ASSISTANT_PYANNOTE_JSON_END__
|
||||
""");
|
||||
var modelsFolder = Path.Combine(
|
||||
Path.GetTempPath(),
|
||||
"meeting-assistant-tests",
|
||||
Guid.NewGuid().ToString("N"),
|
||||
"models");
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["SpeakerIdentification:PyannoteValidation:Enabled"] = "true",
|
||||
["SpeakerIdentification:PyannoteValidation:Diarization:Enabled"] = "false",
|
||||
["SpeakerIdentification:PyannoteValidation:Diarization:BuildImage"] = "false",
|
||||
["SpeakerIdentification:PyannoteValidation:Diarization:ModelsFolder"] = modelsFolder,
|
||||
["SpeakerIdentification:PyannoteValidation:Diarization:Token"] = "hf_test",
|
||||
["SpeakerIdentification:PyannoteValidation:Diarization:TokenEnv"] = ""
|
||||
})
|
||||
.Build();
|
||||
var configuredOptions = configuration.Get<MeetingAssistantOptions>()!;
|
||||
var validator = CreateValidator(commandRunner, configuredOptions);
|
||||
|
||||
var valid = await validator.ValidateSampleAsync(
|
||||
CreateWav(TimeSpan.FromSeconds(20)),
|
||||
CancellationToken.None);
|
||||
|
||||
Assert.True(valid);
|
||||
Assert.Contains(commandRunner.Commands, command => command.Arguments.Contains("run"));
|
||||
}
|
||||
|
||||
private static PyannoteSpeakerIdentityMatchValidator CreateValidator(
|
||||
CapturingCommandRunner commandRunner,
|
||||
bool enabled = true)
|
||||
{
|
||||
var finalizer = new PyannoteTranscriptFinalizer(
|
||||
return CreateValidator(
|
||||
commandRunner,
|
||||
Options.Create(new MeetingAssistantOptions()),
|
||||
NullLogger<PyannoteTranscriptFinalizer>.Instance);
|
||||
return new PyannoteSpeakerIdentityMatchValidator(
|
||||
finalizer,
|
||||
Options.Create(new MeetingAssistantOptions
|
||||
new MeetingAssistantOptions
|
||||
{
|
||||
SpeakerIdentification = new SpeakerIdentificationOptions
|
||||
{
|
||||
@@ -76,9 +109,8 @@ public sealed class PyannoteSpeakerIdentityMatchValidatorTests
|
||||
Enabled = enabled,
|
||||
MinimumSingleSpeakerCoverage = 0.90,
|
||||
MinimumMatchingKnownSnippetRatio = 1,
|
||||
Diarization = new PyannoteDiarizationOptions
|
||||
Diarization = new PyannoteRuntimeOptions
|
||||
{
|
||||
Enabled = true,
|
||||
BuildImage = false,
|
||||
DockerCommand = "docker",
|
||||
Image = "meeting-assistant-pyannote:local",
|
||||
@@ -94,7 +126,20 @@ public sealed class PyannoteSpeakerIdentityMatchValidatorTests
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
private static PyannoteSpeakerIdentityMatchValidator CreateValidator(
|
||||
CapturingCommandRunner commandRunner,
|
||||
MeetingAssistantOptions configuredOptions)
|
||||
{
|
||||
var finalizer = new PyannoteTranscriptFinalizer(
|
||||
commandRunner,
|
||||
Options.Create(new MeetingAssistantOptions()),
|
||||
NullLogger<PyannoteTranscriptFinalizer>.Instance);
|
||||
return new PyannoteSpeakerIdentityMatchValidator(
|
||||
finalizer,
|
||||
Options.Create(configuredOptions),
|
||||
NullLogger<PyannoteSpeakerIdentityMatchValidator>.Instance);
|
||||
}
|
||||
|
||||
|
||||
@@ -156,9 +156,8 @@ public sealed class PyannoteTranscriptFinalizerTests
|
||||
commandRunner,
|
||||
Options.Create(new MeetingAssistantOptions()),
|
||||
NullLogger<PyannoteTranscriptFinalizer>.Instance);
|
||||
var explicitDiarization = new PyannoteDiarizationOptions
|
||||
var explicitDiarization = new PyannoteRuntimeOptions
|
||||
{
|
||||
Enabled = true,
|
||||
DockerCommand = "docker",
|
||||
BaseImage = "python:3.11-slim",
|
||||
Image = "meeting-assistant-pyannote-azure:local",
|
||||
@@ -169,7 +168,7 @@ public sealed class PyannoteTranscriptFinalizerTests
|
||||
CommandTimeout = TimeSpan.FromMinutes(1)
|
||||
};
|
||||
|
||||
await finalizer.FinalizeAsync(
|
||||
await finalizer.FinalizeEnabledAsync(
|
||||
audioPath,
|
||||
[new TranscriptionSegment(TimeSpan.Zero, TimeSpan.FromSeconds(1), "Unknown", "hello")],
|
||||
explicitDiarization,
|
||||
@@ -186,9 +185,8 @@ public sealed class PyannoteTranscriptFinalizerTests
|
||||
{
|
||||
var commandRunner = new CapturingCommandRunner("");
|
||||
var finalizer = CreateFinalizer(commandRunner, token: "hf_test");
|
||||
var diarization = new PyannoteDiarizationOptions
|
||||
var diarization = new PyannoteRuntimeOptions
|
||||
{
|
||||
Enabled = true,
|
||||
DockerCommand = "docker",
|
||||
BaseImage = "python:3.11-slim",
|
||||
Image = "meeting-assistant-pyannote-warmup:local",
|
||||
@@ -218,9 +216,8 @@ public sealed class PyannoteTranscriptFinalizerTests
|
||||
var commandRunner = new CapturingCommandRunner("");
|
||||
var finalizer = CreateFinalizer(commandRunner, token: null);
|
||||
|
||||
await finalizer.WarmUpAsync(new PyannoteDiarizationOptions
|
||||
await finalizer.WarmUpAsync(new PyannoteRuntimeOptions
|
||||
{
|
||||
Enabled = true,
|
||||
Token = "",
|
||||
TokenEnv = "",
|
||||
ModelsFolder = Path.Combine(Path.GetTempPath(), "meeting-assistant-tests", Guid.NewGuid().ToString("N"), "models")
|
||||
|
||||
Reference in New Issue
Block a user