feat: 对接星火大模型
feat: 大模型选择器 feat: 聊天页面适配手机端
This commit is contained in:
@@ -1,7 +1,14 @@
|
||||
<script lang="ts" setup>
|
||||
import ChatItem from "~/components/aigc/chat/ChatItem.vue";
|
||||
import Message from "~/components/aigc/chat/Message.vue";
|
||||
import type {ChatMessage, ChatMessageId, ChatSessionId} from "~/typings/llm";
|
||||
import {
|
||||
type ChatMessage,
|
||||
type ChatMessageId,
|
||||
type ChatSession,
|
||||
type ChatSessionId,
|
||||
llmModels,
|
||||
type ModelTag
|
||||
} from "~/typings/llm";
|
||||
import {useHistory} from "~/composables/useHistory";
|
||||
import {uuidv4} from "@uniiem/uuid";
|
||||
import {useLLM} from "~/composables/useLLM";
|
||||
@@ -17,18 +24,22 @@ const historyStore = useHistory()
|
||||
const {chatSessions} = storeToRefs(historyStore)
|
||||
const {setChatSessions} = historyStore
|
||||
|
||||
// const chatSessions = ref<ChatSession[]>([])
|
||||
const currentSessionId = ref<ChatSessionId | null>(null)
|
||||
const messagesWrapperRef = ref<HTMLDivElement | null>(null)
|
||||
|
||||
const showSidebar = ref(false)
|
||||
const user_input = ref('')
|
||||
const responding = ref(false)
|
||||
const currentModel = ref<ModelTag>('spark3_5')
|
||||
const modals = reactive({
|
||||
modelSelect: false
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取指定 ID 的会话数据
|
||||
* @param chatSessionId
|
||||
*/
|
||||
const getSessionCopyById = (chatSessionId: ChatSessionId) => chatSessions.value.find(s => s.id === chatSessionId);
|
||||
const getSessionCopyById = (chatSessionId: ChatSessionId): ChatSession | undefined => chatSessions.value.find(s => s.id === chatSessionId);
|
||||
/**
|
||||
* 切换当前会话
|
||||
* @param chatSessionId 指定会话 ID,不传则切换到列表中第一个会话
|
||||
@@ -58,6 +69,7 @@ const selectCurrentSessionId = (chatSessionId?: ChatSessionId) => {
|
||||
handleClickCreateSession()
|
||||
}
|
||||
nextTick(() => {
|
||||
showSidebar.value = false
|
||||
scrollToMessageListBottom()
|
||||
})
|
||||
}
|
||||
@@ -80,6 +92,7 @@ const handleClickCreateSession = () => {
|
||||
])
|
||||
// 切换到新的会话
|
||||
selectCurrentSessionId(sessionId)
|
||||
modals.modelSelect = true
|
||||
nextTick(() => {
|
||||
insetMessage({
|
||||
id: uuidv4(),
|
||||
@@ -129,7 +142,7 @@ const handleClickSend = (event: any) => {
|
||||
keys: ['content']
|
||||
})
|
||||
useLLM(trimmedMessages, {
|
||||
modelTag: 'spark3_5'
|
||||
modelTag: currentModel.value
|
||||
}).then(reply => {
|
||||
modifyMessageContent(assistantReplyId, reply)
|
||||
}).catch(err => {
|
||||
@@ -188,8 +201,11 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div class="w-full flex relative">
|
||||
<div class="h-[calc(100vh-4rem)] bg-neutral-100 dark:bg-neutral-900 p-4 flex flex-col w-[300px]
|
||||
shadow-sidebar border-r border-transparent dark:border-neutral-700">
|
||||
<div
|
||||
class="absolute -translate-x-full md:sticky md:translate-x-0 z-10 flex flex-col h-[calc(100vh-4rem)] bg-neutral-100 dark:bg-neutral-900 p-4 w-full md:w-[300px]
|
||||
shadow-sidebar border-r border-transparent dark:border-neutral-700 transition-all duration-300 ease-out"
|
||||
:class="{'translate-x-0': showSidebar}"
|
||||
>
|
||||
<div class="flex-1 flex flex-col overflow-auto overflow-x-hidden">
|
||||
<!-- list -->
|
||||
<div class="flex flex-col gap-3 relative">
|
||||
@@ -225,8 +241,16 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-[calc(100vh-4rem)] bg-white dark:bg-neutral-900 flex-1 flex flex-col">
|
||||
<div class="w-full p-4 bg-neutral-50 dark:bg-neutral-800/50 border-b dark:border-neutral-700/50">
|
||||
{{ getSessionCopyById(currentSessionId!)?.subject || '新对话' }}
|
||||
<div class="w-full p-4 bg-neutral-50 dark:bg-neutral-800/50 border-b dark:border-neutral-700/50 flex items-center gap-2">
|
||||
<UButton
|
||||
class="md:hidden"
|
||||
color="black"
|
||||
variant="ghost"
|
||||
icon="i-tabler-menu-2"
|
||||
@click="showSidebar = !showSidebar"
|
||||
>
|
||||
</UButton>
|
||||
<h1 class="font-medium">{{ getSessionCopyById(currentSessionId!)?.subject || '新对话' }}</h1>
|
||||
</div>
|
||||
<div ref="messagesWrapperRef" class="flex-1 flex flex-col overflow-auto overflow-x-hidden">
|
||||
<div class="flex flex-col gap-8 px-4 py-8">
|
||||
@@ -241,7 +265,14 @@ onMounted(() => {
|
||||
</div>
|
||||
<div
|
||||
class="w-full p-4 pt-2 flex flex-col gap-2 bg-neutral-50 dark:bg-neutral-800/50 border-t dark:border-neutral-700/50">
|
||||
<div>action bar</div>
|
||||
<div class="flex items-center gap-2 overflow-auto overflow-y-hidden">
|
||||
<button class="chat-option-btn" @click="modals.modelSelect = true">
|
||||
<Icon name="tabler:robot-face"/>
|
||||
<span class="text-xs">
|
||||
{{ llmModels.find(m => m.tag === currentModel)?.name.toUpperCase() || '模型' }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<UTextarea
|
||||
v-model="user_input"
|
||||
@@ -266,6 +297,41 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modals -->
|
||||
<UModal v-model="modals.modelSelect">
|
||||
<UCard>
|
||||
<template #header>
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
选择大语言模型
|
||||
</h3>
|
||||
</template>
|
||||
|
||||
<div class="grid grid-cols-3 gap-4">
|
||||
<div
|
||||
v-for="(llm, index) in llmModels"
|
||||
:key="index"
|
||||
@click="currentModel = llm.tag"
|
||||
class="flex flex-col gap-2 justify-center items-center w-full aspect-[1/1] border-2 rounded-xl cursor-pointer transition duration-150 select-none"
|
||||
:class="llm.tag === currentModel ? 'border-primary shadow-xl bg-primary text-white' : 'dark:border-neutral-800 bg-white dark:bg-black shadow-card'"
|
||||
>
|
||||
<Icon :name="llm?.icon" class="text-4xl opacity-80"/>
|
||||
<div class="flex flex-col gap-0.5 items-center">
|
||||
<h1 class="font-bold drop-shadow opacity-90">{{ llm.name || 'unknown' }}</h1>
|
||||
<p class="text-xs opacity-60">{{ llm.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-end items-center" @click="modals.modelSelect = false">
|
||||
<UButton>
|
||||
确定
|
||||
</UButton>
|
||||
</div>
|
||||
</template>
|
||||
</UCard>
|
||||
</UModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -293,4 +359,10 @@ onMounted(() => {
|
||||
.chat-item-leave-active {
|
||||
@apply absolute inset-x-0;
|
||||
}
|
||||
|
||||
.chat-option-btn {
|
||||
@apply text-lg px-2 py-1.5 flex gap-1 justify-center items-center rounded-lg;
|
||||
@apply bg-white border border-neutral-300 shadow-sm hover:shadow-card;
|
||||
@apply dark:bg-neutral-800 dark:border-neutral-600;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user