Feat: optimize title chunk (#14325)

### What problem does this PR solve?

Feat: optimize title chunk
1. Add a new button to enable "Use root chunk as H0 heading", so that
the first chunk is carried on to all remaining chunks.
2. Update resume agent template

### Type of change

- [x] New Feature (non-breaking change which adds functionality)


<img width="700" alt="img_v3_02111_63b04951-b3d7-4001-a08b-539db6d5298g"
src="https://github.com/user-attachments/assets/4179ac4d-90e7-4353-9b93-d649a455e634"
/>

<img width="700" alt="image"
src="https://github.com/user-attachments/assets/c0ba0f3c-05aa-4f2c-b418-e808ca1a2641"
/>
This commit is contained in:
Magicbook1108
2026-04-23 18:55:55 +08:00
committed by GitHub
parent ba47c13eb5
commit 75a5548b85
13 changed files with 96 additions and 41 deletions

View File

@@ -1513,6 +1513,9 @@ Example: Virtual Hosted Style`,
includeHeadingContent: 'Include heading content',
includeHeadingContentTip:
'When enabled, content directly under a heading is kept as its own chunk. Child chunks keep only the heading path.',
rootAsHeading: 'Use root as H0 heading',
rootAsHeadingTip:
'Treat the root node as a H0 heading when building the hierarchy',
hierarchyTip: `Build a heading tree and produce self-contained chunks, each carrying its full ancestor heading path (e.g. Part 1 Chapter 3 Section 2 + body text).\n
Best for: Documents with independent, structurally significant sections — such as legal statutes, regulations, contracts, and technical specifications — where each chunk must be identifiable by its structural position even without surrounding context.`,
groupTip: `Split the document flat at a chosen heading level and automatically merge adjacent small sections to preserve content continuity. No parent-heading path is injected.\n

View File

@@ -333,6 +333,7 @@ export const initialTitleChunkerValues = {
method: 'hierarchy',
hierarchy: Hierarchy.H3,
include_heading_content: false,
root_chunk_as_heading: false,
rules: rules,
};
@@ -340,6 +341,7 @@ export const initialGroupValues = {
method: 'group',
hierarchy: '0',
include_heading_content: false,
root_chunk_as_heading: false,
rules: rules,
};

View File

@@ -128,6 +128,7 @@ function transformApiResponseToForm(
method,
hierarchy,
include_heading_content: Boolean(apiData.include_heading_content),
root_chunk_as_heading: Boolean(apiData.root_chunk_as_heading),
rules,
};
}

View File

@@ -29,6 +29,7 @@ import { transformApiResponseToForm, useDynamicHierarchyOptions } from './hook';
type FormModeValues = {
hierarchy?: string;
include_heading_content?: boolean;
root_chunk_as_heading?: boolean;
rules: Array<{ levels: Array<{ expression: string }> }>;
};
@@ -60,6 +61,7 @@ export const FormSchema = z.object({
method: z.enum(['hierarchy', 'group']),
hierarchy: z.string().optional(),
include_heading_content: z.boolean().optional(),
root_chunk_as_heading: z.boolean().optional(),
rules: rulesSchema,
});
@@ -221,12 +223,14 @@ const TitleChunkerForm = ({ node }: INextOperatorForm) => {
hierarchyModeValues.current = {
hierarchy: hierarchyValue,
include_heading_content: form.getValues('include_heading_content'),
root_chunk_as_heading: form.getValues('root_chunk_as_heading'),
rules: rulesValue,
};
} else if (currentMode === 'group') {
groupValues.current = {
hierarchy: hierarchyValue,
include_heading_content: form.getValues('include_heading_content'),
root_chunk_as_heading: form.getValues('root_chunk_as_heading'),
rules: rulesValue,
};
}
@@ -239,6 +243,7 @@ const TitleChunkerForm = ({ node }: INextOperatorForm) => {
method: 'group',
hierarchy: modeValues?.hierarchy ?? '0',
include_heading_content: false,
root_chunk_as_heading: false,
rules: modeValues?.rules || initialGroupValues.rules,
});
} else {
@@ -251,12 +256,14 @@ const TitleChunkerForm = ({ node }: INextOperatorForm) => {
hierarchy: modeValues.hierarchy || defaultHierarchy,
include_heading_content:
modeValues.include_heading_content || false,
root_chunk_as_heading: modeValues.root_chunk_as_heading || false,
rules: modeValues.rules,
});
} else {
const newModeValues: FormModeValues = {
hierarchy: defaultHierarchy,
include_heading_content: false,
root_chunk_as_heading: false,
rules: JSON.parse(JSON.stringify(initialTitleChunkerValues.rules)),
};
@@ -264,6 +271,7 @@ const TitleChunkerForm = ({ node }: INextOperatorForm) => {
method: method,
hierarchy: defaultHierarchy,
include_heading_content: newModeValues.include_heading_content,
root_chunk_as_heading: newModeValues.root_chunk_as_heading,
rules: newModeValues.rules,
});
}
@@ -323,23 +331,46 @@ const TitleChunkerForm = ({ node }: INextOperatorForm) => {
<SelectWithSearch options={hierarchyOptions}></SelectWithSearch>
</RAGFlowFormItem>
{method === 'hierarchy' && (
<RAGFlowFormItem
name="include_heading_content"
label={t('flow.includeHeadingContent', 'Include heading content')}
tooltip={t('flow.includeHeadingContentTip')}
horizontal={true}
labelClassName="w-full"
valueClassName="w-8"
>
{(field) => (
<Switch
checked={field.value}
onCheckedChange={(checked) => {
field.onChange?.(checked);
}}
/>
)}
</RAGFlowFormItem>
<>
<RAGFlowFormItem
name="include_heading_content"
label={t('flow.includeHeadingContent', 'Include heading content')}
tooltip={t('flow.includeHeadingContentTip')}
horizontal={true}
labelClassName="w-full"
valueClassName="w-8"
>
{(field) => (
<Switch
checked={field.value}
onCheckedChange={(checked) => {
field.onChange?.(checked);
}}
/>
)}
</RAGFlowFormItem>
<RAGFlowFormItem
name="root_chunk_as_heading"
label={t('flow.rootAsHeading', 'Use root as heading')}
tooltip={t(
'flow.rootAsHeadingTip',
'Treat the root node as a H0 heading when building the hierarchy',
)}
horizontal={true}
labelClassName="w-full"
valueClassName="w-8"
>
{(field) => (
<Switch
checked={field.value}
onCheckedChange={(checked) => {
field.onChange?.(checked);
}}
/>
)}
</RAGFlowFormItem>
</>
)}
{/* {method === 'group' ? (
<Card>

View File

@@ -338,6 +338,7 @@ function transformTitleChunkerParams(params: TitleChunkerFormSchemaType) {
method: params.method,
hierarchy: Number(params.hierarchy || 0),
include_heading_content: Boolean(params.include_heading_content),
root_chunk_as_heading: Boolean(params.root_chunk_as_heading),
levels,
};
}