ummaya 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/prompts/manifest.yaml +2 -2
- package/prompts/session_guidance_v1.md +3 -1
- package/prompts/system_v1.md +8 -7
- package/pyproject.toml +2 -7
- package/src/ummaya/context/builder.py +17 -11
- package/src/ummaya/engine/engine.py +27 -7
- package/src/ummaya/engine/query.py +20 -0
- package/src/ummaya/evidence/__init__.py +25 -0
- package/src/ummaya/evidence/__main__.py +7 -0
- package/src/ummaya/evidence/models.py +58 -0
- package/src/ummaya/evidence/runner.py +308 -0
- package/src/ummaya/evidence/task_registry.py +264 -0
- package/src/ummaya/ipc/frame_schema.py +47 -0
- package/src/ummaya/ipc/stdio.py +1349 -90
- package/src/ummaya/llm/client.py +132 -56
- package/src/ummaya/llm/reasoning.py +84 -0
- package/src/ummaya/tools/discovery_bridge.py +17 -1
- package/src/ummaya/tools/executor.py +32 -12
- package/src/ummaya/tools/geocoding/kakao_client.py +1 -2
- package/src/ummaya/tools/kma/apihub_catalog.py +984 -1
- package/src/ummaya/tools/kma/apihub_structured_adapter.py +86 -6
- package/src/ummaya/tools/kma/apihub_url_adapter.py +593 -0
- package/src/ummaya/tools/kma/apihub_url_catalog.py +296 -0
- package/src/ummaya/tools/location_adapters.py +8 -6
- package/src/ummaya/tools/manifest_metadata.py +16 -3
- package/src/ummaya/tools/mvp_surface.py +2 -2
- package/src/ummaya/tools/nmc/emergency_search.py +8 -6
- package/src/ummaya/tools/register_all.py +9 -0
- package/src/ummaya/tools/resolve_location.py +4 -4
- package/src/ummaya/tools/search.py +664 -18
- package/src/ummaya/tools/verified_data_go_kr/_manifest.py +115 -25
- package/src/ummaya/tools/verified_data_go_kr/airkorea_air_quality.py +109 -4
- package/src/ummaya/tools/verified_data_go_kr/nmc_aed_site.py +108 -2
- package/src/ummaya/tools/verified_data_go_kr/pps_bid_public_info.py +174 -9
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_arrival.py +66 -3
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_location.py +12 -2
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_route.py +8 -2
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_route_station.py +114 -0
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_station.py +14 -3
- package/src/ummaya/tools/verify_canonical_map.py +21 -0
- package/tui/package.json +1 -2
- package/tui/src/QueryEngine.ts +4 -0
- package/tui/src/cli/handlers/auth.ts +1 -1
- package/tui/src/cli/handlers/mcp.tsx +3 -3
- package/tui/src/cli/print.ts +69 -18
- package/tui/src/cli/update.ts +13 -13
- package/tui/src/commands/copy/index.ts +1 -1
- package/tui/src/commands/cost/cost.ts +2 -2
- package/tui/src/commands/init-verifiers.ts +5 -5
- package/tui/src/commands/init.ts +30 -30
- package/tui/src/commands/insights.ts +43 -43
- package/tui/src/commands/install-github-app/install-github-app.tsx +2 -2
- package/tui/src/commands/install-github-app/setupGitHubActions.ts +3 -3
- package/tui/src/commands/install.tsx +5 -5
- package/tui/src/commands/mcp/addCommand.ts +5 -5
- package/tui/src/commands/mcp/xaaIdpCommand.ts +2 -2
- package/tui/src/commands/plugin/ManageMarketplaces.tsx +2 -2
- package/tui/src/commands/reasoning/index.ts +13 -0
- package/tui/src/commands/reasoning/reasoning.tsx +177 -0
- package/tui/src/commands/thinkback/thinkback.tsx +3 -3
- package/tui/src/commands.ts +2 -0
- package/tui/src/components/Messages.tsx +2 -1
- package/tui/src/components/Spinner.tsx +2 -2
- package/tui/src/components/design-system/LoadingState.tsx +2 -2
- package/tui/src/ipc/codec.ts +26 -0
- package/tui/src/ipc/frames.generated.ts +398 -303
- package/tui/src/ipc/llmClient.ts +130 -51
- package/tui/src/ipc/llmTypes.ts +16 -1
- package/tui/src/ipc/schema/frame.schema.json +1 -3475
- package/tui/src/main.tsx +3 -0
- package/tui/src/query.ts +467 -2
- package/tui/src/screens/REPL.tsx +3 -3
- package/tui/src/services/api/claude.ts +54 -25
- package/tui/src/services/api/client.ts +33 -12
- package/tui/src/services/api/ummaya.ts +70 -16
- package/tui/src/skills/bundled/stuck.ts +12 -12
- package/tui/src/state/AppStateStore.ts +7 -0
- package/tui/src/tools/AdapterTool/AdapterTool.ts +590 -7
- package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +43 -17
- package/tui/src/tools/LookupPrimitive/prompt.ts +7 -6
- package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +40 -19
- package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +25 -9
- package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +25 -9
- package/tui/src/tools/_shared/citizenUserText.ts +49 -0
- package/tui/src/tools/_shared/directPublicDataGuard.ts +362 -0
- package/tui/src/tools/_shared/kmaAnalysisGuard.ts +197 -0
- package/tui/src/tools/_shared/kmaAviationGuard.ts +70 -0
- package/tui/src/tools/_shared/locationInputRepair.ts +112 -0
- package/tui/src/tools/_shared/nmcAedGuard.ts +234 -0
- package/tui/src/tools/_shared/protectedCheckGuard.ts +207 -0
- package/tui/src/tools/_shared/rootPrimitiveInput.ts +67 -0
- package/tui/src/tools/_shared/textToolCallGuard.ts +91 -0
- package/tui/src/tools/_shared/toolChoiceRepair.ts +866 -0
- package/tui/src/utils/attachments.ts +1 -1
- package/tui/src/utils/kExaoneReasoning.ts +138 -0
- package/tui/src/utils/messages.ts +1 -0
- package/tui/src/utils/multiToolLayout.ts +13 -0
- package/tui/src/utils/processUserInput/processSlashCommand.tsx +2 -2
- package/tui/src/utils/processUserInput/processUserInput.ts +26 -0
- package/tui/src/utils/settings/applySettingsChange.ts +4 -0
- package/tui/src/utils/settings/types.ts +9 -3
- package/tui/src/utils/stats.ts +1 -1
- package/uv.lock +1 -15
- package/assets/copilot-gate-logo.svg +0 -58
- package/assets/govon-logo.svg +0 -40
- package/src/ummaya/eval/__init__.py +0 -5
- package/src/ummaya/eval/retrieval.py +0 -713
- package/tui/src/utils/messageStream.ts +0 -186
|
@@ -40,6 +40,13 @@ _ADMIN_LOCATION_RE = re.compile(
|
|
|
40
40
|
r"(?:[가-힣]{2,}(?:시|군|구|동|읍|면)\b|[가-힣0-9]{2,}(?<!으)(?:로|길)\b)"
|
|
41
41
|
)
|
|
42
42
|
_EMERGENCY_RE = re.compile(r"(응급|응급실|응급의료|\bemergency\b|\ber\b)", re.IGNORECASE)
|
|
43
|
+
_IMPLICIT_EMERGENCY_RE = re.compile(
|
|
44
|
+
r"(사람이\s*(?:쓰러|쓰러졌|쓰러져)|의식(?:을)?\s*(?:잃|없)|"
|
|
45
|
+
r"갑자기\s*쓰러|쓰러진\s*사람|위급|심정지|호흡(?:이)?\s*없|"
|
|
46
|
+
r"collapsed|unconscious|cardiac\s*arrest)",
|
|
47
|
+
re.IGNORECASE,
|
|
48
|
+
)
|
|
49
|
+
_AED_RE = re.compile(r"(\bAED\b|자동심장충격기|자동제세동기|제세동기)", re.IGNORECASE)
|
|
43
50
|
_TRAFFIC_HAZARD_RE = re.compile(
|
|
44
51
|
r"(교통사고|사고\s*위험|사고다발|위험\s*(?:구간|도로|지점)|어린이보호구역|보호구역|"
|
|
45
52
|
r"도로\s*구간|accident|hazard|hotspot)",
|
|
@@ -50,6 +57,604 @@ _TRAFFIC_HAZARD_SPECIFIC_RE = re.compile(
|
|
|
50
57
|
r"도로\s*구간|행정동코드|adm_cd|hazard|hotspot)",
|
|
51
58
|
re.IGNORECASE,
|
|
52
59
|
)
|
|
60
|
+
_KMA_ANALYSIS_CHART_RE = re.compile(
|
|
61
|
+
r"(분석일기도|지상일기도|보조일기도|WthrChartInfoService|getSurfaceChart|"
|
|
62
|
+
r"getAuxillaryChart|synoptic\s+chart)",
|
|
63
|
+
re.IGNORECASE,
|
|
64
|
+
)
|
|
65
|
+
_KMA_GIMHAE_AIRPORT_RE = re.compile(r"(김해(?:공항)?|Gimhae|RKPK)", re.IGNORECASE)
|
|
66
|
+
_KMA_GIMPO_AIRPORT_RE = re.compile(r"(김포(?:공항)?|Gimpo|RKSS)", re.IGNORECASE)
|
|
67
|
+
_KMA_AIRPORT_NAME_RE = re.compile(
|
|
68
|
+
r"(공항|\bairport\b|\bRK[A-Z]{2}\b|station\s*\d{2,3})",
|
|
69
|
+
re.IGNORECASE,
|
|
70
|
+
)
|
|
71
|
+
_KMA_AIRPORT_AVIATION_RE = re.compile(
|
|
72
|
+
r"(AMOS|METAR|SPECI|RVR|항공기상|공항기상|활주로|runway|aviation|"
|
|
73
|
+
r"비행기|항공편|비행편|이륙|착륙|결항|지연|운항|뜰\s*만|뜨나|뜰\s*수|"
|
|
74
|
+
r"flight|take\s*off|landing|delay|cancel)",
|
|
75
|
+
re.IGNORECASE,
|
|
76
|
+
)
|
|
77
|
+
_KMA_EXPLICIT_METAR_RE = re.compile(r"(\bMETAR\b|\bSPECI\b|해독자료)", re.IGNORECASE)
|
|
78
|
+
_KMA_RUNWAY_AREA_RE = re.compile(
|
|
79
|
+
r"(AMOS|활주로|RVR|runway|시정|visibility|공항기상관측|매분)",
|
|
80
|
+
re.IGNORECASE,
|
|
81
|
+
)
|
|
82
|
+
_KMA_ANALYSIS_DATA_RE = re.compile(
|
|
83
|
+
r"(분석자료|이미\s*분석|고해상도\s*격자|객관분석|AWS\s*객관|지도\s*자료|"
|
|
84
|
+
r"일기도|분석일기도|비구름|바람\s*흐름|날씨\s*흐름|공식\s*기상자료|전국\s*날씨|"
|
|
85
|
+
r"synoptic|weather\s*chart|"
|
|
86
|
+
r"objective\s*analysis|high[-\s]?resolution|grid)",
|
|
87
|
+
re.IGNORECASE,
|
|
88
|
+
)
|
|
89
|
+
_KMA_LIFESTYLE_WEATHER_RE = re.compile(
|
|
90
|
+
r"(날씨|현재\s*기상|실황|관측|예보|기온|습도|풍속|지금\s*비|"
|
|
91
|
+
r"비\s*(?:와|오|올|내리)|우산|강수|소나기|산책|퇴근|"
|
|
92
|
+
r"current\s+weather|forecast|rain|umbrella|precipitation|temperature)",
|
|
93
|
+
re.IGNORECASE,
|
|
94
|
+
)
|
|
95
|
+
_HIRA_MEDICAL_DETAIL_RE = re.compile(
|
|
96
|
+
r"((병원|의료기관|의원).*(상세|진료과|진료과목|진료시간|주차)|"
|
|
97
|
+
r"(상세|진료시간|주차|응급실).*(병원|의료기관|의원)|ykiho|detail)",
|
|
98
|
+
re.IGNORECASE,
|
|
99
|
+
)
|
|
100
|
+
_MOIS_EMERGENCY_CALL_BOX_RE = re.compile(
|
|
101
|
+
r"(안전\s*비상벨|비상벨|긴급\s*신고함|긴급신고함|방범벨|"
|
|
102
|
+
r"emergency\s+call\s+box)",
|
|
103
|
+
re.IGNORECASE,
|
|
104
|
+
)
|
|
105
|
+
_GYERYONG_ASSISTIVE_CHARGER_RE = re.compile(
|
|
106
|
+
r"((전동보장구|전동\s*휠체어|보장구|장애인).*(충전|충전소|충전장소)|"
|
|
107
|
+
r"(충전|충전소|충전장소).*(전동보장구|전동\s*휠체어|보장구|장애인)|"
|
|
108
|
+
r"계룡시?.*(충전소|충전\s*장소))",
|
|
109
|
+
re.IGNORECASE,
|
|
110
|
+
)
|
|
111
|
+
_MOF_OCEAN_WATER_QUALITY_RE = re.compile(
|
|
112
|
+
r"(해양\s*수질|해양수질|수질\s*자동\s*측정|용존산소|\bpH\b|"
|
|
113
|
+
r"water\s+quality|ocean\s+water)",
|
|
114
|
+
re.IGNORECASE,
|
|
115
|
+
)
|
|
116
|
+
_PPS_SHOPPING_RE = re.compile(
|
|
117
|
+
r"(종합\s*쇼핑몰|쇼핑몰|계약\s*물품|물품\s*조회|shopping\s*mall)",
|
|
118
|
+
re.IGNORECASE,
|
|
119
|
+
)
|
|
120
|
+
_PPS_BID_RE = re.compile(
|
|
121
|
+
r"(입찰|나라장터|조달청|\bbid\b|procurement|tender)",
|
|
122
|
+
re.IGNORECASE,
|
|
123
|
+
)
|
|
124
|
+
_KCUE_ACADEMY_INFO_RE = re.compile(
|
|
125
|
+
r"(대학알리미|대학정보공시|학교구분코드|schl[_\s-]?div[_\s-]?cd|KCUE)",
|
|
126
|
+
re.IGNORECASE,
|
|
127
|
+
)
|
|
128
|
+
_KCUE_REGIONAL_FINANCE_RE = re.compile(
|
|
129
|
+
r"(지역별\s*(등록금|재정)|등록금\s*(현황|지역별)?|tuition|finance)",
|
|
130
|
+
re.IGNORECASE,
|
|
131
|
+
)
|
|
132
|
+
_KCUE_REGIONAL_FOREIGN_STUDENT_RE = re.compile(
|
|
133
|
+
r"(외국인\s*유학생|유학생\s*현황|foreign\s+student|international\s+student)",
|
|
134
|
+
re.IGNORECASE,
|
|
135
|
+
)
|
|
136
|
+
_KCUE_TOOL_IDS = frozenset(
|
|
137
|
+
{
|
|
138
|
+
"kcue_finance_regional_tuition",
|
|
139
|
+
"kcue_student_regional_foreign",
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
_KMA_ANALYSIS_MAP_RE = re.compile(
|
|
143
|
+
r"(일기도|분석일기도|지도\s*자료|비구름|바람\s*흐름|날씨\s*흐름|전국\s*날씨|"
|
|
144
|
+
r"synoptic|weather\s*chart)",
|
|
145
|
+
re.IGNORECASE,
|
|
146
|
+
)
|
|
147
|
+
_KMA_ANALYSIS_POINT_RE = re.compile(
|
|
148
|
+
r"(주변|근처|특정지점|좌표|위도|경도|\blat\b|\blon\b|공항\s*주변)",
|
|
149
|
+
re.IGNORECASE,
|
|
150
|
+
)
|
|
151
|
+
_KMA_URL_AIR_TOOL_IDS = frozenset(
|
|
152
|
+
{
|
|
153
|
+
"kma_apihub_url_air_amos_minute",
|
|
154
|
+
"kma_apihub_url_air_metar_decoded",
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
_KMA_ANALYSIS_TOOL_IDS = frozenset(
|
|
158
|
+
{
|
|
159
|
+
"kma_apihub_url_high_resolution_grid_point",
|
|
160
|
+
"kma_apihub_url_aws_objective_analysis_grid",
|
|
161
|
+
"kma_apihub_url_analysis_weather_chart_image",
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
_KMA_LIFESTYLE_WEATHER_TOOL_IDS = frozenset(
|
|
165
|
+
{
|
|
166
|
+
"kma_current_observation",
|
|
167
|
+
"kma_ultra_short_term_forecast",
|
|
168
|
+
"kma_short_term_forecast",
|
|
169
|
+
}
|
|
170
|
+
)
|
|
171
|
+
_LOCATION_TOOL_IDS = frozenset(
|
|
172
|
+
{
|
|
173
|
+
"locate",
|
|
174
|
+
"kakao_address_search",
|
|
175
|
+
"kakao_keyword_search",
|
|
176
|
+
"kakao_coord_to_region",
|
|
177
|
+
"juso_adm_cd_lookup",
|
|
178
|
+
"sgis_adm_cd_lookup",
|
|
179
|
+
}
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _is_kma_analysis_point_query(query: str, *, is_analysis_map_query: bool) -> bool:
|
|
184
|
+
return bool(_KMA_ANALYSIS_POINT_RE.search(query)) and not is_analysis_map_query
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _is_airport_aviation_query(query: str) -> bool:
|
|
188
|
+
return bool(
|
|
189
|
+
(
|
|
190
|
+
_KMA_AIRPORT_NAME_RE.search(query)
|
|
191
|
+
or _KMA_GIMHAE_AIRPORT_RE.search(query)
|
|
192
|
+
or _KMA_GIMPO_AIRPORT_RE.search(query)
|
|
193
|
+
)
|
|
194
|
+
and _KMA_AIRPORT_AVIATION_RE.search(query)
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _is_lifestyle_weather_query(query: str, *, is_airport_aviation_query: bool) -> bool:
|
|
199
|
+
return bool(
|
|
200
|
+
_KMA_LIFESTYLE_WEATHER_RE.search(query)
|
|
201
|
+
and not is_airport_aviation_query
|
|
202
|
+
and not _is_emergency_chain_query(query)
|
|
203
|
+
and not _KMA_ANALYSIS_DATA_RE.search(query)
|
|
204
|
+
and not _TRAFFIC_HAZARD_RE.search(query)
|
|
205
|
+
and not _MOF_OCEAN_WATER_QUALITY_RE.search(query)
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _is_pps_bid_query(query: str) -> bool:
|
|
210
|
+
return bool(_PPS_BID_RE.search(query) and not _PPS_SHOPPING_RE.search(query))
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _is_kcue_regional_query(query: str) -> bool:
|
|
214
|
+
has_kcue_anchor = bool(_KCUE_ACADEMY_INFO_RE.search(query)) or (
|
|
215
|
+
bool(re.search(r"대학(?!병원)", query)) and "공식" in query
|
|
216
|
+
)
|
|
217
|
+
if not has_kcue_anchor:
|
|
218
|
+
return False
|
|
219
|
+
return bool(
|
|
220
|
+
_KCUE_REGIONAL_FINANCE_RE.search(query) or _KCUE_REGIONAL_FOREIGN_STUDENT_RE.search(query)
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def _is_emergency_chain_query(query: str) -> bool:
|
|
225
|
+
if _MOIS_EMERGENCY_CALL_BOX_RE.search(query):
|
|
226
|
+
return False
|
|
227
|
+
return bool(_IMPLICIT_EMERGENCY_RE.search(query) or _EMERGENCY_RE.search(query))
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _filter_kma_analysis_scores(
|
|
231
|
+
scored: list[tuple[str, float]],
|
|
232
|
+
*,
|
|
233
|
+
is_analysis_map_query: bool,
|
|
234
|
+
is_analysis_point_query: bool,
|
|
235
|
+
prefer_poi_location: bool,
|
|
236
|
+
) -> list[tuple[str, float]]:
|
|
237
|
+
chart_boost = 900.0 if is_analysis_map_query else 150.0
|
|
238
|
+
if is_analysis_point_query and not is_analysis_map_query:
|
|
239
|
+
chart_boost = -20.0
|
|
240
|
+
analysis_boosts = {
|
|
241
|
+
"kma_apihub_url_analysis_weather_chart_image": chart_boost,
|
|
242
|
+
"kma_apihub_url_high_resolution_grid_point": (900.0 if is_analysis_point_query else 450.0),
|
|
243
|
+
"kma_apihub_url_aws_objective_analysis_grid": (800.0 if is_analysis_point_query else 400.0),
|
|
244
|
+
}
|
|
245
|
+
allowed_location_ids = _LOCATION_TOOL_IDS if is_analysis_point_query else frozenset()
|
|
246
|
+
adjusted: list[tuple[str, float]] = []
|
|
247
|
+
for tool_id, score in scored:
|
|
248
|
+
if tool_id in _KMA_ANALYSIS_TOOL_IDS:
|
|
249
|
+
adjusted.append((tool_id, score + analysis_boosts.get(tool_id, 0.0)))
|
|
250
|
+
continue
|
|
251
|
+
if tool_id in allowed_location_ids:
|
|
252
|
+
location_score = max(1.0, score - 10.0)
|
|
253
|
+
if prefer_poi_location and tool_id == "kakao_keyword_search":
|
|
254
|
+
location_score += 30.0
|
|
255
|
+
elif prefer_poi_location and tool_id == "kakao_address_search":
|
|
256
|
+
location_score = max(1.0, location_score - 15.0)
|
|
257
|
+
adjusted.append((tool_id, location_score))
|
|
258
|
+
return adjusted
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _kma_lifestyle_weather_additions() -> list[str]:
|
|
262
|
+
return [
|
|
263
|
+
"기상청",
|
|
264
|
+
"KMA",
|
|
265
|
+
"현재날씨",
|
|
266
|
+
"초단기실황",
|
|
267
|
+
"초단기예보",
|
|
268
|
+
"단기예보",
|
|
269
|
+
"강수",
|
|
270
|
+
"우산",
|
|
271
|
+
"nx",
|
|
272
|
+
"ny",
|
|
273
|
+
"base_date",
|
|
274
|
+
"base_time",
|
|
275
|
+
"current",
|
|
276
|
+
"observation",
|
|
277
|
+
"forecast",
|
|
278
|
+
"precipitation",
|
|
279
|
+
]
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _airport_aviation_additions(query: str) -> list[str]:
|
|
283
|
+
additions = [
|
|
284
|
+
"METAR",
|
|
285
|
+
"SPECI",
|
|
286
|
+
"AMOS",
|
|
287
|
+
"항공기상",
|
|
288
|
+
"공항기상",
|
|
289
|
+
"항공",
|
|
290
|
+
"비행기",
|
|
291
|
+
"항공편",
|
|
292
|
+
"운항",
|
|
293
|
+
"이륙",
|
|
294
|
+
"시정",
|
|
295
|
+
"RVR",
|
|
296
|
+
"wind",
|
|
297
|
+
"visibility",
|
|
298
|
+
]
|
|
299
|
+
if _KMA_GIMPO_AIRPORT_RE.search(query) and _KMA_RUNWAY_AREA_RE.search(query):
|
|
300
|
+
additions.extend(["AMOS", "공항기상관측", "매분자료", "활주로", "김포공항", "stn110"])
|
|
301
|
+
return additions
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def _kma_analysis_data_additions() -> list[str]:
|
|
305
|
+
return [
|
|
306
|
+
"분석자료",
|
|
307
|
+
"고해상도",
|
|
308
|
+
"격자자료",
|
|
309
|
+
"객관분석",
|
|
310
|
+
"AWS",
|
|
311
|
+
"분석일기도",
|
|
312
|
+
"지도",
|
|
313
|
+
"비구름",
|
|
314
|
+
"바람흐름",
|
|
315
|
+
"objective",
|
|
316
|
+
"analysis",
|
|
317
|
+
"grid",
|
|
318
|
+
"chart",
|
|
319
|
+
]
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _traffic_hazard_additions() -> list[str]:
|
|
323
|
+
return [
|
|
324
|
+
"교통사고",
|
|
325
|
+
"사고다발구역",
|
|
326
|
+
"위험지점",
|
|
327
|
+
"도로위험구역",
|
|
328
|
+
"어린이보호구역",
|
|
329
|
+
"행정동코드",
|
|
330
|
+
"KOROAD",
|
|
331
|
+
"accident",
|
|
332
|
+
"hazard",
|
|
333
|
+
]
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def _emergency_chain_additions(query: str) -> list[str]:
|
|
337
|
+
if not _is_emergency_chain_query(query):
|
|
338
|
+
return []
|
|
339
|
+
additions = [
|
|
340
|
+
"응급실",
|
|
341
|
+
"응급의료",
|
|
342
|
+
"자동심장충격기",
|
|
343
|
+
"AED",
|
|
344
|
+
"국립중앙의료원",
|
|
345
|
+
"NMC",
|
|
346
|
+
"nearby",
|
|
347
|
+
"emergency",
|
|
348
|
+
"hospital",
|
|
349
|
+
]
|
|
350
|
+
if _POI_LOCATION_RE.search(query):
|
|
351
|
+
additions.extend(["장소", "키워드", "POI", "랜드마크", "역", "keyword"])
|
|
352
|
+
return additions
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def _public_safety_location_additions(query: str) -> list[str]:
|
|
356
|
+
additions: list[str] = []
|
|
357
|
+
if _MOIS_EMERGENCY_CALL_BOX_RE.search(query):
|
|
358
|
+
additions.extend(
|
|
359
|
+
[
|
|
360
|
+
"안전비상벨",
|
|
361
|
+
"비상벨",
|
|
362
|
+
"긴급신고함",
|
|
363
|
+
"방범",
|
|
364
|
+
"행정안전부",
|
|
365
|
+
"MOIS",
|
|
366
|
+
"emergency",
|
|
367
|
+
"call",
|
|
368
|
+
"box",
|
|
369
|
+
]
|
|
370
|
+
)
|
|
371
|
+
if _GYERYONG_ASSISTIVE_CHARGER_RE.search(query):
|
|
372
|
+
additions.extend(
|
|
373
|
+
[
|
|
374
|
+
"계룡시",
|
|
375
|
+
"전동보장구",
|
|
376
|
+
"전동휠체어",
|
|
377
|
+
"장애인",
|
|
378
|
+
"충전소",
|
|
379
|
+
"충전장소",
|
|
380
|
+
"accessibility",
|
|
381
|
+
"charger",
|
|
382
|
+
]
|
|
383
|
+
)
|
|
384
|
+
return additions
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def _ocean_water_quality_additions(query: str) -> list[str]:
|
|
388
|
+
if not _MOF_OCEAN_WATER_QUALITY_RE.search(query):
|
|
389
|
+
return []
|
|
390
|
+
return [
|
|
391
|
+
"해양수산부",
|
|
392
|
+
"해양수질",
|
|
393
|
+
"수질자동측정망",
|
|
394
|
+
"관측소",
|
|
395
|
+
"SEA3003",
|
|
396
|
+
"용존산소",
|
|
397
|
+
"water",
|
|
398
|
+
"quality",
|
|
399
|
+
"ocean",
|
|
400
|
+
]
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def _pps_bid_additions(query: str) -> list[str]:
|
|
404
|
+
if not _is_pps_bid_query(query):
|
|
405
|
+
return []
|
|
406
|
+
return [
|
|
407
|
+
"조달청",
|
|
408
|
+
"나라장터",
|
|
409
|
+
"입찰공고",
|
|
410
|
+
"공사입찰",
|
|
411
|
+
"bidNtceNm",
|
|
412
|
+
"inqryBgnDt",
|
|
413
|
+
"inqryEndDt",
|
|
414
|
+
"PPS",
|
|
415
|
+
"bid",
|
|
416
|
+
"procurement",
|
|
417
|
+
]
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
def _kcue_regional_additions(query: str) -> list[str]:
|
|
421
|
+
if not _is_kcue_regional_query(query):
|
|
422
|
+
return []
|
|
423
|
+
additions = [
|
|
424
|
+
"한국대학교육협의회",
|
|
425
|
+
"대학알리미",
|
|
426
|
+
"대학정보공시",
|
|
427
|
+
"학교구분코드",
|
|
428
|
+
"schlDivCd",
|
|
429
|
+
"지역별통계",
|
|
430
|
+
"KCUE",
|
|
431
|
+
]
|
|
432
|
+
if _KCUE_REGIONAL_FINANCE_RE.search(query):
|
|
433
|
+
additions.extend(["재정현황", "등록금", "FinancesService", "regional tuition"])
|
|
434
|
+
if _KCUE_REGIONAL_FOREIGN_STUDENT_RE.search(query):
|
|
435
|
+
additions.extend(["학생현황", "외국인유학생", "regional foreign student"])
|
|
436
|
+
return additions
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def _health_detail_additions(query: str) -> list[str]:
|
|
440
|
+
if not _HIRA_MEDICAL_DETAIL_RE.search(query):
|
|
441
|
+
return []
|
|
442
|
+
return [
|
|
443
|
+
"의료기관",
|
|
444
|
+
"상세정보",
|
|
445
|
+
"진료과목",
|
|
446
|
+
"진료시간",
|
|
447
|
+
"주차",
|
|
448
|
+
"요양기호",
|
|
449
|
+
"ykiho",
|
|
450
|
+
"HIRA",
|
|
451
|
+
"hospital",
|
|
452
|
+
"detail",
|
|
453
|
+
]
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
def _filter_kma_lifestyle_weather_scores(
|
|
457
|
+
scored: list[tuple[str, float]],
|
|
458
|
+
) -> list[tuple[str, float]]:
|
|
459
|
+
allowed_tool_ids = _KMA_LIFESTYLE_WEATHER_TOOL_IDS | _LOCATION_TOOL_IDS
|
|
460
|
+
if any(tool_id in allowed_tool_ids for tool_id, _ in scored):
|
|
461
|
+
scored = [(tool_id, score) for tool_id, score in scored if tool_id in allowed_tool_ids]
|
|
462
|
+
boosts = {
|
|
463
|
+
"kakao_keyword_search": 1100.0,
|
|
464
|
+
"kakao_address_search": 1000.0,
|
|
465
|
+
"kma_current_observation": 900.0,
|
|
466
|
+
"kma_ultra_short_term_forecast": 800.0,
|
|
467
|
+
"kma_short_term_forecast": 650.0,
|
|
468
|
+
"kakao_coord_to_region": 260.0,
|
|
469
|
+
"juso_adm_cd_lookup": 260.0,
|
|
470
|
+
"sgis_adm_cd_lookup": 260.0,
|
|
471
|
+
}
|
|
472
|
+
return [(tool_id, score + boosts.get(tool_id, 0.0)) for tool_id, score in scored]
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def _filter_public_safety_location_scores(
|
|
476
|
+
query: str, scored: list[tuple[str, float]]
|
|
477
|
+
) -> list[tuple[str, float]]:
|
|
478
|
+
boosts = {}
|
|
479
|
+
if _MOIS_EMERGENCY_CALL_BOX_RE.search(query):
|
|
480
|
+
boosts["mois_emergency_call_box_lookup"] = 1000.0
|
|
481
|
+
if _GYERYONG_ASSISTIVE_CHARGER_RE.search(query):
|
|
482
|
+
boosts["gyeryong_assistive_device_charging_place_locate"] = 1000.0
|
|
483
|
+
if not boosts:
|
|
484
|
+
return scored
|
|
485
|
+
return [(tool_id, score + boosts.get(tool_id, 0.0)) for tool_id, score in scored]
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
def _filter_emergency_chain_scores(
|
|
489
|
+
query: str, scored: list[tuple[str, float]]
|
|
490
|
+
) -> list[tuple[str, float]]:
|
|
491
|
+
if not _is_emergency_chain_query(query):
|
|
492
|
+
return scored
|
|
493
|
+
emergency_tool_ids = {
|
|
494
|
+
"nmc_emergency_search",
|
|
495
|
+
"nmc_aed_site_locate",
|
|
496
|
+
"hira_hospital_search",
|
|
497
|
+
"hira_medical_institution_detail",
|
|
498
|
+
}
|
|
499
|
+
allowed_tool_ids = emergency_tool_ids | _LOCATION_TOOL_IDS
|
|
500
|
+
if any(tool_id in emergency_tool_ids for tool_id, _ in scored):
|
|
501
|
+
scored = [(tool_id, score) for tool_id, score in scored if tool_id in allowed_tool_ids]
|
|
502
|
+
implicit_collapse = bool(_IMPLICIT_EMERGENCY_RE.search(query))
|
|
503
|
+
boosts = {
|
|
504
|
+
"nmc_emergency_search": 1200.0,
|
|
505
|
+
"nmc_aed_site_locate": 1150.0 if implicit_collapse else 950.0,
|
|
506
|
+
"kakao_keyword_search": 1100.0 if implicit_collapse else 900.0,
|
|
507
|
+
"kakao_address_search": 800.0,
|
|
508
|
+
"kakao_coord_to_region": 500.0,
|
|
509
|
+
"juso_adm_cd_lookup": 300.0,
|
|
510
|
+
"sgis_adm_cd_lookup": 300.0,
|
|
511
|
+
"hira_hospital_search": 250.0,
|
|
512
|
+
"hira_medical_institution_detail": 200.0,
|
|
513
|
+
}
|
|
514
|
+
return [(tool_id, score + boosts.get(tool_id, 0.0)) for tool_id, score in scored]
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def _filter_ocean_water_quality_scores(
|
|
518
|
+
query: str, scored: list[tuple[str, float]]
|
|
519
|
+
) -> list[tuple[str, float]]:
|
|
520
|
+
if not _MOF_OCEAN_WATER_QUALITY_RE.search(query):
|
|
521
|
+
return scored
|
|
522
|
+
return [
|
|
523
|
+
(
|
|
524
|
+
tool_id,
|
|
525
|
+
score + (1000.0 if tool_id == "mof_ocean_water_quality_check" else 0.0),
|
|
526
|
+
)
|
|
527
|
+
for tool_id, score in scored
|
|
528
|
+
]
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
def _filter_pps_bid_scores(query: str, scored: list[tuple[str, float]]) -> list[tuple[str, float]]:
|
|
532
|
+
if not _is_pps_bid_query(query):
|
|
533
|
+
return scored
|
|
534
|
+
has_pps_bid = any(tool_id == "pps_bid_public_info" for tool_id, _ in scored)
|
|
535
|
+
if not has_pps_bid:
|
|
536
|
+
return scored
|
|
537
|
+
return [
|
|
538
|
+
(tool_id, score + 1000.0) for tool_id, score in scored if tool_id == "pps_bid_public_info"
|
|
539
|
+
]
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def _filter_kcue_regional_scores(
|
|
543
|
+
query: str, scored: list[tuple[str, float]]
|
|
544
|
+
) -> list[tuple[str, float]]:
|
|
545
|
+
if not _is_kcue_regional_query(query):
|
|
546
|
+
return scored
|
|
547
|
+
has_kcue = any(tool_id in _KCUE_TOOL_IDS for tool_id, _ in scored)
|
|
548
|
+
if not has_kcue:
|
|
549
|
+
return scored
|
|
550
|
+
|
|
551
|
+
prefer_finance = bool(_KCUE_REGIONAL_FINANCE_RE.search(query))
|
|
552
|
+
prefer_foreign_student = bool(_KCUE_REGIONAL_FOREIGN_STUDENT_RE.search(query))
|
|
553
|
+
boosts = {
|
|
554
|
+
"kcue_finance_regional_tuition": 1000.0 if prefer_finance else 700.0,
|
|
555
|
+
"kcue_student_regional_foreign": 1000.0 if prefer_foreign_student else 700.0,
|
|
556
|
+
}
|
|
557
|
+
return [
|
|
558
|
+
(tool_id, score + boosts[tool_id]) for tool_id, score in scored if tool_id in _KCUE_TOOL_IDS
|
|
559
|
+
]
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
def _filter_health_detail_scores(
|
|
563
|
+
query: str, scored: list[tuple[str, float]]
|
|
564
|
+
) -> list[tuple[str, float]]:
|
|
565
|
+
if not _HIRA_MEDICAL_DETAIL_RE.search(query):
|
|
566
|
+
return scored
|
|
567
|
+
return [
|
|
568
|
+
(
|
|
569
|
+
tool_id,
|
|
570
|
+
score + (650.0 if tool_id == "hira_medical_institution_detail" else 0.0),
|
|
571
|
+
)
|
|
572
|
+
for tool_id, score in scored
|
|
573
|
+
]
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
def _filter_initial_special_scores(
|
|
577
|
+
query: str, scored: list[tuple[str, float]]
|
|
578
|
+
) -> list[tuple[str, float]]:
|
|
579
|
+
if _TRAFFIC_HAZARD_SPECIFIC_RE.search(query):
|
|
580
|
+
scored = [
|
|
581
|
+
(tool_id, score) for tool_id, score in scored if tool_id != "koroad_accident_search"
|
|
582
|
+
]
|
|
583
|
+
if _KMA_ANALYSIS_CHART_RE.search(query):
|
|
584
|
+
return [
|
|
585
|
+
(tool_id, score)
|
|
586
|
+
for tool_id, score in scored
|
|
587
|
+
if tool_id == "kma_apihub_url_analysis_weather_chart_image"
|
|
588
|
+
]
|
|
589
|
+
return scored
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
def _filter_kma_aviation_scores(
|
|
593
|
+
query: str, scored: list[tuple[str, float]], *, is_airport_aviation_query: bool
|
|
594
|
+
) -> list[tuple[str, float]]:
|
|
595
|
+
if _KMA_GIMHAE_AIRPORT_RE.search(query) and _KMA_AIRPORT_AVIATION_RE.search(query):
|
|
596
|
+
scored = [
|
|
597
|
+
(tool_id, score)
|
|
598
|
+
for tool_id, score in scored
|
|
599
|
+
if tool_id != "kma_apihub_url_air_amos_minute"
|
|
600
|
+
]
|
|
601
|
+
if (
|
|
602
|
+
_KMA_GIMPO_AIRPORT_RE.search(query)
|
|
603
|
+
and _KMA_RUNWAY_AREA_RE.search(query)
|
|
604
|
+
and _KMA_AIRPORT_AVIATION_RE.search(query)
|
|
605
|
+
):
|
|
606
|
+
scored = [
|
|
607
|
+
(tool_id, score + 500.0 if tool_id == "kma_apihub_url_air_amos_minute" else score)
|
|
608
|
+
for tool_id, score in scored
|
|
609
|
+
]
|
|
610
|
+
if not is_airport_aviation_query:
|
|
611
|
+
return scored
|
|
612
|
+
|
|
613
|
+
has_air_url_candidate = any(tool_id in _KMA_URL_AIR_TOOL_IDS for tool_id, _ in scored)
|
|
614
|
+
if not has_air_url_candidate:
|
|
615
|
+
return scored
|
|
616
|
+
if _KMA_EXPLICIT_METAR_RE.search(query):
|
|
617
|
+
blocked_tool_ids = (
|
|
618
|
+
_LOCATION_TOOL_IDS | _KMA_LIFESTYLE_WEATHER_TOOL_IDS | {"kma_forecast_fetch"}
|
|
619
|
+
)
|
|
620
|
+
scored = [(tool_id, score) for tool_id, score in scored if tool_id not in blocked_tool_ids]
|
|
621
|
+
else:
|
|
622
|
+
scored = [(tool_id, score) for tool_id, score in scored if tool_id in _KMA_URL_AIR_TOOL_IDS]
|
|
623
|
+
prefer_amos = bool(
|
|
624
|
+
_KMA_GIMPO_AIRPORT_RE.search(query)
|
|
625
|
+
and _KMA_RUNWAY_AREA_RE.search(query)
|
|
626
|
+
and not _KMA_GIMHAE_AIRPORT_RE.search(query)
|
|
627
|
+
)
|
|
628
|
+
return [
|
|
629
|
+
(
|
|
630
|
+
tool_id,
|
|
631
|
+
score
|
|
632
|
+
+ (
|
|
633
|
+
800.0
|
|
634
|
+
if tool_id == "kma_apihub_url_air_amos_minute" and prefer_amos
|
|
635
|
+
else 700.0
|
|
636
|
+
if tool_id == "kma_apihub_url_air_metar_decoded"
|
|
637
|
+
else 0.0
|
|
638
|
+
),
|
|
639
|
+
)
|
|
640
|
+
for tool_id, score in scored
|
|
641
|
+
]
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
def _boost_aed_scores(query: str, scored: list[tuple[str, float]]) -> list[tuple[str, float]]:
|
|
645
|
+
if not _AED_RE.search(query):
|
|
646
|
+
return scored
|
|
647
|
+
return [
|
|
648
|
+
(
|
|
649
|
+
tool_id,
|
|
650
|
+
score + 900.0
|
|
651
|
+
if tool_id == "nmc_aed_site_locate"
|
|
652
|
+
else score + 700.0
|
|
653
|
+
if tool_id == "nmc_emergency_search" and _EMERGENCY_RE.search(query)
|
|
654
|
+
else score,
|
|
655
|
+
)
|
|
656
|
+
for tool_id, score in scored
|
|
657
|
+
]
|
|
53
658
|
|
|
54
659
|
|
|
55
660
|
def _expand_query_for_adapter_retrieval(query: str) -> str:
|
|
@@ -63,31 +668,75 @@ def _expand_query_for_adapter_retrieval(query: str) -> str:
|
|
|
63
668
|
visible to the model.
|
|
64
669
|
"""
|
|
65
670
|
additions: list[str] = []
|
|
66
|
-
|
|
671
|
+
is_airport_aviation_query = _is_airport_aviation_query(query)
|
|
672
|
+
if is_airport_aviation_query:
|
|
673
|
+
additions.extend(_airport_aviation_additions(query))
|
|
674
|
+
if _KMA_ANALYSIS_DATA_RE.search(query):
|
|
675
|
+
additions.extend(_kma_analysis_data_additions())
|
|
676
|
+
if _is_lifestyle_weather_query(query, is_airport_aviation_query=is_airport_aviation_query):
|
|
677
|
+
additions.extend(_kma_lifestyle_weather_additions())
|
|
678
|
+
if _POI_LOCATION_RE.search(query) and not is_airport_aviation_query:
|
|
67
679
|
additions.extend(["장소", "키워드", "POI", "랜드마크", "역", "keyword"])
|
|
68
680
|
if _ADMIN_LOCATION_RE.search(query):
|
|
69
681
|
additions.extend(["주소", "행정동", "법정동", "도로명", "지번", "address"])
|
|
70
682
|
if _EMERGENCY_RE.search(query):
|
|
71
683
|
additions.extend(["응급실", "응급의료", "NMC", "emergency"])
|
|
684
|
+
if _AED_RE.search(query):
|
|
685
|
+
additions.extend(["AED", "자동심장충격기", "자동제세동기", "국립중앙의료원"])
|
|
686
|
+
additions.extend(_emergency_chain_additions(query))
|
|
687
|
+
additions.extend(_pps_bid_additions(query))
|
|
688
|
+
additions.extend(_kcue_regional_additions(query))
|
|
689
|
+
additions.extend(_ocean_water_quality_additions(query))
|
|
690
|
+
additions.extend(_health_detail_additions(query))
|
|
691
|
+
additions.extend(_public_safety_location_additions(query))
|
|
72
692
|
if _TRAFFIC_HAZARD_RE.search(query):
|
|
73
|
-
additions.extend(
|
|
74
|
-
[
|
|
75
|
-
"교통사고",
|
|
76
|
-
"사고다발구역",
|
|
77
|
-
"위험지점",
|
|
78
|
-
"도로위험구역",
|
|
79
|
-
"어린이보호구역",
|
|
80
|
-
"행정동코드",
|
|
81
|
-
"KOROAD",
|
|
82
|
-
"accident",
|
|
83
|
-
"hazard",
|
|
84
|
-
]
|
|
85
|
-
)
|
|
693
|
+
additions.extend(_traffic_hazard_additions())
|
|
86
694
|
if not additions:
|
|
87
695
|
return query
|
|
88
696
|
return f"{query} {' '.join(additions)}"
|
|
89
697
|
|
|
90
698
|
|
|
699
|
+
def _filter_special_case_scores(
|
|
700
|
+
query: str, scored: list[tuple[str, float]]
|
|
701
|
+
) -> list[tuple[str, float]]:
|
|
702
|
+
"""Apply deterministic domain disambiguation after backend scoring."""
|
|
703
|
+
is_airport_aviation_query = _is_airport_aviation_query(query)
|
|
704
|
+
is_analysis_query = bool(_KMA_ANALYSIS_DATA_RE.search(query))
|
|
705
|
+
is_analysis_map_query = bool(_KMA_ANALYSIS_MAP_RE.search(query))
|
|
706
|
+
is_analysis_point_query = _is_kma_analysis_point_query(
|
|
707
|
+
query, is_analysis_map_query=is_analysis_map_query
|
|
708
|
+
)
|
|
709
|
+
is_lifestyle_weather_query = _is_lifestyle_weather_query(
|
|
710
|
+
query, is_airport_aviation_query=is_airport_aviation_query
|
|
711
|
+
)
|
|
712
|
+
scored = _filter_initial_special_scores(query, scored)
|
|
713
|
+
if is_analysis_query:
|
|
714
|
+
scored = _filter_kma_analysis_scores(
|
|
715
|
+
scored,
|
|
716
|
+
is_analysis_map_query=is_analysis_map_query,
|
|
717
|
+
is_analysis_point_query=is_analysis_point_query,
|
|
718
|
+
prefer_poi_location=bool(_POI_LOCATION_RE.search(query)),
|
|
719
|
+
)
|
|
720
|
+
if is_lifestyle_weather_query:
|
|
721
|
+
scored = _filter_kma_lifestyle_weather_scores(scored)
|
|
722
|
+
scored = _filter_emergency_chain_scores(query, scored)
|
|
723
|
+
scored = _filter_pps_bid_scores(query, scored)
|
|
724
|
+
scored = _filter_kcue_regional_scores(query, scored)
|
|
725
|
+
scored = _filter_health_detail_scores(query, scored)
|
|
726
|
+
scored = _filter_public_safety_location_scores(query, scored)
|
|
727
|
+
scored = _filter_ocean_water_quality_scores(query, scored)
|
|
728
|
+
scored = _filter_kma_aviation_scores(
|
|
729
|
+
query, scored, is_airport_aviation_query=is_airport_aviation_query
|
|
730
|
+
)
|
|
731
|
+
scored = _boost_aed_scores(query, scored)
|
|
732
|
+
|
|
733
|
+
query_lower = query.lower()
|
|
734
|
+
return [
|
|
735
|
+
(tool_id, score + 1000.0 if tool_id.lower() in query_lower else score)
|
|
736
|
+
for tool_id, score in scored
|
|
737
|
+
]
|
|
738
|
+
|
|
739
|
+
|
|
91
740
|
def search(
|
|
92
741
|
query: str,
|
|
93
742
|
bm25_index: BM25Index,
|
|
@@ -161,10 +810,7 @@ def search(
|
|
|
161
810
|
)
|
|
162
811
|
return []
|
|
163
812
|
|
|
164
|
-
|
|
165
|
-
scored = [
|
|
166
|
-
(tool_id, score) for tool_id, score in scored if tool_id != "koroad_accident_search"
|
|
167
|
-
]
|
|
813
|
+
scored = _filter_special_case_scores(query, scored)
|
|
168
814
|
|
|
169
815
|
# Enforce the deterministic tie-break once, here. Backend-internal
|
|
170
816
|
# orderings are not trusted (HybridBackend returns unordered union).
|