Spaces:
Sleeping
Sleeping
Download backend/src/lib/webSearchRouting.ts from bardd/mike-backend: direct link, hf CLI and curl.
- Browser
- Download file 5.75 kB
-
https://huggingface.co/spaces/bardd/mike-backend/resolve/main/backend/src/lib/webSearchRouting.ts
- Command line
-
hf download hf://spaces/bardd/mike-backend/backend/src/lib/webSearchRouting.ts
-
curl -L -o webSearchRouting.ts https://huggingface.co/spaces/bardd/mike-backend/resolve/main/backend/src/lib/webSearchRouting.ts
5.75 kB
| import type { RunTree } from "langsmith"; | |
| import { executeCompleteText } from "./inference/execute"; | |
| import { getDefaultModelForFeature } from "./inference/config"; | |
| import type { UserApiKeys } from "./llm/types"; | |
| import { WEB_SEARCH_ROUTING_SYSTEM_PROMPT } from "../prompts/chat/routing/web-search-routing"; | |
| const WEB_SEARCH_INTENT_RE = | |
| /\b(search|browse|google|look\s+up|web|internet|online|latest|recently|recent|current|today|news|source(?:s)?|cite(?:s|d)?|verify|fact[- ]?check)\b/i; | |
| /** Person/entity + said/talked phrasing usually needs live news context. */ | |
| const RECENT_STATEMENT_RE = | |
| /\b(what did|what has|what does)\b.{0,80}\b(say|said|talk|talked|speak|spoke|mention|mentioned|comment|commented)\b/i; | |
| const REALTIME_FACT_RE = | |
| /\b(price|prices|stock price|share price|exchange rate|market cap|trading at|trading on|how much(?:\s+is)?|worth|value of)\b/i; | |
| const REALTIME_MARKET_RE = | |
| /\bhow much\b.{0,80}\b(stock|stocks|shares?|equity|crypto|cryptocurrency|coin|coins)\b/i; | |
| const MARKET_ASSET_RE = | |
| /\b(stock|stocks|shares?|equity|crypto|cryptocurrency|coin|coins?|bitcoin|btc|ethereum|eth|solana|sol|tao|exchange rate|market cap|trading at|trading on)\b/i; | |
| /** Ambiguous definitions in a geo/news context (e.g. trending acronyms like CJP in India). */ | |
| const AMBIGUOUS_GEO_DEFINITION_RE = | |
| /\b(what is|what's|who is|who's|what does|what do)\b.{0,80}\b(in|for)\b.{0,40}\b(india|usa|u\.?s\.?a?|uk|china|europe|world)\b/i; | |
| const CURRENT_LEGAL_RE = | |
| /\b(current|latest|recent|updated|in force|as of today|as of now)\b.{0,80}\b(law|regulation|statute|case law|guidance|rule|deadline|filing|fee|authority|ministry|court|article)\b/i; | |
| /** Questions that may need live context when heuristics do not already match. */ | |
| const ROUTING_CANDIDATE_RE = | |
| /\b(what is|what's|who is|who's|what does|what do|meaning of|stand for|stands for|trending|why is|why are|explain|define|tell me about|what happened|what's happening|what is happening)\b/i; | |
| const LOCAL_FAST_PATH_RE = | |
| /^\s*(hi|hello|hey|thanks|thank you|ok|okay|yes|no)\s*[!.?]*\s*$/i; | |
| const DOCUMENT_SCOPE_RE = | |
| /\b(this|the|above|attached|uploaded|following)\b.{0,40}\b(document|docx|file|clause|section|paragraph|contract|agreement|draft|exhibit|schedule)\b/i; | |
| export type WebSearchRoutingSource = "heuristic" | "llm" | "skip"; | |
| export type WebSearchRoutingResult = { | |
| needsWebSearch: boolean; | |
| source: WebSearchRoutingSource; | |
| llmRaw?: string; | |
| }; | |
| export function detectWebSearchIntentHeuristic( | |
| lastUserText: string, | |
| options: { hasAttachedDocs?: boolean } = {}, | |
| ): boolean { | |
| const hasAttachedDocs = options.hasAttachedDocs ?? false; | |
| const realtimeFact = REALTIME_FACT_RE.test(lastUserText); | |
| const realtimeMarket = REALTIME_MARKET_RE.test(lastUserText); | |
| if ( | |
| hasAttachedDocs && | |
| realtimeFact && | |
| !realtimeMarket && | |
| !WEB_SEARCH_INTENT_RE.test(lastUserText) && | |
| !CURRENT_LEGAL_RE.test(lastUserText) && | |
| !MARKET_ASSET_RE.test(lastUserText) | |
| ) { | |
| return false; | |
| } | |
| return ( | |
| WEB_SEARCH_INTENT_RE.test(lastUserText) || | |
| RECENT_STATEMENT_RE.test(lastUserText) || | |
| CURRENT_LEGAL_RE.test(lastUserText) || | |
| realtimeFact || | |
| realtimeMarket || | |
| AMBIGUOUS_GEO_DEFINITION_RE.test(lastUserText) | |
| ); | |
| } | |
| function shouldSkipLlmRouting(lastUserText: string, hasAttachedDocs: boolean): boolean { | |
| const trimmed = lastUserText.trim(); | |
| if (!trimmed) return true; | |
| if (trimmed.length < 8) return true; | |
| if (LOCAL_FAST_PATH_RE.test(trimmed)) return true; | |
| if (hasAttachedDocs && DOCUMENT_SCOPE_RE.test(trimmed)) return true; | |
| if (!ROUTING_CANDIDATE_RE.test(trimmed)) return true; | |
| return false; | |
| } | |
| function parseRouterResponse(raw: string): boolean { | |
| const token = raw.trim().toUpperCase().split(/\s+/)[0] ?? ""; | |
| if (token.startsWith("WEB")) return true; | |
| if (token.startsWith("LOCAL")) return false; | |
| return /\bWEB\b/.test(raw.toUpperCase()); | |
| } | |
| export async function classifyWebSearchNeed(params: { | |
| userText: string; | |
| apiKeys?: UserApiKeys; | |
| trace?: RunTree | null; | |
| hasAttachedDocs?: boolean; | |
| }): Promise<WebSearchRoutingResult> { | |
| const userText = params.userText.trim(); | |
| const hasAttachedDocs = params.hasAttachedDocs ?? false; | |
| if (hasAttachedDocs) { | |
| return { needsWebSearch: false, source: "skip" }; | |
| } | |
| if (detectWebSearchIntentHeuristic(userText, { hasAttachedDocs })) { | |
| return { needsWebSearch: true, source: "heuristic" }; | |
| } | |
| if (shouldSkipLlmRouting(userText, hasAttachedDocs)) { | |
| return { needsWebSearch: false, source: "skip" }; | |
| } | |
| if (process.env.WEB_SEARCH_LLM_ROUTING === "0") { | |
| return { needsWebSearch: false, source: "skip" }; | |
| } | |
| try { | |
| const callRouter = async (maxTokens: number) => | |
| executeCompleteText({ | |
| model: getDefaultModelForFeature("web-search-routing"), | |
| featureId: "web-search-routing", | |
| systemPrompt: WEB_SEARCH_ROUTING_SYSTEM_PROMPT, | |
| user: userText, | |
| maxTokens, | |
| temperature: 0, | |
| lightweight: true, | |
| apiKeys: params.apiKeys, | |
| trace: params.trace, | |
| }); | |
| // Proxy models need a non-trivial max_tokens budget; very small limits return null content. | |
| let raw = await callRouter(128); | |
| if (!raw.trim()) { | |
| raw = await callRouter(256); | |
| } | |
| const needsWebSearch = raw.trim() | |
| ? parseRouterResponse(raw) | |
| : true; | |
| return { needsWebSearch, source: "llm", llmRaw: raw }; | |
| } catch { | |
| return { needsWebSearch: false, source: "skip" }; | |
| } | |
| } | |