{"id":14485,"date":"2025-09-23T17:17:12","date_gmt":"2025-09-23T14:17:12","guid":{"rendered":"https:\/\/dhtmlx.com\/blog\/?p=14485"},"modified":"2025-09-23T18:06:10","modified_gmt":"2025-09-23T15:06:10","slug":"dhtmlx-grid-meets-ai-smart-review-analysis-app","status":"publish","type":"post","link":"https:\/\/dhtmlx.com\/blog\/dhtmlx-grid-meets-ai-smart-review-analysis-app\/","title":{"rendered":"DHTMLX Grid Meets AI: Smart Review Analysis in Your App"},"content":{"rendered":"<p>Data management functionalities, like a data table, can be safely attributed to core parts of modern business apps. DHTMLX <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGrid\/\" rel=\"noopener\" target=\"_blank\">JavaScript Grid<\/a> component helps developers speed up the implementation of feature-packed data tables for efficient data analysis. The modern UI of our Grid, which has intuitive features and smooth rendering of complex datasets, ensures a high usability level on various devices. But with the advent of AI technologies, there are new great opportunities to bring the user experience to a new level. For instance,  what if your data grid could analyze text on its own, transforming it into structured, ready-to-use data?<\/p>\n<p>That&#8217;s exactly what we&#8217;re going to implement in this guide. You will learn how to create a smart system that reads customer reviews, figures out the sentiment, pulls out important tags, and writes a quick summary for each one using DHTMLX Grid and the OpenAI API.<\/p>\n<h2>Preparatory Step<\/h2>\n<p>Before we proceed to concrete steps on embedding AI functionality into DHTMLX Grid, you need the following:<\/p>\n<ul>\n<li>Installed Node.js to run the backend server<\/li>\n<li>An API key from an AI provider<\/li>\n<\/ul>\n<p><em><strong>Note:<\/strong> this tutorial uses OpenAI for the AI part, but you can easily replace it with other services such as Google (Gemini models), Anthropic (Claude models), Mistral, etc., without changing much of the backend logic.<\/em><\/p>\n<p>Here&#8217;s a quick look at the expected result:<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2025\/09\/image2.gif\" alt=\"AI-powered data analysis in DHTMLX Grid\" width=\"1208\" height=\"664\" class=\"aligncenter size-full wp-image-14487\"\/> <\/p>\n<p>In this <a href=\"https:\/\/dhtmlx.com\/docs\/demo\/grid-ai-review-analysis\/\" rel=\"noopener\" target=\"_blank\">demo<\/a>, you can paste in raw text, hit the \u201cAnalyze all reviews\u201d button, and watch as the AI fills in the empty fields in real time.<\/p>\n<p>If you want to look under the hood, check the <a href=\"https:\/\/github.com\/DHTMLX\/grid-ai-demo\/\" rel=\"noopener\" target=\"_blank\">complete project<\/a> on GitHub.<\/p>\n<p>Now, let us go through the main steps required to implement a similar integration on the web.<\/p>\n<h2>Step 1: Setting Up DHTMLX Grid<\/h2>\n<p>Let\u2019s start by putting together a simple web page with the initialized Grid. There is nothing complicated here:<\/p>\n<ul>\n<li>Create an HTML file (<a href=\"https:\/\/github.com\/DHTMLX\/grid-ai-demo\/blob\/main\/frontend\/index.html\" rel=\"noopener\" target=\"_blank\">index.html<\/a>), where you\u2019ll include source files + Socket.io for server communication<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"sy0\">&lt;!<\/span>DOCTYPE html<span class=\"sy0\">&gt;<\/span><br \/>\n<span class=\"sy0\">&lt;<\/span>html<span class=\"sy0\">&gt;<\/span><br \/>\n<span class=\"sy0\">&lt;<\/span>head<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>title<span class=\"sy0\">&gt;<\/span>DHTMLX Grid <span class=\"sy0\">+<\/span> AI Analysis<span class=\"sy0\">&lt;\/<\/span>title<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>link rel<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;stylesheet&quot;<\/span> href<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;https:\/\/cdn.dhtmlx.com\/suite\/pro\/edge\/suite.css&quot;<\/span><span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>script src<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;https:\/\/cdn.dhtmlx.com\/suite\/pro\/edge\/suite.js&quot;<\/span><span class=\"sy0\">&gt;&lt;\/<\/span>script<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sy0\">&lt;!--<\/span> We<span class=\"st0\">'ll need Socket.io for server communication, so let'<\/span>s include it now. <span class=\"sy0\">--&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>script src<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;\/socket.io\/socket.io.js&quot;<\/span><span class=\"sy0\">&gt;&lt;\/<\/span>script<span class=\"sy0\">&gt;<\/span><br \/>\n<span class=\"sy0\">&lt;\/<\/span>head<span class=\"sy0\">&gt;<\/span><br \/>\n<span class=\"sy0\">&lt;<\/span>body<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div <span class=\"kw5\">class<\/span><span class=\"sy0\">=<\/span><span class=\"st0\">&quot;container&quot;<\/span><span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>h1<span class=\"sy0\">&gt;<\/span>Customer Review Analysis with AI<span class=\"sy0\">&lt;\/<\/span>h1<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>button id<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;analyze-btn&quot;<\/span><span class=\"sy0\">&gt;<\/span>Analyze all reviews<span class=\"sy0\">&lt;\/<\/span>button<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div id<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;grid&quot;<\/span><span class=\"sy0\">&gt;&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>script src<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;app.js&quot;<\/span><span class=\"sy0\">&gt;&lt;\/<\/span>script<span class=\"sy0\">&gt;<\/span><br \/>\n<span class=\"sy0\">&lt;\/<\/span>body<span class=\"sy0\">&gt;<\/span><br \/>\n<span class=\"sy0\">&lt;\/<\/span>html<span class=\"sy0\">&gt;<\/span><\/div><\/div>\n<ul>\n<li>Prepare the initial data, initialize the Grid in the <a href=\"https:\/\/github.com\/DHTMLX\/grid-ai-demo\/blob\/main\/frontend\/app.js\" rel=\"noopener\" target=\"_blank\">app.js<\/a> file, and load the data into it:<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">document.<span class=\"me1\">addEventListener<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;DOMContentLoaded&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw1\">function<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ 1. Raw data (IDs + reviews)<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> gridData <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> review_text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Five stars! It prevents catastrophic system failures (aka 'life-ruining decisions').&quot;<\/span><span class=\"sy0\">,<\/span> sentiment<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;&quot;<\/span><span class=\"sy0\">,<\/span> tags<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;&quot;<\/span><span class=\"sy0\">,<\/span> summary<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"nu0\">2<\/span><span class=\"sy0\">,<\/span> review_text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;The 'Avoid Major Disaster' feature is a plus, but the 'Guilt' user interface is poorly designed.&quot;<\/span><span class=\"sy0\">,<\/span> sentiment<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;&quot;<\/span><span class=\"sy0\">,<\/span> tags<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;&quot;<\/span><span class=\"sy0\">,<\/span> summary<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"nu0\">3<\/span><span class=\"sy0\">,<\/span> review_text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A very intrusive background app that's impossible to uninstall. Constantly sends push notifications at night.&quot;<\/span><span class=\"sy0\">,<\/span> sentiment<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;&quot;<\/span><span class=\"sy0\">,<\/span> tags<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;&quot;<\/span><span class=\"sy0\">,<\/span> summary<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;&quot;<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ ... and other reviews<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ 2. Now, initialize the Grid widget<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> grid <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> dhx.<span class=\"me1\">Grid<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;grid&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; columns<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ The review column is editable<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;review_text&quot;<\/span><span class=\"sy0\">,<\/span> header<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Review&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span> editable<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">,<\/span> width<span class=\"sy0\">:<\/span> <span class=\"nu0\">450<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ These columns will be populated by the AI<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;sentiment&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; header<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Sentiment&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ Use a template for a more appealing display<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; template<span class=\"sy0\">:<\/span> <span class=\"br0\">&#40;<\/span>text<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>text <span class=\"sy0\">===<\/span> <span class=\"st0\">'positive'<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw1\">return<\/span> <span class=\"st0\">'\ud83d\udc4d Positive'<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>text <span class=\"sy0\">===<\/span> <span class=\"st0\">'negative'<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw1\">return<\/span> <span class=\"st0\">'\ud83d\udc4e Negative'<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>text <span class=\"sy0\">===<\/span> <span class=\"st0\">'neutral'<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw1\">return<\/span> <span class=\"st0\">'\ud83d\ude10 Neutral'<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>text <span class=\"sy0\">===<\/span> <span class=\"st0\">'mixed'<\/span><span class=\"br0\">&#41;<\/span> <span class=\"kw1\">return<\/span> <span class=\"st0\">'\ud83e\udd14 Mixed'<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> text<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;tags&quot;<\/span><span class=\"sy0\">,<\/span> header<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Tags&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span> width<span class=\"sy0\">:<\/span> <span class=\"nu0\">250<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;summary&quot;<\/span><span class=\"sy0\">,<\/span> header<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Summary&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; data<span class=\"sy0\">:<\/span> gridData<span class=\"sy0\">,<\/span> <span class=\"co1\">\/\/ Load the data<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; autoWidth<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; autoHeight<span class=\"sy0\">:<\/span> <span class=\"kw2\">true<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>As a result, you\u2019ll get a data table with the reviews displayed in there. The &#8220;Sentiment,&#8221; &#8220;Tags,&#8221; and &#8220;Summary&#8221; columns will still be empty at this point. That\u2019s where the AI comes in next.<\/p>\n<h2>Step 2: Enabling AI-Powered Analysis in the Grid<\/h2>\n<p>After adding the reviews to the table, it is time to trigger their analysis. There are two possible analysis scenarios:<\/p>\n<ol>\n<li>Bulk analysis &#8211; when a user clicks the &#8220;Analyze all reviews&#8221; button <\/li>\n<li>Single analysis &#8211; immediately after a user edits the text of a review in its cell <\/li>\n<\/ol>\n<p>But first, you need to establish communication between your app and the server (which takes care of the OpenAI requests). To do that, you can use WebSockets via the <a href=\"https:\/\/socket.io\/\" rel=\"noopener\" target=\"_blank\">Socket.IO<\/a> library. It will help ensure real-time updates between the client and server parts of the app. <\/p>\n<p>Here is how it all looks in the <strong>app.js<\/strong> file:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"co1\">\/\/ ... (after grid initialization)<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/ Establish a connection to the server<\/span><br \/>\n<span class=\"kw1\">const<\/span> socket <span class=\"sy0\">=<\/span> io<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\nsocket.<span class=\"me1\">on<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'connect'<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> console.<span class=\"me1\">log<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Successfully connected to the server!&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> analyzeButton <span class=\"sy0\">=<\/span> document.<span class=\"me1\">getElementById<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;analyze-btn&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/ Scenario 1: Bulk analysis on button click<\/span><br \/>\nanalyzeButton.<span class=\"me1\">addEventListener<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'click'<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ Get all rows that haven't been analyzed yet (i.e., have no summary)<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> reviewsToAnalyze <span class=\"sy0\">=<\/span> grid.<span class=\"me1\">data<\/span>.<span class=\"me1\">serialize<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; .<span class=\"me1\">filter<\/span><span class=\"br0\">&#40;<\/span>row <span class=\"sy0\">=&gt;<\/span> row.<span class=\"me1\">review_text<\/span> <span class=\"sy0\">&amp;&amp;<\/span> <span class=\"sy0\">!<\/span>row.<span class=\"me1\">summary<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; .<span class=\"me1\">map<\/span><span class=\"br0\">&#40;<\/span>row <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> row.<span class=\"me1\">id<\/span><span class=\"sy0\">,<\/span> text<span class=\"sy0\">:<\/span> row.<span class=\"me1\">review_text<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>reviewsToAnalyze.<span class=\"me1\">length<\/span> <span class=\"sy0\">&gt;<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ Send the array of reviews to the server<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; socket.<span class=\"me1\">emit<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'analyze_bulk_reviews'<\/span><span class=\"sy0\">,<\/span> reviewsToAnalyze<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/ Scenario 2: Single row analysis after an edit<\/span><br \/>\ngrid.<span class=\"me1\">events<\/span>.<span class=\"me1\">on<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;afterEditEnd&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#40;<\/span>value<span class=\"sy0\">,<\/span> row<span class=\"sy0\">,<\/span> column<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ Fire only if the &quot;review_text&quot; column was changed<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>column.<span class=\"me1\">id<\/span> <span class=\"sy0\">===<\/span> <span class=\"st0\">&quot;review_text&quot;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> reviewData <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> row.<span class=\"me1\">id<\/span><span class=\"sy0\">,<\/span> text<span class=\"sy0\">:<\/span> row.<span class=\"me1\">review_text<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ Send a single review to the server for instant analysis<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; socket.<span class=\"me1\">emit<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'analyze_single_review'<\/span><span class=\"sy0\">,<\/span> reviewData<span class=\"sy0\">,<\/span> <span class=\"br0\">&#40;<\/span>response<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ Process the immediate response from the server<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; updateGridRow<span class=\"br0\">&#40;<\/span>response.<span class=\"me1\">payload<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>The key things here are:<\/p>\n<ul>\n<li><strong>grid.data.serialize()<\/strong> retrieves data from the grid table<\/li>\n<li><strong>afterEditEnd<\/strong> event is a hook for reacting to user input<\/li>\n<\/ul>\n<p>Together, they give you two natural entry points for submitting data to the backend.<\/p>\n<p>Also, you\u2019ll need a special helper function (<strong>updateGridRow<\/strong>) for updating the table with new content:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw1\">function<\/span> updateGridRow<span class=\"br0\">&#40;<\/span>analysis<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>analysis<span class=\"br0\">&#41;<\/span> <span class=\"kw1\">return<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> tagsString <span class=\"sy0\">=<\/span> <span class=\"kw4\">Array<\/span>.<span class=\"me1\">isArray<\/span><span class=\"br0\">&#40;<\/span>analysis.<span class=\"me1\">tags<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">?<\/span> analysis.<span class=\"me1\">tags<\/span>.<span class=\"me1\">join<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">', '<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">:<\/span> analysis.<span class=\"me1\">tags<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ This is a key DHTMLX Grid method!<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ It finds a row by its ID and updates its cells with new data.<\/span><br \/>\n&nbsp; &nbsp; grid.<span class=\"me1\">data<\/span>.<span class=\"me1\">update<\/span><span class=\"br0\">&#40;<\/span>analysis.<span class=\"me1\">id<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; sentiment<span class=\"sy0\">:<\/span> analysis.<span class=\"me1\">sentiment<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; tags<span class=\"sy0\">:<\/span> tagsString<span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; summary<span class=\"sy0\">:<\/span> analysis.<span class=\"me1\">summary<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<h2>Step 3: Receiving Results and Updating the Grid<\/h2>\n<p>The successful sending of data to the server is only half the battle, as you have yet to handle the response. When the AI sends the <strong>review_analyzed<\/strong> event back, you need to receive it and update the right row. <\/p>\n<p>This is where the <strong>updateGridRow<\/strong> function steps in and calls <strong>grid.data.update(id, data)<\/strong>. It is a go-to option for updating rows in the Grid on the fly.<\/p>\n<p>For this purpose, you add a handler in <strong>app.js<\/strong>:<\/p>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"co1\">\/\/ ... (inside the DOMContentLoaded event listener)<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/ Listen for an event from the server with analysis results<\/span><br \/>\nsocket.<span class=\"me1\">on<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'review_analyzed'<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#40;<\/span>response<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>response.<span class=\"me1\">status<\/span> <span class=\"sy0\">===<\/span> <span class=\"st0\">'success'<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; updateGridRow<span class=\"br0\">&#40;<\/span>response.<span class=\"me1\">payload<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ If an error occurred, let the user know<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; grid.<span class=\"me1\">data<\/span>.<span class=\"me1\">update<\/span><span class=\"br0\">&#40;<\/span>response.<span class=\"me1\">id<\/span><span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span> summary<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Error during analysis.&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; console.<span class=\"me1\">error<\/span><span class=\"br0\">&#40;<\/span>`Analysis failed <span class=\"kw1\">for<\/span> ID $<span class=\"br0\">&#123;<\/span>response.<span class=\"me1\">id<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">:<\/span> $<span class=\"br0\">&#123;<\/span>response.<span class=\"me1\">message<\/span><span class=\"br0\">&#125;<\/span>`<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>With this in place, the grid updates instantly without the need for reloading.<\/p>\n<h2>Step 4: Working on AI Responses<\/h2>\n<p>The key step on the backend is to enable the AI functionality. We won\u2019t dive into every single line of code here (the <a href=\"https:\/\/github.com\/DHTMLX\/grid-ai-demo\/\" rel=\"noopener\" target=\"_blank\">full example<\/a> is on GitHub), but the main trick is how you ask the AI for particular data.<\/p>\n<p>A simple &#8220;analyze this&#8221; prompt won\u2019t do the trick. Instead, you can take advantage of Tool Calling. This technique allows specifying the structure of responses expected from AI.<\/p>\n<p>Here is what to do next:<\/p>\n<ul>\n<li>You give AI its main instruction (<a href=\"https:\/\/github.com\/DHTMLX\/grid-ai-demo\/blob\/7dcf59061d77b8df9eb05daea7ce875cf1a435a3\/backend\/server.js#L164\" rel=\"noopener\" target=\"_blank\">system prompt<\/a>). To put it simply, you tell AI that it plays the role of a data analysis assistant responsible for sentiment, tags, and summary fields.<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"co1\">\/\/ backend\/server.js<\/span><br \/>\n<span class=\"kw1\">function<\/span> getSystemPrompt<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> `You are an AI assistant <span class=\"kw1\">for<\/span> data analysis. <span class=\"me1\">Your<\/span> task is to analyze customer reviews. <span class=\"me1\">For<\/span> each review<span class=\"sy0\">,<\/span> determine<span class=\"sy0\">:<\/span><br \/>\n&nbsp; &nbsp; <span class=\"nu0\">1<\/span>. &nbsp;<span class=\"sy0\">**<\/span>sentiment<span class=\"sy0\">**:<\/span> <span class=\"st0\">'positive'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'negative'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'neutral'<\/span><span class=\"sy0\">,<\/span> or <span class=\"st0\">'mixed'<\/span>.<br \/>\n&nbsp; &nbsp; <span class=\"nu0\">2<\/span>. &nbsp;<span class=\"sy0\">**<\/span>tags<span class=\"sy0\">**:<\/span> <span class=\"nu0\">2<\/span><span class=\"sy0\">-<\/span><span class=\"nu0\">4<\/span> keywords <span class=\"br0\">&#40;<\/span>e.<span class=\"me1\">g<\/span>.<span class=\"sy0\">,<\/span> <span class=\"st0\">'bugs'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'resources'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'notifications'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'UI\/UX'<\/span><span class=\"br0\">&#41;<\/span>.<br \/>\n&nbsp; &nbsp; <span class=\"nu0\">3<\/span>. &nbsp;<span class=\"sy0\">**<\/span>summary<span class=\"sy0\">**:<\/span> a very brief summary of the review <span class=\"kw1\">in<\/span> English.<br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"me1\">Always<\/span> use the provided <span class=\"st0\">'update_grid_with_analysis'<\/span> <span class=\"kw1\">function<\/span> to <span class=\"kw1\">return<\/span> the result.`<span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<ul>\n<li>Using the Tool Schema definition, you provide a <a href=\"https:\/\/github.com\/DHTMLX\/grid-ai-demo\/blob\/main\/backend\/schemaListGrid.js\" rel=\"noopener\" target=\"_blank\">blueprint<\/a> for the JSON structure the AI must return.<\/li>\n<\/ul>\n<div class=\"codecolorer-container javascript default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"co1\">\/\/ backend\/schemaListGrid.js<\/span><br \/>\n<span class=\"kw5\">export<\/span> <span class=\"kw1\">const<\/span> schemaList <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;function&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">function<\/span><span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; name<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;update_grid_with_analysis&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; description<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;Accepts an array of analyzed reviews and returns them to update the grid.&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; parameters<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;object&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; properties<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; analyzed_rows<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;array&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; items<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;object&quot;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; properties<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span> type<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"st0\">&quot;string&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;number&quot;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span> description<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;The ID of the row in the grid.&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sentiment<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span> type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;string&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"kw5\">enum<\/span><span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"st0\">&quot;positive&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;negative&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;neutral&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;mixed&quot;<\/span><span class=\"br0\">&#93;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tags<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span> type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;array&quot;<\/span><span class=\"sy0\">,<\/span> items<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span> type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;string&quot;<\/span> <span class=\"br0\">&#125;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; summary<span class=\"sy0\">:<\/span> <span class=\"br0\">&#123;<\/span> type<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;string&quot;<\/span><span class=\"sy0\">,<\/span> description<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;A very brief summary of the review.&quot;<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; required<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"st0\">&quot;id&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;sentiment&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;tags&quot;<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">&quot;summary&quot;<\/span><span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; required<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"st0\">&quot;analyzed_rows&quot;<\/span><span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>Thus, you make sure that AI sticks to the expected format instead of making things up, thereby providing valid results.<\/p>\n<p>That\u2019s it. You\u2019ve connected the modern interface of DHTMLX Grid with AI to make data analysis smoother and more practical. For more technical details, check out the <a href=\"https:\/\/github.com\/DHTMLX\/grid-ai-demo\/tree\/main\/backend\" rel=\"noopener\" target=\"_blank\">full backend code<\/a> on GitHub.<\/p>\n<h2>Wrapping Up<\/h2>\n<p>Integrating DHTMLX Grid with AI-based capabilities opens up new opportunities for ensuring an enjoyable user experience with datasets of any complexity. The same pattern can be used for many other goals: classifying support tickets, enriching user profiles, or finding trends in comments. Learn more about DHTMLX Grid in the <a href=\"https:\/\/docs.dhtmlx.com\/suite\/grid\/\" rel=\"noopener\" target=\"_blank\">documentation<\/a> and download a <a href=\"https:\/\/dhtmlx.com\/docs\/products\/dhtmlxGrid\/download.shtml\" rel=\"noopener\" target=\"_blank\">free 30-day trial version<\/a> of this widget to test its capabilities in real-world scenarios. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Data management functionalities, like a data table, can be safely attributed to core parts of modern business apps. DHTMLX JavaScript Grid component helps developers speed up the implementation of &#8230;<\/p>\n","protected":false},"author":101014,"featured_media":14486,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[71],"tags":[77,33,6],"class_list":["post-14485","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-ai","tag-all-posts","tag-dhtmlxgrid"],"_links":{"self":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14485","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/users\/101014"}],"replies":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/comments?post=14485"}],"version-history":[{"count":8,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14485\/revisions"}],"predecessor-version":[{"id":14499,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/14485\/revisions\/14499"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media\/14486"}],"wp:attachment":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media?parent=14485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/categories?post=14485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/tags?post=14485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}