objectivist-ner 0.0.1 → 0.0.3

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.
Files changed (3) hide show
  1. package/README.md +102 -16
  2. package/index.ts +38 -10
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -148,6 +148,39 @@ ner --relations "Dr. Chen works at MIT and collaborates with Prof. Wright"
148
148
 
149
149
  Relations show how entities connect — extracting the "connective tissue" between concepts.
150
150
 
151
+ You can also categorize relations by class:
152
+
153
+ ```bash
154
+ ner --relations --relation-classes "employment,location,causal,professional" \
155
+ "Dr. Chen works at MIT and collaborates with Prof. Wright"
156
+ ```
157
+
158
+ ```json
159
+ {
160
+ "entities": [
161
+ { "class": "person", "text": "Dr. Chen" },
162
+ { "class": "organization", "text": "MIT" },
163
+ { "class": "person", "text": "Prof. Wright" }
164
+ ],
165
+ "relations": [
166
+ {
167
+ "source": "Dr. Chen",
168
+ "target": "MIT",
169
+ "relation": "works at",
170
+ "class": "employment"
171
+ },
172
+ {
173
+ "source": "Dr. Chen",
174
+ "target": "Prof. Wright",
175
+ "relation": "collaborates with",
176
+ "class": "professional"
177
+ }
178
+ ]
179
+ }
180
+ ```
181
+
182
+ The `class` field categorizes the relation type (e.g., employment, causal, spatial), allowing you to group and analyze connections by category.
183
+
151
184
  ## Installation
152
185
 
153
186
  ```bash
@@ -274,6 +307,7 @@ cat article.txt | ner --detect-negation
274
307
  | `--attr-values <json>` | Enum map for attribute values |
275
308
  | `--taxonomy <json>` | Class hierarchy (parent → children) |
276
309
  | `--relations` | Extract relations between entities |
310
+ | `--relation-classes <list>` | Allowed relation classes (e.g. employment,causal) |
277
311
  | `--resolve` | Resolve coreferences (adds entity_id) |
278
312
  | `--detect-negation` | Add assertion field (present/negated/hypothetical) |
279
313
  | `--include-confidence` | Add confidence field (low/medium/high) |
@@ -304,22 +338,6 @@ Tested on a complex input with 11 entities across 6 classes:
304
338
  | Boston | location | — | location |
305
339
  | **Found** | **3/11** | **8/11** | **11/11** |
306
340
 
307
- ## Integration with objectivist-lattice
308
-
309
- This tool is designed to work with **[objectivist-lattice](https://github.com/richardanaya/objectivist-lattice)** — a knowledge management system that enforces the Objectivist hierarchy: percepts → concepts → principles → actions.
310
-
311
- **objectivist-ner** extracts the percepts and concepts. **objectivist-lattice** validates and organizes them into principles you can act on.
312
-
313
- ### Workflow
314
-
315
- ```bash
316
- # Extract structured observations from text
317
- ner --file chapter1.txt --detect-negation --resolve > percepts.json
318
-
319
- # Import into your knowledge lattice
320
- # (See objectivist-lattice documentation for details)
321
- ```
322
-
323
341
  ## Epistemological Design
324
342
 
325
343
  Each feature maps to an Objectivist principle:
@@ -338,3 +356,71 @@ Use any GGUF model:
338
356
  ner "text" --model "hf:unsloth/Qwen3-8B-GGUF:Qwen3-8B-Q4_K_M.gguf"
339
357
  ner "text" --model ./my-model.gguf
340
358
  ```
359
+
360
+ ---
361
+
362
+ ## Complete Ontology Schema Example
363
+
364
+ Schema files let you define your entire ontology in one place:
365
+
366
+ ```json
367
+ {
368
+ "taxonomy": {
369
+ "organism": [
370
+ "person",
371
+ {
372
+ "animal": ["dog", "cat", "bird"]
373
+ }
374
+ ],
375
+ "place": [
376
+ "city",
377
+ "country",
378
+ {
379
+ "building": ["hospital", "school", "office"]
380
+ }
381
+ ],
382
+ "institution": ["company", "university", "government_agency"],
383
+ "concept": ["idea", "theory", "principle"]
384
+ },
385
+ "classes": ["person", "organization", "location", "event", "disease", "drug"],
386
+ "attributes": ["role", "age", "location", "date", "affiliation", "specialty"],
387
+ "attrValues": {
388
+ "role": ["doctor", "researcher", "patient", "student"],
389
+ "location": ["Boston", "New York", "London", "Tokyo"]
390
+ },
391
+ "relations": [
392
+ "works_at",
393
+ "located_in",
394
+ "treats",
395
+ "studies",
396
+ "collaborates_with"
397
+ ],
398
+ "relationClasses": [
399
+ "employment",
400
+ "spatial",
401
+ "medical",
402
+ "academic",
403
+ "professional"
404
+ ]
405
+ }
406
+ ```
407
+
408
+ Usage:
409
+
410
+ ```bash
411
+ ner --schema complete-ontology.json "Dr. Chen works at Massachusetts General Hospital in Boston"
412
+ ```
413
+
414
+ This loads taxonomy, classes, attributes, attribute values, relation types, and relation classes all at once.
415
+
416
+ ---
417
+
418
+ ## Building Principles from Percepts
419
+
420
+ `objectivist-ner` extracts the raw perceptual material from any text: concrete entities with exact spans, hierarchical taxonomy (genus and differentia), coreferences preserving identity, assertions vs. negations, and relations.
421
+
422
+ This supplies the inductive base required by Objectivist epistemology.
423
+
424
+ Feed it philosophical works, scientific papers, historical accounts, or any reality-grounded writing. The parsed output gives you the concretes needed to form concepts and derive principles—anchored in observed facts, not floating abstractions.
425
+
426
+ Use it to mine source material, reduce arguments to their perceptual roots, and build your own objective knowledge from existence.
package/index.ts CHANGED
@@ -44,6 +44,7 @@ interface SchemaFile {
44
44
  attributes?: string[];
45
45
  attrValues?: Record<string, string[]>;
46
46
  relations?: string[];
47
+ relationClasses?: string[];
47
48
  }
48
49
 
49
50
  // === TAXONOMY HELPERS ===
@@ -178,6 +179,10 @@ program
178
179
  'Class hierarchy JSON e.g. {"organism":["animal","plant"]}',
179
180
  )
180
181
  .option("--relations", "Extract relations between entities")
182
+ .option(
183
+ "--relation-classes <list>",
184
+ "Comma-separated allowed relation classes (e.g. employment,location,causal)",
185
+ )
181
186
  .option("--resolve", "Resolve coreferences (group mentions of same entity)")
182
187
  .option("--include-confidence", "Include confidence scores per entity")
183
188
  .option("--detect-negation", "Detect negated/hypothetical entities")
@@ -293,6 +298,9 @@ if (opts.taxonomy) {
293
298
 
294
299
  const enableRelations = opts.relations || !!schemaFile?.relations;
295
300
  const relationTypes: string[] | undefined = schemaFile?.relations || undefined;
301
+ const relationClasses: string[] | undefined = opts.relationClasses
302
+ ? opts.relationClasses.split(",").map((s: string) => s.trim())
303
+ : schemaFile?.relationClasses;
296
304
  const enableResolve = !!opts.resolve;
297
305
  const enableConfidence = !!opts.includeConfidence;
298
306
  const enableNegation = !!opts.detectNegation;
@@ -444,6 +452,23 @@ function buildGrammarSchema() {
444
452
 
445
453
  // === BUILD RELATIONS SCHEMA ===
446
454
  function buildRelationsSchema() {
455
+ const relationProperties: any = {
456
+ source: { type: "string" },
457
+ target: { type: "string" },
458
+ relation: {
459
+ type: "string",
460
+ ...(relationTypes && { enum: relationTypes }),
461
+ },
462
+ };
463
+
464
+ // Add class field if relationClasses is specified
465
+ if (relationClasses) {
466
+ relationProperties.class = {
467
+ type: "string",
468
+ enum: relationClasses,
469
+ };
470
+ }
471
+
447
472
  const relSchema: any = {
448
473
  type: "object",
449
474
  properties: {
@@ -452,15 +477,10 @@ function buildRelationsSchema() {
452
477
  type: "array",
453
478
  items: {
454
479
  type: "object",
455
- properties: {
456
- source: { type: "string" },
457
- target: { type: "string" },
458
- relation: {
459
- type: "string",
460
- ...(relationTypes && { enum: relationTypes }),
461
- },
462
- },
463
- required: ["source", "target", "relation"],
480
+ properties: relationProperties,
481
+ required: relationClasses
482
+ ? ["source", "target", "relation", "class"]
483
+ : ["source", "target", "relation"],
464
484
  additionalProperties: false,
465
485
  },
466
486
  },
@@ -500,10 +520,18 @@ function buildConstraints(): string {
500
520
  constraints += `\nEvery entity has "entity_id" and "is_canonical" fields. Coreferent mentions share entity_id; exactly one per group has is_canonical:true (the most specific reference). Example: [{"class":"person","text":"Dr. Chen","entity_id":"e1","is_canonical":true,"attributes":{}},{"class":"person","text":"She","entity_id":"e1","is_canonical":false,"attributes":{}}]`;
501
521
  }
502
522
  if (enableRelations) {
503
- constraints += `\nAlso extract relations between entities. Return {"entities": [...], "relations": [{"source": "entity text", "target": "entity text", "relation": "relation type"}]}.`;
523
+ let relDesc = `\nAlso extract relations between entities.`;
524
+ if (relationClasses) {
525
+ relDesc += ` Each relation must have a "class" field categorizing the relation type.`;
526
+ }
527
+ relDesc += ` Return {"entities": [...], "relations": [{"source": "entity text", "target": "entity text", "relation": "relation type"${relationClasses ? ', "class": "relation class"' : ""}}]}.`;
528
+ constraints += relDesc;
504
529
  if (relationTypes) {
505
530
  constraints += ` Allowed relation types: ${relationTypes.join(", ")}.`;
506
531
  }
532
+ if (relationClasses) {
533
+ constraints += ` Allowed relation classes: ${relationClasses.join(", ")}.`;
534
+ }
507
535
  }
508
536
 
509
537
  return constraints;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "objectivist-ner",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Objectivist-inspired Named Entity Recognition with grammar-constrained LLM output",
5
5
  "bin": {
6
6
  "ner": "index.ts"