1. 项目概述当规则失效时记忆如何成为决策引擎的核心在财务自动化领域尤其是发票处理这个场景我们构建系统时最常依赖的就是规则。规则清晰、确定、易于维护比如“金额超过五万需人工审核”、“缺少供应商编号的发票直接拒绝”。这些规则构成了第一道防线能高效地拦截那些显而易见的错误或欺诈。然而在我深度参与构建名为Finley的智能决策引擎后我深刻地认识到一个残酷的现实规则能抓住的往往只是水面上的冰山一角。真正棘手、造成重大损失的问题——那些精心伪装的重复发票、供应商支付条款的缓慢漂移、或是基于历史行为的异常模式——都完美地避开了所有静态规则的检测。它们看起来就像一张张完全合规的普通发票。问题的核心在于静态规则缺乏“经验”。它不认识某个特定的供应商不知道这个供应商过去六个月里提交过三次金额极其相似的发票也不记得财务人员曾两次手动将他的付款条款从“Net-30”更正为“Net-45”。这些隐藏在历史交互中的“记忆”才是识别高级别风险的关键。Finley项目的核心就是探索如何将确定性的规则检查与基于记忆Memory的模式识别相结合构建一个既能快速处理常规事务又能像经验丰富的审计员一样“嗅出”微妙风险的智能体Agent。这不仅仅是技术的叠加更是一种思维范式的转变从“基于规则的过滤”转向“基于上下文的决策”。2. 决策引擎的双层架构设计解析Finley的决策流程被清晰地划分为两个阶段这种分离是系统设计的关键确保了逻辑的清晰和职责的单一。理解这个架构是理解其如何工作的第一步。2.1 分析器与决策构建器的职责分离整个决策过程始于一张待处理的发票。系统首先会通过OCR或结构化接口提取发票上的关键字段如发票号、金额、供应商、日期、行项目等。随后流程进入核心的两步第一步分析器Analyzer—— 上下文的理解者分析器的任务不是做最终决定而是生成一份全面的“体检报告”。它的输入有两部分一是当前提取的发票数据二是从记忆库我们称之为Hindsight中检索出的该供应商的历史交互记录。分析器通常由大语言模型驱动的工作是消化这些信息进行比对、推理和模式识别然后输出两种类型的信号flags风险标志和checks确定性检查结果。你可以把它想象成一位资深审计员他不仅看了当前这张发票还快速翻阅了这个供应商过去的档案然后在他的笔记上标出了可疑点和确认项。第二步决策构建器Decision Builder—— 逻辑的执行者决策构建器则简单、纯粹得多。它只接收分析器输出的那份“体检报告”即flags和checks的列表以及一个整体置信度分数。它不关心数据是怎么来的也不进行复杂的推理。它只是一套预先定义好的、确定性的逻辑规则根据报告中的内容机械地输出一个裁决批准、拒绝或标记待审。这种分离带来了巨大的好处可维护性复杂的、可能随模型能力变化的推理逻辑被封装在分析器中。而核心的业务裁决逻辑如“出现高风险标志就需人工审核”则稳定地留在决策构建器中即使未来更换分析模型裁决逻辑也无需改动。可解释性决策的依据被清晰地记录在分析输出中。我们不仅能知道最终结果还能知道是哪个具体问题如“疑似重复发票”触发了这个结果以及这个判断是基于规则还是基于历史模式。性能优化所有耗时的API调用如LLM推理、记忆检索都集中在分析阶段。决策阶段是轻量级的纯计算响应极快。代码层面这个流程非常简洁// Step 4: 上下文分析包含记忆检索与LLM推理 const analysis await analyzeInvoice(extractedInvoiceData, vendorMemory); // Step 5: 决策引擎纯规则逻辑 const decision buildDecision(analysis);2.2 确定性检查层快速拦截低级错误在调用任何复杂的LLM进行分析之前系统会先运行一层快速的、确定性的字段级检查。这就像海关的快速通关通道先把那些证件不全、信息明显矛盾的旅客筛出来无需惊动后面的专家。这些检查基于简单的布尔逻辑或算术计算速度极快成本几乎为零不消耗LLM Token并且结果100%可靠。常见的检查包括发票号是否存在!!extracted.invoiceId总金额是否与行项目合计匹配Math.abs(lineItemSum - extracted.totalAmount) 0.01考虑浮点数精度发票日期是否有效非未来日期供应商编号格式是否符合规范这些检查被组织成一个数组每个检查都有名称、通过状态和严重级别const checks [ { name: “Invoice ID present”, pass: !!extracted.invoiceId, severity: “error” }, { name: “Amount matches line items”, pass: Math.abs(lineItemSum - extracted.totalAmount) 0.01, severity: “warning” }, // ... 更多检查 ];任何一个检查失败pass: false并且其severity为”error”时决策构建器会直接走向“拒绝”的裁决流程可能就此终止无需进行更昂贵的后续分析。这确保了系统效率将计算资源留给真正需要智能分析的案例。2.3 记忆驱动的模式识别层智能的核心当发票通过了所有基础检查后才进入真正的智能环节。此时系统会从记忆库中检索该供应商最近、最相关的历史交互记录例如最近9次。这些“记忆”与当前发票的数据一起被构造成一个精心设计的提示词Prompt送入大语言模型LLM。LLM在此扮演的角色就是那位拥有“经验”的审计员。它被要求基于当前的“事实”发票数据和过去的“上下文”记忆进行推理识别静态规则无法定义的复杂模式。例如变体重复检测供应商“ABC公司”提交了一张金额为47500卢比的发票INV-2025-0009。记忆显示三周前该公司提交过金额完全相同的INV-2025-0007。更进一步的模式是该供应商在过去六个月内提交了3张金额高度相似的发票其中2张总额完全一致。静态的“完全重复发票号”规则对此无效但基于记忆的模式识别能立刻将其标记为“高风险疑似重复”。支付条款漂移当前发票注明付款条件为“Net-30”。但记忆显示财务人员曾两次手动将这家供应商的发票条款从“Net-30”更正为“Net-45”。这表明该供应商存在系统性错误或故意试探的行为。LLM可以识别出这种“历史纠正模式”并对当前发票的条款提出质疑。舍入异常模式某供应商的历史发票中总金额的小数部分经常出现0.50至2.00卢比的“舍入误差”这可能是其内部系统转换货币或计算税费时的特定缺陷。当一张新发票的金额是干净的整数如47500.00时LLM可以基于记忆指出“此金额干净无历史舍入错误特征”这反而成为一种反向的验证信号。关键在于这些模式并非预先硬编码的。我们并没有写一条规则说“如果同一供应商在三个月内出现两次金额差小于1%的发票则标记”。我们只是给了LLM历史和当前数据并训练它去发现其中的关联与异常。这种能力使得智能体能够随着时间推移自动学习并适应每个供应商独有的行为模式无需人工持续编写和维护日益复杂的规则库。3. 分析输出的结构化标志、检查与置信度分析器LLM的输出必须被严格结构化才能被下游的决策构建器可靠地消费。我们设计了一个包含三个关键部分的输出结构。3.1 风险标志与确定性检查的区分分析器会生成两个独立的列表这区分了“推测性发现”和“事实性验证”。flags风险标志代表分析器识别出的潜在问题或异常。每个flag都是一个对象包含类型、描述信息、严重程度highmediumlow以及一个至关重要的布尔字段——memoryBacked。memoryBacked: true表示这个标志是基于历史记忆的模式识别得出的例如“疑似重复因为三周前有相似金额”。memoryBacked: false表示这个标志是基于当前发票数据本身的推理但未依赖特定历史例如“发票描述过于模糊可能不符合公司政策”这基于LLM对描述文本的通用理解。checks确定性检查这个列表实际上承接并扩展了前置的确定性检查层。它包含一些LLM可以轻松验证的简单事实作为对之前程序化检查的补充或双重确认。例如“供应商是否在注册列表中”、“发票日期是否在财政年度内”。这些检查的pass字段是布尔值非常明确。一个典型的结构化输出如下所示{ “flags”: [ { “type”: “potential_duplicate”, “message”: “Similar invoice amount submitted 3 weeks ago (INV-2025-0007)”, “severity”: “high”, “memoryBacked”: true } ], “checks”: [ { “name”: “Vendor registered”, “pass”: true }, { “name”: “Invoice date valid”, “pass”: true } // ... ], “confidence”: 87 }3.2memoryBacked字段的设计哲学与意义memoryBacked字段是整个设计中的一个点睛之笔。它不仅仅是一个元数据更是一个信任度指示器。对于决策构建器它可以根据memoryBacked的值和severity来实施更精细的决策逻辑。例如系统可以设定对于memoryBacked: false的high风险标志或许可以设置一个更高的置信度阈值才触发“标记审核”而对于memoryBacked: true的high风险标志由于有具体的历史数据支撑可以更果断地要求审核。对于最终用户如财务审核员在用户界面上一个旁边带有“基于历史模式”图标的警告远比一个笼统的“疑似异常”更有说服力。审核员可以立刻看到依据“哦系统发现这个供应商过去有类似问题”这极大地提升了用户对AI建议的信任度和采纳率也简化了他们的判断过程。对于系统监控我们可以追踪memoryBacked标志的准确率。如果大量基于记忆的标志被用户推翻可能意味着记忆质量下降或检索策略需要调整。3.3 置信度分数的角色与局限输出中的confidence分数例如87代表了分析器对其整体分析结果的把握程度。这是一个由LLM生成的、介于0到100之间的数值。重要原则置信度应作为参考信息而非决定因素。我们的决策逻辑主要基于flags的severity。一个置信度为90%的“高风险重复发票”标志和一个置信度为70%的“高风险重复发票”标志在决策逻辑上应该导致相同的动作标记审核。置信度的价值体现在优先级排序在待审核队列中置信度高的项目可以排在前列。辅助人工判断审核员面对两个同类型风险时可以参考置信度分配注意力。内部监控与调试持续低置信度可能提示Prompt需要优化或记忆检索不相关。绝不能设计“置信度低于X则自动忽略该标志”的逻辑这会让系统变得不可预测并可能被低置信度的正确判断所绕过。4. 决策逻辑的构建与裁决流程决策构建器的逻辑需要简单、透明、可审计。它本质上是一个大的if-else或switch语句基于分析器的输出做出裁决。4.1 基于严重级别的裁决阈值我们采用了分层级的裁决逻辑优先处理最严重的问题任何severity: “error”的标志 → 自动拒绝这通常对应于前置确定性检查层发现的硬性错误如发票号缺失、金额不匹配。这类问题没有商量余地系统直接拒绝并给出明确原因。任何severity: “high”的标志 → 标记为待审核无论该标志是memoryBacked还是非memoryBacked只要被判定为高风险就必须交由人工最终裁定。这包括疑似重复、支付条款异常、与黑名单地址关联等。多个severity: “medium”的标志 → 标记为待审核单个中等风险可能可以放过但多个中等风险叠加其整体风险就可能升级。例如一张发票同时存在“描述模糊”中等风险和“金额略高于该供应商历史平均水平”中等风险的情况系统会将其标记出来。检查全部通过且无显著风险标志 → 自动批准这是最理想的流程发票完全合规且无异常模式系统自动完成处理极大提升效率。注意这里的“多个”需要明确定义一个阈值例如“2个”。这个阈值可以根据业务风险容忍度进行调整。在Finley的初版中我们设定为两个或以上的中等风险标志会触发审核。4.2 处理边缘情况与人工复核队列在实际运行中总会遇到一些落在阈值边缘的情况。我们的处理原则是宁严勿松。低风险low标志通常不会单独触发审核动作但会作为备注信息附加在发票记录中供后续查询或审计使用。如果一张发票只有低风险标志它会被自动批准。高置信度与低严重度即使置信度高达95%但只要标志的严重度是medium且未达到数量阈值仍然自动批准。反之即使置信度只有60%只要是high严重度也必须审核。这确保了安全底线。人工复核队列的设计被标记的发票会进入一个专门的复核工作台。工作台会清晰展示触发的具体flags及其详细信息包括memoryBacked的说明。所有checks的结果。分析器的原始confidence分数。该供应商相关的关键历史记忆片段用于提供上下文。 审核员做出“最终批准”或“最终拒绝”的决定后这个决定连同原因会被反馈回系统用于后续的学习和记忆更新。5. 系统当前局限与迭代方向没有任何系统是完美的尤其是在依赖机器学习和大语言模型的场景中。坦诚地识别当前设计的不足是持续改进的关键。5.1 记忆污染当用户行为误导智能体这是我们在实际测试中遇到的最严峻挑战。记忆库的质量直接决定了模式识别的有效性。如果记忆库里充满了“噪音”或错误的信号LLM就会学到错误的东西。问题场景假设系统标记了一张发票为“疑似重复”但审核员由于各种原因例如供应商解释这是合理的补充发票反复点击了“批准”。几次之后关于这个供应商的“疑似重复”标志其关联的历史结果就从“被标记”变成了“被批准”。当未来出现类似的疑似重复时LLM检索到这些历史可能会推理“历史上类似的发票都被批准了所以这张可能也没问题。” 这导致了系统判断力的“钝化”或误判。解决方案思路反馈质量监控我们需要建立一个元监控层追踪用户决策与AI建议的一致性。当系统发现某个用户或针对某个供应商其“批准”决策持续与AI的“高风险”建议相悖时应触发警报。记忆加权与衰减不是所有记忆都同等重要。可以引入权重机制例如近期记忆权重更高被AI正确预测用户采纳建议的记忆权重增加与AI建议相悖的用户决策其记忆权重降低或添加“争议”标记。人工校准入口提供管理员界面允许风控人员查看可能被“污染”的供应商记忆片段并进行手动清理或重新标记。这相当于给系统一个“重置”或“纠正”特定知识点的能力。5.2 检索瓶颈在浩瀚记忆中寻找最相关的片段我们使用的记忆库Hindsight存储了海量的历史交互。检索时我们通常使用基于向量相似度的语义搜索获取最相关的N条比如20条记忆。问题场景对于一个交易频繁的大型供应商其历史发票可能有成千上万张。当前发票金额是47500卢比。系统通过语义搜索基于供应商名、日期、项目描述等找回了最相关的20条记忆但这20条里可能恰好没有三周前那张金额也是47500卢比的发票它可能因为描述略有不同相似度排在第21位。于是一次本应被发现的重复支付风险就被漏掉了。解决方案思路混合检索策略结合语义搜索与精确过滤。在检索时除了用向量搜索找语义相关的记忆还应并行地使用精确查询例如“查找同一供应商在过去90天内金额在[47400 47600]这个狭窄区间的所有发票”。将两者的结果去重后合并能显著提高关键记忆的召回率。分层记忆结构将记忆按类型或关键维度分类存储。例如为每个供应商单独维护一个“金额-日期”的快速索引表专门用于重复检测。通用语义记忆则用于其他模式识别。检索后重排序先召回一个较大的候选集如100条然后使用一个更轻量级的、针对特定任务如重复检测训练的模型或规则对结果进行重排序确保最关键的证据排在前列。5.3 对LLM推理能力的过度依赖与可控性目前复杂的模式识别完全依赖LLM的推理能力这像是一个黑箱。我们输入发票和记忆它输出flags。虽然我们通过Prompt工程和结构化输出尽力引导但其内部推理过程仍不可控。潜在风险幻觉LLM可能基于模糊的记忆“脑补”出一个不存在的模式。不一致性相同的输入在不同时间或不同模型版本下可能产生略有不同的输出。解释成本虽然我们有message字段但向业务人员解释“为什么LLM认为这有问题”有时仍然困难。迭代方向可解释性增强要求LLM在输出flag时必须引用其做出判断所依据的具体记忆条目如“基于记忆#ID: 123中的记录”。这能让推理链条部分“白盒化”。规则与模型的混合对于一些逐渐清晰的高级模式可以设计“模式模板”。当LLM多次识别出某种模式后系统可以提示工程师“是否要将‘同一供应商N天内出现M次金额接近的发票’固化为一条可配置的规则” 这样成熟的模式可以沉淀为确定性规则减少对LLM的依赖。持续验证与评估建立测试集定期评估LLM输出flags的准确率、召回率特别是memoryBacked类标志的可靠性。根据数据驱动Prompt的迭代和模型的选择。6. 实战心得与避坑指南在构建和迭代Finley引擎的过程中我们积累了许多在文档中不会提及的经验和教训。这些实操细节往往决定了项目的成败。6.1 记忆库的设计与数据治理心得1记忆的“粒度”至关重要。最初我们将整张发票的JSON数据作为一条“记忆”存储。这导致检索时信息过于冗杂。后来我们改为存储“记忆片段”例如“事件提交发票INV-2025-0007金额47500日期2025-03-01结果被系统标记为疑似重复后经人工批准”。一个交互可能产生多个片段如“提交事件”、“风险标记事件”、“人工处理事件”。更细的粒度让检索更精准也让LLM更容易消化。心得2必须为记忆建立“失效”或“降权”机制。商业环境在变供应商行为在变。五年前某个供应商频繁出现舍入错误但可能在其升级系统后问题就解决了。如果记忆永远有效旧模式会干扰对新情况的判断。我们引入了“记忆有效期”概念对超过一定时间如2年的记忆自动降低其检索权重除非被频繁激活。避坑指南启动时的“冷启动”问题。新系统上线时记忆库是空的。此时模式识别层完全无效系统只能依赖规则层。这会导致初期价值不明显。我们的解决方案是预加载历史数据将过去1-2年的历史发票和审核记录经过清洗后作为初始记忆导入。模拟运行在正式上线前用过去的数据“回测”系统看看如果有记忆它能抓住多少问题。这既能验证效果也能生成一批初始记忆。设置学习期明确告知用户系统在前1-3个月处于“学习期”其基于记忆的建议可能不成熟需人工重点复核。6.2 Prompt工程的结构化与稳定性心得3用严格的输出格式约束LLM的“创造力”。我们要求LLM的输出必须是严格的JSON格式并提供了详细的Schema描述包括flags数组里每个对象的字段、checks列表、confidence是整数等。在Prompt中我们甚至提供了多个清晰的正确输出示例。这大大减少了输出解析失败的情况。同时在代码中要有健壮的解析逻辑对格式错误的输出有降级处理方案例如触发人工审核并报警。心得4在Prompt中明确“思考框架”和“决策边界”。不要只是让LLM“分析一下这张发票”。而是要在Prompt里给它一个分析框架例如“请按以下步骤思考1. 检查基础矛盾数据是否自洽。2. 对比历史记忆寻找重复或近似重复模式。3. 检查是否存在偏离该供应商常见行为的异常如条款、金额、描述。4. 综合以上列出风险标志和确定性检查。” 这能引导LLM进行更结构化、更可靠的推理。避坑指南警惕Prompt的“隐形变更”。LLM服务提供商可能会在不通知的情况下更新模型。今天有效的Prompt明天可能效果打折。必须为分析器的输出质量建立监控指标如标志的触发率、人工复核后标志的确认率。当指标发生显著波动时应首先排查是否是模型更新导致的Prompt失效。6.3 集成与部署的实际考量心得5决策引擎应作为独立服务部署。不要将分析逻辑直接耦合在核心业务流程代码中。应该将其封装成一个独立的微服务如Decision-Engine-Service。这带来了巨大好处独立伸缩分析任务尤其是LLM调用是计算密集型和延迟敏感型可以独立于业务API进行扩容。技术选型灵活可以在这个服务内方便地切换不同的LLM提供商、调整Prompt、升级记忆检索算法而无需触动主业务代码。便于监控和日志记录所有决策请求、分析输入输出、耗时都可以集中记录便于审计和问题排查。心得6实施完善的降级策略。任何依赖外部APILLM服务、向量数据库的系统都必须有降级方案。我们的策略是超时控制给分析器设置严格的超时如5秒。如果超时则跳过基于记忆的复杂分析仅执行前置的确定性检查并给出“分析超时建议人工复核”的结论。故障回退如果LLM服务或记忆检索服务完全不可用系统自动切换到“仅规则模式”确保基础业务流程不中断。结果缓存对于完全相同的发票数据在极短时间内重试可以返回缓存的分析结果避免重复计算和消耗。避坑指南成本控制与优化。LLM的Token消耗是主要成本。优化措施包括记忆检索的精简不要盲目返回大量记忆。通过更好的检索查询只取最相关的5-10条往往能达到与20条相似的效果但Prompt长度大幅缩短。压缩历史记忆在将记忆插入Prompt前可以用一个小模型或简单算法对长文本记忆进行摘要保留核心信息如“2025-03-01 金额47500 重复嫌疑 已批准”丢弃无关细节。异步与批处理对于非实时性要求极高的场景可以将发票分析任务放入队列进行小批量处理某些LLM API的批量调用有费率优惠。构建这样一个融合规则与记忆的智能决策引擎是一个持续迭代和平衡的过程。规则提供了确定性和效率的基石而记忆赋予了系统学习和适应复杂性的能力。最大的收获在于认识到真正的智能自动化不是用AI完全取代人而是用AI放大人的经验将人类从枯燥的规则核对中解放出来聚焦于那些真正需要专业判断的、模棱两可的复杂案例上。系统的价值最终体现在它能让整个团队的经验得以沉淀、复用和规模化让每一张经过处理的发票都让系统变得更聪明一点。