The rise of AI-powered applications has transformed the way developers build intelligent solutions. Whether it’s chatbots, virtual assistants, or AI-enhanced search, integrating AI into applications is now more accessible than ever.
To simplify AI development in .NET, Microsoft introduced Microsoft.Extensions.AI.Templates, a powerful new project template that enables developers to quickly build AI-driven chatbots. This template comes with pre-built AI capabilities, document processing, and support for multiple AI providers, including Azure OpenAI, OpenAI API, GitHub Copilot, and local AI models (Ollama).
In this guide, we’ll walk through setting up an AI chatbot in .NET using the GitHub Copilot model, exploring its key features and step-by-step implementation.
Introducing the Microsoft.Extensions.AI.Templates
The Microsoft.Extensions.AI.Templates provides a ready-to-use chatbot that can do the following:
Process custom documents (PDFs, text) and extract meaningful information.
Use AI models such as Azure OpenAI, OpenAI API, GitHub Copilot, or local models.
Retrieve contextual answers with citations for accuracy.
Be easily extended for additional AI integrations, UI enhancements, and new features.
Key Features
AI-Powered Chatbot with Retrieval-Augmented Generation (RAG)
Retrieves relevant content from PDFs before sending queries to an AI model.
Uses vector search for enhanced accuracy.
Provides citation-based responses for transparency.
Supports Multiple AI Providers
The chatbot works with various AI models. In this example, we’ll use GitHub Copilot models, as they offer a quick and simple setup.
Azure OpenAI (GPT-4, GPT-3.5)
OpenAI API
GitHub Copilot models
Ollama (for running AI models locally)
Document Ingestion & Vector Storage
Converts PDF content into searchable AI embeddings.
Uses a local vector store by default, but can integrate with Azure AI Search for enterprise-level indexing.
Pre-Built Chat UI
Comes with a Blazor WebAssembly / Razor Pages UI.
Provides a chat interface with real-time AI interactions and follow-up suggestions.
Ready for Cloud & Local Deployment
Run locally with an embedded vector database.
Deploy to Azure with AI Search for scalable solutions.
Step-by-Step Implementation: AI Chatbot using Microsoft.Extensions.AI.Templates & GitHub Copilot
Let’s walk through the process of setting up an AI chatbot using this new template and GitHub Copilot models as the AI provider.
Step 1️⃣: Create a Personal Access Token (PAT) in GitHub
If you don’t have a GitHub account, create one at GitHub.
Navigate to Profile → Settings → Developer Settings.
Under Developer Settings, click Personal Access Tokens → Fine-grained Tokens.
Generate a new token and store it securely for your AI project.
Step 2️⃣: Install the AI Template
Ensure you have Visual Studio 17.12 or later installed to support .NET 9.0.
Install the AI template using the following command:
dotnet new install Microsoft.Extensions.AI.Templates
Step 3️⃣: Create an AI Chatbot Project
In Visual Studio, choose Create a new project and select the AI Chat Web App template.
Alternatively, use this command:
dotnet new aichatweb -o MyAIChatApp
When prompted for the AI service provider, select GitHub Models.
Step 4️⃣: Configure Your Personal Access Token as a Secret
Depending on your Visual Studio version, configure the GitHub PAT (Personal Access Token) as a user secret:
Option 1: Using Visual Studio
Right-click on your project and select Manage User Secrets.
Add the following JSON:
{ "GitHubModels:Token": "YOUR-TOKEN" }
Option 2: Using the Command Line
cd <<your-project-directory>> dotnet user-secrets set GitHubModels:Token YOUR-TOKEN
Step 5️⃣: Run the Application
Next, we can run the application and see what we get out of the box. You can also add your own PDF files to the project data folder and train the AI with your own unique data (product, service, etc.)
Step 6️⃣: Add Custom Content
To fully experience the AI Chatbot’s capabilities, try adding your own PDF files to the data folder for custom knowledge retrieval.
Next, update the Chat.razor file to reference the document for retrieval.
Step 7️⃣: Modify the System Prompt
The Chat.razor page includes a SystemPrompt, which acts as the AI’s guiding instruction set. This prompt allows you to train the AI by defining its behavior, setting boundaries, and ensuring it retrieves and cites information strictly from the provided PDF documents. The AI is instructed to only answer questions based on retrieved data, format responses using simple Markdown, and provide exact citations in a structured XML format.
private const string SystemPrompt = @" You are an assistant who answers questions about information you retrieve. Do not answer questions about anything else. Use only simple markdown to format your responses.
Use the search tool to find relevant information. When you do this, end your reply with citations in the special XML format:
Always include the citation in your response if there are results.
The quote must be max 5 words, taken word-for-word from the search result, and is the basis for why the citation is relevant. Don't refer to the presence of citations; just emit these tags right at the end, with no surrounding text. ";
Example of a Change to the Prompt:
You could modify the prompt to allow more natural explanations while still requiring citations. For instance, if you want the chatbot to summarize content in addition to citing sources, you might adjust the prompt like this:
private const string SystemPrompt = @" You are an assistant specializing in answering questions based on retrieved information. If relevant data is found, summarize it in your own words while keeping the meaning intact. Use simple markdown for formatting.
Always include a citation in this XML format at the end of your response:
The quote must be word-for-word, up to 10 words long, taken directly from the search result. Don't explicitly mention that you are using citations; just include them at the end. ";
Impact of This Adjustment
Allows AI to summarize content instead of just quoting directly.
Increases the quote length to 10 words for better context.
Keeps citations mandatory while making responses feel more natural.
The Microsoft.Extensions.AI.Templates project provides a streamlined way to build AI-powered chat applications using .NET and Blazor. This template offers a Blazor WebAssembly / Razor Pages UI, making it easy to integrate interactive AI experiences into web applications.
At its core, the chatbot utilizes Retrieval-Augmented Generation (RAG) to improve response accuracy by referencing PDF documents stored in the project’s data folder. When a user submits a query, the system extracts relevant information from these PDFs, transforms it into vector embeddings, and retrieves the most contextually appropriate content before sending the query to an AI model like GitHub Copilot, Azure OpenAI, or Ollama. This ensures that responses are not only AI-generated but also grounded in real, source-backed data.
With built-in support for multiple AI providers, cloud and local deployment, and a pre-configured chat UI, this template serves as a powerful foundation for developers looking to integrate AI-driven document search, chatbot interactions, and knowledge retrieval into their .NET applications. Whether you’re building an internal knowledge assistant, customer support bot, or research tool, this project offers a flexible and scalable starting point.
By following the step-by-step guide, you now have a working AI chatbot running on Blazor and .NET 9, processing documents, and responding with contextual answers. From here, you can extend the project by customizing the UI, adding additional document types, or integrating with external data sources to enhance functionality even further.
{"id":"2","mode":"button","open_style":"in_modal","currency_code":"USD","currency_symbol":"$","currency_type":"decimal","blank_flag_url":"https:\/\/robhutton.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/robhutton.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":500,"top_media_type":"featured_image","featured_image_url":"https:\/\/robhutton.com\/wp-content\/uploads\/Screenshot-2025-02-19-163019-100x74.png","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":false,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Tip Jar","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"robhutton.com","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"robhutton.com","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for being a supporter!","payment_confirmation_title":"robhutton.com","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":"Voluntary nature: Tips are non-refundable and given voluntarily. No goods\/services in exchange: Tipping doesn\u2019t entitle the user to any product, service, or preferential treatment. Payment processing: Mention that payments are processed securely through a third-party provider. No liability: You aren\u2019t responsible for transaction failures, fraud, or technical issues.","terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}
{"id":"4","mode":"text_link","open_style":"in_modal","currency_code":"USD","currency_symbol":"$","currency_type":"decimal","blank_flag_url":"https:\/\/robhutton.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/robhutton.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":500,"top_media_type":"featured_image","featured_image_url":"https:\/\/robhutton.com\/wp-content\/uploads\/Screenshot-2025-02-19-163019-100x74.png","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Like my articles? Tips are appreciated.","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for being a supporter!","payment_confirmation_title":"","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":"Voluntary nature: Tips are non-refundable and given voluntarily. No goods\/services in exchange: Tipping doesn\u2019t entitle the user to any product, service, or preferential treatment. Payment processing: Mention that payments are processed securely through a third-party provider. No liability: You aren\u2019t responsible for transaction failures, fraud, or technical issues.","terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}