feat: configurable question auto-generation (stored in additional_params) and manual trigger with UI refinements

This commit is contained in:
Wenjie Zhang 2025-11-30 18:48:33 +08:00
parent 18f641ea39
commit 1c4511a719
5 changed files with 104 additions and 25 deletions

View File

@ -134,12 +134,22 @@ async def update_database_info(
name: str = Body(...),
description: str = Body(...),
llm_info: dict = Body(None),
additional_params: dict = Body({}), # Now accepts a dict
current_user: User = Depends(get_admin_user),
):
"""更新知识库信息"""
logger.debug(f"Update database {db_id} info: {name}, {description}, llm_info: {llm_info}")
logger.debug(
f"Update database {db_id} info: {name}, {description}, llm_info: {llm_info}, "
f"additional_params: {additional_params}"
)
try:
database = await knowledge_base.update_database(db_id, name, description, llm_info)
database = await knowledge_base.update_database(
db_id,
name,
description,
llm_info,
additional_params=additional_params, # Pass the dict to the manager
)
return {"message": "更新成功", "database": database}
except Exception as e:
logger.error(f"更新数据库失败 {e}, {traceback.format_exc()}")

View File

@ -246,12 +246,16 @@ class KnowledgeBaseManager:
db_id = db_info["db_id"]
async with self._metadata_lock:
# 准备 additional_params包含 auto_generate_questions
saved_params = kwargs.copy()
saved_params["auto_generate_questions"] = False
self.global_databases_meta[db_id] = {
"name": database_name,
"description": description,
"kb_type": kb_type,
"created_at": utc_isoformat(),
"additional_params": kwargs.copy(),
"additional_params": saved_params,
}
self._save_global_metadata()
@ -303,9 +307,13 @@ class KnowledgeBaseManager:
# 添加全局元数据中的additional_params信息
if db_info and db_id in self.global_databases_meta:
global_meta = self.global_databases_meta[db_id]
additional_params = global_meta.get("additional_params", {})
if additional_params:
db_info["additional_params"] = additional_params
additional_params = global_meta.get("additional_params", {}).copy()
# 确保 auto_generate_questions 存在,默认为 False
if "auto_generate_questions" not in additional_params:
additional_params["auto_generate_questions"] = False
db_info["additional_params"] = additional_params
return db_info
except KBNotFoundError:
@ -371,7 +379,9 @@ class KnowledgeBaseManager:
return False
async def update_database(self, db_id: str, name: str, description: str, llm_info: dict = None) -> dict:
async def update_database(
self, db_id: str, name: str, description: str, llm_info: dict = None, additional_params: dict | None = None
) -> dict:
"""更新数据库"""
kb_instance = self._get_kb_for_database(db_id)
result = kb_instance.update_database(db_id, name, description, llm_info)
@ -380,6 +390,16 @@ class KnowledgeBaseManager:
if db_id in self.global_databases_meta:
self.global_databases_meta[db_id]["name"] = name
self.global_databases_meta[db_id]["description"] = description
# 合并现有的 additional_params 和新的 additional_params
existing_additional_params = self.global_databases_meta[db_id].get("additional_params", {})
if additional_params:
existing_additional_params.update(additional_params)
self.global_databases_meta[db_id]["additional_params"] = existing_additional_params
# 清理旧的 top-level key (如果存在)
self.global_databases_meta[db_id].pop("auto_generate_questions", None)
self._save_global_metadata()
return result

View File

@ -66,6 +66,12 @@
<a-form-item label="知识库描述" name="description">
<a-textarea v-model:value="editForm.description" placeholder="请输入知识库描述" :rows="4" />
</a-form-item>
<a-form-item label="自动生成问题" name="auto_generate_questions">
<a-switch v-model:checked="editForm.auto_generate_questions" checked-children="开启" un-checked-children="关闭" />
<span style="margin-left: 8px; font-size: 12px; color: var(--gray-500);">上传文件后自动生成测试问题</span>
</a-form-item>
<!-- 仅对 LightRAG 类型显示 LLM 配置 -->
<a-form-item v-if="database.kb_type === 'lightrag'" label="语言模型 (LLM)" name="llm_info">
<ModelSelectorComponent
@ -144,6 +150,7 @@ const editFormRef = ref(null);
const editForm = reactive({
name: '',
description: '',
auto_generate_questions: false,
llm_info: {
provider: '',
model_name: ''
@ -157,6 +164,8 @@ const rules = {
const showEditModal = () => {
editForm.name = database.value.name || '';
editForm.description = database.value.description || '';
editForm.auto_generate_questions = database.value.additional_params?.auto_generate_questions || false;
// LightRAG LLM
if (database.value.kb_type === 'lightrag') {
const llmInfo = database.value.llm_info || {};
@ -170,7 +179,10 @@ const handleEditSubmit = () => {
editFormRef.value.validate().then(async () => {
const updateData = {
name: editForm.name,
description: editForm.description
description: editForm.description,
additional_params: {
auto_generate_questions: editForm.auto_generate_questions
}
};
// LightRAG llm_info

View File

@ -14,18 +14,29 @@
/>
<div class="search-actions">
<div class="query-examples-compact">
<span class="examples-label">示例</span>
<div class="examples-label-group">
<a-tooltip title="点击手动生成测试问题" placement="bottom">
<a-button
type="text"
size="small"
class="examples-label-btn"
@click="() => generateSampleQuestions(false)"
>
示例<ReloadOutlined />:
</a-button>
</a-tooltip>
</div>
<div class="examples-container">
<!-- 加载中或生成中 -->
<div v-if="loadingQuestions || generatingQuestions" class="loading-text">
<a-spin size="small" />
<span>{{ generatingQuestions ? 'AI生成中...' : '加载中...' }}</span>
</div>
<!-- 示例轮播 -->
<transition v-else-if="queryExamples.length > 0" name="fade" mode="out-in">
<a-button
type="text"
type="link"
:key="currentExampleIndex"
@click="useQueryExample(queryExamples[currentExampleIndex])"
size="small"
@ -34,9 +45,9 @@
{{ queryExamples[currentExampleIndex] }}
</a-button>
</transition>
<!-- 空状态 - 添加文件后会自动生成 -->
<span v-else style="color: var(--gray-500); font-size: 12px;">添加文件后自动生成</span>
<span v-else style="color: var(--gray-500); font-size: 12px;">暂无问题请点击左侧按钮生成</span>
</div>
</div>
<div style="display: flex; gap: 12px; align-items: center;">
@ -136,6 +147,7 @@ import { message } from 'ant-design-vue';
import { queryApi } from '@/apis/knowledge_api';
import {
SearchOutlined,
ReloadOutlined,
} from '@ant-design/icons-vue';
const store = useDatabaseStore();
@ -170,7 +182,7 @@ let exampleCarouselInterval = null;
//
const loadSampleQuestions = async () => {
if (!store.database?.db_id) return;
try {
loadingQuestions.value = true;
const data = await queryApi.getSampleQuestions(store.database.db_id);
@ -202,7 +214,7 @@ const clearQuestions = () => {
//
const generateSampleQuestions = async (silent = false) => {
if (!store.database?.db_id) return;
try {
generatingQuestions.value = true;
const data = await queryApi.generateSampleQuestions(store.database.db_id, 10);
@ -311,10 +323,10 @@ const onQuery = async () => {
onMounted(async () => {
//
store.loadQueryParams();
//
await loadSampleQuestions();
//
if (queryExamples.value.length > 0) {
startExampleCarousel();
@ -583,10 +595,21 @@ defineExpose({
flex-wrap: wrap;
}
.examples-label {
font-size: 12px;
.examples-label-btn {
color: var(--gray-500);
white-space: nowrap;
font-size: 12px;
display: flex;
align-items: center;
margin-left: -8px;
&:hover {
color: var(--main-color);
background-color: var(--gray-100);
}
.anticon { /* Target Ant Design icons directly */
font-size: 10px; /* Make icon smaller */
}
}
.examples-container {
@ -607,8 +630,13 @@ defineExpose({
text-align: left;
white-space: normal;
height: auto;
padding: 4px 8px;
padding: 0;
font-size: 12px;
color: var(--gray-500);
&:hover {
color: var(--main-color);
}
}
.fade-enter-active,

View File

@ -214,15 +214,24 @@ watch(
setTimeout(async () => {
console.log('文件数量变化检查是否需要生成问题querySectionRef:', querySectionRef.value);
if (querySectionRef.value) {
console.log('开始重新生成问题...');
await querySectionRef.value.generateSampleQuestions(true);
//
if (database.value.additional_params?.auto_generate_questions) {
console.log('开始重新生成问题...');
await querySectionRef.value.generateSampleQuestions(true);
} else {
console.log('自动生成问题已关闭,跳过生成');
}
} else {
console.warn('querySectionRef 未准备好,稍后重试');
//
setTimeout(async () => {
if (querySectionRef.value) {
console.log('延迟后开始生成问题...');
await querySectionRef.value.generateSampleQuestions(true);
if (database.value.additional_params?.auto_generate_questions) {
console.log('延迟后开始生成问题...');
await querySectionRef.value.generateSampleQuestions(true);
} else {
console.log('自动生成问题已关闭,跳过生成');
}
}
}, 2000);
}