@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.
- package/LICENSE +21 -0
- package/README.md +595 -0
- package/index.ts +53 -0
- package/package.json +56 -0
- package/src/clients/anthropic-client.ts +636 -0
- package/src/clients/openai-client.ts +548 -0
- package/src/clients/openrouter-client.ts +802 -0
- package/src/helpers.ts +185 -0
- package/src/llm.ts +107 -0
- package/src/model-types.ts +61 -0
- package/src/models.ts +98 -0
- package/src/pricing-data.json +1651 -0
- package/src/pricing.ts +36 -0
- package/src/types/client-interface.ts +222 -0
- package/src/utils/debug.ts +120 -0
- package/src/utils/errors.ts +508 -0
- package/src/utils/normalize-null-strings.ts +103 -0
- package/src/utils/resolve-refs.ts +91 -0
- package/src/utils/strip-json-artifacts.ts +98 -0
|
@@ -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
|
+
}
|