(
transcript: TranscriptSegment[],
options: GenerateTopicsOptions = {}
)
| 1167 | * @returns Array of topics with segments and quotes |
| 1168 | */ |
| 1169 | export async function generateTopicsFromTranscript( |
| 1170 | transcript: TranscriptSegment[], |
| 1171 | options: GenerateTopicsOptions = {} |
| 1172 | ): Promise<{ |
| 1173 | topics: Topic[]; |
| 1174 | candidates?: TopicCandidate[]; |
| 1175 | modelUsed: string; |
| 1176 | }> { |
| 1177 | const { |
| 1178 | maxTopics = 5, |
| 1179 | theme, |
| 1180 | excludeTopicKeys, |
| 1181 | includeCandidatePool, |
| 1182 | mode = 'smart', |
| 1183 | provider |
| 1184 | } = options; |
| 1185 | |
| 1186 | const requestedTopics = Math.max(1, Math.min(maxTopics, 5)); |
| 1187 | const fullText = combineTranscript(transcript); |
| 1188 | const excludedKeys = excludeTopicKeys ?? new Set<string>(); |
| 1189 | const primaryProvider = getProviderKey(provider); |
| 1190 | const providerRetryResult = await retryProviderBackedTopicGeneration({ |
| 1191 | primaryProvider, |
| 1192 | availableProviderKeys: availableProviders(), |
| 1193 | run: async (providerKey) => |
| 1194 | generateProviderBackedTopicsFromTranscript(transcript, options, providerKey), |
| 1195 | isUsableResult: (result) => (result?.topicsArray.length ?? 0) > 0 |
| 1196 | }); |
| 1197 | |
| 1198 | let topicsArray = providerRetryResult.result?.topicsArray ?? []; |
| 1199 | const candidateTopics = providerRetryResult.result?.candidateTopics ?? []; |
| 1200 | const resolvedModel = |
| 1201 | providerRetryResult.result?.resolvedModel ?? |
| 1202 | getProviderBackedTopicModel({ |
| 1203 | provider: providerRetryResult.providerUsed, |
| 1204 | mode, |
| 1205 | transcript, |
| 1206 | fastModel: options.fastModel, |
| 1207 | proModel: options.proModel |
| 1208 | }); |
| 1209 | |
| 1210 | if (topicsArray.length === 0) { |
| 1211 | console.warn( |
| 1212 | `[generateTopicsFromTranscript] Falling back to local topic generation after provider-backed attempts (${providerRetryResult.providerUsed} was the last provider tried)` |
| 1213 | ); |
| 1214 | const fallbackTopics = buildFallbackTopics( |
| 1215 | transcript, |
| 1216 | requestedTopics, |
| 1217 | fullText, |
| 1218 | theme |
| 1219 | ); |
| 1220 | topicsArray = fallbackTopics |
| 1221 | .filter((topic) => { |
| 1222 | if (!topic.quote?.timestamp || !topic.quote.text) return false; |
| 1223 | const key = `${topic.quote.timestamp}|${normalizeWhitespace( |
| 1224 | topic.quote.text |
| 1225 | )}`; |
| 1226 | return !excludedKeys.has(key); |
no test coverage detected