Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
16,887 changes: 16,887 additions & 0 deletions apps/demos/Demos/DataGrid/AIAssistant/jQuery/data.js

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions apps/demos/Demos/DataGrid/AIAssistant/jQuery/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
<link rel="stylesheet" type="text/css" href="../../../../node_modules/devextreme/dist/css/dx.light.css" />
<script src="../../../../node_modules/jquery/dist/jquery.min.js"></script>
<script src="../../../../node_modules/devextreme-dist/js/dx.all.js"></script>
<script src="../../../../node_modules/devextreme-dist/js/dx.ai-integration.js"></script>
<script type="module">
import { AzureOpenAI } from "https://esm.sh/openai@4.73.1";

window.AzureOpenAI = AzureOpenAI;
</script>
<script src="data.js"></script>
<script src="index.js"></script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<div id="data-grid-demo">
<div id="gridContainer"></div>
</div>
</div>
</body>
</html>
199 changes: 199 additions & 0 deletions apps/demos/Demos/DataGrid/AIAssistant/jQuery/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
$(() => {
const deployment = 'gpt-4o-mini';
const apiVersion = '2024-02-01';
const endpoint = 'https://public-api.devexpress.com/demo-openai';
const apiKey = 'DEMO';

const aiService = new AzureOpenAI({
dangerouslyAllowBrowser: true,
deployment,
endpoint,
apiVersion,
apiKey,
});

async function getAIResponse(messages, signal, responseSchema) {
const params = {
messages,
model: deployment,
max_tokens: 1000,
temperature: 0.7,
};

params.response_format = {
type: 'json_schema',
json_schema: {
name: 'grid_assistant_response',
strict: true,
schema: responseSchema,
},
};
Comment thread
Raushen marked this conversation as resolved.

const response = await aiService.chat.completions
.create(params, { signal });
const result = response.choices[0].message?.content;

return result;
}

async function getAIResponseRecursive(messages, signal, responseSchema) {
return getAIResponse(messages, signal, responseSchema)
.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, responseSchema);
});
}

const aiIntegration = new DevExpress.aiIntegration.AIIntegration({
sendRequest({ prompt, data }) {
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, data?.responseSchema);

const result = {
promise,
abort: () => {
controller.abort();
},
};

return result;
},
});

let chatInstance;

$('#gridContainer').dxDataGrid({
dataSource: sales,
showBorders: true,
keyExpr: 'Id',
searchPanel: {
visible: true,
width: 240,
placeholder: 'Search...',
},
groupPanel: {
visible: true,
},
headerFilter: {
visible: true,
},
filterRow: {
visible: true,
},
paging: {
pageSize: 10,
},
pager: {
visible: true,
allowedPageSizes: [10, 25, 50, 100],
showPageSizeSelector: true,
},
aiAssistant: {
enabled: true,
aiIntegration,
chat: {
onInitialized(e) {
chatInstance = e.component;
},
suggestions: {
items: [
{
text: '💡 Help',
prompt: `💡 The DataGrid AI Assistant allows you to control the component using natural language. You can execute commands such as the following:
• Sort records
• Apply a filter
• Search for a specific value
• Group records by a field
• Focus and select rows
• Modify paging settings
• Pin, resize, and reorder columns
• Configure data summaries
• Pick a suggestion or enter a custom request to get started.`,
},
{
text: '🔍 Filter Sector by Health',
prompt: 'Filter Sector by Health',
},
{
text: '↕️ Sort by Region',
prompt: 'Sort by Region',
},
{
text: '🧩 Group by Product',
prompt: 'Group by Product',
width: 170,
},
],
onItemClick(e) {
const { prompt, text } = e.itemData;

if (text === '💡 Help') {
const message = {
id: Date.now(),
timestamp: new Date(),
author: { id: 'user' },
text: prompt,
};

chatInstance.getDataSource().store().push([{ type: 'insert', data: message }]);
} else {
chatInstance.option('inputFieldText', prompt);
}
},
},
},
},
columns: [
{
dataField: 'Product',
},
{
dataField: 'Amount',
caption: 'Sale Amount',
dataType: 'number',
format: 'currency',
},
{
dataField: 'Region',
dataType: 'string',
},
{
dataField: 'Sector',
dataType: 'string',
},
{
dataField: 'SaleDate',
dataType: 'date',
},
{
dataField: 'Customer',
dataType: 'string',
},
],
});
});
21 changes: 19 additions & 2 deletions apps/demos/menuMeta.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,22 @@
"Modules": "openai"
}
]
},
{
"Name": "AI Assistant",
"Equivalents": "",
"Demos": [
{
"Title": "AI Assistant",
"Name": "AIAssistant",
"Widget": "DataGrid",
"Badge": "AI",
"DemoType": "Web",
"TopLevel": true,
"Equivalents": "Smart DataGrid Assistant, Natural Language DataGrid Assistant, Natural Language Data Queries, AI-Powered DataGrid Assistant, AI Copilot for DataGrid, Conversational DataGrid, AI DataGrid Helper, AI-Assisted Data Manipulation",
"Modules": "openai"
}
]
}
]
},
Expand Down Expand Up @@ -743,9 +759,10 @@
"Title": "AI Assistant",
"Name": "AIAssistant",
"Widget": "DataGrid",
"Badge": "Roadmap",
"Badge": "AI",
"DemoType": "Web",
"RoadmapSurveyUrl": "https://www.devexpress.com/support/surveys/devextreme-roadmap-2026-ai-assistant.xml"
"Equivalents": "Smart DataGrid Assistant, Natural Language DataGrid Assistant, Natural Language Data Queries, AI-Powered DataGrid Assistant, AI Copilot for DataGrid, Conversational DataGrid, AI DataGrid Helper, AI-Assisted Data Manipulation",
"Modules": "openai"
}
]
},
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export class AIAssistantView extends View {
// (re-evaluated automatically on show and window resize).
// @ts-expect-error type declaration
height: () => this.getPopupHeight(),
_ignoreFunctionValueDeprecation: true,
onShowing: (): void => {
this.visibilityChanged?.fire(true);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const DEFAULT_POPUP_OPTIONS = {
visible: false,
shading: false,
showCloseButton: true,
useFlatToolbarButtons: true,
useDefaultToolbarButtons: false,
};

export const DEFAULT_CHAT_OPTIONS = {
Expand Down
Loading