@claritylabs/cl-sdk 0.10.3 → 0.12.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 +50 -2
- package/dist/index.d.mts +69 -11
- package/dist/index.d.ts +69 -11
- package/dist/index.js +960 -325
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +956 -325
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -6
package/dist/index.mjs
CHANGED
|
@@ -1575,6 +1575,358 @@ async function runExtractor(params) {
|
|
|
1575
1575
|
};
|
|
1576
1576
|
}
|
|
1577
1577
|
|
|
1578
|
+
// src/extraction/promote.ts
|
|
1579
|
+
function getDeclarationFields(doc) {
|
|
1580
|
+
const decl = doc.declarations;
|
|
1581
|
+
return Array.isArray(decl?.fields) ? decl.fields : [];
|
|
1582
|
+
}
|
|
1583
|
+
function fieldMatches(fieldName, patterns) {
|
|
1584
|
+
const lower = fieldName.toLowerCase().replace(/[\s_-]/g, "");
|
|
1585
|
+
return patterns.some((p) => lower === p.toLowerCase().replace(/[\s_-]/g, ""));
|
|
1586
|
+
}
|
|
1587
|
+
function findFieldValue(fields, patterns) {
|
|
1588
|
+
const match = fields.find((f) => fieldMatches(f.field, patterns));
|
|
1589
|
+
return match?.value;
|
|
1590
|
+
}
|
|
1591
|
+
function promoteCarrierFields(doc) {
|
|
1592
|
+
const raw = doc;
|
|
1593
|
+
if (!raw.carrierNaicNumber && raw.naicNumber) {
|
|
1594
|
+
raw.carrierNaicNumber = raw.naicNumber;
|
|
1595
|
+
}
|
|
1596
|
+
if (!raw.carrierAmBestRating && raw.amBestRating) {
|
|
1597
|
+
raw.carrierAmBestRating = raw.amBestRating;
|
|
1598
|
+
}
|
|
1599
|
+
if (!raw.carrierAdmittedStatus && raw.admittedStatus) {
|
|
1600
|
+
raw.carrierAdmittedStatus = raw.admittedStatus;
|
|
1601
|
+
}
|
|
1602
|
+
delete raw.naicNumber;
|
|
1603
|
+
delete raw.amBestRating;
|
|
1604
|
+
delete raw.admittedStatus;
|
|
1605
|
+
if (!raw.insurer && raw.carrierLegalName) {
|
|
1606
|
+
raw.insurer = {
|
|
1607
|
+
legalName: raw.carrierLegalName,
|
|
1608
|
+
...raw.carrierNaicNumber ? { naicNumber: raw.carrierNaicNumber } : {},
|
|
1609
|
+
...raw.carrierAmBestRating ? { amBestRating: raw.carrierAmBestRating } : {},
|
|
1610
|
+
...raw.carrierAdmittedStatus ? { admittedStatus: raw.carrierAdmittedStatus } : {}
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
var BROKER_NAME_PATTERNS = [
|
|
1615
|
+
"brokerName",
|
|
1616
|
+
"broker",
|
|
1617
|
+
"agentName",
|
|
1618
|
+
"agent",
|
|
1619
|
+
"producerName",
|
|
1620
|
+
"producerAgency",
|
|
1621
|
+
"agencyName",
|
|
1622
|
+
"brokerAgency"
|
|
1623
|
+
];
|
|
1624
|
+
var BROKER_CONTACT_PATTERNS = [
|
|
1625
|
+
"brokerContactName",
|
|
1626
|
+
"brokerContact",
|
|
1627
|
+
"agentContactName",
|
|
1628
|
+
"producerContactName",
|
|
1629
|
+
"producerContact"
|
|
1630
|
+
];
|
|
1631
|
+
var BROKER_LICENSE_PATTERNS = [
|
|
1632
|
+
"brokerLicenseNumber",
|
|
1633
|
+
"brokerNumber",
|
|
1634
|
+
"agentLicenseNumber",
|
|
1635
|
+
"producerLicenseNumber",
|
|
1636
|
+
"producerNumber",
|
|
1637
|
+
"agentNumber"
|
|
1638
|
+
];
|
|
1639
|
+
var BROKER_PHONE_PATTERNS = ["brokerPhone", "agentPhone", "producerPhone"];
|
|
1640
|
+
var BROKER_EMAIL_PATTERNS = ["brokerEmail", "agentEmail", "producerEmail"];
|
|
1641
|
+
var BROKER_ADDRESS_PATTERNS = ["brokerAddress", "agentAddress", "producerAddress"];
|
|
1642
|
+
function promoteBroker(doc) {
|
|
1643
|
+
const raw = doc;
|
|
1644
|
+
const fields = getDeclarationFields(doc);
|
|
1645
|
+
const brokerAgency = raw.brokerAgency || findFieldValue(fields, BROKER_NAME_PATTERNS);
|
|
1646
|
+
const brokerContact = raw.brokerContactName || findFieldValue(fields, BROKER_CONTACT_PATTERNS);
|
|
1647
|
+
const brokerLicense = raw.brokerLicenseNumber || findFieldValue(fields, BROKER_LICENSE_PATTERNS);
|
|
1648
|
+
const brokerPhone = findFieldValue(fields, BROKER_PHONE_PATTERNS);
|
|
1649
|
+
const brokerEmail = findFieldValue(fields, BROKER_EMAIL_PATTERNS);
|
|
1650
|
+
const brokerAddress = findFieldValue(fields, BROKER_ADDRESS_PATTERNS);
|
|
1651
|
+
if (brokerAgency) raw.brokerAgency = brokerAgency;
|
|
1652
|
+
if (brokerContact) raw.brokerContactName = brokerContact;
|
|
1653
|
+
if (brokerLicense) raw.brokerLicenseNumber = brokerLicense;
|
|
1654
|
+
if (!raw.producer && brokerAgency) {
|
|
1655
|
+
raw.producer = {
|
|
1656
|
+
agencyName: brokerAgency,
|
|
1657
|
+
...brokerContact ? { contactName: brokerContact } : {},
|
|
1658
|
+
...brokerLicense ? { licenseNumber: brokerLicense } : {},
|
|
1659
|
+
...brokerPhone ? { phone: brokerPhone } : {},
|
|
1660
|
+
...brokerEmail ? { email: brokerEmail } : {},
|
|
1661
|
+
...brokerAddress ? { address: { street1: brokerAddress } } : {}
|
|
1662
|
+
};
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
var LOSS_PAYEE_NAME_PATTERNS = [
|
|
1666
|
+
"lossPayeeName",
|
|
1667
|
+
"lossPayee",
|
|
1668
|
+
"lossPayeeHolder"
|
|
1669
|
+
];
|
|
1670
|
+
var LOSS_PAYEE_ADDRESS_PATTERNS = ["lossPayeeAddress"];
|
|
1671
|
+
var MORTGAGE_HOLDER_NAME_PATTERNS = [
|
|
1672
|
+
"mortgagee",
|
|
1673
|
+
"mortgageHolder",
|
|
1674
|
+
"mortgageHolderName",
|
|
1675
|
+
"mortgageeName",
|
|
1676
|
+
"lienholder",
|
|
1677
|
+
"lienholderName"
|
|
1678
|
+
];
|
|
1679
|
+
var MORTGAGE_HOLDER_ADDRESS_PATTERNS = [
|
|
1680
|
+
"mortgageeAddress",
|
|
1681
|
+
"mortgageHolderAddress",
|
|
1682
|
+
"lienholderAddress"
|
|
1683
|
+
];
|
|
1684
|
+
function promoteLossPayees(doc) {
|
|
1685
|
+
const raw = doc;
|
|
1686
|
+
const fields = getDeclarationFields(doc);
|
|
1687
|
+
if (!raw.lossPayees || Array.isArray(raw.lossPayees) && raw.lossPayees.length === 0) {
|
|
1688
|
+
const name = findFieldValue(fields, LOSS_PAYEE_NAME_PATTERNS);
|
|
1689
|
+
if (name) {
|
|
1690
|
+
const address = findFieldValue(fields, LOSS_PAYEE_ADDRESS_PATTERNS);
|
|
1691
|
+
raw.lossPayees = [{
|
|
1692
|
+
name,
|
|
1693
|
+
role: "loss_payee",
|
|
1694
|
+
...address ? { address: { street1: address } } : {}
|
|
1695
|
+
}];
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
if (!raw.mortgageHolders || Array.isArray(raw.mortgageHolders) && raw.mortgageHolders.length === 0) {
|
|
1699
|
+
const name = findFieldValue(fields, MORTGAGE_HOLDER_NAME_PATTERNS);
|
|
1700
|
+
if (name) {
|
|
1701
|
+
const address = findFieldValue(fields, MORTGAGE_HOLDER_ADDRESS_PATTERNS);
|
|
1702
|
+
raw.mortgageHolders = [{
|
|
1703
|
+
name,
|
|
1704
|
+
role: "mortgage_holder",
|
|
1705
|
+
...address ? { address: { street1: address } } : {}
|
|
1706
|
+
}];
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
function promoteLocations(doc) {
|
|
1711
|
+
const raw = doc;
|
|
1712
|
+
if (Array.isArray(raw.locations) && raw.locations.length > 0) return;
|
|
1713
|
+
const fields = getDeclarationFields(doc);
|
|
1714
|
+
if (fields.length === 0) return;
|
|
1715
|
+
const locationGroups = /* @__PURE__ */ new Map();
|
|
1716
|
+
for (const f of fields) {
|
|
1717
|
+
const lower = f.field.toLowerCase().replace(/[\s_-]/g, "");
|
|
1718
|
+
if (lower.includes("locationnumber") || lower.includes("locnumber") || lower.includes("locno")) {
|
|
1719
|
+
const key = f.value;
|
|
1720
|
+
if (!locationGroups.has(key)) locationGroups.set(key, /* @__PURE__ */ new Map());
|
|
1721
|
+
locationGroups.get(key).set("number", f.value);
|
|
1722
|
+
continue;
|
|
1723
|
+
}
|
|
1724
|
+
if (lower.includes("buildingnumber") || lower.includes("bldgnumber") || lower.includes("bldgno")) {
|
|
1725
|
+
const lastKey2 = [...locationGroups.keys()].pop();
|
|
1726
|
+
if (lastKey2) locationGroups.get(lastKey2).set("buildingNumber", f.value);
|
|
1727
|
+
continue;
|
|
1728
|
+
}
|
|
1729
|
+
const section = (f.section ?? "").toLowerCase();
|
|
1730
|
+
const isLocationField = section.includes("location") || section.includes("building") || section.includes("premises") || section.includes("schedule of locations");
|
|
1731
|
+
if (!isLocationField) continue;
|
|
1732
|
+
if (locationGroups.size === 0) {
|
|
1733
|
+
locationGroups.set("1", /* @__PURE__ */ new Map([["number", "1"]]));
|
|
1734
|
+
}
|
|
1735
|
+
const lastKey = [...locationGroups.keys()].pop();
|
|
1736
|
+
const group = locationGroups.get(lastKey);
|
|
1737
|
+
if (lower.includes("construction") || lower.includes("constructiontype")) {
|
|
1738
|
+
group.set("constructionType", f.value);
|
|
1739
|
+
} else if (lower.includes("occupancy") || lower.includes("occupancytype")) {
|
|
1740
|
+
group.set("occupancy", f.value);
|
|
1741
|
+
} else if (lower.includes("yearbuilt")) {
|
|
1742
|
+
group.set("yearBuilt", f.value);
|
|
1743
|
+
} else if (lower.includes("squarefootage") || lower.includes("sqft") || lower.includes("area")) {
|
|
1744
|
+
group.set("squareFootage", f.value);
|
|
1745
|
+
} else if (lower.includes("protectionclass") || lower.includes("fireprotection")) {
|
|
1746
|
+
group.set("protectionClass", f.value);
|
|
1747
|
+
} else if (lower.includes("sprinkler")) {
|
|
1748
|
+
group.set("sprinklered", f.value);
|
|
1749
|
+
} else if (lower.includes("buildingvalue") || lower.includes("buildingamt") || lower.includes("buildingcoverage")) {
|
|
1750
|
+
group.set("buildingValue", f.value);
|
|
1751
|
+
} else if (lower.includes("contentsvalue") || lower.includes("contentsamt") || lower.includes("contentscoverage")) {
|
|
1752
|
+
group.set("contentsValue", f.value);
|
|
1753
|
+
} else if (lower.includes("businessincome") || lower.includes("bivalue") || lower.includes("businessincomevalue")) {
|
|
1754
|
+
group.set("businessIncomeValue", f.value);
|
|
1755
|
+
} else if (lower.includes("description") || lower.includes("buildingdescription") || lower.includes("locationdescription")) {
|
|
1756
|
+
group.set("description", f.value);
|
|
1757
|
+
} else if (lower.includes("address") || lower.includes("industryaddress") || lower.includes("locationaddress") || lower.includes("premisesaddress")) {
|
|
1758
|
+
group.set("address", f.value);
|
|
1759
|
+
} else if (lower.includes("alarm") || lower.includes("alarmtype")) {
|
|
1760
|
+
group.set("alarmType", f.value);
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
if (locationGroups.size === 0) return;
|
|
1764
|
+
const locations = [];
|
|
1765
|
+
for (const [, group] of locationGroups) {
|
|
1766
|
+
const num = parseInt(group.get("number") ?? "0", 10) || locations.length + 1;
|
|
1767
|
+
const addressStr = group.get("address");
|
|
1768
|
+
locations.push({
|
|
1769
|
+
number: num,
|
|
1770
|
+
address: addressStr ? { street1: addressStr } : { street1: "See declarations" },
|
|
1771
|
+
...group.get("description") ? { description: group.get("description") } : {},
|
|
1772
|
+
...group.get("constructionType") ? { constructionType: group.get("constructionType") } : {},
|
|
1773
|
+
...group.get("occupancy") ? { occupancy: group.get("occupancy") } : {},
|
|
1774
|
+
...group.get("yearBuilt") ? { yearBuilt: parseInt(group.get("yearBuilt"), 10) || void 0 } : {},
|
|
1775
|
+
...group.get("squareFootage") ? { squareFootage: parseInt(group.get("squareFootage").replace(/[^0-9]/g, ""), 10) || void 0 } : {},
|
|
1776
|
+
...group.get("protectionClass") ? { protectionClass: group.get("protectionClass") } : {},
|
|
1777
|
+
...group.get("sprinklered") ? { sprinklered: /yes|true/i.test(group.get("sprinklered")) } : {},
|
|
1778
|
+
...group.get("buildingValue") ? { buildingValue: group.get("buildingValue") } : {},
|
|
1779
|
+
...group.get("contentsValue") ? { contentsValue: group.get("contentsValue") } : {},
|
|
1780
|
+
...group.get("businessIncomeValue") ? { businessIncomeValue: group.get("businessIncomeValue") } : {},
|
|
1781
|
+
...group.get("alarmType") ? { alarmType: group.get("alarmType") } : {}
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
if (locations.length > 0) {
|
|
1785
|
+
raw.locations = locations;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
function normalizeName(name) {
|
|
1789
|
+
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1790
|
+
}
|
|
1791
|
+
var LIMIT_COVERAGE_MAP = [
|
|
1792
|
+
// GL standard
|
|
1793
|
+
[["eachoccurrence", "peroccurrence", "occurrencecombined"], "perOccurrence"],
|
|
1794
|
+
[["generalaggregate"], "generalAggregate"],
|
|
1795
|
+
[["productscompletedoperationsaggregate", "productscompletedopsaggregate", "prodcompopsagg"], "productsCompletedOpsAggregate"],
|
|
1796
|
+
[["personaladvertisinginjury", "personaladvinjury", "pai"], "personalAdvertisingInjury"],
|
|
1797
|
+
[["firedamage", "firedamagelegalliability", "damagetorentedpremises", "damagetopremisesrentedtoyou"], "fireDamage"],
|
|
1798
|
+
[["medicalexpense", "medexp", "medicalexpenseanypersonanyperson", "medicalexpenseanyone"], "medicalExpense"],
|
|
1799
|
+
// Auto
|
|
1800
|
+
[["combinedsingle", "combinedsinglelimit", "csl"], "combinedSingleLimit"],
|
|
1801
|
+
[["bodilyinjuryperperson", "biperperson"], "bodilyInjuryPerPerson"],
|
|
1802
|
+
[["bodilyinjuryperaccident", "biperaccident"], "bodilyInjuryPerAccident"],
|
|
1803
|
+
[["propertydamage", "pdperaccident"], "propertyDamage"],
|
|
1804
|
+
// Umbrella/Excess
|
|
1805
|
+
[["umbrellaoccurrence", "eachoccurrenceumbrella", "excessoccurrence", "excesseachoccurrence"], "eachOccurrenceUmbrella"],
|
|
1806
|
+
[["umbrellaaggregate", "excessaggregate"], "umbrellaAggregate"],
|
|
1807
|
+
[["umbrella retention", "selfinsuredretention", "sir", "excessretention"], "umbrellaRetention"]
|
|
1808
|
+
];
|
|
1809
|
+
function synthesizeLimits(doc) {
|
|
1810
|
+
const raw = doc;
|
|
1811
|
+
if (raw.limits && typeof raw.limits === "object" && Object.keys(raw.limits).length > 0) return;
|
|
1812
|
+
const coverages = doc.coverages;
|
|
1813
|
+
if (!coverages || coverages.length === 0) return;
|
|
1814
|
+
const limits = {};
|
|
1815
|
+
for (const cov of coverages) {
|
|
1816
|
+
if (!cov.name || !cov.limit) continue;
|
|
1817
|
+
const normalized = normalizeName(cov.name);
|
|
1818
|
+
for (const [patterns, fieldName] of LIMIT_COVERAGE_MAP) {
|
|
1819
|
+
if (patterns.some((p) => normalized.includes(p) || p.includes(normalized))) {
|
|
1820
|
+
if (fieldName.includes("Aggregate") || fieldName.includes("aggregate")) {
|
|
1821
|
+
if (!cov.limitType || cov.limitType === "aggregate") {
|
|
1822
|
+
limits[fieldName] = cov.limit;
|
|
1823
|
+
}
|
|
1824
|
+
} else {
|
|
1825
|
+
if (!limits[fieldName]) {
|
|
1826
|
+
limits[fieldName] = cov.limit;
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
break;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
const hasStatutory = coverages.some(
|
|
1834
|
+
(c) => c.limitType === "statutory" || normalizeName(c.name ?? "").includes("statutory")
|
|
1835
|
+
);
|
|
1836
|
+
if (hasStatutory) {
|
|
1837
|
+
limits.statutory = "true";
|
|
1838
|
+
}
|
|
1839
|
+
const elCoverages = coverages.filter(
|
|
1840
|
+
(c) => normalizeName(c.name ?? "").includes("employersliability")
|
|
1841
|
+
);
|
|
1842
|
+
if (elCoverages.length > 0) {
|
|
1843
|
+
const el = {};
|
|
1844
|
+
for (const c of elCoverages) {
|
|
1845
|
+
if (!c.limit) continue;
|
|
1846
|
+
const n = normalizeName(c.name ?? "");
|
|
1847
|
+
if (n.includes("accident") || n.includes("eachaccident")) el.eachAccident = c.limit;
|
|
1848
|
+
else if (n.includes("diseasepolicy") || n.includes("diseasepolicylimit")) el.diseasePolicyLimit = c.limit;
|
|
1849
|
+
else if (n.includes("diseaseemployee") || n.includes("diseaseeachemployee")) el.diseaseEachEmployee = c.limit;
|
|
1850
|
+
else if (!el.eachAccident) el.eachAccident = c.limit;
|
|
1851
|
+
}
|
|
1852
|
+
if (Object.keys(el).length > 0) {
|
|
1853
|
+
limits.employersLiability = el;
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
if (Object.keys(limits).length > 0) {
|
|
1857
|
+
const result = { ...limits };
|
|
1858
|
+
if (result.statutory === "true") result.statutory = true;
|
|
1859
|
+
raw.limits = result;
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
function synthesizeDeductibles(doc) {
|
|
1863
|
+
const raw = doc;
|
|
1864
|
+
if (raw.deductibles && typeof raw.deductibles === "object" && Object.keys(raw.deductibles).length > 0) return;
|
|
1865
|
+
const coverages = doc.coverages;
|
|
1866
|
+
if (!coverages || coverages.length === 0) return;
|
|
1867
|
+
const deductibleValues = coverages.filter((c) => c.deductible && c.deductible.trim() !== "" && c.deductible !== "N/A" && c.deductible !== "None").map((c) => c.deductible);
|
|
1868
|
+
if (deductibleValues.length === 0) return;
|
|
1869
|
+
const freq = /* @__PURE__ */ new Map();
|
|
1870
|
+
for (const d of deductibleValues) {
|
|
1871
|
+
freq.set(d, (freq.get(d) ?? 0) + 1);
|
|
1872
|
+
}
|
|
1873
|
+
let mostCommon = deductibleValues[0];
|
|
1874
|
+
let maxFreq = 0;
|
|
1875
|
+
for (const [val, count] of freq) {
|
|
1876
|
+
if (count > maxFreq) {
|
|
1877
|
+
mostCommon = val;
|
|
1878
|
+
maxFreq = count;
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
const deductibles = {};
|
|
1882
|
+
const hasPerClaim = coverages.some(
|
|
1883
|
+
(c) => c.deductible && normalizeName(c.name ?? "").includes("perclaim")
|
|
1884
|
+
);
|
|
1885
|
+
if (hasPerClaim) {
|
|
1886
|
+
deductibles.perClaim = mostCommon;
|
|
1887
|
+
} else {
|
|
1888
|
+
deductibles.perOccurrence = mostCommon;
|
|
1889
|
+
}
|
|
1890
|
+
const sirCoverage = coverages.find(
|
|
1891
|
+
(c) => c.deductible && (normalizeName(c.name ?? "").includes("selfinsuredretention") || normalizeName(c.name ?? "").includes("sir"))
|
|
1892
|
+
);
|
|
1893
|
+
if (sirCoverage?.deductible) {
|
|
1894
|
+
deductibles.selfInsuredRetention = sirCoverage.deductible;
|
|
1895
|
+
}
|
|
1896
|
+
const aggDed = coverages.find(
|
|
1897
|
+
(c) => c.deductible && normalizeName(c.name ?? "").includes("aggregatedeductible")
|
|
1898
|
+
);
|
|
1899
|
+
if (aggDed?.deductible) {
|
|
1900
|
+
deductibles.aggregateDeductible = aggDed.deductible;
|
|
1901
|
+
}
|
|
1902
|
+
if (Object.keys(deductibles).length > 0) {
|
|
1903
|
+
raw.deductibles = deductibles;
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
var PREMIUM_PATTERNS = ["premium", "totalPremium", "annualPremium", "policyPremium", "basePremium"];
|
|
1907
|
+
var TOTAL_COST_PATTERNS = ["totalCost", "totalDue", "totalAmount", "totalPolicyPremium"];
|
|
1908
|
+
function promotePremium(doc) {
|
|
1909
|
+
const raw = doc;
|
|
1910
|
+
const fields = getDeclarationFields(doc);
|
|
1911
|
+
if (!raw.premium) {
|
|
1912
|
+
const premium = findFieldValue(fields, PREMIUM_PATTERNS);
|
|
1913
|
+
if (premium) raw.premium = premium;
|
|
1914
|
+
}
|
|
1915
|
+
if (!raw.totalCost) {
|
|
1916
|
+
const totalCost = findFieldValue(fields, TOTAL_COST_PATTERNS);
|
|
1917
|
+
if (totalCost) raw.totalCost = totalCost;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
function promoteExtractedFields(doc) {
|
|
1921
|
+
promoteCarrierFields(doc);
|
|
1922
|
+
promoteBroker(doc);
|
|
1923
|
+
promoteLossPayees(doc);
|
|
1924
|
+
promoteLocations(doc);
|
|
1925
|
+
synthesizeLimits(doc);
|
|
1926
|
+
synthesizeDeductibles(doc);
|
|
1927
|
+
promotePremium(doc);
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1578
1930
|
// src/extraction/assembler.ts
|
|
1579
1931
|
function assembleDocument(documentId, documentType, memory) {
|
|
1580
1932
|
const carrier = memory.get("carrier_info");
|
|
@@ -1598,6 +1950,9 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1598
1950
|
policyTypes: classify?.policyTypes,
|
|
1599
1951
|
...sanitizeNulls(carrier ?? {}),
|
|
1600
1952
|
...sanitizeNulls(insured ?? {}),
|
|
1953
|
+
// Map named_insured extractor's loss payees/mortgage holders to EndorsementParty shape
|
|
1954
|
+
...Array.isArray(insured?.lossPayees) && insured.lossPayees.length > 0 ? { lossPayees: insured.lossPayees.map((lp) => ({ ...lp, role: "loss_payee" })) } : {},
|
|
1955
|
+
...Array.isArray(insured?.mortgageHolders) && insured.mortgageHolders.length > 0 ? { mortgageHolders: insured.mortgageHolders.map((mh) => ({ ...mh, role: "mortgage_holder" })) } : {},
|
|
1601
1956
|
...sanitizeNulls(coverages ?? {}),
|
|
1602
1957
|
...sanitizeNulls(premium ?? {}),
|
|
1603
1958
|
...sanitizeNulls(supplementary ?? {}),
|
|
@@ -1609,8 +1964,9 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1609
1964
|
declarations: declarations ? sanitizeNulls(declarations) : void 0,
|
|
1610
1965
|
...sanitizeNulls(lossHistory ?? {})
|
|
1611
1966
|
};
|
|
1967
|
+
let doc;
|
|
1612
1968
|
if (documentType === "policy") {
|
|
1613
|
-
|
|
1969
|
+
doc = {
|
|
1614
1970
|
...base,
|
|
1615
1971
|
type: "policy",
|
|
1616
1972
|
policyNumber: carrier?.policyNumber ?? insured?.policyNumber ?? "Unknown",
|
|
@@ -1618,17 +1974,20 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1618
1974
|
expirationDate: carrier?.expirationDate,
|
|
1619
1975
|
policyTermType: carrier?.policyTermType
|
|
1620
1976
|
};
|
|
1977
|
+
} else {
|
|
1978
|
+
doc = {
|
|
1979
|
+
...base,
|
|
1980
|
+
type: "quote",
|
|
1981
|
+
quoteNumber: carrier?.quoteNumber ?? "Unknown",
|
|
1982
|
+
proposedEffectiveDate: carrier?.proposedEffectiveDate,
|
|
1983
|
+
proposedExpirationDate: carrier?.proposedExpirationDate,
|
|
1984
|
+
subjectivities: coverages?.subjectivities,
|
|
1985
|
+
underwritingConditions: coverages?.underwritingConditions,
|
|
1986
|
+
premiumBreakdown: premium?.premiumBreakdown
|
|
1987
|
+
};
|
|
1621
1988
|
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
type: "quote",
|
|
1625
|
-
quoteNumber: carrier?.quoteNumber ?? "Unknown",
|
|
1626
|
-
proposedEffectiveDate: carrier?.proposedEffectiveDate,
|
|
1627
|
-
proposedExpirationDate: carrier?.proposedExpirationDate,
|
|
1628
|
-
subjectivities: coverages?.subjectivities,
|
|
1629
|
-
underwritingConditions: coverages?.underwritingConditions,
|
|
1630
|
-
premiumBreakdown: premium?.premiumBreakdown
|
|
1631
|
-
};
|
|
1989
|
+
promoteExtractedFields(doc);
|
|
1990
|
+
return doc;
|
|
1632
1991
|
}
|
|
1633
1992
|
|
|
1634
1993
|
// src/prompts/coordinator/format.ts
|
|
@@ -3062,21 +3421,69 @@ Use the page map to target follow-up extraction pages precisely. Prefer narrow,
|
|
|
3062
3421
|
Respond with JSON only.`;
|
|
3063
3422
|
}
|
|
3064
3423
|
|
|
3065
|
-
// src/prompts/
|
|
3424
|
+
// src/prompts/coordinator/summarize.ts
|
|
3066
3425
|
import { z as z22 } from "zod";
|
|
3067
|
-
var
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3426
|
+
var SummaryResultSchema = z22.object({
|
|
3427
|
+
summary: z22.string().describe("A 1-3 sentence overview of this insurance document")
|
|
3428
|
+
});
|
|
3429
|
+
function buildSummaryPrompt(doc) {
|
|
3430
|
+
const snapshot = {
|
|
3431
|
+
type: doc.type,
|
|
3432
|
+
carrier: doc.carrier,
|
|
3433
|
+
insuredName: doc.insuredName,
|
|
3434
|
+
policyTypes: doc.policyTypes,
|
|
3435
|
+
premium: doc.premium,
|
|
3436
|
+
coverageCount: doc.coverages?.length ?? 0
|
|
3437
|
+
};
|
|
3438
|
+
if (doc.type === "policy") {
|
|
3439
|
+
snapshot.policyNumber = doc.policyNumber;
|
|
3440
|
+
snapshot.effectiveDate = doc.effectiveDate;
|
|
3441
|
+
snapshot.expirationDate = doc.expirationDate;
|
|
3442
|
+
} else {
|
|
3443
|
+
snapshot.quoteNumber = doc.quoteNumber;
|
|
3444
|
+
snapshot.proposedEffectiveDate = doc.proposedEffectiveDate;
|
|
3445
|
+
}
|
|
3446
|
+
const raw = doc;
|
|
3447
|
+
if (raw.limits) snapshot.limits = raw.limits;
|
|
3448
|
+
if (raw.deductibles) snapshot.deductibles = raw.deductibles;
|
|
3449
|
+
if (raw.brokerAgency) snapshot.brokerAgency = raw.brokerAgency;
|
|
3450
|
+
if (doc.endorsements?.length) snapshot.endorsementCount = doc.endorsements.length;
|
|
3451
|
+
if (doc.exclusions?.length) snapshot.exclusionCount = doc.exclusions.length;
|
|
3452
|
+
if (doc.coverages?.length) {
|
|
3453
|
+
snapshot.topCoverages = doc.coverages.slice(0, 5).map((c) => c.name);
|
|
3454
|
+
}
|
|
3455
|
+
return `You are an expert insurance document analyst. Generate a brief summary of this insurance document.
|
|
3456
|
+
|
|
3457
|
+
Write 1-3 sentences that capture the essential facts a broker or underwriter would want at a glance:
|
|
3458
|
+
- Who is insured and by whom
|
|
3459
|
+
- What type of policy/quote and the key coverages
|
|
3460
|
+
- Policy period and premium if available
|
|
3461
|
+
- Any notable features (high limits, unusual exclusions, etc.)
|
|
3462
|
+
|
|
3463
|
+
Document data:
|
|
3464
|
+
${JSON.stringify(snapshot, null, 2)}
|
|
3465
|
+
|
|
3466
|
+
Return JSON only with a "summary" field.`;
|
|
3467
|
+
}
|
|
3468
|
+
|
|
3469
|
+
// src/prompts/extractors/carrier-info.ts
|
|
3470
|
+
import { z as z23 } from "zod";
|
|
3471
|
+
var CarrierInfoSchema = z23.object({
|
|
3472
|
+
carrierName: z23.string().describe("Primary insurance company name for display"),
|
|
3473
|
+
carrierLegalName: z23.string().optional().describe("Legal entity name of insurer"),
|
|
3474
|
+
naicNumber: z23.string().optional().describe("NAIC company code"),
|
|
3475
|
+
amBestRating: z23.string().optional().describe("AM Best rating, e.g. 'A+ XV'"),
|
|
3476
|
+
admittedStatus: z23.enum(["admitted", "non_admitted", "surplus_lines"]).optional().describe("Admitted status of the carrier"),
|
|
3477
|
+
mga: z23.string().optional().describe("Managing General Agent or Program Administrator name"),
|
|
3478
|
+
underwriter: z23.string().optional().describe("Named individual underwriter"),
|
|
3479
|
+
brokerAgency: z23.string().optional().describe("Broker or producer agency name"),
|
|
3480
|
+
brokerContactName: z23.string().optional().describe("Broker or producer contact person name"),
|
|
3481
|
+
brokerLicenseNumber: z23.string().optional().describe("Broker or producer license number"),
|
|
3482
|
+
policyNumber: z23.string().optional().describe("Policy or quote reference number"),
|
|
3483
|
+
effectiveDate: z23.string().optional().describe("Policy effective date (MM/DD/YYYY)"),
|
|
3484
|
+
expirationDate: z23.string().optional().describe("Policy expiration date (MM/DD/YYYY)"),
|
|
3485
|
+
quoteNumber: z23.string().optional().describe("Quote or proposal reference number"),
|
|
3486
|
+
proposedEffectiveDate: z23.string().optional().describe("Proposed effective date for quotes (MM/DD/YYYY)")
|
|
3080
3487
|
});
|
|
3081
3488
|
function buildCarrierInfoPrompt() {
|
|
3082
3489
|
return `You are an expert insurance document analyst. Extract carrier and policy identification information from this document.
|
|
@@ -3087,27 +3494,30 @@ Focus on:
|
|
|
3087
3494
|
- Whether the carrier is admitted, non-admitted, or surplus lines
|
|
3088
3495
|
- Managing General Agent (MGA) or Program Administrator if applicable
|
|
3089
3496
|
- Named individual underwriter if listed
|
|
3497
|
+
- Broker/producer/agent: agency name, contact person name, and license number
|
|
3090
3498
|
- Policy number and effective/expiration dates
|
|
3091
3499
|
- For quotes: quote number and proposed effective date
|
|
3092
3500
|
|
|
3093
3501
|
For carrier vs. security distinction: "carrier" is the primary company name; the legal entity on risk (e.g. "Lloyd's Underwriters") may differ from the display name.
|
|
3094
3502
|
|
|
3503
|
+
Look for broker/producer/agent information near the carrier or on the declarations page. This may be labeled "Producer", "Agent", "Broker", or similar.
|
|
3504
|
+
|
|
3095
3505
|
Return JSON only.`;
|
|
3096
3506
|
}
|
|
3097
3507
|
|
|
3098
3508
|
// src/prompts/extractors/named-insured.ts
|
|
3099
|
-
import { z as
|
|
3100
|
-
var AddressSchema2 =
|
|
3101
|
-
street1:
|
|
3102
|
-
city:
|
|
3103
|
-
state:
|
|
3104
|
-
zip:
|
|
3509
|
+
import { z as z24 } from "zod";
|
|
3510
|
+
var AddressSchema2 = z24.object({
|
|
3511
|
+
street1: z24.string(),
|
|
3512
|
+
city: z24.string(),
|
|
3513
|
+
state: z24.string(),
|
|
3514
|
+
zip: z24.string()
|
|
3105
3515
|
});
|
|
3106
|
-
var NamedInsuredSchema2 =
|
|
3107
|
-
insuredName:
|
|
3108
|
-
insuredDba:
|
|
3516
|
+
var NamedInsuredSchema2 = z24.object({
|
|
3517
|
+
insuredName: z24.string().describe("Name of primary named insured"),
|
|
3518
|
+
insuredDba: z24.string().optional().describe("Doing-business-as name"),
|
|
3109
3519
|
insuredAddress: AddressSchema2.optional().describe("Primary insured mailing address"),
|
|
3110
|
-
insuredEntityType:
|
|
3520
|
+
insuredEntityType: z24.enum([
|
|
3111
3521
|
"corporation",
|
|
3112
3522
|
"llc",
|
|
3113
3523
|
"partnership",
|
|
@@ -3120,16 +3530,28 @@ var NamedInsuredSchema2 = z23.object({
|
|
|
3120
3530
|
"married_couple",
|
|
3121
3531
|
"other"
|
|
3122
3532
|
]).optional().describe("Legal entity type of the insured"),
|
|
3123
|
-
insuredFein:
|
|
3124
|
-
insuredSicCode:
|
|
3125
|
-
insuredNaicsCode:
|
|
3126
|
-
additionalNamedInsureds:
|
|
3127
|
-
|
|
3128
|
-
name:
|
|
3129
|
-
relationship:
|
|
3533
|
+
insuredFein: z24.string().optional().describe("Federal Employer Identification Number"),
|
|
3534
|
+
insuredSicCode: z24.string().optional().describe("SIC code"),
|
|
3535
|
+
insuredNaicsCode: z24.string().optional().describe("NAICS code"),
|
|
3536
|
+
additionalNamedInsureds: z24.array(
|
|
3537
|
+
z24.object({
|
|
3538
|
+
name: z24.string(),
|
|
3539
|
+
relationship: z24.string().optional().describe("e.g. subsidiary, affiliate"),
|
|
3540
|
+
address: AddressSchema2.optional()
|
|
3541
|
+
})
|
|
3542
|
+
).optional().describe("Additional named insureds listed on the policy"),
|
|
3543
|
+
lossPayees: z24.array(
|
|
3544
|
+
z24.object({
|
|
3545
|
+
name: z24.string(),
|
|
3546
|
+
address: AddressSchema2.optional()
|
|
3547
|
+
})
|
|
3548
|
+
).optional().describe("Loss payees listed on the policy"),
|
|
3549
|
+
mortgageHolders: z24.array(
|
|
3550
|
+
z24.object({
|
|
3551
|
+
name: z24.string(),
|
|
3130
3552
|
address: AddressSchema2.optional()
|
|
3131
3553
|
})
|
|
3132
|
-
).optional().describe("
|
|
3554
|
+
).optional().describe("Mortgage holders / lienholders listed on the policy")
|
|
3133
3555
|
});
|
|
3134
3556
|
function buildNamedInsuredPrompt() {
|
|
3135
3557
|
return `You are an expert insurance document analyst. Extract all named insured information from this document.
|
|
@@ -3140,21 +3562,23 @@ Focus on:
|
|
|
3140
3562
|
- FEIN (Federal Employer Identification Number) if listed
|
|
3141
3563
|
- SIC code and NAICS code if listed
|
|
3142
3564
|
- ALL additional named insureds with their relationship (subsidiary, affiliate, etc.) and address if provided
|
|
3565
|
+
- ALL loss payees with name and address (e.g. "Loss Payee: BMO Bank of Montreal")
|
|
3566
|
+
- ALL mortgage holders / lienholders / mortgagees with name and address
|
|
3143
3567
|
|
|
3144
|
-
Look on the declarations page, named insured schedule, and any endorsements that add or modify named insureds.
|
|
3568
|
+
Look on the declarations page, named insured schedule, loss payee schedule, mortgagee schedule, and any endorsements that add or modify named insureds, loss payees, or mortgage holders.
|
|
3145
3569
|
|
|
3146
3570
|
Return JSON only.`;
|
|
3147
3571
|
}
|
|
3148
3572
|
|
|
3149
3573
|
// src/prompts/extractors/coverage-limits.ts
|
|
3150
|
-
import { z as
|
|
3574
|
+
import { z as z25 } from "zod";
|
|
3151
3575
|
var ExtractorCoverageSchema = CoverageSchema.extend({
|
|
3152
|
-
coverageCode:
|
|
3576
|
+
coverageCode: z25.string().optional().describe("Coverage code or class code")
|
|
3153
3577
|
});
|
|
3154
|
-
var CoverageLimitsSchema =
|
|
3155
|
-
coverages:
|
|
3156
|
-
coverageForm:
|
|
3157
|
-
retroactiveDate:
|
|
3578
|
+
var CoverageLimitsSchema = z25.object({
|
|
3579
|
+
coverages: z25.array(ExtractorCoverageSchema).describe("All coverages with their limits"),
|
|
3580
|
+
coverageForm: z25.enum(["occurrence", "claims_made", "accident"]).optional().describe("Primary coverage trigger type"),
|
|
3581
|
+
retroactiveDate: z25.string().optional().describe("Retroactive date for claims-made policies (MM/DD/YYYY)")
|
|
3158
3582
|
});
|
|
3159
3583
|
function buildCoverageLimitsPrompt() {
|
|
3160
3584
|
return `You are an expert insurance document analyst. Extract all coverage limits and deductibles from this document.
|
|
@@ -3193,14 +3617,14 @@ Return JSON only.`;
|
|
|
3193
3617
|
}
|
|
3194
3618
|
|
|
3195
3619
|
// src/prompts/extractors/endorsements.ts
|
|
3196
|
-
import { z as
|
|
3197
|
-
var EndorsementsSchema =
|
|
3198
|
-
endorsements:
|
|
3199
|
-
|
|
3200
|
-
formNumber:
|
|
3201
|
-
editionDate:
|
|
3202
|
-
title:
|
|
3203
|
-
endorsementType:
|
|
3620
|
+
import { z as z26 } from "zod";
|
|
3621
|
+
var EndorsementsSchema = z26.object({
|
|
3622
|
+
endorsements: z26.array(
|
|
3623
|
+
z26.object({
|
|
3624
|
+
formNumber: z26.string().describe("Form number, e.g. 'CG 21 47'"),
|
|
3625
|
+
editionDate: z26.string().optional().describe("Edition date, e.g. '12 07'"),
|
|
3626
|
+
title: z26.string().describe("Endorsement title"),
|
|
3627
|
+
endorsementType: z26.enum([
|
|
3204
3628
|
"additional_insured",
|
|
3205
3629
|
"waiver_of_subrogation",
|
|
3206
3630
|
"primary_noncontributory",
|
|
@@ -3220,12 +3644,12 @@ var EndorsementsSchema = z25.object({
|
|
|
3220
3644
|
"territorial_extension",
|
|
3221
3645
|
"other"
|
|
3222
3646
|
]).describe("Endorsement type classification"),
|
|
3223
|
-
effectiveDate:
|
|
3224
|
-
affectedCoverageParts:
|
|
3225
|
-
namedParties:
|
|
3226
|
-
|
|
3227
|
-
name:
|
|
3228
|
-
role:
|
|
3647
|
+
effectiveDate: z26.string().optional().describe("Endorsement effective date"),
|
|
3648
|
+
affectedCoverageParts: z26.array(z26.string()).optional().describe("Coverage parts affected by this endorsement"),
|
|
3649
|
+
namedParties: z26.array(
|
|
3650
|
+
z26.object({
|
|
3651
|
+
name: z26.string().describe("Party name"),
|
|
3652
|
+
role: z26.enum([
|
|
3229
3653
|
"additional_insured",
|
|
3230
3654
|
"loss_payee",
|
|
3231
3655
|
"mortgage_holder",
|
|
@@ -3234,15 +3658,15 @@ var EndorsementsSchema = z25.object({
|
|
|
3234
3658
|
"designated_person",
|
|
3235
3659
|
"other"
|
|
3236
3660
|
]).describe("Party role"),
|
|
3237
|
-
relationship:
|
|
3238
|
-
scope:
|
|
3661
|
+
relationship: z26.string().optional().describe("Relationship to insured"),
|
|
3662
|
+
scope: z26.string().optional().describe("Scope of coverage for this party")
|
|
3239
3663
|
})
|
|
3240
3664
|
).optional().describe("Named parties (additional insureds, loss payees, etc.)"),
|
|
3241
|
-
keyTerms:
|
|
3242
|
-
premiumImpact:
|
|
3243
|
-
content:
|
|
3244
|
-
pageStart:
|
|
3245
|
-
pageEnd:
|
|
3665
|
+
keyTerms: z26.array(z26.string()).optional().describe("Key terms or notable provisions in the endorsement"),
|
|
3666
|
+
premiumImpact: z26.string().optional().describe("Additional premium or credit"),
|
|
3667
|
+
content: z26.string().describe("Full verbatim text of the endorsement"),
|
|
3668
|
+
pageStart: z26.number().describe("Starting page number of this endorsement"),
|
|
3669
|
+
pageEnd: z26.number().optional().describe("Ending page number of this endorsement")
|
|
3246
3670
|
})
|
|
3247
3671
|
).describe("All endorsements found in the document")
|
|
3248
3672
|
});
|
|
@@ -3273,20 +3697,20 @@ Return JSON only.`;
|
|
|
3273
3697
|
}
|
|
3274
3698
|
|
|
3275
3699
|
// src/prompts/extractors/exclusions.ts
|
|
3276
|
-
import { z as
|
|
3277
|
-
var ExclusionsSchema =
|
|
3278
|
-
exclusions:
|
|
3279
|
-
|
|
3280
|
-
name:
|
|
3281
|
-
formNumber:
|
|
3282
|
-
excludedPerils:
|
|
3283
|
-
isAbsolute:
|
|
3284
|
-
exceptions:
|
|
3285
|
-
buybackAvailable:
|
|
3286
|
-
buybackEndorsement:
|
|
3287
|
-
appliesTo:
|
|
3288
|
-
content:
|
|
3289
|
-
pageNumber:
|
|
3700
|
+
import { z as z27 } from "zod";
|
|
3701
|
+
var ExclusionsSchema = z27.object({
|
|
3702
|
+
exclusions: z27.array(
|
|
3703
|
+
z27.object({
|
|
3704
|
+
name: z27.string().describe("Exclusion title or short description"),
|
|
3705
|
+
formNumber: z27.string().optional().describe("Form number if part of a named endorsement"),
|
|
3706
|
+
excludedPerils: z27.array(z27.string()).optional().describe("Specific perils excluded"),
|
|
3707
|
+
isAbsolute: z27.boolean().optional().describe("Whether the exclusion is absolute (no exceptions)"),
|
|
3708
|
+
exceptions: z27.array(z27.string()).optional().describe("Exceptions to the exclusion, if any"),
|
|
3709
|
+
buybackAvailable: z27.boolean().optional().describe("Whether coverage can be bought back via endorsement"),
|
|
3710
|
+
buybackEndorsement: z27.string().optional().describe("Form number of the buyback endorsement if available"),
|
|
3711
|
+
appliesTo: z27.array(z27.string()).optional().describe("Coverage types this exclusion applies to"),
|
|
3712
|
+
content: z27.string().describe("Full verbatim exclusion text"),
|
|
3713
|
+
pageNumber: z27.number().optional().describe("Page number where exclusion appears")
|
|
3290
3714
|
})
|
|
3291
3715
|
).describe("All exclusions found in the document")
|
|
3292
3716
|
});
|
|
@@ -3322,12 +3746,12 @@ Return JSON only.`;
|
|
|
3322
3746
|
}
|
|
3323
3747
|
|
|
3324
3748
|
// src/prompts/extractors/conditions.ts
|
|
3325
|
-
import { z as
|
|
3326
|
-
var ConditionsSchema =
|
|
3327
|
-
conditions:
|
|
3328
|
-
|
|
3329
|
-
name:
|
|
3330
|
-
conditionType:
|
|
3749
|
+
import { z as z28 } from "zod";
|
|
3750
|
+
var ConditionsSchema = z28.object({
|
|
3751
|
+
conditions: z28.array(
|
|
3752
|
+
z28.object({
|
|
3753
|
+
name: z28.string().describe("Condition title"),
|
|
3754
|
+
conditionType: z28.enum([
|
|
3331
3755
|
"duties_after_loss",
|
|
3332
3756
|
"notice_requirements",
|
|
3333
3757
|
"other_insurance",
|
|
@@ -3346,14 +3770,14 @@ var ConditionsSchema = z27.object({
|
|
|
3346
3770
|
"separation_of_insureds",
|
|
3347
3771
|
"other"
|
|
3348
3772
|
]).describe("Condition category"),
|
|
3349
|
-
content:
|
|
3350
|
-
keyValues:
|
|
3351
|
-
|
|
3352
|
-
key:
|
|
3353
|
-
value:
|
|
3773
|
+
content: z28.string().describe("Full verbatim condition text"),
|
|
3774
|
+
keyValues: z28.array(
|
|
3775
|
+
z28.object({
|
|
3776
|
+
key: z28.string().describe("Key name (e.g. 'noticePeriod', 'suitDeadline')"),
|
|
3777
|
+
value: z28.string().describe("Value (e.g. '30 days', '2 years')")
|
|
3354
3778
|
})
|
|
3355
3779
|
).optional().describe("Key values extracted from the condition (notice periods, deadlines, etc.)"),
|
|
3356
|
-
pageNumber:
|
|
3780
|
+
pageNumber: z28.number().optional().describe("Page number where condition appears")
|
|
3357
3781
|
})
|
|
3358
3782
|
).describe("All policy conditions found in the document")
|
|
3359
3783
|
});
|
|
@@ -3391,28 +3815,28 @@ Return JSON only.`;
|
|
|
3391
3815
|
}
|
|
3392
3816
|
|
|
3393
3817
|
// src/prompts/extractors/premium-breakdown.ts
|
|
3394
|
-
import { z as
|
|
3395
|
-
var PremiumBreakdownSchema =
|
|
3396
|
-
premium:
|
|
3397
|
-
totalCost:
|
|
3398
|
-
premiumBreakdown:
|
|
3399
|
-
|
|
3400
|
-
line:
|
|
3401
|
-
amount:
|
|
3818
|
+
import { z as z29 } from "zod";
|
|
3819
|
+
var PremiumBreakdownSchema = z29.object({
|
|
3820
|
+
premium: z29.string().optional().describe("Total premium amount, e.g. '$5,000'"),
|
|
3821
|
+
totalCost: z29.string().optional().describe("Total cost including taxes and fees, e.g. '$5,250'"),
|
|
3822
|
+
premiumBreakdown: z29.array(
|
|
3823
|
+
z29.object({
|
|
3824
|
+
line: z29.string().describe("Coverage line name"),
|
|
3825
|
+
amount: z29.string().describe("Premium amount for this line")
|
|
3402
3826
|
})
|
|
3403
3827
|
).optional().describe("Per-coverage-line premium breakdown"),
|
|
3404
|
-
taxesAndFees:
|
|
3405
|
-
|
|
3406
|
-
name:
|
|
3407
|
-
amount:
|
|
3408
|
-
type:
|
|
3828
|
+
taxesAndFees: z29.array(
|
|
3829
|
+
z29.object({
|
|
3830
|
+
name: z29.string().describe("Fee or tax name"),
|
|
3831
|
+
amount: z29.string().describe("Dollar amount"),
|
|
3832
|
+
type: z29.enum(["tax", "fee", "surcharge", "assessment"]).optional().describe("Fee category")
|
|
3409
3833
|
})
|
|
3410
3834
|
).optional().describe("Taxes, fees, surcharges, and assessments"),
|
|
3411
|
-
minimumPremium:
|
|
3412
|
-
depositPremium:
|
|
3413
|
-
paymentPlan:
|
|
3414
|
-
auditType:
|
|
3415
|
-
ratingBasis:
|
|
3835
|
+
minimumPremium: z29.string().optional().describe("Minimum premium if stated"),
|
|
3836
|
+
depositPremium: z29.string().optional().describe("Deposit premium if stated"),
|
|
3837
|
+
paymentPlan: z29.string().optional().describe("Payment plan description"),
|
|
3838
|
+
auditType: z29.enum(["annual", "semi_annual", "quarterly", "monthly", "final", "self"]).optional().describe("Premium audit type"),
|
|
3839
|
+
ratingBasis: z29.string().optional().describe("Rating basis, e.g. payroll, revenue, area, units")
|
|
3416
3840
|
});
|
|
3417
3841
|
function buildPremiumBreakdownPrompt() {
|
|
3418
3842
|
return `You are an expert insurance document analyst. Extract all premium and cost information from this document.
|
|
@@ -3432,14 +3856,14 @@ Return JSON only.`;
|
|
|
3432
3856
|
}
|
|
3433
3857
|
|
|
3434
3858
|
// src/prompts/extractors/declarations.ts
|
|
3435
|
-
import { z as
|
|
3436
|
-
var DeclarationsFieldSchema =
|
|
3437
|
-
field:
|
|
3438
|
-
value:
|
|
3439
|
-
section:
|
|
3859
|
+
import { z as z30 } from "zod";
|
|
3860
|
+
var DeclarationsFieldSchema = z30.object({
|
|
3861
|
+
field: z30.string().describe("Descriptive field name (e.g. 'policyNumber', 'effectiveDate', 'coverageALimit')"),
|
|
3862
|
+
value: z30.string().describe("Extracted value exactly as it appears in the document"),
|
|
3863
|
+
section: z30.string().optional().describe("Section or grouping this field belongs to (e.g. 'Coverage Limits', 'Vehicle Schedule')")
|
|
3440
3864
|
});
|
|
3441
|
-
var DeclarationsExtractSchema =
|
|
3442
|
-
fields:
|
|
3865
|
+
var DeclarationsExtractSchema = z30.object({
|
|
3866
|
+
fields: z30.array(DeclarationsFieldSchema).describe("All declarations page fields extracted as key-value pairs. Structure varies by line of business.")
|
|
3443
3867
|
});
|
|
3444
3868
|
function buildDeclarationsPrompt() {
|
|
3445
3869
|
return `You are an expert insurance document analyst. Extract all declarations page data from this document into a flexible key-value structure.
|
|
@@ -3479,21 +3903,21 @@ Preserve original values exactly as they appear. Return JSON only.`;
|
|
|
3479
3903
|
}
|
|
3480
3904
|
|
|
3481
3905
|
// src/prompts/extractors/loss-history.ts
|
|
3482
|
-
import { z as
|
|
3483
|
-
var LossHistorySchema =
|
|
3484
|
-
lossSummary:
|
|
3485
|
-
individualClaims:
|
|
3486
|
-
|
|
3487
|
-
date:
|
|
3488
|
-
type:
|
|
3489
|
-
description:
|
|
3490
|
-
amountPaid:
|
|
3491
|
-
amountReserved:
|
|
3492
|
-
status:
|
|
3493
|
-
claimNumber:
|
|
3906
|
+
import { z as z31 } from "zod";
|
|
3907
|
+
var LossHistorySchema = z31.object({
|
|
3908
|
+
lossSummary: z31.string().optional().describe("Summary of loss history, e.g. '3 claims in past 5 years totaling $125,000'"),
|
|
3909
|
+
individualClaims: z31.array(
|
|
3910
|
+
z31.object({
|
|
3911
|
+
date: z31.string().optional().describe("Date of loss or claim"),
|
|
3912
|
+
type: z31.string().optional().describe("Type of claim, e.g. 'property damage', 'bodily injury'"),
|
|
3913
|
+
description: z31.string().optional().describe("Brief description of the claim"),
|
|
3914
|
+
amountPaid: z31.string().optional().describe("Amount paid"),
|
|
3915
|
+
amountReserved: z31.string().optional().describe("Amount reserved"),
|
|
3916
|
+
status: z31.enum(["open", "closed", "reopened"]).optional().describe("Claim status"),
|
|
3917
|
+
claimNumber: z31.string().optional().describe("Claim reference number")
|
|
3494
3918
|
})
|
|
3495
3919
|
).optional().describe("Individual claim records"),
|
|
3496
|
-
experienceMod:
|
|
3920
|
+
experienceMod: z31.string().optional().describe("Experience modification factor for workers comp, e.g. '0.85'")
|
|
3497
3921
|
});
|
|
3498
3922
|
function buildLossHistoryPrompt() {
|
|
3499
3923
|
return `You are an expert insurance document analyst. Extract all loss history and claims information from this document.
|
|
@@ -3510,18 +3934,18 @@ Return JSON only.`;
|
|
|
3510
3934
|
}
|
|
3511
3935
|
|
|
3512
3936
|
// src/prompts/extractors/sections.ts
|
|
3513
|
-
import { z as
|
|
3514
|
-
var SubsectionSchema2 =
|
|
3515
|
-
title:
|
|
3516
|
-
sectionNumber:
|
|
3517
|
-
pageNumber:
|
|
3518
|
-
content:
|
|
3937
|
+
import { z as z32 } from "zod";
|
|
3938
|
+
var SubsectionSchema2 = z32.object({
|
|
3939
|
+
title: z32.string().describe("Subsection title"),
|
|
3940
|
+
sectionNumber: z32.string().optional().describe("Subsection number"),
|
|
3941
|
+
pageNumber: z32.number().optional().describe("Page number"),
|
|
3942
|
+
content: z32.string().describe("Full verbatim text")
|
|
3519
3943
|
});
|
|
3520
|
-
var SectionsSchema =
|
|
3521
|
-
sections:
|
|
3522
|
-
|
|
3523
|
-
title:
|
|
3524
|
-
type:
|
|
3944
|
+
var SectionsSchema = z32.object({
|
|
3945
|
+
sections: z32.array(
|
|
3946
|
+
z32.object({
|
|
3947
|
+
title: z32.string().describe("Section title"),
|
|
3948
|
+
type: z32.enum([
|
|
3525
3949
|
"declarations",
|
|
3526
3950
|
"insuring_agreement",
|
|
3527
3951
|
"policy_form",
|
|
@@ -3535,10 +3959,10 @@ var SectionsSchema = z31.object({
|
|
|
3535
3959
|
"regulatory",
|
|
3536
3960
|
"other"
|
|
3537
3961
|
]).describe("Section type classification"),
|
|
3538
|
-
content:
|
|
3539
|
-
pageStart:
|
|
3540
|
-
pageEnd:
|
|
3541
|
-
subsections:
|
|
3962
|
+
content: z32.string().describe("Full verbatim text of the section"),
|
|
3963
|
+
pageStart: z32.number().describe("Starting page number"),
|
|
3964
|
+
pageEnd: z32.number().optional().describe("Ending page number"),
|
|
3965
|
+
subsections: z32.array(SubsectionSchema2).optional().describe("Subsections within this section")
|
|
3542
3966
|
})
|
|
3543
3967
|
).describe("All document sections")
|
|
3544
3968
|
});
|
|
@@ -3568,20 +3992,20 @@ Return JSON only.`;
|
|
|
3568
3992
|
}
|
|
3569
3993
|
|
|
3570
3994
|
// src/prompts/extractors/supplementary.ts
|
|
3571
|
-
import { z as
|
|
3572
|
-
var ContactSchema2 =
|
|
3573
|
-
name:
|
|
3574
|
-
phone:
|
|
3575
|
-
email:
|
|
3576
|
-
address:
|
|
3577
|
-
type:
|
|
3995
|
+
import { z as z33 } from "zod";
|
|
3996
|
+
var ContactSchema2 = z33.object({
|
|
3997
|
+
name: z33.string().optional().describe("Organization or person name"),
|
|
3998
|
+
phone: z33.string().optional().describe("Phone number"),
|
|
3999
|
+
email: z33.string().optional().describe("Email address"),
|
|
4000
|
+
address: z33.string().optional().describe("Mailing address"),
|
|
4001
|
+
type: z33.string().optional().describe("Contact type, e.g. 'State Department of Insurance'")
|
|
3578
4002
|
});
|
|
3579
|
-
var SupplementarySchema =
|
|
3580
|
-
regulatoryContacts:
|
|
3581
|
-
claimsContacts:
|
|
3582
|
-
thirdPartyAdministrators:
|
|
3583
|
-
cancellationNoticeDays:
|
|
3584
|
-
nonrenewalNoticeDays:
|
|
4003
|
+
var SupplementarySchema = z33.object({
|
|
4004
|
+
regulatoryContacts: z33.array(ContactSchema2).optional().describe("Regulatory body contacts (state department of insurance, ombudsman)"),
|
|
4005
|
+
claimsContacts: z33.array(ContactSchema2).optional().describe("Claims reporting contacts and instructions"),
|
|
4006
|
+
thirdPartyAdministrators: z33.array(ContactSchema2).optional().describe("Third-party administrators for claims handling"),
|
|
4007
|
+
cancellationNoticeDays: z33.number().optional().describe("Required notice period for cancellation in days"),
|
|
4008
|
+
nonrenewalNoticeDays: z33.number().optional().describe("Required notice period for nonrenewal in days")
|
|
3585
4009
|
});
|
|
3586
4010
|
function buildSupplementaryPrompt() {
|
|
3587
4011
|
return `You are an expert insurance document analyst. Extract supplementary and regulatory information from this document.
|
|
@@ -4440,6 +4864,31 @@ function createExtractor(config) {
|
|
|
4440
4864
|
memory: Object.fromEntries(memory),
|
|
4441
4865
|
document
|
|
4442
4866
|
});
|
|
4867
|
+
if (!document.summary) {
|
|
4868
|
+
onProgress?.("Generating document summary...");
|
|
4869
|
+
try {
|
|
4870
|
+
const summaryResponse = await safeGenerateObject(
|
|
4871
|
+
generateObject,
|
|
4872
|
+
{
|
|
4873
|
+
prompt: buildSummaryPrompt(document),
|
|
4874
|
+
schema: SummaryResultSchema,
|
|
4875
|
+
maxTokens: 512,
|
|
4876
|
+
providerOptions
|
|
4877
|
+
},
|
|
4878
|
+
{
|
|
4879
|
+
fallback: { summary: "" },
|
|
4880
|
+
log,
|
|
4881
|
+
onError: (err, attempt) => log?.(`Summary attempt ${attempt + 1} failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
4882
|
+
}
|
|
4883
|
+
);
|
|
4884
|
+
trackUsage(summaryResponse.usage);
|
|
4885
|
+
if (summaryResponse.object.summary) {
|
|
4886
|
+
document.summary = summaryResponse.object.summary;
|
|
4887
|
+
}
|
|
4888
|
+
} catch (error) {
|
|
4889
|
+
await log?.(`Summary generation failed, skipping: ${error instanceof Error ? error.message : String(error)}`);
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4443
4892
|
onProgress?.("Formatting extracted content...");
|
|
4444
4893
|
const formatResult = await formatDocumentContent(document, generateText, {
|
|
4445
4894
|
providerOptions,
|
|
@@ -4683,8 +5132,8 @@ Respond with JSON only:
|
|
|
4683
5132
|
}`;
|
|
4684
5133
|
|
|
4685
5134
|
// src/schemas/application.ts
|
|
4686
|
-
import { z as
|
|
4687
|
-
var FieldTypeSchema =
|
|
5135
|
+
import { z as z34 } from "zod";
|
|
5136
|
+
var FieldTypeSchema = z34.enum([
|
|
4688
5137
|
"text",
|
|
4689
5138
|
"numeric",
|
|
4690
5139
|
"currency",
|
|
@@ -4693,131 +5142,131 @@ var FieldTypeSchema = z33.enum([
|
|
|
4693
5142
|
"table",
|
|
4694
5143
|
"declaration"
|
|
4695
5144
|
]);
|
|
4696
|
-
var ApplicationFieldSchema =
|
|
4697
|
-
id:
|
|
4698
|
-
label:
|
|
4699
|
-
section:
|
|
5145
|
+
var ApplicationFieldSchema = z34.object({
|
|
5146
|
+
id: z34.string(),
|
|
5147
|
+
label: z34.string(),
|
|
5148
|
+
section: z34.string(),
|
|
4700
5149
|
fieldType: FieldTypeSchema,
|
|
4701
|
-
required:
|
|
4702
|
-
options:
|
|
4703
|
-
columns:
|
|
4704
|
-
requiresExplanationIfYes:
|
|
4705
|
-
condition:
|
|
4706
|
-
dependsOn:
|
|
4707
|
-
whenValue:
|
|
5150
|
+
required: z34.boolean(),
|
|
5151
|
+
options: z34.array(z34.string()).optional(),
|
|
5152
|
+
columns: z34.array(z34.string()).optional(),
|
|
5153
|
+
requiresExplanationIfYes: z34.boolean().optional(),
|
|
5154
|
+
condition: z34.object({
|
|
5155
|
+
dependsOn: z34.string(),
|
|
5156
|
+
whenValue: z34.string()
|
|
4708
5157
|
}).optional(),
|
|
4709
|
-
value:
|
|
4710
|
-
source:
|
|
4711
|
-
confidence:
|
|
5158
|
+
value: z34.string().optional(),
|
|
5159
|
+
source: z34.string().optional().describe("Where the value came from: auto-fill, user, lookup"),
|
|
5160
|
+
confidence: z34.enum(["confirmed", "high", "medium", "low"]).optional()
|
|
4712
5161
|
});
|
|
4713
|
-
var ApplicationClassifyResultSchema =
|
|
4714
|
-
isApplication:
|
|
4715
|
-
confidence:
|
|
4716
|
-
applicationType:
|
|
5162
|
+
var ApplicationClassifyResultSchema = z34.object({
|
|
5163
|
+
isApplication: z34.boolean(),
|
|
5164
|
+
confidence: z34.number().min(0).max(1),
|
|
5165
|
+
applicationType: z34.string().nullable()
|
|
4717
5166
|
});
|
|
4718
|
-
var FieldExtractionResultSchema =
|
|
4719
|
-
fields:
|
|
5167
|
+
var FieldExtractionResultSchema = z34.object({
|
|
5168
|
+
fields: z34.array(ApplicationFieldSchema)
|
|
4720
5169
|
});
|
|
4721
|
-
var AutoFillMatchSchema =
|
|
4722
|
-
fieldId:
|
|
4723
|
-
value:
|
|
4724
|
-
confidence:
|
|
4725
|
-
contextKey:
|
|
5170
|
+
var AutoFillMatchSchema = z34.object({
|
|
5171
|
+
fieldId: z34.string(),
|
|
5172
|
+
value: z34.string(),
|
|
5173
|
+
confidence: z34.enum(["confirmed"]),
|
|
5174
|
+
contextKey: z34.string()
|
|
4726
5175
|
});
|
|
4727
|
-
var AutoFillResultSchema =
|
|
4728
|
-
matches:
|
|
5176
|
+
var AutoFillResultSchema = z34.object({
|
|
5177
|
+
matches: z34.array(AutoFillMatchSchema)
|
|
4729
5178
|
});
|
|
4730
|
-
var QuestionBatchResultSchema =
|
|
4731
|
-
batches:
|
|
5179
|
+
var QuestionBatchResultSchema = z34.object({
|
|
5180
|
+
batches: z34.array(z34.array(z34.string()).describe("Array of field IDs in this batch"))
|
|
4732
5181
|
});
|
|
4733
|
-
var LookupRequestSchema =
|
|
4734
|
-
type:
|
|
4735
|
-
description:
|
|
4736
|
-
url:
|
|
4737
|
-
targetFieldIds:
|
|
5182
|
+
var LookupRequestSchema = z34.object({
|
|
5183
|
+
type: z34.string().describe("Type of lookup: 'records', 'website', 'policy'"),
|
|
5184
|
+
description: z34.string(),
|
|
5185
|
+
url: z34.string().optional(),
|
|
5186
|
+
targetFieldIds: z34.array(z34.string())
|
|
4738
5187
|
});
|
|
4739
|
-
var ReplyIntentSchema =
|
|
4740
|
-
primaryIntent:
|
|
4741
|
-
hasAnswers:
|
|
4742
|
-
questionText:
|
|
4743
|
-
questionFieldIds:
|
|
4744
|
-
lookupRequests:
|
|
5188
|
+
var ReplyIntentSchema = z34.object({
|
|
5189
|
+
primaryIntent: z34.enum(["answers_only", "question", "lookup_request", "mixed"]),
|
|
5190
|
+
hasAnswers: z34.boolean(),
|
|
5191
|
+
questionText: z34.string().optional(),
|
|
5192
|
+
questionFieldIds: z34.array(z34.string()).optional(),
|
|
5193
|
+
lookupRequests: z34.array(LookupRequestSchema).optional()
|
|
4745
5194
|
});
|
|
4746
|
-
var ParsedAnswerSchema =
|
|
4747
|
-
fieldId:
|
|
4748
|
-
value:
|
|
4749
|
-
explanation:
|
|
5195
|
+
var ParsedAnswerSchema = z34.object({
|
|
5196
|
+
fieldId: z34.string(),
|
|
5197
|
+
value: z34.string(),
|
|
5198
|
+
explanation: z34.string().optional()
|
|
4750
5199
|
});
|
|
4751
|
-
var AnswerParsingResultSchema =
|
|
4752
|
-
answers:
|
|
4753
|
-
unanswered:
|
|
5200
|
+
var AnswerParsingResultSchema = z34.object({
|
|
5201
|
+
answers: z34.array(ParsedAnswerSchema),
|
|
5202
|
+
unanswered: z34.array(z34.string()).describe("Field IDs that were not answered")
|
|
4754
5203
|
});
|
|
4755
|
-
var LookupFillSchema =
|
|
4756
|
-
fieldId:
|
|
4757
|
-
value:
|
|
4758
|
-
source:
|
|
5204
|
+
var LookupFillSchema = z34.object({
|
|
5205
|
+
fieldId: z34.string(),
|
|
5206
|
+
value: z34.string(),
|
|
5207
|
+
source: z34.string().describe("Specific citable reference, e.g. 'GL Policy #POL-12345 (Hartford)'")
|
|
4759
5208
|
});
|
|
4760
|
-
var LookupFillResultSchema =
|
|
4761
|
-
fills:
|
|
4762
|
-
unfillable:
|
|
4763
|
-
explanation:
|
|
5209
|
+
var LookupFillResultSchema = z34.object({
|
|
5210
|
+
fills: z34.array(LookupFillSchema),
|
|
5211
|
+
unfillable: z34.array(z34.string()),
|
|
5212
|
+
explanation: z34.string().optional()
|
|
4764
5213
|
});
|
|
4765
|
-
var FlatPdfPlacementSchema =
|
|
4766
|
-
fieldId:
|
|
4767
|
-
page:
|
|
4768
|
-
x:
|
|
4769
|
-
y:
|
|
4770
|
-
text:
|
|
4771
|
-
fontSize:
|
|
4772
|
-
isCheckmark:
|
|
5214
|
+
var FlatPdfPlacementSchema = z34.object({
|
|
5215
|
+
fieldId: z34.string(),
|
|
5216
|
+
page: z34.number(),
|
|
5217
|
+
x: z34.number().describe("Percentage from left edge (0-100)"),
|
|
5218
|
+
y: z34.number().describe("Percentage from top edge (0-100)"),
|
|
5219
|
+
text: z34.string(),
|
|
5220
|
+
fontSize: z34.number().optional(),
|
|
5221
|
+
isCheckmark: z34.boolean().optional()
|
|
4773
5222
|
});
|
|
4774
|
-
var AcroFormMappingSchema =
|
|
4775
|
-
fieldId:
|
|
4776
|
-
acroFormName:
|
|
4777
|
-
value:
|
|
5223
|
+
var AcroFormMappingSchema = z34.object({
|
|
5224
|
+
fieldId: z34.string(),
|
|
5225
|
+
acroFormName: z34.string(),
|
|
5226
|
+
value: z34.string()
|
|
4778
5227
|
});
|
|
4779
|
-
var QualityGateStatusSchema =
|
|
4780
|
-
var QualitySeveritySchema =
|
|
4781
|
-
var ApplicationQualityIssueSchema =
|
|
4782
|
-
code:
|
|
5228
|
+
var QualityGateStatusSchema = z34.enum(["passed", "warning", "failed"]);
|
|
5229
|
+
var QualitySeveritySchema = z34.enum(["info", "warning", "blocking"]);
|
|
5230
|
+
var ApplicationQualityIssueSchema = z34.object({
|
|
5231
|
+
code: z34.string(),
|
|
4783
5232
|
severity: QualitySeveritySchema,
|
|
4784
|
-
message:
|
|
4785
|
-
fieldId:
|
|
5233
|
+
message: z34.string(),
|
|
5234
|
+
fieldId: z34.string().optional()
|
|
4786
5235
|
});
|
|
4787
|
-
var ApplicationQualityRoundSchema =
|
|
4788
|
-
round:
|
|
4789
|
-
kind:
|
|
5236
|
+
var ApplicationQualityRoundSchema = z34.object({
|
|
5237
|
+
round: z34.number(),
|
|
5238
|
+
kind: z34.string(),
|
|
4790
5239
|
status: QualityGateStatusSchema,
|
|
4791
|
-
summary:
|
|
5240
|
+
summary: z34.string().optional()
|
|
4792
5241
|
});
|
|
4793
|
-
var ApplicationQualityArtifactSchema =
|
|
4794
|
-
kind:
|
|
4795
|
-
label:
|
|
4796
|
-
itemCount:
|
|
5242
|
+
var ApplicationQualityArtifactSchema = z34.object({
|
|
5243
|
+
kind: z34.string(),
|
|
5244
|
+
label: z34.string().optional(),
|
|
5245
|
+
itemCount: z34.number().optional()
|
|
4797
5246
|
});
|
|
4798
|
-
var ApplicationEmailReviewSchema =
|
|
4799
|
-
issues:
|
|
5247
|
+
var ApplicationEmailReviewSchema = z34.object({
|
|
5248
|
+
issues: z34.array(ApplicationQualityIssueSchema),
|
|
4800
5249
|
qualityGateStatus: QualityGateStatusSchema
|
|
4801
5250
|
});
|
|
4802
|
-
var ApplicationQualityReportSchema =
|
|
4803
|
-
issues:
|
|
4804
|
-
rounds:
|
|
4805
|
-
artifacts:
|
|
5251
|
+
var ApplicationQualityReportSchema = z34.object({
|
|
5252
|
+
issues: z34.array(ApplicationQualityIssueSchema),
|
|
5253
|
+
rounds: z34.array(ApplicationQualityRoundSchema).optional(),
|
|
5254
|
+
artifacts: z34.array(ApplicationQualityArtifactSchema).optional(),
|
|
4806
5255
|
emailReview: ApplicationEmailReviewSchema.optional(),
|
|
4807
5256
|
qualityGateStatus: QualityGateStatusSchema
|
|
4808
5257
|
});
|
|
4809
|
-
var ApplicationStateSchema =
|
|
4810
|
-
id:
|
|
4811
|
-
pdfBase64:
|
|
4812
|
-
title:
|
|
4813
|
-
applicationType:
|
|
4814
|
-
fields:
|
|
4815
|
-
batches:
|
|
4816
|
-
currentBatchIndex:
|
|
5258
|
+
var ApplicationStateSchema = z34.object({
|
|
5259
|
+
id: z34.string(),
|
|
5260
|
+
pdfBase64: z34.string().optional().describe("Original PDF, omitted after extraction"),
|
|
5261
|
+
title: z34.string().optional(),
|
|
5262
|
+
applicationType: z34.string().nullable().optional(),
|
|
5263
|
+
fields: z34.array(ApplicationFieldSchema),
|
|
5264
|
+
batches: z34.array(z34.array(z34.string())).optional(),
|
|
5265
|
+
currentBatchIndex: z34.number().default(0),
|
|
4817
5266
|
qualityReport: ApplicationQualityReportSchema.optional(),
|
|
4818
|
-
status:
|
|
4819
|
-
createdAt:
|
|
4820
|
-
updatedAt:
|
|
5267
|
+
status: z34.enum(["classifying", "extracting", "auto_filling", "batching", "collecting", "confirming", "mapping", "complete"]),
|
|
5268
|
+
createdAt: z34.number(),
|
|
5269
|
+
updatedAt: z34.number()
|
|
4821
5270
|
});
|
|
4822
5271
|
|
|
4823
5272
|
// src/application/agents/classifier.ts
|
|
@@ -5887,7 +6336,7 @@ Respond with the explanation text only \u2014 no JSON, no field ID, no extra for
|
|
|
5887
6336
|
}
|
|
5888
6337
|
|
|
5889
6338
|
// src/prompts/query/classify.ts
|
|
5890
|
-
function buildQueryClassifyPrompt(question, conversationContext) {
|
|
6339
|
+
function buildQueryClassifyPrompt(question, conversationContext, attachmentContext) {
|
|
5891
6340
|
return `You are a query classifier for an insurance document intelligence system.
|
|
5892
6341
|
|
|
5893
6342
|
Analyze the user's question and produce a structured classification.
|
|
@@ -5897,6 +6346,9 @@ ${question}
|
|
|
5897
6346
|
${conversationContext ? `
|
|
5898
6347
|
CONVERSATION CONTEXT:
|
|
5899
6348
|
${conversationContext}` : ""}
|
|
6349
|
+
${attachmentContext ? `
|
|
6350
|
+
ATTACHMENT CONTEXT:
|
|
6351
|
+
${attachmentContext}` : ""}
|
|
5900
6352
|
|
|
5901
6353
|
INSTRUCTIONS:
|
|
5902
6354
|
|
|
@@ -5917,6 +6369,7 @@ INSTRUCTIONS:
|
|
|
5917
6369
|
- requiresDocumentLookup: true if a specific document needs to be fetched by ID/number/carrier
|
|
5918
6370
|
- requiresChunkSearch: true if semantic search over document chunks is needed
|
|
5919
6371
|
- requiresConversationHistory: true if the question references prior conversation
|
|
6372
|
+
- If the user's attachment already contains critical facts, still request chunk/document lookup when policy or quote details should be cross-checked against stored records
|
|
5920
6373
|
|
|
5921
6374
|
CHUNK TYPES (for chunkTypes filter):
|
|
5922
6375
|
carrier_info, named_insured, coverage, endorsement, exclusion, condition, section, declaration, loss_history, premium, supplementary
|
|
@@ -5950,73 +6403,90 @@ Respond with the final answer, deduplicated citations array, overall confidence
|
|
|
5950
6403
|
}
|
|
5951
6404
|
|
|
5952
6405
|
// src/schemas/query.ts
|
|
5953
|
-
import { z as
|
|
5954
|
-
var QueryIntentSchema =
|
|
6406
|
+
import { z as z35 } from "zod";
|
|
6407
|
+
var QueryIntentSchema = z35.enum([
|
|
5955
6408
|
"policy_question",
|
|
5956
6409
|
"coverage_comparison",
|
|
5957
6410
|
"document_search",
|
|
5958
6411
|
"claims_inquiry",
|
|
5959
6412
|
"general_knowledge"
|
|
5960
6413
|
]);
|
|
5961
|
-
var
|
|
5962
|
-
|
|
6414
|
+
var QueryAttachmentKindSchema = z35.enum(["image", "pdf", "text"]);
|
|
6415
|
+
var QueryAttachmentSchema = z35.object({
|
|
6416
|
+
id: z35.string().optional().describe("Optional stable attachment ID from the caller"),
|
|
6417
|
+
kind: QueryAttachmentKindSchema,
|
|
6418
|
+
name: z35.string().optional().describe("Original filename or user-facing label"),
|
|
6419
|
+
mimeType: z35.string().optional().describe("MIME type such as image/jpeg or application/pdf"),
|
|
6420
|
+
base64: z35.string().optional().describe("Base64-encoded file content for image/pdf attachments"),
|
|
6421
|
+
text: z35.string().optional().describe("Plain-text attachment content when available"),
|
|
6422
|
+
description: z35.string().optional().describe("Caller-provided description of the attachment")
|
|
6423
|
+
});
|
|
6424
|
+
var SubQuestionSchema = z35.object({
|
|
6425
|
+
question: z35.string().describe("Atomic sub-question to retrieve and answer independently"),
|
|
5963
6426
|
intent: QueryIntentSchema,
|
|
5964
|
-
chunkTypes:
|
|
5965
|
-
documentFilters:
|
|
5966
|
-
type:
|
|
5967
|
-
carrier:
|
|
5968
|
-
insuredName:
|
|
5969
|
-
policyNumber:
|
|
5970
|
-
quoteNumber:
|
|
6427
|
+
chunkTypes: z35.array(z35.string()).optional().describe("Chunk types to filter retrieval (e.g. coverage, endorsement, declaration)"),
|
|
6428
|
+
documentFilters: z35.object({
|
|
6429
|
+
type: z35.enum(["policy", "quote"]).optional(),
|
|
6430
|
+
carrier: z35.string().optional(),
|
|
6431
|
+
insuredName: z35.string().optional(),
|
|
6432
|
+
policyNumber: z35.string().optional(),
|
|
6433
|
+
quoteNumber: z35.string().optional()
|
|
5971
6434
|
}).optional().describe("Structured filters to narrow document lookup")
|
|
5972
6435
|
});
|
|
5973
|
-
var QueryClassifyResultSchema =
|
|
6436
|
+
var QueryClassifyResultSchema = z35.object({
|
|
5974
6437
|
intent: QueryIntentSchema,
|
|
5975
|
-
subQuestions:
|
|
5976
|
-
requiresDocumentLookup:
|
|
5977
|
-
requiresChunkSearch:
|
|
5978
|
-
requiresConversationHistory:
|
|
6438
|
+
subQuestions: z35.array(SubQuestionSchema).min(1).describe("Decomposed atomic sub-questions"),
|
|
6439
|
+
requiresDocumentLookup: z35.boolean().describe("Whether structured document lookup is needed"),
|
|
6440
|
+
requiresChunkSearch: z35.boolean().describe("Whether semantic chunk search is needed"),
|
|
6441
|
+
requiresConversationHistory: z35.boolean().describe("Whether conversation history is relevant")
|
|
5979
6442
|
});
|
|
5980
|
-
var EvidenceItemSchema =
|
|
5981
|
-
source:
|
|
5982
|
-
chunkId:
|
|
5983
|
-
documentId:
|
|
5984
|
-
turnId:
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
6443
|
+
var EvidenceItemSchema = z35.object({
|
|
6444
|
+
source: z35.enum(["chunk", "document", "conversation", "attachment"]),
|
|
6445
|
+
chunkId: z35.string().optional(),
|
|
6446
|
+
documentId: z35.string().optional(),
|
|
6447
|
+
turnId: z35.string().optional(),
|
|
6448
|
+
attachmentId: z35.string().optional(),
|
|
6449
|
+
text: z35.string().describe("Text excerpt from the source"),
|
|
6450
|
+
relevance: z35.number().min(0).max(1),
|
|
6451
|
+
metadata: z35.array(z35.object({ key: z35.string(), value: z35.string() })).optional()
|
|
5988
6452
|
});
|
|
5989
|
-
var
|
|
5990
|
-
|
|
5991
|
-
|
|
6453
|
+
var AttachmentInterpretationSchema = z35.object({
|
|
6454
|
+
summary: z35.string().describe("Concise summary of what the attachment shows or contains"),
|
|
6455
|
+
extractedFacts: z35.array(z35.string()).describe("Specific observable or document facts grounded in the attachment"),
|
|
6456
|
+
recommendedFocus: z35.array(z35.string()).describe("Important details to incorporate when answering follow-up questions"),
|
|
6457
|
+
confidence: z35.number().min(0).max(1)
|
|
5992
6458
|
});
|
|
5993
|
-
var
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
documentId: z34.string(),
|
|
5997
|
-
documentType: z34.enum(["policy", "quote"]).optional(),
|
|
5998
|
-
field: z34.string().optional().describe("Specific field path, e.g. coverages[0].deductible"),
|
|
5999
|
-
quote: z34.string().describe("Exact text from source that supports the claim"),
|
|
6000
|
-
relevance: z34.number().min(0).max(1)
|
|
6459
|
+
var RetrievalResultSchema = z35.object({
|
|
6460
|
+
subQuestion: z35.string(),
|
|
6461
|
+
evidence: z35.array(EvidenceItemSchema)
|
|
6001
6462
|
});
|
|
6002
|
-
var
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6463
|
+
var CitationSchema = z35.object({
|
|
6464
|
+
index: z35.number().describe("Citation number [1], [2], etc."),
|
|
6465
|
+
chunkId: z35.string().describe("Source chunk ID, e.g. doc-123:coverage:2"),
|
|
6466
|
+
documentId: z35.string(),
|
|
6467
|
+
documentType: z35.enum(["policy", "quote"]).optional(),
|
|
6468
|
+
field: z35.string().optional().describe("Specific field path, e.g. coverages[0].deductible"),
|
|
6469
|
+
quote: z35.string().describe("Exact text from source that supports the claim"),
|
|
6470
|
+
relevance: z35.number().min(0).max(1)
|
|
6008
6471
|
});
|
|
6009
|
-
var
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6472
|
+
var SubAnswerSchema = z35.object({
|
|
6473
|
+
subQuestion: z35.string(),
|
|
6474
|
+
answer: z35.string(),
|
|
6475
|
+
citations: z35.array(CitationSchema),
|
|
6476
|
+
confidence: z35.number().min(0).max(1),
|
|
6477
|
+
needsMoreContext: z35.boolean().describe("True if evidence was insufficient to answer fully")
|
|
6013
6478
|
});
|
|
6014
|
-
var
|
|
6015
|
-
|
|
6016
|
-
|
|
6479
|
+
var VerifyResultSchema = z35.object({
|
|
6480
|
+
approved: z35.boolean().describe("Whether all sub-answers are adequately grounded"),
|
|
6481
|
+
issues: z35.array(z35.string()).describe("Specific grounding or consistency issues found"),
|
|
6482
|
+
retrySubQuestions: z35.array(z35.string()).optional().describe("Sub-questions that need additional retrieval or re-reasoning")
|
|
6483
|
+
});
|
|
6484
|
+
var QueryResultSchema = z35.object({
|
|
6485
|
+
answer: z35.string(),
|
|
6486
|
+
citations: z35.array(CitationSchema),
|
|
6017
6487
|
intent: QueryIntentSchema,
|
|
6018
|
-
confidence:
|
|
6019
|
-
followUp:
|
|
6488
|
+
confidence: z35.number().min(0).max(1),
|
|
6489
|
+
followUp: z35.string().optional().describe("Suggested follow-up question if applicable")
|
|
6020
6490
|
});
|
|
6021
6491
|
|
|
6022
6492
|
// src/query/retriever.ts
|
|
@@ -6306,7 +6776,7 @@ async function verify(originalQuestion, subAnswers, allEvidence, config) {
|
|
|
6306
6776
|
|
|
6307
6777
|
// src/query/quality.ts
|
|
6308
6778
|
function sourceIdForEvidence(evidence) {
|
|
6309
|
-
return evidence.chunkId ?? evidence.documentId ?? evidence.turnId;
|
|
6779
|
+
return evidence.chunkId ?? evidence.documentId ?? evidence.turnId ?? evidence.attachmentId;
|
|
6310
6780
|
}
|
|
6311
6781
|
function citationSourceId(citation) {
|
|
6312
6782
|
return citation.chunkId || citation.documentId;
|
|
@@ -6410,6 +6880,152 @@ function buildQueryReviewReport(params) {
|
|
|
6410
6880
|
};
|
|
6411
6881
|
}
|
|
6412
6882
|
|
|
6883
|
+
// src/prompts/query/interpret-attachment.ts
|
|
6884
|
+
function buildInterpretAttachmentPrompt(question, attachment) {
|
|
6885
|
+
const attachmentLabel = attachment.name ?? attachment.id ?? "attachment";
|
|
6886
|
+
const descriptor = [
|
|
6887
|
+
`Attachment: ${attachmentLabel}`,
|
|
6888
|
+
`Kind: ${attachment.kind}`,
|
|
6889
|
+
attachment.mimeType ? `MIME type: ${attachment.mimeType}` : null,
|
|
6890
|
+
attachment.description ? `Caller description: ${attachment.description}` : null
|
|
6891
|
+
].filter(Boolean).join("\n");
|
|
6892
|
+
return `You are interpreting a user-supplied attachment for an insurance-support question.
|
|
6893
|
+
|
|
6894
|
+
USER QUESTION:
|
|
6895
|
+
${question}
|
|
6896
|
+
|
|
6897
|
+
ATTACHMENT METADATA:
|
|
6898
|
+
${descriptor}
|
|
6899
|
+
|
|
6900
|
+
${attachment.kind === "text" && attachment.text ? `ATTACHMENT TEXT:
|
|
6901
|
+
${attachment.text}
|
|
6902
|
+
` : "The attachment content is provided separately as a file or image input.\n"}
|
|
6903
|
+
INSTRUCTIONS:
|
|
6904
|
+
1. Describe what the attachment appears to show or contain in a concise summary.
|
|
6905
|
+
2. Extract concrete facts that may matter when answering the user's question.
|
|
6906
|
+
3. Note the most important details to carry forward into follow-up questions.
|
|
6907
|
+
4. If the attachment is a document, identify the key business or insurance details visible.
|
|
6908
|
+
5. If the attachment is a photo of damage or a real-world issue, describe the observable issue without guessing beyond what is visible.
|
|
6909
|
+
6. Do not invent unreadable text. If something is unclear, say so in the summary or extracted facts.
|
|
6910
|
+
|
|
6911
|
+
Respond with the structured interpretation.`;
|
|
6912
|
+
}
|
|
6913
|
+
|
|
6914
|
+
// src/query/multimodal.ts
|
|
6915
|
+
function attachmentSourceId(attachment, index) {
|
|
6916
|
+
return attachment.id ?? `attachment-${index + 1}`;
|
|
6917
|
+
}
|
|
6918
|
+
function buildAttachmentProviderOptions(attachment, providerOptions) {
|
|
6919
|
+
const merged = {
|
|
6920
|
+
...providerOptions,
|
|
6921
|
+
attachments: [
|
|
6922
|
+
{
|
|
6923
|
+
kind: attachment.kind,
|
|
6924
|
+
name: attachment.name,
|
|
6925
|
+
mimeType: attachment.mimeType,
|
|
6926
|
+
base64: attachment.base64,
|
|
6927
|
+
text: attachment.text,
|
|
6928
|
+
description: attachment.description
|
|
6929
|
+
}
|
|
6930
|
+
]
|
|
6931
|
+
};
|
|
6932
|
+
if (attachment.kind === "pdf" && attachment.base64) {
|
|
6933
|
+
merged.pdfBase64 = attachment.base64;
|
|
6934
|
+
}
|
|
6935
|
+
if (attachment.kind === "image" && attachment.base64) {
|
|
6936
|
+
merged.images = [
|
|
6937
|
+
{
|
|
6938
|
+
imageBase64: attachment.base64,
|
|
6939
|
+
mimeType: attachment.mimeType ?? "image/jpeg"
|
|
6940
|
+
}
|
|
6941
|
+
];
|
|
6942
|
+
}
|
|
6943
|
+
return merged;
|
|
6944
|
+
}
|
|
6945
|
+
function buildAttachmentEvidenceText(attachment, interpretation) {
|
|
6946
|
+
const lines = [
|
|
6947
|
+
`Attachment kind: ${attachment.kind}`,
|
|
6948
|
+
attachment.name ? `Attachment name: ${attachment.name}` : null,
|
|
6949
|
+
attachment.mimeType ? `MIME type: ${attachment.mimeType}` : null,
|
|
6950
|
+
attachment.description ? `Caller description: ${attachment.description}` : null,
|
|
6951
|
+
`Summary: ${interpretation.summary}`,
|
|
6952
|
+
interpretation.extractedFacts.length > 0 ? `Extracted facts:
|
|
6953
|
+
${interpretation.extractedFacts.map((fact) => `- ${fact}`).join("\n")}` : null,
|
|
6954
|
+
interpretation.recommendedFocus.length > 0 ? `Important follow-up details:
|
|
6955
|
+
${interpretation.recommendedFocus.map((item) => `- ${item}`).join("\n")}` : null,
|
|
6956
|
+
attachment.kind === "text" && attachment.text ? `Original text:
|
|
6957
|
+
${attachment.text}` : null
|
|
6958
|
+
];
|
|
6959
|
+
return lines.filter(Boolean).join("\n");
|
|
6960
|
+
}
|
|
6961
|
+
async function interpretAttachments(params) {
|
|
6962
|
+
const { attachments = [], question, generateObject, providerOptions, log, onUsage } = params;
|
|
6963
|
+
if (attachments.length === 0) {
|
|
6964
|
+
return { evidence: [] };
|
|
6965
|
+
}
|
|
6966
|
+
const evidence = [];
|
|
6967
|
+
for (const [index, attachment] of attachments.entries()) {
|
|
6968
|
+
const id = attachmentSourceId(attachment, index);
|
|
6969
|
+
if (attachment.kind === "text" && attachment.text) {
|
|
6970
|
+
const textEvidence = buildAttachmentEvidenceText(attachment, {
|
|
6971
|
+
summary: attachment.description ?? "User supplied text context.",
|
|
6972
|
+
extractedFacts: [attachment.text],
|
|
6973
|
+
recommendedFocus: [],
|
|
6974
|
+
confidence: 1
|
|
6975
|
+
});
|
|
6976
|
+
evidence.push({
|
|
6977
|
+
source: "attachment",
|
|
6978
|
+
attachmentId: id,
|
|
6979
|
+
chunkId: id,
|
|
6980
|
+
documentId: id,
|
|
6981
|
+
text: textEvidence,
|
|
6982
|
+
relevance: 0.95,
|
|
6983
|
+
metadata: [
|
|
6984
|
+
{ key: "kind", value: attachment.kind },
|
|
6985
|
+
...attachment.name ? [{ key: "name", value: attachment.name }] : []
|
|
6986
|
+
]
|
|
6987
|
+
});
|
|
6988
|
+
continue;
|
|
6989
|
+
}
|
|
6990
|
+
const prompt = buildInterpretAttachmentPrompt(question, attachment);
|
|
6991
|
+
const { object, usage } = await safeGenerateObject(
|
|
6992
|
+
generateObject,
|
|
6993
|
+
{
|
|
6994
|
+
prompt,
|
|
6995
|
+
schema: AttachmentInterpretationSchema,
|
|
6996
|
+
maxTokens: 2048,
|
|
6997
|
+
providerOptions: buildAttachmentProviderOptions(attachment, providerOptions)
|
|
6998
|
+
},
|
|
6999
|
+
{
|
|
7000
|
+
fallback: {
|
|
7001
|
+
summary: attachment.description ?? `User supplied ${attachment.kind} attachment.`,
|
|
7002
|
+
extractedFacts: [],
|
|
7003
|
+
recommendedFocus: [],
|
|
7004
|
+
confidence: 0.2
|
|
7005
|
+
},
|
|
7006
|
+
log,
|
|
7007
|
+
onError: (error, attempt) => log?.(`Attachment interpretation attempt ${attempt + 1} failed for "${attachment.name ?? id}": ${error}`)
|
|
7008
|
+
}
|
|
7009
|
+
);
|
|
7010
|
+
onUsage?.(usage);
|
|
7011
|
+
evidence.push({
|
|
7012
|
+
source: "attachment",
|
|
7013
|
+
attachmentId: id,
|
|
7014
|
+
chunkId: id,
|
|
7015
|
+
documentId: id,
|
|
7016
|
+
text: buildAttachmentEvidenceText(attachment, object),
|
|
7017
|
+
relevance: Math.max(0.7, object.confidence),
|
|
7018
|
+
metadata: [
|
|
7019
|
+
{ key: "kind", value: attachment.kind },
|
|
7020
|
+
...attachment.name ? [{ key: "name", value: attachment.name }] : []
|
|
7021
|
+
]
|
|
7022
|
+
});
|
|
7023
|
+
}
|
|
7024
|
+
const contextSummary = evidence.map((item, index) => `Attachment ${index + 1}:
|
|
7025
|
+
${item.text}`).join("\n\n");
|
|
7026
|
+
return { evidence, contextSummary };
|
|
7027
|
+
}
|
|
7028
|
+
|
|
6413
7029
|
// src/query/coordinator.ts
|
|
6414
7030
|
function createQueryAgent(config) {
|
|
6415
7031
|
const {
|
|
@@ -6437,13 +7053,23 @@ function createQueryAgent(config) {
|
|
|
6437
7053
|
}
|
|
6438
7054
|
async function query(input) {
|
|
6439
7055
|
totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
6440
|
-
const { question, conversationId, context } = input;
|
|
7056
|
+
const { question, conversationId, context, attachments } = input;
|
|
6441
7057
|
const pipelineCtx = createPipelineContext({
|
|
6442
7058
|
id: `query-${Date.now()}`
|
|
6443
7059
|
});
|
|
7060
|
+
onProgress?.("Interpreting attachments...");
|
|
7061
|
+
const { evidence: attachmentEvidence, contextSummary: attachmentContext } = await interpretAttachments({
|
|
7062
|
+
attachments,
|
|
7063
|
+
question,
|
|
7064
|
+
generateObject,
|
|
7065
|
+
providerOptions,
|
|
7066
|
+
log,
|
|
7067
|
+
onUsage: trackUsage
|
|
7068
|
+
});
|
|
7069
|
+
await pipelineCtx.save("attachments", { attachmentEvidence });
|
|
6444
7070
|
onProgress?.("Classifying query...");
|
|
6445
|
-
const classification = await classify(question, conversationId);
|
|
6446
|
-
await pipelineCtx.save("classify", { classification });
|
|
7071
|
+
const classification = await classify(question, conversationId, attachmentContext);
|
|
7072
|
+
await pipelineCtx.save("classify", { classification, attachmentEvidence });
|
|
6447
7073
|
onProgress?.(`Retrieving evidence for ${classification.subQuestions.length} sub-question(s)...`);
|
|
6448
7074
|
const retrieverConfig = {
|
|
6449
7075
|
documentStore,
|
|
@@ -6456,8 +7082,8 @@ function createQueryAgent(config) {
|
|
|
6456
7082
|
(sq) => limit(() => retrieve(sq, conversationId, retrieverConfig))
|
|
6457
7083
|
)
|
|
6458
7084
|
);
|
|
6459
|
-
const allEvidence = retrievalResults.flatMap((r) => r.evidence);
|
|
6460
|
-
await pipelineCtx.save("retrieve", { classification, evidence: allEvidence });
|
|
7085
|
+
const allEvidence = [...attachmentEvidence, ...retrievalResults.flatMap((r) => r.evidence)];
|
|
7086
|
+
await pipelineCtx.save("retrieve", { classification, attachmentEvidence, evidence: allEvidence });
|
|
6461
7087
|
onProgress?.("Reasoning over evidence...");
|
|
6462
7088
|
const reasonerConfig = { generateObject, providerOptions };
|
|
6463
7089
|
const reasonResults = await Promise.allSettled(
|
|
@@ -6466,7 +7092,7 @@ function createQueryAgent(config) {
|
|
|
6466
7092
|
const { subAnswer, usage } = await reason(
|
|
6467
7093
|
sq.question,
|
|
6468
7094
|
sq.intent,
|
|
6469
|
-
retrievalResults[i].evidence,
|
|
7095
|
+
[...attachmentEvidence, ...retrievalResults[i].evidence],
|
|
6470
7096
|
reasonerConfig
|
|
6471
7097
|
);
|
|
6472
7098
|
trackUsage(usage);
|
|
@@ -6490,7 +7116,7 @@ function createQueryAgent(config) {
|
|
|
6490
7116
|
});
|
|
6491
7117
|
}
|
|
6492
7118
|
}
|
|
6493
|
-
await pipelineCtx.save("reason", { classification, evidence: allEvidence, subAnswers });
|
|
7119
|
+
await pipelineCtx.save("reason", { classification, attachmentEvidence, evidence: allEvidence, subAnswers });
|
|
6494
7120
|
onProgress?.("Verifying answer grounding...");
|
|
6495
7121
|
const verifierConfig = { generateObject, providerOptions };
|
|
6496
7122
|
const verifyRounds = [];
|
|
@@ -6538,7 +7164,7 @@ function createQueryAgent(config) {
|
|
|
6538
7164
|
const { subAnswer, usage: u } = await reason(
|
|
6539
7165
|
sq.question,
|
|
6540
7166
|
sq.intent,
|
|
6541
|
-
retryRetrievals[i].evidence,
|
|
7167
|
+
[...attachmentEvidence, ...retryRetrievals[i].evidence],
|
|
6542
7168
|
reasonerConfig
|
|
6543
7169
|
);
|
|
6544
7170
|
trackUsage(u);
|
|
@@ -6573,6 +7199,7 @@ function createQueryAgent(config) {
|
|
|
6573
7199
|
});
|
|
6574
7200
|
await pipelineCtx.save("review", {
|
|
6575
7201
|
classification,
|
|
7202
|
+
attachmentEvidence,
|
|
6576
7203
|
evidence: allEvidence,
|
|
6577
7204
|
subAnswers,
|
|
6578
7205
|
reviewReport
|
|
@@ -6605,7 +7232,7 @@ function createQueryAgent(config) {
|
|
|
6605
7232
|
}
|
|
6606
7233
|
return { ...queryResult, tokenUsage: totalUsage, reviewReport };
|
|
6607
7234
|
}
|
|
6608
|
-
async function classify(question, conversationId) {
|
|
7235
|
+
async function classify(question, conversationId, attachmentContext) {
|
|
6609
7236
|
let conversationContext;
|
|
6610
7237
|
if (conversationId) {
|
|
6611
7238
|
try {
|
|
@@ -6616,7 +7243,7 @@ function createQueryAgent(config) {
|
|
|
6616
7243
|
} catch {
|
|
6617
7244
|
}
|
|
6618
7245
|
}
|
|
6619
|
-
const prompt = buildQueryClassifyPrompt(question, conversationContext);
|
|
7246
|
+
const prompt = buildQueryClassifyPrompt(question, conversationContext, attachmentContext);
|
|
6620
7247
|
const { object, usage } = await safeGenerateObject(
|
|
6621
7248
|
generateObject,
|
|
6622
7249
|
{
|
|
@@ -6831,6 +7458,7 @@ export {
|
|
|
6831
7458
|
ApplicationQualityReportSchema,
|
|
6832
7459
|
ApplicationQualityRoundSchema,
|
|
6833
7460
|
ApplicationStateSchema,
|
|
7461
|
+
AttachmentInterpretationSchema,
|
|
6834
7462
|
AuditTypeSchema,
|
|
6835
7463
|
AutoFillMatchSchema,
|
|
6836
7464
|
AutoFillResultSchema,
|
|
@@ -6952,6 +7580,8 @@ export {
|
|
|
6952
7580
|
ProducerInfoSchema,
|
|
6953
7581
|
ProfessionalLiabilityDeclarationsSchema,
|
|
6954
7582
|
QUOTE_SECTION_TYPES,
|
|
7583
|
+
QueryAttachmentKindSchema,
|
|
7584
|
+
QueryAttachmentSchema,
|
|
6955
7585
|
QueryClassifyResultSchema,
|
|
6956
7586
|
QueryIntentSchema,
|
|
6957
7587
|
QueryResultSchema,
|
|
@@ -7010,6 +7640,7 @@ export {
|
|
|
7010
7640
|
buildFormattingPrompt,
|
|
7011
7641
|
buildIdentityPrompt,
|
|
7012
7642
|
buildIntentPrompt,
|
|
7643
|
+
buildInterpretAttachmentPrompt,
|
|
7013
7644
|
buildLookupFillPrompt,
|
|
7014
7645
|
buildQueryClassifyPrompt,
|
|
7015
7646
|
buildQuestionBatchPrompt,
|