Connecting the AIPrompt component to a streaming AI chat client service is a common scenario.
In this article, you will build a practical, end-to-end example that wires the AIPrompt to a lightweight AI chat client, which opens a chat session, sends the user prompt, and streams the model's response into the Output view.
To creare an AI chat serivce that connects to the AIPrompt, follow the next steps:
Add a reference to the AI chat client script and initialize the client.
JS
<script src="~/ai-chat-service.js"></script><script>const apiClient =newAIChatClient({// Replace with your AI service endpoint (for example, "https://api.yourdomain.com/ai").apiBaseUrl:"https://demos.telerik.com/service/v2/ai",defaultHeaders:{'Content-Type':'application/json'},aiId: kendo.guid()});</script>
JS
classAIChatClient{constructor(config){this.apiBaseUrl= config.apiBaseUrl||"https://demos.telerik.com/service/v2/ai";// Replace with your AI service endpoint (for example, "https://api.yourdomain.com/ai").this.defaultHeaders= config.defaultHeaders||{'Content-Type':'application/json'};this.aiId= config.aiId|| kendo.guid();this.currentChatId=null;this.controller=null;this.onTokenUpdate= config.onTokenUpdate||(()=>{});this.onChatStateChange= config.onChatStateChange||(()=>{});}asyncapiRequest(endpoint, options ={}){const url =`${this.apiBaseUrl}${endpoint}`;const defaultOptions ={headers:this.defaultHeaders};const response =awaitfetch(url,{...defaultOptions,...options });if(!response.ok){thrownewError(`HTTP error! status: ${response.status}`);}return response;}asyncsendMessage(promptText, callbacks ={}){if(!this.currentChatId){awaitthis.createNewChat();}this.controller=newAbortController();try{const response =awaitthis.apiRequest(`/chat/${encodeURIComponent(this.currentChatId)}`,{method:'POST',body:JSON.stringify(promptText),signal:this.controller.signal});returnawaitthis.processStreamingResponse(response, callbacks);}catch(error){this.handleStreamingError(error);throw error;}finally{this.controller=null;}}asynccreateNewChat(){try{const response =awaitthis.apiRequest('/chat/conversations',{method:'POST'});const data =await response.json();this.currentChatId= data.chatId;this.onChatStateChange({chatId: data.chatId,action:'created'});return data.chatId;}catch(err){console.error("Failed to create new chat:", err);throw err;}}asyncprocessStreamingResponse(response, callbacks ={}){let buffer ="";let accumulatedText ="";const reader = response.body.getReader();const decoder =newTextDecoder();while(true){const result =await reader.read();if(result.done)break;
buffer += decoder.decode(result.value,{stream:!result.done});const lines = buffer.split("\n");
buffer = lines.pop();for(const line of lines){if(line.trim()){try{const data =JSON.parse(line);
accumulatedText =this.handleStreamingData(data, accumulatedText, callbacks);}catch(e){console.error("Failed to parse streaming data:", e);}}}}return accumulatedText;}handleStreamingData(data, accumulatedText, callbacks ={}){switch(data.status){case"start":if(callbacks.onStart) callbacks.onStart(data);return"";case"streaming":const messageContent = data.message|| data.content|| data.text||"";
accumulatedText += messageContent;if(callbacks.onProgress) callbacks.onProgress(accumulatedText, data);return accumulatedText;case"complete":if(data.message&& data.message.inputTokens!==undefined){this.onTokenUpdate(data.message.inputTokens, data.message.outputTokens);}elseif(data.inputTokens!==undefined){this.onTokenUpdate(data.inputTokens, data.outputTokens);}this.controller=null;if(callbacks.onComplete) callbacks.onComplete(accumulatedText, data);return accumulatedText;default:return accumulatedText;}}handleStreamingError(error){if(error.name==='AbortError'){console.log('Request was aborted by user');}else{console.error('Error during streaming:', error);}}abortRequest(){if(this.controller){this.controller.abort();this.controller=null;}}}
How does the chat client work?
Creates a chat session (/chat/conversations).
Sends prompts (/chat/{chatId}).
Reads the stream and invokes callbacks: onStart, onProgress, onComplete.
Supports cancelling through abortRequest().
Define the AIPrompt component and enable the built-in SpeechToTextButton and TextArea components through the SpeechToText() and PromptTextArea() configurations.
@addTagHelper*, Kendo.Mvc<kendo-aipromptname="aiprompt"active-view="0"><speech-to-textintegration-mode="webSpeech"lang="en-US"continuous="false"interim-results="true"max-alternatives="1"/><prompt-text-arearows="3"resize="TextAreaResize.Auto"placeholder="Enter your prompt here..."fill-mode="outline"rounded="Rounded.Medium"max-length="1000"></prompt-text-area><aiprompt-views><aiprompt-viewtype="ViewType.Prompt"></aiprompt-view><aiprompt-viewtype="ViewType.Output"></aiprompt-view></aiprompt-views></kendo-aiprompt>
Handle the following AIPrompt client events:
PromptRequest event—Fires when the user clicks the Generate or Retry buttons. Within the event handler, get the submitted text (e.prompt) and switch to the Output view. Start the asynchronous call to the chat client. Provide the following callbacks:
PromptRequestCancel event—Triggers when the user clicks Stop during streaming (the prompt request is canceled). Abort the in‑flight request by calling the apiClient.abortRequest(), so the streaming logic calls the stopStreaming() method of the AIPrompt and updates the output card.
<script src="~/ai-chat-service.js"></script><script>const apiClient =newAIChatClient({apiBaseUrl:'https://',// for example, "https://demos.telerik.com/service/v2/ai".defaultHeaders:{'Content-Type':'application/json'},aiId: kendo.guid()});asyncfunctiononPromptRequest(ev){const aiPromptInstance =this;if(ev.prompt&& ev.prompt.trim()){const promptText = ev.prompt.trim();const currentOutputId = kendo.guid();const isRetry = ev.isRetry||false;// Set active view to output
aiPromptInstance.activeView("output");try{// Handle the streaming response using the API client.const finalText =await apiClient.sendMessage(promptText,{onStart:(data)=>{
aiPromptInstance.startStreaming();},onProgress:(accumulatedText, data)=>{
aiPromptInstance.updatePromptOutputContent(accumulatedText, currentOutputId);},onComplete:(finalText, data)=>{
aiPromptInstance.stopStreaming();}});}catch(error){console.error("Error in prompt request:", error);const errorMessage = error.name==='AbortError'?"Request was cancelled.":"An error occurred while generating the response.";
aiPromptInstance.updatePromptOutputContent(errorMessage);
aiPromptInstance.stopStreaming();}}else{console.log("Prompt is empty, not sending request.");}}functiononPromptRequestCancel(e){
apiClient.abortRequest();// Abort the current request.}</script>