fix(chat): stop 429 retry spiral and add get_weather coord fallback
- search_places: detect HTTP 429 and mark retryable=False to stop the retry loop immediately instead of spiraling until MAX_ITERATIONS - get_weather: extract collection coordinates (lat/lng from first location with coords) and retry when LLM omits required params; uses sync_to_async for the DB query in the async view - AITravelChat: deduplicate context-only tools (get_trip_details, get_weather) in the render pipeline to prevent duplicate place cards from appearing when the retry loop causes multiple get_trip_details calls - Tests: 5 new tests covering 429 non-retryable path and weather coord fallback; all 39 chat tests pass
This commit is contained in:
@@ -348,7 +348,9 @@
|
||||
return [...next, toolResult];
|
||||
}
|
||||
|
||||
function uniqueToolResultsByCallId(toolResults: ToolResultEntry[] | undefined): ToolResultEntry[] {
|
||||
function uniqueToolResultsByCallId(
|
||||
toolResults: ToolResultEntry[] | undefined
|
||||
): ToolResultEntry[] {
|
||||
if (!toolResults) {
|
||||
return [];
|
||||
}
|
||||
@@ -368,6 +370,24 @@
|
||||
return unique;
|
||||
}
|
||||
|
||||
// Context-loading tools that should render at most once per message, even if
|
||||
// the retry loop caused the LLM to call them multiple times.
|
||||
const CONTEXT_ONLY_TOOLS = new Set(['get_trip_details', 'get_weather']);
|
||||
|
||||
function deduplicateContextTools(toolResults: ToolResultEntry[]): ToolResultEntry[] {
|
||||
const seenContextTool = new Set<string>();
|
||||
return toolResults.filter((result) => {
|
||||
const name = result.name;
|
||||
if (name && CONTEXT_ONLY_TOOLS.has(name)) {
|
||||
if (seenContextTool.has(name)) {
|
||||
return false;
|
||||
}
|
||||
seenContextTool.add(name);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
function rebuildConversationMessages(rawMessages: ChatMessage[]): ChatMessage[] {
|
||||
const rebuilt = rawMessages.map((msg) => ({
|
||||
...msg,
|
||||
@@ -936,7 +956,7 @@
|
||||
<div class="whitespace-pre-wrap">{msg.content}</div>
|
||||
{#if msg.role === 'assistant' && msg.tool_results}
|
||||
<div class="mt-2 space-y-2">
|
||||
{#each uniqueToolResultsByCallId(msg.tool_results) as result}
|
||||
{#each deduplicateContextTools(uniqueToolResultsByCallId(msg.tool_results)) as result}
|
||||
{#if hasPlaceResults(result)}
|
||||
<div class="grid gap-2">
|
||||
{#each getPlaceResults(result) as place}
|
||||
|
||||
Reference in New Issue
Block a user