diff --git a/agent/component/docs_generator.py b/agent/component/docs_generator.py index b0c1b313af..ce7a3abad5 100644 --- a/agent/component/docs_generator.py +++ b/agent/component/docs_generator.py @@ -49,6 +49,7 @@ class DocGeneratorParam(ComponentParamBase): self.watermark_text = "" self.add_page_numbers = True self.add_timestamp = True + self.include_download_info_in_content = False self.font_size = 12 self.outputs = { "download": {"value": "", "type": "string"}, @@ -131,6 +132,7 @@ class DocGenerator(Message, ABC): "mime_type": mime_type, "size": file_size, "base64": file_base64, + "include_download_info_in_content": self._param.include_download_info_in_content, } self.set_output("download", json.dumps(download_info)) return download_info diff --git a/agent/component/message.py b/agent/component/message.py index 8db4eedbd1..a52741f6b3 100644 --- a/agent/component/message.py +++ b/agent/component/message.py @@ -75,6 +75,22 @@ class Message(ComponentBase): key in value for key in ("doc_id", "filename", "mime_type") ) + @staticmethod + def _download_info_includes_content(value: Any) -> bool: + return isinstance(value, dict) and bool(value.get("include_download_info_in_content")) + + @staticmethod + def _normalize_download_info(value: Any) -> Any: + if isinstance(value, list): + return [Message._normalize_download_info(item) for item in value] + + if not isinstance(value, dict): + return value + + normalized = value.copy() + normalized.pop("include_download_info_in_content", None) + return normalized + def _extract_downloads(self, value: Any) -> list[dict[str, Any]]: if isinstance(value, str): try: @@ -100,7 +116,19 @@ class Message(ComponentBase): extracted_downloads = self._extract_downloads(value) if extracted_downloads: if downloads is not None: - downloads.extend(extracted_downloads) + downloads.extend(self._normalize_download_info(item) for item in extracted_downloads) + if any(self._download_info_includes_content(item) for item in extracted_downloads): + if isinstance(value, str): + try: + value = json.loads(value) + except Exception: + return value + try: + return json.dumps(self._normalize_download_info(value), ensure_ascii=False) + except Exception: + if fallback_to_str: + return str(value) + return "" return "" if value is None: diff --git a/web/src/pages/agent/constant/index.tsx b/web/src/pages/agent/constant/index.tsx index 6cbb516715..3c815b4269 100644 --- a/web/src/pages/agent/constant/index.tsx +++ b/web/src/pages/agent/constant/index.tsx @@ -973,6 +973,7 @@ export const initialDocGeneratorValues = { watermark_text: '', add_page_numbers: true, add_timestamp: true, + include_download_info_in_content: false, font_size: 12, outputs: { download: { type: 'string' }, diff --git a/web/src/pages/agent/form/doc-generator-form/index.tsx b/web/src/pages/agent/form/doc-generator-form/index.tsx index e9d0e82dcb..56faf96535 100644 --- a/web/src/pages/agent/form/doc-generator-form/index.tsx +++ b/web/src/pages/agent/form/doc-generator-form/index.tsx @@ -11,9 +11,9 @@ import { Input } from '@/components/ui/input'; import { RAGFlowSelect } from '@/components/ui/select'; import { Switch } from '@/components/ui/switch'; import { zodResolver } from '@hookform/resolvers/zod'; -import { t } from 'i18next'; import { memo, useEffect, useMemo } from 'react'; import { useForm } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; import { z } from 'zod'; import { INextOperatorForm } from '../../interface'; import { FormWrapper } from '../components/form-wrapper'; @@ -23,6 +23,7 @@ import { useValues } from './use-values'; import { useWatchFormChange } from './use-watch-form-change'; function DocGeneratorForm({ node }: INextOperatorForm) { + const { t } = useTranslation(); const values = useValues(node); const FormSchema = z.object({ @@ -34,6 +35,7 @@ function DocGeneratorForm({ node }: INextOperatorForm) { watermark: z.string().optional(), add_page_numbers: z.boolean(), add_timestamp: z.boolean(), + include_download_info_in_content: z.boolean(), font_size: z.coerce.number().min(12, 'Font size must be at least 12'), outputs: z.object({ download: z.object({ type: z.string() }), @@ -113,6 +115,29 @@ function DocGeneratorForm({ node }: INextOperatorForm) { )} /> + ( + +
+ + {t( + 'flow.includeDownloadInfoInContent', + 'Append download info to content', + )} + +
+ + + +
+ )} + /> + { watermark_text: nextValues.watermark_text, add_page_numbers: nextValues.add_page_numbers, add_timestamp: nextValues.add_timestamp, + include_download_info_in_content: + nextValues.include_download_info_in_content ?? false, font_size: Math.max(12, Number(nextValues.font_size) || 12), outputs: initialDocGeneratorValues.outputs, };