Dify文档智能审核工作流搭建完整指南
目录
一、整体架构设计
1.1 工作流程图
用户上传文件 → 文件类型识别 → 文件内容提取 → 规则解析 → LLM智能审核 → 结果汇总 → 输出报告
1.2 核心功能模块
- 文件解析模块:支持Excel、Word、PPT格式
- 规则引擎:模板校验、数据合规性、数据准确性
- LLM审核:基于大语言模型的智能分析
- 报告生成:结构化输出不符合项
二、前置准备
2.1 创建知识库
步骤1:登录Dify平台
- 访问你的Dify平台地址
- 使用管理员账号登录
步骤2:创建"审核规则知识库"
- 点击左侧菜单 "知识库"
- 点击 "创建知识库" 按钮
- 填写信息:
- 名称:
document-audit-rules - 描述:存储各类文档的审核规则和标准
- 类型:文本型
- 名称:
- 点击 "创建"
步骤3:创建"文档模板知识库"
- 重复上述步骤
- 填写信息:
- 名称:
document-templates - 描述:存储标准文档模板供比对
- 类型:文本型
- 名称:
- 点击 "创建"
步骤4:上传规则文档到知识库
- 进入
document-audit-rules知识库 - 点击 "添加文档"
- 上传以下内容(保存为txt或md文件):
文件名:excel_audit_rules.txt
Excel文档审核规则标准:
结构规范
必须包含表头行
表头不能有空单元格
每个sheet必须有明确的名称
数据行不能有完全空的行
数据格式规范
日期字段格式:YYYY-MM-DD
金额字段:数字类型,保留2位小数
百分比字段:0-100之间的数值
项目编号格式:PRJ-XXXX-XXX
必填字段
项目名称
负责人
开始日期
结束日期
预算金额
文件名:word_audit_rules.txt
Word文档审核规则标准:
文档结构规范
必须包含标题(Heading 1)
至少包含2级标题结构
章节顺序合理
段落间距统一
必需章节
摘要/前言
背景说明
主体内容
结论/建议
附录(如需要)
格式规范
字体统一(正文:宋体/微软雅黑)
字号规范(标题:小二/三号,正文:小四)
行距:1.5倍行距
页边距:上下2.54cm,左右3.17cm
文件名:ppt_audit_rules.txt
PPT演示文稿审核规则标准:
结构规范
必须包含封面页
必须包含目录页
必须包含结束页
幻灯片数量适中(建议10-30页)
内容规范
每页标题清晰
文字简洁(每页不超过6行)
图文结合
数据有来源标注
设计规范
配色方案统一
字体大小可读(正文不小于18pt)
图片清晰度高
动画效果适度
- 对每个文档点击 "启用" 状态
三、工作流搭建详细步骤
3.1 创建工作流应用
步骤1:创建新应用
- 点击左侧菜单 "工作室" 或 "应用"
- 点击 "创建应用" 按钮
- 选择 "工作流" 类型(不是聊天助手)
- 填写应用信息:
- 应用名称:
文档智能审核助手 - 应用描述:智能审核Excel、Word、PPT文档,检查模板规范性、数据合规性和准确性
- 图标:选择一个合适的图标
- 应用名称:
- 点击 "创建"
步骤2:进入工作流编辑器
- 创建成功后自动进入工作流编辑界面
- 你会看到一个空白的画布,左侧是节点面板
3.2 配置"开始"节点
步骤1:点击"开始"节点
- 在画布上找到默认的 "开始" 节点
- 点击该节点,右侧会显示配置面板
步骤2:添加输入变量
在右侧配置面板中,找到 "输入变量" 部分,依次添加以下变量:
变量1:file(文件)
- 变量名:
file - 变量类型:选择 "文件"
- 是否必填:勾选
- 允许的文件类型:选择
xlsx, xls, docx, doc, pptx, ppt - 描述:上传需要审核的文档
变量2:audit_rules(审核规则JSON)
- 变量名:
audit_rules - 变量类型:选择 "段落" 或 "字符串"
- 是否必填:不勾选(提供默认值)
- 默认值:留空或填入基础规则JSON(见第四章)
- 描述:审核规则配置(JSON格式),为空则使用默认规则
变量3:template_name(模板名称)
- 变量名:
template_name - 变量类型:选择 "字符串"
- 是否必填:不勾选
- 描述:指定比对的模板名称(可选)
变量4:strict_mode(严格模式)
- 变量名:
strict_mode - 变量类型:选择 "布尔值"
- 是否必填:不勾选
- 默认值:
false - 描述:是否启用严格审核模式
步骤3:保存配置
点击右侧面板底部的 "保存" 按钮
3.3 添加"文件类型识别"代码节点
步骤1:添加代码执行节点
- 在画布上,点击 "开始"节点 右侧的 "+" 号
- 在弹出的节点选择菜单中,选择 "代码" 或 "Code"
- 节点会自动添加到画布上
步骤2:配置节点基本信息
- 双击新添加的代码节点
- 在右侧配置面板中:
- 节点名称:修改为
文件类型识别 - 节点描述:识别上传文件的类型并确定解析策略
- 节点名称:修改为
步骤3:配置输入变量
在 "输入变量" 部分,点击 "添加变量":
- 变量名:
file - 变量类型:选择 "文件"
- 值:选择
{``{file}}(从开始节点引用)
步骤4:选择编程语言
在 "代码" 部分:
- 语言:选择 Python3
步骤5:粘贴代码
将以下代码完整粘贴到代码编辑区:
python def main(file: str) -> dict: """识别文件类型并返回处理策略""" # 从文件名中提取扩展名 file_extension = file.split('.')-1.lower()
定义文件类型映射
type_mapping = {
'xlsx': {'type': 'excel', 'parser': 'openpyxl'},
'xls': {'type': 'excel', 'parser': 'xlrd'},
'docx': {'type': 'word', 'parser': 'python-docx'},
'doc': {'type': 'word', 'parser': 'antiword'},
'pptx': {'type': 'ppt', 'parser': 'python-pptx'},
'ppt': {'type': 'ppt', 'parser': 'powerpoint'}
}
检查文件格式是否支持
if file_extension not in type_mapping:
return {
'success': False,
'error': f'不支持的文件格式: {file_extension}'
}
返回文件类型信息
return {
'success': True,
'file_type': type_mappingfile_extension'type',
'parser': type_mappingfile_extension'parser',
'extension': file_extension
}
步骤6:配置输出变量
在 "输出变量" 部分,点击 "添加变量",添加以下4个变量:
-
success
- 变量名:
success - 类型:选择 "布尔值"
- 描述:文件类型识别是否成功
- 变量名:
-
file_type
- 变量名:
file_type - 类型:选择 "字符串"
- 描述:文件类型(excel/word/ppt)
- 变量名:
-
parser
- 变量名:
parser - 类型:选择 "字符串"
- 描述:使用的解析器
- 变量名:
-
extension
- 变量名:
extension - 类型:选择 "字符串"
- 描述:文件扩展名
- 变量名:
-
error
- 变量名:
error - 类型:选择 "字符串"
- 描述:错误信息(如果失败)
- 变量名:
步骤7:保存节点
点击右侧面板底部的 "保存" 按钮
3.4 添加条件分支节点
步骤1:添加条件判断节点
- 点击 "文件类型识别"节点 右侧的 "+" 号
- 选择 "条件分支" 或 "If-Else" 节点
- 节点名称:修改为
检查文件类型识别结果
步骤2:配置条件
在右侧配置面板中:
条件1:识别成功
- 条件名称:
识别成功 - 条件表达式:选择
{``{文件类型识别.success}} - 运算符:选择
等于 - 值:输入
true
条件2:识别失败
- 点击 "添加分支"
- 条件名称:
识别失败 - 条件表达式:选择
{``{文件类型识别.success}} - 运算符:选择
等于 - 值:输入
false
步骤3:保存配置
点击 "保存" 按钮
3.5 添加"失败提示"结束节点(失败分支)
步骤1:在失败分支添加结束节点
- 在 "识别失败" 分支的 "+" 号处
- 选择 "结束" 节点
- 节点名称:修改为
返回错误信息
步骤2:配置输出
在右侧配置面板中:
- 输出类型:选择 "文本"
- 输出内容:输入
{``{文件类型识别.error}}
步骤3:保存
点击 "保存" 按钮
3.6 添加"文件内容提取"代码节点(成功分支)
步骤1:在成功分支添加代码节点
- 在 "识别成功" 分支的 "+" 号处
- 选择 "代码" 节点
- 节点名称:修改为
文件内容提取
步骤2:配置输入变量
添加以下输入变量:
-
file
- 变量名:
file - 类型:文件
- 值:
{``{file}}
- 变量名:
-
file_type
- 变量名:
file_type - 类型:字符串
- 值:
{``{文件类型识别.file_type}}
- 变量名:
步骤3:粘贴代码
python import json
def main(file: str, file_type: str) -> dict: """ 根据文件类型提取内容 注意:实际使用时需要根据Dify支持的库调整代码 """
result = {
'success': False,
'file_type': file_type,
'content': {},
'full_text': '',
'structure': {},
'error': ''
}
try:
if file_type == 'excel':
result = extract_excel_content(file)
elif file_type == 'word':
result = extract_word_content(file)
elif file_type == 'ppt':
result = extract_ppt_content(file)
else:
result'error' = f'不支持的文件类型: {file_type}'
except Exception as e:
result'success' = False
result'error' = f'文件解析失败: {str(e)}'
return result
def extract_excel_content(file_path: str) -> dict: """ 提取Excel文件内容 注意:需要根据Dify实际支持的库进行调整 """ try: sheets_info = {}
如果能读取到文件内容,解析各个sheet
这里提供伪代码示例,实际使用时需要调整
"""
import openpyxl
workbook = openpyxl.load_workbook(file_path, data_only=True)
for sheet_name in workbook.sheetnames:
sheet = workbook[sheet_name]
rows = []
for row in sheet.iter_rows(values_only=True):
rows.append([str(cell) if cell is not None else '' for cell
in row])
sheets_infosheet_name = {
'headers': rows0 if rows else \[\],
'data': rows1: if len(rows) > 1 else \[\],
'row_count': len(rows),
'column_count': len(rows0) if rows else 0
}
"""
临时方案:返回文件基本信息
return {
'success': True,
'file_type': 'excel',
'content': sheets_info,
'full_text': json.dumps(sheets_info, ensure_ascii=False),
'structure': {
'sheet_count': len(sheets_info),
'sheet_names': list(sheets_info.keys())
},
'error': ''
}
except Exception as e:
return {
'success': False,
'file_type': 'excel',
'content': {},
'full_text': '',
'structure': {},
'error': str(e)
}
def extract_word_content(file_path: str) -> dict: """提取Word文档内容""" try: paragraphs = \[\] tables = \[\] full_text = ""
实际实现需要根据Dify环境调整
"""
from docx import Document
doc = Document(file_path)
for i, para in enumerate(doc.paragraphs):
paragraphs.append({
'index': i,
'text': para.text,
'style': para.style.name if para.style else ''
})
for i, table in enumerate(doc.tables):
table_data = []
for row in table.rows:
row_data = [cell.text.strip() for cell in row.cells]
table_data.append(row_data)
tables.append({
'index': i,
'data': table_data
})
full_text = '\n'.join([p['text'] for p in paragraphs])
"""
return {
'success': True,
'file_type': 'word',
'content': {
'paragraphs': paragraphs,
'tables': tables
},
'full_text': full_text,
'structure': {
'paragraph_count': len(paragraphs),
'table_count': len(tables)
},
'error': ''
}
except Exception as e:
return {
'success': False,
'file_type': 'word',
'content': {},
'full_text': '',
'structure': {},
'error': str(e)
}
def extract_ppt_content(file_path: str) -> dict: """提取PPT演示文稿内容""" try: slides = \[\] full_text = ""
实际实现需要根据Dify环境调整
"""
from pptx import Presentation
prs = Presentation(file_path)
for i, slide in enumerate(prs.slides):
slide_content = {
'slide_number': i + 1,
'title': '',
'text_boxes': []
}
if slide.shapes.title:
slide_content['title'] = slide.shapes.title.text
for shape in slide.shapes:
if hasattr(shape, 'text_frame') and shape.text_frame:
if shape != slide.shapes.title:
slide_content['text_boxes'].append({
'text': shape.text
})
slides.append(slide_content)
full_text = '\n'.join([
f"幻灯片{s['slide_number']}: {s['title']}\n" +
'\n'.join([tb['text'] for tb in s['text_boxes']])
for s in slides
])
"""
return {
'success': True,
'file_type': 'ppt',
'content': {
'slides': slides
},
'full_text': full_text,
'structure': {
'total_slides': len(slides)
},
'error': ''
}
except Exception as e:
return {
'success': False,
'file_type': 'ppt',
'content': {},
'full_text': '',
'structure': {},
'error': str(e)
}
重要提示:由于Dify沙箱环境的限制,上述代码可能需要调整。有两种替代方案:
替代方案1:使用HTTP请求节点调用外部解析服务
- 部署一个文件解析API服务
- 使用Dify的 "HTTP请求" 节点调用该服务
替代方案2:简化处理,让LLM直接处理文件
- 跳过复杂的代码解析
- 直接将文件传递给LLM节点
- 在LLM提示词中说明如何处理文件
步骤4:配置输出变量
添加以下输出变量:
- success - 布尔值
- file_type - 字符串
- content - 对象/JSON
- full_text - 字符串
- structure - 对象/JSON
- error - 字符串
步骤5:保存
3.7 添加"审核规则解析"代码节点
步骤1:添加代码节点
- 点击 "文件内容提取"节点 右侧的 "+" 号
- 选择 "代码" 节点
- 节点名称:
审核规则解析
步骤2:配置输入变量
-
audit_rules_json
- 变量名:
audit_rules_json - 类型:字符串
- 值:
{``{audit_rules}}
- 变量名:
-
document_content
- 变量名:
document_content - 类型:对象
- 值:
{``{文件内容提取.content}}
- 变量名:
-
document_full_text
- 变量名:
document_full_text - 类型:字符串
- 值:
{``{文件内容提取.full_text}}
- 变量名:
步骤3:粘贴代码
python import json
def main(audit_rules_json: str, document_content: dict, document_full_text: str) -> dict: """解析审核规则并准备执行""" try: # 如果没有提供规则,使用默认规则 if not audit_rules_json or audit_rules_json.strip() == '': audit_rules = get_default_rules() else: audit_rules = json.loads(audit_rules_json)
分类整理启用的规则
enabled_rules = {
'template': \[\],
'compliance': \[\],
'accuracy': \[\],
'custom': \[\]
}
# 模板校验规则
if audit_rules.get('template_validation', {}).get('enabled', False):
enabled_rules['template'] = audit_rules['template_validation']['rules']
# 数据合规性规则
if audit_rules.get('data_compliance', {}).get('enabled', False):
enabled_rules['compliance'] = audit_rules['data_compliance']['rules']
# 数据准确性规则
if audit_rules.get('data_accuracy', {}).get('enabled', False):
enabled_rules['accuracy'] = audit_rules['data_accuracy']['rules']
# 自定义规则
if audit_rules.get('custom_rules', {}).get('enabled', False):
enabled_rules['custom'] = audit_rules['custom_rules']['rules']
total_rules = sum(len(v) for v in enabled_rules.values())
# 生成文档摘要
document_summary = {
'has_tables': len(document_content.get('tables', [])) > 0 if isinstance(document_content, dict) else False,
'has_structure': bool(document_content.get('structure')) if isinstance(document_content, dict) else False,
'content_length': len(document_full_text) if document_full_text else 0,
'table_count': len(document_content.get('tables', [])) if isinstance(document_content, dict) else 0
}
return {
'success': True,
'enabled_rules': enabled_rules,
'total_rules_count': total_rules,
'document_summary': document_summary,
'full_rules': audit_rules
}
except json.JSONDecodeError as e:
return {
'success': False,
'error': f'规则JSON解析失败: {str(e)}',
'enabled_rules': {},
'total_rules_count': 0,
'document_summary': {},
'full_rules': {}
}
except Exception as e:
return {
'success': False,
'error': f'规则解析失败: {str(e)}',
'enabled_rules': {},
'total_rules_count': 0,
'document_summary': {},
'full_rules': {}
}
def get_default_rules() -> dict: """获取默认审核规则""" return { "template_validation": { "enabled": True, "rules": { "rule_id": "TPL_001", "rule_name": "必需章节检查", "description": "检查文档是否包含所有必需的章节", "required_sections": \["摘要", "背景", "方案", "预算", "tolerance": 0.8 } ] }, "data_compliance": { "enabled": True, "rules": { "rule_id": "COMP_001", "rule_name": "敏感信息检测", "description": "检测是否包含未脱敏的敏感信息", "sensitive_patterns": \[ {"type": "身份证号", "pattern": "\\d{17}\[\\dXx", "action": "flag"}, {"type": "手机号", "pattern": "13-9\d{9}", "action": "flag"} ] } ] }, "data_accuracy": { "enabled": True, "rules": { "rule_id": "ACC_001", "rule_name": "数值一致性校验", "description": "检查汇总数据与明细数据是否一致", "validation_type": "cross_check" } }, "custom_rules": { "enabled": False, "rules": \[\] } }
步骤4:配置输出变量
- success - 布尔值
- enabled_rules - 对象
- total_rules_count - 数字
- document_summary - 对象
- full_rules - 对象
- error - 字符串
步骤5:保存
3.8 添加条件分支 - 检查规则解析
步骤1:添加条件分支节点
- 点击 "审核规则解析"节点 右侧的 "+" 号
- 选择 "条件分支" 节点
- 节点名称:
检查规则解析结果
步骤2:配置条件
条件1:解析成功
- 条件名称:
解析成功 - 表达式:
{``{审核规则解析.success}}等于true
条件2:解析失败
- 条件名称:
解析失败 - 表达式:
{``{审核规则解析.success}}等于false
步骤3:保存
3.9 添加LLM审核节点
这是整个工作流的核心节点。
步骤1:添加LLM节点
- 在 "解析成功" 分支的 "+" 号处
- 选择 "LLM" 或 "模型" 节点
- 节点名称:
LLM智能审核
步骤2:配置模型
在右侧配置面板中:
- 模型:选择你配置的模型(如 GPT-4、Claude等)
- 温度:设置为
0.3(审核任务需要较低的温度以保证稳定性) - 最大Token:设置为
4000或更高
步骤3:配置输入变量
添加以下上下文变量:
-
file_type
- 变量名:
file_type - 值:
{``{文件内容提取.file_type}}
- 变量名:
-
document_content
- 变量名:
document_content - 值:
{``{文件内容提取.full_text}}
- 变量名:
-
audit_rules
- 变量名:
audit_rules - 值:
{``{审核规则解析.enabled_rules}}
- 变量名:
-
document_summary
- 变量名:
document_summary - 值:
{``{审核规则解析.document_summary}}
- 变量名:
-
total_rules_count
- 变量名:
total_rules_count - 值:
{``{审核规则解析.total_rules_count}}
- 变量名:
步骤4:编写系统提示词(System Prompt)
在 "系统提示词" 或 "角色设定" 区域,输入:
你是一位专业的文档审核专家,拥有10年以上的文档质量控制经验。你擅长:
文档结构和模板规范性检查
数据合规性和敏感性检测
数据准确性和逻辑一致性验证
专业术语和表述规范性评估
你的工作是严格按照提供的审核规则,对文档进行全面、细致的审核,找出所有不符合规范的项,并提供具体的改进建议。
审核原则:
客观公正:基于事实和规则进行判断,不带主观偏见
全面细致:不遗漏任何可能的不符合项
具体明确:每个问题都要有清晰的描述和定位
建设性:提供可操作的改进建议
分级处理:根据问题的严重程度进行分级
输出要求:
必须严格按照指定的JSON格式输出
每个不符合项都要有充分的理由说明
评分要客观反映文档的质量水平
步骤5:编写用户提示词(User Prompt)
在 "用户提示词" 区域,输入:
审核任务
请对上传的{{file_type}}文档进行智能审核。
文档信息
文档类型:{{file_type}}
文档长度:{{document_summary.content_length}} 字符
包含表格:{{document_summary.has_tables}}
表格数量:{{document_summary.table_count}}
有结构信息:{{document_summary.has_structure}}
审核规则
共 {{total_rules_count}} 条规则需要检查:
{{{audit_rules}}}
文档内容
{{{document_content}}}
审核要求
请按照以下类别逐项检查:
- 模板规范性检查
检查文档结构是否完整
验证必需章节是否存在
确认格式是否符合规范 - 数据合规性检查
检测敏感信息泄露
验证数据格式是否正确
检查必填字段是否完整 - 数据准确性检查
核对数值一致性
验证逻辑关系合理性
检查数据完整性
输出格式
请严格按照以下JSON格式输出审核结果(不要包含markdown代码块标记):
{ "audit_summary": { "document_type": "{{file_type}}", "total_rules_checked": {{total_rules_count}}, "overall_score": 0-100的数字, "compliance_level": "优秀|良好|合格|不合格", "summary": "总体评价简述" }, "template_validation": { "score": 0-100, "passed": true/false, "issues": { "rule_id": "规则ID", "rule_name": "规则名称", "severity": "严重\|中等\|轻微", "description": "具体问题描述", "location": "问题所在位置(如:第3章、Sheet2、第5行)", "current_value": "当前值", "expected_value": "期望值", "suggestion": "改进建议" } }, "data_compliance": { "score": 0-100, "passed": true/false, "issues": { "rule_id": "规则ID", "rule_name": "规则名称", "severity": "严重\|中等\|轻微", "description": "具体问题描述", "location": "问题所在位置", "sensitive_type": "敏感信息类型(如适用)", "suggestion": "改进建议" } }, "data_accuracy": { "score": 0-100, "passed": true/false, "issues": { "rule_id": "规则ID", "rule_name": "规则名称", "severity": "严重\|中等\|轻微", "description": "具体问题描述", "location": "问题所在位置", "impact": "影响说明", "suggestion": "改进建议" } }, "recommendations": "优先改进建议1", "优先改进建议2", "优先改进建议3" }
注意事项
如果某个类别没有问题,issues数组可以为空,passed设为true,score设为100
severity分级标准:
严重:影响文档可用性、违反法规、重大错误
中等:影响文档质量、不规范、需要改进
轻微:细节问题、优化建议
overall_score计算建议:
90-100:优秀,基本无问题
75-89:良好,有少量轻微问题
60-74:合格,存在中等程度问题
0-59:不合格,存在严重问题或多个中等问题
compliance_level对应:
90-100:优秀
75-89:良好
60-74:合格
0-59:不合格
确保输出的JSON格式正确,可以被程序解析
对于无法确定的问题,标注为"需要人工复核"
现在开始审核,请输出JSON格式的审核结果:
步骤6:配置输出
- 输出类型:选择 "JSON" 或 "对象"
- 如果Dify支持JSON Schema,可以定义输出结构
步骤7:保存
3.10 添加"结果格式化"代码节点
步骤1:添加代码节点
- 点击 "LLM智能审核"节点 右侧的 "+" 号
- 选择 "代码" 节点
- 节点名称:
结果格式化
步骤2:配置输入变量
-
llm_result
- 变量名:
llm_result - 类型:对象
- 值:
{``{LLM智能审核.output}}(根据实际输出变量名调整)
- 变量名:
-
file_type
- 变量名:
file_type - 类型:字符串
- 值:
{``{文件内容提取.file_type}}
- 变量名:
步骤3:粘贴代码
python import json from datetime import datetime
def main(llm_result: dict, file_type: str) -> dict: """格式化审核结果为易读的报告""" try: # 如果LLM返回的是字符串,尝试解析为JSON if isinstance(llm_result, str): llm_result = json.loads(llm_result)
生成审核报告
report = generate_audit_report(llm_result, file_type)
return {
'success': True,
'report': report,
'raw_result': llm_result
}
except Exception as e:
return {
'success': False,
'error': f'结果格式化失败: {str(e)}',
'raw_result': llm_result
}
def generate_audit_report(result: dict, file_type: str) -> str: """生成人类可读的审核报告"""
summary = result.get('audit_summary', {})
template_val = result.get('template_validation', {})
data_comp = result.get('data_compliance', {})
data_acc = result.get('data_accuracy', {})
recommendations = result.get('recommendations', \[\])
构建报告
report_lines = \[\]
标题
report_lines.append("=" * 60)
report_lines.append("文档智能审核报告")
report_lines.append("=" * 60)
report_lines.append("")
基本信息
report_lines.append("【基本信息】")
report_lines.append(f"文档类型:{file_type.upper()}")
report_lines.append(f"审核时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
report_lines.append(f"检查规则数:{summary.get('total_rules_checked', 0)}")
report_lines.append("")
总体评价
report_lines.append("【总体评价】")
report_lines.append(f"综合得分:{summary.get('overall_score', 0)}/100")
report_lines.append(f"合规等级:{summary.get('compliance_level', '未评级')}")
report_lines.append(f"总体评价:{summary.get('summary', '无')}")
report_lines.append("")
模板规范性
report_lines.append("【模板规范性检查】")
report_lines.append(f"得分:{template_val.get('score', 0)}/100")
report_lines.append(f"状态:{'通过' if template_val.get('passed') else '不通过'}")
template_issues = template_val.get('issues', \[\])
if template_issues:
report_lines.append(f"发现问题:{len(template_issues)} 个")
report_lines.append("")
for i, issue in enumerate(template_issues, 1):
report_lines.append(f" {i}. {issue.get('severity', '未知')} {issue.get('rule_name', '')}")
report_lines.append(f" 规则ID:{issue.get('rule_id', '')}")
report_lines.append(f" 问题:{issue.get('description', '')}")
if issue.get('location'):
report_lines.append(f" 位置:{issue.get('location', '')}")
if issue.get('suggestion'):
report_lines.append(f" 建议:{issue.get('suggestion', '')}")
report_lines.append("")
else:
report_lines.append("✓ 未发现模板规范性问题")
report_lines.append("")
数据合规性
report_lines.append("【数据合规性检查】")
report_lines.append(f"得分:{data_comp.get('score', 0)}/100")
report_lines.append(f"状态:{'通过' if data_comp.get('passed') else '不通过'}")
compliance_issues = data_comp.get('issues', \[\])
if compliance_issues:
report_lines.append(f"发现问题:{len(compliance_issues)} 个")
report_lines.append("")
for i, issue in enumerate(compliance_issues, 1):
report_lines.append(f" {i}. {issue.get('severity', '未知')} {issue.get('rule_name', '')}")
report_lines.append(f" 规则ID:{issue.get('rule_id', '')}")
report_lines.append(f" 问题:{issue.get('description', '')}")
if issue.get('location'):
report_lines.append(f" 位置:{issue.get('location', '')}")
if issue.get('sensitive_type'):
report_lines.append(f" 敏感类型:{issue.get('sensitive_type', '')}")
if issue.get('suggestion'):
report_lines.append(f" 建议:{issue.get('suggestion', '')}")
report_lines.append("")
else:
report_lines.append("✓ 未发现数据合规性问题")
report_lines.append("")
数据准确性
report_lines.append("【数据准确性检查】")
report_lines.append(f"得分:{data_acc.get('score', 0)}/100")
report_lines.append(f"状态:{'通过' if data_acc.get('passed') else '不通过'}")
accuracy_issues = data_acc.get('issues', \[\])
if accuracy_issues:
report_lines.append(f"发现问题:{len(accuracy_issues)} 个")
report_lines.append("")
for i, issue in enumerate(accuracy_issues, 1):
report_lines.append(f" {i}. {issue.get('severity', '未知')} {issue.get('rule_name', '')}")
report_lines.append(f" 规则ID:{issue.get('rule_id', '')}")
report_lines.append(f" 问题:{issue.get('description', '')}")
if issue.get('location'):
report_lines.append(f" 位置:{issue.get('location', '')}")
if issue.get('impact'):
report_lines.append(f" 影响:{issue.get('impact', '')}")
if issue.get('suggestion'):
report_lines.append(f" 建议:{issue.get('suggestion', '')}")
report_lines.append("")
else:
report_lines.append("✓ 未发现数据准确性问题")
report_lines.append("")
改进建议
if recommendations:
report_lines.append("【优先改进建议】")
for i, rec in enumerate(recommendations, 1):
report_lines.append(f" {i}. {rec}")
report_lines.append("")
统计信息
total_issues = len(template_issues) + len(compliance_issues) + len(accuracy_issues)
severe_issues = sum(1 for issues in template_issues, compliance_issues, accuracy_issues
for issue in issues if issue.get('severity') == '严重')
report_lines.append("【统计信息】")
report_lines.append(f"总问题数:{total_issues}")
report_lines.append(f"严重问题:{severe_issues}")
report_lines.append(f"中等问题:{sum(1 for issues in template_issues, compliance_issues, accuracy_issues for issue in issues if issue.get('severity') == '中等')}")
report_lines.append(f"轻微问题:{sum(1 for issues in template_issues, compliance_issues, accuracy_issues for issue in issues if issue.get('severity') == '轻微')}")
report_lines.append("")
report_lines.append("=" * 60)
report_lines.append("报告结束")
report_lines.append("=" * 60)
return '\n'.join(report_lines)
步骤4:配置输出变量
- success - 布尔值
- report - 字符串(格式化后的报告)
- raw_result - 对象(原始JSON结果)
- error - 字符串
步骤5:保存
3.11 添加"结束"节点
步骤1:添加结束节点
- 点击 "结果格式化"节点 右侧的 "+" 号
- 选择 "结束" 节点
- 节点名称:
输出审核报告
步骤2:配置输出
在右侧配置面板中:
输出1:审核报告(文本格式)
- 变量名:
audit_report - 类型:字符串
- 值:
{``{结果格式化.report}}
输出2:审核结果(JSON格式)
- 变量名:
audit_result_json - 类型:对象
- 值:
{``{结果格式化.raw_result}}
输出3:处理状态
- 变量名:
status - 类型:字符串
- 值:
{``{结果格式化.success}}
步骤3:保存
3.12 连接失败分支的结束节点
步骤1:为规则解析失败添加结束节点
- 在 "检查规则解析结果" 的 "解析失败" 分支
- 添加 "结束" 节点
- 节点名称:
返回规则解析错误 - 输出内容:
{``{审核规则解析.error}}
步骤2:保存
四、审核规则配置模板
4.1 完整规则配置示例
将以下内容保存为JSON文件,或直接复制到工作流的 audit_rules 参数中:
json { "template_validation": { "enabled": true, "rules": { "rule_id": "TPL_001", "rule_name": "必需章节检查", "description": "检查文档是否包含所有必需的章节", "required_sections": \["摘要", "背景", "目标", "方案", "预算", "风险评估", "结论", "tolerance": 0.8, "applicable_types": "word", "ppt" }, { "rule_id": "TPL_002", "rule_name": "文档结构完整性", "description": "检查文档结构的层次是否合理", "min_heading_levels": 2, "max_heading_levels": 5, "require_toc": true, "applicable_types": "word" }, { "rule_id": "TPL_003", "rule_name": "Excel表格规范性", "description": "检查Excel表格的结构规范性", "require_header": true, "no_empty_cells_in_header": true, "no_completely_empty_rows": true, "applicable_types": "excel" }, { "rule_id": "TPL_004", "rule_name": "PPT结构完整性", "description": "检查PPT是否包含必要的页面", "require_cover_page": true, "require_toc_page": true, "require_end_page": true, "min_slides": 5, "max_slides": 50, "applicable_types": "ppt" }, { "rule_id": "TPL_005", "rule_name": "页眉页脚规范", "description": "检查是否包含正确的页眉页脚信息", "required_header_elements": "文档编号", "版本号", "日期", "required_footer_elements": "页码", "保密级别", "applicable_types": "word" } ] }, "data_compliance": { "enabled": true, "rules": { "rule_id": "COMP_001", "rule_name": "敏感信息检测", "description": "检测是否包含未脱敏的敏感信息", "sensitive_patterns": \[ { "type": "身份证号", "pattern": "\\d{17}\[\\dXx", "action": "flag", "allow_masked": true }, { "type": "手机号", "pattern": "13-9\d{9}", "action": "flag", "allow_masked": true }, { "type": "邮箱地址", "pattern": "a-zA-Z0-9._%±+@a-zA-Z0-9.-+.a-zA-Z{2,}", "action": "flag" }, { "type": "银行卡号", "pattern": "\d{16,19}", "action": "flag" } ], "applicable_types": "word", "excel", "ppt" }, { "rule_id": "COMP_002", "rule_name": "数据格式合规性", "description": "检查关键字段的数据格式是否符合规范", "field_validations": { "field_name": "金额", "expected_format": "number", "min_value": 0, "max_value": 1000000000, "decimal_places": 2, "allow_null": false }, { "field_name": "日期", "expected_format": "YYYY-MM-DD", "allow_null": false, "date_range": { "min": "2020-01-01", "max": "2030-12-31" } }, { "field_name": "百分比", "expected_format": "percentage", "min_value": 0, "max_value": 100, "allow_null": false }, { "field_name": "项目编号", "expected_format": "regex", "pattern": "\^PRJ-\[0-9{4}-0-9{3}KaTeX parse error: Expected 'EOF', got '}' at position 24: ...w_null": false }̲, { "field_name..." } ], "applicable_types": "excel" }, { "rule_id": "COMP_003", "rule_name": "必填字段检查", "description": "检查所有必填字段是否有值", "required_fields": "项目名称", "项目负责人", "开始日期", "结束日期", "预算金额", "项目状态" , "check_empty_string": true, "check_whitespace_only": true, "applicable_types": "excel", "word" }, { "rule_id": "COMP_004", "rule_name": "隐私合规检查", "description": "检查是否符合隐私保护要求", "check_personal_info_exposure": true, "require_consent_statement": false, "applicable_types": "word", "ppt" } ] }, "data_accuracy": { "enabled": true, "rules": { "rule_id": "ACC_001", "rule_name": "数值一致性校验", "description": "检查汇总数据与明细数据是否一致", "validation_type": "cross_check", "checks": \[ { "summary_field": "总预算", "detail_fields": \["人力成本", "设备成本", "材料成本", "其他成本", "tolerance": 0.01, "tolerance_type": "percentage" }, { "summary_field": "总人数", "detail_fields": "技术人员", "管理人员", "其他人员", "tolerance": 0 } ], "applicable_types": "excel" }, { "rule_id": "ACC_002", "rule_name": "逻辑合理性检查", "description": "检查数据的逻辑关系是否合理", "logic_rules": { "condition": "结束日期 \>= 开始日期", "error_message": "项目结束日期不能早于开始日期", "severity": "严重" }, { "condition": "实际进度 \<= 100%", "error_message": "项目进度不能超过100%", "severity": "严重" }, { "condition": "参与人数 \> 0", "error_message": "项目参与人数必须大于0", "severity": "中等" }, { "condition": "预算金额 \> 0", "error_message": "项目预算必须大于0", "severity": "中等" }, { "condition": "如果状态='已完成', 则实际进度=100%", "error_message": "已完成项目的进度应为100%", "severity": "严重" } , "applicable_types": "excel", "word" }, { "rule_id": "ACC_003", "rule_name": "历史数据对比", "description": "与历史数据进行对比,发现异常波动", "comparison_source": "knowledge_base", "knowledge_base_name": "historical_project_data", "threshold_percentage": 30, "alert_on_deviation": true, "fields_to_compare": "预算金额", "项目周期", "人员配置", "applicable_types": "excel" }, { "rule_id": "ACC_004", "rule_name": "计算公式验证", "description": "验证Excel中的计算公式是否正确", "check_formulas": true, "verify_calculation_accuracy": true, "applicable_types": "excel" }, { "rule_id": "ACC_005", "rule_name": "数据完整性检查", "description": "检查数据序列的完整性", "checks": { "field": "月份", "expected_sequence": "continuous", "allow_gaps": false }, { "field": "序号", "expected_sequence": "sequential", "start_from": 1, "allow_gaps": false } , "applicable_types": "excel" } ] }, "custom_rules": { "enabled": true, "rules": { "rule_id": "CUST_001", "rule_name": "专业术语规范性", "description": "检查是否使用了规范的专业术语", "terminology_source": "knowledge_base", "knowledge_base_name": "professional_terminology", "fuzzy_match": true, "similarity_threshold": 0.85, "applicable_types": \["word", "ppt" }, { "rule_id": "CUST_002", "rule_name": "引用完整性", "description": "检查文档中的引用是否有对应的参考文献", "check_citations": true, "check_references": true, "require_consistency": true, "applicable_types": "word" }, { "rule_id": "CUST_003", "rule_name": "图表规范性", "description": "检查图表是否有标题、编号和数据来源", "require_chart_title": true, "require_chart_number": true, "require_data_source": true, "applicable_types": "word", "ppt", "excel" }, { "rule_id": "CUST_004", "rule_name": "版本控制检查", "description": "检查文档版本信息是否完整", "require_version_number": true, "require_revision_date": true, "require_author_info": true, "applicable_types": "word", "ppt" } ] } }
4.2 简化版规则配置(适用于快速测试)
json { "template_validation": { "enabled": true, "rules": { "rule_id": "TPL_001", "rule_name": "基本结构检查", "description": "检查文档是否有基本的结构" } }, "data_compliance": { "enabled": true, "rules": { "rule_id": "COMP_001", "rule_name": "敏感信息检测", "description": "检测明显的敏感信息" } }, "data_accuracy": { "enabled": true, "rules": { "rule_id": "ACC_001", "rule_name": "基本逻辑检查", "description": "检查基本的逻辑关系" } }, "custom_rules": { "enabled": false, "rules": \[\] } }
五、LLM提示词集合
5.1 模板校验专用提示词
如果你的工作流需要分步骤审核,可以使用这个专门的模板校验提示词:
角色
你是一位文档结构和模板规范性审核专家。
任务
检查{{file_type}}文档的结构完整性和模板规范性。
审核要点
对于Word文档:
文档是否有清晰的标题层级(Heading 1, Heading 2等)
是否包含必需的章节(摘要、背景、主体、结论)
段落格式是否统一
是否有目录(如文档较长)
页眉页脚是否规范
对于Excel文档:
每个sheet是否有明确的名称
是否有表头行
表头是否为空
数据结构是否规整
是否有合并单元格影响数据处理
对于PPT文档:
是否有封面页
是否有目录页
是否有结束页
每页是否有清晰的标题
幻灯片数量是否合理
文档内容
{{{document_content}}}
输出格式
{ "score": 0-100, "passed": true/false, "issues": { "severity": "严重\|中等\|轻微", "description": "详细描述", "location": "位置", "suggestion": "改进建议" } , "comments": "总体评价" }
5.2 数据合规性专用提示词
角色
你是一位数据合规性和隐私保护专家。
任务
检测文档中的敏感信息和数据合规性问题。
检测项目
敏感信息检测
身份证号码(未脱敏)
手机号码(未脱敏)
邮箱地址
银行卡号
家庭住址
密码或密钥
数据格式合规
日期格式是否正确(YYYY-MM-DD)
金额格式是否规范
百分比是否在合理范围
枚举值是否符合定义
隐私保护
是否有个人隐私信息泄露
是否有商业机密暴露
是否需要脱敏处理
文档内容
{{{document_content}}}
输出格式
{ "score": 0-100, "passed": true/false, "sensitive_findings": { "type": "身份证号\|手机号\|邮箱\|其他", "location": "位置", "severity": "严重\|中等\|轻微", "sample": "脱敏后的样本", "suggestion": "处理建议" } , "format_issues": { "field": "字段名", "expected": "期望格式", "actual": "实际格式", "severity": "严重\|中等\|轻微" } , "recommendations": "建议1", "建议2" }
5.3 数据准确性专用提示词
角色
你是一位数据质量分析师,专注于数据准确性和逻辑一致性验证。
任务
验证文档中数据的准确性、一致性和逻辑合理性。
检查项目
数值一致性
汇总值与明细值是否一致
百分比计算是否正确
平均值、总计等统计值是否准确
逻辑合理性
日期关系是否合理(结束>=开始)
数值范围是否合理(进度0-100%)
因果关系是否成立
业务逻辑是否正确
数据完整性
是否有缺失值
是否有异常值
数据序列是否连续
必填字段是否完整
交叉验证
不同表格间的数据是否一致
文字描述与数据是否矛盾
图表数据与表格数据是否一致
文档内容
{{{document_content}}}
输出格式
{ "score": 0-100, "passed": true/false, "consistency_issues": { "type": "数值不一致\|逻辑错误\|数据缺失", "description": "问题描述", "location": "位置", "expected": "期望值", "actual": "实际值", "severity": "严重\|中等\|轻微", "impact": "影响说明" } , "data_quality_metrics": { "completeness": 0-100, "accuracy": 0-100, "consistency": 0-100 }, "recommendations": "建议1", "建议2" }
5.4 错误处理和调试提示词
当工作流出现问题时,可以使用这个提示词进行调试:
调试辅助提示词
你在审核过程中遇到了问题。请分析以下信息并给出诊断:
问题信息
文件类型:{{file_type}}
规则解析状态:{{审核规则解析.success}}
规则数量:{{审核规则解析.total_rules_count}}
文档长度:{{审核规则解析.document_summary.content_length}}
可能的问题
文件格式不支持或损坏
审核规则JSON格式错误
文档内容为空或无法解析
规则配置与文件类型不匹配
请输出
{ "diagnosis": "问题诊断", "possible_causes": "原因1", "原因2", "solutions": "解决方案1", "解决方案2", "can_proceed": true/false }
六、测试与优化
6.1 测试用例准备
测试文件1:Excel文档(有问题)
创建一个Excel文件,包含以下故意设置的问题:
Sheet1: 项目列表
项目名称
负责人
开始日期
结束日期
预算金额
状态
进度
项目A
张三
2024-01-01
2023-12-31
100000
进行中
50%
项目B
李四
2024-02-01
2024-08-01
-50000
已完成
100%
项目C
王五
2024-03-01
2024-09-01
200000
进行中
120%
赵六
2024-04-01
2024-10-01
150000
未开始
0%
问题点:
- 项目A:结束日期早于开始日期(逻辑错误)
- 项目B:预算为负数(不合理)
- 项目C:进度超过100%(不合理)
- 第4行:项目名为空(必填字段缺失)
测试文件2:Word文档(有问题)
创建一个Word文档,缺少必需章节,包含敏感信息:
项目方案
本项目旨在开发一个新的管理系统...
联系人:张三,电话:13800138000,身份证:110101199001011234
预算总计:100万元
(缺少背景、风险评估、结论等章节)
测试文件3:正常文档
创建一个符合规范的文档用于测试通过场景。
6.2 测试步骤
步骤1:在工作流中测试
- 打开Dify工作流编辑界面
- 点击右上角的 "运行" 或 "测试" 按钮
- 上传测试文件
- 填写审核规则(或使用默认)
- 点击 "运行"
- 查看输出结果
步骤2:检查结果
验证输出是否包含:
- ✓ 正确识别了所有问题
- ✓ 问题严重程度分级合理
- ✓ 提供了具体的改进建议
- ✓ JSON格式正确可解析
- ✓ 报告易于理解
步骤3:调整参数
根据测试结果调整:
- LLM温度值(降低以提高一致性)
- 提示词内容(增加或减少约束)
- 规则配置(调整阈值)
6.3 性能优化建议
优化1:减少Token消耗
在发送给LLM前,对文档内容进行预处理
只提取关键部分进行审核
设置合理的最大Token限制
优化2:提高响应速度
使用更快的模型(如GPT-3.5-Turbo用于初步筛选)
并行处理多个审核维度(如果Dify支持)
缓存常用的审核规则
优化3:提高准确性
增加few-shot示例(在提示词中给出示例)
使用思维链(Chain-of-Thought)提示
多次审核取共识(对重要文档)
6.4 监控和日志
添加日志记录节点
在工作流的关键节点后添加日志记录:
- 在"文件类型识别"后
- 在"文件内容提取"后
- 在"LLM智能审核"后
记录关键信息用于后续分析和优化。
七、常见问题
Q1: 文件解析失败怎么办?
A:
- 检查文件格式是否在支持列表中
- 确认文件没有损坏
- 查看Dify环境是否安装了必要的库(openpyxl, python-docx, python-pptx)
- 如果Dify沙箱不支持这些库,考虑:
- 使用HTTP请求节点调用外部解析服务
- 简化流程,让LLM直接处理文件
Q2: LLM输出的JSON格式不正确?
A:
- 在提示词中强调"不要包含markdown代码块标记"
- 在提示词末尾再次说明输出格式要求
- 在代码节点中添加JSON修复逻辑:
python import json import re
def fix_json_output(llm_output: str) -> dict: """修复LLM输出的JSON""" # 移除markdown代码块标记 cleaned = re.sub(r'
\s*', '', llm_output)
cleaned = re.sub(r'\s*$', '', cleaned) cleaned = cleaned.strip()
尝试解析
try:
return json.loads(cleaned)
except json.JSONDecodeError:
尝试修复常见的JSON错误
... 添加修复逻辑
raise
Q3: 审核结果不准确?
A:
- 优化提示词,增加更具体的审核标准
- 在提示词中提供示例(few-shot learning)
- 调整LLM温度值(降低到0.2-0.3)
- 使用更强的模型(如GPT-4)
- 拆分审核任务,每个类别单独审核
Q4: 如何处理大文件?
A:
- 在代码节点中添加文件大小检查
- 对超大文件进行截断或分段处理
- 提取关键信息进行审核,而非全文
- 增加最大Token限制
python MAX_CONTENT_LENGTH = 50000 # 限制内容长度
if len(document_content) > MAX_CONTENT_LENGTH: # 截取关键部分 document_content = document_content:MAX_CONTENT_LENGTH warning = "文档过长,仅审核前部分内容"
Q5: 如何集成到现有系统?
A:
- 在Dify中发布工作流为API
- 获取API端点和密钥
- 在RuoYi系统中创建前端页面
- 使用axios调用Dify API:
javascript // 在前端项目中 import axios from 'axios'
export function auditDocument(file, rules) { const formData = new FormData() formData.append('file', file) formData.append('audit_rules', JSON.stringify(rules))
return axios.post('http://your-dify-api/v1/workflows/run', formData, { headers: { 'Authorization': 'Bearer your-api-key', 'Content-Type': 'multipart/form-data' } }) }
Q6: 如何保存审核历史?
A:
- 在RuoYi后端创建审核记录表
- 每次审核后保存结果到数据库
- 创建查询接口用于查看历史记录
sql CREATE TABLE document_audit_log ( id BIGINT PRIMARY KEY AUTO_INCREMENT, file_name VARCHAR(255), file_type VARCHAR(10), audit_time DATETIME, overall_score INT, compliance_level VARCHAR(20), issue_count INT, audit_result TEXT, create_by VARCHAR(64), create_time DATETIME );
Q7: 如何自定义审核规则?
A:
- 创建规则管理界面
- 提供可视化规则编辑器
- 将规则保存到数据库
- 运行时动态加载规则
Q8: 审核速度慢怎么办?
A:
- 使用流式输出(如果Dify支持)
- 优化提示词长度
- 选择更快的模型
- 异步处理,先返回接收确认,完成后通知用户
八、进阶功能(可选)
8.1 添加知识库检索
- 在工作流中添加 "知识库检索" 节点
- 连接到之前创建的
document-audit-rules知识库 - 根据文档类型检索相关规则
- 将检索结果传递给LLM
8.2 添加人工复核环节
- 添加 "人工确认" 节点
- 对于严重问题,暂停工作流等待人工确认
- 人工确认后续审或终止
8.3 批量处理功能
- 修改开始节点,接受多个文件
- 添加循环处理逻辑
- 汇总所有文件的审核结果
8.4 生成可视化报告
- 添加代码节点生成HTML报告
- 包含图表展示问题分布
- 导出为PDF或HTML文件
九、工作流结构总结
完整的工作流节点顺序:
开始节点 ↓ 文件类型识别(代码节点) ↓ 检查文件类型识别结果(条件分支) ├─ 失败 → 返回错误信息(结束节点) └─ 成功 → 文件内容提取(代码节点) ↓ 审核规则解析(代码节点) ↓ 检查规则解析结果(条件分支) ├─ 失败 → 返回规则解析错误(结束节点) └─ 成功 → LLM智能审核(LLM节点) ↓ 结果格式化(代码节点) ↓ 输出审核报告(结束节点)
十、附录
A. 完整的变量引用列表
{{file}} # 用户上传的文件 {{audit_rules}} # 审核规则JSON {{template_name}} # 模板名称 {{strict_mode}} # 严格模式
{{文件类型识别.success}} # 文件类型识别是否成功 {{文件类型识别.file_type}} # 文件类型 {{文件类型识别.parser}} # 解析器 {{文件类型识别.extension}} # 文件扩展名 {{文件类型识别.error}} # 错误信息
{{文件内容提取.success}} # 文件提取是否成功 {{文件内容提取.file_type}} # 文件类型 {{文件内容提取.content}} # 解析后的内容 {{文件内容提取.full_text}} # 完整文本 {{文件内容提取.structure}} # 结构信息 {{文件内容提取.error}} # 错误信息
{{审核规则解析.success}} # 规则解析是否成功 {{审核规则解析.enabled_rules}} # 启用的规则 {{审核规则解析.total_rules_count}} # 规则数量 {{审核规则解析.document_summary}} # 文档摘要 {{审核规则解析.full_rules}} # 完整规则 {{审核规则解析.error}} # 错误信息
{{LLM智能审核.output}} # LLM输出结果
{{结果格式化.success}} # 格式化是否成功 {{结果格式化.report}} # 格式化后的报告 {{结果格式化.raw_result}} # 原始JSON结果 {{结果格式化.error}} # 错误信息