ResponsesParser.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.addOutputText = exports.validateInputTools = exports.shouldParseToolCall = exports.isAutoParsableTool = exports.makeParseableResponseTool = exports.hasAutoParseableInput = exports.parseResponse = exports.maybeParseResponse = void 0;
  4. const error_1 = require("../error.js");
  5. const parser_1 = require("../lib/parser.js");
  6. function maybeParseResponse(response, params) {
  7. if (!params || !hasAutoParseableInput(params)) {
  8. return {
  9. ...response,
  10. output_parsed: null,
  11. output: response.output.map((item) => {
  12. if (item.type === 'function_call') {
  13. return {
  14. ...item,
  15. parsed_arguments: null,
  16. };
  17. }
  18. if (item.type === 'message') {
  19. return {
  20. ...item,
  21. content: item.content.map((content) => ({
  22. ...content,
  23. parsed: null,
  24. })),
  25. };
  26. }
  27. else {
  28. return item;
  29. }
  30. }),
  31. };
  32. }
  33. return parseResponse(response, params);
  34. }
  35. exports.maybeParseResponse = maybeParseResponse;
  36. function parseResponse(response, params) {
  37. const output = response.output.map((item) => {
  38. if (item.type === 'function_call') {
  39. return {
  40. ...item,
  41. parsed_arguments: parseToolCall(params, item),
  42. };
  43. }
  44. if (item.type === 'message') {
  45. const content = item.content.map((content) => {
  46. if (content.type === 'output_text') {
  47. return {
  48. ...content,
  49. parsed: parseTextFormat(params, content.text),
  50. };
  51. }
  52. return content;
  53. });
  54. return {
  55. ...item,
  56. content,
  57. };
  58. }
  59. return item;
  60. });
  61. const parsed = Object.assign({}, response, { output });
  62. if (!Object.getOwnPropertyDescriptor(response, 'output_text')) {
  63. addOutputText(parsed);
  64. }
  65. Object.defineProperty(parsed, 'output_parsed', {
  66. enumerable: true,
  67. get() {
  68. for (const output of parsed.output) {
  69. if (output.type !== 'message') {
  70. continue;
  71. }
  72. for (const content of output.content) {
  73. if (content.type === 'output_text' && content.parsed !== null) {
  74. return content.parsed;
  75. }
  76. }
  77. }
  78. return null;
  79. },
  80. });
  81. return parsed;
  82. }
  83. exports.parseResponse = parseResponse;
  84. function parseTextFormat(params, content) {
  85. if (params.text?.format?.type !== 'json_schema') {
  86. return null;
  87. }
  88. if ('$parseRaw' in params.text?.format) {
  89. const text_format = params.text?.format;
  90. return text_format.$parseRaw(content);
  91. }
  92. return JSON.parse(content);
  93. }
  94. function hasAutoParseableInput(params) {
  95. if ((0, parser_1.isAutoParsableResponseFormat)(params.text?.format)) {
  96. return true;
  97. }
  98. return false;
  99. }
  100. exports.hasAutoParseableInput = hasAutoParseableInput;
  101. function makeParseableResponseTool(tool, { parser, callback, }) {
  102. const obj = { ...tool };
  103. Object.defineProperties(obj, {
  104. $brand: {
  105. value: 'auto-parseable-tool',
  106. enumerable: false,
  107. },
  108. $parseRaw: {
  109. value: parser,
  110. enumerable: false,
  111. },
  112. $callback: {
  113. value: callback,
  114. enumerable: false,
  115. },
  116. });
  117. return obj;
  118. }
  119. exports.makeParseableResponseTool = makeParseableResponseTool;
  120. function isAutoParsableTool(tool) {
  121. return tool?.['$brand'] === 'auto-parseable-tool';
  122. }
  123. exports.isAutoParsableTool = isAutoParsableTool;
  124. function getInputToolByName(input_tools, name) {
  125. return input_tools.find((tool) => tool.type === 'function' && tool.name === name);
  126. }
  127. function parseToolCall(params, toolCall) {
  128. const inputTool = getInputToolByName(params.tools ?? [], toolCall.name);
  129. return {
  130. ...toolCall,
  131. ...toolCall,
  132. parsed_arguments: isAutoParsableTool(inputTool) ? inputTool.$parseRaw(toolCall.arguments)
  133. : inputTool?.strict ? JSON.parse(toolCall.arguments)
  134. : null,
  135. };
  136. }
  137. function shouldParseToolCall(params, toolCall) {
  138. if (!params) {
  139. return false;
  140. }
  141. const inputTool = getInputToolByName(params.tools ?? [], toolCall.name);
  142. return isAutoParsableTool(inputTool) || inputTool?.strict || false;
  143. }
  144. exports.shouldParseToolCall = shouldParseToolCall;
  145. function validateInputTools(tools) {
  146. for (const tool of tools ?? []) {
  147. if (tool.type !== 'function') {
  148. throw new error_1.OpenAIError(`Currently only \`function\` tool types support auto-parsing; Received \`${tool.type}\``);
  149. }
  150. if (tool.function.strict !== true) {
  151. throw new error_1.OpenAIError(`The \`${tool.function.name}\` tool is not marked with \`strict: true\`. Only strict function tools can be auto-parsed`);
  152. }
  153. }
  154. }
  155. exports.validateInputTools = validateInputTools;
  156. function addOutputText(rsp) {
  157. const texts = [];
  158. for (const output of rsp.output) {
  159. if (output.type !== 'message') {
  160. continue;
  161. }
  162. for (const content of output.content) {
  163. if (content.type === 'output_text') {
  164. texts.push(content.text);
  165. }
  166. }
  167. }
  168. rsp.output_text = texts.join('');
  169. }
  170. exports.addOutputText = addOutputText;
  171. //# sourceMappingURL=ResponsesParser.js.map