Build a RAG Application with .NET and React for Internal Knowledge Assistants

Meta Description: Learn how to create a RAG application using .NET and React for internal knowledge assistants. Step-by-step guide with best practices and code examples....

By · · Updated · 10 min read · intermediate

Meta Description: Learn how to create a RAG application using .NET and React for internal knowledge assistants. Step-by-step guide with best practices and code examples.


Introduction

Imagine transforming your company’s internal documentation, manuals, and knowledge bases into an intelligent, conversational assistant. Employees could ask questions in natural language and receive accurate, context-aware answers instantly. This isn’t just a futuristic dream—it’s achievable today with Retrieval-Augmented Generation (RAG).

RAG combines the power of large language models (LLMs) with your internal knowledge base to deliver precise, relevant, and secure responses. In this guide, we’ll walk you through building a RAG application using .NET and React for an internal knowledge assistant. Whether you're a developer, tech lead, or IT decision-maker, this step-by-step guide will equip you with the knowledge to implement a RAG solution tailored to your organization’s needs.


What is RAG and Why Use It for Internal Knowledge Assistants?

Understanding RAG

Retrieval-Augmented Generation (RAG) is a technique that enhances the capabilities of LLMs by grounding their responses in real-world data. Instead of relying solely on the model’s training data, RAG retrieves relevant information from a curated knowledge base and uses it to generate accurate and context-aware responses.

Why RAG for Internal Knowledge Assistants?

  1. Accuracy: Ensures responses are based on your organization’s latest documents and policies.
  2. Security: Keeps sensitive data within your infrastructure, reducing exposure risks.
  3. Cost-Effective: Leverages existing documentation without the need for extensive retraining of models.
  4. Scalability: Adapts to growing knowledge bases and user queries seamlessly.
  5. Customization: Tailors responses to your organization’s tone, terminology, and processes.

Use Cases for Internal Knowledge Assistants

  • HR Assistants: Answer employee questions about policies, benefits, and procedures.
  • IT Support: Provide troubleshooting steps and documentation for common issues.
  • Customer Support: Equip agents with instant access to product manuals and FAQs.
  • Legal and Compliance: Retrieve relevant clauses from contracts or regulatory documents.

Step-by-Step Guide to Building a RAG Application with .NET and React

Prerequisites

Before diving into the implementation, ensure you have the following:

  • Development Environment:
  • Tools:
  • Accounts:
    • Azure account (for Azure Cognitive Search or OpenAI)
    • Or access to an open-source embedding model (e.g., Sentence Transformers)

Step 1: Set Up the Backend with .NET

1.1 Create a .NET Web API Project

Start by creating a new .NET Web API project:

dotnet new webapi -n RagBackend
cd RagBackend

1.2 Install Required Packages

Install the packages for handling HTTP requests, OpenAI integration, and vector operations:

dotnet add package Microsoft.SemanticKernel
dotnet add package Azure.AI.OpenAI
dotnet add package Azure.Search.Documents
dotnet add package System.Numerics.Tensors

1.3 Configure Azure Cognitive Search

Azure Cognitive Search will serve as your vector database for storing and retrieving document embeddings.

  1. Create an Azure Cognitive Search Service:

    • Log in to the Azure Portal.
    • Create a new Cognitive Search resource.
    • Note the Endpoint and API Key.
  2. Set Up the Search Index:

    • Define a schema for your index that includes fields for id, content, and embedding (a vector field).
    • Use the Azure SDK to create the index in your .NET application.
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;

string searchServiceEndpoint = "https://your-search-service-name.search.windows.net";
string apiKey = "your-api-key";
string indexName = "knowledge-base";

SearchIndexClient indexClient = new SearchIndexClient(new Uri(searchServiceEndpoint), new AzureKeyCredential(apiKey));
SearchIndex index = new SearchIndex(indexName)
{
    Fields =
    {
        new SimpleField("id", SearchFieldDataType.String) { IsKey = true },
        new SearchableField("content") { IsFilterable = true, IsSortable = true },
        new VectorSearchField("embedding", 1536, "HNSW") // 1536 dimensions for OpenAI embeddings
    }
};

indexClient.CreateOrUpdateIndex(index);

1.4 Generate Embeddings with OpenAI

Use OpenAI’s embedding model to convert your documents into vectors.

  1. Set Up OpenAI API:

    • Create an OpenAI account and generate an API key.
    • Install the OpenAI SDK:
      dotnet add package Azure.AI.OpenAI
      
  2. Generate Embeddings:

    • Write a method to generate embeddings for your documents.
using Azure.AI.OpenAI;

string openAIEndpoint = "https://your-openai-resource.openai.azure.com/";
string openAIKey = "your-openai-key";
string deploymentName = "text-embedding-ada-002";

OpenAIClient openAIClient = new OpenAIClient(new Uri(openAIEndpoint), new AzureKeyCredential(openAIKey));

async Task<float[]> GenerateEmbedding(string text)
{
    var response = await openAIClient.GetEmbeddingsAsync(deploymentName, new EmbeddingsOptions(text));
    return response.Value.Data[0].Embedding.ToArray();
}

1.5 Implement the RAG Logic

Combine retrieval and generation to create the RAG pipeline.

  1. Retrieve Relevant Documents:
    • Use Azure Cognitive Search to find documents similar to the user’s query.
using Azure.Search.Documents;
using Azure.Search.Documents.Models;

SearchClient searchClient = new SearchClient(new Uri(searchServiceEndpoint), indexName, new AzureKeyCredential(apiKey));

async Task<List<string>> RetrieveRelevantDocuments(string query, int topN = 3)
{
    float[] queryEmbedding = await GenerateEmbedding(query);
    var searchOptions = new SearchOptions
    {
        VectorSearch = new VectorSearchOptions
        {
            Queries = { new VectorizedQuery(queryEmbedding) { KNearestNeighborsCount = topN } }
        },
        Size = topN
    };

    SearchResults<SearchDocument> results = await searchClient.SearchAsync<SearchDocument>(null, searchOptions);
    return results.GetResults().Select(r => r.Document["content"].ToString()).ToList();
}
  1. Generate a Response:
    • Use OpenAI’s GPT model to generate a response based on the retrieved documents.
async Task<string> GenerateResponse(string query, List<string> documents)
{
    string context = string.Join("\n\n", documents);
    var prompt = 
quot;Answer the question based on the following context:\n\n{context}\n\nQuestion: {query}"; var response = await openAIClient.GetCompletionsAsync(deploymentName, new CompletionsOptions { Prompts = { prompt }, MaxTokens = 150 }); return response.Value.Choices[0].Text; }
  1. Create an API Endpoint:
    • Expose the RAG functionality via a REST API.
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/rag")]
public class RagController : ControllerBase
{
    [HttpGet("query")]
    public async Task<IActionResult> Query([FromQuery] string question)
    {
        var documents = await RetrieveRelevantDocuments(question);
        var answer = await GenerateResponse(question, documents);
        return Ok(new { question, answer, documents });
    }
}

Step 2: Set Up the Frontend with React

2.1 Create a React Application

Use Create React App to set up your frontend:

npx create-react-app rag-frontend
cd rag-frontend

2.2 Install Required Packages

Install packages for making HTTP requests and styling:

npm install axios @mui/material @mui/icons-material @emotion/react @emotion/styled

2.3 Build the User Interface

Create a simple chat interface for users to interact with the RAG assistant.

  1. Create a Chat Component:
    • Add a component to display messages and handle user input.
// src/components/Chat.js
import React, { useState } from "react";
import axios from "axios";
import { TextField, Button, Paper, Typography, Box } from "@mui/material";

const Chat = () => {
    const [messages, setMessages] = useState([]);
    const [input, setInput] = useState("");

    const handleSend = async () => {
        if (!input.trim()) return;

        const userMessage = { text: input, sender: "user" };
        setMessages((prev) => [...prev, userMessage]);
        setInput("");

        try {
            const response = await axios.get("http://localhost:5000/api/rag/query", {
                params: { question: input }
            });
            const botMessage = { text: response.data.answer, sender: "bot" };
            setMessages((prev) => [...prev, botMessage]);
        } catch (error) {
            console.error("Error fetching response:", error);
        }
    };

    return (
        <Paper elevation={3} sx={{ padding: 3, maxWidth: 600, margin: "auto" }}>
            <Typography variant="h5" gutterBottom>
                Internal Knowledge Assistant
            </Typography>
            <Box sx={{ height: 400, overflowY: "auto", marginBottom: 2 }}>
                {messages.map((msg, index) => (
                    <Box
                        key={index}
                        sx={{
                            textAlign: msg.sender === "user" ? "right" : "left",
                            marginBottom: 1
                        }}
                    >
                        <Typography
                            variant="body1"
                            sx={{
                                display: "inline-block",
                                padding: 1,
                                borderRadius: 1,
                                backgroundColor: msg.sender === "user" ? "#e3f2fd" : "#f1f1f1"
                            }}
                        >
                            {msg.text}
                        </Typography>
                    </Box>
                ))}
            </Box>
            <Box sx={{ display: "flex", gap: 1 }}>
                <TextField
                    fullWidth
                    variant="outlined"
                    value={input}
                    onChange={(e) => setInput(e.target.value)}
                    onKeyPress={(e) => e.key === "Enter" && handleSend()}
                    placeholder="Ask a question..."
                />
                <Button variant="contained" onClick={handleSend}>
                    Send
                </Button>
            </Box>
        </Paper>
    );
};

export default Chat;
  1. Integrate the Chat Component:
    • Update App.js to include the Chat component.
// src/App.js
import React from "react";
import Chat from "./components/Chat";
import { Container } from "@mui/material";

function App() {
    return (
        <Container sx={{ paddingTop: 4 }}>
            <Chat />
        </Container>
    );
}

export default App;

Step 3: Deploy and Test Your RAG Application

3.1 Run the Backend

Start the .NET Web API:

cd RagBackend
dotnet run

3.2 Run the Frontend

Start the React application:

cd rag-frontend
npm start

3.3 Test the Application

  1. Open your browser and navigate to http://localhost:3000.
  2. Ask a question related to your internal knowledge base (e.g., "What is our company’s remote work policy?").
  3. Verify that the assistant retrieves relevant documents and generates a accurate response.

3.4 Deploy to Production

  1. Backend Deployment:

    • Deploy the .NET API to Azure App Service or AWS Elastic Beanstalk.
    • Ensure environment variables (e.g., API keys) are securely configured.
  2. Frontend Deployment:

    • Build the React app for production:
      npm run build
      
    • Deploy the build folder to Azure Static Web Apps, Netlify, or Vercel.
  3. Monitor and Optimize:

    • Use Application Insights (Azure) or CloudWatch (AWS) to monitor performance.
    • Collect user feedback to refine the knowledge base and improve response accuracy.

Best Practices for Building RAG Applications

1. Data Preparation

  • Clean and Structure Data: Ensure documents are well-structured (e.g., PDFs, Word docs, or databases) and free of noise.
  • Chunking: Split large documents into smaller chunks (e.g., 500-1000 tokens) to improve retrieval accuracy.
  • Metadata: Include metadata (e.g., document source, date) to enhance filtering and relevance.

2. Embedding Models

  • Choose the Right Model: Use models like text-embedding-ada-002 (OpenAI) or all-MiniLM-L6-v2 (Sentence Transformers) based on your needs.
  • Fine-Tuning: Consider fine-tuning the embedding model on your domain-specific data for better performance.

3. Vector Database

  • Scalability: Choose a vector database that scales with your data (e.g., Azure Cognitive Search, Pinecone, or Weaviate).
  • Indexing: Use efficient indexing strategies (e.g., HNSW) to speed up retrieval.

4. Security and Compliance

  • Data Privacy: Ensure sensitive data is encrypted and access is restricted.
  • Authentication: Integrate with your organization’s authentication system (e.g., Azure AD, Okta).
  • Audit Logs: Track user queries and responses for compliance and improvement.

5. User Experience

  • Feedback Loop: Allow users to rate responses to improve the system over time.
  • Fallback Mechanisms: Provide options to escalate to human support if the assistant cannot answer a question.
  • Context Awareness: Maintain conversation context for follow-up questions.

Conclusion

Building a RAG application with .NET and React for internal knowledge assistants is a powerful way to unlock the value of your organization’s data. By combining the retrieval capabilities of vector databases with the generative power of LLMs, you can create an intelligent assistant that delivers accurate, context-aware responses to employee queries.

Key Takeaways

  1. RAG enhances LLMs by grounding responses in your internal knowledge base.
  2. .NET and React provide a robust and scalable stack for building RAG applications.
  3. Azure Cognitive Search and OpenAI simplify the implementation of vector search and embeddings.
  4. Best practices in data preparation, security, and user experience are critical for success.

Call to Action

Ready to build your own internal knowledge assistant? Start by:

  1. Gathering your organization’s documents and structuring them for embedding.
  2. Setting up Azure Cognitive Search and OpenAI for vector storage and generation.
  3. Following this guide to implement the backend with .NET and the frontend with React.

Share your progress or ask questions in the comments below—we’d love to hear about your journey in building a RAG application! For more advanced use cases, explore fine-tuning embeddings or integrating multi-modal data (e.g., images, tables) into your knowledge base.