Skip to content

Commit 39e6b64

Browse files
Chat: add Integrate with AI Service (DevExpress#7737) (DevExpress#7827)
1 parent be58262 commit 39e6b64

File tree

5 files changed

+333
-0
lines changed

5 files changed

+333
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
You can integrate DevExtreme Chat with various AI services, such as [OpenAI](https://platform.openai.com/docs/overview), [Azure OpenAI](https://learn.microsoft.com/en-us/azure/ai-services/openai/), [Google Dialogflow](https://cloud.google.com/dialogflow/docs), and [Microsoft Bot Framework](https://learn.microsoft.com/en-us/azure/bot-service/index-bf-sdk).
2+
3+
[note]
4+
5+
Review this demo for Azure OpenAI integration:
6+
7+
#include btn-open-demo with {
8+
href: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/Chat/AIAndChatbotIntegration/"
9+
}
10+
11+
[/note]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
This help topic describes how to integrate Chat with [OpenAI](https://platform.openai.com/docs/overview). You can find the full example code in the following GitHub repository:
2+
3+
#include btn-open-github with {
4+
href: "https://github.com/DevExpress-Examples/devextreme-chat-openai-integration"
5+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
First, obtain an [API key](https://platform.openai.com/api-keys). Next, install OpenAI SDK:
2+
3+
---
4+
5+
##### jQuery
6+
7+
<!-- tab: index.html -->
8+
<head>
9+
<!-- ... -->
10+
<script type="module">
11+
import OpenAI from "https://esm.sh/[email protected]";
12+
</script>
13+
</hea>
14+
15+
[note] Ensure DevExtreme is [installed](/Documentation/Guide/jQuery_Components/Add_DevExtreme_to_a_jQuery_Application/) in your project.
16+
17+
##### Angular
18+
19+
npm install openai
20+
21+
[note] Ensure DevExtreme is [installed](/Documentation/Guide/Angular_Components/Getting_Started/Add_DevExtreme_to_an_Angular_CLI_Application/) in your project.
22+
23+
##### Vue
24+
25+
npm install openai
26+
27+
[note] Ensure DevExtreme is [installed](/Documentation/Guide/Vue_Components/Add_DevExtreme_to_a_Vue_Application/) in your project.
28+
29+
##### React
30+
31+
npm install openai
32+
33+
[note] Ensure DevExtreme is [installed](/Documentation/Guide/React_Components/Add_DevExtreme_to_a_React_Application/) in your project.
34+
35+
---
36+
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
Create an instance of OpenAI:
2+
3+
---
4+
5+
##### jQuery
6+
7+
const chatService = new OpenAI({
8+
dangerouslyAllowBrowser: true,
9+
apiKey: "OPENAI_API_KEY", // insert your OpenAI API key
10+
});
11+
12+
##### Angular
13+
14+
<!--TypeScript-->
15+
import { OpenAI } from "openai";
16+
17+
export class AppService {
18+
chatService: OpenAI;
19+
OpenAIConfig = {
20+
dangerouslyAllowBrowser: true,
21+
apiKey: "OPENAI_API_KEY", // insert your OpenAI API key
22+
};
23+
constructor() {
24+
this.chatService = new OpenAI(this.OpenAIConfig);
25+
}
26+
}
27+
28+
##### Vue
29+
30+
<!--TypeScript-->
31+
import { OpenAI } from 'openai';
32+
33+
const OpenAIConfig = {
34+
dangerouslyAllowBrowser: true,
35+
apiKey: 'OPEN_AI_KEY', // insert your OpenAI API key
36+
};
37+
38+
const chatService = new OpenAI(OpenAIConfig);
39+
40+
##### React
41+
42+
<!--TypeScript-->
43+
import { OpenAI } from "openai";
44+
45+
class AppService {
46+
chatService: OpenAI;
47+
OpenAIConfig = {
48+
dangerouslyAllowBrowser: true,
49+
apiKey: "OPENAI_API_KEY", // insert your OpenAI API key
50+
};
51+
constructor() {
52+
this.chatService = new OpenAI(this.OpenAIConfig);
53+
}
54+
}
55+
56+
---
57+
58+
[important] `dangerouslyAllowBrowser: true` enables browser-side requests. This exposes the API key. For production, route requests through your backend.
59+
60+
Implement a `getAIResponse(messages)` function to call the OpenAI API for responses. Here, the incoming argument `messages` is an array of `{ role: "user" | "assistant" | "system"; content: string }` objects.
61+
62+
---
63+
64+
##### jQuery
65+
66+
async function getAIResponse(messages) {
67+
const params = {
68+
messages,
69+
model: 'gpt-4o-mini',
70+
};
71+
const response = await chatService.chat.completions.create(params);
72+
return response.choices[0].message?.content;
73+
}
74+
75+
##### Angular
76+
77+
<!--TypeScript-->
78+
async getAIResponse(messages: Array<{ role: "user" | "assistant" | "system"; content: string }>) {
79+
const params = {
80+
messages: messages.map(msg => ({
81+
role: msg.role,
82+
content: msg.content
83+
})),
84+
model: 'gpt-4o-mini',
85+
};
86+
const response = await this.chatService.chat.completions.create(params);
87+
const data = { choices: response.choices };
88+
return data.choices[0].message?.content;
89+
}
90+
91+
##### Vue
92+
93+
<!--TypeScript-->
94+
const getAIResponse = async(messages: Array<{ role: 'user' | 'assistant' | 'system'; content: string }>) => {
95+
const params = {
96+
messages: messages.map(msg => ({
97+
role: msg.role,
98+
content: msg.content
99+
})),
100+
model: 'gpt-4o-mini'
101+
};
102+
103+
const response = await chatService.chat.completions.create(params);
104+
return response.choices[0].message?.content;
105+
};
106+
107+
##### React
108+
109+
<!--TypeScript-->
110+
async getAIResponse(messages: { role: 'user' | 'assistant' | 'system'; content: string }[]): Promise<any> {
111+
const params = {
112+
messages: messages.map((msg) => ({
113+
role: msg.role,
114+
content: msg.content,
115+
})),
116+
model: 'gpt-4o-mini',
117+
};
118+
119+
const response = await this.chatService.chat.completions.create(params);
120+
const data = { choices: response.choices };
121+
return data.choices[0].message?.content;
122+
}
123+
124+
---
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
To synchronize Chat and OpenAI, declare the `processMessageSending()` function. This function configures [typingUsers](/Documentation/ApiReference/UI_Components/dxChat/Configuration/#typingUsers), pushes the assistant message to the store, and renders the message.
2+
3+
---
4+
5+
##### jQuery
6+
7+
<!-- tab: index.js -->
8+
async function processMessageSending() {
9+
toggleDisabledState(true);
10+
instance.option({ typingUsers: [assistant] });
11+
try {
12+
const aiResponse = await getAIResponse(messages);
13+
setTimeout(() => {
14+
instance.option({ typingUsers: [] });
15+
messages.push({ role: 'assistant', content: aiResponse });
16+
renderMessage(aiResponse);
17+
}, 200);
18+
} catch {
19+
instance.option({ typingUsers: [] });
20+
alertLimitReached();
21+
} finally {
22+
toggleDisabledState(false);
23+
}
24+
}
25+
26+
##### Angular
27+
28+
<!--TypeScript-->
29+
async processMessageSending() {
30+
this.toggleDisabledState(true);
31+
this.typingUsersSubject.next([this.assistant]);
32+
try {
33+
const aiResponse = await this.getAIResponse(this.messages);
34+
setTimeout(() => {
35+
this.typingUsersSubject.next([]);
36+
this.messages.push({ role: "assistant", content: aiResponse ?? "" });
37+
this.renderAssistantMessage(aiResponse ?? "");
38+
}, 200);
39+
} catch {
40+
this.typingUsersSubject.next([]);
41+
this.alertLimitReached();
42+
} finally {
43+
this.toggleDisabledState(false);
44+
}
45+
}
46+
47+
##### Vue
48+
49+
<!--TypeScript-->
50+
const processMessageSending = async() => {
51+
toggleDisabledState(true);
52+
typingUsers.value = [assistant];
53+
try {
54+
const aiResponse = await getAIResponse(messages.value);
55+
setTimeout(() => {
56+
typingUsers.value = [];
57+
messages.value.push({ role: 'assistant', content: aiResponse ?? '' });
58+
renderAssistantMessage(aiResponse ?? '');
59+
}, 200);
60+
} catch {
61+
typingUsers.value = [];
62+
alertLimitReached();
63+
} finally {
64+
toggleDisabledState(false);
65+
}
66+
};
67+
68+
##### React
69+
70+
<!--TypeScript-->
71+
async processMessageSending(): Promise<void> {
72+
this.toggleDisabledState(true);
73+
this.typingUsersSubject.next([this.assistant]);
74+
try {
75+
const aiResponse = await this.getAIResponse(this.messages);
76+
setTimeout(() => {
77+
this.typingUsersSubject.next([]);
78+
this.messages.push({ role: 'assistant', content: aiResponse ?? '' });
79+
this.renderAssistantMessage(aiResponse ?? '');
80+
}, 200);
81+
} catch {
82+
this.typingUsersSubject.next([]);
83+
this.alertLimitReached();
84+
} finally {
85+
this.toggleDisabledState(false);
86+
}
87+
}
88+
89+
---
90+
91+
Call `processMessageSending()` after a user message is sent in the [onMessageEntered](/Documentation/ApiReference/UI_Components/dxChat/Configuration/#onMessageEntered) event handler:
92+
93+
---
94+
95+
##### jQuery
96+
97+
<!-- tab: index.js -->
98+
const instance = $('#dx-ai-chat').dxChat({
99+
// ...
100+
dataSource: customStore,
101+
reloadOnChange: false,
102+
onMessageEntered: (e) => {
103+
const { message } = e;
104+
customStore.push([{ type: 'insert', data: { id: Date.now(), ...message } }]);
105+
messages.push({ role: 'user', content: message.text });
106+
processMessageSending();
107+
}
108+
}).dxChat('instance');
109+
110+
##### Angular
111+
112+
<!--TypeScript-->
113+
async onMessageEntered({ message, event }: MessageEnteredEvent) {
114+
this.dataSource
115+
?.store()
116+
.push([{ type: "insert", data: { id: Date.now(), ...message } }]);
117+
118+
this.messages.push({ role: "user", content: message?.text ?? "" });
119+
this.processMessageSending();
120+
}
121+
122+
##### Vue
123+
124+
<!--TypeScript-->
125+
const onMessageEntered = async(e: MessageEnteredEvent) => {
126+
let { message } = e;
127+
dataSource.value?.store().push([{
128+
type: 'insert',
129+
data: { id: Date.now(), ...message }
130+
}]);
131+
132+
messages.value.push({ role: 'user', content: message?.text ?? '' });
133+
await processMessageSending();
134+
};
135+
136+
##### React
137+
138+
<!--TypeScript-->
139+
onMessageEntered({ message }: MessageEnteredEvent): void {
140+
this.dataSource
141+
?.store()
142+
.push([{ type: 'insert', data: { id: Date.now(), ...message } }]);
143+
144+
this.messages.push({ role: 'user', content: message?.text ?? '' });
145+
void this.processMessageSending();
146+
}
147+
148+
---
149+
150+
You can also implement additional UI capabilities to further improve user experience:
151+
152+
- Add a Markdown converter for assistant outputs. For more information, refer to the [Markdown Support](/Documentation/Guide/UI_Components/Chat/Markdown_Support/) help topic.
153+
- Define a [messageTemplate](/Documentation/ApiReference/UI_Components/dxChat/Configuration/#messageTemplate) for the assistant’s responses and add two buttons: copy and regenerate response. See the example code in the GitHub repository:
154+
155+
#include btn-open-github with {
156+
href: "https://github.com/DevExpress-Examples/devextreme-chat-openai-integration"
157+
}

0 commit comments

Comments
 (0)