[crawler]
This commit is contained in:
2
crawler_platform/app/core/ontology/__init__.py
Normal file
2
crawler_platform/app/core/ontology/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
"""Ontology definitions and mapping helpers."""
|
||||
|
||||
130
crawler_platform/app/core/ontology/definitions.py
Normal file
130
crawler_platform/app/core/ontology/definitions.py
Normal file
@@ -0,0 +1,130 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class Ontology:
|
||||
domain: str
|
||||
entity_types: list[str]
|
||||
predicates: list[str]
|
||||
attributes: list[str]
|
||||
aliases: dict[str, str] = field(default_factory=dict)
|
||||
|
||||
|
||||
COMMON_ONTOLOGY = Ontology(
|
||||
domain="common",
|
||||
entity_types=[
|
||||
"Source",
|
||||
"Page",
|
||||
"Entity",
|
||||
"Attribute",
|
||||
"Relation",
|
||||
"Claim",
|
||||
"Evidence",
|
||||
"Extraction",
|
||||
"Confidence",
|
||||
"UpdatePolicy",
|
||||
],
|
||||
predicates=[
|
||||
"mentions",
|
||||
"hasAttribute",
|
||||
"relatedTo",
|
||||
"sameAs",
|
||||
"soldBy",
|
||||
"hasPrice",
|
||||
],
|
||||
attributes=["name", "source_url", "updated_at", "confidence"],
|
||||
)
|
||||
|
||||
|
||||
DOMAIN_ONTOLOGIES: dict[str, Ontology] = {
|
||||
"perfume": Ontology(
|
||||
domain="perfume",
|
||||
entity_types=[
|
||||
"Perfume",
|
||||
"Brand",
|
||||
"Note",
|
||||
"Accord",
|
||||
"Mood",
|
||||
"Season",
|
||||
"Occasion",
|
||||
"Review",
|
||||
"Price",
|
||||
"ProductPage",
|
||||
],
|
||||
predicates=[
|
||||
"hasBrand",
|
||||
"hasTopNote",
|
||||
"hasMiddleNote",
|
||||
"hasBaseNote",
|
||||
"hasAccord",
|
||||
"evokesMood",
|
||||
"suitableForSeason",
|
||||
"suitableForOccasion",
|
||||
"similarTo",
|
||||
"soldBy",
|
||||
"hasPrice",
|
||||
"hasReviewKeyword",
|
||||
],
|
||||
attributes=[
|
||||
"name",
|
||||
"brand",
|
||||
"gender_bias",
|
||||
"longevity",
|
||||
"sillage",
|
||||
"price_range",
|
||||
"popularity_score",
|
||||
"review_count",
|
||||
"source_url",
|
||||
"updated_at",
|
||||
],
|
||||
aliases={
|
||||
"top_notes": "hasTopNote",
|
||||
"middle_notes": "hasMiddleNote",
|
||||
"heart_notes": "hasMiddleNote",
|
||||
"base_notes": "hasBaseNote",
|
||||
"accords": "hasAccord",
|
||||
"mood_tags": "evokesMood",
|
||||
"season_tags": "suitableForSeason",
|
||||
"occasion_tags": "suitableForOccasion",
|
||||
"review_keywords": "hasReviewKeyword",
|
||||
"price": "hasPrice",
|
||||
},
|
||||
),
|
||||
"tea": Ontology(
|
||||
domain="tea",
|
||||
entity_types=["Tea", "Ingredient", "Flavor", "Effect", "CaffeineLevel", "MoodState"],
|
||||
predicates=["hasIngredient", "hasFlavor", "hasEffect", "suitableForCondition"],
|
||||
attributes=["name", "origin", "caffeine_level", "price_range"],
|
||||
),
|
||||
"coffee": Ontology(
|
||||
domain="coffee",
|
||||
entity_types=["CoffeeBean", "Origin", "RoastLevel", "FlavorNote", "BrewMethod"],
|
||||
predicates=["hasOrigin", "hasRoastLevel", "hasFlavorNote", "recommendedForBrewMethod"],
|
||||
attributes=["name", "origin", "roast_level", "process", "price_range"],
|
||||
),
|
||||
"candle": Ontology(
|
||||
domain="candle",
|
||||
entity_types=["ScentProduct", "ScentNote", "SpaceType", "Mood", "Season"],
|
||||
predicates=["suitableForSpace", "evokesMood", "hasScentNote"],
|
||||
attributes=["name", "burn_time", "volume", "price_range"],
|
||||
),
|
||||
"supplement": Ontology(
|
||||
domain="supplement",
|
||||
entity_types=["Supplement", "Ingredient", "HealthGoal", "Symptom", "Dosage"],
|
||||
predicates=["hasIngredient", "supportsGoal", "recommendedForCondition"],
|
||||
attributes=["name", "dosage", "warnings", "price_range"],
|
||||
),
|
||||
"gift": Ontology(
|
||||
domain="gift",
|
||||
entity_types=["GiftProduct", "RecipientType", "Relationship", "Occasion", "PersonalityTag"],
|
||||
predicates=["suitableForRecipient", "suitableForOccasion", "matchesPersonality"],
|
||||
attributes=["name", "price_range", "availability", "gift_wrap_available"],
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def ontology_for_domain(domain: str) -> Ontology:
|
||||
return DOMAIN_ONTOLOGIES.get(domain, COMMON_ONTOLOGY)
|
||||
|
||||
27
crawler_platform/app/core/ontology/mapper.py
Normal file
27
crawler_platform/app/core/ontology/mapper.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
|
||||
def normalize_predicate(predicate: str, ontology: dict[str, Any] | None) -> str:
|
||||
if not ontology:
|
||||
return predicate
|
||||
aliases = ontology.get("aliases", {})
|
||||
return aliases.get(predicate, predicate)
|
||||
|
||||
|
||||
def is_allowed_predicate(predicate: str, ontology: dict[str, Any] | None) -> bool:
|
||||
if not ontology or not ontology.get("predicates"):
|
||||
return True
|
||||
return predicate in ontology["predicates"]
|
||||
|
||||
|
||||
def ontology_to_dict(domain_ontology) -> dict[str, Any]:
|
||||
return {
|
||||
"domain": domain_ontology.domain,
|
||||
"entity_types": domain_ontology.entity_types,
|
||||
"predicates": domain_ontology.predicates,
|
||||
"attributes": domain_ontology.attributes,
|
||||
"aliases": domain_ontology.aliases,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user