feat: 添加生成对话标题功能,支持根据内容自动生成简短标题,使用 fast_model
This commit is contained in:
parent
74229c05a4
commit
53e0ed37f6
@ -47,11 +47,11 @@ class Config(BaseModel):
|
||||
# 模型配置
|
||||
# ============================================================
|
||||
default_model: str = Field(
|
||||
default="siliconflow/Pro/deepseek-ai/DeepSeek-V3.2",
|
||||
default="siliconflow/Pro/MiniMaxAI/MiniMax-M2.5",
|
||||
description="默认对话模型",
|
||||
)
|
||||
fast_model: str = Field(
|
||||
default="siliconflow/Qwen/Qwen3.5-9B",
|
||||
default="siliconflow/Pro/MiniMaxAI/MiniMax-M2.5",
|
||||
description="快速响应模型",
|
||||
)
|
||||
embed_model: str = Field(
|
||||
@ -63,7 +63,7 @@ class Config(BaseModel):
|
||||
description="默认 Re-Ranker 模型",
|
||||
)
|
||||
content_guard_llm_model: str = Field(
|
||||
default="siliconflow/Qwen/Qwen3.5-9B",
|
||||
default="siliconflow/Pro/MiniMaxAI/MiniMax-M2.5",
|
||||
description="内容审查LLM模型",
|
||||
)
|
||||
|
||||
|
||||
@ -52,6 +52,20 @@ export const agentApi = {
|
||||
*/
|
||||
simpleCall: (query) => apiPost('/api/chat/call', { query }),
|
||||
|
||||
/**
|
||||
* 生成对话标题
|
||||
* @param {string} query - 查询内容
|
||||
* @param {Object} modelSpec - 模型配置
|
||||
* @returns {Promise<string>} - 生成的标题
|
||||
*/
|
||||
generateTitle: async (query, modelSpec) => {
|
||||
const response = await apiPost('/api/chat/call', {
|
||||
query: `根据以下对话内容生成一个简短的标题(最多30个字符,中英文均可),不要包含 markdown 标记:\n\n${query.slice(0, 2000)}`,
|
||||
meta: { model_spec: modelSpec }
|
||||
})
|
||||
return response.response
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取默认智能体
|
||||
* @returns {Promise} - 默认智能体信息
|
||||
|
||||
@ -63,6 +63,12 @@
|
||||
<MessageCirclePlus v-else class="nav-btn-icon" size="16" />
|
||||
<span class="text">新对话</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="currentThread?.title && currentThread.title !== '新的对话'"
|
||||
class="conversation-title"
|
||||
>
|
||||
{{ currentThread.title }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="header__right">
|
||||
<UserInfoComponent v-if="!userStore.isAdmin" />
|
||||
@ -227,6 +233,7 @@ import { useAgentStore } from '@/stores/agent'
|
||||
import { useChatUIStore } from '@/stores/chatUI'
|
||||
import { useInfoStore } from '@/stores/info'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { MessageProcessor } from '@/utils/messageProcessor'
|
||||
import { agentApi, threadApi } from '@/apis'
|
||||
@ -250,6 +257,7 @@ const agentStore = useAgentStore()
|
||||
const chatUIStore = useChatUIStore()
|
||||
const infoStore = useInfoStore()
|
||||
const userStore = useUserStore()
|
||||
const configStore = useConfigStore()
|
||||
const {
|
||||
agents,
|
||||
selectedAgentId,
|
||||
@ -798,11 +806,24 @@ const sendMessage = async ({
|
||||
return Promise.reject(error)
|
||||
}
|
||||
|
||||
// 如果是新对话,用消息内容作为标题
|
||||
// 如果是新对话,用 fast-model 异步生成标题(不阻塞消息发送)
|
||||
if ((threadMessages.value[threadId] || []).length === 0) {
|
||||
const autoTitle = text.replace(/\s+/g, ' ').trim().slice(0, 255)
|
||||
const autoTitle = text.replace(/\s+/g, ' ').trim().slice(0, 2000)
|
||||
if (autoTitle) {
|
||||
void updateThread(threadId, autoTitle).catch(() => {})
|
||||
void (async () => {
|
||||
try {
|
||||
const generatedTitle = await agentApi.generateTitle(autoTitle, configStore.config?.fast_model)
|
||||
if (generatedTitle) {
|
||||
const finalTitle = generatedTitle.slice(0, 30).replace(/\s+/g, ' ').trim()
|
||||
if (finalTitle) {
|
||||
void updateThread(threadId, finalTitle).catch(() => {})
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// 失败时使用原始文本作为标题
|
||||
void updateThread(threadId, autoTitle.slice(0, 30)).catch(() => {})
|
||||
}
|
||||
})()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1017,9 +1038,22 @@ const handleSendMessage = async ({ image } = {}) => {
|
||||
|
||||
if (useRunsApi) {
|
||||
if ((threadMessages.value[threadId] || []).length === 0) {
|
||||
const autoTitle = text.replace(/\s+/g, ' ').trim().slice(0, 255)
|
||||
const autoTitle = text.replace(/\s+/g, ' ').trim().slice(0, 2000)
|
||||
if (autoTitle) {
|
||||
void updateThread(threadId, autoTitle).catch(() => {})
|
||||
void (async () => {
|
||||
try {
|
||||
const generatedTitle = await agentApi.generateTitle(autoTitle, configStore.config?.fast_model)
|
||||
if (generatedTitle) {
|
||||
const finalTitle = generatedTitle.slice(0, 30).replace(/\s+/g, ' ').trim()
|
||||
if (finalTitle) {
|
||||
void updateThread(threadId, finalTitle).catch(() => {})
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// 失败时使用原始文本作为标题
|
||||
void updateThread(threadId, autoTitle.slice(0, 30)).catch(() => {})
|
||||
}
|
||||
})()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1459,6 +1493,17 @@ watch(
|
||||
.sidebar-logo-toggle:hover .sidebar-expand-overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.conversation-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--text-primary);
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user