fix: 对话配置扁平化+启用联网搜索移到对话配置
对话配置改为单配置: - 只有一个默认配置,所有用户共用 - 去掉添加/删除配置按钮和逻辑 - 直接编辑保存配置 配置参数扁平化: - enable_search 启用联网搜索开关 - LLM配置、可用工具、历史记录数、Temperature、系统提示词 启用联网搜索开关: - 从系统设置移到对话配置页面 - 开关自动添加/移除 search 工具 系统设置简化: - 去掉启用联网搜索开关 - 提示用户去对话配置页面设置
This commit is contained in:
@@ -102,11 +102,12 @@ def init_db():
|
||||
config_id TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
llm_config_id INTEGER,
|
||||
enable_search INTEGER DEFAULT 1,
|
||||
enable_tools TEXT,
|
||||
max_history INTEGER DEFAULT 20,
|
||||
temperature REAL DEFAULT 0.7,
|
||||
system_prompt TEXT,
|
||||
is_default INTEGER DEFAULT 0,
|
||||
is_default INTEGER DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (llm_config_id) REFERENCES llm_configs(id)
|
||||
@@ -423,67 +424,41 @@ def delete_agent(agent_id):
|
||||
# ==================== 对话配置管理 ====================
|
||||
|
||||
@app.route('/api/admin/chat', methods=['GET'])
|
||||
def get_chat_configs():
|
||||
"""获取对话配置"""
|
||||
def get_chat_config():
|
||||
"""获取对话配置(只有一个默认配置)"""
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT * FROM chat_configs ORDER BY is_default DESC')
|
||||
configs = [dict(row) for row in cursor.fetchall()]
|
||||
cursor.execute('SELECT * FROM chat_configs WHERE is_default=1 LIMIT 1')
|
||||
config = cursor.fetchone()
|
||||
|
||||
if not config:
|
||||
# 如果没有配置,创建默认配置
|
||||
cursor.execute('''
|
||||
INSERT INTO chat_configs (config_id, name, llm_config_id, enable_search, enable_tools, max_history, temperature, is_default)
|
||||
VALUES ('default', '默认配置', 1, 1, 'search', 20, 0.7, 1)
|
||||
''')
|
||||
conn.commit()
|
||||
cursor.execute('SELECT * FROM chat_configs WHERE is_default=1 LIMIT 1')
|
||||
config = cursor.fetchone()
|
||||
|
||||
conn.close()
|
||||
return jsonify(configs)
|
||||
return jsonify(dict(config) if config else {})
|
||||
|
||||
|
||||
@app.route('/api/admin/chat', methods=['POST'])
|
||||
def add_chat_config():
|
||||
"""添加对话配置"""
|
||||
data = request.json
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('''
|
||||
INSERT INTO chat_configs (config_id, name, llm_config_id, enable_tools, max_history, temperature, system_prompt)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
''', (data['config_id'], data['name'], data.get('llm_config_id'), data.get('enable_tools', ''),
|
||||
data.get('max_history', 20), data.get('temperature', 0.7), data.get('system_prompt', '')))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return jsonify({'success': True})
|
||||
|
||||
|
||||
@app.route('/api/admin/chat/<config_id>', methods=['PUT'])
|
||||
def update_chat_config(config_id):
|
||||
@app.route('/api/admin/chat', methods=['PUT'])
|
||||
def update_chat_config():
|
||||
"""更新对话配置"""
|
||||
data = request.json
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('''
|
||||
UPDATE chat_configs SET name=?, llm_config_id=?, enable_tools=?, max_history=?,
|
||||
temperature=?, system_prompt=?, updated_at=CURRENT_TIMESTAMP WHERE config_id=?
|
||||
''', (data['name'], data.get('llm_config_id'), data.get('enable_tools', ''),
|
||||
data.get('max_history', 20), data.get('temperature', 0.7),
|
||||
data.get('system_prompt', ''), config_id))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return jsonify({'success': True})
|
||||
|
||||
|
||||
@app.route('/api/admin/chat/<config_id>', methods=['DELETE'])
|
||||
def delete_chat_config(config_id):
|
||||
"""删除对话配置"""
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('DELETE FROM chat_configs WHERE config_id=?', (config_id,))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return jsonify({'success': True})
|
||||
|
||||
|
||||
@app.route('/api/admin/chat/<config_id>/default', methods=['POST'])
|
||||
def set_default_chat(config_id):
|
||||
"""设置默认对话配置"""
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('UPDATE chat_configs SET is_default=0')
|
||||
cursor.execute('UPDATE chat_configs SET is_default=1 WHERE config_id=?', (config_id,))
|
||||
UPDATE chat_configs SET
|
||||
llm_config_id=?, enable_search=?, enable_tools=?, max_history=?,
|
||||
temperature=?, system_prompt=?, updated_at=CURRENT_TIMESTAMP
|
||||
WHERE is_default=1
|
||||
''', (data.get('llm_config_id', 1), data.get('enable_search', 1),
|
||||
data.get('enable_tools', 'search'), data.get('max_history', 20),
|
||||
data.get('temperature', 0.7), data.get('system_prompt', '')))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return jsonify({'success': True})
|
||||
|
||||
248
www/admin.js
248
www/admin.js
@@ -586,186 +586,113 @@ async function deleteAgent(agentId) {
|
||||
// ==================== 对话配置页面 ====================
|
||||
|
||||
async function loadChatConfigPage(content) {
|
||||
chatConfigs = await fetchAPI('/api/admin/chat');
|
||||
llmConfigs = await fetchAPI('/api/admin/llm');
|
||||
toolConfigs = await fetchAPI('/api/admin/tools');
|
||||
const chatConfig = await fetchAPI('/api/admin/chat');
|
||||
|
||||
content.innerHTML = `
|
||||
<div class="content-header">
|
||||
<h1 class="content-title">对话配置</h1>
|
||||
<button class="add-btn" onclick="showAddChatConfigModal()">+ 添加配置</button>
|
||||
</div>
|
||||
|
||||
<div class="data-table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>配置名称</th>
|
||||
<th>LLM</th>
|
||||
<th>可用工具</th>
|
||||
<th>历史记录数</th>
|
||||
<th>Temperature</th>
|
||||
<th>状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${chatConfigs.map(c => `
|
||||
<tr>
|
||||
<td>${c.name} ${c.is_default ? '<span class="default-badge">默认</span>' : ''}</td>
|
||||
<td>${llmConfigs.find(l => l.id === c.llm_config_id)?.name || '未指定'}</td>
|
||||
<td>${c.enable_tools || '无'}</td>
|
||||
<td>${c.max_history || 20}</td>
|
||||
<td>${c.temperature || 0.7}</td>
|
||||
<td>${c.is_default ? '✅ 默认' : '-'}</td>
|
||||
<td>
|
||||
<div class="action-btns">
|
||||
<button class="action-btn edit" onclick="showEditChatConfigModal('${c.config_id}')">编辑</button>
|
||||
${!c.is_default ? `<button class="action-btn default" onclick="setDefaultChatConfig('${c.config_id}')">设为默认</button>` : ''}
|
||||
<button class="action-btn delete" onclick="deleteChatConfig('${c.config_id}')">删除</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('')}
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="background: white; padding: 24px; border-radius: 12px;">
|
||||
<p style="color: #718096; margin-bottom: 24px;">
|
||||
此配置对所有用户的普通对话生效,修改后立即生效。
|
||||
</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">LLM 配置(对话使用的大模型)</label>
|
||||
<select class="form-select" id="chatLLMConfig">
|
||||
${llmConfigs.map(l => `<option value="${l.id}" ${l.id === chatConfig.llm_config_id ? 'selected' : ''}>${l.name}</option>`).join('')}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label style="display: flex; align-items: center; gap: 8px;">
|
||||
<input type="checkbox" id="chatEnableSearch" ${chatConfig.enable_search ? 'checked' : ''} onchange="toggleEnableSearch()">
|
||||
启用联网搜索
|
||||
</label>
|
||||
<span style="color: #999; font-size: 12px; margin-top: 4px;">开启后对话可联网搜索实时信息</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">可用工具(逗号分隔)</label>
|
||||
<input type="text" class="form-input" id="chatEnableTools" value="${chatConfig.enable_tools || ''}" placeholder="如:search,calculator">
|
||||
<span style="color: #999; font-size: 12px;">已配置工具: ${toolConfigs.map(t => t.tool_id).join(', ')}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">历史记录数(对话上下文)</label>
|
||||
<input type="number" class="form-input" id="chatMaxHistory" value="${chatConfig.max_history || 20}">
|
||||
<span style="color: #999; font-size: 12px;">发送给模型的对话历史条数</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Temperature(创造性)</label>
|
||||
<input type="number" class="form-input" id="chatTemperature" value="${chatConfig.temperature || 0.7}" step="0.1" min="0" max="2">
|
||||
<span style="color: #999; font-size: 12px;">0-2之间,越高越随机创造性,越低越稳定精确</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">系统提示词(可选)</label>
|
||||
<textarea class="form-textarea" id="chatSystemPrompt" placeholder="全局系统提示词,对所有对话生效">${chatConfig.system_prompt || ''}</textarea>
|
||||
</div>
|
||||
|
||||
<button class="form-submit" onclick="saveChatConfig()">保存配置</button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 24px; padding: 16px; background: white; border-radius: 12px;">
|
||||
<h3 style="margin-bottom: 16px;">对话配置说明</h3>
|
||||
<p style="color: #718096; font-size: 14px;">
|
||||
对话配置用于控制普通对话的各项参数。可以选择使用的大模型接口、启用的工具、历史记录数量等。
|
||||
前端 APP 会自动使用默认配置进行对话。
|
||||
</p>
|
||||
<h3 style="margin-bottom: 16px;">参数说明</h3>
|
||||
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px;">
|
||||
<div style="padding: 12px; background: #f5f7fa; border-radius: 8px;">
|
||||
<strong>🧠 LLM配置</strong>
|
||||
<p style="color: #718096; font-size: 12px; margin-top: 4px;">选择对话使用的大模型接口</p>
|
||||
</div>
|
||||
<div style="padding: 12px; background: #f5f7fa; border-radius: 8px;">
|
||||
<strong>🔍 启用联网搜索</strong>
|
||||
<p style="color: #718096; font-size: 12px; margin-top: 4px;">用户可在对话中开启联网搜索</p>
|
||||
</div>
|
||||
<div style="padding: 12px; background: #f5f7fa; border-radius: 8px;">
|
||||
<strong>🔧 可用工具</strong>
|
||||
<p style="color: #718096; font-size: 12px; margin-top: 4px;">对话中可使用的工具列表</p>
|
||||
</div>
|
||||
<div style="padding: 12px; background: #f5f7fa; border-radius: 8px;">
|
||||
<strong>📜 历史记录数</strong>
|
||||
<p style="color: #718096; font-size: 12px; margin-top: 4px;">发送多少条历史对话给模型</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function showAddChatConfigModal() {
|
||||
showModal('添加对话配置', `
|
||||
<div class="form-group">
|
||||
<label class="form-label">配置ID</label>
|
||||
<input type="text" class="form-input" id="chatConfigId" placeholder="如:default">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">配置名称</label>
|
||||
<input type="text" class="form-input" id="chatConfigName" placeholder="如:默认对话配置">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">LLM 配置</label>
|
||||
<select class="form-select" id="chatLLMConfig">
|
||||
${llmConfigs.map(l => `<option value="${l.id}">${l.name}</option>`).join('')}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">可用工具(逗号分隔)</label>
|
||||
<input type="text" class="form-input" id="chatEnableTools" placeholder="如:search,calculator">
|
||||
<span style="color: #999; font-size: 12px;">可用工具: ${toolConfigs.map(t => t.tool_id).join(', ')}</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">历史记录数</label>
|
||||
<input type="number" class="form-input" id="chatMaxHistory" value="20">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Temperature</label>
|
||||
<input type="number" class="form-input" id="chatTemperature" value="0.7" step="0.1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">系统提示词(可选)</label>
|
||||
<textarea class="form-textarea" id="chatSystemPrompt" placeholder="全局系统提示词"></textarea>
|
||||
</div>
|
||||
<button class="form-submit" onclick="saveChatConfig()">保存</button>
|
||||
`);
|
||||
}
|
||||
|
||||
function showEditChatConfigModal(configId) {
|
||||
const config = chatConfigs.find(c => c.config_id === configId);
|
||||
if (!config) return;
|
||||
function toggleEnableSearch() {
|
||||
const enableSearch = document.getElementById('chatEnableSearch').checked;
|
||||
const toolsInput = document.getElementById('chatEnableTools');
|
||||
|
||||
showModal('编辑对话配置', `
|
||||
<div class="form-group">
|
||||
<label class="form-label">配置ID(不可修改)</label>
|
||||
<input type="text" class="form-input" id="chatConfigId" value="${config.config_id}" readonly style="background: #f5f7fa;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">配置名称</label>
|
||||
<input type="text" class="form-input" id="chatConfigName" value="${config.name}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">LLM 配置</label>
|
||||
<select class="form-select" id="chatLLMConfig">
|
||||
${llmConfigs.map(l => `<option value="${l.id}" ${l.id === config.llm_config_id ? 'selected' : ''}>${l.name}</option>`).join('')}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">可用工具(逗号分隔)</label>
|
||||
<input type="text" class="form-input" id="chatEnableTools" value="${config.enable_tools || ''}">
|
||||
<span style="color: #999; font-size: 12px;">可用工具: ${toolConfigs.map(t => t.tool_id).join(', ')}</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">历史记录数</label>
|
||||
<input type="number" class="form-input" id="chatMaxHistory" value="${config.max_history || 20}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Temperature</label>
|
||||
<input type="number" class="form-input" id="chatTemperature" value="${config.temperature || 0.7}" step="0.1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">系统提示词(可选)</label>
|
||||
<textarea class="form-textarea" id="chatSystemPrompt">${config.system_prompt || ''}</textarea>
|
||||
</div>
|
||||
<button class="form-submit" onclick="updateChatConfig('${configId}')">保存</button>
|
||||
`);
|
||||
// 自动添加/移除 search 工具
|
||||
let tools = toolsInput.value.split(',').filter(t => t.trim());
|
||||
if (enableSearch) {
|
||||
if (!tools.includes('search')) {
|
||||
tools.push('search');
|
||||
}
|
||||
} else {
|
||||
tools = tools.filter(t => t !== 'search');
|
||||
}
|
||||
toolsInput.value = tools.join(',');
|
||||
}
|
||||
|
||||
async function saveChatConfig() {
|
||||
const data = {
|
||||
config_id: document.getElementById('chatConfigId').value,
|
||||
name: document.getElementById('chatConfigName').value,
|
||||
llm_config_id: parseInt(document.getElementById('chatLLMConfig').value),
|
||||
enable_search: document.getElementById('chatEnableSearch').checked ? 1 : 0,
|
||||
enable_tools: document.getElementById('chatEnableTools').value,
|
||||
max_history: parseInt(document.getElementById('chatMaxHistory').value),
|
||||
temperature: parseFloat(document.getElementById('chatTemperature').value),
|
||||
system_prompt: document.getElementById('chatSystemPrompt').value
|
||||
};
|
||||
|
||||
if (!data.config_id || !data.name) {
|
||||
showToast('请填写完整信息');
|
||||
return;
|
||||
}
|
||||
|
||||
await fetchAPI('/api/admin/chat', 'POST', data);
|
||||
closeModal();
|
||||
showToast('添加成功');
|
||||
loadPage('chat');
|
||||
}
|
||||
|
||||
async function updateChatConfig(configId) {
|
||||
const data = {
|
||||
name: document.getElementById('chatConfigName').value,
|
||||
llm_config_id: parseInt(document.getElementById('chatLLMConfig').value),
|
||||
enable_tools: document.getElementById('chatEnableTools').value,
|
||||
max_history: parseInt(document.getElementById('chatMaxHistory').value),
|
||||
temperature: parseFloat(document.getElementById('chatTemperature').value),
|
||||
system_prompt: document.getElementById('chatSystemPrompt').value
|
||||
};
|
||||
|
||||
await fetchAPI(`/api/admin/chat/${configId}`, 'PUT', data);
|
||||
closeModal();
|
||||
showToast('更新成功');
|
||||
loadPage('chat');
|
||||
}
|
||||
|
||||
async function setDefaultChatConfig(configId) {
|
||||
await fetchAPI(`/api/admin/chat/${configId}/default`, 'POST');
|
||||
showToast('已设为默认');
|
||||
loadPage('chat');
|
||||
}
|
||||
|
||||
async function deleteChatConfig(configId) {
|
||||
if (!confirm('确定删除此配置?')) return;
|
||||
await fetchAPI(`/api/admin/chat/${configId}`, 'DELETE');
|
||||
showToast('删除成功');
|
||||
await fetchAPI('/api/admin/chat', 'PUT', data);
|
||||
showToast('保存成功');
|
||||
loadPage('chat');
|
||||
}
|
||||
|
||||
@@ -1013,13 +940,6 @@ async function loadSystemPage(content) {
|
||||
<input type="text" class="form-input" id="appVersion" value="${systemConfigs.app_version?.value || ''}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label style="display: flex; align-items: center; gap: 8px;">
|
||||
<input type="checkbox" id="enableSearch" ${systemConfigs.enable_search?.value === 'true' ? 'checked' : ''}>
|
||||
启用联网搜索
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<h3 style="margin: 24px 0 16px; padding-top: 16px; border-top: 1px solid #e2e8f0;">游客使用限制</h3>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -1046,6 +966,12 @@ async function loadSystemPage(content) {
|
||||
|
||||
<button class="form-submit" onclick="saveSystemConfig()">保存设置</button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 16px; padding: 12px; background: #f5f7fa; border-radius: 8px;">
|
||||
<p style="color: #718096; font-size: 13px;">
|
||||
💡 提示:启用联网搜索等对话相关配置请前往"对话配置"页面设置
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -1053,7 +979,6 @@ async function saveSystemConfig() {
|
||||
const data = {
|
||||
app_name: document.getElementById('appName').value,
|
||||
app_version: document.getElementById('appVersion').value,
|
||||
enable_search: document.getElementById('enableSearch').checked ? 'true' : 'false',
|
||||
guest_chat_sessions: document.getElementById('guestChatSessions').value,
|
||||
guest_chat_messages: document.getElementById('guestChatMessages').value,
|
||||
guest_agent_messages: document.getElementById('guestAgentMessages').value,
|
||||
@@ -1062,7 +987,6 @@ async function saveSystemConfig() {
|
||||
|
||||
await fetchAPI('/api/admin/system', 'POST', data);
|
||||
showToast('保存成功');
|
||||
loadPage('system');
|
||||
}
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
Reference in New Issue
Block a user