feat: 新增停止大模型回答功能(关联 Issue #104)

This commit is contained in:
zhaoshibao 2025-03-30 12:08:32 +08:00
commit 964e5f9079
5 changed files with 104 additions and 23 deletions

View File

@ -1,7 +1,8 @@
source "https://rubygems.org" source "https://rubygems.org"
gem "jekyll", "~> 4.3.2" gem "jekyll", "~> 4.3.2"
gem "just-the-docs", "~> 0.5.0" # gem "just-the-docs", "~> 0.5.0"
gem "minima", "~> 2.5"
group :jekyll_plugins do group :jekyll_plugins do
gem "jekyll-include-cache" gem "jekyll-include-cache"

View File

@ -1,4 +1,4 @@
remote_theme: just-the-docs/just-the-docs # remote_theme: just-the-docs/just-the-docs
url: https://xerrors.github.io/Yuxi-Know url: https://xerrors.github.io/Yuxi-Know
baseurl: /Yuxi-Know baseurl: /Yuxi-Know
title: 语析 - 基于大模型的知识库与知识图谱问答系统 title: 语析 - 基于大模型的知识库与知识图谱问答系统

View File

@ -1,5 +1,5 @@
--- ---
layout: home layout: default
title: 语析 - 基于大模型的知识库与知识图谱问答系统 title: 语析 - 基于大模型的知识库与知识图谱问答系统
nav_order: 1 nav_order: 1
description: "语析是一个强大的问答平台,结合了大模型 RAG 知识库与知识图谱技术,基于 Llamaindex + VueJS + FastAPI + Neo4j 构建。" description: "语析是一个强大的问答平台,结合了大模型 RAG 知识库与知识图谱技术,基于 Llamaindex + VueJS + FastAPI + Neo4j 构建。"

View File

@ -9,11 +9,29 @@
> >
<MenuOutlined /> <MenuOutlined />
</div> </div>
<a-tooltip :title="configStore.config?.model_name" placement="rightTop">
<div class="newchat nav-btn" @click="$emit('newconv')"> <div class="newchat nav-btn" @click="$emit('newconv')">
<PlusCircleOutlined /> <span class="text">新对话</span> <PlusCircleOutlined /> <span class="text">新对话</span>
</div> </div>
</a-tooltip> <a-dropdown>
<a class="model-select nav-btn" @click.prevent>
<BulbOutlined /> <span class="text">{{ configStore.config?.model_provider }}/{{ configStore.config?.model_name }}</span>
</a>
<template #overlay>
<a-menu class="scrollable-menu">
<a-menu-item-group v-for="(item, key) in modelKeys" :key="key" :title="modelNames[item]?.name">
<a-menu-item v-for="(model, idx) in modelNames[item]?.models" :key="`${item}-${idx}`" @click="selectModel(item, model)">
{{ item }}/{{ model }}
</a-menu-item>
</a-menu-item-group>
<a-menu-item-group v-if="customModels.length > 0" title="自定义模型">
<a-menu-item v-for="(model, idx) in customModels" :key="`custom-${idx}`" @click="selectModel('custom', model.custom_id)">
custom/{{ model.custom_id }}
</a-menu-item>
</a-menu-item-group>
</a-menu>
</template>
</a-dropdown>
</div> </div>
<div class="header__right"> <div class="header__right">
<div class="nav-btn text" @click="opts.showPanel = !opts.showPanel"> <div class="nav-btn text" @click="opts.showPanel = !opts.showPanel">
@ -179,7 +197,7 @@
</template> </template>
<script setup> <script setup>
import { reactive, ref, onMounted, toRefs, nextTick, onUnmounted, watch } from 'vue' import { reactive, ref, onMounted, toRefs, nextTick, onUnmounted, watch, computed } from 'vue'
import { import {
SendOutlined, SendOutlined,
MenuOutlined, MenuOutlined,
@ -199,7 +217,7 @@ import {
FolderOpenOutlined, FolderOpenOutlined,
GlobalOutlined, GlobalOutlined,
FileTextOutlined, FileTextOutlined,
RobotOutlined, BulbOutlined,
CaretRightOutlined, CaretRightOutlined,
DeploymentUnitOutlined, DeploymentUnitOutlined,
StopOutlined StopOutlined
@ -638,6 +656,7 @@ watch(
{ deep: true } { deep: true }
); );
<<<<<<< HEAD
// //
const handleSendOrStop = () => { const handleSendOrStop = () => {
if (isStreaming.value) { if (isStreaming.value) {
@ -666,6 +685,22 @@ const retryStoppedMessage = (message) => {
conv.value.messages = conv.value.messages.slice(0, messageIndex); conv.value.messages = conv.value.messages.slice(0, messageIndex);
} }
} }
=======
const modelNames = computed(() => configStore.config?.model_names)
const modelStatus = computed(() => configStore.config?.model_provider_status)
const customModels = computed(() => configStore.config?.custom_models || [])
// modelStatus key
const modelKeys = computed(() => {
return Object.keys(modelStatus.value || {}).filter(key => modelStatus.value?.[key])
})
//
const selectModel = (provider, name) => {
configStore.setConfigValue('model_provider', provider)
configStore.setConfigValue('model_name', name)
message.success(`已切换到模型: ${provider}/${name}`)
>>>>>>> 2cec299306b323c10368dd3af82c110753ae963b
} }
</script> </script>
@ -709,9 +744,9 @@ const retryStoppedMessage = (message) => {
border-radius: 8px; border-radius: 8px;
color: var(--gray-900); color: var(--gray-900);
cursor: pointer; cursor: pointer;
font-size: 1rem; // font-size: 1rem;
width: auto; width: auto;
padding: 0.5rem 1rem; padding: 0.5rem 0.75rem;
.text { .text {
margin-left: 10px; margin-left: 10px;
@ -722,6 +757,18 @@ const retryStoppedMessage = (message) => {
} }
} }
.model-select {
// color: var(--gray-900);
max-width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.text {
overflow: hidden;
text-overflow: ellipsis;
}
}
} }
.metas { .metas {
display: flex; display: flex;
@ -1170,6 +1217,7 @@ const retryStoppedMessage = (message) => {
} }
} }
<<<<<<< HEAD
.retry-hint { .retry-hint {
margin-top: 8px; margin-top: 8px;
padding: 8px 16px; padding: 8px 16px;
@ -1195,6 +1243,28 @@ const retryStoppedMessage = (message) => {
&:hover { &:hover {
background-color: #ff7875 !important; background-color: #ff7875 !important;
} }
=======
.scrollable-menu {
max-height: 300px;
overflow-y: auto;
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-track {
background: transparent;
border-radius: 3px;
}
&::-webkit-scrollbar-thumb {
background: var(--gray-400);
border-radius: 3px;
}
&::-webkit-scrollbar-thumb:hover {
background: var(--gray-500);
>>>>>>> 2cec299306b323c10368dd3af82c110753ae963b
} }
} }
</style> </style>
@ -1249,4 +1319,14 @@ const retryStoppedMessage = (message) => {
} }
</style> </style>
<style lang="less">
// dropdown
.ant-dropdown-menu {
&.scrollable-menu {
max-height: 300px;
overflow-y: auto;
}
}
</style>

View File

@ -94,7 +94,7 @@
</div> </div>
<div class="setting" v-if="state.windowWidth <= 520 || state.section === 'model'"> <div class="setting" v-if="state.windowWidth <= 520 || state.section === 'model'">
<h3>模型配置</h3> <h3>模型配置</h3>
<p>请在 <code>src/.env</code> 文件中配置对应的 APIKEY</p> <p>请在 <code>src/.env</code> 文件中配置对应的 APIKEY并重新启动服务</p>
<div class="model-provider-card"> <div class="model-provider-card">
<div class="card-header"> <div class="card-header">
<h3>自定义模型</h3> <h3>自定义模型</h3>