@mux/ai 0.15.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-yn3fUDgv.d.ts → index-CXC5gAHs.d.ts} +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +66 -54
- package/dist/index.js.map +1 -1
- package/dist/primitives/index.js +1 -1
- package/dist/primitives/index.js.map +1 -1
- package/dist/workflows/index.d.ts +1 -1
- package/dist/workflows/index.js +65 -53
- package/dist/workflows/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as AskQuestionsOptions, a as AskQuestionsResult, b as AskQuestionsType, c as AudioTranslationOptions, d as AudioTranslationResult, e as AutoCensorProfanityOptions, B as BurnedInCaptionsAnalysis, f as BurnedInCaptionsOptions, g as BurnedInCaptionsPromptOverrides, h as BurnedInCaptionsPromptSections, j as BurnedInCaptionsResult, C as CaptionReplacement, k as CensorMode, l as Chapter, m as ChapterSystemPromptSections, n as ChaptersOptions, o as ChaptersPromptOverrides, p as ChaptersPromptSections, q as ChaptersResult, r as ChaptersType, D as DEFAULT_DESCRIPTION_LENGTH, s as DEFAULT_SUMMARY_KEYWORD_LIMIT, t as DEFAULT_TITLE_LENGTH, E as EditCaptionsOptions, u as EditCaptionsResult, v as EmbeddingsOptions, w as EmbeddingsResult, x as EngagementInsightsOptions, y as EngagementInsightsResult, H as HIVE_SEXUAL_CATEGORIES, z as HIVE_VIOLENCE_CATEGORIES, F as HiveModerationOutput, G as HiveModerationSource, M as ModerationOptions, I as ModerationProvider, J as ModerationResult, K as MomentInsight, O as OverallInsight, P as ProfanityDetectionPayload, Q as Question, L as QuestionAnswer, N as QuestionAnswerType, R as ReplacementRecord, S as SummarizationOptions, T as SummarizationPromptOverrides, U as SummarizationPromptSections, V as SummaryAndTagsResult, W as SummaryType, X as ThumbnailModerationScore, Y as TranslationChunkingOptions, Z as TranslationOptions, _ as TranslationPayload, $ as TranslationResult, a0 as aggregateTokenUsage, a1 as applyOverrideLists, a2 as applyReplacements, a3 as askQuestions, a4 as buildReplacementRegex, a5 as burnedInCaptionsSchema, a6 as censorVttContent, a7 as chapterSchema, a8 as chaptersSchema, a9 as createReplacer, aa as editCaptions, ab as extractTranscriptSegmentsForHotspots, ac as generateChapters, ad as generateEmbeddings, ae as generateEngagementInsights, af as generateVideoEmbeddings, ag as getModerationScores, ah as getSummaryAndTags, ai as hasBurnedInCaptions, aj as mapShotsToHotspots, ak as profanityDetectionSchema, al as questionAnswerSchema, am as shouldSplitChunkTranslationError, an as summarySchema, ao as transformCueText, ap as translateAudio, aq as translateCaptions, ar as translationSchema } from '../index-
|
|
1
|
+
export { A as AskQuestionsOptions, a as AskQuestionsResult, b as AskQuestionsType, c as AudioTranslationOptions, d as AudioTranslationResult, e as AutoCensorProfanityOptions, B as BurnedInCaptionsAnalysis, f as BurnedInCaptionsOptions, g as BurnedInCaptionsPromptOverrides, h as BurnedInCaptionsPromptSections, j as BurnedInCaptionsResult, C as CaptionReplacement, k as CensorMode, l as Chapter, m as ChapterSystemPromptSections, n as ChaptersOptions, o as ChaptersPromptOverrides, p as ChaptersPromptSections, q as ChaptersResult, r as ChaptersType, D as DEFAULT_DESCRIPTION_LENGTH, s as DEFAULT_SUMMARY_KEYWORD_LIMIT, t as DEFAULT_TITLE_LENGTH, E as EditCaptionsOptions, u as EditCaptionsResult, v as EmbeddingsOptions, w as EmbeddingsResult, x as EngagementInsightsOptions, y as EngagementInsightsResult, H as HIVE_SEXUAL_CATEGORIES, z as HIVE_VIOLENCE_CATEGORIES, F as HiveModerationOutput, G as HiveModerationSource, M as ModerationOptions, I as ModerationProvider, J as ModerationResult, K as MomentInsight, O as OverallInsight, P as ProfanityDetectionPayload, Q as Question, L as QuestionAnswer, N as QuestionAnswerType, R as ReplacementRecord, S as SummarizationOptions, T as SummarizationPromptOverrides, U as SummarizationPromptSections, V as SummaryAndTagsResult, W as SummaryType, X as ThumbnailModerationScore, Y as TranslationChunkingOptions, Z as TranslationOptions, _ as TranslationPayload, $ as TranslationResult, a0 as aggregateTokenUsage, a1 as applyOverrideLists, a2 as applyReplacements, a3 as askQuestions, a4 as buildReplacementRegex, a5 as burnedInCaptionsSchema, a6 as censorVttContent, a7 as chapterSchema, a8 as chaptersSchema, a9 as createReplacer, aa as editCaptions, ab as extractTranscriptSegmentsForHotspots, ac as generateChapters, ad as generateEmbeddings, ae as generateEngagementInsights, af as generateVideoEmbeddings, ag as getModerationScores, ah as getSummaryAndTags, ai as hasBurnedInCaptions, aj as mapShotsToHotspots, ak as profanityDetectionSchema, al as questionAnswerSchema, am as shouldSplitChunkTranslationError, an as summarySchema, ao as transformCueText, ap as translateAudio, aq as translateCaptions, ar as translationSchema } from '../index-CXC5gAHs.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import '@ai-sdk/anthropic';
|
|
4
4
|
import '@ai-sdk/google';
|
package/dist/workflows/index.js
CHANGED
|
@@ -116,7 +116,7 @@ var MuxAiError = class extends Error {
|
|
|
116
116
|
super(message);
|
|
117
117
|
/** Structural brand for duck-type identification. */
|
|
118
118
|
this.__robots_error = true;
|
|
119
|
-
this.name = "
|
|
119
|
+
this.name = "FatalError";
|
|
120
120
|
this.publicType = opts?.type ?? "processing_error";
|
|
121
121
|
this.publicMessage = message;
|
|
122
122
|
this.retryable = opts?.retryable ?? false;
|
|
@@ -794,7 +794,7 @@ function renderSection(section) {
|
|
|
794
794
|
throw new Error(`Invalid XML ${context} name: "${name}"`);
|
|
795
795
|
}
|
|
796
796
|
};
|
|
797
|
-
const escapeXmlText = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">
|
|
797
|
+
const escapeXmlText = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
798
798
|
const escapeXmlAttribute = (value) => escapeXmlText(value).replace(/"/g, """);
|
|
799
799
|
if (!content.trim()) {
|
|
800
800
|
return "";
|
|
@@ -1342,7 +1342,7 @@ async function fetchTranscriptForAsset(asset, playbackId, options = {}) {
|
|
|
1342
1342
|
|
|
1343
1343
|
// src/workflows/ask-questions.ts
|
|
1344
1344
|
var questionAnswerSchema = z2.object({
|
|
1345
|
-
question: z2.string(),
|
|
1345
|
+
question: z2.string().describe("The full text of the original question"),
|
|
1346
1346
|
answer: z2.string().nullable(),
|
|
1347
1347
|
confidence: z2.number(),
|
|
1348
1348
|
reasoning: z2.string(),
|
|
@@ -1388,12 +1388,14 @@ var SYSTEM_PROMPT = dedent`
|
|
|
1388
1388
|
<task>
|
|
1389
1389
|
For each question provided, you must:
|
|
1390
1390
|
1. Analyze the storyboard frames and transcript (if provided)
|
|
1391
|
-
2. Answer with ONLY the allowed response options - no other values are acceptable
|
|
1391
|
+
2. Answer with ONLY the allowed response options listed for that question - no other values are acceptable
|
|
1392
1392
|
3. Provide a confidence score between 0 and 1 reflecting your certainty
|
|
1393
1393
|
4. Explain your reasoning based on observable evidence
|
|
1394
1394
|
</task>
|
|
1395
1395
|
|
|
1396
1396
|
<answer_guidelines>
|
|
1397
|
+
- Each question is presented as its own <question> block with a <text> element (the question) and an <allowed_answers> element (the permitted response values)
|
|
1398
|
+
- Choose only from the values listed in that question's <allowed_answers> element
|
|
1397
1399
|
- Choose the affirmative option only if you have clear evidence supporting it
|
|
1398
1400
|
- Choose the negative/contradicting option if evidence contradicts or if insufficient evidence exists
|
|
1399
1401
|
- Confidence should reflect the clarity and strength of evidence:
|
|
@@ -1441,7 +1443,7 @@ var SYSTEM_PROMPT = dedent`
|
|
|
1441
1443
|
</relevance_filtering>
|
|
1442
1444
|
|
|
1443
1445
|
<constraints>
|
|
1444
|
-
- You MUST answer every relevant question with one of
|
|
1446
|
+
- You MUST answer every relevant question with one of its own listed allowed response options
|
|
1445
1447
|
- Skip irrelevant questions as described in relevance_filtering
|
|
1446
1448
|
- Only describe observable evidence from frames or transcript
|
|
1447
1449
|
- Do not fabricate details or make unsupported assumptions
|
|
@@ -1476,12 +1478,14 @@ var AUDIO_ONLY_SYSTEM_PROMPT = dedent`
|
|
|
1476
1478
|
<task>
|
|
1477
1479
|
For each question provided, you must:
|
|
1478
1480
|
1. Analyze the transcript
|
|
1479
|
-
2. Answer with ONLY the allowed response options - no other values are acceptable
|
|
1481
|
+
2. Answer with ONLY the allowed response options listed for that question - no other values are acceptable
|
|
1480
1482
|
3. Provide a confidence score between 0 and 1 reflecting your certainty
|
|
1481
1483
|
4. Explain your reasoning based on observable evidence
|
|
1482
1484
|
</task>
|
|
1483
1485
|
|
|
1484
1486
|
<answer_guidelines>
|
|
1487
|
+
- Each question is presented as its own <question> block with a <text> element (the question) and an <allowed_answers> element (the permitted response values)
|
|
1488
|
+
- Choose only from the values listed in that question's <allowed_answers> element
|
|
1485
1489
|
- Choose the affirmative option only if you have clear evidence supporting it
|
|
1486
1490
|
- Choose the negative/contradicting option if evidence contradicts or if insufficient evidence exists
|
|
1487
1491
|
- Confidence should reflect the clarity and strength of evidence:
|
|
@@ -1529,7 +1533,7 @@ var AUDIO_ONLY_SYSTEM_PROMPT = dedent`
|
|
|
1529
1533
|
</relevance_filtering>
|
|
1530
1534
|
|
|
1531
1535
|
<constraints>
|
|
1532
|
-
- You MUST answer every relevant question with one of
|
|
1536
|
+
- You MUST answer every relevant question with one of its own listed allowed response options
|
|
1533
1537
|
- Skip irrelevant questions as described in relevance_filtering
|
|
1534
1538
|
- Only describe observable evidence from transcript content
|
|
1535
1539
|
- Do not fabricate details or make unsupported assumptions
|
|
@@ -1544,46 +1548,43 @@ var AUDIO_ONLY_SYSTEM_PROMPT = dedent`
|
|
|
1544
1548
|
- GOOD: "The speaker describes running through a park"
|
|
1545
1549
|
- Be specific and evidence-based
|
|
1546
1550
|
</language_guidelines>`;
|
|
1547
|
-
var askQuestionsPromptBuilder = createPromptBuilder({
|
|
1548
|
-
template: {
|
|
1549
|
-
questions: {
|
|
1550
|
-
tag: "questions",
|
|
1551
|
-
content: "Please answer the following questions about this content:"
|
|
1552
|
-
}
|
|
1553
|
-
},
|
|
1554
|
-
sectionOrder: ["questions"]
|
|
1555
|
-
});
|
|
1556
1551
|
function buildUserPrompt({
|
|
1557
1552
|
questions,
|
|
1558
|
-
allowedAnswers,
|
|
1559
1553
|
transcriptText,
|
|
1560
1554
|
isCleanTranscript = true,
|
|
1561
1555
|
isAudioOnly = false
|
|
1562
1556
|
}) {
|
|
1563
|
-
const
|
|
1564
|
-
const
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
const
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
${
|
|
1557
|
+
const contentDescriptor = isAudioOnly ? "audio content using transcript evidence" : "content";
|
|
1558
|
+
const taskContent = dedent`
|
|
1559
|
+
Answer each question in the <questions> block below about the ${contentDescriptor}.
|
|
1560
|
+
Use only the values listed inside each question's own <allowed_answers> element.
|
|
1561
|
+
Return one answer per question, in the order the questions appear.
|
|
1562
|
+
If a question cannot be answered from the provided content, skip it as described in the system instructions.`;
|
|
1563
|
+
const taskSection = `<task>
|
|
1564
|
+
${taskContent}
|
|
1565
|
+
</task>`;
|
|
1566
|
+
const questionBlocks = questions.map((q, idx) => {
|
|
1567
|
+
const textTag = renderSection({ tag: "text", content: q.question });
|
|
1568
|
+
const answersTag = renderSection({
|
|
1569
|
+
tag: "allowed_answers",
|
|
1570
|
+
content: q.answerOptions.map((a) => `"${a}"`).join(", ")
|
|
1571
|
+
});
|
|
1572
|
+
return `<question number="${idx + 1}">
|
|
1573
|
+
${textTag}
|
|
1574
|
+
${answersTag}
|
|
1575
|
+
</question>`;
|
|
1576
|
+
}).join("\n\n");
|
|
1577
|
+
const questionsSection = `<questions>
|
|
1578
|
+
${questionBlocks}
|
|
1579
|
+
</questions>`;
|
|
1580
|
+
const sections = [];
|
|
1581
|
+
if (transcriptText) {
|
|
1582
|
+
const format = isCleanTranscript ? "plain text" : "WebVTT";
|
|
1583
|
+
sections.push(renderSection(createTranscriptSection(transcriptText, format)));
|
|
1579
1584
|
}
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
return
|
|
1583
|
-
|
|
1584
|
-
${questionsSection}
|
|
1585
|
-
|
|
1586
|
-
${responseOptions}`;
|
|
1585
|
+
sections.push(taskSection);
|
|
1586
|
+
sections.push(questionsSection);
|
|
1587
|
+
return sections.join("\n\n");
|
|
1587
1588
|
}
|
|
1588
1589
|
async function fetchImageAsBase64(imageUrl, imageDownloadOptions) {
|
|
1589
1590
|
"use step";
|
|
@@ -1652,7 +1653,6 @@ async function askQuestions(assetId, questions, options) {
|
|
|
1652
1653
|
provider = "openai",
|
|
1653
1654
|
model,
|
|
1654
1655
|
languageCode,
|
|
1655
|
-
answerOptions,
|
|
1656
1656
|
includeTranscript = true,
|
|
1657
1657
|
cleanTranscript = true,
|
|
1658
1658
|
imageSubmissionMode = "url",
|
|
@@ -1660,15 +1660,23 @@ async function askQuestions(assetId, questions, options) {
|
|
|
1660
1660
|
storyboardWidth = 640,
|
|
1661
1661
|
credentials
|
|
1662
1662
|
} = options ?? {};
|
|
1663
|
-
const
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1663
|
+
const normalizedQuestions = questions.map((q, idx) => {
|
|
1664
|
+
const options2 = Array.from(
|
|
1665
|
+
new Set(
|
|
1666
|
+
(q.answerOptions?.length ? q.answerOptions : ["yes", "no"]).map((o) => o.trim()).filter(Boolean)
|
|
1667
|
+
)
|
|
1668
|
+
);
|
|
1669
|
+
if (!options2.length) {
|
|
1670
|
+
throw new MuxAiError(
|
|
1671
|
+
`Question at index ${idx} has invalid answerOptions: must include at least one non-empty value.`,
|
|
1672
|
+
{ type: "validation_error" }
|
|
1673
|
+
);
|
|
1674
|
+
}
|
|
1675
|
+
return { ...q, answerOptions: options2 };
|
|
1676
|
+
});
|
|
1677
|
+
const allowedAnswers = Array.from(
|
|
1678
|
+
new Set(normalizedQuestions.flatMap((q) => q.answerOptions))
|
|
1667
1679
|
);
|
|
1668
|
-
if (!normalizedAnswerOptions.length) {
|
|
1669
|
-
throw new MuxAiError("answerOptions must include at least one non-empty value.", { type: "validation_error" });
|
|
1670
|
-
}
|
|
1671
|
-
const allowedAnswers = normalizedAnswerOptions;
|
|
1672
1680
|
const modelConfig = resolveLanguageModelConfig({
|
|
1673
1681
|
...options,
|
|
1674
1682
|
model,
|
|
@@ -1699,8 +1707,7 @@ async function askQuestions(assetId, questions, options) {
|
|
|
1699
1707
|
}) : void 0;
|
|
1700
1708
|
const transcriptText = transcriptResult?.transcriptText ?? "";
|
|
1701
1709
|
const userPrompt = buildUserPrompt({
|
|
1702
|
-
questions,
|
|
1703
|
-
allowedAnswers,
|
|
1710
|
+
questions: normalizedQuestions,
|
|
1704
1711
|
transcriptText,
|
|
1705
1712
|
isCleanTranscript: cleanTranscript,
|
|
1706
1713
|
isAudioOnly
|
|
@@ -1763,10 +1770,15 @@ async function askQuestions(assetId, questions, options) {
|
|
|
1763
1770
|
`Failed to generate answers for all questions for asset ${assetId}.`
|
|
1764
1771
|
);
|
|
1765
1772
|
}
|
|
1766
|
-
const answers = analysisResponse.result.answers.map((raw) => {
|
|
1773
|
+
const answers = analysisResponse.result.answers.map((raw, idx) => {
|
|
1767
1774
|
const isSkipped = raw.skipped || raw.answer === SKIP_SENTINEL;
|
|
1775
|
+
if (!isSkipped && !normalizedQuestions[idx].answerOptions.includes(raw.answer)) {
|
|
1776
|
+
throw new MuxAiError(
|
|
1777
|
+
`Answer "${raw.answer}" for question ${idx} is not in allowed options: ${normalizedQuestions[idx].answerOptions.join(", ")}`
|
|
1778
|
+
);
|
|
1779
|
+
}
|
|
1768
1780
|
return {
|
|
1769
|
-
// Strip numbering prefix (e.g
|
|
1781
|
+
// Strip numbering prefix (e.g. "1. ") if the LLM prepends one
|
|
1770
1782
|
question: raw.question.replace(/^\d+\.\s*/, ""),
|
|
1771
1783
|
confidence: isSkipped ? 0 : Math.min(1, Math.max(0, raw.confidence)),
|
|
1772
1784
|
reasoning: raw.reasoning,
|