fix(rag): default search to keyword and rebuild saved roots

This commit is contained in:
lix-2026
2026-06-09 09:32:36 +08:00
parent 8e3be8b0b7
commit 516121e6f9
4 changed files with 50 additions and 10 deletions
@@ -670,7 +670,7 @@ export function createSidebarPageSettingsRuntime(context) {
'</div>' + '</div>' +
'<div class="wolai-page-settings-index-actions">' + '<div class="wolai-page-settings-index-actions">' +
'<button type="button" data-knowledge-rag-action="refresh">刷新状态</button>' + '<button type="button" data-knowledge-rag-action="refresh">刷新状态</button>' +
'<button type="button" data-knowledge-rag-action="ingest">索引来源</button>' + '<button type="button" data-knowledge-rag-action="ingest">索引/重建来源</button>' +
'<button type="button" data-knowledge-rag-action="prune">清除失效记录</button>' + '<button type="button" data-knowledge-rag-action="prune">清除失效记录</button>' +
'<button type="button" data-knowledge-rag-action="open-dashboard">打开 LightRAG</button>' + '<button type="button" data-knowledge-rag-action="open-dashboard">打开 LightRAG</button>' +
'</div>' + '</div>' +
@@ -1058,6 +1058,17 @@ export function createSidebarPageSettingsRuntime(context) {
}); });
} }
function knowledgeRagIndexedRootValues() {
var status = currentKnowledgeRagSummary().status || {};
var registry = status.registry && typeof status.registry === 'object' ? status.registry : {};
var roots = Array.isArray(registry.indexedRoots) ? registry.indexedRoots : [];
return roots.map(function(root) {
return String(root && (root.rootRelativePath || root.root_relative_path) || '').trim();
}).filter(Boolean).filter(function(value, index, list) {
return list.indexOf(value) === index;
});
}
function knowledgeRagCurrentFilter() { function knowledgeRagCurrentFilter() {
return pageUiState.knowledgeRagSourceFilter || 'attention'; return pageUiState.knowledgeRagSourceFilter || 'attention';
} }
@@ -1503,11 +1514,12 @@ export function createSidebarPageSettingsRuntime(context) {
async function ingestKnowledgeRagSources() { async function ingestKnowledgeRagSources() {
if (!knowledgeRagIsAvailable()) return; if (!knowledgeRagIsAvailable()) return;
var sources = knowledgeRagSourceInputValues(); var sources = knowledgeRagSourceInputValues();
if (!sources.length) sources = knowledgeRagIndexedRootValues();
if (!sources.length) { if (!sources.length) {
pageUiState.knowledgeRagSummary = Object.assign({}, currentKnowledgeRagSummary(), { pageUiState.knowledgeRagSummary = Object.assign({}, currentKnowledgeRagSummary(), {
scopeKey: knowledgeRagScopeKey(), scopeKey: knowledgeRagScopeKey(),
loading: false, loading: false,
error: '请先填写要索引的资料路径' error: '请先填写要索引的资料路径,或保留至少一个已保存的索引范围'
}); });
renderKnowledgeRagSettings(); renderKnowledgeRagSettings();
return; return;
@@ -2135,12 +2135,12 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
'<div class="wolai-search-options-left">' + '<div class="wolai-search-options-left">' +
'<span class="wolai-search-switch-control"><span>仅匹配标题</span><button type="button" class="wolai-search-switch" data-search-switch="title" role="switch" aria-checked="false" aria-label="仅匹配标题"></button></span>' + '<span class="wolai-search-switch-control"><span>仅匹配标题</span><button type="button" class="wolai-search-switch" data-search-switch="title" role="switch" aria-checked="false" aria-label="仅匹配标题"></button></span>' +
'<span class="wolai-search-switch-control"><span>精确匹配</span><button type="button" class="wolai-search-switch" data-search-switch="exact" role="switch" aria-checked="false" aria-label="精确匹配"></button></span>' + '<span class="wolai-search-switch-control"><span>精确匹配</span><button type="button" class="wolai-search-switch" data-search-switch="exact" role="switch" aria-checked="false" aria-label="精确匹配"></button></span>' +
'<span class="wolai-search-sort-control"><span>资料库模式</span><select class="wolai-search-sort-value" data-search-knowledge-mode aria-label="资料库检索模式"><option value="mix">综合</option><option value="hybrid">图谱混合</option><option value="naive">向量</option><option value="local">实体</option><option value="global">关系</option><option value="exact">关键词</option></select></span>' + '<span class="wolai-search-sort-control"><span>资料库模式</span><select class="wolai-search-sort-value" data-search-knowledge-mode aria-label="资料库检索模式"><option value="exact" selected>关键词</option><option value="mix">综合</option><option value="hybrid">图谱混合</option><option value="naive">向量</option><option value="local">实体</option><option value="global">关系</option></select></span>' +
'<span class="wolai-search-sort-control"><span>按编辑时间</span><button type="button" class="wolai-search-sort-value" data-search-sort="updated" aria-label="按编辑时间范围">所有</button></span>' + '<span class="wolai-search-sort-control"><span>按编辑时间</span><button type="button" class="wolai-search-sort-value" data-search-sort="updated" aria-label="按编辑时间范围">所有</button></span>' +
'<span class="wolai-search-sort-control"><span>按创建时间</span><button type="button" class="wolai-search-sort-value" data-search-sort="created" aria-label="按创建时间范围">所有</button></span>' + '<span class="wolai-search-sort-control"><span>按创建时间</span><button type="button" class="wolai-search-sort-value" data-search-sort="created" aria-label="按创建时间范围">所有</button></span>' +
'</div>' + '</div>' +
'<div class="wolai-search-options-right">' + '<div class="wolai-search-options-right">' +
'<span class="wolai-search-switch-control"><span>全盘资料库</span><button type="button" class="wolai-search-switch" data-search-switch="knowledge" role="switch" aria-checked="false" aria-label="全盘资料库检索"></button></span>' + '<span class="wolai-search-switch-control"><span>全盘资料库</span><button type="button" class="wolai-search-switch is-on" data-search-switch="knowledge" role="switch" aria-checked="true" aria-label="全盘资料库检索"></button></span>' +
'<span class="wolai-search-switch-control"><span>页面内搜索</span><button type="button" class="wolai-search-switch" data-search-switch="page" role="switch" aria-checked="false" aria-label="页面内搜索"></button></span>' + '<span class="wolai-search-switch-control"><span>页面内搜索</span><button type="button" class="wolai-search-switch" data-search-switch="page" role="switch" aria-checked="false" aria-label="页面内搜索"></button></span>' +
'<span class="wolai-search-switch-control"><span>折叠同来源</span><button type="button" class="wolai-search-switch is-on" data-search-switch="collapseSource" role="switch" aria-checked="true" aria-label="默认折叠相同来源结果"></button></span>' + '<span class="wolai-search-switch-control"><span>折叠同来源</span><button type="button" class="wolai-search-switch is-on" data-search-switch="collapseSource" role="switch" aria-checked="true" aria-label="默认折叠相同来源结果"></button></span>' +
'</div>' + '</div>' +
@@ -2152,7 +2152,9 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
document.body.appendChild(overlay); document.body.appendChild(overlay);
var input = overlay.querySelector('[data-testid="wolai-search-input"]'); var input = overlay.querySelector('[data-testid="wolai-search-input"]');
var closeButton = overlay.querySelector('[data-testid="wolai-search-close"]'); var closeButton = overlay.querySelector('[data-testid="wolai-search-close"]');
applySearchSwitchState(overlay, { collapseSource: readSearchCollapseSourcesDefault() }); applySearchSwitchState(overlay, { knowledge: true, collapseSource: readSearchCollapseSourcesDefault() });
var initialKnowledgeModeSelect = overlay.querySelector('[data-search-knowledge-mode]');
if (initialKnowledgeModeSelect && 'value' in initialKnowledgeModeSelect) initialKnowledgeModeSelect.value = 'exact';
if (input) input.addEventListener('input', function() { if (input) input.addEventListener('input', function() {
searchUiState.hasRendered = false; searchUiState.hasRendered = false;
scheduleSearchResultsRender(); scheduleSearchResultsRender();
@@ -2194,7 +2196,7 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
metaHtml: '', metaHtml: '',
resultsHtml: '', resultsHtml: '',
items: [], items: [],
knowledgeMode: 'mix', knowledgeMode: 'exact',
sourceCollapsed: {}, sourceCollapsed: {},
scrollTop: 0, scrollTop: 0,
signature: '', signature: '',
@@ -2345,7 +2347,7 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
if (input && 'value' in input) input.value = searchUiState.query || ''; if (input && 'value' in input) input.value = searchUiState.query || '';
applySearchSwitchState(overlay, searchUiState.switches); applySearchSwitchState(overlay, searchUiState.switches);
var knowledgeModeSelect = overlay.querySelector('[data-search-knowledge-mode]'); var knowledgeModeSelect = overlay.querySelector('[data-search-knowledge-mode]');
if (knowledgeModeSelect && 'value' in knowledgeModeSelect) knowledgeModeSelect.value = searchUiState.knowledgeMode || 'mix'; if (knowledgeModeSelect && 'value' in knowledgeModeSelect) knowledgeModeSelect.value = searchUiState.knowledgeMode || 'exact';
if (options instanceof HTMLElement) options.hidden = !searchText(searchUiState.query); if (options instanceof HTMLElement) options.hidden = !searchText(searchUiState.query);
if (meta && searchUiState.metaHtml) meta.innerHTML = searchUiState.metaHtml; if (meta && searchUiState.metaHtml) meta.innerHTML = searchUiState.metaHtml;
if (results && searchUiState.resultsHtml) { if (results && searchUiState.resultsHtml) {
@@ -369,7 +369,27 @@ pub async fn ingest(
let mut expanded_count = 0usize; let mut expanded_count = 0usize;
let mut seen_sources = BTreeSet::<String>::new(); let mut seen_sources = BTreeSet::<String>::new();
let force = body.force.unwrap_or(false); let force = body.force.unwrap_or(false);
for source in body.sources { let mut requested_sources = body.sources;
if requested_sources.is_empty() {
requested_sources = registry
.indexed_roots
.iter()
.map(|root| KnowledgeRagSourceInput {
source_path: Some(root.root_relative_path.clone()),
path: None,
parser_hint: None,
})
.collect();
}
if requested_sources.is_empty() {
return Err(WebError::bad_request_code(
"knowledge_rag_source_required",
"资料库索引缺少 sourcePath,且没有可重建的已保存索引范围",
)
.with_context(&context));
}
for source in requested_sources {
let source_path = source.source_path.or(source.path).ok_or_else(|| { let source_path = source.source_path.or(source.path).ok_or_else(|| {
WebError::bad_request_code("knowledge_rag_source_required", "资料库索引缺少 sourcePath") WebError::bad_request_code("knowledge_rag_source_required", "资料库索引缺少 sourcePath")
.with_context(&context) .with_context(&context)
@@ -1087,7 +1107,8 @@ fn normalize_knowledge_rag_search_mode(mode: Option<&str>) -> String {
Some("hybrid") => "hybrid".into(), Some("hybrid") => "hybrid".into(),
Some("naive" | "vector") => "naive".into(), Some("naive" | "vector") => "naive".into(),
Some("mix" | "mixed") => "mix".into(), Some("mix" | "mixed") => "mix".into(),
_ => "mix".into(), Some(_) => "mix".into(),
None => "exact".into(),
} }
} }
@@ -4718,7 +4739,7 @@ mod tests {
normalize_knowledge_rag_search_mode(Some("hybrid")), normalize_knowledge_rag_search_mode(Some("hybrid")),
"hybrid" "hybrid"
); );
assert_eq!(normalize_knowledge_rag_search_mode(None), "mix"); assert_eq!(normalize_knowledge_rag_search_mode(None), "exact");
} }
#[test] #[test]
@@ -568,6 +568,11 @@ mod tests {
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("pruneKnowledgeRagRegistry")); assert!(SIDEBAR_TREE_RUNTIME_JS.contains("pruneKnowledgeRagRegistry"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("setKnowledgeRagSourceFilter")); assert!(SIDEBAR_TREE_RUNTIME_JS.contains("setKnowledgeRagSourceFilter"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("mnote:knowledge-rag-source-updated")); assert!(SIDEBAR_TREE_RUNTIME_JS.contains("mnote:knowledge-rag-source-updated"));
assert!(
SIDEBAR_TREE_RUNTIME_JS.contains(r#"<option value="exact" selected>关键词</option>"#)
);
assert!(SIDEBAR_TREE_RUNTIME_JS
.contains(r#"data-search-switch="knowledge" role="switch" aria-checked="true""#));
assert!(SIDEBAR_FILETREE_COMMAND_RUNTIME_JS.contains("knowledgeRagSourceRelativePath")); assert!(SIDEBAR_FILETREE_COMMAND_RUNTIME_JS.contains("knowledgeRagSourceRelativePath"));
assert!(SIDEBAR_FILETREE_COMMAND_RUNTIME_JS.contains("supportsKnowledgeRagSource")); assert!(SIDEBAR_FILETREE_COMMAND_RUNTIME_JS.contains("supportsKnowledgeRagSource"));
assert!(!SIDEBAR_FILETREE_COMMAND_RUNTIME_JS.contains("runLocalOcr")); assert!(!SIDEBAR_FILETREE_COMMAND_RUNTIME_JS.contains("runLocalOcr"));