feat: update tool names and descriptions for diagram handling, add clear messages functionality in ChatInput

This commit is contained in:
dayuan.jiang
2025-03-22 14:28:55 +00:00
parent 4834d524b9
commit fc4383dfb5
3 changed files with 45 additions and 27 deletions

View File

@@ -21,22 +21,23 @@ export async function POST(req: Request) {
You are a helpful assistant that can create, edit, and display diagram using draw.io through xml strings. You are a helpful assistant that can create, edit, and display diagram using draw.io through xml strings.
You can use the following tools: You can use the following tools:
---Tool1--- ---Tool1---
tool name: display_flow_chart tool name: display_diagram
description: write a xml and display it on draw.io description: Display a diagram on draw.io
parameters: { parameters: {
xml: string xml: string
} }
---Tool2---
tool name: fetch_flow_chart
description: Get the current diagram XML from draw.io
parameters: {}
---End of tools--- ---End of tools---
When you need to modify the diagram, you need fetch the current diagram XML from draw.io and then modify it and display it again. Here is a guide for the XML format:
here is a guide for the XML format: ${guide} """md
You can use the tools to create and manipulate diagram. ${guide}
"""
You can use the tools to create and manipulate diagrams.
You can also answer questions and provide explanations. You can also answer questions and provide explanations.
If user want you to draw something rather than diagram, you can use the combination of the shape to draw it. Note that:
- If the user wants you to draw something rather than a diagram, you can use the combination of the shapes to draw it.
- Consider the layout of the diagram and the shapes used to avoid overlapping.
- Ensure that the XML strings are well-formed and valid.
`; `;
// Add system message if only user message is provided // Add system message if only user message is provided
@@ -50,17 +51,12 @@ If user want you to draw something rather than diagram, you can use the combinat
messages: enhancedMessages, messages: enhancedMessages,
tools: { tools: {
// Client-side tool that will be executed on the client // Client-side tool that will be executed on the client
display_flow_chart: { display_diagram: {
description: "Display a flowchart on draw.io", description: "Display a diagram on draw.io",
parameters: z.object({ parameters: z.object({
xml: z.string().describe("XML string to be displayed on draw.io") xml: z.string().describe("XML string to be displayed on draw.io")
}) })
}, },
// Client-side tool that will be executed on the client
fetch_flow_chart: {
description: "Get the current flowchart XML from draw.io",
parameters: z.object({})
}
}, },
temperature: 0, temperature: 0,
}); });

View File

@@ -3,16 +3,17 @@
import React, { useCallback, useRef, useEffect } from "react" import React, { useCallback, useRef, useEffect } from "react"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { Textarea } from "@/components/ui/textarea" import { Textarea } from "@/components/ui/textarea"
import { Loader2, Send } from "lucide-react" import { Loader2, Send, Trash } from "lucide-react"
interface ChatInputProps { interface ChatInputProps {
input: string input: string
status: "submitted" | "streaming" | "ready" | "error" status: "submitted" | "streaming" | "ready" | "error"
onSubmit: (e: React.FormEvent<HTMLFormElement>) => void onSubmit: (e: React.FormEvent<HTMLFormElement>) => void
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void
setMessages: (messages: any[]) => void
} }
export function ChatInput({ input, status, onSubmit, onChange }: ChatInputProps) { export function ChatInput({ input, status, onSubmit, onChange, setMessages }: ChatInputProps) {
const textareaRef = useRef<HTMLTextAreaElement>(null) const textareaRef = useRef<HTMLTextAreaElement>(null)
// Auto-resize textarea based on content // Auto-resize textarea based on content
@@ -51,7 +52,17 @@ export function ChatInput({ input, status, onSubmit, onChange }: ChatInputProps)
aria-label="Chat input" aria-label="Chat input"
className="min-h-[80px] resize-none transition-all duration-200" className="min-h-[80px] resize-none transition-all duration-200"
/> />
<div className="flex justify-end"> <div className="flex justify-between gap-2">
<Button
type="button"
variant="outline"
size="default"
onClick={() => setMessages([])}
title="Clear messages"
>
<Trash className="mr-2 h-4 w-4" />
Start a new conversation
</Button>
<Button <Button
type="submit" type="submit"
disabled={status === "streaming" || !input.trim()} disabled={status === "streaming" || !input.trim()}

View File

@@ -5,6 +5,7 @@ import { useRef, useEffect } from "react"
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card" import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { ScrollArea } from "@/components/ui/scroll-area" import { ScrollArea } from "@/components/ui/scroll-area"
import { Button } from "@/components/ui/button"
import { useChat } from '@ai-sdk/react'; import { useChat } from '@ai-sdk/react';
import { ChatInput } from "@/components/chat-input" import { ChatInput } from "@/components/chat-input"
@@ -14,20 +15,16 @@ interface ChatPanelProps {
} }
export default function ChatPanel({ onDisplayChart, onFetchChart }: ChatPanelProps) { export default function ChatPanel({ onDisplayChart, onFetchChart }: ChatPanelProps) {
const { messages, input, handleInputChange, handleSubmit, status, error, addToolResult } = useChat({ const { messages, input, handleInputChange, handleSubmit, status, error, setInput, setMessages } = useChat({
maxSteps: 5,
async onToolCall({ toolCall }) { async onToolCall({ toolCall }) {
console.log("Tool call:", toolCall); console.log("Tool call:", toolCall);
console.log("Tool call name:", toolCall.toolName); console.log("Tool call name:", toolCall.toolName);
console.log("Tool call arguments:", toolCall.args); console.log("Tool call arguments:", toolCall.args);
if (toolCall.toolName === "display_diagram") {
if (toolCall.toolName === "display_flow_chart") {
const { xml } = toolCall.args as { xml: string }; const { xml } = toolCall.args as { xml: string };
onDisplayChart(xml); onDisplayChart(xml);
return "Successfully displayed the flowchart."; return "Successfully displayed the flowchart.";
} else if (toolCall.toolName === "fetch_flow_chart") {
const currentXML = await onFetchChart();
console.log("Current XML:", currentXML);
return currentXML;
} }
}, },
onError: (error) => { onError: (error) => {
@@ -41,11 +38,24 @@ export default function ChatPanel({ onDisplayChart, onFetchChart }: ChatPanelPro
if (messagesEndRef.current) { if (messagesEndRef.current) {
messagesEndRef.current.scrollIntoView({ behavior: "smooth" }) messagesEndRef.current.scrollIntoView({ behavior: "smooth" })
} }
console.log("Messages updated:", messages);
}, [messages]) }, [messages])
const onFormSubmit = (e: React.FormEvent<HTMLFormElement>) => { const onFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault() e.preventDefault()
if (input.trim() && status !== "streaming") { if (input.trim() && status !== "streaming") {
setInput(
`
Current diagram XML:
"""xml
${onFetchChart()}
"""
User input:
"""md
${input}
"""
`
)
handleSubmit(e) handleSubmit(e)
} }
} }
@@ -169,6 +179,7 @@ export default function ChatPanel({ onDisplayChart, onFetchChart }: ChatPanelPro
status={status} status={status}
onSubmit={onFormSubmit} onSubmit={onFormSubmit}
onChange={handleInputChange} onChange={handleInputChange}
setMessages={setMessages}
/> />
</CardFooter> </CardFooter>
</Card> </Card>