feat(query-analyzer): configurable dateparser locale detection - #3154
Merged
nicoloboschi merged 2 commits intoAug 5, 2026
Merged
Conversation
nicoloboschi
requested changes
Aug 3, 2026
nicoloboschi
left a comment
Collaborator
There was a problem hiding this comment.
please ensure the doc page configuration.md contains this new config, thanks
Contributor
Author
|
Added the entry to |
nicoloboschi
approved these changes
Aug 4, 2026
Collaborator
|
@yufanw03 please rebase |
search_dates() runs auto-detection across 200+ locales on every recall. This costs 62 ms P50 on the recall critical path, and misdetects English queries as other locales: "May 23, 2023" parses to 2023-11-23 after the detector picks 'bas' (Basaa), where May maps to November. Adds an optional languages restriction to DateparserQueryAnalyzer, wired through HINDSIGHT_API_QUERY_ANALYZER_LANGUAGES. Default stays None (full auto-detection), since restricting degrades explicit dates in unlisted locales to a wrong date rather than to no constraint.
yufanw03
force-pushed
the
feat/query-analyzer-languages
branch
from
August 5, 2026 03:24
cc526d7 to
66bc061
Compare
Contributor
Author
|
Rebased onto latest main. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
DateparserQueryAnalyzercallssearch_dates()without alanguagesargument (query_analyzer.py:253), so dateparser runs auto-detection across 200+ locales on every query. Two consequences: latency, as temporal analysis becomes the dominant CPU cost on the recall critical path; and locale misdetection, where English queries are identified as another language and yield a non-null but incorrect temporal constraint.This adds an optional language restriction, defaulting to
None(current auto-detection).1. Latency
The call sits on the recall critical path via
extract_temporal_constraint(retrieval.py:743) insideretrieve_all_fact_types_parallel, as synchronous CPU work. The class docstring states~10-50ms per query(query_analyzer.py:189). Measured over 300locomo10.jsonquestions:languages=["en"]2. Locale misdetection
FullTextLanguageDetectoridentifies this English query asbas(Basaa, a Bantu language of Cameroon), whose month table mapsMayto November. The first match,'Jon', is correctly rejected by the scoring from #2772 — that mechanism works as intended; the problem is the second match.Output is byte-identical on dateparser 1.2.2 (the pinned version) and 1.4.1 (shipped in the
0.8.4image), and stable across 5 consecutive runs. Testing the same query against each of 44 locales individually, none produces November:en/es/tr/tlgive the correct 2023-05-23, and the remaining 40 degrade to the fragment'23, 2023'→ 2023-07-23.Three failure shapes:
["en"]…on May 23, 2023?'May 23, 2023'→ 2023-11-23…on 31 October, 2022?'on 31'→ 2026-07-31…got her at age 10?'10'→ 2025-10-31NoneIn the second row,
'on 31'carries no month or year, soRELATIVE_BASEfills both in from the current date — landing nearly four years off the date written in the query.These constraints are non-null but wrong, the case #2768 identified as worse than no constraint at all. This is complementary to the scoring in #2772 rather than overlapping with it: scoring ranks candidates by the date signal they carry, but the problem here is the candidate set itself.
'May 23, 2023'scores 150, the highest of its candidates, and'on 31'scores 100 on the digit alone; both clear any reasonable threshold.Why the default stays
NoneRestricting languages degrades explicit dates in unlisted locales, and degrades them to a wrong date rather than to
None:["en"]el 3 de junio de 2023le 3 juin 2023il 3 giugno 2023em 3 de junho de 2023extract_periodcovers fixed phrases in these locales (ayer,hier,letzte woche) but not explicit dates, so those necessarily reachsearch_dates. German and Chinese are unchanged. Chinese is handled byextract_chinese_period: of 32 Chinese temporal expressions tested, 23 resolve on that path — including Chinese-numeral dates such as五月三日and二零二三年六月三日— without reachingsearch_dates.["en"]and["en","zh"]produce identical results across all 300 English queries.Locale coverage is limited to the 8 languages tabulated above; among non-Latin scripts, only Chinese, Japanese, and Russian were checked.
Changes
query_analyzer.py:__init__takeslanguages: list[str] | None = None. Adds_search_kwargs()soanalyze()and the warm-up call inload()use the same locale set — otherwise the warm-up is wasted and part of dateparser's lazy-load cost lands on the first real query. Withlanguages=Noneit returns an empty dict, byte-identical to the previous behavior.config.py: addsHINDSIGHT_API_QUERY_ANALYZER_LANGUAGESand thequery_analyzer_languagesfield, comma-separated. Named following the scoping convention from feat(bm25): configurable native language + opt-in pgroonga backend #1538 (HINDSIGHT_API_BM25_LANGUAGE→..._TEXT_SEARCH_EXTENSION_NATIVE_LANGUAGE). No value validation: this never reaches SQL, and an invalid locale code surfaces as a dateparser error. Happy to add startup validation if you'd prefer to fail early.memory_engine.py: passeslanguages=config.query_analyzer_languagesat construction.Testing
tests/test_query_analyzer.pyadds 4 cases: the default passes nolanguages, an explicit list reachessearch_datesunchanged,load()'s warm-up uses the same locale set, and a regression guard thaton 31 October, 2022resolves to 2022-10-31. The file is at 426 passed on dateparser 1.2.2.Env var parsing: unset /
""/",,"→None;"en"→["en"];"en,zh"→["en","zh"];" EN , ZH "→["en","zh"].The latency benchmark runs 300
locomo10.jsonquestions (random.seed(42),reference_datepinned to 2026-07-31), taking the minimum of 3 runs per query to filter scheduling jitter, fully offline with no service or network involved. Environment: Apple Silicon MacBook Pro / Python 3.11.15 / dateparser 1.2.2.Arm order was swapped and re-measured to rule out warm-up bias; mean holds:
autofirst gives 68.19 / 0.25 ms,enfirst gives 0.25 / 68.33 ms. In this sampleextract_periodshort-circuits 16 queries and the other 284 reachsearch_dates.Correctness was enumerated over all 1,986 questions rather than sampled, giving 17 differences: 13 where auto-detect is wrong (1 locale month misread, 9 fragments, 3 non-date numbers), 3 where the restriction adds a correct constraint (
next month,next year×2), and 1 where it adds a questionable one (half an hour→'an hour'→ 2026-07-31, where auto-detect returnsNone; this is a behavior change introduced here and I have not evaluated it further). The 9 fragment cases:["en"]…on 31 October, 2022?×2'on 31'→ 2026-07-31…community on 7 July, 2023?'on 7'→ 2026-07-31…help with on 13 March, 2023?'on 13'→ 2026-07-13…Caroline on October 13, 2023?'13, 2023'→ 2023-07-13…Nate on February 7, 2022?'7, 2022'→ 2022-07-31…goodbye to on 3 June, 2023?'2023'→ 2023-07-31…evening of 7 July, 2023?'2023'→ 2023-07-31…subjects on 9 February, 2023?'2023'→ 2023-07-31Related
#3140 (open) also reduces the cost of this function, but by bounding query length — orthogonal to this change. Prior changes to this file (#893, #2772, #2791, #2767) do not touch locale selection.