
最近在尝试将AI能力集成到日常办公流程中发现一个普遍痛点处理PDF、Word、Excel等文档时往往需要多个工具来回切换手动复制粘贴、格式转换、数据提取过程繁琐且容易出错。无论是财务对账、合同审核还是报告生成这些重复性的文档工作流Document Workflows消耗了大量开发者和业务人员的时间。本文要探讨的正是利用AI Agents智能体来自动化解决这些文档工作流难题。我们将从一个具体的业务场景出发拆解如何构建一个能够理解文档内容、执行复杂任务链的AI智能体并提供从环境搭建、核心代码到部署上线的完整实战指南。无论你是想提升个人效率还是为企业构建自动化流程这套方案都能提供直接的参考和复现路径。1. 理解核心概念AI Agents 与文档工作流在深入实战之前我们有必要厘清几个关键概念这有助于理解我们到底要构建什么以及为什么选择AI Agents这个技术路径。1.1 什么是文档工作流Document Workflows文档工作流指的是围绕文档处理的一系列有序任务。它不仅仅是打开一个文件那么简单而是一个包含多个步骤、可能涉及决策和分支的完整过程。一个典型的文档工作流可能包含以下环节文档摄入从邮箱、云盘、扫描仪等渠道获取原始文档如PDF发票、Word合同、Excel报表。内容提取从文档中识别并提取关键信息例如发票号、金额、日期、合同条款、表格数据。数据验证与处理将提取的数据与数据库记录进行比对、校验逻辑如金额合计、或进行格式转换。决策与路由根据处理结果决定下一步动作例如审批通过则归档金额异常则触发人工审核信息缺失则退回补全。输出与集成生成新的文档如审核报告、汇总表格、更新业务系统、或通过邮件/消息通知相关人员。传统上这类工作流严重依赖人工操作或需要开发复杂的、规则固定的脚本如使用Python的pdfplumber、openpyxl库。后者在面对文档格式多变、内容非结构化时显得非常脆弱。1.2 AI Agents 如何赋能文档工作流AI Agent或称智能体在此语境下指的是一个能够感知环境读取文档、接收指令、进行规划拆解任务、调用工具使用函数、并执行行动以达到目标的自主或半自主程序。将AI Agents应用于文档工作流意味着理解而非解析Agent可以利用大语言模型LLM的语义理解能力去“读懂”文档内容即使文档格式不统一、文字排版非常规也能准确提取信息。动态规划与决策Agent可以根据当前文档的内容和预设目标动态规划处理步骤。例如遇到一份包含多个附表的合同它能自主决定先总结主合同条款再逐一提取附表关键信息。多工具协调一个强大的Agent可以调用一系列工具Tools如专用OCR接口、计算器、数据库查询API、文档生成库等形成一个处理流水线。处理复杂性与不确定性对于规则模糊或需要上下文判断的任务如“判断这份申请是否符合公司政策”Agent可以提供推理过程和建议而不仅仅是二值输出。简而言之AI Agent将文档处理从“基于固定规则的解析”升级为“基于理解与推理的自动化”。1.3 相关技术栈与工具在开始构建之前了解生态中的相关工具很有帮助LLM API提供核心的推理与理解能力。如 OpenAI GPT-4/3.5、 Anthropic Claude、国内的通义千问、文心一言等。AI Agent 框架帮助管理Agent的思维链、工具调用、记忆等。如LangChain、LlamaIndex、AutoGen、Semantic Kernel等。本文将主要使用LangChain因其生态丰富、文档完善。文档加载与处理库用于读取各种格式的文档并将其转换为LLM能处理的文本。如PyPDF2/pdfplumber/pymupdfPDF、python-docxWord、openpyxl/pandasExcel、langchain.document_loaders下的各种集成。向量数据库与检索当需要处理大量文档并基于文档内容进行问答时使用。如Chroma、Weaviate、Pinecone、Milvus。本文的单一文档处理流程暂不深入此部分。编排与部署将Agent流程服务化。如使用FastAPI构建API使用Docker容器化或使用Dify、Flowise等低代码平台进行可视化编排。网络热词中提到的“dify本地部署文档分割工具”正是此类平台的应用。2. 环境准备与项目初始化我们假设要构建一个“智能发票处理Agent”它能接收PDF发票自动提取关键字段发票号码、日期、销售方、购买方、金额、税额等并结构化输出为JSON同时能对异常数据如金额不符进行简单校验。2.1 环境与版本说明操作系统Windows 10/11, macOS, 或 Linux (Ubuntu 20.04) 均可。本文命令以Linux/macOS的bash为例Windows用户可在PowerShell或WSL中操作。Python版本 3.8 至 3.11。推荐使用 3.9 或 3.10以获得最佳的库兼容性。可使用python --version检查。包管理工具使用pip进行安装。强烈建议使用虚拟环境venv或conda隔离项目依赖。关键依赖库langchain核心Agent框架。langchain-openaiLangChain的OpenAI集成如果你使用OpenAI模型。openaiOpenAI官方Python SDK。pymupdf(又名fitz)强大的PDF文本和图像提取库。python-dotenv管理环境变量如API密钥。注意具体版本号可能随时间更新以下版本在撰写时已验证可用。请根据实际情况调整。2.2 项目初始化与依赖安装创建项目目录并进入mkdir ai-document-agent cd ai-document-agent创建并激活Python虚拟环境# 使用 venv python -m venv venv # 激活 (Linux/macOS) source venv/bin/activate # 激活 (Windows PowerShell) # .\venv\Scripts\Activate.ps1创建依赖文件requirements.txtlangchain0.1.0 langchain-openai0.0.5 openai1.12.0 pymupdf1.23.8 python-dotenv1.0.0 pydantic2.5.0 # LangChain 常用数据验证 # 可选用于更复杂的PDF或需要OCR时安装 # pdfplumber0.10.3 # pillow10.1.0 # pytesseract0.3.10安装依赖pip install -r requirements.txt准备配置文件 创建.env文件来存储敏感信息切勿提交到版本控制系统# .env OPENAI_API_KEY你的OpenAI_API密钥 # 如果使用其他模型如Azure OpenAI或国内模型此处配置相应的密钥和端点 # AZURE_OPENAI_API_KEY... # AZURE_OPENAI_ENDPOINT...项目结构预览ai-document-agent/ ├── .env # 环境变量密钥 ├── requirements.txt # 项目依赖 ├── main.py # 主程序入口 ├── agents/ # Agent相关模块 │ ├── __init__.py │ ├── invoice_agent.py # 发票处理智能体 │ └── tools.py # 自定义工具集 ├── documents/ # 存放待处理的文档 │ └── sample_invoice.pdf ├── utils/ # 工具函数 │ ├── __init__.py │ ├── document_loader.py # 文档加载器 │ └── validators.py # 数据验证器 └── outputs/ # 处理结果输出目录3. 核心组件拆解构建Agent的基石一个功能完整的AI Agent通常由几个核心部分组成模型LLM、提示词Prompt、工具Tools、记忆Memory和执行链Chain/Agent Executor。对于文档工作流我们重点关前三个。3.1 文档加载与预处理这是第一步目标是将二进制或特定格式的文档转化为纯文本或结构化数据供LLM理解。我们创建一个通用的文档加载器。# utils/document_loader.py import fitz # PyMuPDF from typing import Optional, Dict, Any import logging logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) class PDFDocumentLoader: 使用 PyMuPDF 加载和提取PDF文本内容。 def __init__(self, file_path: str): self.file_path file_path self.doc None def load(self) - Optional[str]: 加载PDF并提取所有文本。 try: self.doc fitz.open(self.file_path) full_text for page_num in range(len(self.doc)): page self.doc[page_num] full_text page.get_text() logger.info(f成功加载PDF: {self.file_path}, 共 {len(self.doc)} 页。) return full_text except Exception as e: logger.error(f加载PDF失败 {self.file_path}: {e}) return None finally: if self.doc: self.doc.close() def extract_metadata(self) - Dict[str, Any]: 提取PDF元数据如作者、标题等。 metadata {} try: with fitz.open(self.file_path) as doc: metadata doc.metadata except Exception as e: logger.error(f提取元数据失败: {e}) return metadata # 示例用法 if __name__ __main__: loader PDFDocumentLoader(./documents/sample_invoice.pdf) text loader.load() if text: print(f提取文本前500字符\n{text[:500]}...) print(f元数据{loader.extract_metadata()})为什么选择PyMuPDF相比PyPDF2它在处理复杂排版、非嵌入字体PDF时提取文本更准确相比pdfplumber它速度通常更快且不依赖pdfminer。对于需要OCR的扫描件可以集成pytesseract但本文聚焦于文本型PDF。3.2 设计提示词Prompt提示词是引导LLM行为的关键。我们需要设计一个系统提示词明确告诉AI Agent它的角色、任务、输出格式和规则。# agents/invoice_agent.py 的一部分 from langchain.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate # 系统提示词模板 SYSTEM_PROMPT_TEMPLATE 你是一个专业的财务助理AI专门处理发票信息提取与审核。 你的任务是从用户提供的发票文本中准确提取出以下结构化信息 **必须提取的字段** 1. invoice_number (发票号码): 字符串。 2. invoice_date (开票日期): 格式化为 YYYY-MM-DD。 3. seller_name (销售方名称): 字符串。 4. buyer_name (购买方名称): 字符串。 5. total_amount (价税合计/总金额): 浮点数单位元。 6. tax_amount (税额): 浮点数单位元。 7. amount_without_tax (不含税金额): 浮点数单位元。 **处理规则** 1. 仔细阅读全文确保信息提取自发票正文而非页眉页脚或其他无关文字。 2. 如果某个字段在发票中明确不存在将其值设置为 null。 3. 金额类字段请确保是数字并去除“¥”、“元”等货币符号。 4. 日期请统一转换。 5. 最终输出 **必须且只能** 是一个合法的JSON对象包含上述7个字段。 **输出示例** {{ invoice_number: 12345678, invoice_date: 2023-10-27, seller_name: 某某科技有限公司, buyer_name: 示例有限公司, total_amount: 11800.00, tax_amount: 1800.00, amount_without_tax: 10000.00 }} 现在开始处理以下发票文本 # 构建LangChain提示词 def create_invoice_extraction_prompt(): system_message_prompt SystemMessagePromptTemplate.from_template(SYSTEM_PROMPT_TEMPLATE) human_message_prompt HumanMessagePromptTemplate.from_template({invoice_text}) chat_prompt ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt]) return chat_prompt提示词设计要点角色定义让AI进入特定角色“专业财务助理”有助于其理解任务背景。任务明确清晰列出需要提取的字段及其格式。规则具体说明如何处理缺失值、格式化数据避免歧义。输出约束强制要求JSON格式这是与程序交互的关键。示例驱动提供一个输出示例让LLM更好地遵循格式。3.3 创建自定义工具Tools工具是Agent的“手”和“脚”。除了LLM自身的推理Agent可以调用外部函数来完成特定任务。我们创建两个工具一个用于计算校验一个用于格式化输出。# agents/tools.py from langchain.tools import tool from typing import Optional import json import logging logger logging.getLogger(__name__) tool def validate_amounts(total: float, tax: float, subtotal: float) - dict: 验证发票金额的逻辑正确性。 规则不含税金额 税额 应等于价税合计金额允许微小浮点数误差。 参数 total: 价税合计 tax: 税额 subtotal: 不含税金额 返回 包含验证结果和消息的字典。 tolerance 0.01 # 允许1分钱的误差 calculated_total subtotal tax is_valid abs(calculated_total - total) tolerance result { is_valid: is_valid, total_provided: total, total_calculated: round(calculated_total, 2), difference: round(abs(calculated_total - total), 2), message: } if is_valid: result[message] 金额校验通过。 else: result[message] f金额校验失败发票合计{total}但计算值({subtotal}{tax})为{calculated_total}差额{result[difference]}元。请人工复核。 logger.warning(result[message]) return result tool def save_to_json(data: dict, filename: Optional[str] None) - str: 将提取的数据保存为JSON文件。 参数 data: 要保存的字典数据。 filename: 自定义文件名。如果为None则使用发票号码。 返回 保存的文件路径。 import os import time # 生成文件名 if filename is None: invoice_num data.get(invoice_number, unknown) filename finvoice_{invoice_num}_{int(time.time())}.json else: if not filename.endswith(.json): filename .json output_dir ./outputs os.makedirs(output_dir, exist_okTrue) filepath os.path.join(output_dir, filename) try: with open(filepath, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2) msg f数据已成功保存至{filepath} logger.info(msg) return msg except Exception as e: error_msg f保存JSON文件失败{e} logger.error(error_msg) return error_msg # 工具列表方便后续添加到Agent CUSTOM_TOOLS [validate_amounts, save_to_json]工具设计思想tool装饰器LangChain用于将普通函数声明为Agent可调用工具的标准方式。单一职责每个工具只做一件事。validate_amounts负责业务逻辑校验save_to_json负责持久化。清晰的文档字符串这会被LangChain用于生成工具描述帮助LLM理解何时调用该工具。健壮性包含错误处理和日志记录。4. 完整实战构建并运行发票处理AI Agent现在我们将所有组件组装起来创建一个可以执行完整工作流的Agent。4.1 主Agent逻辑实现# agents/invoice_agent.py import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.agents import AgentExecutor, create_react_agent from langchain.memory import ConversationBufferMemory from langchain import hub # 用于拉取预设的Agent提示词 # 导入我们之前创建的模块 from utils.document_loader import PDFDocumentLoader from .tools import CUSTOM_TOOLS from .prompts import create_invoice_extraction_prompt # 假设提示词函数移到了prompts.py # 加载环境变量 load_dotenv() class InvoiceProcessingAgent: def __init__(self, model_name: str gpt-3.5-turbo, temperature: float 0): 初始化发票处理Agent。 参数 model_name: 使用的LLM模型名称。 temperature: 模型创造性0表示更确定性输出。 # 1. 初始化LLM self.llm ChatOpenAI( modelmodel_name, temperaturetemperature, openai_api_keyos.getenv(OPENAI_API_KEY) ) # 2. 初始化工具 self.tools CUSTOM_TOOLS # 3. 初始化记忆虽然本例是单次任务但保留记忆接口以备扩展 self.memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 4. 从LangChain Hub拉取一个强大的ReAct Agent提示词并融合我们的自定义提示词 base_prompt hub.pull(hwchase17/react-chat) # 5. 创建Agent self.agent create_react_agent( llmself.llm, toolsself.tools, promptbase_prompt, # 使用ReAct框架的基础提示词 ) # 6. 创建执行器 self.agent_executor AgentExecutor( agentself.agent, toolsself.tools, memoryself.memory, verboseTrue, # 开启详细日志看到Agent的“思考过程” handle_parsing_errorsTrue, # 处理输出解析错误 max_iterations5, # 限制最大迭代步骤防止死循环 ) # 7. 用于信息提取的专用提示词不用于Agent用于前置步骤 self.extraction_prompt create_invoice_extraction_prompt() def extract_invoice_info(self, pdf_path: str) - dict: 步骤1使用LLM从PDF文本中提取结构化信息。 print(f步骤1正在从 {pdf_path} 提取文本...) loader PDFDocumentLoader(pdf_path) invoice_text loader.load() if not invoice_text: raise ValueError(f无法从 {pdf_path} 加载或提取文本。) print(步骤2调用LLM进行信息提取...) # 构建消息链并调用LLM messages self.extraction_prompt.format_messages(invoice_textinvoice_text[:6000]) # 限制文本长度 response self.llm.invoke(messages) # 解析LLM的响应应为JSON字符串 try: import json # 尝试从响应内容中查找JSON块 content response.content # 简单的JSON提取实际应用中可能需要更健壮的解析 start_idx content.find({) end_idx content.rfind(}) 1 if start_idx ! -1 and end_idx ! 0: json_str content[start_idx:end_idx] extracted_data json.loads(json_str) print(信息提取成功。) return extracted_data else: raise json.JSONDecodeError(未找到JSON结构, content, 0) except json.JSONDecodeError as e: print(fLLM响应解析为JSON失败: {e}) print(f原始响应内容:\n{content}) # 可以在这里加入重试或人工干预逻辑 return {} def process_invoice(self, pdf_path: str): 主流程处理一张发票PDF。 print(f\n{*50}) print(f开始处理发票: {pdf_path}) print(f{*50}) # 阶段A信息提取 invoice_data self.extract_invoice_info(pdf_path) if not invoice_data: print(信息提取失败流程终止。) return print(f提取的原始数据: {invoice_data}) # 阶段B使用Agent进行校验与保存 print(\n步骤3启动AI Agent进行数据校验与持久化...) # 构造给Agent的输入 agent_input f 我刚刚从发票中提取了以下数据 {invoice_data} 请你执行以下任务 1. 使用工具验证金额字段total_amount, tax_amount, amount_without_tax的逻辑是否正确。 2. 如果验证通过将数据保存为一个JSON文件。 3. 如果验证不通过请告诉我具体问题。 try: result self.agent_executor.invoke({input: agent_input}) print(f\nAgent执行结果: {result[output]}) except Exception as e: print(fAgent执行过程中出现错误: {e}) print(f\n发票 {pdf_path} 处理流程结束。) print(f{*50}) # 主程序入口 if __name__ __main__: # 初始化Agent print(初始化发票处理AI Agent...) agent InvoiceProcessingAgent(model_namegpt-3.5-turbo) # 可替换为 gpt-4 以获得更好效果 # 指定要处理的PDF文件路径 sample_pdf ./documents/sample_invoice.pdf # 请在此处放置你的示例发票PDF # 运行处理流程 if os.path.exists(sample_pdf): agent.process_invoice(sample_pdf) else: print(f示例文件不存在: {sample_pdf}) print(请将PDF发票文件放入 ./documents/ 目录下。)4.2 准备示例发票并运行准备示例PDF在./documents/目录下放置一个名为sample_invoice.pdf的发票文件可以是任意包含中文或英文的文本型PDF发票。运行程序cd /path/to/ai-document-agent source venv/bin/activate # 激活虚拟环境 python -m agents.invoice_agent # 或者直接运行 python main.py (如果你创建了main.py来调用)4.3 预期输出与解析程序运行后你将在控制台看到类似以下的详细输出初始化发票处理AI Agent... 开始处理发票: ./documents/sample_invoice.pdf 步骤1正在从 ./documents/sample_invoice.pdf 提取文本... 步骤2调用LLM进行信息提取... 信息提取成功。 提取的原始数据: {invoice_number: 24408193, invoice_date: 2024-04-01, ...} 步骤3启动AI Agent进行数据校验与持久化... Entering new AgentExecutor chain... 我需要先验证金额然后保存数据。 首先我应该使用验证工具检查金额是否正确。 Action: validate_amounts Action Input: {total: 11800.0, tax: 1800.0, subtotal: 10000.0} Observation: {is_valid: true, total_provided: 11800.0, ... , message: 金额校验通过。} 金额验证通过了。现在我需要保存数据。 Action: save_to_json Action Input: {data: {invoice_number: 24408193, invoice_date: 2024-04-01, ...}, filename: null} Observation: 数据已成功保存至./outputs/invoice_24408193_1712345678.json 现在我可以总结一下了。 Thought: 我已经完成了所有任务验证了金额并保存了数据。 Final Answer: 发票数据已成功处理。金额校验通过数据已保存至 ./outputs/invoice_24408193_1712345678.json。 Finished chain. Agent执行结果: 发票数据已成功处理。金额校验通过数据已保存至 ./outputs/invoice_24408193_1712345678.json。 发票 ./documents/sample_invoice.pdf 处理流程结束。 过程解析文本提取PDFDocumentLoader读取PDF并输出纯文本。信息提取专用提示词引导LLM从文本中精准提取7个字段并以JSON格式返回。Agent执行思考ThoughtAgent根据指令“验证并保存”规划行动。行动Action决定调用validate_amounts工具。观察Observation工具返回校验结果。再思考根据结果校验通过决定下一步调用save_to_json。再行动与观察调用保存工具并收到成功消息。最终回答Final AnswerAgent总结任务完成。至此一个能够自动读取PDF发票、提取信息、进行业务逻辑校验并保存结果的AI Agent就成功运行了。5. 常见问题与排查思路在实际部署和运行中你可能会遇到以下问题问题现象可能原因排查思路与解决方案ModuleNotFoundError: No module named fitzPyMuPDF安装不正确。PyMuPDF的导入名是fitz但包名是pymupdf。确保使用pip install pymupdf安装。LLM返回内容不是有效JSON1. 提示词约束不够强。2. 提取的文本噪音太大干扰了LLM。3. 模型本身“不听话”。1. 强化提示词中的输出格式指令使用更严格的示例。2. 在document_loader中增加文本清洗步骤移除页眉页脚、无关字符。3. 使用更强大的模型如GPT-4或在调用后加入输出解析Output Parser例如使用LangChain的JsonOutputParser进行重试和格式化。Agent陷入循环或调用错误工具1. Agent提示词ReAct对工具描述不清。2.max_iterations设置过高。3. 工具返回的结果格式让Agent困惑。1. 检查工具函数的文档字符串是否清晰描述了功能和参数。2. 适当降低max_iterations如设为3-5。3. 确保工具返回的是简单、清晰的字符串或字典。可在AgentExecutor中设置early_stopping_methodgenerate。处理扫描版PDF或图片发票失败文档加载器只能提取文本无法处理图像中的文字。集成OCR能力。方案1. 使用pdf2image将PDF页面转为图片。2. 使用pytesseractTesseract OCR引擎的Python封装或调用云OCR API如百度OCR、阿里云OCR识别图片中的文字。3. 将识别后的文本送入后续流程。API调用超时或报错1. 网络问题。2. API密钥错误或额度不足。3. 请求速率超限。1. 检查网络连接。2. 确认.env文件中的OPENAI_API_KEY正确无误并在OpenAI平台检查余额和用量。3. 在代码中增加重试机制和指数退避或降低请求频率。提取的信息不准确1. PDF文本提取质量差如文字为曲线、编码问题。2. 发票格式与提示词预设差异大。3. LLM理解偏差。1. 尝试换用pdfplumber或调整PyMuPDF的提取参数。2. 丰富提示词加入更多发票格式的示例Few-Shot Learning。3. 考虑使用函数调用Function Calling或结构化输出Structured Output等更可靠的技术替代纯文本提示词提取。6. 最佳实践与进阶优化方向构建用于生产环境的文档AI Agent需要考虑更多工程化因素。6.1 提示词工程优化少样本学习Few-Shot在系统提示词中提供2-3个不同格式发票的文本片段和对应的正确JSON输出能极大提升模型在复杂场景下的准确性。输出结构化使用LangChain的StructuredOutputParser、PydanticOutputParser或LLM原生的函数调用功能强制模型输出结构化的数据对象比解析自由文本JSON更可靠。链式思考Chain-of-Thought对于非常复杂的文档如多页合同可以设计多步提示词。第一步总结章节第二步针对特定章节提取条款第三步整合。这可以通过LangChain的SequentialChain实现。6.2 工程与部署建议异步处理如果处理大量文档使用asyncio和langchain.callbacks进行异步调用提升吞吐量。配置管理将模型类型、API端点、温度等参数外置到配置文件如config.yaml中便于不同环境切换。日志与监控集成像structlog或loguru这样的日志库记录每个处理步骤、API调用耗时和费用便于问题追踪和成本分析。错误处理与重试为LLM API调用、工具调用添加完善的try-except块和重试逻辑如使用tenacity库。容器化部署使用Docker将整个应用及其依赖打包确保环境一致性。编写Dockerfile和docker-compose.yml。API服务化使用FastAPI或Flask将Agent封装成REST API提供/process_invoice等端点方便与其他系统集成。6.3 扩展复杂工作流本文的Agent是顺序执行提取→校验→保存。更复杂的工作流可以是自主决策型的。例如条件路由根据发票金额大小决定走快速通道还是人工审核通道。多Agent协作设计一个“调度Agent”接收任务根据文档类型发票、合同、简历调用不同的“专家Agent”进行处理。与知识库结合将历史处理过的发票信息存入向量数据库。当新发票来时Agent可以先检索类似发票的处理记录作为参考。人类在环Human-in-the-loop当Agent置信度低或校验失败时自动生成一个待办事项发送到企业微信/钉钉/Slack等待人工确认。6.4 关于网络热词的延伸Dify与可视化编排网络热词中提到了“dify本地部署文档分割工具”。Dify、Flowise等低代码AI应用平台其核心价值在于可视化编排复杂的工作流。在我们的代码示例中工作流是硬编码在process_invoice函数里的。而在Dify这样的平台上你可以通过拖拽节点文档加载、文本分割、LLM调用、条件判断、工具调用、数据保存来构建这个流程无需编写大量胶水代码。这对于业务人员快速原型设计或管理非常复杂的多分支工作流尤其有用。你可以将本文中开发的PDFDocumentLoader和validate_amounts工具封装成API然后作为自定义工具接入Dify从而享受可视化编排的好处。构建一个解决实际问题的AI Agent是一个迭代过程。从本文这个可运行的发票处理示例开始你可以逐步融入更强大的工具、更精细的提示词、更健壮的架构最终将其打造成一个能够处理各类文档、真正提升团队效率的智能自动化中枢。