diff --git a/CHANGELOG.md b/CHANGELOG.md index 337b37d..7038dfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [4.37.0] + +- Remove LeMUR support — the LeMUR API has been shut down and its endpoints answer 404. `client.lemur`, `LemurService`, and all Lemur request/response types are removed. For LeMUR-style workloads, use the LLM Gateway (`llm-gateway.assemblyai.com/v1/chat/completions`); it takes transcript text rather than `transcript_ids` + ## [4.36.8] - Fix an uncaught exception that killed the process when a still-connecting socket was torn down — on a connection-attempt timeout or a `close()` racing `connect()`, `ws` emits `error` on the next tick after the SDK had removed all listeners. Teardown now keeps an error sink attached, and a timed-out `connect()` rejects into the caller's `catch` instead of crashing first diff --git a/package.json b/package.json index e5aef75..ca31ca1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "assemblyai", - "version": "4.36.8", - "description": "The AssemblyAI JavaScript SDK provides an easy-to-use interface for interacting with the AssemblyAI API, which supports async and real-time transcription, as well as the latest LeMUR models.", + "version": "4.37.0", + "description": "The AssemblyAI JavaScript SDK provides an easy-to-use interface for interacting with the AssemblyAI API, which supports async and real-time transcription.", "engines": { "node": ">=18" }, diff --git a/src/services/index.ts b/src/services/index.ts index d92bde1..ddbac78 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -1,7 +1,6 @@ import { BaseServiceParams } from ".."; import { SyncTranscriber } from "./sync"; import { SyncTranscriptError } from "../utils/errors"; -import { LemurService } from "./lemur"; import { RealtimeTranscriber, RealtimeTranscriberFactory, @@ -38,11 +37,6 @@ class AssemblyAI { */ public transcripts: TranscriptService; - /** - * The LeMUR service. - */ - public lemur: LemurService; - /** * The realtime service. */ @@ -70,7 +64,6 @@ class AssemblyAI { this.files = new FileService(params); this.transcripts = new TranscriptService(params, this.files); - this.lemur = new LemurService(params); this.realtime = new RealtimeTranscriberFactory(params); this.streaming = new StreamingTranscriberFactory({ @@ -93,7 +86,6 @@ export { AssemblyAI, SyncTranscriber, SyncTranscriptError, - LemurService, RealtimeTranscriberFactory, RealtimeTranscriber, RealtimeServiceFactory, diff --git a/src/services/lemur/index.ts b/src/services/lemur/index.ts deleted file mode 100644 index 6dad8da..0000000 --- a/src/services/lemur/index.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { - LemurSummaryParams, - LemurActionItemsParams, - LemurQuestionAnswerParams, - LemurTaskParams, - LemurSummaryResponse, - LemurQuestionAnswerResponse, - LemurActionItemsResponse, - LemurTaskResponse, - PurgeLemurRequestDataResponse, - LemurResponse, -} from "../.."; -import { BaseService } from "../base"; - -export class LemurService extends BaseService { - summary( - params: LemurSummaryParams, - signal?: AbortSignal, - ): Promise { - return this.fetchJson("/lemur/v3/generate/summary", { - method: "POST", - body: JSON.stringify(params), - signal, - }); - } - - questionAnswer( - params: LemurQuestionAnswerParams, - signal?: AbortSignal, - ): Promise { - return this.fetchJson( - "/lemur/v3/generate/question-answer", - { - method: "POST", - body: JSON.stringify(params), - signal, - }, - ); - } - - actionItems( - params: LemurActionItemsParams, - signal?: AbortSignal, - ): Promise { - return this.fetchJson( - "/lemur/v3/generate/action-items", - { - method: "POST", - body: JSON.stringify(params), - signal, - }, - ); - } - - task( - params: LemurTaskParams, - signal?: AbortSignal, - ): Promise { - return this.fetchJson("/lemur/v3/generate/task", { - method: "POST", - body: JSON.stringify(params), - signal, - }); - } - - /** - * Retrieve a LeMUR response that was previously generated. - * @param id - The ID of the LeMUR request you previously made. This would be found in the response of the original request. - * @param signal - Optional AbortSignal to cancel the request - * @returns The LeMUR response. - */ - getResponse( - id: string, - signal?: AbortSignal, - ): Promise; - getResponse(id: string, signal?: AbortSignal): Promise; - getResponse(id: string, signal?: AbortSignal): Promise { - return this.fetchJson(`/lemur/v3/${id}`, { signal }); - } - - /** - * Delete the data for a previously submitted LeMUR request. - * @param id - ID of the LeMUR request - * @param signal - Optional AbortSignal to cancel the request - */ - purgeRequestData( - id: string, - signal?: AbortSignal, - ): Promise { - return this.fetchJson(`/lemur/v3/${id}`, { - method: "DELETE", - signal, - }); - } -} diff --git a/src/types/deprecated.ts b/src/types/deprecated.ts index f561d19..bfa5f90 100644 --- a/src/types/deprecated.ts +++ b/src/types/deprecated.ts @@ -1,11 +1,6 @@ import { FileUploadParams } from "./files"; import { CreateRealtimeTemporaryTokenParams, - LemurActionItemsParams, - LemurBaseParams, - LemurQuestionAnswerParams, - LemurSummaryParams, - LemurTaskParams, ListTranscriptParams, TranscriptOptionalParams, TranscriptParams, @@ -36,31 +31,6 @@ export type SubmitParameters = SubmitParams; */ export type CreateRealtimeTemporaryTokenParameters = CreateRealtimeTemporaryTokenParams; -/** - * @deprecated - * Use`LemurActionItemsParams` instead. - */ -export type LemurActionItemsParameters = LemurActionItemsParams; -/** - * @deprecated - * Use`LemurBaseParams` instead. - */ -export type LemurBaseParameters = LemurBaseParams; -/** - * @deprecated - * Use`LemurQuestionAnswerParams` instead. - */ -export type LemurQuestionAnswerParameters = LemurQuestionAnswerParams; -/** - * @deprecated - * Use`LemurSummaryParams` instead. - */ -export type LemurSummaryParameters = LemurSummaryParams; -/** - * @deprecated - * Use`LemurTaskParams` instead. - */ -export type LemurTaskParameters = LemurTaskParams; /** * @deprecated * Use`ListTranscriptParams` instead. diff --git a/src/types/openapi.generated.ts b/src/types/openapi.generated.ts index 5107e48..ee5cba9 100644 --- a/src/types/openapi.generated.ts +++ b/src/types/openapi.generated.ts @@ -576,443 +576,6 @@ export type Error = { [key: string]: unknown; }; -/** - * @example - * ```js - * { - * "transcript_ids": [ - * "64nygnr62k-405c-4ae8-8a6b-d90b40ff3cce" - * ], - * "context": "This is an interview about wildfires.", - * "answer_format": "Bullet Points", - * "final_model": "anthropic/claude-3-5-sonnet", - * "temperature": 0, - * "max_output_size": 3000 - * } - * ``` - */ -export type LemurActionItemsParams = LemurBaseParams & { - /** - * How you want the action items to be returned. This can be any text. - * Defaults to "Bullet Points". - * - * @defaultValue "Bullet Points - */ - answer_format?: string; -}; - -/** - * @example - * ```js - * { - * "request_id": "5"e1b27c2-691f-4414-8bc5-f14678442f9e", - * "response": "Here are some potential action items based on the transcript:\n\n- Monitor air quality levels in affected areas and issue warnings as needed.\n\n- Advise vulnerable populations like children, the elderly, and those with respiratory conditions to limit time outdoors.\n\n- Have schools cancel outdoor activities when air quality is poor.\n\n- Educate the public on health impacts of smoke inhalation and precautions to take.\n\n- Track progression of smoke plumes using weather and air quality monitoring systems.\n\n- Coordinate cross-regionally to manage smoke exposure as air masses shift.\n\n- Plan for likely increase in such events due to climate change. Expand monitoring and forecasting capabilities.\n\n- Conduct research to better understand health impacts of wildfire smoke and mitigation strategies.\n\n- Develop strategies to prevent and manage wildfires to limit air quality impacts.\n", - * "usage": { - * "input_tokens": 27, - * "output_tokens": 3 - * } - * } - * ``` - */ -export type LemurActionItemsResponse = LemurStringResponse; - -/** - * @example - * ```js - * { - * "transcript_ids": [ - * "85f9b381-e90c-46ed-beca-7d76245d375e", - * "7c3acd18-df4d-4432-88f5-1e89f8827eea" - * ], - * "context": "This is an interview about wildfires.", - * "final_model": "anthropic/claude-3-5-sonnet", - * "temperature": 0, - * "max_output_size": 3000 - * } - * ``` - */ -export type LemurBaseParams = { - /** - * Context to provide the model. This can be a string or a free-form JSON value. - */ - context?: OneOf< - [ - string, - { - [key: string]: unknown; - }, - ] - >; - /** - * The model that is used for the final prompt after compression is performed. - * - * @defaultValue "default - */ - final_model?: LiteralUnion; - /** - * Custom formatted transcript data. Maximum size is the context limit of the selected model, which defaults to 100000". - * Use either transcript_ids or input_text as input into LeMUR. - */ - input_text?: string; - /** - * Max output size in tokens, up to 4000 - * @defaultValue 2000 - */ - max_output_size?: number; - /** - * The temperature to use for the model. - * Higher values result in answers that are more creative, lower values are more conservative. - * Can be any value between 0.0 and 1.0 inclusive. - * - * @defaultValue 0 - */ - temperature?: number; - /** - * A list of completed transcripts with text. Up to a maximum of 100 files or 100 hours, whichever is lower. - * Use either transcript_ids or input_text as input into LeMUR. - */ - transcript_ids?: string[]; -}; - -/** - * @example - * ```js - * { - * "request_id": "5e1b27c2-691f-4414-8bc5-f14678442f9e", - * "usage": { - * "input_tokens": 27, - * "output_tokens": 3 - * } - * } - * ``` - */ - -export type LemurRequestDetails = { - /** - * The endpoint used for the leMUR request - */ - request_endpoint: string; - /** - * The temperature to use for the model. - * Higher values result in answers that are more creative, lower values are more conservative. - * Can be any value between 0.0 and 1.0 inclusive. - * - * @defaultValue 0 - */ - temperature: number; - /** - * The model that was used for the final prompt after compression is performed. - * - * @defaultValue "default" - */ - final_model: LiteralUnion; - /** - * Max output size in tokens, up to 4000 - * @defaultValue 2000 - */ - max_output_size: number; - /** - * The date when the request was created - */ - created_at: Date; - /** - * A list of completed transcripts with text. - * Use either transcript_ids or input_text as input into LeMUR. - */ - transcript_ids?: string[]; - /** - * Custom formatted transcript data. Maximum size is the context limit of the selected model, which defaults to 100000". - * Use either transcript_ids or input_text as input into LeMUR. - */ - input_text?: string; - /** - * A list of questions asked in the request - * Each question can have its own context and answer format. - */ - questions?: LemurQuestion[]; - /** - * The prompt used for the model. - */ - prompt?: string; - /** - * Context provided to the model. This can be a string or a free-form JSON value. - */ - context?: OneOf< - [ - string, - { - [key: string]: unknown; - }, - ] - >; - /** - * The format to use for the model's answers. - */ - answer_format?: string; -}; - -export type LemurBaseResponse = { - /** - * The ID of the LeMUR request - */ - request_id: string; - /** - * The usage numbers for the LeMUR request - */ - usage: LemurUsage; - request?: LemurRequestDetails; -}; - -/** - * The model that is used for the final prompt after compression is performed. - * - */ -export type LemurModel = - | "anthropic/claude-opus-4-20250514" - | "anthropic/claude-sonnet-4-20250514" - | "anthropic/claude-3-7-sonnet-20250219" - | "anthropic/claude-3-5-sonnet" - | "anthropic/claude-3-opus" - | "anthropic/claude-3-5-haiku-20241022" - | "anthropic/claude-3-haiku" - | "anthropic/claude-3-sonnet" - | "anthropic/claude-2-1" - | "anthropic/claude-2" - | "default" - | "assemblyai/mistral-7b"; - -/** - * @example - * ```js - * { - * "question": "Where are there wildfires?", - * "answer_format": "List of countries in ISO 3166-1 alpha-2 format" - * } - * ``` - */ -export type LemurQuestion = { - /** - * How you want the answer to be returned. This can be any text. Can't be used with answer_options. Examples: "short sentence", "bullet points" - */ - answer_format?: string; - /** - * What discrete options to return. Useful for precise responses. Can't be used with answer_format. Example: ["Yes", "No"] - */ - answer_options?: string[]; - /** - * Any context about the transcripts you wish to provide. This can be a string or any object. - */ - context?: OneOf< - [ - string, - { - [key: string]: unknown; - }, - ] - >; - /** - * The question you wish to ask. For more complex questions use default model. - */ - question: string; -}; - -/** - * An answer generated by LeMUR and its question - * @example - * ```js - * { - * "answer": "CA, US", - * "question": "Where are there wildfires?" - * } - * ``` - */ -export type LemurQuestionAnswer = { - /** - * The answer generated by LeMUR - */ - answer: string; - /** - * The question for LeMUR to answer - */ - question: string; -}; - -/** - * @example - * ```js - * { - * "transcript_ids": [ - * "64nygnr62k-405c-4ae8-8a6b-d90b40ff3cce" - * ], - * "context": "This is an interview about wildfires.", - * "questions": [ - * { - * "question": "Where are there wildfires?", - * "answer_format": "List of countries in ISO 3166-1 alpha-2 format", - * "answer_options": [ - * "US", - * "CA" - * ] - * }, - * { - * "question": "Is global warming affecting wildfires?", - * "answer_options": [ - * "yes", - * "no" - * ] - * } - * ], - * "final_model": "anthropic/claude-3-5-sonnet", - * "temperature": 0, - * "max_output_size": 3000 - * } - * ``` - */ -export type LemurQuestionAnswerParams = LemurBaseParams & { - /** - * A list of questions to ask - */ - questions: LemurQuestion[]; -}; - -/** - * @example - * ```js - * { - * "request_id": "5e1b27c2-691f-4414-8bc5-f14678442f9e", - * "response": [ - * { - * "answer": "CA, US", - * "question": "Where are there wildfires?" - * }, - * { - * "answer": "yes", - * "question": "Is global warming affecting wildfires?" - * } - * ], - * "usage": { - * "input_tokens": 27, - * "output_tokens": 3 - * } - * } - * ``` - */ -export type LemurQuestionAnswerResponse = LemurBaseResponse & { - /** - * The answers generated by LeMUR and their questions - */ - response: LemurQuestionAnswer[]; -}; - -export type LemurResponse = LemurStringResponse | LemurQuestionAnswerResponse; - -/** - * @example - * ```js - * { - * "request_id": "5e1b27c2-691f-4414-8bc5-f14678442f9e", - * "response": "Based on the transcript, the following locations were mentioned as being affected by wildfire smoke from Canada:\n\n- Maine\n- Maryland\n- Minnesota\n- Mid Atlantic region\n- Northeast region\n- New York City\n- Baltimore\n", - * "usage": { - * "input_tokens": 27, - * "output_tokens": 3 - * } - * } - * ``` - */ -export type LemurStringResponse = { - /** - * The response generated by LeMUR. - */ - response: string; -} & LemurBaseResponse; - -/** - * @example - * ```js - * { - * "transcript_ids": [ - * "47b95ba5-8889-44d8-bc80-5de38306e582" - * ], - * "context": "This is an interview about wildfires.", - * "final_model": "anthropic/claude-3-5-sonnet", - * "temperature": 0, - * "max_output_size": 3000 - * } - * ``` - */ -export type LemurSummaryParams = LemurBaseParams & { - /** - * How you want the summary to be returned. This can be any text. Examples: "TLDR", "bullet points" - */ - answer_format?: string; -}; - -/** - * @example - * ```js - * { - * "request_id": "5e1b27c2-691f-4414-8bc5-f14678442f9e", - * "response": "- Wildfires in Canada are sending smoke and air pollution across parts of the US, triggering air quality alerts from Maine to Minnesota. Concentrations of particulate matter have exceeded safety levels.\n\n- Weather systems are channeling the smoke through Pennsylvania into the Mid-Atlantic and Northeast regions. New York City has canceled outdoor activities to keep children and vulnerable groups indoors.\n\n- Very small particulate matter can enter the lungs and impact respiratory, cardiovascular and neurological health. Young children, the elderly and those with preexisting conditions are most at risk.\n\n- The conditions causing the poor air quality could get worse or shift to different areas in coming days depending on weather patterns. More wildfires may also contribute to higher concentrations.\n\n- Climate change is leading to longer and more severe fire seasons. Events of smoke traveling long distances and affecting air quality over wide areas will likely become more common in the future.\"\n", - * "usage": { - * "input_tokens": 27, - * "output_tokens": 3 - * } - * } - * ``` - */ -export type LemurSummaryResponse = LemurStringResponse; - -/** - * @example - * ```js - * { - * "transcript_ids": [ - * "64nygnr62k-405c-4ae8-8a6b-d90b40ff3cce" - * ], - * "prompt": "List all the locations affected by wildfires.", - * "context": "This is an interview about wildfires.", - * "final_model": "anthropic/claude-3-5-sonnet", - * "temperature": 0, - * "max_output_size": 3000 - * } - * ``` - */ -export type LemurTaskParams = { - /** - * Your text to prompt the model to produce a desired output, including any context you want to pass into the model. - */ - prompt: string; -} & LemurBaseParams; - -/** - * @example - * ```js - * { - * "request_id": "5e1b27c2-691f-4414-8bc5-f14678442f9e", - * "response": "Based on the transcript, the following locations were mentioned as being affected by wildfire smoke from Canada:\n\n- Maine\n- Maryland\n- Minnesota\n- Mid Atlantic region\n- Northeast region\n- New York City\n- Baltimore\n", - * "usage": { - * "input_tokens": 27, - * "output_tokens": 3 - * } - * } - * ``` - */ -export type LemurTaskResponse = LemurStringResponse; - -/** - * The usage numbers for the LeMUR request - */ -export type LemurUsage = { - /** - * The number of input tokens used by the model - */ - input_tokens: number; - /** - * The number of output tokens generated by the model - */ - output_tokens: number; -}; - /** * @example * ```js @@ -1241,31 +804,6 @@ export type PiiPolicy = | "vehicle_id" | "zodiac_sign"; -/** - * @example - * ```js - * { - * "request_id": "914fe7e4-f10a-4364-8946-34614c2873f6", - * "request_id_to_purge": "b7eb03ec-1650-4181-949b-75d9de317de1", - * "deleted": true - * } - * ``` - */ -export type PurgeLemurRequestDataResponse = { - /** - * Whether the request data was deleted - */ - deleted: boolean; - /** - * The ID of the deletion request of the LeMUR request - */ - request_id: string; - /** - * The ID of the LeMUR request to purge the data for - */ - request_id_to_purge: string; -}; - /** * @example * ```js diff --git a/tests/integration/lemur.test.ts b/tests/integration/lemur.test.ts deleted file mode 100644 index 95afc26..0000000 --- a/tests/integration/lemur.test.ts +++ /dev/null @@ -1,141 +0,0 @@ -import "dotenv/config"; -import { AssemblyAI, LemurTaskResponse } from "../../src"; - -const client = new AssemblyAI({ - apiKey: process.env.ASSEMBLYAI_API_KEY!, -}); -const knownTranscriptIds = process.env.TEST_TRANSCRIPT_IDS?.split(","); - -describe("lemur", () => { - it("should generate a summary", async () => { - const { response } = await client.lemur.summary({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - answer_format: "one sentence", - }); - - expect(response).toBeTruthy(); - }); - - it("should generate an answer", async () => { - const { response } = await client.lemur.questionAnswer({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - questions: [ - { - question: "What are they discussing?", - answer_format: "text", - }, - ], - }); - - expect(response).toBeTruthy(); - expect(response).toHaveLength(1); - }); - - it("should generate action items", async () => { - const { response } = await client.lemur.actionItems({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - }); - - expect(response).toBeTruthy(); - }); - - it("should generate a task", async () => { - const { response } = await client.lemur.task({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - prompt: "Write a haiku about this conversation.", - }); - - expect(response).toBeTruthy(); - }); - - it("should fail to generate a summary", async () => { - const promise = client.lemur.summary({ - final_model: "basic", - transcript_ids: ["bad-id"], - answer_format: "one sentence", - }); - - await expect(promise).rejects.toThrowError( - "each transcript source id must be valid", - ); - }); - - it("should return response", async () => { - const taskResponse = await client.lemur.task({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - prompt: "Write a haiku about this conversation.", - }); - - const taskResponse2 = await client.lemur.getResponse( - taskResponse.request_id, - ); - expect(taskResponse).toStrictEqual(taskResponse2); - }); - - it("should return response with generic", async () => { - const taskResponse = await client.lemur.task({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - prompt: "Write a haiku about this conversation.", - }); - - const taskResponse2 = await client.lemur.getResponse( - taskResponse.request_id, - ); - expect(taskResponse).toStrictEqual(taskResponse2); - }); - - it("should purge request data", async () => { - const { request_id } = await client.lemur.summary({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - answer_format: "one sentence", - }); - - const deletionRequest = await client.lemur.purgeRequestData(request_id); - expect(deletionRequest.deleted).toBeTruthy(); - expect(deletionRequest.request_id_to_purge).toBe(request_id); - }); - - it("should abort a summary request", async () => { - const controller = new AbortController(); - - // Start the request - const promise = client.lemur.summary( - { - final_model: "basic", - transcript_ids: knownTranscriptIds, - answer_format: "one sentence", - }, - controller.signal, - ); - - // Abort immediately - controller.abort(); - - // Should throw an error - await expect(promise).rejects.toThrow(); - }); - - it("should abort a task request", async () => { - const controller = new AbortController(); - - const promise = client.lemur.task( - { - final_model: "basic", - transcript_ids: knownTranscriptIds, - prompt: "Write a haiku about this conversation.", - }, - controller.signal, - ); - - controller.abort(); - - await expect(promise).rejects.toThrow(); - }); -}); diff --git a/tests/unit/lemur.test.ts b/tests/unit/lemur.test.ts deleted file mode 100644 index 4d5753e..0000000 --- a/tests/unit/lemur.test.ts +++ /dev/null @@ -1,308 +0,0 @@ -import fetchMock from "jest-fetch-mock"; -import { createClient, requestMatches } from "./utils"; -import { LemurTaskResponse } from "../../src"; - -const knownTranscriptIds = ["transcript_123"]; -const knownLemurRequestId = "lemur_123"; -const purgeRequestId = "purger_123"; - -fetchMock.enableMocks(); - -const assembly = createClient(); - -const lemurResponse = { - response: "some response", - requestId: knownLemurRequestId, -}; - -beforeEach(() => { - fetchMock.resetMocks(); - fetchMock.doMock(); -}); - -describe("lemur", () => { - it("should generate a summary", async () => { - fetchMock.doMockOnceIf( - requestMatches({ method: "POST", url: "/lemur/v3/generate/summary" }), - JSON.stringify(lemurResponse), - ); - const { response } = await assembly.lemur.summary({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - answer_format: "one sentence", - }); - - expect(response).toBeTruthy(); - }); - - it("should generate an answer", async () => { - fetchMock.doMockOnceIf( - requestMatches({ - method: "POST", - url: "/lemur/v3/generate/question-answer", - }), - JSON.stringify({ - ...lemurResponse, - response: [ - { - question: "question", - answer: "answer", - }, - ], - }), - ); - const { response } = await assembly.lemur.questionAnswer({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - questions: [ - { - question: "What are they discussing?", - answer_format: "text", - }, - ], - }); - - expect(response).toBeTruthy(); - expect(response).toHaveLength(1); - }); - - it("should generate action items", async () => { - fetchMock.doMockOnceIf( - requestMatches({ - method: "POST", - url: "/lemur/v3/generate/action-items", - }), - JSON.stringify(lemurResponse), - ); - const { response } = await assembly.lemur.actionItems({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - }); - - expect(response).toBeTruthy(); - }); - - it("should generate a task", async () => { - fetchMock.doMockOnceIf( - requestMatches({ method: "POST", url: "/lemur/v3/generate/task" }), - JSON.stringify(lemurResponse), - ); - const { response } = await assembly.lemur.task({ - final_model: "basic", - transcript_ids: knownTranscriptIds, - prompt: "Write a haiku about this conversation.", - }); - - expect(response).toBeTruthy(); - }); - - it("should fail to generate a summary", async () => { - fetchMock.mockResponseOnce( - JSON.stringify({ - error: "each transcript source id must be valid", - }), - { status: 500 }, - ); - const promise = assembly.lemur.summary({ - final_model: "basic", - transcript_ids: ["bad-id"], - answer_format: "one sentence", - }); - - await expect(promise).rejects.toThrowError( - "each transcript source id must be valid", - ); - }); - - it("should return response", async () => { - fetchMock.doMockOnceIf( - requestMatches({ - method: "GET", - url: `/lemur/v3/${knownLemurRequestId}`, - }), - JSON.stringify({ - request_id: knownLemurRequestId, - response: "some response", - }), - ); - const response = await assembly.lemur.getResponse(knownLemurRequestId); - expect(response).toBeTruthy(); - expect(response.request_id).toBe(knownLemurRequestId); - expect(response.response).toBe("some response"); - }); - - it("should return response with generic", async () => { - fetchMock.doMockOnceIf( - requestMatches({ - method: "GET", - url: `/lemur/v3/${knownLemurRequestId}`, - }), - JSON.stringify({ - request_id: knownLemurRequestId, - response: "some response", - }), - ); - const response = - await assembly.lemur.getResponse(knownLemurRequestId); - expect(response).toBeTruthy(); - expect(response.request_id).toBe(knownLemurRequestId); - expect(response.response).toBe("some response"); - }); - - it("should return response with request details", async () => { - const responseWithDetails = { - request_id: knownLemurRequestId, - response: "detailed response", - usage: { - input_tokens: 250, - output_tokens: 75, - }, - request: { - request_endpoint: "/lemur/v3/generate/task", - temperature: 0.7, - final_model: "anthropic/claude-3-5-sonnet", - max_output_size: 1500, - created_at: "2024-01-01T10:30:00Z", - transcript_ids: knownTranscriptIds, - prompt: "Analyze the key themes in this conversation", - context: "Focus on business decisions and action items", - }, - }; - - fetchMock.doMockOnceIf( - requestMatches({ - method: "GET", - url: `/lemur/v3/${knownLemurRequestId}`, - }), - JSON.stringify(responseWithDetails), - ); - - const response = await assembly.lemur.getResponse(knownLemurRequestId); - expect(response.request_id).toBe(knownLemurRequestId); - expect(response.request).toBeDefined(); - expect(response.request?.request_endpoint).toBe("/lemur/v3/generate/task"); - expect(response.request?.temperature).toBe(0.7); - expect(response.request?.final_model).toBe("anthropic/claude-3-5-sonnet"); - expect(response.request?.max_output_size).toBe(1500); - expect(response.request?.prompt).toBe( - "Analyze the key themes in this conversation", - ); - expect(response.usage.input_tokens).toBe(250); - expect(response.usage.output_tokens).toBe(75); - }); - - it("should return response with question-answer request details", async () => { - const qaResponseWithDetails = { - request_id: knownLemurRequestId, - response: [ - { question: "What was discussed?", answer: "Project updates" }, - ], - usage: { - input_tokens: 300, - output_tokens: 100, - }, - request: { - request_endpoint: "/lemur/v3/generate/question-answer", - temperature: 0.3, - final_model: "anthropic/claude-3-opus", - max_output_size: 2500, - created_at: "2024-01-01T14:15:00Z", - input_text: "Custom transcript content...", - questions: [ - { - question: "What was discussed?", - answer_format: "concise summary", - context: "Meeting notes", - }, - { - question: "Was the date of the next meeting called out?", - answer_options: ["Yes", "No", "Not mentioned"], - }, - ], - }, - }; - - fetchMock.doMockOnceIf( - requestMatches({ - method: "GET", - url: `/lemur/v3/${knownLemurRequestId}`, - }), - JSON.stringify(qaResponseWithDetails), - ); - - const response = await assembly.lemur.getResponse(knownLemurRequestId); - expect(response.request?.request_endpoint).toBe( - "/lemur/v3/generate/question-answer", - ); - expect(response.request?.input_text).toBe("Custom transcript content..."); - expect(response.request?.questions).toHaveLength(2); - expect(response.request?.questions?.[0].question).toBe( - "What was discussed?", - ); - expect(response.request?.questions?.[0].context).toBe("Meeting notes"); - expect(response.request?.questions?.[1].answer_options).toEqual([ - "Yes", - "No", - "Not mentioned", - ]); - }); - - it("should return response with context as object in request details", async () => { - const responseWithObjectContext = { - request_id: knownLemurRequestId, - response: "context-aware response", - usage: { - input_tokens: 180, - output_tokens: 60, - }, - request: { - request_endpoint: "/lemur/v3/generate/summary", - temperature: 0.5, - final_model: "default", - max_output_size: 2000, - created_at: "2024-01-01T16:45:00Z", - transcript_ids: knownTranscriptIds, - context: { - meeting_type: "standup", - team: "engineering", - date: "2024-01-01", - }, - answer_format: "bullet points", - }, - }; - - fetchMock.doMockOnceIf( - requestMatches({ - method: "GET", - url: `/lemur/v3/${knownLemurRequestId}`, - }), - JSON.stringify(responseWithObjectContext), - ); - - const response = await assembly.lemur.getResponse(knownLemurRequestId); - expect(response.request?.context).toEqual({ - meeting_type: "standup", - team: "engineering", - date: "2024-01-01", - }); - }); - - it("should purge request data", async () => { - fetchMock.doMockOnceIf( - requestMatches({ - method: "DELETE", - url: `/lemur/v3/${knownLemurRequestId}`, - }), - JSON.stringify({ - deleted: true, - request_id: purgeRequestId, - request_id_to_purge: knownLemurRequestId, - }), - ); - const deletionRequest = - await assembly.lemur.purgeRequestData(knownLemurRequestId); - expect(deletionRequest.deleted).toBeTruthy(); - expect(deletionRequest.request_id_to_purge).toBe(knownLemurRequestId); - expect(deletionRequest.request_id).toBe(purgeRequestId); - }); -});