rust-kgdb 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Insurance Underwriting Agent - Production Example
3
+ *
4
+ * Real-world commercial insurance underwriting using rust-kgdb:
5
+ * - Risk factor analysis from knowledge graph
6
+ * - GraphFrames for exposure correlation
7
+ * - Embeddings for similar policy matching
8
+ * - Datalog rules for automated decisioning
9
+ *
10
+ * Based on ISO (Insurance Services Office) rating factors:
11
+ * - Business classification (NAICS/SIC codes)
12
+ * - Territory risk factors
13
+ * - Loss history analysis
14
+ * - Exposure correlation
15
+ */
16
+
17
+ const {
18
+ GraphDB,
19
+ GraphFrame,
20
+ EmbeddingService,
21
+ DatalogProgram,
22
+ evaluateDatalog,
23
+ queryDatalog,
24
+ getVersion
25
+ } = require('../index.js')
26
+
27
+ // ============================================
28
+ // STEP 1: Commercial Insurance Policy Data
29
+ // ============================================
30
+
31
+ const UNDERWRITING_DATA_TTL = `
32
+ @prefix : <http://underwriting.org/> .
33
+ @prefix risk: <http://underwriting.org/risk/> .
34
+ @prefix pol: <http://underwriting.org/policy/> .
35
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
36
+
37
+ # === BUSINESS ENTITIES ===
38
+ :BUS001 :name "Acme Manufacturing" ;
39
+ :naics "332119" ;
40
+ :employees "250" ;
41
+ :revenue "45000000" ;
42
+ :territory "FL-33101" ;
43
+ :yearsInBusiness "15" .
44
+
45
+ :BUS002 :name "TechStart LLC" ;
46
+ :naics "541512" ;
47
+ :employees "45" ;
48
+ :revenue "8500000" ;
49
+ :territory "CA-94105" ;
50
+ :yearsInBusiness "3" .
51
+
52
+ :BUS003 :name "SafeHaul Logistics" ;
53
+ :naics "484121" ;
54
+ :employees "120" ;
55
+ :revenue "22000000" ;
56
+ :territory "TX-75201" ;
57
+ :yearsInBusiness "8" .
58
+
59
+ :BUS004 :name "Downtown Restaurant Group" ;
60
+ :naics "722511" ;
61
+ :employees "85" ;
62
+ :revenue "12000000" ;
63
+ :territory "NY-10001" ;
64
+ :yearsInBusiness "12" .
65
+
66
+ # === RISK FACTORS ===
67
+ risk:NAICS-332119 :baseRate "2.45" ; :modClass "manufacturing" ; :hazardGrade "B" .
68
+ risk:NAICS-541512 :baseRate "0.85" ; :modClass "tech" ; :hazardGrade "A" .
69
+ risk:NAICS-484121 :baseRate "3.80" ; :modClass "transportation" ; :hazardGrade "C" .
70
+ risk:NAICS-722511 :baseRate "1.95" ; :modClass "hospitality" ; :hazardGrade "B" .
71
+
72
+ risk:FL-33101 :territoryMod "1.35" ; :catExposure "hurricane" .
73
+ risk:CA-94105 :territoryMod "1.15" ; :catExposure "earthquake" .
74
+ risk:TX-75201 :territoryMod "1.05" ; :catExposure "tornado" .
75
+ risk:NY-10001 :territoryMod "1.25" ; :catExposure "flood" .
76
+
77
+ # === LOSS HISTORY ===
78
+ :BUS001 :lossCount "2" ; :lossAmount "125000" ; :lossRatio "0.45" .
79
+ :BUS002 :lossCount "0" ; :lossAmount "0" ; :lossRatio "0.00" .
80
+ :BUS003 :lossCount "4" ; :lossAmount "380000" ; :lossRatio "0.72" .
81
+ :BUS004 :lossCount "1" ; :lossAmount "45000" ; :lossRatio "0.28" .
82
+
83
+ # === POLICY APPLICATIONS ===
84
+ pol:APP001 :applicant :BUS001 ; :coverage "GL" ; :limit "2000000" ; :deductible "10000" .
85
+ pol:APP002 :applicant :BUS002 ; :coverage "E&O" ; :limit "5000000" ; :deductible "25000" .
86
+ pol:APP003 :applicant :BUS003 ; :coverage "AL" ; :limit "1000000" ; :deductible "5000" .
87
+ pol:APP004 :applicant :BUS004 ; :coverage "GL" ; :limit "1000000" ; :deductible "5000" .
88
+ `
89
+
90
+ // ============================================
91
+ // STEP 2: Risk Score Embedding Generator
92
+ // ============================================
93
+
94
+ function generateRiskEmbedding(naicsClass, lossRatio, territoryMod, yearsInBusiness) {
95
+ const embedding = new Array(384).fill(0)
96
+
97
+ // Industry risk encoding (dims 0-95)
98
+ const industryRisk = {
99
+ manufacturing: 0.6,
100
+ tech: 0.25,
101
+ transportation: 0.85,
102
+ hospitality: 0.55
103
+ }
104
+ const risk = industryRisk[naicsClass] || 0.5
105
+ for (let i = 0; i < 96; i++) {
106
+ embedding[i] = risk * (0.7 + Math.sin(i * 0.1) * 0.3)
107
+ }
108
+
109
+ // Loss ratio encoding (dims 96-191)
110
+ for (let i = 96; i < 192; i++) {
111
+ embedding[i] = lossRatio * (0.6 + Math.cos((i - 96) * 0.08) * 0.4)
112
+ }
113
+
114
+ // Territory encoding (dims 192-287)
115
+ for (let i = 192; i < 288; i++) {
116
+ embedding[i] = territoryMod * (0.5 + Math.sin((i - 192) * 0.12) * 0.5)
117
+ }
118
+
119
+ // Experience factor (dims 288-383)
120
+ const expFactor = Math.min(yearsInBusiness / 20, 1)
121
+ for (let i = 288; i < 384; i++) {
122
+ embedding[i] = (1 - expFactor) * 0.5 * Math.cos((i - 288) * 0.06)
123
+ }
124
+
125
+ // Normalize
126
+ const mag = Math.sqrt(embedding.reduce((s, v) => s + v * v, 0))
127
+ if (mag > 0) {
128
+ for (let i = 0; i < 384; i++) embedding[i] /= mag
129
+ }
130
+
131
+ return embedding
132
+ }
133
+
134
+ // ============================================
135
+ // PREMIUM CALCULATION
136
+ // ============================================
137
+
138
+ function calculatePremium(baseRate, exposure, territoryMod, lossRatio, yearsInBusiness) {
139
+ // ISO-based premium calculation
140
+ const experienceMod = yearsInBusiness >= 10 ? 0.90 : yearsInBusiness >= 5 ? 0.95 : 1.05
141
+ const lossMod = lossRatio < 0.3 ? 0.85 : lossRatio < 0.5 ? 1.0 : lossRatio < 0.7 ? 1.15 : 1.35
142
+
143
+ const premium = baseRate * exposure * territoryMod * experienceMod * lossMod
144
+ return Math.round(premium * 100) / 100
145
+ }
146
+
147
+ // ============================================
148
+ // MAIN UNDERWRITING PIPELINE
149
+ // ============================================
150
+
151
+ async function runUnderwriting() {
152
+ console.log('='.repeat(70))
153
+ console.log(' INSURANCE UNDERWRITING AGENT - Production Pipeline')
154
+ console.log(' rust-kgdb v' + getVersion() + ' | Neuro-Symbolic AI Framework')
155
+ console.log('='.repeat(70))
156
+ console.log()
157
+
158
+ // ===== PHASE 1: Knowledge Graph =====
159
+ console.log('[PHASE 1] Loading Underwriting Knowledge Base')
160
+ console.log('-'.repeat(50))
161
+
162
+ const db = new GraphDB('http://underwriting.org/kb')
163
+ db.loadTtl(UNDERWRITING_DATA_TTL, null)
164
+
165
+ console.log(` Knowledge graph: ${db.countTriples()} triples`)
166
+ console.log(` URI: ${db.getGraphUri()}`)
167
+
168
+ // Query business entities
169
+ const businesses = db.querySelect(`
170
+ PREFIX : <http://underwriting.org/>
171
+ SELECT ?bus ?name ?naics ?employees WHERE {
172
+ ?bus :name ?name .
173
+ ?bus :naics ?naics .
174
+ ?bus :employees ?employees .
175
+ }
176
+ `)
177
+
178
+ console.log(` Business entities: ${businesses.length}`)
179
+ businesses.forEach(b => {
180
+ console.log(` - ${b.bindings.name || b.bindings.bus}: NAICS ${b.bindings.naics}, ${b.bindings.employees} employees`)
181
+ })
182
+ console.log()
183
+
184
+ // ===== PHASE 2: Risk Factor Analysis =====
185
+ console.log('[PHASE 2] Risk Factor Analysis')
186
+ console.log('-'.repeat(50))
187
+
188
+ // Build risk correlation graph
189
+ const vertices = JSON.stringify([
190
+ { id: 'BUS001' }, { id: 'BUS002' }, { id: 'BUS003' }, { id: 'BUS004' },
191
+ { id: 'hurricane' }, { id: 'earthquake' }, { id: 'tornado' }, { id: 'flood' },
192
+ { id: 'manufacturing' }, { id: 'tech' }, { id: 'transportation' }, { id: 'hospitality' }
193
+ ])
194
+
195
+ const edges = JSON.stringify([
196
+ // Business to CAT exposure
197
+ { src: 'BUS001', dst: 'hurricane' },
198
+ { src: 'BUS002', dst: 'earthquake' },
199
+ { src: 'BUS003', dst: 'tornado' },
200
+ { src: 'BUS004', dst: 'flood' },
201
+ // Business to industry
202
+ { src: 'BUS001', dst: 'manufacturing' },
203
+ { src: 'BUS002', dst: 'tech' },
204
+ { src: 'BUS003', dst: 'transportation' },
205
+ { src: 'BUS004', dst: 'hospitality' },
206
+ // Correlated risks
207
+ { src: 'hurricane', dst: 'flood' },
208
+ { src: 'manufacturing', dst: 'transportation' }
209
+ ])
210
+
211
+ const graph = new GraphFrame(vertices, edges)
212
+ console.log(` Risk network: ${graph.vertexCount()} nodes, ${graph.edgeCount()} edges`)
213
+
214
+ // PageRank for risk concentration
215
+ const pr = JSON.parse(graph.pageRank(0.15, 20))
216
+ console.log(' Risk concentration (PageRank):')
217
+ if (pr.ranks) {
218
+ const sorted = Object.entries(pr.ranks)
219
+ .filter(([k]) => k.startsWith('BUS'))
220
+ .sort((a, b) => b[1] - a[1])
221
+ sorted.forEach(([node, score]) => {
222
+ console.log(` - ${node}: ${score.toFixed(4)}`)
223
+ })
224
+ }
225
+
226
+ // Connected components (correlated exposures)
227
+ const cc = JSON.parse(graph.connectedComponents())
228
+ console.log(' Exposure correlation: Businesses share connected risk factors')
229
+ console.log()
230
+
231
+ // ===== PHASE 3: Similarity Analysis =====
232
+ console.log('[PHASE 3] Similar Risk Profile Matching')
233
+ console.log('-'.repeat(50))
234
+
235
+ const embeddings = new EmbeddingService()
236
+
237
+ // Risk profiles for each business
238
+ const riskProfiles = [
239
+ { id: 'BUS001', class: 'manufacturing', lossRatio: 0.45, territory: 1.35, years: 15 },
240
+ { id: 'BUS002', class: 'tech', lossRatio: 0.00, territory: 1.15, years: 3 },
241
+ { id: 'BUS003', class: 'transportation', lossRatio: 0.72, territory: 1.05, years: 8 },
242
+ { id: 'BUS004', class: 'hospitality', lossRatio: 0.28, territory: 1.25, years: 12 }
243
+ ]
244
+
245
+ riskProfiles.forEach(p => {
246
+ const vec = generateRiskEmbedding(p.class, p.lossRatio, p.territory, p.years)
247
+ embeddings.storeVector(p.id, vec)
248
+ })
249
+
250
+ console.log(` Risk embeddings stored: ${riskProfiles.length}`)
251
+ embeddings.rebuildIndex()
252
+
253
+ // Find similar risk profiles to the high-risk transportation company
254
+ const similar = JSON.parse(embeddings.findSimilar('BUS003', 5, 0.3))
255
+ console.log(' Profiles similar to BUS003 (high-risk transportation):')
256
+ similar.filter(s => s.entity !== 'BUS003').forEach(s => {
257
+ const profile = riskProfiles.find(p => p.id === s.entity)
258
+ if (profile) {
259
+ console.log(` - ${s.entity}: ${profile.class}, loss ratio ${profile.lossRatio}`)
260
+ }
261
+ })
262
+ console.log()
263
+
264
+ // ===== PHASE 4: Automated Decision Rules =====
265
+ console.log('[PHASE 4] Underwriting Decision Rules')
266
+ console.log('-'.repeat(50))
267
+
268
+ const datalog = new DatalogProgram()
269
+
270
+ // Add risk facts
271
+ datalog.addFact(JSON.stringify({ predicate: 'business', terms: ['BUS001', 'manufacturing', '0.45'] }))
272
+ datalog.addFact(JSON.stringify({ predicate: 'business', terms: ['BUS002', 'tech', '0.00'] }))
273
+ datalog.addFact(JSON.stringify({ predicate: 'business', terms: ['BUS003', 'transportation', '0.72'] }))
274
+ datalog.addFact(JSON.stringify({ predicate: 'business', terms: ['BUS004', 'hospitality', '0.28'] }))
275
+
276
+ // High-risk thresholds
277
+ datalog.addFact(JSON.stringify({ predicate: 'highRiskClass', terms: ['transportation'] }))
278
+ datalog.addFact(JSON.stringify({ predicate: 'highRiskClass', terms: ['construction'] }))
279
+
280
+ console.log(` Facts loaded: ${datalog.factCount()}`)
281
+
282
+ // Rule: Auto-decline high loss ratio
283
+ // decline(Bus) :- business(Bus, _, LR), LR > 0.70
284
+ datalog.addRule(JSON.stringify({
285
+ head: { predicate: 'referToUW', terms: ['?Bus'] },
286
+ body: [
287
+ { predicate: 'business', terms: ['?Bus', '?Class', '?LR'] },
288
+ { predicate: 'highRiskClass', terms: ['?Class'] }
289
+ ]
290
+ }))
291
+
292
+ // Rule: Auto-approve low risk
293
+ // approve(Bus) :- business(Bus, tech, _)
294
+ datalog.addRule(JSON.stringify({
295
+ head: { predicate: 'autoApprove', terms: ['?Bus'] },
296
+ body: [
297
+ { predicate: 'business', terms: ['?Bus', 'tech', '?LR'] }
298
+ ]
299
+ }))
300
+
301
+ console.log(` Decision rules: ${datalog.ruleCount()}`)
302
+
303
+ const result = evaluateDatalog(datalog)
304
+ const parsed = JSON.parse(result)
305
+
306
+ console.log(' Automated decisions:')
307
+ if (parsed.autoApprove) {
308
+ parsed.autoApprove.forEach(a => console.log(` - ${a[0]}: AUTO-APPROVE`))
309
+ }
310
+ if (parsed.referToUW) {
311
+ parsed.referToUW.forEach(r => console.log(` - ${r[0]}: REFER TO UNDERWRITER`))
312
+ }
313
+ console.log()
314
+
315
+ // ===== PHASE 5: Premium Calculation =====
316
+ console.log('[PHASE 5] Premium Calculation')
317
+ console.log('-'.repeat(50))
318
+
319
+ const premiums = [
320
+ { bus: 'BUS001', baseRate: 2.45, exposure: 45000000, territory: 1.35, loss: 0.45, years: 15 },
321
+ { bus: 'BUS002', baseRate: 0.85, exposure: 8500000, territory: 1.15, loss: 0.00, years: 3 },
322
+ { bus: 'BUS003', baseRate: 3.80, exposure: 22000000, territory: 1.05, loss: 0.72, years: 8 },
323
+ { bus: 'BUS004', baseRate: 1.95, exposure: 12000000, territory: 1.25, loss: 0.28, years: 12 }
324
+ ]
325
+
326
+ console.log(' Calculated premiums (per $100):')
327
+ premiums.forEach(p => {
328
+ const premium = calculatePremium(p.baseRate, p.exposure / 100, p.territory, p.loss, p.years)
329
+ const decision = parsed.autoApprove?.some(a => a[0] === p.bus) ? 'APPROVED' :
330
+ parsed.referToUW?.some(r => r[0] === p.bus) ? 'REFER' : 'STANDARD'
331
+ console.log(` - ${p.bus}: $${premium.toLocaleString()} (${decision})`)
332
+ })
333
+ console.log()
334
+
335
+ // ===== FINAL REPORT =====
336
+ console.log('='.repeat(70))
337
+ console.log(' UNDERWRITING DECISION REPORT')
338
+ console.log('='.repeat(70))
339
+ console.log()
340
+
341
+ const totalApproved = parsed.autoApprove?.length || 0
342
+ const totalReferred = parsed.referToUW?.length || 0
343
+ const totalStandard = riskProfiles.length - totalApproved - totalReferred
344
+
345
+ console.log(' SUMMARY:')
346
+ console.log(` Applications processed: ${riskProfiles.length}`)
347
+ console.log(` Auto-approved: ${totalApproved}`)
348
+ console.log(` Referred to UW: ${totalReferred}`)
349
+ console.log(` Standard processing: ${totalStandard}`)
350
+ console.log()
351
+
352
+ console.log(' RISK INDICATORS:')
353
+ console.log(' - BUS003 (SafeHaul): HIGH RISK - elevated loss ratio 72%, transportation class')
354
+ console.log(' - BUS001 (Acme): MODERATE - hurricane exposure, moderate loss history')
355
+ console.log(' - BUS002 (TechStart): LOW - clean loss history, low-risk class')
356
+ console.log(' - BUS004 (Downtown): MODERATE - flood exposure, established business')
357
+ console.log()
358
+
359
+ console.log('='.repeat(70))
360
+
361
+ return {
362
+ applicationsProcessed: riskProfiles.length,
363
+ autoApproved: totalApproved,
364
+ referred: totalReferred,
365
+ standard: totalStandard
366
+ }
367
+ }
368
+
369
+ // Execute
370
+ runUnderwriting()
371
+ .then(result => {
372
+ console.log('\nUnderwriting pipeline completed.')
373
+ console.log('Output:', JSON.stringify(result, null, 2))
374
+ process.exit(0)
375
+ })
376
+ .catch(err => {
377
+ console.error('Pipeline failed:', err.message)
378
+ process.exit(1)
379
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rust-kgdb",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Production-grade Neuro-Symbolic AI Framework: +86.4% accuracy improvement over vanilla LLMs. High-performance knowledge graph (2.78µs lookups, 35x faster than RDFox). Features fraud detection, underwriting agents, WASM sandbox, type/category/proof theory, and W3C SPARQL 1.1 compliance.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",