| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- <script setup>
- import {useEchoModel} from "@laravel/echo-vue";
- import {useInferenceResponse} from "@/Composables/useInferenceResponse.js";
- import {Spinner} from "@/Packages/Shadcn/Components/ui/spinner/index.js";
- import AnimatedDots from "@/Components/AnimatedDots.vue";
- import {computed, ref} from "vue";
- import {parse} from "marked";
- import {Badge} from "@/Packages/Shadcn/Components/ui/badge/index.js";
- const response = useInferenceResponse()
- const {message} = defineProps({
- message: {
- type: Object,
- required: true,
- }
- })
- response.setStatus(message.status)
- useEchoModel('App.Models.Message', message.id, '.Wisper', e => response.setStatus(e.status))
- useEchoModel('App.Models.Message', message.id, '.Streaming', e => response.append(e.chunk, e.index))
- const stream = computed(() => ({
- think: response.think.value ? parse(response.think.value) : null,
- content: response.content.value ? parse(response.content.value) : null,
- status: response.status.value,
- }))
- const thinking = computed(() => message.thinking ? parse(message.thinking) : null)
- const content = computed(() => message.content ? parse(message.content) : null)
- const spoiler = ref(false)
- </script>
- <template>
- <div>
- <div>
- <div v-if="stream.status === 0">
- <Badge class="text-sm" variant="outline">
- <Spinner class="!text-lg mr-1"/>
- <span>Загрузка<AnimatedDots/></span>
- </Badge>
- </div>
- <div v-if="[1, 2].includes(stream.status) || stream.think || thinking">
- <Badge class="cursor-pointer text-sm" variant="outline" @click="spoiler = !spoiler">
- <Spinner v-if="stream.status === 1" class="mr-1"/>
- <span>Размышления<AnimatedDots :animating="stream.status === 2"/></span>
- </Badge>
- </div>
- </div>
- <transition
- enter-active-class="transition-transform duration-300 ease-out"
- enter-from-class="scale-y-0"
- enter-to-class="scale-y-100"
- leave-active-class="transition-transform duration-300 ease-in"
- leave-from-class="scale-y-100"
- leave-to-class="scale-y-0"
- >
- <div v-show="spoiler"
- class="h-[250px] origin-top transform overflow-auto bg-muted rounded-lg px-3 mt-2 border shadow-xs">
- <div class="max-w-full prose dark:prose-invert text-xs" v-html="thinking ?? stream.think"></div>
- </div>
- </transition>
- <div class="max-w-full prose dark:prose-invert text-sm mt-2" v-html="content ?? stream.content"></div>
- </div>
- </template>
- <style scoped>
- </style>
|