检查点
一个简单的组件,用于标记对话历史点并将聊天恢复到之前的状态。
Checkpoint 组件提供了一种方法来标记对话历史中的特定点并将聊天恢复到该状态。受 VSCode 的 Copilot 检查点功能启发,它允许用户恢复到更早的对话状态,同时在不同对话段之间保持清晰的可视化分离。
使用 CLI 安装
AI Elements Vue
shadcn-vue CLI
npx ai-elements-vue@latest add checkpoint
npx shadcn-vue@latest add https://registry.ai-elements-vue.com/checkpoint.json
手动安装
将以下代码复制并粘贴到同一文件夹中。
Checkpoint.vue
CheckpointIcon.vue
CheckpointTrigger.vue
index.ts
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { Separator } from '@repo/shadcn-vue/components/ui/separator'
import { cn } from '@repo/shadcn-vue/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<div
:class="cn('flex items-center gap-0.5 text-muted-foreground', props.class)"
v-bind="$attrs"
>
<slot />
<Separator />
</div>
</template>
<script lang="ts" setup>
import type { HTMLAttributes } from 'vue'
import { cn } from '@repo/shadcn-vue/lib/utils'
import { BookmarkIcon } from 'lucide-vue-next'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<slot v-if="$slots.default" />
<BookmarkIcon
v-else
:class="cn('size-4 shrink-0', props.class)"
v-bind="$attrs"
/>
</template>
<script lang="ts" setup>
import type { ButtonVariants } from '@repo/shadcn-vue/components/ui/button'
import { Button } from '@repo/shadcn-vue/components/ui/button'
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@repo/shadcn-vue/components/ui/tooltip'
interface Props {
tooltip?: string
variant?: ButtonVariants['variant']
size?: ButtonVariants['size']
}
const props = withDefaults(defineProps<Props>(), {
variant: 'ghost',
size: 'sm',
})
const buttonProps = {
variant: props.variant,
size: props.size,
type: 'button' as const,
}
</script>
<template>
<Tooltip v-if="props.tooltip">
<TooltipTrigger as-child>
<Button v-bind="{ ...buttonProps, ...$attrs }">
<slot />
</Button>
</TooltipTrigger>
<TooltipContent align="start" side="bottom">
<p>{{ props.tooltip }}</p>
</TooltipContent>
</Tooltip>
<Button v-else v-bind="{ ...buttonProps, ...$attrs }">
<slot />
</Button>
</template>
export { default as Checkpoint } from './Checkpoint.vue'
export { default as CheckpointIcon } from './CheckpointIcon.vue'
export { default as CheckpointTrigger } from './CheckpointTrigger.vue'
特性
- 简单的 flex 布局,带有图标、触发器和分隔符
- 可视化分隔线,用于清晰的对话中断
- 可点击的恢复按钮,用于恢复到检查点
- 可自定义图标(默认为 BookmarkIcon)
- 键盘可访问,具有适当的 ARIA 标签
- 响应式设计,适应不同的屏幕尺寸
- 无缝的浅色/深色主题集成
与 AI SDK 一起使用
构建一个带有对话检查点的聊天界面,允许用户恢复到之前的状态。
将以下组件添加到你的前端:
pages/index.vue
<script setup lang="ts">
import { useChat } from '@ai-sdk/vue'
import { nanoid } from 'nanoid'
import { computed, ref } from 'vue'
import {
Checkpoint,
CheckpointIcon,
CheckpointTrigger,
} from '@/components/ai-elements/checkpoint'
import {
Conversation,
ConversationContent,
} from '@/components/ai-elements/conversation'
import {
Message,
MessageContent,
MessageResponse,
} from '@/components/ai-elements/message'
interface CheckpointType {
id: string
messageIndex: number
timestamp: Date
messageCount: number
}
const { messages, setMessages } = useChat()
const checkpoints = ref<CheckpointType[]>([])
const messagesWithCheckpoints = computed(() => {
return messages.value.map((message, index) => {
const checkpoint = checkpoints.value.find(
cp => cp.messageIndex === index
)
return { message, index, checkpoint }
})
})
function createCheckpoint(messageIndex: number) {
const checkpoint: CheckpointType = {
id: nanoid(),
messageIndex,
timestamp: new Date(),
messageCount: messageIndex + 1,
}
checkpoints.value.push(checkpoint)
}
function restoreToCheckpoint(messageIndex: number) {
// Restore messages to checkpoint state (assuming setMessages API is the same)
setMessages(messages.value.slice(0, messageIndex + 1))
// Remove checkpoints after this point
checkpoints.value = checkpoints.value.filter(
cp => cp.messageIndex <= messageIndex
)
}
</script>
<template>
<div
class="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]"
>
<Conversation>
<ConversationContent>
<template
v-for="{ message, checkpoint } in messagesWithCheckpoints"
:key="message.id"
>
<Message :from="message.role">
<MessageContent>
<MessageResponse>{{ message.content }}</MessageResponse>
</MessageContent>
</Message>
<Checkpoint v-if="checkpoint">
<CheckpointIcon />
<CheckpointTrigger
@click="restoreToCheckpoint(checkpoint.messageIndex)"
>
Restore checkpoint
</CheckpointTrigger>
</Checkpoint>
</template>
</ConversationContent>
</Conversation>
</div>
</template>
使用场景
手动检查点
允许用户在重要的对话点手动创建检查点:
<Button @click="createCheckpoint(messages.length - 1)">
Create Checkpoint
</Button>
自动检查点
在重要的对话里程碑后自动创建检查点:
watch(
() => messages.value.length,
(length) => {
// Create checkpoint every 5 messages
if (length > 0 && length % 5 === 0) {
createCheckpoint(length - 1)
}
}
)
分支对话
使用检查点启用对话分支,用户可以探索不同的对话路径:
function restoreAndBranch(messageIndex: number) {
// Save current branch
const currentBranch = messages.value.slice(messageIndex + 1)
saveBranch(currentBranch)
// Restore to checkpoint
restoreToCheckpoint(messageIndex)
}
Props
<Checkpoint />
classstring
''<CheckpointIcon />
classstring
''<CheckpointTrigger />
tooltipstring
''variantstring
'ghost'sizestring
'sm'