feat(schema): migrate collection_focus to has_or_had_category; archive collection_focus slot

This commit is contained in:
kempersc 2026-01-19 16:56:34 +01:00
parent b68d580c82
commit b32efc208e
12 changed files with 423 additions and 10 deletions

View file

@ -407,7 +407,7 @@ class Settings:
# RAG uses only Qdrant (vectors) and Oxigraph (SPARQL) for retrieval
# LLM Configuration
anthropic_api_key: str = os.getenv("ANTHROPIC_API_KEY", "")
anthropic_api_key: str = os.getenv("ANTHROPIC_API_KEY", "") or os.getenv("CLAUDE_API_KEY", "")
openai_api_key: str = os.getenv("OPENAI_API_KEY", "")
huggingface_api_key: str = os.getenv("HUGGINGFACE_API_KEY", "")
groq_api_key: str = os.getenv("GROQ_API_KEY", "")
@ -3501,6 +3501,21 @@ async def dspy_query(request: DSPyQueryRequest) -> DSPyQueryResponse:
logger.info(f"LLM provider requested: {requested_provider} (request.llm_provider={request.llm_provider}, server default={settings.llm_provider})")
# Check if requested provider has API key configured - fail early if not
provider_api_keys = {
"zai": settings.zai_api_token,
"groq": settings.groq_api_key,
"anthropic": settings.anthropic_api_key,
"openai": settings.openai_api_key,
"huggingface": settings.huggingface_api_key,
}
if requested_provider in provider_api_keys and not provider_api_keys[requested_provider]:
raise ValueError(
f"LLM provider '{requested_provider}' was requested but its API key is not configured. "
f"Please set the appropriate environment variable (e.g., ANTHROPIC_API_KEY or CLAUDE_API_KEY for anthropic)."
)
# Provider configuration priority: requested provider first, then fallback chain
providers_to_try = [requested_provider]
# Add fallback chain (but not duplicates)
@ -4201,6 +4216,22 @@ async def stream_dspy_query_response(
llm_model_used: str | None = None
lm = None
# Check if requested provider has API key configured - fail early if not
provider_api_keys = {
"zai": settings.zai_api_token,
"groq": settings.groq_api_key,
"anthropic": settings.anthropic_api_key,
"openai": settings.openai_api_key,
"huggingface": settings.huggingface_api_key,
}
if requested_provider in provider_api_keys and not provider_api_keys[requested_provider]:
yield emit_error(
f"LLM provider '{requested_provider}' was requested but its API key is not configured. "
f"Please set the appropriate environment variable (e.g., ANTHROPIC_API_KEY or CLAUDE_API_KEY for anthropic)."
)
return
providers_to_try = [requested_provider]
for fallback in ["zai", "groq", "anthropic", "openai"]:
if fallback not in providers_to_try:

View file

@ -1,5 +1,5 @@
{
"generated": "2026-01-19T15:15:51.847Z",
"generated": "2026-01-19T15:56:34.364Z",
"schemaRoot": "/schemas/20251121/linkml",
"totalFiles": 2969,
"categoryCounts": {

View file

@ -0,0 +1,107 @@
# CollectionContent - Content held by a collection
#
# Created per slot_fixes.yaml migration for: collection_type
# Creation date: 2026-01-19
#
# Rule 53 (No Bespoke Slots): collection_type → has_or_had_content + CollectionContent + has_or_had_type + CollectionContentType
id: https://nde.nl/ontology/hc/class/CollectionContent
name: CollectionContent
title: Collection Content
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
dcterms: http://purl.org/dc/terms/
rico: https://www.ica.org/standards/RiC/ontology#
default_prefix: hc
imports:
- linkml:types
- ./CollectionContentType
- ./CollectionContentTypes
- ../slots/has_or_had_type
classes:
CollectionContent:
class_uri: hc:CollectionContent
description: |
Represents content held within a collection, with typed categorization.
**RULE 53 MIGRATION**:
Replaces the simple `collection_type` string slot with a structured model:
- `has_or_had_content` → CollectionContent (this class)
- `has_or_had_type` → CollectionContentType (categorization)
**USAGE**:
```yaml
has_or_had_content:
- content_description: "Medieval manuscripts and parish registers"
has_or_had_type:
- type_label: Archival
- type_label: Library
```
**CHARACTERISTICS**:
- Supports multiple content types per collection
- Provides structured categorization
- Links to CollectionContentType taxonomy
slots:
- has_or_had_type
slot_usage:
has_or_had_type:
range: CollectionContentType
multivalued: true
inlined: true
description: |
Type(s) of content in this collection.
Uses CollectionContentType taxonomy (Archival, Library, Art, etc.).
attributes:
content_description:
range: string
description: Free-text description of the collection content
content_extent:
range: string
description: Extent/size of this content (e.g., "500 linear meters", "10,000 items")
content_date_range:
range: string
description: Date range covered by this content (e.g., "1500-1900")
exact_mappings:
- rico:RecordResource
close_mappings:
- dcterms:BibliographicResource
annotations:
specificity_score: "0.45"
specificity_rationale: "Moderately generic - applies broadly to collections."
template_specificity: '{"archive_search": 0.55, "museum_search": 0.50, "library_search": 0.55, "collection_discovery": 0.75, "person_research": 0.15, "location_browse": 0.25, "identifier_lookup": 0.20, "organizational_change": 0.10, "digital_platform": 0.30, "general_heritage": 0.45}'
examples:
- value:
content_description: "Medieval manuscripts and parish registers from 14th-18th century"
content_extent: "2,500 volumes"
content_date_range: "1350-1800"
has_or_had_type:
- type_label: Archival
- type_label: Library
description: Church archive with mixed archival and library content
- value:
content_description: "Religious art including icons, paintings, and stained glass"
content_extent: "450 objects"
has_or_had_type:
- type_label: Art
- type_label: Liturgical
description: Cathedral treasury art collection
comments:
- "Created per slot_fixes.yaml migration (2026-01-19)"
- "RULE 53: Replaces collection_type string slot with structured model"

View file

@ -0,0 +1,73 @@
# CollectionContentType - Base class for collection content type taxonomy
#
# Created per slot_fixes.yaml migration for: collection_type
# Creation date: 2026-01-19
#
# Rule 0b (Type/Types Naming): CollectionContentType (base) + CollectionContentTypes (subclasses)
# Rule 53 (No Bespoke Slots): collection_type → has_or_had_type + CollectionContentType
# Rule 39 (RiC-O Naming): Uses has_or_had_* pattern
id: https://nde.nl/ontology/hc/class/CollectionContentType
name: CollectionContentType
title: Collection Content Type (Base)
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
dcterms: http://purl.org/dc/terms/
skos: http://www.w3.org/2004/02/skos/core#
default_prefix: hc
imports:
- linkml:types
classes:
CollectionContentType:
class_uri: hc:CollectionContentType
description: |
Abstract base class for types of heritage materials held by custodians.
**RULE 0b PATTERN**:
- This file (CollectionContentType.yaml): Abstract base class
- CollectionContentTypes.yaml: Concrete subclasses (Archival, Library, Art, etc.)
**CATEGORIES**:
- **Archival**: Parish registers, administrative records, correspondence
- **Library**: Sacred texts, theological works, manuscripts
- **Liturgical**: Vessels, vestments, ritual implements
- **Art**: Icons, paintings, sculpture, stained glass
- **Architectural**: Building fragments, archaeological remains
- **Relics**: Saints' relics, holy objects, pilgrimage souvenirs
- **Musical**: Organs, bells, choir books, instruments
- **Ephemera**: Bulletins, programs, pamphlets, photographs
**USAGE**:
Multiple types common (e.g., church with archive + library + art).
abstract: true
attributes:
type_label:
range: string
required: true
slot_uri: skos:prefLabel
description: Human-readable label for the collection content type
type_definition:
range: string
slot_uri: skos:definition
description: Definition of this collection content type
exact_mappings:
- dcterms:type
annotations:
specificity_score: "0.50"
specificity_rationale: "Moderately specific - applies to multiple custodian types with collections."
template_specificity: '{"archive_search": 0.60, "museum_search": 0.55, "library_search": 0.55, "collection_discovery": 0.70, "person_research": 0.20, "location_browse": 0.30, "identifier_lookup": 0.25, "organizational_change": 0.15, "digital_platform": 0.35, "general_heritage": 0.50}'
comments:
- "Created per slot_fixes.yaml migration (2026-01-19)"
- "RULE 0b: Base class for CollectionContentTypes taxonomy"
- "RULE 53: Replaces collection_type string slot"

View file

@ -0,0 +1,169 @@
# CollectionContentTypes - Concrete subclasses for collection content taxonomy
#
# Created per slot_fixes.yaml migration for: collection_type
# Creation date: 2026-01-19
#
# Rule 0b (Type/Types Naming): CollectionContentType (base) + CollectionContentTypes (subclasses)
# Rule 53 (No Bespoke Slots): collection_type → has_or_had_type + CollectionContentType
id: https://nde.nl/ontology/hc/class/CollectionContentTypes
name: CollectionContentTypes
title: Collection Content Types (Taxonomy)
prefixes:
linkml: https://w3id.org/linkml/
hc: https://nde.nl/ontology/hc/
dcterms: http://purl.org/dc/terms/
skos: http://www.w3.org/2004/02/skos/core#
default_prefix: hc
imports:
- linkml:types
- ./CollectionContentType
classes:
ArchivalCollectionContent:
is_a: CollectionContentType
class_uri: hc:ArchivalCollectionContent
description: |
Archival materials: Parish registers, administrative records, correspondence,
historical documents, manuscript collections.
attributes:
type_label:
ifabsent: "string(Archival)"
LibraryCollectionContent:
is_a: CollectionContentType
class_uri: hc:LibraryCollectionContent
description: |
Library materials: Sacred texts, theological works, manuscripts,
printed books, periodicals, rare books.
attributes:
type_label:
ifabsent: "string(Library)"
LiturgicalCollectionContent:
is_a: CollectionContentType
class_uri: hc:LiturgicalCollectionContent
description: |
Liturgical objects: Vessels, vestments, ritual implements,
ceremonial items, religious artifacts.
attributes:
type_label:
ifabsent: "string(Liturgical)"
ArtCollectionContent:
is_a: CollectionContentType
class_uri: hc:ArtCollectionContent
description: |
Art collections: Icons, paintings, sculpture, stained glass,
religious imagery, decorative arts.
attributes:
type_label:
ifabsent: "string(Art)"
ArchitecturalCollectionContent:
is_a: CollectionContentType
class_uri: hc:ArchitecturalCollectionContent
description: |
Architectural materials: Building fragments, archaeological remains,
architectural drawings, building records.
attributes:
type_label:
ifabsent: "string(Architectural)"
RelicsCollectionContent:
is_a: CollectionContentType
class_uri: hc:RelicsCollectionContent
description: |
Relics and devotional objects: Saints' relics, holy objects,
pilgrimage souvenirs, votive offerings.
attributes:
type_label:
ifabsent: "string(Relics)"
MusicalCollectionContent:
is_a: CollectionContentType
class_uri: hc:MusicalCollectionContent
description: |
Musical heritage: Organs, bells, choir books, instruments,
sheet music, sound recordings.
attributes:
type_label:
ifabsent: "string(Musical)"
EphemeraCollectionContent:
is_a: CollectionContentType
class_uri: hc:EphemeraCollectionContent
description: |
Ephemeral materials: Bulletins, programs, pamphlets, photographs,
postcards, tickets, posters.
attributes:
type_label:
ifabsent: "string(Ephemera)"
PhotographicCollectionContent:
is_a: CollectionContentType
class_uri: hc:PhotographicCollectionContent
description: |
Photographic materials: Historical photographs, negatives,
slides, digital images, photo albums.
attributes:
type_label:
ifabsent: "string(Photographic)"
AudiovisualCollectionContent:
is_a: CollectionContentType
class_uri: hc:AudiovisualCollectionContent
description: |
Audiovisual materials: Film, video, sound recordings,
oral histories, multimedia.
attributes:
type_label:
ifabsent: "string(Audiovisual)"
TextileCollectionContent:
is_a: CollectionContentType
class_uri: hc:TextileCollectionContent
description: |
Textile materials: Historical garments, tapestries,
banners, ecclesiastical vestments, embroidery.
attributes:
type_label:
ifabsent: "string(Textile)"
NaturalHistoryCollectionContent:
is_a: CollectionContentType
class_uri: hc:NaturalHistoryCollectionContent
description: |
Natural history specimens: Botanical, zoological, geological,
paleontological collections.
attributes:
type_label:
ifabsent: "string(Natural History)"
ScientificCollectionContent:
is_a: CollectionContentType
class_uri: hc:ScientificCollectionContent
description: |
Scientific instruments and materials: Laboratory equipment,
measuring devices, scientific models, specimens.
attributes:
type_label:
ifabsent: "string(Scientific)"
DigitalCollectionContent:
is_a: CollectionContentType
class_uri: hc:DigitalCollectionContent
description: |
Born-digital and digitized materials: Digital archives,
electronic records, digital art, web archives.
attributes:
type_label:
ifabsent: "string(Digital)"
comments:
- "Created per slot_fixes.yaml migration (2026-01-19)"
- "RULE 0b: Concrete subclasses of CollectionContentType"
- "Extensible taxonomy - add new subclasses as needed"

View file

@ -16,7 +16,9 @@ prefixes:
imports:
- linkml:types
- ../slots/has_or_had_quantity
- ../slots/has_or_had_category
- ./Quantity
- ./Category
- ./MuseumRegisterProvenance
default_range: string
@ -72,10 +74,13 @@ classes:
range: string
multivalued: true
inlined_as_list: true
collection_focus:
range: string
has_or_had_category: # MIGRATED 2026-01-19: was collection_focus - per Rule 53
range: Category
multivalued: true
inlined_as_list: true
inlined: true
description: >-
Collection focus/category from museum register.
MIGRATED from collection_focus per slot_fixes.yaml (Rule 53, 2026-01-19).
has_or_had_quantity:
range: Quantity
inlined: true

View file

@ -126,10 +126,10 @@ classes:
\ .\n\n:MuseumType_ArtMuseum_Q207694\n a glamtype:MuseumType, crm:E55_Type, skos:Concept ;\n skos:prefLabel \"\
Art Museum\"@en, \"kunstmuseum\"@nl ;\n skos:broader :MuseumType_Museum_Q33506 ;\n skos:narrower :MuseumType_ModernArtMuseum_Q108860593\
\ ;\n schema:additionalType <http://www.wikidata.org/entity/Q207694> ;\n glamtype:glamorcubesfixphdnt_code \"\
MUSEUM\" ;\n glamtype:collection_focus [\"paintings\", \"sculptures\", \"decorative arts\"] ;\n glamtype:exhibition_program\
MUSEUM\" ;\n glamtype:has_or_had_category [ hc:category_name \"paintings\" ; hc:category_type \"TYPOLOGY\" ] ;\n glamtype:exhibition_program\
\ \"rotating exhibitions with permanent collection\" ;\n glamtype:cataloging_standard \"LIDO\" .\n```\n\n**Domain-Specific\
\ Properties**:\nThis class adds museum-specific metadata beyond base CustodianType:\n- `collection_focus` - Subject\
\ areas of collections (art, history, science, etc.)\n- `exhibition_program` - Exhibition strategy (permanent, rotating,\
\ Properties**:\nThis class adds museum-specific metadata beyond base CustodianType:\n- `has_or_had_category` - Subject\
\ areas of collections (art, history, science, etc.) using Category class\n- `exhibition_program` - Exhibition strategy (permanent, rotating,\
\ temporary)\n- `visitor_facilities` - Public amenities (cafe, shop, education center, etc.)\n- `cataloging_standard`\
\ - Standards used (LIDO, SPECTRUM, CIDOC-CRM, etc.)\n- `conservation_lab` - Whether museum has conservation facilities\n\
- `research_department` - Whether museum conducts scholarly research\n\n**Integration with CIDOC-CRM**:\nMuseum organizations\

View file

@ -164,7 +164,7 @@ classes:
\ hc:Numismatist ;\n schema:url <https://nde.nl/ontology/hc/class/personal-collection-type> .\n\n# Example:\
\ Willem Six Collection (17th-century Dutch paintings, Amsterdam)\n<https://w3id.org/heritage/custodian/nl/willem-six-collection>\n\
\ a schema:Person, foaf:Person, crm:E21_Person, hc:PersonalCollector ;\n hc:custodian_type hc:PersonalCollectionType\
\ ;\n hc:collection_focus \"Dutch Golden Age paintings\", \"Rembrandt works\", \"Family portraits\" ;\n hc:collection_size\
\ ;\n hc:has_or_had_category [ hc:category_name \"Dutch Golden Age paintings\" ; hc:category_type \"SUBJECT\" ] ;\n hc:has_or_had_quantity\
\ \"50+ paintings\", \"Historical furniture\", \"Family archives\" ;\n hc:acquisition_history \"Inherited family collection\
\ since 1654\", \"Selective purchases 1980-2020\" ;\n hc:access_restrictions \"Private residence, No public access\"\
, \"Occasional museum loans\" ;\n hc:preservation_approach \"Professional conservation\", \"Climate-controlled room\"\

View file

@ -2,6 +2,7 @@
"files": [
"accepts_or_accepted.yaml",
"address_formatted.yaml",
"administrative_context.yaml",
"affects_or_affected.yaml",
"aggregates_or_aggregated_from.yaml",
"allocates_or_allocated.yaml",
@ -76,6 +77,7 @@
"claim_value.yaml",
"based_on_claim.yaml",
"classifies_or_classified.yaml",
"class_definition.yaml",
"closed_space_id.yaml",
"cms_id.yaml",
"cms_product_name.yaml",
@ -283,7 +285,6 @@
"derived_from_observation.yaml",
"derives_or_derived_from.yaml",
"description.yaml",
"description_section.yaml",
"description_text.yaml",
"description_type.yaml",
"detection_count.yaml",
@ -335,6 +336,7 @@
"dual_class_link.yaml",
"dual_class_role.yaml",
"duration.yaml",
"dutch_context.yaml",
"ead_id.yaml",
"ebook_url.yaml",
"ecclesiastical_province.yaml",
@ -412,6 +414,10 @@
"evidence_documentation.yaml",
"evidence_gap.yaml",
"example_instance.yaml",
"example_location.yaml",
"example_name.yaml",
"example_note.yaml",
"example_wikidata_id.yaml",
"example_platform.yaml",
"example_portal.yaml",
"excluded_materials.yaml",
@ -981,6 +987,7 @@
"heritage_relevant_count.yaml",
"heritage_relevant_percentage.yaml",
"heritage_society_subtype.yaml",
"heritage_sector_usage.yaml",
"heritage_status.yaml",
"heritage_type.yaml",
"heritage_type_classification.yaml",
@ -990,6 +997,7 @@
"historic_building_id.yaml",
"historic_building_name.yaml",
"historic_garden_designation.yaml",
"historical_significance.yaml",
"historical_region.yaml",
"hold_or_held_record_set_type.yaml",
"holy_site_subtype.yaml",
@ -1172,6 +1180,7 @@
"jurisdiction_type.yaml",
"justification.yaml",
"keyframe_extraction.yaml",
"key_distinction.yaml",
"keyword.yaml",
"kien_registration_date.yaml",
"kien_url.yaml",
@ -1359,6 +1368,7 @@
"notarial_deed_number.yaml",
"notary_name.yaml",
"notary_office.yaml",
"notable_examples.yaml",
"note.yaml",
"note_content.yaml",
"note_date.yaml",
@ -1693,6 +1703,11 @@
"related_concept.yaml",
"related_loan.yaml",
"related_project.yaml",
"related_type_name.yaml",
"related_type_note.yaml",
"related_type_relationship.yaml",
"related_type_wikidata.yaml",
"related_types.yaml",
"relationship.yaml",
"religion.yaml",
"religious_function.yaml",
@ -1735,6 +1750,7 @@
"research_infrastructure.yaml",
"research_program.yaml",
"research_project.yaml",
"research_value.yaml",
"reservation_required.yaml",
"resource_description.yaml",
"response_format.yaml",
@ -1788,6 +1804,7 @@
"scheme_type.yaml",
"scheme_url.yaml",
"scope.yaml",
"scope_description.yaml",
"scope_exclude.yaml",
"scope_include.yaml",
"scrape_method.yaml",

View file

@ -9998,6 +9998,17 @@ fixes:
type: slot
- label: Category
type: class
processed:
status: true
notes: |
FULLY_MIGRATED 2026-01-19: collection_focus → has_or_had_category + Category
**Files Modified**:
- MuseumType.yaml: Migrated to has_or_had_category + Category
- MuseumRegisterEnrichment.yaml: Migrated collection_focus attribute to has_or_had_category
- Category.yaml: Created per slot_fixes.yaml revision
**Archived**: modules/slots/archive/collection_focus_archived_20260119.yaml
- original_slot_id: https://nde.nl/ontology/hc/slot/collection_id
revision:
- label: has_or_had_identifier