# Chat with Your Own Data | WinForms Controls | DevExpress Documentation

When integrating the [AI Chat Control](/WindowsForms/405218/ai-powered-extensions/ai-chat-control) with an AI Assistant API (for example, the [OpenAI Responses API](https://openai.com/index/new-tools-for-building-agents/) or [Azure AI Projects](https://learn.microsoft.com/en-us/azure/foundry/quickstarts/get-started-code?tabs=csharp)), you can configure the control to work with external data sources (for example, text files or PDF documents).

By providing a supplementary document as a context source, the assistant is augmented with relevant background information. The AI service parses the document, extracts semantic information, and uses it to generate accurate responses.

![AI Assistant - WinForms AI Chat Control, DevExpress](/WindowsForms/images/winforms-aichatcontrol-process-document.png)

Warning

[OpenAI Assistants API will be deprecated in August 2026](https://learn.microsoft.com/en-us/answers/questions/5571874/openai-assistants-api-will-be-deprecated-in-august)

## OpenAI Responses API

The OpenAI Responses API supplies a unified way to build stateful AI agents that can use tools and external data sources. In this example, it is used to create an assistant that analyzes a user-supplied PDF file.

### Install NuGet Packages

Install the following packages:

- [Azure.AI.OpenAI (version 2.9.0-beta.1)](https://www.nuget.org/packages/Azure.AI.OpenAI/2.9.0-beta.1)
- [Microsoft.Agents.AI.OpenAI](https://www.nuget.org/packages/Microsoft.Agents.AI.OpenAI/1.0.0)
- `DevExpress.AIIntegration.Agents`
- `DevExpress.AIIntegration.WinForms.Chat`
- `DevExpress.Win`

### Create an Assistant

`OpenAIResponsesCreator` creates an AI agent that can process and analyze a document (the agent is exposed as an `IChatResponseProvider`).

```
using System;
using System.ClientModel;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using DevExpress.AIIntegration.Agents;
using DevExpress.AIIntegration.Chat;
using Microsoft.Extensions.AI;
using OpenAI;
using OpenAI.Files;
using OpenAI.Responses;
using OpenAI.VectorStores;
#pragma warning disable OPENAI001
namespace AIChatAssistantDemo {
    public class OpenAIResponsesCreator {
        readonly ResponsesClient responsesClient;
        readonly OpenAIFileClient fileClient;
        readonly VectorStoreClient vectorStoreClient;
        readonly string deployment;

        public OpenAIResponsesCreator(OpenAIClient client, string deployment) {
            responsesClient = client.GetResponsesClient();
            fileClient = client.GetOpenAIFileClient();
            vectorStoreClient = client.GetVectorStoreClient();
            this.deployment = deployment;
        }

        public IChatResponseProvider Build(
            string instructions,
            OpenAIResponsesFileInfo fileInfo,
            bool useFileSearchTool = true,
            CancellationToken ct = default) {
            fileInfo.Data.Position = 0;

            OpenAIFile file = null;
            VectorStore vectorStore = null;

            try {
                try {
                    ClientResult<OpenAIFile> fileResponse = fileClient.UploadFile(
                        fileInfo.Data,
                        fileInfo.FileName,
                        FileUploadPurpose.Assistants,
                        ct);
                    file = fileResponse.Value;
                }
                finally {
                    fileInfo.Data.Dispose();
                }

                // Create a vector store for file search.
                if (useFileSearchTool) {
                    var vectorStoreOptions = new VectorStoreCreationOptions() {
                        ExpirationPolicy = new VectorStoreExpirationPolicy(
                            VectorStoreExpirationAnchor.LastActiveAt,
                            1)
                    };
                    vectorStore = vectorStoreClient.CreateVectorStore(vectorStoreOptions, ct).Value;
                    vectorStoreClient.AddFileToVectorStore(vectorStore.Id, file.Id, ct);
                }

                // Create a tools list.
                var tools = new List<AITool>();

                if (useFileSearchTool && vectorStore != null) {
                    var fileSearchTool = new HostedFileSearchTool {
                        Inputs = [new HostedVectorStoreContent(vectorStore.Id)]
                    };
                    tools.Add(fileSearchTool);
                }

                var codeInterpreterTool = new HostedCodeInterpreterTool {
                    Inputs = [new HostedFileContent(file.Id)]
                };
                tools.Add(codeInterpreterTool);

                // Create an AI agent.
                var aiAgent = responsesClient.AsAIAgent(
                    instructions: instructions,
                    tools: tools,
                    name: $"Responses Agent {Guid.NewGuid()}",
                    model: deployment
                );

                var session = aiAgent.CreateSessionAsync(ct);
                return aiAgent.AsIChatResponseProvider(session.Result);
            }
            catch {
                if (vectorStore != null) {
                    TryDeleteVectorStore(vectorStore.Id, ct);
                }
                if (file != null) {
                    TryDeleteFile(file.Id, ct);
                }
                throw;
            }
        }

        void TryDeleteVectorStore(string vectorStoreId, CancellationToken ct) {
            try {
                vectorStoreClient.DeleteVectorStore(vectorStoreId, ct);
            }
            catch {
                // Best-effort cleanup only; preserve the original exception.
            }
        }

        void TryDeleteFile(string fileId, CancellationToken ct) {
            try {
                fileClient.DeleteFile(fileId, ct);
            }
            catch {
                // Best-effort cleanup only; preserve the original exception.
            }
        }
    }
    public record OpenAIResponsesFileInfo(string FileName, Stream Data);
}
#pragma warning restore OPENAI001
```

Warning

The `OpenAI.Responses` API is for evaluation purposes only and is subject to change or removal in a future update. The following code snippet suppresses the `OPENAI001` diagnostic.

### Configure the AI Chat

Connect the AI Chat Control to the registered response provider and define assistant behavior.

```
using System;
using System.IO;
using DevExpress.XtraBars.Ribbon;

namespace AIChatAssistantDemo {
    public partial class AIAssistantForm : RibbonForm {
        public Form1() {
            InitializeComponent();

            // Assign the service key used by the AI Chat Control to resolve
            // the registered IChatResponseProvider.
            aiChatControl1.ChatResponseProviderServiceKey = Program.ResponsesAPIChatResponseProviderServiceKey;
        }

        public static string GetInstructions() {
            // Return system-level instructions that define the assistant's role and behavior.
            return "You are an analytics assistant that specializes in analyzing PDF files. Your role is to assist users by...";
        }

        public static OpenAIResponsesFileInfo GetFile() {
            const string fileName = "RestaurantMenu.pdf";

            // Open a file stream that will be sent to the AI service for processing.
            Stream data = new FileStream(fileName, FileMode.Open);

            return new OpenAIResponsesFileInfo(fileName, data);
        }
    }
}
```

### Register AI Services and an IChatResponseProvider

```
using Azure.AI.OpenAI;
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Chat;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.ClientModel;
using System.Windows.Forms;

namespace AIChatAssistantDemo {
    internal static class Program {
        internal const string ResponsesAPIChatResponseProviderServiceKey = "ChatResponseProvider-ResponsesApi";

        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // Create an Azure OpenAI chat client.
            var azureChatClient = new AzureOpenAIClient(AzureOpenAIEndpoint, AzureOpenAIKey);

            // Create a service collection to register AI chat clients.
            var collection = new ServiceCollection();

            // Register a keyed IChatResponseProvider for Azure OpenAI.
            collection.AddKeyedSingleton<IChatResponseProvider>(ResponsesAPIChatResponseProviderServiceKey, (_, _) => {
                return new OpenAIResponsesCreator(azureChatClient, AzureOpenAIModel).Build(AIAssistantForm.GetInstructions(), AIAssistantForm.GetFile());
            });

            // Register a default (non-keyed) IChatResponseProvider.
            // This provider is used when no ChatResponseProviderServiceKey is specified.
            collection.AddScoped<IChatResponseProvider>(
                (serviceProvider) => azureChatClient.GetChatClient(AzureOpenAIModel).AsIChatClient().AsIChatResponseProvider()
            );

            // Add DevExpress AI services (required for AIChatControl).
            collection.AddDevExpressAIDesktop();

            Application.Run(new Form1());
        }

        static Uri AzureOpenAIEndpoint = new Uri("YOUR_AZURE_ENDPOINT");
        static ApiKeyCredential AzureOpenAIKey = new ApiKeyCredential("YOUR_AZURE_API_KEY");
        static string AzureOpenAIModel = "gpt-5.2";
    }
}
```

## Azure AI Projects

The following example uses the Azure AI Projects API to analyze a user-supplied PDF file.

### Install NuGet Packages

Install the following packages:

- [Azure.AI.Projects (version 2.0.0)](https://www.nuget.org/packages/Azure.AI.Projects/2.0.0)
- [Microsoft.Agents.AI.OpenAI](https://www.nuget.org/packages/Microsoft.Agents.AI.OpenAI/1.0.0)
- `DevExpress.AIIntegration.Agents`
- `DevExpress.AIIntegration.WinForms.Chat`
- `DevExpress.Win`

### Create an Azure AI Projects Agent

```
using System;
using System.IO;
using System.Linq;
using Azure.AI.Extensions.OpenAI;
using Azure.AI.Projects;
using Azure.AI.Projects.Agents;
using Azure.Identity;
using DevExpress.AIIntegration.Chat;
using Microsoft.Extensions.AI;
using OpenAI.Files;
using OpenAI.Responses;
using OpenAI.VectorStores;

namespace AIChatAzureAiProjectsDemo {
    internal static class AzureAIProjectsAgentCreator {
        const string AgentName = "AssistantTestAgent";
        const string VectorStoreName = "RestaurantMenuVectorStore";
        const string Model = "gpt-5.4-mini";

        // Replace "YOUR_ENDPOINT" with the actual endpoint URL of your Azure AI Project.
        const string FoundryProjectEndpointSampleValue = "YOUR_ENDPOINT";

        #region Instructions
        const string Instructions = "You are an analytics assistant that specializes in analyzing PDF files. Your role is to assist users by...";
        #endregion

#pragma warning disable OPENAI001
        internal static IChatResponseProvider Create() {
            AIProjectClient projectClient = new(new Uri(FoundryProjectEndpointSampleValue), new VisualStudioCredential());

            var agents = projectClient.AgentAdministrationClient.GetAgents();

            CreateOrUpdateAgent(projectClient);

            var responseClient = projectClient.ProjectOpenAIClient.GetProjectResponsesClient();

            IChatClient chatClient = responseClient.AsIChatClient();
            var chatOptions = new ChatOptions {
                RawRepresentationFactory = _ => {
                    CreateResponseOptions options = new() {
                        Agent = new AgentReference(AgentName)
                    };
                    return options;
                }
            };

            return chatClient.AsIChatResponseProvider(chatOptions);
        }

        static void CreateOrUpdateAgent(AIProjectClient projectClient) {
            var agents = projectClient.AgentAdministrationClient.GetAgents();
            var existingAgent = agents.FirstOrDefault(a => a.Name == AgentName);
            if(existingAgent != null) {
                projectClient.AgentAdministrationClient.DeleteAgent(existingAgent.Id);
            }

            string vectorStoreId = CreateVectorStore(projectClient);

            var agentDefinition = new DeclarativeAgentDefinition(Model) {
                Instructions = Instructions,
                Tools = {
                    ResponseTool.CreateFileSearchTool([vectorStoreId])
                }
            };
            var options = new ProjectsAgentVersionCreationOptions(agentDefinition);
            projectClient.AgentAdministrationClient.CreateAgentVersion(AgentName, options);
        }

        static string CreateVectorStore(AIProjectClient projectClient) {
            var fileClient = projectClient.ProjectOpenAIClient.GetOpenAIFileClient();
            var vectorStoreClient = projectClient.ProjectOpenAIClient.GetVectorStoreClient();

            using Stream pdfStream = GetEmbeddedResourceStream();
            var uploadedFile = fileClient.UploadFile(pdfStream, "RestaurantMenu.pdf", FileUploadPurpose.Assistants);

            var creationOptions = new VectorStoreCreationOptions {
                Name = VectorStoreName
            };

            var vectorStore = vectorStoreClient.CreateVectorStore(creationOptions);
            vectorStoreClient.AddFileToVectorStore(vectorStore.Value.Id, uploadedFile.Value.Id);

            return vectorStore.Value.Id;
        }

        static Stream GetEmbeddedResourceStream() {
            const string fileName = "RestaurantMenu.pdf";
            Stream stream = new FileStream(fileName, FileMode.Open);
            if(stream is null) {
                throw new InvalidOperationException($"'{fileName}' doesn't exist.");
            }
            return stream;
        }
#pragma warning restore OPENAI001
    }
}
```

### Register AI Services

```
// Program.cs
using DevExpress.AIIntegration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Windows.Forms;

namespace AIChat {
    internal static class Program {
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            var collection = new ServiceCollection();
            collection.AddSingleton(AzureAIProjectsAgentCreator.Create());

            // Add DevExpress AI services (required for AIChatControl).
            collection.AddDevExpressAIDesktop();

            Application.Run(new Form1());
        }
    }
}
```

## DevExpress AI Chat (RAG) App Template

The **AI Chat (RAG) Application** template creates a desktop WinForms application with the AI Chat Control and built-in Retrieval-Augmented Generation (RAG) for document-grounded conversations.

This template does the following:

- Uses local document data for context-aware answers.
- Scans the user’s Documents folder and indexes PDF, DOCX, TXT, RTF, and HTML files.
- Extracts, embeds, and semantically searches document text.
- Stores vectors in In-Memory data source (rebuilt on each run) or SQLite (a persistent database).
- Combines the user’s prompt with retrieved content to improve accuracy.
- Optionally integrates the DevExpress MCP Server for DevExpress-specific guidance.

Refer to the following help topic for additional information: [Artificial Intelligence — DevExpress Template Kit](/WindowsForms/405275/whats-installed/project-template-kit#artificial-intelligence).