Sasquatch: local fast-path for finder questions (kills ~30s AI wait)
Root cause of the ~35s "spots in bangkok" response: every live-data question first waited on an AI round-trip just to produce a tool call, and the keyless backup model (Pollinations) can take tens of seconds. The relay query and local formatting were already fast — the AI was the bottleneck. Fix: before touching the AI, try parseLocalIntent(). For clear finder questions (spots/events/coaches/crews/shops/tours/gear + community stats + weather with a parseable location) we now go STRAIGHT to the relays (capped at 4.5s) and render locally — zero AI calls. Expected ~35s → ~2–4s on the most common queries. Deliberately still routed through the AI: - trip planning (needs the rich itinerary card) - personal "my …" Pro queries (get_my_* tools) - anything without a confidently-parseable intent/location If the fast-path relay query errors, it falls through to the existing AI loop as a backup, so nothing regresses. Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
8b7d9ca4ea
commit
6df526bf27
1 changed files with 62 additions and 0 deletions
|
|
@ -864,6 +864,68 @@ export function SasquatchGuide({ message, onDismiss }: SasquatchGuideProps) {
|
|||
return;
|
||||
}
|
||||
|
||||
// 1d. LOCAL FAST-PATH — the big speed win.
|
||||
// For clear finder questions ("spots in bangkok", "events in lisbon",
|
||||
// "coaches near berlin", "community stats", "weather in X") we can parse
|
||||
// the intent + location ourselves and go STRAIGHT to the relays — skipping
|
||||
// the AI entirely. Previously every live query waited on an AI round-trip
|
||||
// just to produce a tool call, which is what made these take ~30s+.
|
||||
//
|
||||
// We deliberately DON'T fast-path:
|
||||
// • trip planning (needs the rich itinerary card + AI nuance)
|
||||
// • personal "my …" queries (Pro tools handled by the AI path)
|
||||
// Those fall through to the AI loop below.
|
||||
const isPersonalQuery = /\bmy (stash|gear|crew|crews|spots?|listings?|inventory)\b|what am i selling|what do i own/i.test(question);
|
||||
const fastIntent = isPersonalQuery ? null : parseLocalIntent(question);
|
||||
if (fastIntent && fastIntent.tool !== 'plan_trip') {
|
||||
try {
|
||||
setStreamingText('🔍 Checking live data…');
|
||||
let fastResult: unknown;
|
||||
switch (fastIntent.tool) {
|
||||
case 'find_spots':
|
||||
fastResult = await cvm.findSpots({ city: fastIntent.location, limit: 30 });
|
||||
break;
|
||||
case 'find_events':
|
||||
fastResult = await cvm.findEvents({ city: fastIntent.location, limit: 30 });
|
||||
break;
|
||||
case 'find_coaches':
|
||||
fastResult = await cvm.findCoaches({ location: fastIntent.location, limit: 30 });
|
||||
break;
|
||||
case 'find_crews':
|
||||
fastResult = await cvm.findCrews({ city: fastIntent.location, limit: 30 });
|
||||
break;
|
||||
case 'find_shops':
|
||||
fastResult = await cvm.findShops({ city: fastIntent.location, limit: 30 });
|
||||
break;
|
||||
case 'find_tours':
|
||||
fastResult = await cvm.findTours({ city: fastIntent.location, limit: 30 });
|
||||
break;
|
||||
case 'find_gear':
|
||||
fastResult = await cvm.findGear({ search: fastIntent.search, limit: 30 });
|
||||
break;
|
||||
case 'get_community_stats':
|
||||
fastResult = await cvm.getCommunityStats();
|
||||
break;
|
||||
case 'get_weather':
|
||||
fastResult = { content: [{ type: 'text', text: await fetchWeatherForCity(fastIntent.city) }] };
|
||||
break;
|
||||
}
|
||||
setCvmConnected(true);
|
||||
setStreamingText('');
|
||||
appendMessage({
|
||||
role: 'sasquatch',
|
||||
text: formatLocalResults(fastIntent, fastResult),
|
||||
timestamp: Date.now(),
|
||||
isLive: true,
|
||||
});
|
||||
return;
|
||||
} catch (fastErr) {
|
||||
// Relays hiccuped — fall through to the AI path as a backup.
|
||||
console.warn('[Sasquatch] fast-path failed, falling back to AI:', fastErr);
|
||||
setStreamingText('');
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Build conversation history for AI
|
||||
const history = chatMessages.map((m) => ({
|
||||
role: m.role === 'user' ? ('user' as const) : ('assistant' as const),
|
||||
|
|
|
|||
Loading…
Reference in a new issue