An educational .NET Aspire application demonstrating how to integrate GitHub Models (AI) with a blog summarization service and interactive chat capabilities. This project showcases modern cloud-native development practices using .NET 10, Aspire orchestration, and AI-powered content processing.
This project demonstrates:
- GitHub Models Integration: Using GitHub's AI models (GPT-4o-mini) through the Aspire framework
- Blog Content Summarization: Fetching and summarizing blog content using AI
- Interactive AI Chat: Direct chat interface with GitHub's AI models
- Distributed Application Architecture: Leveraging .NET Aspire for orchestration
- Service Discovery: Automatic service discovery between components
- OpenTelemetry Integration: Built-in observability with metrics, logs, and traces
- Modern .NET Practices: Minimal APIs, dependency injection, interface-based design, and configuration management
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β GitHubModelsPlayground.AppHost β
β (Orchestrator) β
β βββββββββββββββ ββββββββββββββββ βββββββββββββββββ β
β β External β β GitHub Model β β API Service β β
β β Service β β (GPT-4o) β β β β
β βββββββββββββββ ββββββββββββββββ βββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββ
β API Service β
β ββββββββββββββββββ β
β β IBlogService β β
β β IBlogSummarizerβ β
β β IChatClient β β
β ββββββββββββββββββ β
ββββββββββββββββββββββββ
β
ββββββββββββββββββββββββ
β External Blog β
β (aspire.dev) β
ββββββββββββββββββββββββ
-
GitHubModelsPlayground.ApiService
- ASP.NET Core minimal API
- Exposes
/summarizeendpoint for blog content summarization - Exposes
/chatendpoint for interactive AI conversations - Interface-based design for improved testability
-
GitHubModelsPlayground.AppHost
- .NET Aspire orchestrator
- Manages service references and dependencies
- Configures GitHub Models connection
-
GitHubModelsPlayground.ServiceDefaults
- Shared service configurations
- OpenTelemetry setup
- Health checks and resilience patterns
- .NET 10 SDK or later
- Azure Developer CLI (azd)
- GitHub Personal Access Token with access to GitHub Models
- Azure Subscription (for deployment)
-
Clone the repository
git clone https://github.com/yourusername/GitHubModelsPlayground.git cd GitHubModelsPlayground -
Set up GitHub Models access
Configure your GitHub Personal Access Token (PAT):
cd src/GitHubModelsPlayground.AppHost dotnet user-secrets set "GitHub:Token" "your-github-pat-token-here"
How to get a GitHub PAT:
- Go to GitHub Settings > Developer settings > Personal access tokens
- Generate a new token with access to GitHub Models
-
Run locally
cd src/GitHubModelsPlayground.AppHost dotnet runThe Aspire Dashboard will open automatically in your browser.
This project uses Azure Developer CLI (azd) for seamless deployment to Azure Container Apps.
-
Initialize azd (first time only)
azd init
-
Provision and deploy
azd up
This single command will:
- Provision Azure resources (Container Apps, Container Registry, etc.)
- Build and containerize the application
- Deploy to Azure Container Apps
- Configure environment variables
-
Set GitHub token for Azure deployment
azd env set GITHUB_TOKEN "your-github-pat-token-here" azd deploy
The application deploys to Azure Container Apps with:
- Automatic scaling based on load
- Managed identity for secure access
- Built-in observability with Application Insights
- HTTPS endpoint automatically provisioned
Once running, you can test the API endpoints:
# Example: Summarize a blog post from aspire.dev
curl "http://localhost:5000/summarize?slug=whats-new/aspire-13/"Response:
"This is a two-sentence summary of the blog content generated by AI..."# Example: Send a message to the AI chat endpoint
curl -X POST "http://localhost:5000/chat" \
-H "Content-Type: application/json" \
-d '{"message": "Hello, what can you tell me about .NET Aspire?"}'Response:
{
"response": ".NET Aspire is a cloud-native application framework that simplifies building distributed applications..."
}The project includes a GitHubModelsPlayground.ApiService.http file for easy testing in Visual Studio:
- Open the file in Visual Studio
- Click "Send Request" above any endpoint
- View responses directly in the editor
After starting the application:
- Navigate to the Aspire Dashboard (typically
http://localhost:15888) - View:
- Resources: All running services and their status
- Logs: Centralized logging from all services
- Traces: Distributed tracing information
- Metrics: Performance metrics and telemetry
GitHubModelsPlayground/
βββ src/
β βββ GitHubModelsPlayground.ApiService/
β β βββ Services/
β β β βββ BlogService.cs # HTTP client for fetching blog content
β β β βββ IBlogService.cs # Interface for blog service
β β β βββ BlogSummarizer.cs # AI-powered summarization service
β β β βββ IBlogSummarizer.cs # Interface for summarization service
β β βββ Program.cs # API configuration and endpoints
β β βββ appsettings.json # Application configuration
β β βββ GitHubModelsPlayground.ApiService.http # HTTP request examples
β β βββ GitHubModelsPlayground.ApiService.csproj
β βββ GitHubModelsPlayground.AppHost/
β β βββ AppHost.cs # Aspire orchestration setup
β β βββ appsettings.json # Host configuration
β β βββ GitHubModelsPlayground.AppHost.csproj
β βββ GitHubModelsPlayground.ServiceDefaults/
β βββ Extensions.cs # Shared service extensions
β βββ GitHubModelsPlayground.ServiceDefaults.csproj
βββ .gitignore
βββ LICENSE
βββ README.md
βββ CONTRIBUTING.md
βββ GitHubModelsPlayground.slnx # Solution file
The application uses GitHub's hosted AI models through the Aspire framework:
var aiModel = builder.AddGitHubModel("ai-model", GitHubModel.OpenAI.OpenAIGpt4oMini);Services are referenced and discovered automatically:
var apiService = builder.AddProject<Projects.GitHubModelsPlayground_ApiService>("apiservice")
.WithReference(blogService)
.WithReference(aiModel);The BlogSummarizer uses the AI chat client to generate summaries:
var response = await chatClient.GetResponseAsync(prompt);The application follows SOLID principles with interface-based dependency injection:
// Service registration
builder.Services.AddHttpClient<IBlogService, BlogService>();
builder.Services.AddScoped<IBlogSummarizer, BlogSummarizer>();
// Endpoint usage
app.MapGet("/summarize", async (IBlogService blogService, IBlogSummarizer blogSummarizer) =>
{
// Implementation...
});This approach provides:
- Improved testability - Easy to mock dependencies for unit testing
- Loose coupling - Depend on abstractions, not concrete implementations
- Flexibility - Swap implementations without changing consumers
- Clear contracts - Interfaces document expected behavior
Built-in patterns through ServiceDefaults:
- Automatic retries with exponential backoff
- Circuit breaker patterns
- Distributed tracing
- Health checks
appsettings.json (ApiService)
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}| Variable | Description | Required |
|---|---|---|
GITHUB_TOKEN |
GitHub Personal Access Token | Yes |
OTEL_EXPORTER_OTLP_ENDPOINT |
OpenTelemetry endpoint | No |
The project includes GitHubModelsPlayground.ApiService.http for easy endpoint testing:
- Open
src/GitHubModelsPlayground.ApiService/GitHubModelsPlayground.ApiService.httpin Visual Studio - Click "Send Request" above any endpoint
- View the response in the editor
- Start the application
- Access the OpenAPI documentation at
http://localhost:5000/openapi(in development mode) - Test both endpoints with different inputs
Summarize Blog Posts:
# Test with different blog posts
curl "http://localhost:5000/summarize?slug=whats-new/aspire-13/"
curl "http://localhost:5000/summarize?slug=blog/aspire-ga"Chat with AI:
# Simple greeting
curl -X POST "http://localhost:5000/chat" \
-H "Content-Type: application/json" \
-d '{"message": "Hello, how are you?"}'
# Technical question
curl -X POST "http://localhost:5000/chat" \
-H "Content-Type: application/json" \
-d '{"message": "Explain the benefits of using .NET Aspire for cloud-native applications"}'
# Code-related question
curl -X POST "http://localhost:5000/chat" \
-H "Content-Type: application/json" \
-d '{"message": "What are the key differences between minimal APIs and controllers in ASP.NET Core?"}'| Endpoint | Method | Description | Parameters |
|---|---|---|---|
/summarize |
GET | Summarize blog content from aspire.dev | slug (query string) |
/chat |
POST | Interactive chat with GitHub Models AI | message (JSON body) |
/health |
GET | Health check endpoint | None |