|
18 | 18 | import { SummaryStats, TopicStats } from "../../stats/summary_stats";
|
19 | 19 | import { SummaryContent, Summary } from "../../types";
|
20 | 20 | import { RecursiveSummary } from "./recursive_summarization";
|
21 |
| -import { getAbstractPrompt, decimalToPercent, filterSummaryContent } from "../../sensemaker_utils"; |
| 21 | +import { |
| 22 | + getAbstractPrompt, |
| 23 | + decimalToPercent, |
| 24 | + filterSummaryContent, |
| 25 | + retryCall, |
| 26 | +} from "../../sensemaker_utils"; |
22 | 27 |
|
23 | 28 | function oneShotInstructions(topicNames: string[]) {
|
24 | 29 | return (
|
@@ -97,14 +102,23 @@ export class OverviewSummary extends RecursiveSummary<OverviewInput> {
|
97 | 102 | ` </topicsSummary>`,
|
98 | 103 | this.additionalContext
|
99 | 104 | );
|
100 |
| - const result = await this.model.generateText(prompt); |
101 |
| - // Check to make sure that every single topicName in topicNames is in the list, and raise an error if not |
102 |
| - for (const topicName of topicNames) { |
103 |
| - if (!result.includes(topicName)) { |
104 |
| - throw new Error(`Overview summary is missing topic name: ${topicName}`); |
105 |
| - } |
106 |
| - } |
107 |
| - return removeEmptyLines(result); |
| 105 | + return await retryCall( |
| 106 | + async function (model, prompt) { |
| 107 | + let result = await model.generateText(prompt); |
| 108 | + result = removeEmptyLines(result); |
| 109 | + if (!result) { |
| 110 | + throw new Error(`Overview summary failed to conform to markdown list format.`); |
| 111 | + } else { |
| 112 | + return result; |
| 113 | + } |
| 114 | + }, |
| 115 | + (result) => isMdListValid(result, topicNames), |
| 116 | + 3, |
| 117 | + "Overview summary failed to conform to markdown list format, or did not include all topic descriptions exactly as intended.", |
| 118 | + undefined, |
| 119 | + [this.model, prompt], |
| 120 | + [] |
| 121 | + ); |
108 | 122 | }
|
109 | 123 |
|
110 | 124 | /**
|
@@ -171,3 +185,25 @@ function filterSectionsForOverview(topicSummary: SummaryContent): SummaryContent
|
171 | 185 | export function removeEmptyLines(mdList: string): string {
|
172 | 186 | return mdList.replace(/\s*[\r\n]+\s*/g, "\n").trim();
|
173 | 187 | }
|
| 188 | + |
| 189 | +/** |
| 190 | + * This function processes the input markdown list string, ensuring that it matches |
| 191 | + * the expected format, normalizing it with `removeEmptyLines`, and ensuring that each |
| 192 | + * lines matches the expected format (* **bold topic**: summary...) |
| 193 | + */ |
| 194 | +export function isMdListValid(mdList: string, topicNames: string[]): boolean { |
| 195 | + const lines = mdList.split("\n"); |
| 196 | + for (const [index, line] of lines.entries()) { |
| 197 | + // Check to make sure that every single topicName in topicNames is in the list, and in the right order |
| 198 | + if (!line.includes(topicNames[index])) { |
| 199 | + console.log("Topic name not found in list:", topicNames[index]); |
| 200 | + return false; |
| 201 | + } |
| 202 | + // Check to make sure that every line matches the expected format |
| 203 | + if (!line.match(/^[\*\-]\s\*\*.*:?\*\*:?\s/) && !line.match(/^[\*\-]\s\_\_.*:?\_\_:?\s/)) { |
| 204 | + console.log("Line does not match expected format:", line); |
| 205 | + return false; |
| 206 | + } |
| 207 | + } |
| 208 | + return true; |
| 209 | +} |
0 commit comments