pipeline.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import { BasePromptTemplate } from "./base.js";
  2. import { ChatPromptTemplate } from "./chat.js";
  3. /**
  4. * Class that handles a sequence of prompts, each of which may require
  5. * different input variables. Includes methods for formatting these
  6. * prompts, extracting required input values, and handling partial
  7. * prompts.
  8. * @example
  9. * ```typescript
  10. * const composedPrompt = new PipelinePromptTemplate({
  11. * pipelinePrompts: [
  12. * {
  13. * name: "introduction",
  14. * prompt: PromptTemplate.fromTemplate(`You are impersonating {person}.`),
  15. * },
  16. * {
  17. * name: "example",
  18. * prompt: PromptTemplate.fromTemplate(
  19. * `Here's an example of an interaction:
  20. * Q: {example_q}
  21. * A: {example_a}`,
  22. * ),
  23. * },
  24. * {
  25. * name: "start",
  26. * prompt: PromptTemplate.fromTemplate(
  27. * `Now, do this for real!
  28. * Q: {input}
  29. * A:`,
  30. * ),
  31. * },
  32. * ],
  33. * finalPrompt: PromptTemplate.fromTemplate(
  34. * `{introduction}
  35. * {example}
  36. * {start}`,
  37. * ),
  38. * });
  39. *
  40. * const formattedPrompt = await composedPrompt.format({
  41. * person: "Elon Musk",
  42. * example_q: `What's your favorite car?`,
  43. * example_a: "Tesla",
  44. * input: `What's your favorite social media site?`,
  45. * });
  46. * ```
  47. */
  48. export class PipelinePromptTemplate extends BasePromptTemplate {
  49. static lc_name() {
  50. return "PipelinePromptTemplate";
  51. }
  52. constructor(input) {
  53. super({ ...input, inputVariables: [] });
  54. Object.defineProperty(this, "pipelinePrompts", {
  55. enumerable: true,
  56. configurable: true,
  57. writable: true,
  58. value: void 0
  59. });
  60. Object.defineProperty(this, "finalPrompt", {
  61. enumerable: true,
  62. configurable: true,
  63. writable: true,
  64. value: void 0
  65. });
  66. this.pipelinePrompts = input.pipelinePrompts;
  67. this.finalPrompt = input.finalPrompt;
  68. this.inputVariables = this.computeInputValues();
  69. }
  70. /**
  71. * Computes the input values required by the pipeline prompts.
  72. * @returns Array of input values required by the pipeline prompts.
  73. */
  74. computeInputValues() {
  75. const intermediateValues = this.pipelinePrompts.map((pipelinePrompt) => pipelinePrompt.name);
  76. const inputValues = this.pipelinePrompts
  77. .map((pipelinePrompt) => pipelinePrompt.prompt.inputVariables.filter((inputValue) => !intermediateValues.includes(inputValue)))
  78. .flat();
  79. return [...new Set(inputValues)];
  80. }
  81. static extractRequiredInputValues(allValues, requiredValueNames) {
  82. return requiredValueNames.reduce((requiredValues, valueName) => {
  83. // eslint-disable-next-line no-param-reassign
  84. requiredValues[valueName] = allValues[valueName];
  85. return requiredValues;
  86. }, {});
  87. }
  88. /**
  89. * Formats the pipeline prompts based on the provided input values.
  90. * @param values Input values to format the pipeline prompts.
  91. * @returns Promise that resolves with the formatted input values.
  92. */
  93. async formatPipelinePrompts(values) {
  94. const allValues = await this.mergePartialAndUserVariables(values);
  95. for (const { name: pipelinePromptName, prompt: pipelinePrompt } of this
  96. .pipelinePrompts) {
  97. const pipelinePromptInputValues = PipelinePromptTemplate.extractRequiredInputValues(allValues, pipelinePrompt.inputVariables);
  98. // eslint-disable-next-line no-instanceof/no-instanceof
  99. if (pipelinePrompt instanceof ChatPromptTemplate) {
  100. allValues[pipelinePromptName] = await pipelinePrompt.formatMessages(pipelinePromptInputValues);
  101. }
  102. else {
  103. allValues[pipelinePromptName] = await pipelinePrompt.format(pipelinePromptInputValues);
  104. }
  105. }
  106. return PipelinePromptTemplate.extractRequiredInputValues(allValues, this.finalPrompt.inputVariables);
  107. }
  108. /**
  109. * Formats the final prompt value based on the provided input values.
  110. * @param values Input values to format the final prompt value.
  111. * @returns Promise that resolves with the formatted final prompt value.
  112. */
  113. async formatPromptValue(values) {
  114. return this.finalPrompt.formatPromptValue(await this.formatPipelinePrompts(values));
  115. }
  116. async format(values) {
  117. return this.finalPrompt.format(await this.formatPipelinePrompts(values));
  118. }
  119. /**
  120. * Handles partial prompts, which are prompts that have been partially
  121. * filled with input values.
  122. * @param values Partial input values.
  123. * @returns Promise that resolves with a new PipelinePromptTemplate instance with updated input variables.
  124. */
  125. async partial(values) {
  126. const promptDict = { ...this };
  127. promptDict.inputVariables = this.inputVariables.filter((iv) => !(iv in values));
  128. promptDict.partialVariables = {
  129. ...(this.partialVariables ?? {}),
  130. ...values,
  131. };
  132. return new PipelinePromptTemplate(promptDict);
  133. }
  134. serialize() {
  135. throw new Error("Not implemented.");
  136. }
  137. _getPromptType() {
  138. return "pipeline";
  139. }
  140. }