mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-09-22 00:32:49 +00:00
docs(protocol): add typed edge link protocol documentation Add comprehensive documentation for the link protocol supporting typed edges in body text. This includes specification for three legal inline forms (bare wikilink, line-level Dataview, inline-bracketed Dataview), predicate syntax rules, and the machine-managed Relations section convention for organizing discovered edges. fix(memory): update path reference from vault_root to working_dir Change the memory_create operation's path anchoring from vault_root to working_dir to maintain consistency with the current working directory configuration. refactor(components): remove edge_extractor module and simplify parsing Remove the edge_extractor component module entirely and inline edge extraction logic directly into LinkedFileParser using parse_wikilinks utility. This simplifies the architecture by eliminating the separate edge extraction component and delegating edge discovery to the maintainer's enrichment operations. feat(parser): update parse method signature and simplify edge extraction Modify LinkedFileParser to return (FileNode, list[FileChunk]) tuple instead of ParsedFile, remove dependency on BaseEdgeExtractor, and implement direct wikilink parsing from body text only. ```
42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
"""Chunk-search helpers — small pure functions used by file_store backends.
|
|
|
|
Pulled out of `BaseFileStore` so the abstract base only carries graph
|
|
mechanics. Both `LocalFileStore` and `SqliteFileStore` consume these
|
|
to score / filter candidate chunks.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from reme2.schema import ChunkFilter, FileChunk
|
|
|
|
|
|
def keyword_score(query: str, text: str) -> float:
|
|
"""Word-overlap score with phrase bonus. Range [0, 1].
|
|
|
|
`match_count / n_words` baseline + 0.2 if the full query phrase
|
|
appears verbatim. Returns 0 when no query word hits the text.
|
|
"""
|
|
words = query.split()
|
|
if not words:
|
|
return 0.0
|
|
query_lower = query.lower()
|
|
words_lower = [w.lower() for w in words]
|
|
text_lower = text.lower()
|
|
n_words = len(words)
|
|
|
|
match_count = sum(1 for w in words_lower if w in text_lower)
|
|
if match_count == 0:
|
|
return 0.0
|
|
|
|
base = match_count / n_words
|
|
phrase_bonus = 0.2 if n_words > 1 and query_lower in text_lower else 0.0
|
|
return min(1.0, base + phrase_bonus)
|
|
|
|
|
|
def filter_chunks(
|
|
chunks: list[FileChunk], chunk_filter: ChunkFilter | None,
|
|
) -> list[FileChunk]:
|
|
"""Restrict `chunks` to those whose path passes the (compiled) filter."""
|
|
if chunk_filter is None or chunk_filter.resolved_paths is None:
|
|
return chunks
|
|
return [c for c in chunks if chunk_filter.match_path(c.path)]
|