跳转至

Executor#

nlql.exec —— Evaluator(表达式求值)与 Executor(执行召回 → 过滤 → 重排 → limit)。SIMILARITY 等函数的值在召回阶段计算并写入。

exec #

Query execution: the expression evaluator and the executor.

__all__ module-attribute #

__all__ = ['Executor', 'Evaluator']

Evaluator #

Evaluator(registry: Registry, field_types: dict[str, TypeTag] | None = None, type_handlers: dict | None = None)

Evaluates IR expressions against a single unit and a set of LET bindings.

源代码位于: src/nlql/exec/evaluate.py
def __init__(self, registry: Registry, field_types: dict[str, TypeTag] | None = None, type_handlers: dict | None = None) -> None:
    self._registry = registry
    self._field_types = field_types or {}
    self._type_handlers = type_handlers if type_handlers is not None else {}

eval #

eval(expr: Expr, unit: Unit, bindings: dict[str, Expr]) -> Any
源代码位于: src/nlql/exec/evaluate.py
def eval(self, expr: Expr, unit: Unit, bindings: dict[str, Expr]) -> Any:
    if isinstance(expr, Literal):
        return expr.value
    if isinstance(expr, Path):
        return self._eval_path(expr, unit)
    if isinstance(expr, Ref):
        if expr.name not in bindings:
            raise NLQLExecutionError(f"unknown alias {expr.name!r}")
        return self.eval(bindings[expr.name], unit, bindings)
    if isinstance(expr, Call):
        return self._eval_call(expr, unit, bindings)
    if isinstance(expr, Compare):
        return self._eval_compare(expr, unit, bindings)
    if isinstance(expr, And):
        return all(self.truthy(self.eval(o, unit, bindings)) for o in expr.operands)
    if isinstance(expr, Or):
        return any(self.truthy(self.eval(o, unit, bindings)) for o in expr.operands)
    if isinstance(expr, Not):
        return not self.truthy(self.eval(expr.operand, unit, bindings))
    raise NLQLExecutionError(f"cannot evaluate node {type(expr).__name__}")

truthy staticmethod #

truthy(value: Any) -> bool
源代码位于: src/nlql/exec/evaluate.py
@staticmethod
def truthy(value: Any) -> bool:
    return bool(value) if value is not None else False

Executor #

Executor(store: Store, registry: Any, embedder: Embedder, *, granularity: str = 'sentence', field_types: dict[str, TypeTag] | None = None, type_handlers: dict | None = None, reranker: Reranker | None = None, rerank_factor: int = 5, named_embedders: dict[str, Embedder] | None = None)

Executes queries against a :class:~nlql.store.base.Store.

源代码位于: src/nlql/exec/executor.py
def __init__(
    self,
    store: Store,
    registry: Any,
    embedder: Embedder,
    *,
    granularity: str = "sentence",
    field_types: dict[str, TypeTag] | None = None,
    type_handlers: dict | None = None,
    reranker: Reranker | None = None,
    rerank_factor: int = 5,
    named_embedders: dict[str, Embedder] | None = None,
) -> None:
    self._store = store
    self._registry = registry
    self._embedder = embedder
    self._granularity = granularity
    self._field_types = field_types or {}
    self._reranker = reranker
    self._rerank_factor = max(1, rerank_factor)
    self._named_embedders = named_embedders or {}
    self._planner = Planner(registry)
    self._evaluator = Evaluator(registry, self._field_types, type_handlers)

reranker property #

reranker: Reranker | None

plan #

plan(query: Query) -> QueryPlan
源代码位于: src/nlql/exec/executor.py
def plan(self, query: Query) -> QueryPlan:
    return self._planner.plan(
        query,
        granularity=self._granularity,
        caps=self._store.capabilities(),
        field_types=self._field_types,
    )

execute #

execute(query: Query, *, reranker: Reranker | None = None, rerank_query: str | None = None) -> list[Unit]
源代码位于: src/nlql/exec/executor.py
def execute(
    self,
    query: Query,
    *,
    reranker: Reranker | None = None,
    rerank_query: str | None = None,
) -> list[Unit]:
    active = reranker if reranker is not None else self._reranker
    plan = self.plan(query)
    # A reranker refines a wider candidate set, so recall over-fetches before it.
    overfetch = self._rerank_factor if (active is not None and plan.scorers) else 1
    candidates = self._recall(query, plan, overfetch=overfetch)
    self._apply_scores(candidates, plan)
    survivors = self._filter(candidates, plan)
    ordered = self._order(survivors, plan)
    results = self._materialize(ordered, plan)
    if active is not None and plan.scorers:
        question = rerank_query if rerank_query is not None else plan.scorers[0].query_text
        results = active.rerank(question, results)
    if query.limit is not None:
        results = results[: query.limit]
    self._surface_named_scores(results, plan)
    return results