feat(ebook): add protected phrase extraction library with config-driven tuning
Refactor protected phrase handling from a single module into a python/ebook_search/protected_phrases package covering extraction, storage, and runtime matching. Phrase filtering is now data-driven via bundled TOML files: ignored_phrases, bad_starts, bad_ends, and most_common_words. Add phrase-tuning settings to EbookSearchConfig so candidate generation, scoring, LLM judging, and matching are configurable rather than hardcoded: token bounds, entity token limit, raw n-gram min count, frequency and chapter-spread score thresholds, candidate/LLM/target caps, confidence threshold, nesting defaults, and the phrase hit boost.
This commit is contained in:
@@ -86,6 +86,21 @@ class EbookSearchConfig(BaseSettings):
|
|||||||
validate_citations_enabled: bool = True
|
validate_citations_enabled: bool = True
|
||||||
bm25_index_dir: str = ".ebook_search_bm25"
|
bm25_index_dir: str = ".ebook_search_bm25"
|
||||||
bm25_refresh_delay_seconds: int = 60
|
bm25_refresh_delay_seconds: int = 60
|
||||||
|
protected_phrase_max_candidates_per_book: int = 5000
|
||||||
|
protected_phrase_llm_candidates_per_book: int = 500
|
||||||
|
protected_phrase_confidence_threshold: float = 0.80
|
||||||
|
phrase_hit_boost: float = 0.25
|
||||||
|
phrase_min_tokens: int = 2
|
||||||
|
phrase_max_tokens: int = 5
|
||||||
|
phrase_max_entity_tokens: int = 8
|
||||||
|
phrase_raw_ngram_min_count: int = 2
|
||||||
|
phrase_raw_count_score_threshold: int = 3
|
||||||
|
phrase_raw_count_high_score_threshold: int = 10
|
||||||
|
phrase_chapter_count_score_threshold: int = 2
|
||||||
|
phrase_chapter_count_high_score_threshold: int = 5
|
||||||
|
phrase_target_protected_per_book: int = 100
|
||||||
|
phrase_default_allow_nested: bool = False
|
||||||
|
phrase_default_suppress_children: bool = True
|
||||||
|
|
||||||
@field_validator("library_paths", mode="before")
|
@field_validator("library_paths", mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
tokens = [
|
||||||
|
"a",
|
||||||
|
"an",
|
||||||
|
"and",
|
||||||
|
"any",
|
||||||
|
"as",
|
||||||
|
"at",
|
||||||
|
"be",
|
||||||
|
"because",
|
||||||
|
"but",
|
||||||
|
"by",
|
||||||
|
"can",
|
||||||
|
"could",
|
||||||
|
"do",
|
||||||
|
"for",
|
||||||
|
"from",
|
||||||
|
"have",
|
||||||
|
"if",
|
||||||
|
"of",
|
||||||
|
"or",
|
||||||
|
"some",
|
||||||
|
"than",
|
||||||
|
"the",
|
||||||
|
"these",
|
||||||
|
"this",
|
||||||
|
"to",
|
||||||
|
"will",
|
||||||
|
"with",
|
||||||
|
"would",
|
||||||
|
]
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
tokens = [
|
||||||
|
"a",
|
||||||
|
"an",
|
||||||
|
"the",
|
||||||
|
]
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
phrases = [
|
||||||
|
"ended up",
|
||||||
|
"had a",
|
||||||
|
"across the",
|
||||||
|
"anyone in",
|
||||||
|
"are you",
|
||||||
|
"around him",
|
||||||
|
"around the",
|
||||||
|
"as much",
|
||||||
|
"as soon",
|
||||||
|
"before the",
|
||||||
|
"behind him",
|
||||||
|
"between the",
|
||||||
|
"did you",
|
||||||
|
"end up",
|
||||||
|
"he asked",
|
||||||
|
"he concluded",
|
||||||
|
"he continued",
|
||||||
|
"he couldn't",
|
||||||
|
"he did",
|
||||||
|
"he didn't",
|
||||||
|
"he felt",
|
||||||
|
"he had",
|
||||||
|
"he hadn't",
|
||||||
|
"he knew",
|
||||||
|
"he noted",
|
||||||
|
"he pointed",
|
||||||
|
"he realized",
|
||||||
|
"he replied",
|
||||||
|
"he said",
|
||||||
|
"he saw",
|
||||||
|
"he tapped",
|
||||||
|
"he told",
|
||||||
|
"he was",
|
||||||
|
"he wasn't",
|
||||||
|
"his body",
|
||||||
|
"his chair",
|
||||||
|
"his feet",
|
||||||
|
"his hands",
|
||||||
|
"his head",
|
||||||
|
"his office",
|
||||||
|
"his own",
|
||||||
|
"his pc",
|
||||||
|
"his power",
|
||||||
|
"his shield",
|
||||||
|
"his sight",
|
||||||
|
"his voice",
|
||||||
|
"his wrist",
|
||||||
|
"how many",
|
||||||
|
"i am",
|
||||||
|
"i don't",
|
||||||
|
"i was",
|
||||||
|
"i wouldn't",
|
||||||
|
"i'm not",
|
||||||
|
"is in",
|
||||||
|
"is not",
|
||||||
|
"is that",
|
||||||
|
"is the",
|
||||||
|
"it had",
|
||||||
|
"it had",
|
||||||
|
"it was",
|
||||||
|
"it wasn't",
|
||||||
|
"it wasn't",
|
||||||
|
"of course",
|
||||||
|
"of force",
|
||||||
|
"of magic",
|
||||||
|
"of marines",
|
||||||
|
"of power",
|
||||||
|
"of those",
|
||||||
|
"old man",
|
||||||
|
"older man",
|
||||||
|
"set up",
|
||||||
|
"she admitted",
|
||||||
|
"she asked",
|
||||||
|
"she had",
|
||||||
|
"she replied",
|
||||||
|
"she said",
|
||||||
|
"she snapped",
|
||||||
|
"she told",
|
||||||
|
"she was",
|
||||||
|
"she'd been",
|
||||||
|
"shook his",
|
||||||
|
"sure he",
|
||||||
|
"tell you",
|
||||||
|
"that had",
|
||||||
|
"that is",
|
||||||
|
"that was",
|
||||||
|
"there are",
|
||||||
|
"there was",
|
||||||
|
"there were",
|
||||||
|
"they are",
|
||||||
|
"they had",
|
||||||
|
"they were",
|
||||||
|
"they weren't",
|
||||||
|
"this is",
|
||||||
|
"this place",
|
||||||
|
"though he",
|
||||||
|
"through his",
|
||||||
|
"through the",
|
||||||
|
"to find",
|
||||||
|
"to keep",
|
||||||
|
"to stay",
|
||||||
|
"to stop",
|
||||||
|
"to tell",
|
||||||
|
"to try",
|
||||||
|
"told her",
|
||||||
|
"told him",
|
||||||
|
"under his",
|
||||||
|
"was a",
|
||||||
|
"was enough",
|
||||||
|
"was going",
|
||||||
|
"was in",
|
||||||
|
"was no",
|
||||||
|
"was not",
|
||||||
|
"was now",
|
||||||
|
"was on",
|
||||||
|
"was one",
|
||||||
|
"was only",
|
||||||
|
"was still",
|
||||||
|
"was that",
|
||||||
|
"was the",
|
||||||
|
"was there",
|
||||||
|
"were in",
|
||||||
|
"what had",
|
||||||
|
"what happened",
|
||||||
|
"what was",
|
||||||
|
"where the",
|
||||||
|
"while i",
|
||||||
|
"you are",
|
||||||
|
"you can't",
|
||||||
|
"you don't",
|
||||||
|
"you need",
|
||||||
|
"you were",
|
||||||
|
]
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
|||||||
|
words = [
|
||||||
|
"the",
|
||||||
|
"be",
|
||||||
|
"to",
|
||||||
|
"of",
|
||||||
|
"and",
|
||||||
|
"a",
|
||||||
|
"in",
|
||||||
|
"that",
|
||||||
|
"have",
|
||||||
|
"I",
|
||||||
|
"it",
|
||||||
|
"for",
|
||||||
|
"not",
|
||||||
|
"on",
|
||||||
|
"with",
|
||||||
|
"he",
|
||||||
|
"as",
|
||||||
|
"you",
|
||||||
|
"do",
|
||||||
|
"at",
|
||||||
|
"this",
|
||||||
|
"but",
|
||||||
|
"his",
|
||||||
|
"by",
|
||||||
|
"from",
|
||||||
|
"they",
|
||||||
|
"we",
|
||||||
|
"say",
|
||||||
|
"her",
|
||||||
|
"she",
|
||||||
|
"or",
|
||||||
|
"an",
|
||||||
|
"will",
|
||||||
|
"my",
|
||||||
|
"one",
|
||||||
|
"all",
|
||||||
|
"would",
|
||||||
|
"there",
|
||||||
|
"their",
|
||||||
|
"what",
|
||||||
|
"so",
|
||||||
|
"up",
|
||||||
|
"out",
|
||||||
|
"if",
|
||||||
|
"about",
|
||||||
|
"who",
|
||||||
|
"get",
|
||||||
|
"which",
|
||||||
|
"go",
|
||||||
|
"me",
|
||||||
|
"when",
|
||||||
|
"make",
|
||||||
|
"can",
|
||||||
|
"like",
|
||||||
|
"time",
|
||||||
|
"no",
|
||||||
|
"just",
|
||||||
|
"him",
|
||||||
|
"know",
|
||||||
|
"take",
|
||||||
|
"people",
|
||||||
|
"into",
|
||||||
|
"year",
|
||||||
|
"your",
|
||||||
|
"good",
|
||||||
|
"some",
|
||||||
|
"could",
|
||||||
|
"them",
|
||||||
|
"see",
|
||||||
|
"other",
|
||||||
|
"than",
|
||||||
|
"then",
|
||||||
|
"now",
|
||||||
|
"look",
|
||||||
|
"only",
|
||||||
|
"come",
|
||||||
|
"its",
|
||||||
|
"over",
|
||||||
|
"think",
|
||||||
|
"also",
|
||||||
|
"back",
|
||||||
|
"after",
|
||||||
|
"use",
|
||||||
|
"two",
|
||||||
|
"how",
|
||||||
|
"our",
|
||||||
|
"work",
|
||||||
|
"first",
|
||||||
|
"well",
|
||||||
|
"way",
|
||||||
|
"even",
|
||||||
|
"new",
|
||||||
|
"want",
|
||||||
|
"because",
|
||||||
|
"any",
|
||||||
|
"these",
|
||||||
|
"give",
|
||||||
|
"day",
|
||||||
|
"most",
|
||||||
|
"us",
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user