mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-01-02 14:22:28 +08:00
fix: implement client-side caching for example diagrams (#150)
- Add client-side cache check in onFormSubmit to bypass API calls for example prompts - Use findCachedResponse to match input against cached examples - Directly set messages with cached tool response when example matches - Hide regenerate button for cached example responses (toolCallId starts with 'cached-') - Prevents unnecessary API calls when using example buttons Co-authored-by: dayuan.jiang <jiangdy@amazon.co.jp>
This commit is contained in:
@@ -195,20 +195,44 @@ async function handleChatRequest(req: Request): Promise<Response> {
|
|||||||
const isFirstMessage = messages.length === 1
|
const isFirstMessage = messages.length === 1
|
||||||
const isEmptyDiagram = !xml || xml.trim() === "" || isMinimalDiagram(xml)
|
const isEmptyDiagram = !xml || xml.trim() === "" || isMinimalDiagram(xml)
|
||||||
|
|
||||||
|
// DEBUG: Log cache check conditions
|
||||||
|
console.log("[Cache DEBUG] messages.length:", messages.length)
|
||||||
|
console.log("[Cache DEBUG] isFirstMessage:", isFirstMessage)
|
||||||
|
console.log("[Cache DEBUG] xml length:", xml?.length || 0)
|
||||||
|
console.log("[Cache DEBUG] xml preview:", xml?.substring(0, 200))
|
||||||
|
console.log("[Cache DEBUG] isEmptyDiagram:", isEmptyDiagram)
|
||||||
|
|
||||||
if (isFirstMessage && isEmptyDiagram) {
|
if (isFirstMessage && isEmptyDiagram) {
|
||||||
const lastMessage = messages[0]
|
const lastMessage = messages[0]
|
||||||
const textPart = lastMessage.parts?.find((p: any) => p.type === "text")
|
const textPart = lastMessage.parts?.find((p: any) => p.type === "text")
|
||||||
const filePart = lastMessage.parts?.find((p: any) => p.type === "file")
|
const filePart = lastMessage.parts?.find((p: any) => p.type === "file")
|
||||||
|
|
||||||
|
console.log("[Cache DEBUG] textPart?.text:", textPart?.text)
|
||||||
|
console.log("[Cache DEBUG] hasFilePart:", !!filePart)
|
||||||
|
|
||||||
const cached = findCachedResponse(textPart?.text || "", !!filePart)
|
const cached = findCachedResponse(textPart?.text || "", !!filePart)
|
||||||
|
|
||||||
|
console.log("[Cache DEBUG] cached found:", !!cached)
|
||||||
|
|
||||||
if (cached) {
|
if (cached) {
|
||||||
console.log(
|
console.log(
|
||||||
"[Cache] Returning cached response for:",
|
"[Cache] Returning cached response for:",
|
||||||
textPart?.text,
|
textPart?.text,
|
||||||
)
|
)
|
||||||
return createCachedStreamResponse(cached.xml)
|
return createCachedStreamResponse(cached.xml)
|
||||||
|
} else {
|
||||||
|
console.log("[Cache DEBUG] No cache match - checking why...")
|
||||||
|
console.log(
|
||||||
|
"[Cache DEBUG] Exact promptText:",
|
||||||
|
JSON.stringify(textPart?.text),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.log("[Cache DEBUG] Skipping cache check - conditions not met")
|
||||||
|
if (!isFirstMessage)
|
||||||
|
console.log("[Cache DEBUG] Reason: not first message")
|
||||||
|
if (!isEmptyDiagram)
|
||||||
|
console.log("[Cache DEBUG] Reason: diagram not empty")
|
||||||
}
|
}
|
||||||
// === CACHE CHECK END ===
|
// === CACHE CHECK END ===
|
||||||
|
|
||||||
|
|||||||
@@ -676,9 +676,14 @@ export function ChatMessageDisplay({
|
|||||||
<Copy className="h-3.5 w-3.5" />
|
<Copy className="h-3.5 w-3.5" />
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
{/* Regenerate button - only on last assistant message */}
|
{/* Regenerate button - only on last assistant message, not for cached examples */}
|
||||||
{onRegenerate &&
|
{onRegenerate &&
|
||||||
isLastAssistantMessage && (
|
isLastAssistantMessage &&
|
||||||
|
!message.parts?.some((p: any) =>
|
||||||
|
p.toolCallId?.startsWith(
|
||||||
|
"cached-",
|
||||||
|
),
|
||||||
|
) && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ const STORAGE_SESSION_ID_KEY = "next-ai-draw-io-session-id"
|
|||||||
const STORAGE_DIAGRAM_XML_KEY = "next-ai-draw-io-diagram-xml"
|
const STORAGE_DIAGRAM_XML_KEY = "next-ai-draw-io-diagram-xml"
|
||||||
|
|
||||||
import { useDiagram } from "@/contexts/diagram-context"
|
import { useDiagram } from "@/contexts/diagram-context"
|
||||||
|
import { findCachedResponse } from "@/lib/cached-responses"
|
||||||
import { formatXML } from "@/lib/utils"
|
import { formatXML } from "@/lib/utils"
|
||||||
import { ChatMessageDisplay } from "./chat-message-display"
|
import { ChatMessageDisplay } from "./chat-message-display"
|
||||||
|
|
||||||
@@ -450,6 +451,42 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const isProcessing = status === "streaming" || status === "submitted"
|
const isProcessing = status === "streaming" || status === "submitted"
|
||||||
if (input.trim() && !isProcessing) {
|
if (input.trim() && !isProcessing) {
|
||||||
|
// Check if input matches a cached example (only when no messages yet)
|
||||||
|
if (messages.length === 0) {
|
||||||
|
const cached = findCachedResponse(
|
||||||
|
input.trim(),
|
||||||
|
files.length > 0,
|
||||||
|
)
|
||||||
|
if (cached) {
|
||||||
|
// Add user message and fake assistant response to messages
|
||||||
|
// The chat-message-display useEffect will handle displaying the diagram
|
||||||
|
const toolCallId = `cached-${Date.now()}`
|
||||||
|
setMessages([
|
||||||
|
{
|
||||||
|
id: `user-${Date.now()}`,
|
||||||
|
role: "user" as const,
|
||||||
|
parts: [{ type: "text" as const, text: input }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: `assistant-${Date.now()}`,
|
||||||
|
role: "assistant" as const,
|
||||||
|
parts: [
|
||||||
|
{
|
||||||
|
type: "tool-display_diagram" as const,
|
||||||
|
toolCallId,
|
||||||
|
state: "output-available" as const,
|
||||||
|
input: { xml: cached.xml },
|
||||||
|
output: "Successfully displayed the diagram.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
] as any)
|
||||||
|
setInput("")
|
||||||
|
setFiles([])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let chartXml = await onFetchChart()
|
let chartXml = await onFetchChart()
|
||||||
chartXml = formatXML(chartXml)
|
chartXml = formatXML(chartXml)
|
||||||
|
|||||||
Reference in New Issue
Block a user