Your search did not match any results.

Tree List - AI Columns

DevExtreme TreeList allows you to add multiple AI columns to the TreeList. These columns auto generate meaningful cell values based on component data and a custom prompt, transforming DevExtreme TreeList into an AI-powered data analysis tool. In this demo, an AI column is fixed to the right side of the component.

Backend API
@using DevExtreme.MVC.Demos.Models.TreeList.AIColumns @model IEnumerable<Employee> @section ExternalDependencies { <script type="module"> import { AzureOpenAI } from "https://esm.sh/openai@4.73.1"; window.AzureOpenAI = AzureOpenAI; </script> } @(Html.DevExtreme().TreeList<Employee>() .ID("treeList") .DataSource(Model, "ID") .ShowBorders(true) .ParentIdExpr("Head_ID") .AutoExpandAll(true) .AiIntegration(new JS("aiIntegration")) .Scrolling(s => s.Mode(TreeListScrollingMode.Standard)) .Paging(p => p .Enabled(true) .PageSize(10) ) .Columns(columns => { columns.Add() .Caption("Employee") .Width(260) .CssClass("name_cell") .CellTemplate(@<text> <div class="name__wrapper"> <% if (data.ID && data.First_Name && data.Last_Name) { %> <div class="name__img-wrapper"> <img class="name__img" src="@Url.Content("~/Content/images/employees/new/")<%- data.First_Name %> <%- data.Last_Name %>.jpg" alt="<%- data.First_Name %> <%- data.Last_Name %>" /> </div> <div class="name__text-wrapper"> <div class="name__text"><%- data.First_Name %></div> <div class="name__text"><%- data.Last_Name %></div> </div> <% } %> </div> </text>); columns.AddFor(m => m.Title) .Width(140); columns.AddFor(m => m.Status) .MinWidth(180) .CellTemplate(@<text> <div class="status status--<%- data.Status.toLowerCase() %>"> <div class="indicator"></div> <div><%- data.Status %></div> </div> </text>); columns.AddFor(m => m.City) .Width(180); columns.AddFor(m => m.State) .Width(140); columns.AddFor(m => m.Email) .MinWidth(200); columns.Add() .Name("AIColumn") .Caption("AI Column") .Type(TreeListCommandColumnType.Ai) .CssClass("ai__cell") .Width(180) .Fixed(true) .FixedPosition(FixedPosition.Right) .AI(ai => ai .Prompt("Identify the department where the employee works. Select from the following department list: \"Management\", \"Human Resources\", \"IT\", \"Shipping\", \"Support\", \"Sales\", \"Engineering\". Use \"Engineering\" if you cannot find a better match.") .Mode(AIColumnMode.Auto) .NoDataText("No data") ); }) .OnAIColumnRequestCreating("onAIColumnRequestCreating") ) <script> let chatService; const deployment = "gpt-4o-mini"; const apiVersion = "2024-02-01"; const endpoint = "https://public-api.devexpress.com/demo-openai"; const apiKey = "DEMO"; function onAIColumnRequestCreating(e) { e.data = e.data.map((item) => ({ ID: item.ID, First_Name: item.First_Name, Last_Name: item.Last_Name, Title: item.Title, })); } async function getAIResponse(messages, signal) { const params = { messages, model: deployment, max_tokens: 1000, temperature: 0.7, }; const response = await chatService.chat.completions .create(params, { signal }); const result = response.choices[0].message?.content; return result; } async function getAIResponseRecursive(messages, signal) { return getAIResponse(messages, signal) .catch(async (error) => { if (!error.message.includes('Connection error')) { return Promise.reject(error); } DevExpress.ui.notify({ message: 'Our demo AI service reached a temporary request limit. Retrying in 30 seconds.', width: 'auto', type: 'error', displayTime: 5000, }); await new Promise((resolve) => setTimeout(resolve, 30000)); return getAIResponseRecursive(messages, signal); }); } const aiIntegration = new DevExpress.aiIntegration({ sendRequest({ prompt }) { const isValidRequest = JSON.stringify(prompt.user).length < 5000; if (!isValidRequest) { return { promise: Promise.reject(new Error('Request is too long. Specify a shorter prompt.')), abort: () => {}, }; } const controller = new AbortController(); const signal = controller.signal; const aiPrompt = [ { role: 'system', content: prompt.system }, { role: 'user', content: prompt.user }, ]; const promise = getAIResponseRecursive(aiPrompt, signal); const result = { promise, abort: () => { controller.abort(); }, }; return result; }, }); $(() => { chatService = new AzureOpenAI({ dangerouslyAllowBrowser: true, deployment, endpoint, apiVersion, apiKey, }); }); </script>
using DevExtreme.MVC.Demos.Models.SampleData; using DevExtreme.MVC.Demos.Models.TreeList.AIColumns; using System.Web.Mvc; namespace DevExtreme.MVC.Demos.Controllers { public class TreeListController : Controller { public ActionResult AIColumns() { return View(AIColumnsSampleData.Employees); } } }
#treeList { min-height: 560px; } #treeList .ai__cell { background-color: var(--dx-datagrid-row-alternation-bg); } #treeList .name_cell > div { align-items: flex-end; } .name__wrapper { display: flex; align-items: center; gap: 8px; } .name__img-wrapper { width: 40px; height: 40px; border: var(--dx-border-width) solid var(--dx-color-border); border-radius: 50%; cursor: pointer; } .name__img-wrapper img { width: 100%; height: 100%; object-fit: cover; object-position: center; border-radius: 50%; } .name__text-wrapper { width: calc(100% - 48px); } .name__text { margin: 0; padding: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .status { display: flex; align-items: center; } .status--salaried { color: var(--dx-color-success); } .status--commission { color: #f7630c; } .status--terminated { color: var(--dx-color-danger); } .indicator { background-color: currentColor; margin-right: 8px; border-radius: 50%; height: 12px; width: 12px; }

AI services used for this demo have been rate and data limited. As such, you may experience performance-related delays when exploring the capabilities of TreeList AI Columns.

When connected to your own AI model/service without rate and data limits, TreeList AI Columns will perform seamlessly, without artificial delays. Note that DevExtreme does not offer an AI REST API and does not ship any built-in LLMs/SLMs.

This demo instructs the AI service to identify the department name associated with each employee. You can modify the default prompt or enter a custom prompt in the AI column header menu.

To integrate an AI column into the DevExtreme TreeList, you must:

  • Configure the aiIntegration property at the component or column level (aiIntegration or columns[].ai.aiIntegration).
  • Set the column type to "ai".
  • Specify the column name.
  • Configure columns[].ai options, such as generation mode, predefined prompt, and no data text (displayed when the AI service returns no data for a row).

Our DevExtreme TreeList component uses all visible row data in AI requests, including fields not bound to a column and hidden column fields. This data gives LLMs broader context, but increases the use of AI resources. To limit data included in AI requests, modify the AIColumnRequestCreatingEvent.data parameter in the onAIColumnRequestCreating event handler.