@sprqvntrs/llm 3.13.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.
@@ -0,0 +1,98 @@
1
+ export type SanitizationResult = {
2
+ /** The sanitized text with artifacts removed */
3
+ sanitized: string;
4
+ /** Whether any artifacts were removed */
5
+ wasModified: boolean;
6
+ /** Human-readable descriptions of what was removed */
7
+ removedPatterns: string[];
8
+ };
9
+
10
+ /**
11
+ * Strips JSON-style and structural artifacts from prose text produced by LLMs.
12
+ *
13
+ * Each pattern is applied independently. The function is pure (no I/O, no side effects).
14
+ * Surrounding prose is never removed — only the artifact token/sequence itself.
15
+ *
16
+ * Patterns handled:
17
+ * 1. Markdown code fences (``` or ~~~) leaked into plain text
18
+ * 2. XML-like closing tags (</article>, </content>, </output>) from prompt scaffolding
19
+ * 3. PMID-style bracketed numeric placeholders ([PMID:12345], [14094+])
20
+ * 4. Structural/editorial ALL_CAPS labels at line start (PARAGRAPH_1:, SECTION_2:)
21
+ * 5. INVALID_* token blocks (model generation corruption)
22
+ * 6. Stray JSON structural delimiters (sequences of 2+ of {}[], or orphaned "]} etc.)
23
+ * 7. Meta-commentary/apology fragments (I apologize for…, As an AI…)
24
+ * 8. (Blank-line normalization runs after all patterns)
25
+ *
26
+ * @param text - The raw text from LLM output
27
+ * @returns SanitizationResult with the cleaned text and metadata
28
+ */
29
+ export function stripJsonArtifacts(text: string): SanitizationResult {
30
+ const removedPatterns: string[] = [];
31
+ let result = text;
32
+
33
+ // Pattern 1: Markdown code fences (``` or ~~~) leaked into prose
34
+ // Must run first — they often wrap JSON blocks
35
+ const codeFencesBefore = result;
36
+ result = result.replace(/^```[\w]*\n?/gm, '').replace(/^```\s*$/gm, '').replace(/^~~~[\w]*\n?/gm, '').replace(/^~~~\s*$/gm, '');
37
+ if (result !== codeFencesBefore) {
38
+ removedPatterns.push('markdown code fences');
39
+ }
40
+
41
+ // Pattern 2: XML-like closing tags leaked from prompt scaffolding
42
+ // e.g. </article>, </output>, </content>, </task>
43
+ const xmlTagsBefore = result;
44
+ result = result.replace(/<\/[a-zA-Z_][a-zA-Z0-9_-]*>/g, '');
45
+ if (result !== xmlTagsBefore) {
46
+ removedPatterns.push('XML-like closing tags');
47
+ }
48
+
49
+ // Pattern 3: PMID-style bracketed numeric placeholders
50
+ // [PMID:12345] or [12345] where number is 5+ digits — document IDs, not years/scores
51
+ const pmidBefore = result;
52
+ result = result.replace(/\[PMID:\d+\]/gi, '');
53
+ result = result.replace(/\[\d{5,}\]/g, '');
54
+ if (result !== pmidBefore) {
55
+ removedPatterns.push('PMID-style numeric placeholders');
56
+ }
57
+
58
+ // Pattern 4: Structural/editorial label at line start
59
+ // e.g. "PARAGRAPH_1:", "SECTION_2:", "PART_1:", "INTRO:", "CONCLUSION:"
60
+ const labelsBefore = result;
61
+ result = result.replace(/^[A-Z][A-Z0-9_]{2,}:\s*/gm, '');
62
+ if (result !== labelsBefore) {
63
+ removedPatterns.push('structural/editorial ALL_CAPS labels');
64
+ }
65
+
66
+ // Pattern 5: INVALID_* token blocks (model generation corruption)
67
+ const invalidTokensBefore = result;
68
+ result = result.replace(/\bINVALID_[A-Z_]+\b/g, '');
69
+ if (result !== invalidTokensBefore) {
70
+ removedPatterns.push('INVALID_* token blocks');
71
+ }
72
+
73
+ // Pattern 6: Stray JSON structural delimiters
74
+ const jsonDelimitersBefore = result;
75
+ result = result.replace(/["\]}\[{]{2,}/g, '');
76
+ result = result.replace(/"[\]},]+/g, '');
77
+ if (result !== jsonDelimitersBefore) {
78
+ removedPatterns.push('JSON structural delimiters');
79
+ }
80
+
81
+ // Pattern 7: Meta-commentary / apology fragments
82
+ const metaBefore = result;
83
+ result = result.replace(/(?:^|\n)(I apologize for[^.!?]*[.!?])/gi, '');
84
+ result = result.replace(/(?:^|\n)(I'm sorry,? but[^.!?]*[.!?])/gi, '');
85
+ result = result.replace(/(?:^|\n)(As an AI[^.!?]*[.!?])/gi, '');
86
+ if (result !== metaBefore) {
87
+ removedPatterns.push('meta-commentary/apology fragments');
88
+ }
89
+
90
+ // Normalise blank-line runs that artifact removal might have created
91
+ result = result.replace(/\n{3,}/g, '\n\n').trim();
92
+
93
+ return {
94
+ sanitized: result,
95
+ wasModified: removedPatterns.length > 0,
96
+ removedPatterns,
97
+ };
98
+ }