ResponsesParser.js 5.5 KB

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