v4.3.20-3: ollama_web_* 도구 키워드 게이팅 — 오버헤드 214토큰 절감

ollama_web_search / ollama_web_fetch가 매 턴 무조건 스키마에 포함되고 있었음.
두 도구는 자기 description에 "뉴스·정보 검색은 반드시 web_search를 사용. 이
툴은 web_search가 없는 환경에서만 fallback으로 사용"이라고 적혀 있어서, 모델
에게 "이 도구를 쓰지 말라"고 알리는 데 214토큰을 쓰던 셈. 게다가 그 폴백
체인은 이미 executeWebSearch 내부에서 서버가 처리하므로 모델이 직접 부를
이유가 없음.

삭제가 아니라 게이팅을 택함: personality-context.ts에 "올라마로 검색" 류
표현에만 뜨는 ollama_web 힌트 블록이 이미 있어서, 도구를 제거하면 그 힌트가
존재하지 않는 도구를 설명하게 됨. 같은 표현으로 게이트해 평소엔 0토큰,
명시 요청 시엔 정상 동작하도록 함.

실측: 3,788 → 3,574. "올라마로 검색해줘" 요청에서는 4,980으로 도구가 정상
복귀하는 것도 확인.

조사 중 정정: eonet_events/satellite_snapshot과 run_command는 이미
skillToolFilter에 게이트가 있었음(각각 hasSatelliteKeyword, hasCodeKeyword).
초기 분석에서 필터 전체를 보지 못해 "무조건 켜짐"으로 잘못 판단했던 것을
바로잡음 — 실제 always-on은 8개(1,109토큰)뿐이며 07-26 스코핑 작업이
이미 대부분을 처리해둔 상태.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
kim
2026-07-29 15:18:06 +09:00
co-authored by Claude Opus 5
parent 37257801ed
commit 8a121457ff
+10
View File
@@ -261,6 +261,15 @@ async function handleChat(
// explicit excel/spreadsheet keyword, same shape as the weather/legal gates above. Previously
// ungated, so both tool schemas rode along on every single chat turn regardless of app.
const hasExcelKeyword = /엑셀|xlsx|xls\b|스프레드시트|spreadsheet|excel/i.test(message);
// ollama_web_search/ollama_web_fetch are explicitly self-deprecating in their own descriptions
// ("web_search가 없는 환경에서만 fallback으로 사용") — and the provider fallback they exist for
// is already handled server-side inside executeWebSearch, so the model never needs to reach for
// them on its own. Advertising them cost 214 tokens per turn to tell the model not to use a
// tool. Gate on the same explicit phrasing personality-context.ts already uses for its
// ollama_web hint block, so the pair stays available when the user actually asks for it by name
// (otherwise that hint would describe tools no longer in the schema).
const ollamaWebToolNames = new Set(['ollama_web_search', 'ollama_web_fetch']);
const hasOllamaWebKeyword = /ollama[\s_]?(웹|web|검색|search)|올라마\s*(웹|검색|로\s*검색)/i.test(message);
// Sub-agent/task-orchestration tools that tool_audit.log shows near-zero real usage for
// (2026-05-04~2026-07-12: start_task/request_secondary_assist/subagent_spawn/
// delegate_to_specialist/spawn_subagent = 0 calls; task_control/parse_schedule_pattern/
@@ -311,6 +320,7 @@ async function handleChat(
// model there has already generated the embed.windy.com URL to capture) — unlike the
// other weather tools, not offered via the meteorologist skill in general chat.
if (name === 'weather_map_screenshot' && !isWeatherAppSession) return false;
if (ollamaWebToolNames.has(name) && !hasOllamaWebKeyword) return false;
if (legalToolNames.has(name) && !isLawyerAppSession && !(lawyerEnabled && hasLegalKeyword)) return false;
if ((name === 'excel_read' || name === 'excel_write') && !isAccountantAppSession && !hasExcelKeyword) return false;
if (coderToolNames.has(name) && !hasCodeKeyword) return false;