feat(对话): 扩展对话管理支持助手关联

- 对话创建接口支持关联助手ID和系统提示词
- 对话查询接口返回关联的助手信息
- 聊天接口支持使用助手系统提示词
- useConversations Hook 扩展助手相关参数
This commit is contained in:
gaoziman 2025-12-20 20:46:35 +08:00
parent 2d4bdfb7f5
commit a5fcc9edae
4 changed files with 48 additions and 7 deletions

View File

@ -269,15 +269,26 @@ export async function POST(request: Request) {
try { try {
const cchUrl = settings.cchUrl || 'http://localhost:13500'; const cchUrl = settings.cchUrl || 'http://localhost:13500';
// 获取系统提示词 // 获取系统提示词(叠加模式)
const baseSystemPrompt = conversation.systemPrompt || settings.systemPrompt || DEFAULT_SYSTEM_PROMPT; // 1. 始终使用 DEFAULT_SYSTEM_PROMPT 作为基础
// 2. 如果对话有关联助手的提示词conversation.systemPrompt则叠加到默认提示词后面
// 3. 助手提示词替代设置页面的自定义提示词,不替代默认提示词
const currentDate = new Date().toLocaleDateString('zh-CN', { const currentDate = new Date().toLocaleDateString('zh-CN', {
year: 'numeric', year: 'numeric',
month: 'long', month: 'long',
day: 'numeric', day: 'numeric',
weekday: 'long', weekday: 'long',
}); });
const systemPrompt = baseSystemPrompt.replace('{{CURRENT_DATE}}', currentDate); const basePrompt = DEFAULT_SYSTEM_PROMPT.replace('{{CURRENT_DATE}}', currentDate);
// 叠加助手提示词
let systemPrompt = basePrompt;
if (conversation.systemPrompt) {
systemPrompt = `${basePrompt}\n\n---\n\n## 🎭 当前助手角色设定\n\n${conversation.systemPrompt}`;
console.log('[API/chat] 🎭 使用助手提示词:', conversation.systemPrompt.substring(0, 100) + '...');
} else {
console.log('[API/chat] 📝 无助手提示词,使用默认提示词');
}
// 获取温度参数 // 获取温度参数
const temperature = parseFloat(conversation.temperature || settings.temperature || '0.7'); const temperature = parseFloat(conversation.temperature || settings.temperature || '0.7');

View File

@ -1,6 +1,6 @@
import { NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
import { db } from '@/drizzle/db'; import { db } from '@/drizzle/db';
import { conversations, messages } from '@/drizzle/schema'; import { conversations, messages, assistants } from '@/drizzle/schema';
import { eq, asc, and } from 'drizzle-orm'; import { eq, asc, and } from 'drizzle-orm';
import { getCurrentUser } from '@/lib/auth'; import { getCurrentUser } from '@/lib/auth';
@ -41,9 +41,23 @@ export async function GET(request: Request, { params }: RouteParams) {
orderBy: [asc(messages.createdAt)], orderBy: [asc(messages.createdAt)],
}); });
// 如果有关联助手,获取助手信息
let assistant = null;
if (conversation.assistantId) {
assistant = await db.query.assistants.findFirst({
where: eq(assistants.id, conversation.assistantId),
});
}
return NextResponse.json({ return NextResponse.json({
...conversation, ...conversation,
messages: messageList, messages: messageList,
assistant: assistant ? {
id: assistant.id,
name: assistant.name,
icon: assistant.icon,
description: assistant.description,
} : null,
}); });
} catch (error) { } catch (error) {
console.error('Failed to get conversation:', error); console.error('Failed to get conversation:', error);
@ -68,7 +82,7 @@ export async function PUT(request: Request, { params }: RouteParams) {
const { id } = await params; const { id } = await params;
const body = await request.json(); const body = await request.json();
const { title, isPinned, isArchived } = body; const { title, isPinned, isArchived, model } = body;
// 验证对话属于当前用户 // 验证对话属于当前用户
const existingConversation = await db.query.conversations.findFirst({ const existingConversation = await db.query.conversations.findFirst({
@ -101,6 +115,10 @@ export async function PUT(request: Request, { params }: RouteParams) {
updateData.isArchived = isArchived; updateData.isArchived = isArchived;
} }
if (model !== undefined) {
updateData.model = model;
}
const [updated] = await db const [updated] = await db
.update(conversations) .update(conversations)
.set(updateData) .set(updateData)

View File

@ -48,7 +48,7 @@ export async function POST(request: Request) {
} }
const body = await request.json(); const body = await request.json();
const { title, model, tools, enableThinking } = body; const { title, model, tools, enableThinking, assistantId, systemPrompt } = body;
const conversationId = nanoid(); const conversationId = nanoid();
@ -61,6 +61,8 @@ export async function POST(request: Request) {
tools: tools || [], tools: tools || [],
enableThinking: enableThinking || false, enableThinking: enableThinking || false,
userId: user.userId, // 关联当前用户 userId: user.userId, // 关联当前用户
assistantId: assistantId || null, // 关联助手
systemPrompt: systemPrompt || null, // 对话专属系统提示词(来自助手)
}) })
.returning(); .returning();

View File

@ -3,8 +3,16 @@
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect, useCallback } from 'react';
import type { Conversation, Message } from '@/drizzle/schema'; import type { Conversation, Message } from '@/drizzle/schema';
export interface AssistantInfo {
id: number;
name: string;
icon: string | null;
description: string | null;
}
export interface ConversationWithMessages extends Conversation { export interface ConversationWithMessages extends Conversation {
messages: Message[]; messages: Message[];
assistant?: AssistantInfo | null;
} }
export function useConversations() { export function useConversations() {
@ -34,6 +42,8 @@ export function useConversations() {
model: string; model: string;
tools?: string[]; tools?: string[];
enableThinking?: boolean; enableThinking?: boolean;
assistantId?: number;
systemPrompt?: string;
}) => { }) => {
try { try {
const response = await fetch('/api/conversations', { const response = await fetch('/api/conversations', {
@ -54,7 +64,7 @@ export function useConversations() {
const updateConversation = useCallback(async ( const updateConversation = useCallback(async (
conversationId: string, conversationId: string,
data: { title?: string; isPinned?: boolean; isArchived?: boolean } data: { title?: string; isPinned?: boolean; isArchived?: boolean; model?: string }
) => { ) => {
try { try {
const response = await fetch(`/api/conversations/${conversationId}`, { const response = await fetch(`/api/conversations/${conversationId}`, {