You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

sessionConnectionChat.js 7.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. const createConnectionSessionChat = () => {
  2. const outputErrorTemplate = $("#outputErrorTemplate").html();
  3. const outputInfoTemplate = $("#outputInfoTemplate").html();
  4. const outputUserTemplate = $("#outputUserTemplate").html();
  5. const outputBotTemplate = $("#outputBotTemplate").html();
  6. const signatureTemplate = $("#signatureTemplate").html();
  7. let inferenceSession;
  8. const connection = new signalR.HubConnectionBuilder().withUrl("/SessionConnectionHub").build();
  9. const scrollContainer = $("#scroll-container");
  10. const outputContainer = $("#output-container");
  11. const chatInput = $("#input");
  12. const onStatus = (connection, status) => {
  13. if (status == Enums.SessionConnectionStatus.Connected) {
  14. $("#socket").text("Connected").addClass("text-success");
  15. }
  16. else if (status == Enums.SessionConnectionStatus.Loaded) {
  17. loaderHide();
  18. enableControls();
  19. $("#load").hide();
  20. $("#unload").show();
  21. onInfo(`New model session successfully started`)
  22. }
  23. }
  24. const onError = (error) => {
  25. enableControls();
  26. outputContainer.append(Mustache.render(outputErrorTemplate, { text: error, date: getDateTime() }));
  27. }
  28. const onInfo = (message) => {
  29. outputContainer.append(Mustache.render(outputInfoTemplate, { text: message, date: getDateTime() }));
  30. }
  31. let responseContent;
  32. let responseContainer;
  33. let responseFirstToken;
  34. const onResponse = (response) => {
  35. if (!response)
  36. return;
  37. if (response.tokenType == Enums.TokenType.Begin) {
  38. let uniqueId = randomString();
  39. outputContainer.append(Mustache.render(outputBotTemplate, { uniqueId: uniqueId, ...response }));
  40. responseContainer = $(`#${uniqueId}`);
  41. responseContent = responseContainer.find(".content");
  42. responseFirstToken = true;
  43. scrollToBottom(true);
  44. return;
  45. }
  46. if (response.tokenType == Enums.TokenType.End || response.tokenType == Enums.TokenType.Cancel) {
  47. enableControls();
  48. responseContainer.find(".signature").append(Mustache.render(signatureTemplate, response));
  49. scrollToBottom();
  50. }
  51. else {
  52. if (responseFirstToken) {
  53. responseContent.empty();
  54. responseFirstToken = false;
  55. responseContainer.find(".date").append(getDateTime());
  56. }
  57. responseContent.append(response.content);
  58. scrollToBottom();
  59. }
  60. }
  61. const sendPrompt = async () => {
  62. const text = chatInput.val();
  63. if (text) {
  64. chatInput.val(null);
  65. disableControls();
  66. outputContainer.append(Mustache.render(outputUserTemplate, { text: text, date: getDateTime() }));
  67. inferenceSession = await connection
  68. .stream("SendPrompt", text, serializeFormToJson('SessionParameters'))
  69. .subscribe({
  70. next: onResponse,
  71. complete: onResponse,
  72. error: onError,
  73. });
  74. scrollToBottom(true);
  75. }
  76. }
  77. const cancelPrompt = async () => {
  78. if (inferenceSession)
  79. inferenceSession.dispose();
  80. }
  81. const loadModel = async () => {
  82. const sessionParams = serializeFormToJson('SessionParameters');
  83. loaderShow();
  84. disableControls();
  85. disablePromptControls();
  86. $("#load").attr("disabled", "disabled");
  87. // TODO: Split parameters sets
  88. await connection.invoke('LoadModel', sessionParams, sessionParams);
  89. }
  90. const unloadModel = async () => {
  91. await cancelPrompt();
  92. disableControls();
  93. enablePromptControls();
  94. $("#load").removeAttr("disabled");
  95. }
  96. const serializeFormToJson = (form) => {
  97. const formDataJson = {};
  98. const formData = new FormData(document.getElementById(form));
  99. formData.forEach((value, key) => {
  100. if (key.includes("."))
  101. key = key.split(".")[1];
  102. // Convert number strings to numbers
  103. if (!isNaN(value) && value.trim() !== "") {
  104. formDataJson[key] = parseFloat(value);
  105. }
  106. // Convert boolean strings to booleans
  107. else if (value === "true" || value === "false") {
  108. formDataJson[key] = (value === "true");
  109. }
  110. else {
  111. formDataJson[key] = value;
  112. }
  113. });
  114. return formDataJson;
  115. }
  116. const enableControls = () => {
  117. $(".input-control").removeAttr("disabled");
  118. }
  119. const disableControls = () => {
  120. $(".input-control").attr("disabled", "disabled");
  121. }
  122. const enablePromptControls = () => {
  123. $("#load").show();
  124. $("#unload").hide();
  125. $(".prompt-control").removeAttr("disabled");
  126. activatePromptTab();
  127. }
  128. const disablePromptControls = () => {
  129. $(".prompt-control").attr("disabled", "disabled");
  130. activateParamsTab();
  131. }
  132. const clearOutput = () => {
  133. outputContainer.empty();
  134. }
  135. const updatePrompt = () => {
  136. const customPrompt = $("#PromptText");
  137. const selection = $("option:selected", "#Prompt");
  138. const selectedValue = selection.data("prompt");
  139. customPrompt.text(selectedValue);
  140. }
  141. const getDateTime = () => {
  142. const dateTime = new Date();
  143. return dateTime.toLocaleString();
  144. }
  145. const randomString = () => {
  146. return Math.random().toString(36).slice(2);
  147. }
  148. const scrollToBottom = (force) => {
  149. const scrollTop = scrollContainer.scrollTop();
  150. const scrollHeight = scrollContainer[0].scrollHeight;
  151. if (force) {
  152. scrollContainer.scrollTop(scrollContainer[0].scrollHeight);
  153. return;
  154. }
  155. if (scrollTop + 70 >= scrollHeight - scrollContainer.innerHeight()) {
  156. scrollContainer.scrollTop(scrollContainer[0].scrollHeight)
  157. }
  158. }
  159. const activatePromptTab = () => {
  160. $("#nav-prompt-tab").trigger("click");
  161. }
  162. const activateParamsTab = () => {
  163. $("#nav-params-tab").trigger("click");
  164. }
  165. const loaderShow = () => {
  166. $(".spinner").show();
  167. }
  168. const loaderHide = () => {
  169. $(".spinner").hide();
  170. }
  171. // Map UI functions
  172. $("#load").on("click", loadModel);
  173. $("#unload").on("click", unloadModel);
  174. $("#send").on("click", sendPrompt);
  175. $("#clear").on("click", clearOutput);
  176. $("#cancel").on("click", cancelPrompt);
  177. $("#Prompt").on("change", updatePrompt);
  178. chatInput.on('keydown', function (event) {
  179. if (event.key === 'Enter' && !event.shiftKey) {
  180. event.preventDefault();
  181. sendPrompt();
  182. }
  183. });
  184. $(".slider").on("input", function (e) {
  185. const slider = $(this);
  186. slider.next().text(slider.val());
  187. }).trigger("input");
  188. // Map signalr functions
  189. connection.on("OnStatus", onStatus);
  190. connection.on("OnError", onError);
  191. connection.on("OnResponse", onResponse);
  192. connection.start();
  193. }