Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@

var builder = DistributedApplication.CreateBuilder(args);

var apiKeyParameter = builder.AddParameter("github-api-key", secret: true);
var chat = builder.AddGitHubModel("chat", "openai/gpt-4o-mini");

var chat = builder.AddGitHubModel("chat", "openai/gpt-4o-mini")
.WithApiKey(apiKeyParameter);
// To set the GitHub Models API key define the value for the following parameter in User Secrets.
// Alternatively, you can set the environment variable GITHUB_TOKEN and comment the line below.
chat.WithApiKey(builder.AddParameter("github-api-key", secret: true));

builder.AddProject<Projects.GitHubModelsEndToEnd_WebStory>("webstory")
.WithExternalHttpEndpoints()
Expand Down
34 changes: 3 additions & 31 deletions src/Aspire.Hosting.GitHub.Models/GitHubModelsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,36 +28,6 @@ public static IResourceBuilder<GitHubModelsResource> AddGitHubModel(this IDistri
return builder.AddResource(resource);
}

/// <summary>
/// Configures the endpoint for the GitHub Models resource.
/// </summary>
/// <param name="builder">The resource builder.</param>
/// <param name="endpoint">The endpoint URL.</param>
/// <returns>The resource builder.</returns>
public static IResourceBuilder<GitHubModelsResource> WithEndpoint(this IResourceBuilder<GitHubModelsResource> builder, string endpoint)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(endpoint);

builder.Resource.Endpoint = endpoint;
return builder;
}

/// <summary>
/// Configures the API key for the GitHub Models resource.
/// </summary>
/// <param name="builder">The resource builder.</param>
/// <param name="key">The API key.</param>
/// <returns>The resource builder.</returns>
public static IResourceBuilder<GitHubModelsResource> WithApiKey(this IResourceBuilder<GitHubModelsResource> builder, string key)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentException.ThrowIfNullOrEmpty(key);

builder.Resource.Key = key;
return builder;
}

/// <summary>
/// Configures the API key for the GitHub Models resource from a parameter.
/// </summary>
Expand All @@ -69,6 +39,8 @@ public static IResourceBuilder<GitHubModelsResource> WithApiKey(this IResourceBu
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(apiKey);

return WithApiKey(builder, apiKey.Resource.Value);
builder.Resource.Key = apiKey.Resource;

return builder;
}
}
18 changes: 6 additions & 12 deletions src/Aspire.Hosting.GitHub.Models/GitHubModelsResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ namespace Aspire.Hosting.GitHub.Models;
/// </summary>
public class GitHubModelsResource : Resource, IResourceWithConnectionString
{
/// <summary>
/// The default endpoint for GitHub Models.
/// </summary>
public const string DefaultEndpoint = "https://models.github.ai/inference";
internal const string GitHubModelsEndpoint = "https://models.github.ai/inference";

/// <summary>
/// Initializes a new instance of the <see cref="GitHubModelsResource"/> class.
Expand All @@ -23,14 +20,8 @@ public class GitHubModelsResource : Resource, IResourceWithConnectionString
public GitHubModelsResource(string name, string model) : base(name)
{
Model = model;
Endpoint = DefaultEndpoint;
}

/// <summary>
/// Gets or sets the endpoint URL for the GitHub Models service, e.g., "https://models.github.ai/inference".
/// </summary>
public string Endpoint { get; set; }

/// <summary>
/// Gets or sets the model name, e.g., "openai/gpt-4o-mini".
/// </summary>
Expand All @@ -39,11 +30,14 @@ public GitHubModelsResource(string name, string model) : base(name)
/// <summary>
/// Gets or sets the API key for accessing GitHub Models.
/// </summary>
public string? Key { get; set; }
/// <remarks>
/// If not set, the value will be retrieved from the environment variable GITHUB_TOKEN.
/// </remarks>
public ParameterResource Key { get; set; } = new ParameterResource("github-api-key", p => Environment.GetEnvironmentVariable("GITHUB_TOKEN") ?? string.Empty, secret: true);

/// <summary>
/// Gets the connection string expression for the GitHub Models resource.
/// </summary>
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create($"Endpoint={Endpoint};Key={Key};Model={Model};DeploymentId={Model}");
ReferenceExpression.Create($"Endpoint={GitHubModelsEndpoint};Key={Key};Model={Model};DeploymentId={Model}");
}
2 changes: 1 addition & 1 deletion src/Aspire.Hosting.GitHub.Models/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Provides extension methods and resource definitions for a .NET Aspire AppHost to
### Prerequisites

- GitHub account with access to GitHub Models
- GitHub personal access token with appropriate permissions
- GitHub [personal access token](https://docs.github.com/en/github-models/use-github-models/prototyping-with-ai-models#experimenting-with-ai-models-using-the-api) with appropriate permissions

### Install the package

Expand Down
Binary file added src/Shared/GitHub_256x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -17,61 +17,62 @@ public void AddGitHubModelAddsResourceWithCorrectName()

Assert.Equal("github", github.Resource.Name);
Assert.Equal("openai/gpt-4o-mini", github.Resource.Model);
Assert.Equal(GitHubModelsResource.DefaultEndpoint, github.Resource.Endpoint);
}

[Fact]
public void WithEndpointSetsEndpointCorrectly()
public void AddGitHubModelUsesCorrectEndpoint()
{
using var builder = TestDistributedApplicationBuilder.Create();

var customEndpoint = "https://custom.endpoint.com";
var github = builder.AddGitHubModel("github", "openai/gpt-4o-mini")
.WithEndpoint(customEndpoint);

Assert.Equal(customEndpoint, github.Resource.Endpoint);
}

[Fact]
public void WithApiKeySetsKeyCorrectly()
{
using var builder = TestDistributedApplicationBuilder.Create();

var apiKey = "test-api-key";
var github = builder.AddGitHubModel("github", "openai/gpt-4o-mini")
.WithApiKey(apiKey);
var github = builder.AddGitHubModel("github", "openai/gpt-4o-mini");

Assert.Equal(apiKey, github.Resource.Key);
var connectionString = github.Resource.ConnectionStringExpression.ValueExpression;
Assert.Contains("Endpoint=https://models.github.ai/inference", connectionString);
}

[Fact]
public void ConnectionStringExpressionIsCorrectlyFormatted()
{
using var builder = TestDistributedApplicationBuilder.Create();

var github = builder.AddGitHubModel("github", "openai/gpt-4o-mini")
.WithApiKey("test-key");
var github = builder.AddGitHubModel("github", "openai/gpt-4o-mini");

var connectionString = github.Resource.ConnectionStringExpression.ValueExpression;

Assert.Contains("Endpoint=https://models.github.ai/inference", connectionString);
Assert.Contains("Key=test-key", connectionString);
Assert.Contains("Model=openai/gpt-4o-mini", connectionString);
Assert.Contains("DeploymentId=openai/gpt-4o-mini", connectionString);
Assert.Contains("Key=", connectionString);
}

[Fact]
public void WithApiKeySetFromParameter()
{
using var builder = TestDistributedApplicationBuilder.Create();

var randomApiKey = $"test-key";
const string apiKey = "randomkey";

var apiKeyParameter = builder.AddParameter("github-api-key", secret: true);
builder.Configuration["Parameters:github-api-key"] = randomApiKey;
builder.Configuration["Parameters:github-api-key"] = apiKey;

var github = builder.AddGitHubModel("github", "openai/gpt-4o-mini")
.WithApiKey(apiKeyParameter);

Assert.Equal(randomApiKey, github.Resource.Key);
var connectionString = github.Resource.ConnectionStringExpression.ValueExpression;

Assert.Equal(apiKeyParameter.Resource, github.Resource.Key);
Assert.Contains($"Key={apiKey}", connectionString);
}

[Fact]
public void DefaultKeyParameterIsCreated()
{
using var builder = TestDistributedApplicationBuilder.Create();

var github = builder.AddGitHubModel("github", "openai/gpt-4o-mini");

Assert.NotNull(github.Resource.Key);
Assert.Equal("github-api-key", github.Resource.Key.Name);
Assert.True(github.Resource.Key.Secret);
}
}
Loading