diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 98144b04e..efb39fad4 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.65.0" + ".": "4.66.0" } diff --git a/.stats.yml b/.stats.yml index 0998368a4..68789976b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 68 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-17ddd746c775ca4d4fbe64e5621ac30756ef09c061ff6313190b6ec162222d4c.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-71e58a77027c67e003fdd1b1ac8ac11557d8bfabc7666d1a827c6b1ca8ab98b5.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index d05b606e7..61e398258 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 4.66.0 (2024-09-27) + +Full Changelog: [v4.65.0...v4.66.0](https://github.com/openai/openai-node/compare/v4.65.0...v4.66.0) + +### Features + +* **client:** add request_id to `.withResponse()` ([#1095](https://github.com/openai/openai-node/issues/1095)) ([2d0f565](https://github.com/openai/openai-node/commit/2d0f565f124a8862bc24214cc3ddce9db0ba75bc)) + + +### Bug Fixes + +* **audio:** correct types for transcriptions / translations ([#1104](https://github.com/openai/openai-node/issues/1104)) ([96e86c2](https://github.com/openai/openai-node/commit/96e86c214ba79d50035b61e5daa3489f082512c4)) +* **client:** correct types for transcriptions / translations ([#1105](https://github.com/openai/openai-node/issues/1105)) ([fa16ebb](https://github.com/openai/openai-node/commit/fa16ebbb314ebc7c274d27f0148d248edf48e055)) + ## 4.65.0 (2024-09-26) Full Changelog: [v4.64.0...v4.65.0](https://github.com/openai/openai-node/compare/v4.64.0...v4.65.0) diff --git a/README.md b/README.md index 7bcb0dcda..1058dce4c 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ You can import in Deno via: ```ts -import OpenAI from 'https://deno.land/x/openai@v4.65.0/mod.ts'; +import OpenAI from 'https://deno.land/x/openai@v4.66.0/mod.ts'; ``` diff --git a/api.md b/api.md index 73ac38068..71027acfd 100644 --- a/api.md +++ b/api.md @@ -115,20 +115,26 @@ Types: Types: - Transcription +- TranscriptionSegment +- TranscriptionVerbose +- TranscriptionWord +- TranscriptionCreateResponse Methods: -- client.audio.transcriptions.create({ ...params }) -> Transcription +- client.audio.transcriptions.create({ ...params }) -> TranscriptionCreateResponse ## Translations Types: - Translation +- TranslationVerbose +- TranslationCreateResponse Methods: -- client.audio.translations.create({ ...params }) -> Translation +- client.audio.translations.create({ ...params }) -> TranslationCreateResponse ## Speech diff --git a/package.json b/package.json index 03825be64..b8cdcb658 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openai", - "version": "4.65.0", + "version": "4.66.0", "description": "The official TypeScript library for the OpenAI API", "author": "OpenAI ", "types": "dist/index.d.ts", diff --git a/scripts/build-deno b/scripts/build-deno index cbedabbb5..04f414a32 100755 --- a/scripts/build-deno +++ b/scripts/build-deno @@ -16,7 +16,7 @@ This is a build produced from https://github.com/openai/openai-node – please g Usage: \`\`\`ts -import OpenAI from "https://deno.land/x/openai@v4.65.0/mod.ts"; +import OpenAI from "https://deno.land/x/openai@v4.66.0/mod.ts"; const client = new OpenAI(); \`\`\` diff --git a/src/core.ts b/src/core.ts index f0619c3d9..c104b61d1 100644 --- a/src/core.ts +++ b/src/core.ts @@ -138,8 +138,11 @@ export class APIPromise extends Promise> { asResponse(): Promise { return this.responsePromise.then((p) => p.response); } + /** - * Gets the parsed response data and the raw `Response` instance. + * Gets the parsed response data, the raw `Response` instance and the ID of the request, + * returned via the X-Request-ID header which is useful for debugging requests and reporting + * issues to OpenAI. * * If you just want to get the raw `Response` instance without parsing it, * you can use {@link asResponse()}. @@ -151,9 +154,9 @@ export class APIPromise extends Promise> { * - `import 'openai/shims/node'` (if you're running on Node) * - `import 'openai/shims/web'` (otherwise) */ - async withResponse(): Promise<{ data: T; response: Response }> { + async withResponse(): Promise<{ data: T; response: Response; request_id: string | null | undefined }> { const [data, response] = await Promise.all([this.parse(), this.asResponse()]); - return { data, response }; + return { data, response, request_id: response.headers.get('x-request-id') }; } private parse(): Promise> { diff --git a/src/resources/audio/audio.ts b/src/resources/audio/audio.ts index a8b35d986..9c2c2b982 100644 --- a/src/resources/audio/audio.ts +++ b/src/resources/audio/audio.ts @@ -25,9 +25,15 @@ export namespace Audio { export import AudioResponseFormat = AudioAPI.AudioResponseFormat; export import Transcriptions = TranscriptionsAPI.Transcriptions; export import Transcription = TranscriptionsAPI.Transcription; + export import TranscriptionSegment = TranscriptionsAPI.TranscriptionSegment; + export import TranscriptionVerbose = TranscriptionsAPI.TranscriptionVerbose; + export import TranscriptionWord = TranscriptionsAPI.TranscriptionWord; + export import TranscriptionCreateResponse = TranscriptionsAPI.TranscriptionCreateResponse; export import TranscriptionCreateParams = TranscriptionsAPI.TranscriptionCreateParams; export import Translations = TranslationsAPI.Translations; export import Translation = TranslationsAPI.Translation; + export import TranslationVerbose = TranslationsAPI.TranslationVerbose; + export import TranslationCreateResponse = TranslationsAPI.TranslationCreateResponse; export import TranslationCreateParams = TranslationsAPI.TranslationCreateParams; export import Speech = SpeechAPI.Speech; export import SpeechModel = SpeechAPI.SpeechModel; diff --git a/src/resources/audio/index.ts b/src/resources/audio/index.ts index e8836470c..952c05b03 100644 --- a/src/resources/audio/index.ts +++ b/src/resources/audio/index.ts @@ -2,5 +2,19 @@ export { AudioModel, AudioResponseFormat, Audio } from './audio'; export { SpeechModel, SpeechCreateParams, Speech } from './speech'; -export { Transcription, TranscriptionCreateParams, Transcriptions } from './transcriptions'; -export { Translation, TranslationCreateParams, Translations } from './translations'; +export { + Transcription, + TranscriptionSegment, + TranscriptionVerbose, + TranscriptionWord, + TranscriptionCreateResponse, + TranscriptionCreateParams, + Transcriptions, +} from './transcriptions'; +export { + Translation, + TranslationVerbose, + TranslationCreateResponse, + TranslationCreateParams, + Translations, +} from './translations'; diff --git a/src/resources/audio/transcriptions.ts b/src/resources/audio/transcriptions.ts index 1ee6921cd..e230bc4a4 100644 --- a/src/resources/audio/transcriptions.ts +++ b/src/resources/audio/transcriptions.ts @@ -9,7 +9,22 @@ export class Transcriptions extends APIResource { /** * Transcribes audio into the input language. */ - create(body: TranscriptionCreateParams, options?: Core.RequestOptions): Core.APIPromise { + create( + body: TranscriptionCreateParams<'json' | undefined>, + options?: Core.RequestOptions, + ): Core.APIPromise; + create( + body: TranscriptionCreateParams<'verbose_json'>, + options?: Core.RequestOptions, + ): Core.APIPromise; + create( + body: TranscriptionCreateParams<'srt' | 'vtt' | 'text'>, + options?: Core.RequestOptions, + ): Core.APIPromise; + create( + body: TranscriptionCreateParams, + options?: Core.RequestOptions, + ): Core.APIPromise { return this._client.post('/audio/transcriptions', Core.multipartFormRequestOptions({ body, ...options })); } } @@ -25,7 +40,118 @@ export interface Transcription { text: string; } -export interface TranscriptionCreateParams { +export interface TranscriptionSegment { + /** + * Unique identifier of the segment. + */ + id: number; + + /** + * Average logprob of the segment. If the value is lower than -1, consider the + * logprobs failed. + */ + avg_logprob: number; + + /** + * Compression ratio of the segment. If the value is greater than 2.4, consider the + * compression failed. + */ + compression_ratio: number; + + /** + * End time of the segment in seconds. + */ + end: number; + + /** + * Probability of no speech in the segment. If the value is higher than 1.0 and the + * `avg_logprob` is below -1, consider this segment silent. + */ + no_speech_prob: number; + + /** + * Seek offset of the segment. + */ + seek: number; + + /** + * Start time of the segment in seconds. + */ + start: number; + + /** + * Temperature parameter used for generating the segment. + */ + temperature: number; + + /** + * Text content of the segment. + */ + text: string; + + /** + * Array of token IDs for the text content. + */ + tokens: Array; +} + +/** + * Represents a verbose json transcription response returned by model, based on the + * provided input. + */ +export interface TranscriptionVerbose { + /** + * The duration of the input audio. + */ + duration: string; + + /** + * The language of the input audio. + */ + language: string; + + /** + * The transcribed text. + */ + text: string; + + /** + * Segments of the transcribed text and their corresponding details. + */ + segments?: Array; + + /** + * Extracted words and their corresponding timestamps. + */ + words?: Array; +} + +export interface TranscriptionWord { + /** + * End time of the word in seconds. + */ + end: number; + + /** + * Start time of the word in seconds. + */ + start: number; + + /** + * The text content of the word. + */ + word: string; +} + +/** + * Represents a transcription response returned by model, based on the provided + * input. + */ +export type TranscriptionCreateResponse = Transcription | TranscriptionVerbose; + +export interface TranscriptionCreateParams< + ResponseFormat extends AudioAPI.AudioResponseFormat | undefined = AudioAPI.AudioResponseFormat | undefined, +> { /** * The audio file object (not file name) to transcribe, in one of these formats: * flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. @@ -57,7 +183,7 @@ export interface TranscriptionCreateParams { * The format of the output, in one of these options: `json`, `text`, `srt`, * `verbose_json`, or `vtt`. */ - response_format?: AudioAPI.AudioResponseFormat; + response_format?: ResponseFormat; /** * The sampling temperature, between 0 and 1. Higher values like 0.8 will make the @@ -80,5 +206,9 @@ export interface TranscriptionCreateParams { export namespace Transcriptions { export import Transcription = TranscriptionsAPI.Transcription; + export import TranscriptionSegment = TranscriptionsAPI.TranscriptionSegment; + export import TranscriptionVerbose = TranscriptionsAPI.TranscriptionVerbose; + export import TranscriptionWord = TranscriptionsAPI.TranscriptionWord; + export import TranscriptionCreateResponse = TranscriptionsAPI.TranscriptionCreateResponse; export import TranscriptionCreateParams = TranscriptionsAPI.TranscriptionCreateParams; } diff --git a/src/resources/audio/translations.ts b/src/resources/audio/translations.ts index 6df718112..819804332 100644 --- a/src/resources/audio/translations.ts +++ b/src/resources/audio/translations.ts @@ -4,12 +4,28 @@ import { APIResource } from '../../resource'; import * as Core from '../../core'; import * as TranslationsAPI from './translations'; import * as AudioAPI from './audio'; +import * as TranscriptionsAPI from './transcriptions'; export class Translations extends APIResource { /** * Translates audio into English. */ - create(body: TranslationCreateParams, options?: Core.RequestOptions): Core.APIPromise { + create( + body: TranslationCreateParams<'json' | undefined>, + options?: Core.RequestOptions, + ): Core.APIPromise; + create( + body: TranslationCreateParams<'verbose_json'>, + options?: Core.RequestOptions, + ): Core.APIPromise; + create( + body: TranslationCreateParams<'text' | 'srt' | 'vtt'>, + options?: Core.RequestOptions, + ): Core.APIPromise; + create( + body: TranslationCreateParams, + options?: Core.RequestOptions, + ): Core.APIPromise { return this._client.post('/audio/translations', Core.multipartFormRequestOptions({ body, ...options })); } } @@ -18,7 +34,33 @@ export interface Translation { text: string; } -export interface TranslationCreateParams { +export interface TranslationVerbose { + /** + * The duration of the input audio. + */ + duration: string; + + /** + * The language of the output translation (always `english`). + */ + language: string; + + /** + * The translated text. + */ + text: string; + + /** + * Segments of the translated text and their corresponding details. + */ + segments?: Array; +} + +export type TranslationCreateResponse = Translation | TranslationVerbose; + +export interface TranslationCreateParams< + ResponseFormat extends AudioAPI.AudioResponseFormat | undefined = AudioAPI.AudioResponseFormat | undefined, +> { /** * The audio file object (not file name) translate, in one of these formats: flac, * mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. @@ -43,7 +85,7 @@ export interface TranslationCreateParams { * The format of the output, in one of these options: `json`, `text`, `srt`, * `verbose_json`, or `vtt`. */ - response_format?: AudioAPI.AudioResponseFormat; + response_format?: ResponseFormat; /** * The sampling temperature, between 0 and 1. Higher values like 0.8 will make the @@ -57,5 +99,7 @@ export interface TranslationCreateParams { export namespace Translations { export import Translation = TranslationsAPI.Translation; + export import TranslationVerbose = TranslationsAPI.TranslationVerbose; + export import TranslationCreateResponse = TranslationsAPI.TranslationCreateResponse; export import TranslationCreateParams = TranslationsAPI.TranslationCreateParams; } diff --git a/src/version.ts b/src/version.ts index db5c3bcf7..3da94762b 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '4.65.0'; // x-release-please-version +export const VERSION = '4.66.0'; // x-release-please-version diff --git a/tests/responses.test.ts b/tests/responses.test.ts index fbd073a79..527763465 100644 --- a/tests/responses.test.ts +++ b/tests/responses.test.ts @@ -41,6 +41,27 @@ describe('request id', () => { compareType>>, Array<{ foo: string }>>(true); }); + test('withResponse', async () => { + const client = new OpenAI({ + apiKey: 'dummy', + fetch: async () => + new Response(JSON.stringify({ id: 'bar' }), { + headers: { 'x-request-id': 'req_id_xxx', 'content-type': 'application/json' }, + }), + }); + + const { + data: completion, + response, + request_id, + } = await client.chat.completions.create({ messages: [], model: 'gpt-4' }).withResponse(); + + expect(request_id).toBe('req_id_xxx'); + expect(response.headers.get('x-request-id')).toBe('req_id_xxx'); + expect(completion.id).toBe('bar'); + expect(JSON.stringify(completion)).toBe('{"id":"bar"}'); + }); + test('object response', async () => { const client = new OpenAI({ apiKey: 'dummy',