Skip to content

ontocast.tool.atomic

Minimal tool contracts for atomic render/critic loops.

Classes

AtomicLLMProvider

Bases: Protocol

Provides budget-aware LLM instances for atomic loop calls.

Source code in ontocast/tool/atomic.py
class AtomicLLMProvider(Protocol):
    """Provides budget-aware LLM instances for atomic loop calls."""

    async def get_llm_tool(self, budget_tracker) -> LLMTool:
        """Return an LLM tool tied to the given budget tracker."""
        ...

Methods:

get_llm_tool(budget_tracker) async

Return an LLM tool tied to the given budget tracker.

Source code in ontocast/tool/atomic.py
async def get_llm_tool(self, budget_tracker) -> LLMTool:
    """Return an LLM tool tied to the given budget tracker."""
    ...

AtomicOntologyCatalog

Bases: Protocol

The slice of an ontology catalog the per-unit repairs read.

A unit sees a retrieved snapshot of the catalog; the repairs that decide whether a term is real need the whole catalog, since a term the snapshot did not retrieve is still a term.

Source code in ontocast/tool/atomic.py
class AtomicOntologyCatalog(Protocol):
    """The slice of an ontology catalog the per-unit repairs read.

    A unit sees a retrieved *snapshot* of the catalog; the repairs that decide
    whether a term is real need the *whole* catalog, since a term the snapshot
    did not retrieve is still a term.
    """

    def catalog_terms(self) -> set[str]:
        """Every IRI any served ontology declares or references."""
        ...

Methods:

catalog_terms()

Every IRI any served ontology declares or references.

Source code in ontocast/tool/atomic.py
def catalog_terms(self) -> set[str]:
    """Every IRI any served ontology declares or references."""
    ...

AtomicSearchProvider

Bases: Protocol

Provides optional web-search retrieval for ontology grounding.

Source code in ontocast/tool/atomic.py
class AtomicSearchProvider(Protocol):
    """Provides optional web-search retrieval for ontology grounding."""

    async def search(self, query: str, max_results: int) -> list[SearchHit]:
        """Return web hits relevant to the query."""
        ...

Methods:

search(query, max_results) async

Return web hits relevant to the query.

Source code in ontocast/tool/atomic.py
async def search(self, query: str, max_results: int) -> list[SearchHit]:
    """Return web hits relevant to the query."""
    ...

AtomicToolBox

Small tool surface used by atomic render/critic paths.

Configuration arrives as config sections, never as unpacked scalars. An earlier signature accepted both a :class:WebSearchConfig and seventeen flat web_search_* parameters mirroring its fields, chosen between by an if/else; production passed the section and only tests took the flat branch, so the tested configuration path was not the one that shipped. Each default also existed three times -- here, in settings.py, and inline at the read sites. Now settings.py is the single source.

Source code in ontocast/tool/atomic.py
class AtomicToolBox:
    """Small tool surface used by atomic render/critic paths.

    Configuration arrives as config *sections*, never as unpacked scalars. An
    earlier signature accepted both a :class:`WebSearchConfig` and seventeen
    flat ``web_search_*`` parameters mirroring its fields, chosen between by an
    ``if/else``; production passed the section and only tests took the flat
    branch, so the tested configuration path was not the one that shipped. Each
    default also existed three times -- here, in ``settings.py``, and inline at
    the read sites. Now ``settings.py`` is the single source.
    """

    def __init__(
        self,
        llm_provider: AtomicLLMProvider,
        search_provider: AtomicSearchProvider | None = None,
        web_search_config: WebSearchConfig | None = None,
        facts_validation_config: FactsValidationConfig | None = None,
        ontology_validation_config: OntologyValidationConfig | None = None,
        citation_vocabulary: dict[str, str] | None = None,
        ontology_catalog: AtomicOntologyCatalog | None = None,
    ):
        """Build the atomic tool surface.

        Args:
            llm_provider: Supplies budget-aware LLM tools.
            search_provider: Optional web-search backend. Without one, search
                returns no hits regardless of configuration.
            web_search_config: Web-grounding settings. Defaults to
                :class:`WebSearchConfig`, which is disabled unless configured.
            facts_validation_config: Facts-gate settings consumed by the render
                and critic paths. Defaults to :class:`FactsValidationConfig`.
            ontology_validation_config: Ontology-delta settings, including the
                ontology critic's pass budget and patch limits. Defaults to
                :class:`OntologyValidationConfig`.
            citation_vocabulary: Bibliographic terms for citation-metadata
                units. Configuration rather than retrieval: a reference list is
                not domain content, so its vocabulary never reaches the catalog.
            ontology_catalog: The scope's full ontology catalog, read by the
                per-unit repairs for term membership. The shared surface is
                built without one; :meth:`scoped_to_catalog` binds it per
                scope.
        """
        web_search = web_search_config or WebSearchConfig()
        facts_validation = facts_validation_config or FactsValidationConfig()
        ontology_validation = ontology_validation_config or OntologyValidationConfig()

        self.llm_provider = llm_provider
        self.search_provider = search_provider
        self.web_search_config = web_search
        self.ontology_catalog: AtomicOntologyCatalog | None = ontology_catalog

        self.object_property_literal_check = (
            facts_validation.object_property_literal_check
        )
        # Review-and-patch passes: each one is a provider call.
        self.facts_critic_passes = facts_validation.critic_passes
        self.ontology_critic_passes = ontology_validation.critic_passes
        # Below this many rendered triples the facts critic is skipped: a
        # review of an empty graph is a billed call that changes nothing.
        self.facts_critic_min_triples = facts_validation.critic_min_triples
        # Insert-only completion passes after the critic loop, each a provider
        # call, taken only while measurements are still missing.
        self.facts_completion_passes = facts_validation.completion_passes
        self.facts_patch_policy = CriticPatchPolicy(
            max_delete_share=facts_validation.critic_max_delete_share,
            min_deletes=facts_validation.critic_min_deletes,
            allow_subject_rename=facts_validation.critic_allow_subject_rename,
        )
        self.ontology_patch_policy = CriticPatchPolicy(
            max_delete_share=ontology_validation.critic_max_delete_share,
            min_deletes=ontology_validation.critic_min_deletes,
            allow_subject_rename=False,
        )
        # Numeric-coverage knobs for the deterministic per-unit validator.
        self.numeric_coverage_limit = facts_validation.numeric_coverage_limit
        self.numeric_coverage_mandatory = facts_validation.numeric_coverage_mandatory
        # Code predicates for the LLM-free code -> catalog IRI repair.
        self.code_predicates: tuple[str, ...] = tuple(facts_validation.code_predicates)
        self.property_alias_min_ratio = facts_validation.property_alias_min_ratio
        self.citation_vocabulary: dict[str, str] = dict(citation_vocabulary or {})
        # Fallback vocabulary the facts prompt names for bounded quantities when
        # retrieval supplied no suitable class. An explicitly empty mapping
        # forbids the fallback.
        self.quantity_fallback_vocabulary: dict[str, str] | None = dict(
            facts_validation.quantity_fallback_vocabulary
        )
        # Non-meta vocabularies a deployment shares across catalogs and does not
        # want reported as unknown terms.
        self.additional_standard_namespaces: tuple[str, ...] = tuple(
            facts_validation.additional_standard_namespaces
        )
        # Everything the deterministic term checks must treat as blessed, as
        # one object -- see ValidationPolicy.
        self.validation_policy = ValidationPolicy(
            additional_standard_namespaces=self.additional_standard_namespaces,
            quantity_fallback_vocabulary=self.quantity_fallback_vocabulary,
            code_predicates=self.code_predicates,
            numeric_identifier_guard=facts_validation.numeric_identifier_guard,
            domain_adherence_min_share=facts_validation.domain_adherence_min_share,
            domain_adherence_min_terms=facts_validation.domain_adherence_min_terms,
        )
        # A sibling of ValidationPolicy, deliberately not a field on it.
        # ValidationPolicy answers "what must never be flagged"; this answers
        # "what blocks a unit from leaving the loop". Both travel to the unit
        # loop, but the term checks and the catalog lint have no business
        # knowing about acceptance.
        self.acceptance_policy = FactsAcceptancePolicy(
            blocking_fix_severity=facts_validation.accept_blocking_severity,
        )
        self.ontology_acceptance_policy = FactsAcceptancePolicy(
            blocking_finding_kinds=frozenset(
                ontology_validation.accept_blocking_finding_kinds
            ),
            blocking_fix_severity=facts_validation.accept_blocking_severity,
        )

        self.web_search_enabled = web_search.enabled
        self.web_search_top_k = web_search.top_k
        self.web_search_max_snippet_chars = web_search.max_snippet_chars
        self.web_search_max_total_chars = web_search.max_total_chars
        self.web_search_for_ontology_render = web_search.ontology_render_enabled
        self.web_search_for_ontology_critic = web_search.ontology_critic_enabled
        self.web_search_for_facts_render = web_search.facts_render_enabled
        self.web_search_for_facts_critic = web_search.facts_critic_enabled
        self.web_search_planner_enabled = web_search.planner_enabled
        self.web_search_planner_max_queries = web_search.planner_max_queries
        self.web_search_planner_min_query_chars = web_search.planner_min_query_chars
        self.web_search_planner_min_confidence = web_search.planner_min_confidence
        self.web_search_reuse_evidence_across_attempt = (
            web_search.reuse_evidence_across_attempt
        )
        self.web_search_allowed_domains = _domain_set(web_search.allowed_domains)
        self.web_search_blocked_domains = _domain_set(web_search.blocked_domains)
        self.web_search_min_snippet_chars = web_search.min_snippet_chars

    def scoped_to_catalog(self, catalog: AtomicOntologyCatalog) -> "AtomicToolBox":
        """A shallow copy of this surface bound to ``catalog``.

        The surface is tenancy-independent and shared by every scope; a
        catalog is not. Binding on a copy rather than on ``self`` keeps one
        scope's catalog from being read by a unit of another scope that runs on
        the same shared instance.
        """
        scoped = copy.copy(self)
        scoped.ontology_catalog = catalog
        return scoped

    def catalog_terms(self) -> set[str]:
        """Every IRI the bound catalog declares or references, across all of it.

        Membership set for the per-unit repairs: a predicate present here is a
        real catalog term even when the unit's retrieved snapshot omits it, and
        must never be rewritten toward a look-alike the snapshot does carry.
        Empty when no catalog is bound. The catalog memoises the set on its
        served versions, so calling this per unit is cheap; treat the result
        as read-only.
        """
        if self.ontology_catalog is None:
            return set()
        return self.ontology_catalog.catalog_terms()

    async def get_llm_tool(self, budget_tracker) -> LLMTool:
        """Return a budget-aware LLM tool instance."""
        return await self.llm_provider.get_llm_tool(budget_tracker)

    async def search(
        self, query: str, max_results: int | None = None
    ) -> list[SearchHit]:
        """Run optional web search and return normalized hits."""
        if not self.web_search_enabled or self.search_provider is None:
            return []

        result_limit = max_results if max_results is not None else self.web_search_top_k
        return await self.search_provider.search(query=query, max_results=result_limit)

    def web_grounding_enabled_for_node(self, node: WorkflowNode) -> bool:
        """Return whether web grounding is enabled for a workflow node."""
        if not self.web_search_enabled:
            return False
        mapping = {
            WorkflowNode.TEXT_TO_ONTOLOGY: self.web_search_for_ontology_render,
            WorkflowNode.CRITICISE_ONTOLOGY: self.web_search_for_ontology_critic,
            WorkflowNode.TEXT_TO_FACTS: self.web_search_for_facts_render,
            WorkflowNode.CRITICISE_FACTS: self.web_search_for_facts_critic,
        }
        return mapping.get(node, False)

Attributes

acceptance_policy = FactsAcceptancePolicy(blocking_fix_severity=facts_validation.accept_blocking_severity) instance-attribute
additional_standard_namespaces = tuple(facts_validation.additional_standard_namespaces) instance-attribute
citation_vocabulary = dict(citation_vocabulary or {}) instance-attribute
code_predicates = tuple(facts_validation.code_predicates) instance-attribute
facts_completion_passes = facts_validation.completion_passes instance-attribute
facts_critic_min_triples = facts_validation.critic_min_triples instance-attribute
facts_critic_passes = facts_validation.critic_passes instance-attribute
facts_patch_policy = CriticPatchPolicy(max_delete_share=facts_validation.critic_max_delete_share, min_deletes=facts_validation.critic_min_deletes, allow_subject_rename=facts_validation.critic_allow_subject_rename) instance-attribute
llm_provider = llm_provider instance-attribute
numeric_coverage_limit = facts_validation.numeric_coverage_limit instance-attribute
numeric_coverage_mandatory = facts_validation.numeric_coverage_mandatory instance-attribute
object_property_literal_check = facts_validation.object_property_literal_check instance-attribute
ontology_acceptance_policy = FactsAcceptancePolicy(blocking_finding_kinds=frozenset(ontology_validation.accept_blocking_finding_kinds), blocking_fix_severity=facts_validation.accept_blocking_severity) instance-attribute
ontology_catalog = ontology_catalog instance-attribute
ontology_critic_passes = ontology_validation.critic_passes instance-attribute
ontology_patch_policy = CriticPatchPolicy(max_delete_share=ontology_validation.critic_max_delete_share, min_deletes=ontology_validation.critic_min_deletes, allow_subject_rename=False) instance-attribute
property_alias_min_ratio = facts_validation.property_alias_min_ratio instance-attribute
quantity_fallback_vocabulary = dict(facts_validation.quantity_fallback_vocabulary) instance-attribute
search_provider = search_provider instance-attribute
validation_policy = ValidationPolicy(additional_standard_namespaces=self.additional_standard_namespaces, quantity_fallback_vocabulary=self.quantity_fallback_vocabulary, code_predicates=self.code_predicates, numeric_identifier_guard=facts_validation.numeric_identifier_guard, domain_adherence_min_share=facts_validation.domain_adherence_min_share, domain_adherence_min_terms=facts_validation.domain_adherence_min_terms) instance-attribute
web_search_allowed_domains = _domain_set(web_search.allowed_domains) instance-attribute
web_search_blocked_domains = _domain_set(web_search.blocked_domains) instance-attribute
web_search_config = web_search instance-attribute
web_search_enabled = web_search.enabled instance-attribute
web_search_for_facts_critic = web_search.facts_critic_enabled instance-attribute
web_search_for_facts_render = web_search.facts_render_enabled instance-attribute
web_search_for_ontology_critic = web_search.ontology_critic_enabled instance-attribute
web_search_for_ontology_render = web_search.ontology_render_enabled instance-attribute
web_search_max_snippet_chars = web_search.max_snippet_chars instance-attribute
web_search_max_total_chars = web_search.max_total_chars instance-attribute
web_search_min_snippet_chars = web_search.min_snippet_chars instance-attribute
web_search_planner_enabled = web_search.planner_enabled instance-attribute
web_search_planner_max_queries = web_search.planner_max_queries instance-attribute
web_search_planner_min_confidence = web_search.planner_min_confidence instance-attribute
web_search_planner_min_query_chars = web_search.planner_min_query_chars instance-attribute
web_search_reuse_evidence_across_attempt = web_search.reuse_evidence_across_attempt instance-attribute
web_search_top_k = web_search.top_k instance-attribute

Methods:

__init__(llm_provider, search_provider=None, web_search_config=None, facts_validation_config=None, ontology_validation_config=None, citation_vocabulary=None, ontology_catalog=None)

Build the atomic tool surface.

Parameters:

Name Type Description Default
llm_provider AtomicLLMProvider

Supplies budget-aware LLM tools.

required
search_provider AtomicSearchProvider | None

Optional web-search backend. Without one, search returns no hits regardless of configuration.

None
web_search_config WebSearchConfig | None

Web-grounding settings. Defaults to :class:WebSearchConfig, which is disabled unless configured.

None
facts_validation_config FactsValidationConfig | None

Facts-gate settings consumed by the render and critic paths. Defaults to :class:FactsValidationConfig.

None
ontology_validation_config OntologyValidationConfig | None

Ontology-delta settings, including the ontology critic's pass budget and patch limits. Defaults to :class:OntologyValidationConfig.

None
citation_vocabulary dict[str, str] | None

Bibliographic terms for citation-metadata units. Configuration rather than retrieval: a reference list is not domain content, so its vocabulary never reaches the catalog.

None
ontology_catalog AtomicOntologyCatalog | None

The scope's full ontology catalog, read by the per-unit repairs for term membership. The shared surface is built without one; :meth:scoped_to_catalog binds it per scope.

None
Source code in ontocast/tool/atomic.py
def __init__(
    self,
    llm_provider: AtomicLLMProvider,
    search_provider: AtomicSearchProvider | None = None,
    web_search_config: WebSearchConfig | None = None,
    facts_validation_config: FactsValidationConfig | None = None,
    ontology_validation_config: OntologyValidationConfig | None = None,
    citation_vocabulary: dict[str, str] | None = None,
    ontology_catalog: AtomicOntologyCatalog | None = None,
):
    """Build the atomic tool surface.

    Args:
        llm_provider: Supplies budget-aware LLM tools.
        search_provider: Optional web-search backend. Without one, search
            returns no hits regardless of configuration.
        web_search_config: Web-grounding settings. Defaults to
            :class:`WebSearchConfig`, which is disabled unless configured.
        facts_validation_config: Facts-gate settings consumed by the render
            and critic paths. Defaults to :class:`FactsValidationConfig`.
        ontology_validation_config: Ontology-delta settings, including the
            ontology critic's pass budget and patch limits. Defaults to
            :class:`OntologyValidationConfig`.
        citation_vocabulary: Bibliographic terms for citation-metadata
            units. Configuration rather than retrieval: a reference list is
            not domain content, so its vocabulary never reaches the catalog.
        ontology_catalog: The scope's full ontology catalog, read by the
            per-unit repairs for term membership. The shared surface is
            built without one; :meth:`scoped_to_catalog` binds it per
            scope.
    """
    web_search = web_search_config or WebSearchConfig()
    facts_validation = facts_validation_config or FactsValidationConfig()
    ontology_validation = ontology_validation_config or OntologyValidationConfig()

    self.llm_provider = llm_provider
    self.search_provider = search_provider
    self.web_search_config = web_search
    self.ontology_catalog: AtomicOntologyCatalog | None = ontology_catalog

    self.object_property_literal_check = (
        facts_validation.object_property_literal_check
    )
    # Review-and-patch passes: each one is a provider call.
    self.facts_critic_passes = facts_validation.critic_passes
    self.ontology_critic_passes = ontology_validation.critic_passes
    # Below this many rendered triples the facts critic is skipped: a
    # review of an empty graph is a billed call that changes nothing.
    self.facts_critic_min_triples = facts_validation.critic_min_triples
    # Insert-only completion passes after the critic loop, each a provider
    # call, taken only while measurements are still missing.
    self.facts_completion_passes = facts_validation.completion_passes
    self.facts_patch_policy = CriticPatchPolicy(
        max_delete_share=facts_validation.critic_max_delete_share,
        min_deletes=facts_validation.critic_min_deletes,
        allow_subject_rename=facts_validation.critic_allow_subject_rename,
    )
    self.ontology_patch_policy = CriticPatchPolicy(
        max_delete_share=ontology_validation.critic_max_delete_share,
        min_deletes=ontology_validation.critic_min_deletes,
        allow_subject_rename=False,
    )
    # Numeric-coverage knobs for the deterministic per-unit validator.
    self.numeric_coverage_limit = facts_validation.numeric_coverage_limit
    self.numeric_coverage_mandatory = facts_validation.numeric_coverage_mandatory
    # Code predicates for the LLM-free code -> catalog IRI repair.
    self.code_predicates: tuple[str, ...] = tuple(facts_validation.code_predicates)
    self.property_alias_min_ratio = facts_validation.property_alias_min_ratio
    self.citation_vocabulary: dict[str, str] = dict(citation_vocabulary or {})
    # Fallback vocabulary the facts prompt names for bounded quantities when
    # retrieval supplied no suitable class. An explicitly empty mapping
    # forbids the fallback.
    self.quantity_fallback_vocabulary: dict[str, str] | None = dict(
        facts_validation.quantity_fallback_vocabulary
    )
    # Non-meta vocabularies a deployment shares across catalogs and does not
    # want reported as unknown terms.
    self.additional_standard_namespaces: tuple[str, ...] = tuple(
        facts_validation.additional_standard_namespaces
    )
    # Everything the deterministic term checks must treat as blessed, as
    # one object -- see ValidationPolicy.
    self.validation_policy = ValidationPolicy(
        additional_standard_namespaces=self.additional_standard_namespaces,
        quantity_fallback_vocabulary=self.quantity_fallback_vocabulary,
        code_predicates=self.code_predicates,
        numeric_identifier_guard=facts_validation.numeric_identifier_guard,
        domain_adherence_min_share=facts_validation.domain_adherence_min_share,
        domain_adherence_min_terms=facts_validation.domain_adherence_min_terms,
    )
    # A sibling of ValidationPolicy, deliberately not a field on it.
    # ValidationPolicy answers "what must never be flagged"; this answers
    # "what blocks a unit from leaving the loop". Both travel to the unit
    # loop, but the term checks and the catalog lint have no business
    # knowing about acceptance.
    self.acceptance_policy = FactsAcceptancePolicy(
        blocking_fix_severity=facts_validation.accept_blocking_severity,
    )
    self.ontology_acceptance_policy = FactsAcceptancePolicy(
        blocking_finding_kinds=frozenset(
            ontology_validation.accept_blocking_finding_kinds
        ),
        blocking_fix_severity=facts_validation.accept_blocking_severity,
    )

    self.web_search_enabled = web_search.enabled
    self.web_search_top_k = web_search.top_k
    self.web_search_max_snippet_chars = web_search.max_snippet_chars
    self.web_search_max_total_chars = web_search.max_total_chars
    self.web_search_for_ontology_render = web_search.ontology_render_enabled
    self.web_search_for_ontology_critic = web_search.ontology_critic_enabled
    self.web_search_for_facts_render = web_search.facts_render_enabled
    self.web_search_for_facts_critic = web_search.facts_critic_enabled
    self.web_search_planner_enabled = web_search.planner_enabled
    self.web_search_planner_max_queries = web_search.planner_max_queries
    self.web_search_planner_min_query_chars = web_search.planner_min_query_chars
    self.web_search_planner_min_confidence = web_search.planner_min_confidence
    self.web_search_reuse_evidence_across_attempt = (
        web_search.reuse_evidence_across_attempt
    )
    self.web_search_allowed_domains = _domain_set(web_search.allowed_domains)
    self.web_search_blocked_domains = _domain_set(web_search.blocked_domains)
    self.web_search_min_snippet_chars = web_search.min_snippet_chars
catalog_terms()

Every IRI the bound catalog declares or references, across all of it.

Membership set for the per-unit repairs: a predicate present here is a real catalog term even when the unit's retrieved snapshot omits it, and must never be rewritten toward a look-alike the snapshot does carry. Empty when no catalog is bound. The catalog memoises the set on its served versions, so calling this per unit is cheap; treat the result as read-only.

Source code in ontocast/tool/atomic.py
def catalog_terms(self) -> set[str]:
    """Every IRI the bound catalog declares or references, across all of it.

    Membership set for the per-unit repairs: a predicate present here is a
    real catalog term even when the unit's retrieved snapshot omits it, and
    must never be rewritten toward a look-alike the snapshot does carry.
    Empty when no catalog is bound. The catalog memoises the set on its
    served versions, so calling this per unit is cheap; treat the result
    as read-only.
    """
    if self.ontology_catalog is None:
        return set()
    return self.ontology_catalog.catalog_terms()
get_llm_tool(budget_tracker) async

Return a budget-aware LLM tool instance.

Source code in ontocast/tool/atomic.py
async def get_llm_tool(self, budget_tracker) -> LLMTool:
    """Return a budget-aware LLM tool instance."""
    return await self.llm_provider.get_llm_tool(budget_tracker)
scoped_to_catalog(catalog)

A shallow copy of this surface bound to catalog.

The surface is tenancy-independent and shared by every scope; a catalog is not. Binding on a copy rather than on self keeps one scope's catalog from being read by a unit of another scope that runs on the same shared instance.

Source code in ontocast/tool/atomic.py
def scoped_to_catalog(self, catalog: AtomicOntologyCatalog) -> "AtomicToolBox":
    """A shallow copy of this surface bound to ``catalog``.

    The surface is tenancy-independent and shared by every scope; a
    catalog is not. Binding on a copy rather than on ``self`` keeps one
    scope's catalog from being read by a unit of another scope that runs on
    the same shared instance.
    """
    scoped = copy.copy(self)
    scoped.ontology_catalog = catalog
    return scoped
search(query, max_results=None) async

Run optional web search and return normalized hits.

Source code in ontocast/tool/atomic.py
async def search(
    self, query: str, max_results: int | None = None
) -> list[SearchHit]:
    """Run optional web search and return normalized hits."""
    if not self.web_search_enabled or self.search_provider is None:
        return []

    result_limit = max_results if max_results is not None else self.web_search_top_k
    return await self.search_provider.search(query=query, max_results=result_limit)
web_grounding_enabled_for_node(node)

Return whether web grounding is enabled for a workflow node.

Source code in ontocast/tool/atomic.py
def web_grounding_enabled_for_node(self, node: WorkflowNode) -> bool:
    """Return whether web grounding is enabled for a workflow node."""
    if not self.web_search_enabled:
        return False
    mapping = {
        WorkflowNode.TEXT_TO_ONTOLOGY: self.web_search_for_ontology_render,
        WorkflowNode.CRITICISE_ONTOLOGY: self.web_search_for_ontology_critic,
        WorkflowNode.TEXT_TO_FACTS: self.web_search_for_facts_render,
        WorkflowNode.CRITICISE_FACTS: self.web_search_for_facts_critic,
    }
    return mapping.get(node, False)

SearchHit

Bases: BaseModel

Single web-search hit used as optional grounding context.

Source code in ontocast/tool/atomic.py
class SearchHit(BaseModel):
    """Single web-search hit used as optional grounding context."""

    title: str
    url: str
    snippet: str

Attributes

snippet instance-attribute
title instance-attribute
url instance-attribute