Files
wehub-resource-sync 2c632336aa
CI / Viewer CI (push) Successful in 13m37s
CI / Core CI (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:38 +08:00

742 lines
22 KiB
Python

from __future__ import annotations
import re
import unicodedata
from dataclasses import dataclass
from functools import lru_cache
from pathlib import Path
import bm25s
_FRONTMATTER_RE = re.compile(r"\A---\n(?P<frontmatter>.*?)\n---\n?(?P<body>.*)\Z", re.DOTALL)
_TOKEN_PATTERN = re.compile(r"[a-z0-9]+")
_CODE_FENCE_RE = re.compile(r"```[^\n]*\n(?P<code>.*?)```", re.DOTALL)
_IDENTIFIER_PATTERN = re.compile(r"[A-Za-z_][A-Za-z0-9_]*")
_CAMEL_CASE_BOUNDARY_RE = re.compile(r"(?<=[a-z0-9])(?=[A-Z])")
_NON_DISTINCTIVE_TAG_TOKENS = frozenset({"cadquery", "example", "examples"})
_NON_DISTINCTIVE_CODE_TOKENS = frozenset({"cq", "false", "none", "result", "self", "true"})
_STOPWORD_TOKENS = frozenset(
{
"a",
"an",
"and",
"as",
"at",
"by",
"for",
"from",
"in",
"into",
"of",
"on",
"or",
"the",
"to",
"with",
"without",
}
)
_FIELD_REPETITIONS = {
"slug": 6,
"title": 5,
"tags": 4,
"description": 3,
"code": 2,
"prose": 1,
}
_FIELD_BONUSES = {
"slug": 4.0,
"title": 3.5,
"tags": 3.0,
"description": 1.75,
"code": 1.25,
"prose": 0.5,
}
_FIELD_PREFIX_BONUSES = {
"slug": 1.5,
"title": 1.25,
"tags": 1.0,
"description": 0.6,
"code": 0.5,
"prose": 0.2,
}
_FIELD_PHRASE_BONUSES = {
"slug": 4.0,
"title": 3.5,
"tags": 2.5,
"description": 1.5,
"code": 1.0,
"prose": 0.75,
}
@dataclass(slots=True, frozen=True)
class ExampleDocument:
path: Path
title: str
description: str
tags: tuple[str, ...]
body: str
content: str
@dataclass(slots=True, frozen=True)
class SearchField:
tokens: tuple[str, ...]
token_set: frozenset[str]
phrase_text: str
@dataclass(slots=True, frozen=True)
class IndexedExampleDocument:
doc: ExampleDocument
slug: SearchField
title: SearchField
description: SearchField
tags: SearchField
prose: SearchField
code: SearchField
weighted_tokens: tuple[str, ...]
@dataclass(slots=True, frozen=True)
class ExampleIndex:
documents: tuple[IndexedExampleDocument, ...]
retriever: bm25s.BM25
@dataclass(slots=True, frozen=True)
class ExampleSearchMatch:
doc: ExampleDocument
match_quality: str
matched_tokens: tuple[str, ...]
matched_fields: tuple[str, ...]
score: float
structured_match_count: int
total_match_count: int
coverage: float
has_non_prose_phrase_hit: bool
has_code_only_signal: bool
@property
def path(self) -> Path:
return self.doc.path
@property
def title(self) -> str:
return self.doc.title
@property
def description(self) -> str:
return self.doc.description
@property
def tags(self) -> tuple[str, ...]:
return self.doc.tags
@property
def body(self) -> str:
return self.doc.body
@property
def content(self) -> str:
return self.doc.content
@dataclass(slots=True, frozen=True)
class _CandidateMatch:
doc: ExampleDocument
score: float
bm25_score: float
matched_tokens: tuple[str, ...]
matched_fields: tuple[str, ...]
structured_match_count: int
total_match_count: int
coverage: float
has_non_prose_phrase_hit: bool
has_metadata_phrase_hit: bool
has_code_only_signal: bool
has_structured_signal: bool
has_slug_or_title_prefix: bool
prose_matches: tuple[str, ...]
def _repo_root() -> Path:
return Path(__file__).resolve().parents[1]
def examples_root() -> Path:
return _repo_root() / "sdk" / "_examples"
def example_dirs_for_sdk(sdk_package: str) -> tuple[Path, ...]:
if sdk_package == "sdk":
return (
examples_root() / "base",
examples_root() / "cadquery",
)
raise ValueError(f"Unsupported SDK package for examples: {sdk_package!r}")
def _normalize_text(value: str) -> str:
normalized = unicodedata.normalize("NFKD", value)
ascii_text = normalized.encode("ascii", "ignore").decode("ascii")
return ascii_text.lower()
def _tokenize(value: str) -> list[str]:
return _TOKEN_PATTERN.findall(_normalize_text(value))
def _meaningful_tokens(value: str) -> list[str]:
return [
token
for token in _tokenize(value)
if token not in _NON_DISTINCTIVE_TAG_TOKENS and token not in _STOPWORD_TOKENS
]
def _dedupe_preserving_order(tokens: list[str]) -> list[str]:
return list(dict.fromkeys(tokens))
def _token_variants(token: str) -> list[str]:
variants = [token]
candidate: str | None = None
if len(token) > 5 and token.endswith("ies"):
candidate = f"{token[:-3]}y"
elif len(token) > 6 and token.endswith("ing"):
candidate = token[:-3]
elif len(token) > 5 and token.endswith("ed"):
candidate = token[:-2]
elif len(token) > 4 and token.endswith("es"):
candidate = token[:-2]
elif len(token) > 4 and token.endswith("s"):
candidate = token[:-1]
if candidate and len(candidate) >= 4 and candidate not in variants:
variants.append(candidate)
if len(token) > 6 and token.endswith("e"):
candidate = token[:-1]
if len(candidate) >= 4 and candidate not in variants:
variants.append(candidate)
return variants
def _split_identifier(identifier: str) -> list[str]:
normalized = _normalize_text(identifier)
if not normalized:
return []
expanded = _CAMEL_CASE_BOUNDARY_RE.sub(" ", identifier.replace("_", " ").replace("-", " "))
split_tokens = _tokenize(expanded)
ordered: list[str] = []
seen: set[str] = set()
for token in [normalized, *split_tokens]:
if (
token
and token not in seen
and token not in _STOPWORD_TOKENS
and token not in _NON_DISTINCTIVE_TAG_TOKENS
and token not in _NON_DISTINCTIVE_CODE_TOKENS
):
ordered.append(token)
seen.add(token)
return ordered
def _query_alias_tokens(query: str, query_tokens: list[str]) -> list[str]:
aliases: list[str] = []
for token in query_tokens:
for variant in _token_variants(token)[1:]:
if variant not in query_tokens:
aliases.append(variant)
for identifier in _IDENTIFIER_PATTERN.findall(query):
parts = _split_identifier(identifier)
if len(parts) <= 1:
continue
for token in parts[1:]:
if token not in query_tokens and len(token) >= 4:
aliases.append(token)
return _dedupe_preserving_order(aliases)
def _extract_code_tokens(body: str) -> list[str]:
tokens: list[str] = []
for match in _CODE_FENCE_RE.finditer(body):
code = match.group("code")
for identifier in _IDENTIFIER_PATTERN.findall(code):
tokens.extend(_split_identifier(identifier))
return tokens
def _strip_code_fences(body: str) -> str:
return _CODE_FENCE_RE.sub("\n", body)
def _build_search_field(tokens: list[str]) -> SearchField:
stable_tokens = tuple(
_dedupe_preserving_order(
[variant for token in tokens for variant in _token_variants(token)]
)
)
phrase_tokens = tuple(_dedupe_preserving_order(tokens))
return SearchField(
tokens=stable_tokens,
token_set=frozenset(stable_tokens),
phrase_text=" ".join(phrase_tokens),
)
def _build_weighted_tokens(
*,
slug: SearchField,
title: SearchField,
description: SearchField,
tags: SearchField,
prose: SearchField,
code: SearchField,
) -> tuple[str, ...]:
weighted: list[str] = []
for field_name, field in (
("slug", slug),
("title", title),
("tags", tags),
("description", description),
("code", code),
("prose", prose),
):
weighted.extend(list(field.tokens) * _FIELD_REPETITIONS[field_name])
return tuple(weighted)
def _index_document(doc: ExampleDocument) -> IndexedExampleDocument:
slug = _build_search_field(_meaningful_tokens(doc.path.stem.replace("_", " ")))
title = _build_search_field(_meaningful_tokens(doc.title))
description = _build_search_field(_meaningful_tokens(doc.description))
tags = _build_search_field(_meaningful_tokens(" ".join(doc.tags)))
prose = _build_search_field(_meaningful_tokens(_strip_code_fences(doc.body)))
code = _build_search_field(_extract_code_tokens(doc.body))
return IndexedExampleDocument(
doc=doc,
slug=slug,
title=title,
description=description,
tags=tags,
prose=prose,
code=code,
weighted_tokens=_build_weighted_tokens(
slug=slug,
title=title,
description=description,
tags=tags,
prose=prose,
code=code,
),
)
def _field_has_prefix(field: SearchField, query_token: str) -> bool:
if len(query_token) < 4:
return False
return any(
token != query_token
and min(len(token), len(query_token)) >= 4
and (token.startswith(query_token) or query_token.startswith(token))
for token in field.token_set
)
def _parse_frontmatter_value(raw: str) -> str:
value = raw.strip()
if len(value) >= 2 and value[0] == value[-1] and value[0] in {'"', "'"}:
inner = value[1:-1]
if value[0] == "'":
return inner.replace("''", "'")
return inner.replace('\\"', '"')
return value
def _parse_frontmatter(text: str, *, source: Path) -> dict[str, object]:
values: dict[str, object] = {}
current_key: str | None = None
list_values: list[str] = []
def _flush_list() -> None:
nonlocal current_key, list_values
if current_key is not None:
values[current_key] = list(list_values)
current_key = None
list_values = []
for raw_line in text.splitlines():
line = raw_line.rstrip()
stripped = line.strip()
if not stripped:
continue
if line.startswith(" - ") or line.startswith("- "):
item = line.split("-", 1)[1].strip()
if current_key is None:
raise ValueError(f"{source}: list item found before list key")
list_values.append(_parse_frontmatter_value(item))
continue
_flush_list()
if ":" not in line:
raise ValueError(f"{source}: invalid frontmatter line: {raw_line!r}")
key, raw_value = line.split(":", 1)
key = key.strip()
value = raw_value.strip()
if not key:
raise ValueError(f"{source}: missing frontmatter key")
if not value:
current_key = key
list_values = []
continue
if value.startswith("[") and value.endswith("]"):
inner = value[1:-1].strip()
if not inner:
values[key] = []
else:
values[key] = [_parse_frontmatter_value(part) for part in inner.split(",")]
continue
values[key] = _parse_frontmatter_value(value)
_flush_list()
return values
def parse_example_document(path: Path) -> ExampleDocument:
text = path.read_text(encoding="utf-8")
match = _FRONTMATTER_RE.match(text)
if not match:
raise ValueError(f"{path}: expected YAML frontmatter delimited by ---")
frontmatter = _parse_frontmatter(match.group("frontmatter"), source=path)
title = str(frontmatter.get("title") or "").strip()
description = str(frontmatter.get("description") or "").strip()
raw_tags = frontmatter.get("tags")
if not title:
raise ValueError(f"{path}: missing required frontmatter field 'title'")
if not description:
raise ValueError(f"{path}: missing required frontmatter field 'description'")
if not isinstance(raw_tags, list) or not raw_tags:
raise ValueError(f"{path}: missing required frontmatter field 'tags'")
tags = tuple(str(tag).strip() for tag in raw_tags if str(tag).strip())
if not tags:
raise ValueError(f"{path}: tags must contain at least one non-empty value")
return ExampleDocument(
path=path,
title=title,
description=description,
tags=tags,
body=match.group("body"),
content=text,
)
@lru_cache(maxsize=8)
def load_example_documents(sdk_package: str) -> tuple[ExampleDocument, ...]:
docs: list[ExampleDocument] = []
for root in example_dirs_for_sdk(sdk_package):
if not root.exists():
continue
docs.extend(parse_example_document(path) for path in sorted(root.glob("*.md")))
return tuple(docs)
@lru_cache(maxsize=8)
def load_example_search_index(sdk_package: str) -> ExampleIndex:
documents = tuple(_index_document(doc) for doc in load_example_documents(sdk_package))
retriever = bm25s.BM25()
if documents:
retriever.index(
[list(document.weighted_tokens) for document in documents],
show_progress=False,
)
return ExampleIndex(documents=documents, retriever=retriever)
def _collect_candidate_match(
indexed_doc: IndexedExampleDocument,
*,
bm25_score: float,
query_tokens: list[str],
query_alias_tokens: list[str],
phrase_query: str,
) -> _CandidateMatch | None:
metadata_field_names = {"slug", "title", "description", "tags"}
fields = {
"slug": indexed_doc.slug,
"title": indexed_doc.title,
"description": indexed_doc.description,
"tags": indexed_doc.tags,
"code": indexed_doc.code,
"prose": indexed_doc.prose,
}
score = bm25_score
matched_tokens: set[str] = set()
matched_fields: set[str] = set()
structured_matches: set[str] = set()
structured_fields: set[str] = set()
code_matches: set[str] = set()
prose_matches: set[str] = set()
phrase_fields: set[str] = set()
slug_or_title_prefix = False
for token in query_tokens:
for field_name, field in fields.items():
if token in field.token_set:
score += _FIELD_BONUSES[field_name]
matched_tokens.add(token)
matched_fields.add(field_name)
if field_name == "prose":
prose_matches.add(token)
elif field_name == "code":
code_matches.add(token)
else:
if field_name in metadata_field_names:
structured_matches.add(token)
structured_fields.add(field_name)
continue
if _field_has_prefix(field, token):
score += _FIELD_PREFIX_BONUSES[field_name]
matched_tokens.add(token)
matched_fields.add(field_name)
if field_name in {"slug", "title"}:
slug_or_title_prefix = True
if field_name == "prose":
prose_matches.add(token)
elif field_name == "code":
code_matches.add(token)
else:
if field_name in metadata_field_names:
structured_matches.add(token)
structured_fields.add(field_name)
for token in query_alias_tokens:
for field_name in ("slug", "title", "tags", "description"):
field = fields[field_name]
if token in field.token_set:
score += _FIELD_BONUSES[field_name] * 0.3
elif _field_has_prefix(field, token):
score += _FIELD_PREFIX_BONUSES[field_name] * 0.3
if len(query_tokens) >= 2:
for field_name, field in fields.items():
if phrase_query in field.phrase_text:
score += _FIELD_PHRASE_BONUSES[field_name]
phrase_fields.add(field_name)
matched_fields.add(field_name)
if not matched_tokens and not phrase_fields:
return None
coverage = len(matched_tokens) / len(query_tokens)
score += coverage * coverage * 3.0
if len(structured_matches) >= 2:
score += 2.0
elif structured_matches:
score += 1.0
metadata_phrase_fields = phrase_fields & metadata_field_names
has_structured_signal = bool(structured_matches or metadata_phrase_fields)
has_code_only_signal = bool(code_matches) and not has_structured_signal
return _CandidateMatch(
doc=indexed_doc.doc,
score=score,
bm25_score=bm25_score,
matched_tokens=tuple(sorted(matched_tokens)),
matched_fields=tuple(sorted(matched_fields)),
structured_match_count=len(structured_matches),
total_match_count=len(matched_tokens),
coverage=coverage,
has_non_prose_phrase_hit=bool(phrase_fields - {"prose"}),
has_metadata_phrase_hit=bool(metadata_phrase_fields),
has_code_only_signal=has_code_only_signal,
has_structured_signal=has_structured_signal,
has_slug_or_title_prefix=slug_or_title_prefix,
prose_matches=tuple(sorted(prose_matches)),
)
def _make_search_match(candidate: _CandidateMatch, *, match_quality: str) -> ExampleSearchMatch:
return ExampleSearchMatch(
doc=candidate.doc,
match_quality=match_quality,
matched_tokens=candidate.matched_tokens,
matched_fields=candidate.matched_fields,
score=candidate.score,
structured_match_count=candidate.structured_match_count,
total_match_count=candidate.total_match_count,
coverage=candidate.coverage,
has_non_prose_phrase_hit=candidate.has_non_prose_phrase_hit,
has_code_only_signal=candidate.has_code_only_signal,
)
def _single_token_matches(
candidates: list[_CandidateMatch],
*,
token: str,
limit: int,
) -> list[ExampleSearchMatch]:
ranked: list[_CandidateMatch] = []
for candidate in candidates:
if candidate.has_code_only_signal:
if len(token) < 5 or candidate.bm25_score < 0.5:
continue
elif not candidate.has_structured_signal:
if not (
token in candidate.prose_matches and len(token) >= 6 and candidate.score >= 2.0
):
continue
ranked.append(candidate)
ranked.sort(key=lambda item: (-item.score, item.doc.title, item.doc.path.as_posix()))
if not ranked:
return []
best_score = ranked[0].score
retained = [item for item in ranked if item.score >= max(1.0, best_score * 0.5)]
return [_make_search_match(item, match_quality="strong") for item in retained[:limit]]
def _is_strong_multi_token_match(candidate: _CandidateMatch) -> bool:
if candidate.has_code_only_signal:
return False
if candidate.has_metadata_phrase_hit:
return True
if candidate.structured_match_count >= 2:
return True
return candidate.total_match_count >= 3 and candidate.structured_match_count >= 1
def _is_weak_multi_token_match(candidate: _CandidateMatch, *, query_len: int) -> bool:
if not (candidate.structured_match_count >= 1 or candidate.has_slug_or_title_prefix):
return False
if query_len >= 3 and candidate.total_match_count < 2:
return False
return not candidate.has_code_only_signal
def _strong_multi_token_matches(
candidates: list[_CandidateMatch],
*,
limit: int,
) -> list[ExampleSearchMatch]:
ranked = [candidate for candidate in candidates if _is_strong_multi_token_match(candidate)]
ranked.sort(
key=lambda item: (
-item.coverage,
-item.structured_match_count,
-int(item.has_non_prose_phrase_hit),
-item.score,
item.doc.title,
item.doc.path.as_posix(),
)
)
if not ranked:
return []
best_score = max(item.score for item in ranked)
retained = [item for item in ranked if item.score >= max(1.0, best_score * 0.5)]
return [_make_search_match(item, match_quality="strong") for item in retained[:limit]]
def _weak_multi_token_matches(
candidates: list[_CandidateMatch],
*,
query_len: int,
limit: int,
) -> list[ExampleSearchMatch]:
ranked = [
candidate
for candidate in candidates
if not _is_strong_multi_token_match(candidate)
and _is_weak_multi_token_match(candidate, query_len=query_len)
]
ranked.sort(
key=lambda item: (
-item.structured_match_count,
-item.coverage,
-int(item.has_slug_or_title_prefix),
-item.score,
item.doc.title,
item.doc.path.as_posix(),
)
)
if not ranked:
return []
best_score = ranked[0].score
retained = [item for item in ranked if item.score >= max(1.0, best_score * 0.7)]
capped_limit = min(limit, 2)
return [
_make_search_match(item, match_quality="weakly_relevant")
for item in retained[:capped_limit]
]
def search_example_documents(
query: str,
*,
sdk_package: str,
limit: int = 3,
) -> list[ExampleSearchMatch]:
query_tokens = _dedupe_preserving_order(_meaningful_tokens(query))
if not query_tokens:
return []
index = load_example_search_index(sdk_package)
if not index.documents:
return []
query_alias_tokens = _query_alias_tokens(query, query_tokens)
query_for_bm25 = _dedupe_preserving_order([*query_tokens, *query_alias_tokens])
candidate_k = min(len(index.documents), max(limit * 6, 12))
retrieval = index.retriever.retrieve(
[query_for_bm25],
k=candidate_k,
corpus=list(range(len(index.documents))),
show_progress=False,
)
phrase_query = " ".join(query_tokens)
candidates: list[_CandidateMatch] = []
for raw_doc_index, raw_score in zip(retrieval.documents[0], retrieval.scores[0], strict=True):
bm25_score = float(raw_score)
if bm25_score <= 0:
continue
indexed_doc = index.documents[int(raw_doc_index)]
candidate = _collect_candidate_match(
indexed_doc,
bm25_score=bm25_score,
query_tokens=query_tokens,
query_alias_tokens=query_alias_tokens,
phrase_query=phrase_query,
)
if candidate is not None:
candidates.append(candidate)
if not candidates:
return []
if len(query_tokens) == 1:
return _single_token_matches(candidates, token=query_tokens[0], limit=limit)
strong_matches = _strong_multi_token_matches(candidates, limit=limit)
if strong_matches:
return strong_matches
return _weak_multi_token_matches(candidates, query_len=len(query_tokens), limit=limit)