completion.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. const paramDefaults = {
  2. stream: true,
  3. n_predict: 500,
  4. temperature: 0.2,
  5. stop: ["</s>"]
  6. };
  7. /**
  8. * This function completes the input text using a llama dictionary.
  9. * @param {object} params - The parameters for the completion request.
  10. * @param {object} controller - an instance of AbortController if you need one, or null.
  11. * @param {function} callback - The callback function to call when the completion is done.
  12. * @returns {string} the completed text as a string. Ideally ignored, and you get at it via the callback.
  13. */
  14. export const llamaComplete = async (params, controller, callback) => {
  15. if (!controller) {
  16. controller = new AbortController();
  17. }
  18. const completionParams = { ...paramDefaults, ...params };
  19. // we use fetch directly here becasue the built in fetchEventSource does not support POST
  20. const response = await fetch("/completion", {
  21. method: 'POST',
  22. body: JSON.stringify(completionParams),
  23. headers: {
  24. 'Connection': 'keep-alive',
  25. 'Content-Type': 'application/json',
  26. 'Accept': 'text/event-stream'
  27. },
  28. signal: controller.signal,
  29. });
  30. const reader = response.body.getReader();
  31. const decoder = new TextDecoder();
  32. let content = "";
  33. try {
  34. let cont = true;
  35. while (cont) {
  36. const result = await reader.read();
  37. if (result.done) {
  38. break;
  39. }
  40. // sse answers in the form multiple lines of: value\n with data always present as a key. in our case we
  41. // mainly care about the data: key here, which we expect as json
  42. const text = decoder.decode(result.value);
  43. // parse all sse events and add them to result
  44. const regex = /^(\S+):\s(.*)$/gm;
  45. for (const match of text.matchAll(regex)) {
  46. result[match[1]] = match[2]
  47. }
  48. // since we know this is llama.cpp, let's just decode the json in data
  49. result.data = JSON.parse(result.data);
  50. content += result.data.content;
  51. // callack
  52. if (callback) {
  53. cont = callback(result) != false;
  54. }
  55. // if we got a stop token from server, we will break here
  56. if (result.data.stop) {
  57. break;
  58. }
  59. }
  60. } catch (e) {
  61. console.error("llama error: ", e);
  62. throw e;
  63. }
  64. finally {
  65. controller.abort();
  66. }
  67. return content;
  68. }