Repository navigation
Taxonomy.yml
Jack J Burleson // Lucius Morningstar edited this page Aug 16, 2026
·
2 revisions
# Mailroom Document Taxonomy — prompt experiment loop task specification.
# Same taxonomy as llm-mailroom/config/taxonomy.yaml (sibling repo).
# Adding a new doc class: add an entry below + a matching specialist schema in
# agents/specialist_agents.py. Adjusting thresholds: edit the numbers here —
# no code changes needed.
confidence:
# high is the auto-continue gate for classification: confidence >= high -> extract -> archive.
# Recalibrated to 0.95 from observed sorter behavior (pilot, Aug 2026): every unambiguously
# classifiable document scored >= 0.95, while the deliberately multi-topic memo (ambiguous_01)
# scored 0.90 — which must route to human review, not archive.
high: 0.95
low: 0.70 # below this -> retry; still below after retry -> human review
retry_max: 1 # max retries before routing to review
conflict_threshold: 0.3 # extraction confidence gap below this -> potential conflict
# Deterministic field-type-aware extraction scoring. The scorer normalizes each
# field by its type (date/money/id exact-after-normalize, name fuzzy match,
# free-text token F1, entity-list bipartite matching). `ambiguous_band` is the
# judge escalation gate: fields scoring inside the band trigger the LLM judge.
field_scoring:
ambiguous_band: [0.5, 0.85]
bipartite_match_threshold: 0.6 # minimum pairwise similarity for a list match
embedding_enabled: true
embedding_model: sentence-transformers/all-MiniLM-L6-v2
embedding_rescue_below: 0.7 # only consult embeddings when string score is below this
# Fields whose ground truth is a PARTIAL SAMPLE of the document's content
# (CUAD clause-QA answer snippets, not exhaustive lists). The model is
# usually MORE complete than the label set, so list fields here are scored
# by GROUND-TRUTH COVERAGE (recall over matched labels; role-word labels
# like "Shipper." match whenever any party is named) instead of F1, which
# penalized correct extractions.
partial_gt_fields: ["parties", "key_obligations", "termination_clauses"]
# Verbatim-clause fields whose label is one sentence of a longer passage:
# scored by EXPECTED-WITHIN-PREDICTED token containment, so returning the
# expected sentence plus its riders/citations no longer zeroes the field.
containment_fields: ["governing_law", "term_length", "renewal_terms"]
# Factuality guard ("everything the model reports must be TRUE"): every
# predicted list item must match a ground-truth label OR have its content
# present in the source document (normalized token coverage >= token_coverage).
# Items that are neither are counted as HALLUCINATED and drive the
# verified_precision tracker down.
factuality_verification:
enabled: true
token_coverage: 0.7
# Approximate per-1M-token pricing used for estimated_cost_usd scoring.
cost_models:
qwen/qwen3.7-flash:
input_per_million: 0.03
output_per_million: 0.13
deepseek/deepseek-v4-flash:
input_per_million: 0.05
output_per_million: 0.25
deepseek/deepseek-v4-pro:
input_per_million: 0.435
output_per_million: 0.87
doc_classes:
- key: contract
label: "Contract / Agreement"
schema: ContractExtraction
specialist: contracts_specialist
description: "Formal agreements between parties: M&A, vendor, employment, NDAs, etc."
field_types:
document_name: name
parties: entity_list:name
effective_date: date
term_length: free_text
termination_clauses: entity_list:free_text
governing_law: name
key_obligations: entity_list:free_text
contract_value: money
renewal_terms: free_text
- key: merger_agreement
label: "Merger / Acquisition Agreement"
schema: ContractExtraction
specialist: contracts_specialist
description: "Merger and acquisition agreements: agreements and plans of merger, share/asset purchase agreements (MAUD corpus)"
# Subclass: consideration type (MAUD expert GT) — all_cash / all_stock /
# mixed_cash_stock / mixed_cash_stock_election / other. No tertiary level
# (data-necessity rule): MAUD categories are metadata.
- key: corporate_record
label: "Corporate Record"
schema: CorporateRecordExtraction
specialist: corporate_records_specialist
description: "Bylaws, resolutions, board minutes, cap table entries, incorporation docs"
field_types:
entity_name: name
record_type: name
effective_date: date
key_provisions: entity_list:free_text
signatories: entity_list:name
jurisdiction: name
filing_number: id
- key: due_diligence
label: "Due Diligence"
schema: DueDiligenceExtraction
specialist: due_diligence_specialist
description: "Checklists, disclosure schedules, diligence memos, risk assessments"
field_types:
target_entity: name
diligence_type: name
material_findings: entity_list:free_text
risk_flags: entity_list:free_text
outstanding_items: entity_list:free_text
document_date: date
prepared_by: name
- key: correspondence
label: "Correspondence"
schema: CorrespondenceExtraction
specialist: correspondence_specialist
description: "Letters, emails, memos, notices between parties or with regulators"
field_types:
sender: name
recipient: name
additional_recipients: entity_list
communication_type: name
communication_date: date
key_points: entity_list
demand_amount: money
action_items: entity_list
urgency: name
referenced_communications: entity_list
- key: compliance_filing
label: "Compliance Filing"
schema: ComplianceFilingExtraction
specialist: compliance_specialist
description: "SEC filings, state registrations, regulatory submissions, annual reports"
field_types:
filing_type: name
regulatory_body: name
filing_date: date
due_date: date
entity_name: name
key_requirements: entity_list:free_text
status: name
reference_number: id
- key: court_opinion
label: "Court Opinion"
schema: CourtOpinionExtraction
specialist: court_opinions_specialist
description: "Judicial opinions and orders: published decisions, memorandum opinions, rulings by federal and state courts"
field_types:
case_name: name
court: name
date_decided: date
docket_number: id
opinion_type: name
parties: entity_list:name
holding: free_text
legal_issues: entity_list:free_text
outcome: free_text
citations: entity_list:id
authored_by: name
# === Agent -> model mapping ===
# Each agent list entry: provider, model, temperature, optional max_tokens
# (caps output/reasoning-token generation) and optional max_input_chars
# (input-text budget per call; defaults to 25000). The evaluation loops read
# this file, so model cut-overs are YAML edits, not code changes.
agents:
sorter:
provider: openrouter
model: qwen/qwen3.7-flash
temperature: 0.1
max_tokens: 2048
max_input_chars: 12000
contracts_specialist:
provider: openrouter
model: qwen/qwen3.7-flash
temperature: 0.1
max_tokens: 4096
max_input_chars: 100000
corporate_records_specialist:
provider: openrouter
model: qwen/qwen3.7-flash
temperature: 0.1
max_tokens: 4096
max_input_chars: 40000
due_diligence_specialist:
provider: openrouter
model: qwen/qwen3.7-flash
temperature: 0.1
max_tokens: 4096
max_input_chars: 40000
reasoning_effort: none
correspondence_specialist:
provider: openrouter
model: qwen/qwen3.7-flash
temperature: 0.1
max_tokens: 4096
max_input_chars: 40000
compliance_specialist:
provider: openrouter
model: qwen/qwen3.7-flash
temperature: 0.1
max_tokens: 4096
max_input_chars: 60000
court_opinions_specialist:
provider: openrouter
model: qwen/qwen3.7-flash
temperature: 0.1
max_tokens: 4096
max_input_chars: 60000
# Offline LLM-as-a-judge used by scripts/eval and scripts/reporting.
judge:
provider: openrouter
model: deepseek/deepseek-v4-flash
temperature: 0.1
max_tokens: 2048
reasoning_effort: nonellm-entity-extraction · prompt experiment loop for llm-mailroom — repository · experiment-log site