Generate navigation, navigation search (#18096)

### Summary
2 API

POST /api/v1/datasets/{dataset_id}/navigation

GET
/api/v1/datasets/{dataset_id}/navigation/search?q={query}&mode={mode}&top_k={topk}


2 cli

uv run --no-sync python3 admin/client/ragflow_cli.py -h 127.0.0.1 -p
9380 -t user

ragflow> GENERATE NAVIGATION OF DATASET 'frames tree';

ragflow> NAVIGATION SEARCH 'Christie introduced blockchain-based digital
passports' IN DATASET 'frames tree' MODE 'all' topk 20;

(mode: chunk, nav_cluster, nav_doc, navigation_tree, all)
This commit is contained in:
qinling0210
2026-08-11 17:48:24 +08:00
committed by GitHub
parent a399b93143
commit d49af7f218
12 changed files with 1270 additions and 93 deletions

View File

@@ -3,8 +3,11 @@ export interface DatasetNavNode {
description: string;
doc_count: number;
type: string;
doc_id?: string; // only returned by the children endpoint
doc_id?: string;
has_children: boolean;
keywords?: string[];
entities?: string[];
graph_content?: string;
}
export interface DatasetNavList {

View File

@@ -2399,6 +2399,10 @@ Example: Virtual Hosted Style`,
loading: 'Loading...',
selectNode: 'Select a child node to view details',
noDescription: 'No description',
description: 'Description',
keywords: 'Keywords',
entities: 'Entities',
graphContent: 'Full Graph Content',
docCount: '{{count}} documents',
deleteAllTitle: 'Delete navigation tree',
deleteAllDescription:

View File

@@ -2045,6 +2045,10 @@ NER使用 spaCy NER 和基于规则的关键词提取来抽取实体和关系
loading: '加载中...',
selectNode: '选择子节点以查看详情',
noDescription: '暂无描述',
description: '描述',
keywords: '关键词',
entities: '实体',
graphContent: '完整图谱内容',
docCount: '{{count}} 个文档',
deleteAllTitle: '删除目录树',
deleteAllDescription: '确定要删除整个目录树吗?此操作无法撤销。',

View File

@@ -12,6 +12,9 @@ export interface SelectedNavNode {
name: string;
description: string;
doc_count: number;
keywords?: string[];
entities?: string[];
graph_content?: string;
}
export function useCompilationNav() {
@@ -95,6 +98,9 @@ export function useCompilationNav() {
name: node.name,
description: node.description,
doc_count: node.doc_count,
keywords: node.keywords,
entities: node.entities,
graph_content: node.graph_content,
});
},
[],

View File

@@ -52,8 +52,59 @@ export function NavTreeView() {
{t('datasetNav.docCount', { count: selectedNode.doc_count })}
</span>
</header>
<div className="flex-1 min-h-0 overflow-y-auto px-4 py-3 text-sm text-text-primary whitespace-pre-wrap">
{selectedNode.description || t('datasetNav.noDescription')}
<div className="flex-1 min-h-0 overflow-y-auto px-4 py-3 text-sm text-text-primary space-y-4">
<div>
<h4 className="text-xs font-medium text-text-secondary mb-1">
{t('datasetNav.description')}
</h4>
<p className="whitespace-pre-wrap">
{selectedNode.description || t('datasetNav.noDescription')}
</p>
</div>
{selectedNode.keywords && selectedNode.keywords.length > 0 && (
<div>
<h4 className="text-xs font-medium text-text-secondary mb-1">
{t('datasetNav.keywords')}
</h4>
<div className="flex flex-wrap gap-1">
{selectedNode.keywords.map((kw, i) => (
<span
key={i}
className="inline-block px-2 py-0.5 rounded text-xs bg-fill-quaternary text-text-secondary"
>
{kw}
</span>
))}
</div>
</div>
)}
{selectedNode.entities && selectedNode.entities.length > 0 && (
<div>
<h4 className="text-xs font-medium text-text-secondary mb-1">
{t('datasetNav.entities')}
</h4>
<div className="flex flex-wrap gap-1">
{selectedNode.entities.map((entity, i) => (
<span
key={i}
className="inline-block px-2 py-0.5 rounded text-xs bg-fill-quaternary text-text-secondary"
>
{entity}
</span>
))}
</div>
</div>
)}
{selectedNode.graph_content && (
<div>
<h4 className="text-xs font-medium text-text-secondary mb-1">
{t('datasetNav.graphContent')}
</h4>
<p className="whitespace-pre-wrap text-xs text-text-secondary">
{selectedNode.graph_content}
</p>
</div>
)}
</div>
</section>
) : (