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/fkucukkara/github-models-playground.git cd github-models-playground -
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 |