@painitehq/structured-llm 0.1.0 → 0.2.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/README.md +145 -59
- package/dist/index.cjs +280 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -5
- package/dist/index.d.ts +19 -5
- package/dist/index.js +279 -75
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/llm-client.ts","../src/validator.ts","../src/schema.ts","../src/extractor.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export interface LLMClientConfig {\n apiKey: string;\n model: string;\n temperature?: number;\n timeout?: number;\n}\n\nexport interface LLMResponse {\n content: string;\n model: string;\n usage?: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n}\n\ninterface OpenRouterChoice {\n message?: {\n content?: string;\n };\n}\n\ninterface OpenRouterResponse {\n choices?: OpenRouterChoice[];\n model?: string;\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\nconst DEFAULT_MODEL = \"openrouter/free\";\nconst DEFAULT_TEMPERATURE = 0;\nconst DEFAULT_TIMEOUT = 60000;\n\nexport async function callLLM(\n prompt: string,\n config: LLMClientConfig\n): Promise<LLMResponse> {\n const {\n apiKey,\n model = DEFAULT_MODEL,\n temperature = DEFAULT_TEMPERATURE,\n timeout = DEFAULT_TIMEOUT,\n } = config;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(\"https://openrouter.ai/api/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n \"HTTP-Referer\": \"https://github.com/harshitduggal/structured-llm\",\n \"X-Title\": \"structured-llm\",\n },\n body: JSON.stringify({\n model,\n messages: [\n {\n role: \"system\",\n content: \"You are a precise data extraction assistant. You MUST respond with valid JSON only. No explanations, no markdown, no text outside the JSON. Just the raw JSON object.\",\n },\n {\n role: \"user\",\n content: prompt,\n },\n ],\n temperature,\n response_format: { type: \"json_object\" },\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n throw new Error(\n `OpenRouter API error: ${response.status} - ${errorBody}`\n );\n }\n\n const data = (await response.json()) as OpenRouterResponse;\n\n if (!data.choices || data.choices.length === 0) {\n throw new Error(\"No response from LLM\");\n }\n\n const content = data.choices[0].message?.content;\n if (!content) {\n throw new Error(\"Empty response from LLM\");\n }\n\n return {\n content,\n model: data.model || model,\n usage: data.usage\n ? {\n promptTokens: data.usage.prompt_tokens,\n completionTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined,\n };\n } finally {\n clearTimeout(timeoutId);\n }\n}\n","export function tryParseJSON(raw: string): { success: true; data: unknown } | { success: false; error: string } {\n try {\n const data = JSON.parse(raw);\n return { success: true, data };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : \"Unknown parse error\" };\n }\n}\n\nexport function extractJSON(raw: string): string | null {\n const trimmed = raw.trim();\n\n if (tryParseJSON(trimmed).success) {\n return trimmed;\n }\n\n const codeBlockMatch = trimmed.match(/```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?\\s*```/);\n if (codeBlockMatch) {\n const inner = codeBlockMatch[1].trim();\n if (tryParseJSON(inner).success) {\n return inner;\n }\n }\n\n const firstBrace = trimmed.indexOf(\"{\");\n const lastBrace = trimmed.lastIndexOf(\"}\");\n if (firstBrace !== -1 && lastBrace > firstBrace) {\n const candidate = trimmed.slice(firstBrace, lastBrace + 1);\n if (tryParseJSON(candidate).success) {\n return candidate;\n }\n }\n\n const firstBracket = trimmed.indexOf(\"[\");\n const lastBracket = trimmed.lastIndexOf(\"]\");\n if (firstBracket !== -1 && lastBracket > firstBracket) {\n const candidate = trimmed.slice(firstBracket, lastBracket + 1);\n if (tryParseJSON(candidate).success) {\n return candidate;\n }\n }\n\n return null;\n}\n\nexport function repairJSON(raw: string): string | null {\n let candidate = raw.trim();\n\n candidate = candidate.replace(/,\\s*([}\\]])/g, \"$1\");\n\n candidate = candidate.replace(/'/g, '\"');\n\n candidate = candidate.replace(/(\\w+)\\s*:/g, '\"$1\":');\n\n candidate = candidate.replace(/:\\s*\"([^\"]*?)\"/g, (match, content) => {\n if (content.includes('\"')) {\n return match;\n }\n return match;\n });\n\n if (!candidate.startsWith(\"{\") && !candidate.startsWith(\"[\")) {\n const firstBrace = candidate.indexOf(\"{\");\n const firstBracket = candidate.indexOf(\"[\");\n if (firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket)) {\n candidate = candidate.slice(firstBrace);\n } else if (firstBracket !== -1) {\n candidate = candidate.slice(firstBracket);\n }\n }\n\n if (!candidate.endsWith(\"}\") && !candidate.endsWith(\"]\")) {\n const lastBrace = candidate.lastIndexOf(\"}\");\n const lastBracket = candidate.lastIndexOf(\"]\");\n if (lastBrace !== -1 && (lastBracket === -1 || lastBrace > lastBracket)) {\n candidate = candidate.slice(0, lastBrace + 1);\n } else if (lastBracket !== -1) {\n candidate = candidate.slice(0, lastBracket + 1);\n }\n }\n\n const result = tryParseJSON(candidate);\n if (result.success) {\n return candidate;\n }\n\n return null;\n}\n\nexport function validateAgainstSchema(data: unknown, schema: Record<string, { type: string; required?: boolean }>): { valid: true; data: unknown } | { valid: false; errors: string[] } {\n if (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n return { valid: false, errors: [\"Root value must be an object\"] };\n }\n\n const errors: string[] = [];\n const obj = data as Record<string, unknown>;\n\n for (const [key, field] of Object.entries(schema)) {\n const value = obj[key];\n\n if (value === undefined && field.required !== false) {\n errors.push(`Missing required field: \"${key}\"`);\n continue;\n }\n\n if (value === undefined) {\n continue;\n }\n\n switch (field.type) {\n case \"string\":\n if (typeof value !== \"string\") {\n errors.push(`Field \"${key}\" must be string, got ${typeof value}`);\n }\n break;\n case \"number\":\n if (typeof value !== \"number\") {\n errors.push(`Field \"${key}\" must be number, got ${typeof value}`);\n }\n break;\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n errors.push(`Field \"${key}\" must be boolean, got ${typeof value}`);\n }\n break;\n case \"array\":\n if (!Array.isArray(value)) {\n errors.push(`Field \"${key}\" must be array, got ${typeof value}`);\n }\n break;\n case \"object\":\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n errors.push(`Field \"${key}\" must be object, got ${typeof value}`);\n }\n break;\n }\n }\n\n if (errors.length > 0) {\n return { valid: false, errors };\n }\n\n return { valid: true, data };\n}\n","import { ExtractionSchema, SchemaField } from \"./types\";\n\nexport function defineSchema(name: string, fields: Record<string, SchemaField>): ExtractionSchema {\n return { name, fields };\n}\n\nexport function schemaToPrompt(schema: ExtractionSchema): string {\n const fieldDescriptions = Object.entries(schema.fields)\n .map(([key, field]) => {\n const parts = [`\"${key}\": ${fieldTypeToExample(field)}`];\n if (field.description) {\n parts.push(`// ${field.description}`);\n }\n return parts.join(\" \");\n })\n .join(\",\\n \");\n\n return `{\n \"${schema.name}\": {\n ${fieldDescriptions}\n }\n}`;\n}\n\nfunction fieldTypeToExample(field: SchemaField): string {\n switch (field.type) {\n case \"string\":\n return `\"...\"`;\n case \"number\":\n return \"0\";\n case \"boolean\":\n return \"true\";\n case \"array\":\n if (field.items) {\n return `[${fieldTypeToExample(field.items)}]`;\n }\n return \"[]\";\n case \"object\":\n if (field.properties) {\n const inner = Object.entries(field.properties)\n .map(([k, v]) => `\"${k}\": ${fieldTypeToExample(v)}`)\n .join(\", \");\n return `{ ${inner} }`;\n }\n return \"{}\";\n }\n}\n\nexport function schemaToZodishString(schema: ExtractionSchema): string {\n const lines: string[] = [];\n lines.push(`Expected JSON structure for \"${schema.name}\":`);\n\n for (const [key, field] of Object.entries(schema.fields)) {\n const required = field.required !== false ? \"(required)\" : \"(optional)\";\n lines.push(` - \"${key}\": ${field.type} ${required}${field.description ? ` - ${field.description}` : \"\"}`);\n }\n\n return lines.join(\"\\n\");\n}\n","import { ExtractionSchema, ExtractionOptions, ExtractionResult } from \"./types\";\nimport { callLLM, LLMClientConfig } from \"./llm-client\";\nimport { extractJSON, repairJSON, tryParseJSON, validateAgainstSchema } from \"./validator\";\nimport { schemaToPrompt, schemaToZodishString } from \"./schema\";\n\n\nconst MAX_REPAIR_ATTEMPTS = 3;\n\nfunction unwrapNamedResponse(data: unknown, schemaName: string): unknown {\n if (\n typeof data === \"object\" &&\n data !== null &&\n !Array.isArray(data) &&\n schemaName in data &&\n typeof (data as Record<string, unknown>)[schemaName] === \"object\"\n ) {\n return (data as Record<string, unknown>)[schemaName];\n }\n return data;\n}\n\nexport async function extract<T = Record<string, unknown>>(\n input: string,\n schema: ExtractionSchema,\n options: ExtractionOptions = {}\n): Promise<ExtractionResult<T>> {\n const config: LLMClientConfig = {\n apiKey: options.apiKey || process.env.OPENROUTER_API_KEY || \"\",\n model: options.model || \"openrouter/free\",\n temperature: options.temperature ?? 0,\n timeout: options.timeout ?? 30000,\n };\n\n if (!config.apiKey || config.apiKey.trim() === \"\") {\n throw new Error(\n \"OpenRouter API key required. Pass it in options or set OPENROUTER_API_KEY environment variable.\"\n );\n }\n\n const schemaDescription = schemaToZodishString(schema);\n const exampleJSON = schemaToPrompt(schema);\n\n const userPrompt = `Extract structured data from the following text.\n\n${schemaDescription}\n\nReturn ONLY valid JSON matching this structure:\n${exampleJSON}\n\nText to extract from:\n\"\"\"\n${input}\n\"\"\"`;\n\n const schemaFields: Record<string, { type: string; required?: boolean }> = {};\n for (const [key, field] of Object.entries(schema.fields)) {\n schemaFields[key] = { type: field.type, required: field.required };\n }\n\n let lastRaw = \"\";\n let lastError = \"\";\n\n for (let attempt = 0; attempt <= MAX_REPAIR_ATTEMPTS; attempt++) {\n const prompt =\n attempt === 0\n ? userPrompt\n : `${userPrompt}\n\nIMPORTANT: Your previous response was invalid JSON. Here was the error:\n${lastError}\n\nPrevious raw response:\n${lastRaw}\n\nFix the JSON and return ONLY valid JSON. No explanations, no markdown, just the raw JSON object.`;\n\n const response = await callLLM(prompt, config);\n lastRaw = response.content;\n\n const extracted = extractJSON(response.content);\n if (!extracted) {\n lastError = \"Could not extract JSON from response\";\n continue;\n }\n\n const parsed = tryParseJSON(extracted);\n if (!parsed.success) {\n lastError = parsed.error;\n continue;\n }\n\n const repaired = repairJSON(extracted);\n const finalData = repaired\n ? tryParseJSON(repaired).success\n ? JSON.parse(repaired)\n : parsed.data\n : parsed.data;\n\n const unwrapped = unwrapNamedResponse(finalData, schema.name);\n\n const validation = validateAgainstSchema(unwrapped, schemaFields);\n if (!validation.valid) {\n lastError = `Schema validation failed: ${validation.errors.join(\", \")}`;\n continue;\n }\n\n return {\n data: unwrapped as T,\n raw: response.content,\n model: response.model,\n usage: response.usage,\n };\n }\n\n throw new Error(\n `Failed to extract valid JSON after ${MAX_REPAIR_ATTEMPTS + 1} attempts. Last error: ${lastError}`\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/llm-client.ts","../src/validator.ts","../src/schema.ts","../src/extractor.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export interface LLMClientConfig {\n apiKey: string;\n model: string;\n temperature?: number;\n timeout?: number;\n}\n\nexport interface LLMResponse {\n content: string;\n model: string;\n usage?: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n };\n}\n\ninterface OpenRouterChoice {\n message?: {\n content?: string;\n };\n}\n\ninterface OpenRouterResponse {\n choices?: OpenRouterChoice[];\n model?: string;\n usage?: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n}\n\nconst DEFAULT_MODEL = \"openrouter/free\";\nconst DEFAULT_TEMPERATURE = 0;\nconst DEFAULT_TIMEOUT = 60000;\n\nexport async function callLLM(\n prompt: string,\n config: LLMClientConfig\n): Promise<LLMResponse> {\n const {\n apiKey,\n model = DEFAULT_MODEL,\n temperature = DEFAULT_TEMPERATURE,\n timeout = DEFAULT_TIMEOUT,\n } = config;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(\"https://openrouter.ai/api/v1/chat/completions\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n \"HTTP-Referer\": \"https://github.com/harshitduggal/structured-llm\",\n \"X-Title\": \"structured-llm\",\n },\n body: JSON.stringify({\n model,\n messages: [\n {\n role: \"system\",\n content: \"You are a precise data extraction assistant. You MUST respond with valid JSON only. No explanations, no markdown, no text outside the JSON. Just the raw JSON object.\",\n },\n {\n role: \"user\",\n content: prompt,\n },\n ],\n temperature,\n response_format: { type: \"json_object\" },\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n throw new Error(\n `OpenRouter API error: ${response.status} - ${errorBody}`\n );\n }\n\n const data = (await response.json()) as OpenRouterResponse;\n\n if (!data.choices || data.choices.length === 0) {\n throw new Error(\"No response from LLM\");\n }\n\n const content = data.choices[0].message?.content;\n if (!content) {\n throw new Error(\"Empty response from LLM\");\n }\n\n return {\n content,\n model: data.model || model,\n usage: data.usage\n ? {\n promptTokens: data.usage.prompt_tokens,\n completionTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined,\n };\n } finally {\n clearTimeout(timeoutId);\n }\n}\n","import { SchemaField, RepairAction } from \"./types\";\n\nexport function tryParseJSON(raw: string): { success: true; data: unknown } | { success: false; error: string } {\n try {\n const data = JSON.parse(raw);\n return { success: true, data };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : \"Unknown parse error\" };\n }\n}\n\nexport function extractJSON(raw: string): string | null {\n const trimmed = raw.trim();\n\n if (tryParseJSON(trimmed).success) {\n return trimmed;\n }\n\n const codeBlockMatch = trimmed.match(/```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?\\s*```/);\n if (codeBlockMatch) {\n const inner = codeBlockMatch[1].trim();\n if (tryParseJSON(inner).success) {\n return inner;\n }\n }\n\n const firstBrace = trimmed.indexOf(\"{\");\n const lastBrace = trimmed.lastIndexOf(\"}\");\n if (firstBrace !== -1 && lastBrace > firstBrace) {\n const candidate = trimmed.slice(firstBrace, lastBrace + 1);\n if (tryParseJSON(candidate).success) {\n return candidate;\n }\n }\n\n const firstBracket = trimmed.indexOf(\"[\");\n const lastBracket = trimmed.lastIndexOf(\"]\");\n if (firstBracket !== -1 && lastBracket > firstBracket) {\n const candidate = trimmed.slice(firstBracket, lastBracket + 1);\n if (tryParseJSON(candidate).success) {\n return candidate;\n }\n }\n\n return null;\n}\n\nexport function repairJSON(raw: string): string | null {\n let candidate = raw.trim();\n\n candidate = candidate.replace(/,\\s*([}\\]])/g, \"$1\");\n candidate = candidate.replace(/'/g, '\"');\n candidate = candidate.replace(/(\\w+)\\s*:/g, '\"$1\":');\n\n if (!candidate.startsWith(\"{\") && !candidate.startsWith(\"[\")) {\n const firstBrace = candidate.indexOf(\"{\");\n const firstBracket = candidate.indexOf(\"[\");\n if (firstBrace !== -1 && (firstBracket === -1 || firstBrace < firstBracket)) {\n candidate = candidate.slice(firstBrace);\n } else if (firstBracket !== -1) {\n candidate = candidate.slice(firstBracket);\n }\n }\n\n if (!candidate.endsWith(\"}\") && !candidate.endsWith(\"]\")) {\n const lastBrace = candidate.lastIndexOf(\"}\");\n const lastBracket = candidate.lastIndexOf(\"]\");\n if (lastBrace !== -1 && (lastBracket === -1 || lastBrace > lastBracket)) {\n candidate = candidate.slice(0, lastBrace + 1);\n } else if (lastBracket !== -1) {\n candidate = candidate.slice(0, lastBracket + 1);\n }\n }\n\n const result = tryParseJSON(candidate);\n if (result.success) {\n return candidate;\n }\n\n return null;\n}\n\nexport function coerceType(value: unknown, targetType: string): { value: unknown; coerced: boolean } {\n if (value === undefined || value === null) {\n return { value, coerced: false };\n }\n\n switch (targetType) {\n case \"string\":\n if (typeof value === \"string\") return { value, coerced: false };\n return { value: String(value), coerced: true };\n\n case \"number\":\n if (typeof value === \"number\") return { value, coerced: false };\n if (typeof value === \"string\") {\n const num = Number(value);\n if (!isNaN(num)) return { value: num, coerced: true };\n }\n return { value, coerced: false };\n\n case \"boolean\":\n if (typeof value === \"boolean\") return { value, coerced: false };\n if (typeof value === \"string\") {\n const lower = value.toLowerCase();\n if (lower === \"true\" || lower === \"yes\" || lower === \"1\") return { value: true, coerced: true };\n if (lower === \"false\" || lower === \"no\" || lower === \"0\") return { value: false, coerced: true };\n }\n if (typeof value === \"number\") {\n return { value: value !== 0, coerced: true };\n }\n return { value, coerced: false };\n\n case \"array\":\n if (Array.isArray(value)) return { value, coerced: false };\n return { value: [value], coerced: true };\n\n default:\n return { value, coerced: false };\n }\n}\n\nexport function repairData(data: unknown, fields: Record<string, SchemaField>, schemaName: string): { data: unknown; actions: RepairAction[] } {\n const actions: RepairAction[] = [];\n\n if (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n return { data, actions };\n }\n\n let obj = data as Record<string, unknown>;\n\n if (schemaName in obj && typeof obj[schemaName] === \"object\" && obj[schemaName] !== null) {\n actions.push({ attempt: 0, type: \"unwrap\", detail: `Unwrapped \"${schemaName}\" wrapper` });\n obj = obj[schemaName] as Record<string, unknown>;\n }\n\n for (const [key, field] of Object.entries(fields)) {\n if (obj[key] === undefined) {\n if (field.default !== undefined) {\n obj[key] = field.default;\n actions.push({ attempt: 0, type: \"default_fill\", detail: `Set \"${key}\" to default: ${JSON.stringify(field.default)}` });\n } else if (field.type === \"string\") {\n obj[key] = \"\";\n actions.push({ attempt: 0, type: \"missing_field\", detail: `Added empty string for \"${key}\"` });\n } else if (field.type === \"number\") {\n obj[key] = 0;\n actions.push({ attempt: 0, type: \"missing_field\", detail: `Added 0 for \"${key}\"` });\n } else if (field.type === \"boolean\") {\n obj[key] = false;\n actions.push({ attempt: 0, type: \"missing_field\", detail: `Added false for \"${key}\"` });\n } else if (field.type === \"array\") {\n obj[key] = [];\n actions.push({ attempt: 0, type: \"missing_field\", detail: `Added empty array for \"${key}\"` });\n } else if (field.type === \"object\") {\n obj[key] = {};\n actions.push({ attempt: 0, type: \"missing_field\", detail: `Added empty object for \"${key}\"` });\n }\n }\n\n if (obj[key] !== undefined) {\n const coerced = coerceType(obj[key], field.type);\n if (coerced.coerced) {\n obj[key] = coerced.value;\n actions.push({ attempt: 0, type: \"type_coercion\", detail: `Coerced \"${key}\" to ${field.type}: ${JSON.stringify(coerced.value)}` });\n }\n\n if (field.type === \"array\" && Array.isArray(obj[key]) && field.items) {\n obj[key] = (obj[key] as unknown[]).map((item, i) => {\n const itemResult = repairItem(item, field.items!);\n if (itemResult.actions.length > 0) {\n actions.push(...itemResult.actions.map(a => ({ ...a, detail: `[${i}] ${a.detail}` })));\n }\n return itemResult.data;\n });\n }\n\n if (field.type === \"object\" && typeof obj[key] === \"object\" && obj[key] !== null && field.properties) {\n const nested = repairData(obj[key], field.properties, \"\");\n if (nested.actions.length > 0) {\n actions.push(...nested.actions);\n }\n obj[key] = nested.data;\n }\n }\n }\n\n return { data: obj, actions };\n}\n\nfunction repairItem(item: unknown, field: SchemaField): { data: unknown; actions: RepairAction[] } {\n const actions: RepairAction[] = [];\n\n if (field.type === \"object\" && typeof item === \"object\" && item !== null && !Array.isArray(item) && field.properties) {\n const obj = item as Record<string, unknown>;\n for (const [key, prop] of Object.entries(field.properties)) {\n if (obj[key] === undefined) {\n if (prop.type === \"string\") {\n obj[key] = \"\";\n actions.push({ attempt: 0, type: \"missing_field\", detail: `Added empty string for \"${key}\"` });\n } else if (prop.type === \"number\") {\n obj[key] = 0;\n actions.push({ attempt: 0, type: \"missing_field\", detail: `Added 0 for \"${key}\"` });\n } else if (prop.type === \"boolean\") {\n obj[key] = false;\n actions.push({ attempt: 0, type: \"missing_field\", detail: `Added false for \"${key}\"` });\n } else if (prop.type === \"array\") {\n obj[key] = [];\n actions.push({ attempt: 0, type: \"missing_field\", detail: `Added empty array for \"${key}\"` });\n }\n }\n\n if (obj[key] !== undefined) {\n const coerced = coerceType(obj[key], prop.type);\n if (coerced.coerced) {\n obj[key] = coerced.value;\n actions.push({ attempt: 0, type: \"type_coercion\", detail: `Coerced \"${key}\" to ${prop.type}` });\n }\n }\n }\n }\n\n return { data: item, actions };\n}\n\nexport function validateAgainstSchema(data: unknown, schema: Record<string, SchemaField>): { valid: true; data: unknown } | { valid: false; errors: string[] } {\n if (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n return { valid: false, errors: [\"Root value must be an object\"] };\n }\n\n const errors: string[] = [];\n const obj = data as Record<string, unknown>;\n\n for (const [key, field] of Object.entries(schema)) {\n const value = obj[key];\n\n if (value === undefined && field.required !== false) {\n errors.push(`Missing required field: \"${key}\"`);\n continue;\n }\n\n if (value === undefined) {\n continue;\n }\n\n switch (field.type) {\n case \"string\":\n if (typeof value !== \"string\") {\n errors.push(`Field \"${key}\" must be string, got ${typeof value}`);\n }\n break;\n case \"number\":\n if (typeof value !== \"number\") {\n errors.push(`Field \"${key}\" must be number, got ${typeof value}`);\n }\n break;\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n errors.push(`Field \"${key}\" must be boolean, got ${typeof value}`);\n }\n break;\n case \"array\":\n if (!Array.isArray(value)) {\n errors.push(`Field \"${key}\" must be array, got ${typeof value}`);\n }\n break;\n case \"object\":\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n errors.push(`Field \"${key}\" must be object, got ${typeof value}`);\n }\n break;\n }\n }\n\n if (errors.length > 0) {\n return { valid: false, errors };\n }\n\n return { valid: true, data };\n}\n","import { ExtractionSchema, SchemaField } from \"./types\";\n\nexport function defineSchema(name: string, fields: Record<string, SchemaField>): ExtractionSchema {\n return { name, fields };\n}\n\nfunction schemaToJSONExample(fields: Record<string, SchemaField>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, field] of Object.entries(fields)) {\n switch (field.type) {\n case \"string\":\n result[key] = field.description || \"...\";\n break;\n case \"number\":\n result[key] = 0;\n break;\n case \"boolean\":\n result[key] = true;\n break;\n case \"array\":\n if (field.items) {\n result[key] = [schemaToJSONExample(field.items.properties || {})];\n } else {\n result[key] = [];\n }\n break;\n case \"object\":\n if (field.properties) {\n result[key] = schemaToJSONExample(field.properties);\n } else {\n result[key] = {};\n }\n break;\n }\n }\n return result;\n}\n\nexport function buildForcedPrompt(input: string, schema: ExtractionSchema): string {\n const example = schemaToJSONExample(schema.fields);\n const exampleStr = JSON.stringify({ [schema.name]: example }, null, 2);\n\n return `TASK: Extract structured data from the text below into EXACTLY this JSON format.\n\nCRITICAL RULES:\n- Output ONLY valid JSON. No text before or after.\n- No markdown. No code blocks. No explanations.\n- Every field MUST be present with the correct type.\n- String fields: use \"\" if unknown.\n- Number fields: use 0 if unknown.\n- Boolean fields: use true or false, never null.\n- Array fields: use [] if empty, never null.\n- Object fields: use {} if empty, never null.\n\nREQUIRED JSON STRUCTURE:\n${exampleStr}\n\nTEXT TO EXTRACT FROM:\n\"\"\"\n${input}\n\"\"\"\n\nOUTPUT ONLY THE JSON OBJECT. NOTHING ELSE.`;\n}\n\nexport function buildRetryPrompt(\n input: string,\n schema: ExtractionSchema,\n previousResponse: string,\n error: string\n): string {\n const example = schemaToJSONExample(schema.fields);\n const exampleStr = JSON.stringify({ [schema.name]: example }, null, 2);\n\n return `YOUR PREVIOUS RESPONSE WAS INVALID. You MUST fix it.\n\nERROR: ${error}\n\nYOUR PREVIOUS RESPONSE:\n${previousResponse.slice(0, 1000)}\n\nWHAT YOU MUST DO NOW:\n1. Output ONLY valid JSON matching this EXACT structure\n2. No text before or after the JSON\n3. No markdown, no code blocks, no explanations\n4. Fix the errors listed above\n5. Every field MUST be present\n\nREQUIRED JSON STRUCTURE:\n${exampleStr}\n\nTEXT TO EXTRACT FROM:\n\"\"\"\n${input}\n\"\"\"\n\nOUTPUT ONLY THE JSON OBJECT. NOTHING ELSE.`;\n}\n\nexport function buildFinalPrompt(\n input: string,\n schema: ExtractionSchema,\n previousResponse: string,\n error: string\n): string {\n const example = schemaToJSONExample(schema.fields);\n const exampleStr = JSON.stringify({ [schema.name]: example }, null, 2);\n\n return `FINAL ATTEMPT. THIS IS YOUR LAST CHANCE.\n\nYOUR PREVIOUS RESPONSE FAILED VALIDATION:\n${error}\n\nYOUR PREVIOUS RESPONSE:\n${previousResponse.slice(0, 800)}\n\nYOU MUST OUTPUT EXACTLY THIS STRUCTURE. NOTHING MORE. NOTHING LESS.\nDO NOT ADD FIELDS THAT ARE NOT IN THE SCHEMA.\nDO NOT OMIT ANY FIELDS.\nDO NOT WRAP IN markdown OR code blocks.\nDO NOT ADD ANY TEXT BEFORE OR AFTER THE JSON.\n\nSTRUCTURE:\n${exampleStr}\n\nINPUT TEXT:\n\"\"\"\n${input}\n\"\"\"\n\nOUTPUT ONLY:\n`;\n}\n\nexport function schemaToPrompt(schema: ExtractionSchema): string {\n const example = schemaToJSONExample(schema.fields);\n return JSON.stringify({ [schema.name]: example }, null, 2);\n}\n\nexport function schemaToZodishString(schema: ExtractionSchema): string {\n const lines: string[] = [];\n lines.push(`Expected JSON structure for \"${schema.name}\":`);\n\n for (const [key, field] of Object.entries(schema.fields)) {\n const required = field.required !== false ? \"(required)\" : \"(optional)\";\n lines.push(` - \"${key}\": ${field.type} ${required}${field.description ? ` - ${field.description}` : \"\"}`);\n }\n\n return lines.join(\"\\n\");\n}\n","import { ExtractionSchema, ExtractionOptions, ExtractionResult, RepairAction, SchemaField } from \"./types\";\nimport { callLLM, LLMClientConfig } from \"./llm-client\";\nimport { extractJSON, repairJSON, tryParseJSON, validateAgainstSchema, repairData } from \"./validator\";\nimport { buildForcedPrompt, buildRetryPrompt, buildFinalPrompt } from \"./schema\";\n\nconst MAX_REPAIR_ATTEMPTS = 3;\n\nfunction calculateConfidence(\n attempts: number,\n repairActions: RepairAction[],\n jsonValidFirstTry: boolean\n): number {\n let score = 100;\n\n if (!jsonValidFirstTry) {\n score -= 15;\n }\n\n score -= (attempts - 1) * 10;\n\n score -= repairActions.filter(a => a.type === \"type_coercion\").length * 5;\n score -= repairActions.filter(a => a.type === \"missing_field\").length * 8;\n score -= repairActions.filter(a => a.type === \"default_fill\").length * 3;\n\n return Math.max(0, Math.min(100, score));\n}\n\nexport async function extract<T = Record<string, unknown>>(\n input: string,\n schema: ExtractionSchema,\n options: ExtractionOptions = {}\n): Promise<ExtractionResult<T>> {\n const config: LLMClientConfig = {\n apiKey: options.apiKey || process.env.OPENROUTER_API_KEY || \"\",\n model: options.model || \"openrouter/free\",\n temperature: options.temperature ?? 0,\n timeout: options.timeout ?? 30000,\n };\n\n if (!config.apiKey || config.apiKey.trim() === \"\") {\n throw new Error(\n \"OpenRouter API key required. Pass it in options or set OPENROUTER_API_KEY environment variable.\"\n );\n }\n\n const allRepairActions: RepairAction[] = [];\n let lastRaw = \"\";\n let lastError = \"\";\n let jsonValidFirstTry = false;\n let successAttempt = 0;\n\n for (let attempt = 0; attempt <= MAX_REPAIR_ATTEMPTS; attempt++) {\n let prompt: string;\n\n if (attempt === 0) {\n prompt = buildForcedPrompt(input, schema);\n } else if (attempt === 1) {\n prompt = buildRetryPrompt(input, schema, lastRaw, lastError);\n } else {\n prompt = buildFinalPrompt(input, schema, lastRaw, lastError);\n }\n\n const response = await callLLM(prompt, config);\n lastRaw = response.content;\n\n const extracted = extractJSON(response.content);\n if (!extracted) {\n lastError = \"Could not extract JSON from response. Your response contained no valid JSON.\";\n continue;\n }\n\n const parsed = tryParseJSON(extracted);\n if (!parsed.success) {\n lastError = `Invalid JSON: ${parsed.error}`;\n continue;\n }\n\n if (attempt === 0) {\n jsonValidFirstTry = true;\n }\n\n const repaired = repairJSON(extracted);\n let finalData = repaired\n ? tryParseJSON(repaired).success\n ? JSON.parse(repaired)\n : parsed.data\n : parsed.data;\n\n const repairResult = repairData(finalData, schema.fields, schema.name);\n finalData = repairResult.data;\n allRepairActions.push(...repairResult.actions);\n\n const schemaFields: Record<string, SchemaField> = {};\n for (const [key, field] of Object.entries(schema.fields)) {\n schemaFields[key] = field;\n }\n\n const validation = validateAgainstSchema(finalData, schemaFields);\n if (!validation.valid) {\n lastError = `Schema validation failed: ${validation.errors.join(\"; \")}`;\n allRepairActions.push({\n attempt,\n type: \"type_coercion\",\n detail: `Validation failed: ${validation.errors.join(\"; \")}`,\n });\n continue;\n }\n\n successAttempt = attempt + 1;\n\n return {\n data: finalData as T,\n raw: response.content,\n model: response.model,\n confidence: calculateConfidence(successAttempt, allRepairActions, jsonValidFirstTry),\n repairLog: allRepairActions,\n attempts: successAttempt,\n usage: response.usage,\n };\n }\n\n throw new Error(\n `Failed to extract valid JSON after ${MAX_REPAIR_ATTEMPTS + 1} attempts. Last error: ${lastError}`\n );\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -6,6 +6,7 @@ type SchemaField = {
|
|
|
6
6
|
type: "string" | "number" | "boolean" | "array" | "object";
|
|
7
7
|
description?: string;
|
|
8
8
|
required?: boolean;
|
|
9
|
+
default?: unknown;
|
|
9
10
|
items?: SchemaField;
|
|
10
11
|
properties?: Record<string, SchemaField>;
|
|
11
12
|
};
|
|
@@ -20,6 +21,9 @@ interface ExtractionResult<T> {
|
|
|
20
21
|
data: T;
|
|
21
22
|
raw: string;
|
|
22
23
|
model: string;
|
|
24
|
+
confidence: number;
|
|
25
|
+
repairLog: RepairAction[];
|
|
26
|
+
attempts: number;
|
|
23
27
|
usage?: {
|
|
24
28
|
promptTokens: number;
|
|
25
29
|
completionTokens: number;
|
|
@@ -32,6 +36,11 @@ interface ExtractionError {
|
|
|
32
36
|
raw?: string;
|
|
33
37
|
attempts: number;
|
|
34
38
|
}
|
|
39
|
+
interface RepairAction {
|
|
40
|
+
attempt: number;
|
|
41
|
+
type: "unwrap" | "json_repair" | "type_coercion" | "default_fill" | "missing_field";
|
|
42
|
+
detail: string;
|
|
43
|
+
}
|
|
35
44
|
|
|
36
45
|
declare function extract<T = Record<string, unknown>>(input: string, schema: ExtractionSchema, options?: ExtractionOptions): Promise<ExtractionResult<T>>;
|
|
37
46
|
|
|
@@ -48,10 +57,15 @@ declare function tryParseJSON(raw: string): {
|
|
|
48
57
|
};
|
|
49
58
|
declare function extractJSON(raw: string): string | null;
|
|
50
59
|
declare function repairJSON(raw: string): string | null;
|
|
51
|
-
declare function
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
60
|
+
declare function coerceType(value: unknown, targetType: string): {
|
|
61
|
+
value: unknown;
|
|
62
|
+
coerced: boolean;
|
|
63
|
+
};
|
|
64
|
+
declare function repairData(data: unknown, fields: Record<string, SchemaField>, schemaName: string): {
|
|
65
|
+
data: unknown;
|
|
66
|
+
actions: RepairAction[];
|
|
67
|
+
};
|
|
68
|
+
declare function validateAgainstSchema(data: unknown, schema: Record<string, SchemaField>): {
|
|
55
69
|
valid: true;
|
|
56
70
|
data: unknown;
|
|
57
71
|
} | {
|
|
@@ -59,4 +73,4 @@ declare function validateAgainstSchema(data: unknown, schema: Record<string, {
|
|
|
59
73
|
errors: string[];
|
|
60
74
|
};
|
|
61
75
|
|
|
62
|
-
export { type ExtractionError, type ExtractionOptions, type ExtractionResult, type ExtractionSchema, type SchemaField, defineSchema, extract, extractJSON, repairJSON, schemaToPrompt, schemaToZodishString, tryParseJSON, validateAgainstSchema };
|
|
76
|
+
export { type ExtractionError, type ExtractionOptions, type ExtractionResult, type ExtractionSchema, type RepairAction, type SchemaField, coerceType, defineSchema, extract, extractJSON, repairData, repairJSON, schemaToPrompt, schemaToZodishString, tryParseJSON, validateAgainstSchema };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ type SchemaField = {
|
|
|
6
6
|
type: "string" | "number" | "boolean" | "array" | "object";
|
|
7
7
|
description?: string;
|
|
8
8
|
required?: boolean;
|
|
9
|
+
default?: unknown;
|
|
9
10
|
items?: SchemaField;
|
|
10
11
|
properties?: Record<string, SchemaField>;
|
|
11
12
|
};
|
|
@@ -20,6 +21,9 @@ interface ExtractionResult<T> {
|
|
|
20
21
|
data: T;
|
|
21
22
|
raw: string;
|
|
22
23
|
model: string;
|
|
24
|
+
confidence: number;
|
|
25
|
+
repairLog: RepairAction[];
|
|
26
|
+
attempts: number;
|
|
23
27
|
usage?: {
|
|
24
28
|
promptTokens: number;
|
|
25
29
|
completionTokens: number;
|
|
@@ -32,6 +36,11 @@ interface ExtractionError {
|
|
|
32
36
|
raw?: string;
|
|
33
37
|
attempts: number;
|
|
34
38
|
}
|
|
39
|
+
interface RepairAction {
|
|
40
|
+
attempt: number;
|
|
41
|
+
type: "unwrap" | "json_repair" | "type_coercion" | "default_fill" | "missing_field";
|
|
42
|
+
detail: string;
|
|
43
|
+
}
|
|
35
44
|
|
|
36
45
|
declare function extract<T = Record<string, unknown>>(input: string, schema: ExtractionSchema, options?: ExtractionOptions): Promise<ExtractionResult<T>>;
|
|
37
46
|
|
|
@@ -48,10 +57,15 @@ declare function tryParseJSON(raw: string): {
|
|
|
48
57
|
};
|
|
49
58
|
declare function extractJSON(raw: string): string | null;
|
|
50
59
|
declare function repairJSON(raw: string): string | null;
|
|
51
|
-
declare function
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
60
|
+
declare function coerceType(value: unknown, targetType: string): {
|
|
61
|
+
value: unknown;
|
|
62
|
+
coerced: boolean;
|
|
63
|
+
};
|
|
64
|
+
declare function repairData(data: unknown, fields: Record<string, SchemaField>, schemaName: string): {
|
|
65
|
+
data: unknown;
|
|
66
|
+
actions: RepairAction[];
|
|
67
|
+
};
|
|
68
|
+
declare function validateAgainstSchema(data: unknown, schema: Record<string, SchemaField>): {
|
|
55
69
|
valid: true;
|
|
56
70
|
data: unknown;
|
|
57
71
|
} | {
|
|
@@ -59,4 +73,4 @@ declare function validateAgainstSchema(data: unknown, schema: Record<string, {
|
|
|
59
73
|
errors: string[];
|
|
60
74
|
};
|
|
61
75
|
|
|
62
|
-
export { type ExtractionError, type ExtractionOptions, type ExtractionResult, type ExtractionSchema, type SchemaField, defineSchema, extract, extractJSON, repairJSON, schemaToPrompt, schemaToZodishString, tryParseJSON, validateAgainstSchema };
|
|
76
|
+
export { type ExtractionError, type ExtractionOptions, type ExtractionResult, type ExtractionSchema, type RepairAction, type SchemaField, coerceType, defineSchema, extract, extractJSON, repairData, repairJSON, schemaToPrompt, schemaToZodishString, tryParseJSON, validateAgainstSchema };
|