prompt.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Default generic "any" values are for backwards compatibility.
  2. // Replace with "string" when we are comfortable with a breaking change.
  3. import { BaseStringPromptTemplate } from "./string.js";
  4. import { checkValidTemplate, parseTemplate, renderTemplate, } from "./template.js";
  5. /**
  6. * Schema to represent a basic prompt for an LLM.
  7. * @augments BasePromptTemplate
  8. * @augments PromptTemplateInput
  9. *
  10. * @example
  11. * ```ts
  12. * import { PromptTemplate } from "langchain/prompts";
  13. *
  14. * const prompt = new PromptTemplate({
  15. * inputVariables: ["foo"],
  16. * template: "Say {foo}",
  17. * });
  18. * ```
  19. */
  20. export class PromptTemplate extends BaseStringPromptTemplate {
  21. static lc_name() {
  22. return "PromptTemplate";
  23. }
  24. constructor(input) {
  25. super(input);
  26. Object.defineProperty(this, "template", {
  27. enumerable: true,
  28. configurable: true,
  29. writable: true,
  30. value: void 0
  31. });
  32. Object.defineProperty(this, "templateFormat", {
  33. enumerable: true,
  34. configurable: true,
  35. writable: true,
  36. value: "f-string"
  37. });
  38. Object.defineProperty(this, "validateTemplate", {
  39. enumerable: true,
  40. configurable: true,
  41. writable: true,
  42. value: true
  43. });
  44. /**
  45. * Additional fields which should be included inside
  46. * the message content array if using a complex message
  47. * content.
  48. */
  49. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  50. Object.defineProperty(this, "additionalContentFields", {
  51. enumerable: true,
  52. configurable: true,
  53. writable: true,
  54. value: void 0
  55. });
  56. // If input is mustache and validateTemplate is not defined, set it to false
  57. if (input.templateFormat === "mustache" &&
  58. input.validateTemplate === undefined) {
  59. this.validateTemplate = false;
  60. }
  61. Object.assign(this, input);
  62. if (this.validateTemplate) {
  63. if (this.templateFormat === "mustache") {
  64. throw new Error("Mustache templates cannot be validated.");
  65. }
  66. let totalInputVariables = this.inputVariables;
  67. if (this.partialVariables) {
  68. totalInputVariables = totalInputVariables.concat(Object.keys(this.partialVariables));
  69. }
  70. checkValidTemplate(this.template, this.templateFormat, totalInputVariables);
  71. }
  72. }
  73. _getPromptType() {
  74. return "prompt";
  75. }
  76. /**
  77. * Formats the prompt template with the provided values.
  78. * @param values The values to be used to format the prompt template.
  79. * @returns A promise that resolves to a string which is the formatted prompt.
  80. */
  81. async format(values) {
  82. const allValues = await this.mergePartialAndUserVariables(values);
  83. return renderTemplate(this.template, this.templateFormat, allValues);
  84. }
  85. /**
  86. * Take examples in list format with prefix and suffix to create a prompt.
  87. *
  88. * Intended to be used a a way to dynamically create a prompt from examples.
  89. *
  90. * @param examples - List of examples to use in the prompt.
  91. * @param suffix - String to go after the list of examples. Should generally set up the user's input.
  92. * @param inputVariables - A list of variable names the final prompt template will expect
  93. * @param exampleSeparator - The separator to use in between examples
  94. * @param prefix - String that should go before any examples. Generally includes examples.
  95. *
  96. * @returns The final prompt template generated.
  97. */
  98. static fromExamples(examples, suffix, inputVariables, exampleSeparator = "\n\n", prefix = "") {
  99. const template = [prefix, ...examples, suffix].join(exampleSeparator);
  100. return new PromptTemplate({
  101. inputVariables,
  102. template,
  103. });
  104. }
  105. static fromTemplate(template, options) {
  106. const { templateFormat = "f-string", ...rest } = options ?? {};
  107. const names = new Set();
  108. parseTemplate(template, templateFormat).forEach((node) => {
  109. if (node.type === "variable") {
  110. names.add(node.name);
  111. }
  112. });
  113. return new PromptTemplate({
  114. // Rely on extracted types
  115. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  116. inputVariables: [...names],
  117. templateFormat,
  118. template,
  119. ...rest,
  120. });
  121. }
  122. /**
  123. * Partially applies values to the prompt template.
  124. * @param values The values to be partially applied to the prompt template.
  125. * @returns A new instance of PromptTemplate with the partially applied values.
  126. */
  127. async partial(values) {
  128. const newInputVariables = this.inputVariables.filter((iv) => !(iv in values));
  129. const newPartialVariables = {
  130. ...(this.partialVariables ?? {}),
  131. ...values,
  132. };
  133. const promptDict = {
  134. ...this,
  135. inputVariables: newInputVariables,
  136. partialVariables: newPartialVariables,
  137. };
  138. return new PromptTemplate(promptDict);
  139. }
  140. serialize() {
  141. if (this.outputParser !== undefined) {
  142. throw new Error("Cannot serialize a prompt template with an output parser");
  143. }
  144. return {
  145. _type: this._getPromptType(),
  146. input_variables: this.inputVariables,
  147. template: this.template,
  148. template_format: this.templateFormat,
  149. };
  150. }
  151. static async deserialize(data) {
  152. if (!data.template) {
  153. throw new Error("Prompt template must have a template");
  154. }
  155. const res = new PromptTemplate({
  156. inputVariables: data.input_variables,
  157. template: data.template,
  158. templateFormat: data.template_format,
  159. });
  160. return res;
  161. }
  162. }