Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 65 additions & 16 deletions tests/SemanticKernel.Rankers.LMRanker.Tests/LMRankerDebugTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ public LMRankerDebugTests(ITestOutputHelper output)
if (_kernel != null)
{
_ranker = new LMRanker(_kernel);

// Quick test to see if the AI service is actually working
if (!IsAIServiceWorking())
{
_skipTests = true;
}
}
else
{
Expand Down Expand Up @@ -138,24 +144,31 @@ private static async IAsyncEnumerable<T> CreateAsyncEnumerable<T>(T[] items)
var builder = Kernel.CreateBuilder();

var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile("appsettings.Development.json", optional: true)
.AddEnvironmentVariables()
.Build();

// Try Azure OpenAI first
var azureEndpoint = config.GetValue<string>("AZURE_OPENAI_ENDPOINT");
var azureApiKey = config.GetValue<string>("AZURE_OPENAI_API_KEY");
var azureDeployment = config.GetValue<string>("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4";
// Try Azure OpenAI first (from config or environment)
var azureEndpoint = config.GetValue<string>("AZURE_OPENAI_ENDPOINT") ?? Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
var azureApiKey = config.GetValue<string>("AZURE_OPENAI_API_KEY") ?? Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY");
var azureDeployment = config.GetValue<string>("AZURE_OPENAI_DEPLOYMENT_NAME") ?? Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4";

if (!string.IsNullOrEmpty(azureEndpoint) && !string.IsNullOrEmpty(azureApiKey))
{
builder.AddAzureOpenAIChatCompletion(
deploymentName: azureDeployment,
endpoint: azureEndpoint,
apiKey: azureApiKey
);
return builder.Build();
try
{
builder.AddAzureOpenAIChatCompletion(
deploymentName: azureDeployment,
endpoint: azureEndpoint,
apiKey: azureApiKey
);
return builder.Build();
}
catch
{
// Azure OpenAI configuration failed
}
}

// Try OpenAI
Expand All @@ -164,11 +177,18 @@ private static async IAsyncEnumerable<T> CreateAsyncEnumerable<T>(T[] items)

if (!string.IsNullOrEmpty(openAIKey))
{
builder.AddOpenAIChatCompletion(
modelId: openAIModel,
apiKey: openAIKey
);
return builder.Build();
try
{
builder.AddOpenAIChatCompletion(
modelId: openAIModel,
apiKey: openAIKey
);
return builder.Build();
}
catch
{
// OpenAI configuration failed
}
}

// Try local Ollama (for development)
Expand All @@ -189,6 +209,35 @@ private static async IAsyncEnumerable<T> CreateAsyncEnumerable<T>(T[] items)
return null;
}

/// <summary>
/// Quick check to see if AI services are actually available and working
/// </summary>
private bool IsAIServiceWorking()
{
if (_ranker == null || _kernel == null) return false;

try
{
// Try a very simple scoring operation to test service availability
var testTask = Task.Run(async () =>
{
var testDocs = new[] { "test document" };
await foreach (var result in _ranker.ScoreAsync("test", CreateAsyncEnumerable(testDocs)))
{
return result.Item2 > 0; // If we get a meaningful score, the service is working
Copy link

Copilot AI Sep 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic assumes any positive score indicates a working service, but legitimate scores can be 0 or negative. Consider checking for !double.IsNaN(result.Item2) or a more appropriate threshold based on your scoring model.

Suggested change
return result.Item2 > 0; // If we get a meaningful score, the service is working
return !double.IsNaN(result.Item2); // If we get a valid score, the service is working

Copilot uses AI. Check for mistakes.
}
return false;
});

// Give it 5 seconds to respond, if it times out the service isn't available
return testTask.Wait(5000) && testTask.Result;
}
catch
{
return false;
}
}

public void Dispose()
{
// No explicit disposal needed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ public LMRankerIntegrationTests()
if (_kernel != null)
{
_ranker = new LMRanker(_kernel);

// Quick test to see if the AI service is actually working
if (!IsAIServiceWorking())
{
_skipTests = true;
}
}
else
{
Expand Down Expand Up @@ -86,8 +92,8 @@ public async Task LMRanker_CustomerSupportScenario_RanksCorrectly()
passwordResetDoc.Score.Should().BeGreaterThan(0.6, "password reset document should be highly relevant");

// Related documents should have moderate relevance (adjusted thresholds to be more tolerant)
passwordRequirementsDoc.Score.Should().BeGreaterOrEqualTo(0.15, "password requirements should be somewhat relevant");
loginTroubleDoc.Score.Should().BeGreaterOrEqualTo(0.25, "login trouble should be moderately relevant");
passwordRequirementsDoc.Score.Should().BeGreaterThanOrEqualTo(0.15, "password requirements should be somewhat relevant");
loginTroubleDoc.Score.Should().BeGreaterThanOrEqualTo(0.25, "login trouble should be moderately relevant");

// Unrelated documents should have low relevance (adjusted to be more tolerant)
billingDoc.Score.Should().BeLessThan(0.5, "billing document should not be very relevant");
Expand Down Expand Up @@ -137,8 +143,8 @@ public async Task LMRanker_TechnicalDocumentationScenario_RanksCorrectly()
oauthDoc.Score.Should().BeGreaterThan(0.6, "OAuth document should be highly relevant");

// JWT and REST docs should be moderately relevant (related concepts, adjusted for boundary cases)
jwtDoc.Score.Should().BeGreaterOrEqualTo(0.2, "JWT document should be moderately relevant");
restDoc.Score.Should().BeGreaterOrEqualTo(0.15, "REST API document should be somewhat relevant");
jwtDoc.Score.Should().BeGreaterThanOrEqualTo(0.2, "JWT document should be moderately relevant");
restDoc.Score.Should().BeGreaterThanOrEqualTo(0.15, "REST API document should be somewhat relevant");

// Database security and rate limiting should be less relevant
dbSecurityDoc.Score.Should().BeLessThan(0.6, "database security should be less relevant");
Expand Down Expand Up @@ -236,7 +242,7 @@ public async Task LMRanker_MedicalInformationScenario_RanksCorrectly()
coldDoc.Score.Should().BeGreaterThan(0.7, "common cold document should be highly relevant");

// Flu and allergic rhinitis share some symptoms, should be moderately relevant (adjusted)
fluDoc.Score.Should().BeGreaterOrEqualTo(0.25, "flu document should be somewhat relevant");
fluDoc.Score.Should().BeGreaterThanOrEqualTo(0.25, "flu document should be somewhat relevant");
allergyDoc.Score.Should().BeGreaterThan(0.25, "allergy document should be somewhat relevant");

// Pneumonia and gastroenteritis should be less relevant
Expand Down Expand Up @@ -422,25 +428,32 @@ private static async IAsyncEnumerable<T> CreateAsyncEnumerable<T>(T[] items)
{
var builder = Kernel.CreateBuilder();

var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false)
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile("appsettings.Development.json", optional: true)
.AddEnvironmentVariables()
.Build();

// Try Azure OpenAI first
var azureEndpoint = config.GetValue<string>("AZURE_OPENAI_ENDPOINT");
var azureApiKey = config.GetValue<string>("AZURE_OPENAI_API_KEY");
var azureDeployment = config.GetValue<string>("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4";
// Try Azure OpenAI first (from config or environment)
var azureEndpoint = config.GetValue<string>("AZURE_OPENAI_ENDPOINT") ?? Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
var azureApiKey = config.GetValue<string>("AZURE_OPENAI_API_KEY") ?? Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY");
var azureDeployment = config.GetValue<string>("AZURE_OPENAI_DEPLOYMENT_NAME") ?? Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4";

if (!string.IsNullOrEmpty(azureEndpoint) && !string.IsNullOrEmpty(azureApiKey))
{
builder.AddAzureOpenAIChatCompletion(
deploymentName: azureDeployment,
endpoint: azureEndpoint,
apiKey: azureApiKey
);
return builder.Build();
try
{
builder.AddAzureOpenAIChatCompletion(
deploymentName: azureDeployment,
endpoint: azureEndpoint,
apiKey: azureApiKey
);
return builder.Build();
}
catch
{
// Azure OpenAI configuration failed
}
}

// Try OpenAI
Expand All @@ -449,11 +462,18 @@ private static async IAsyncEnumerable<T> CreateAsyncEnumerable<T>(T[] items)

if (!string.IsNullOrEmpty(openAIKey))
{
builder.AddOpenAIChatCompletion(
modelId: openAIModel,
apiKey: openAIKey
);
return builder.Build();
try
{
builder.AddOpenAIChatCompletion(
modelId: openAIModel,
apiKey: openAIKey
);
return builder.Build();
}
catch
{
// OpenAI configuration failed
}
}

// Try local Ollama (for development)
Expand All @@ -474,6 +494,35 @@ private static async IAsyncEnumerable<T> CreateAsyncEnumerable<T>(T[] items)
return null;
}

/// <summary>
/// Quick check to see if AI services are actually available and working
/// </summary>
private bool IsAIServiceWorking()
{
if (_ranker == null || _kernel == null) return false;

try
{
// Try a very simple scoring operation to test service availability
var testTask = Task.Run(async () =>
{
var testDocs = new[] { "test document" };
await foreach (var result in _ranker.ScoreAsync("test", CreateAsyncEnumerable(testDocs)))
{
return result.Item2 > 0; // If we get a meaningful score, the service is working
Copy link

Copilot AI Sep 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic assumes any positive score indicates a working service, but legitimate scores can be 0 or negative. Consider checking for !double.IsNaN(result.Item2) or a more appropriate threshold based on your scoring model.

Suggested change
return result.Item2 > 0; // If we get a meaningful score, the service is working
return !double.IsNaN(result.Item2); // If we get a valid score, the service is working

Copilot uses AI. Check for mistakes.
}
return false;
});

// Give it 5 seconds to respond, if it times out the service isn't available
return testTask.Wait(5000) && testTask.Result;
}
catch
{
return false;
}
}

public void Dispose()
{
// Kernel doesn't implement IDisposable in current version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ public LMRankerPerformanceTests(ITestOutputHelper output)
if (_kernel != null)
{
_ranker = new LMRanker(_kernel);

// Quick test to see if the AI service is actually working
if (!IsAIServiceWorking())
{
_skipTests = true;
}
}
else
{
Expand Down Expand Up @@ -368,25 +374,32 @@ private static async IAsyncEnumerable<T> CreateAsyncEnumerable<T>(T[] items)
{
var builder = Kernel.CreateBuilder();

var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false)
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile("appsettings.Development.json", optional: true)
.AddEnvironmentVariables()
.Build();

// Try Azure OpenAI first
var azureEndpoint = config.GetValue<string>("AZURE_OPENAI_ENDPOINT");
var azureApiKey = config.GetValue<string>("AZURE_OPENAI_API_KEY");
var azureDeployment = config.GetValue<string>("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4";
// Try Azure OpenAI first (from config or environment)
var azureEndpoint = config.GetValue<string>("AZURE_OPENAI_ENDPOINT") ?? Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
var azureApiKey = config.GetValue<string>("AZURE_OPENAI_API_KEY") ?? Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY");
var azureDeployment = config.GetValue<string>("AZURE_OPENAI_DEPLOYMENT_NAME") ?? Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4";

if (!string.IsNullOrEmpty(azureEndpoint) && !string.IsNullOrEmpty(azureApiKey))
{
builder.AddAzureOpenAIChatCompletion(
deploymentName: azureDeployment,
endpoint: azureEndpoint,
apiKey: azureApiKey
);
return builder.Build();
try
{
builder.AddAzureOpenAIChatCompletion(
deploymentName: azureDeployment,
endpoint: azureEndpoint,
apiKey: azureApiKey
);
return builder.Build();
}
catch
{
// Azure OpenAI configuration failed
}
}

// Try OpenAI
Expand All @@ -395,11 +408,18 @@ private static async IAsyncEnumerable<T> CreateAsyncEnumerable<T>(T[] items)

if (!string.IsNullOrEmpty(openAIKey))
{
builder.AddOpenAIChatCompletion(
modelId: openAIModel,
apiKey: openAIKey
);
return builder.Build();
try
{
builder.AddOpenAIChatCompletion(
modelId: openAIModel,
apiKey: openAIKey
);
return builder.Build();
}
catch
{
// OpenAI configuration failed
}
}

// Try local Ollama (for development)
Expand All @@ -420,6 +440,35 @@ private static async IAsyncEnumerable<T> CreateAsyncEnumerable<T>(T[] items)
return null;
}

/// <summary>
/// Quick check to see if AI services are actually available and working
/// </summary>
private bool IsAIServiceWorking()
{
if (_ranker == null || _kernel == null) return false;

try
{
// Try a very simple scoring operation to test service availability
var testTask = Task.Run(async () =>
{
var testDocs = new[] { "test document" };
await foreach (var result in _ranker.ScoreAsync("test", CreateAsyncEnumerable(testDocs)))
{
return result.Item2 > 0; // If we get a meaningful score, the service is working
Copy link

Copilot AI Sep 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic assumes any positive score indicates a working service, but legitimate scores can be 0 or negative. Consider checking for !double.IsNaN(result.Item2) or a more appropriate threshold based on your scoring model.

Suggested change
return result.Item2 > 0; // If we get a meaningful score, the service is working
return !double.IsNaN(result.Item2); // If we get a valid score, the service is working

Copilot uses AI. Check for mistakes.
}
return false;
});

// Give it 5 seconds to respond, if it times out the service isn't available
return testTask.Wait(5000) && testTask.Result;
}
catch
{
return false;
}
}

public void Dispose()
{
// Kernel doesn't implement IDisposable in current version
Expand Down
Loading