三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

基于EdgeOne Makers与CodeBuddy构建安全AI Agent:实现自动化对账核对

基于EdgeOne Makers与CodeBuddy构建安全AI Agent:实现自动化对账核对

1. 项目概述:一个能“看懂”账单的AI助手

最近在折腾一个挺有意思的东西:用腾讯云EdgeOne Makers和CodeBuddy,从零开始搭了一个专门处理对账核对任务的AI Agent。简单来说,就是造一个“数字员工”,它能自动读取不同格式的账单(比如Excel、PDF、甚至是截图),理解里面的金额、日期、项目,然后帮你找出两边数据不一致的地方,最后还能生成一份清晰的差异报告。

这想法源于我自己的痛点。无论是做自由职业接项目,还是处理公司内部的一些报销、供应商结算,每个月总有那么几天要埋头在一堆表格里“找不同”。人工核对不仅耗时,还容易因为疲劳而出错。市面上虽然有一些财务软件,但要么流程僵化,要么价格不菲,对于中小团队或者个人开发者来说,定制化成本太高。而现在的AI,特别是大语言模型(LLM),在理解非结构化文本和进行逻辑推理上已经相当成熟,让它来干这种重复性的“找茬”工作,再合适不过。

EdgeOne Makers和CodeBuddy这个组合,正好解决了AI Agent落地中最头疼的几个问题:环境隔离代码安全执行。EdgeOne Makers提供了Serverless函数和边缘网络,能让我们的Agent服务快速部署、全球低延迟访问;而CodeBuddy则是一个安全的代码执行沙箱(Sandbox),它允许AI生成的代码在一个受控的环境里运行,比如调用Python的Pandas库处理Excel,或者用OCR库解析图片,而不用担心它执行rm -rf /这种危险操作。这个“AI大脑(LLM)+ 安全手脚(沙箱)”的架构,让构建一个真正能干事、不出格的AI Agent变得可行。

这个项目适合谁呢?如果你是对AI应用开发感兴趣的开发者,想亲手搭建一个能解决实际问题的智能体;或者是中小企业的技术负责人,正在寻找提升内部运营效率的自动化方案;亦或是财务、运营人员,想了解AI如何赋能你的日常工作,那么跟着这篇记录走一遍,你应该能获得一个可运行、可扩展的“对账核对员”原型,以及一套构建类似AI Agent的完整思路。

2. 技术选型与架构设计思路

2.1 为什么是EdgeOne Makers + CodeBuddy?

在决定技术栈时,我主要评估了四个维度的需求:开发部署效率安全可控性成本以及生态整合度。最终锁定这个组合,是基于以下几个关键考量:

首先,开发与部署的敏捷性至关重要。传统的AI应用部署涉及服务器运维、环境配置、网络调试等一系列繁琐工作。EdgeOne Makers的Serverless函数能力让我只需关注核心业务逻辑代码。它天然支持HTTP触发器,我写好一个处理对账请求的函数,部署上去就能直接通过API调用,无需操心负载均衡、扩缩容。这对于快速验证AI Agent想法、进行迭代开发来说,效率提升是数量级的。

其次,代码执行的安全性是生命线。一个能够自动执行代码的AI Agent,其破坏力与创造力并存。CodeBuddy提供的沙箱环境完美解决了这个顾虑。它不是一个简单的Docker容器,而是一个深度定制的安全执行环境。在我的项目里,当AI需要解析一份上传的PDF账单时,它会生成调用pdfplumberPyMuPDF库的Python代码。这段代码不会直接在我的服务器或函数环境中运行,而是被发送到CodeBuddy沙箱。沙箱会严格限制其网络访问、文件系统操作和系统调用,比如禁止访问/etc/passwd,限制内存和CPU使用。执行完毕后,只返回结果(如提取出的文本数据),而不会留下任何潜在的安全隐患。这就好比给AI配了一个“防爆工作间”,任它在里面折腾,也不会影响到外部主环境。

再者,成本模型非常友好。EdgeOne Makers有丰富的免费额度,对于我这种个人项目或低频使用的场景,几乎可以零成本运行。CodeBuddy通常按执行次数或时长计费,在Agent“思考”并生成代码、沙箱执行代码这个交互过程中,只有实际执行代码的环节会计费。通过对逻辑的优化(比如减少不必要的代码生成轮次),可以有效控制成本。这种按需付费的模式,比起长期租赁一台虚拟机来跑Python脚本,要经济得多。

最后,生态与工具链的成熟度。EdgeOne与CodeBuddy都提供了完善的SDK和API文档,并且能很好地与主流AI模型平台(如OpenAI API、国内各大模型平台)协同工作。整个工作流可以很顺畅地串联起来:用户通过EdgeOne函数接口上传账单 -> 函数调用AI模型分析用户意图并生成处理计划 -> 调用CodeBuddy安全执行数据提取代码 -> AI模型对比分析结果 -> 生成报告并返回。这个链条上的每个环节都有成熟的服务支撑。

2.2 核心架构设计

基于以上考量,我设计了如下架构,这个架构清晰地划分了“思考”和“执行”的边界:

用户请求 | v [EdgeOne Makers Function] (HTTP 入口/流程控制器) | | 1. 接收账单文件,调用LLM分析任务 v [大语言模型 (LLM)] (如 GPT-4, Claude, 或国内深度求索等) | | 2. 生成任务执行计划和安全代码 v [CodeBuddy 沙箱] (安全执行代码,如数据提取、清洗) | | 3. 返回结构化数据结果 v [EdgeOne Makers Function] (数据处理与逻辑核对) | | 4. 调用LLM进行数据对比与差异分析 v [大语言模型 (LLM)] (推理与报告生成) | | 5. 格式化最终结果 v [EdgeOne Makers Function] (响应输出) | v 用户 (收到核对报告)

各组件职责详解:

  1. EdgeOne Makers Function (流程控制器):这是整个Agent的“躯干”和“调度中心”。它负责:

    • 接收HTTP请求:提供一个API端点,接收用户上传的账单文件(支持多文件)和核对指令。
    • 状态管理与协调:维护整个核对任务的会话状态,按顺序调用LLM和CodeBuddy。
    • 错误处理与重试:当某个步骤失败时(如CodeBuddy执行超时),负责重试或向用户返回友好错误信息。
    • 最终响应组装:将LLM生成的报告文本,可能加上高亮差异的HTML预览或结构化JSON数据,返回给客户端。
  2. 大语言模型 (LLM) (大脑):这是Agent的“智慧核心”,我将其能力拆解为三个子角色:

    • 任务规划师:分析用户请求(“请核对A公司的发票和B系统的记录”),理解账单文件的类型和内容,拆解出具体的执行步骤,例如“先提取发票PDF中的金额和订单号,再查询数据库中的对应记录,最后逐条对比”。
    • 代码生成器:根据任务规划,生成可在CodeBuddy沙箱中安全运行的Python代码。例如,生成使用pandas.read_excel读取Excel,或使用PILpytesseract进行图像识别的代码。这里的关键是生成的代码必须是自包含的、处理特定输入数据、并输出明确结果的
    • 数据分析与报告员:接收从CodeBuddy返回的结构化数据(如两个列表的字典),进行智能对比。它不仅进行精确匹配,还能处理模糊匹配(如名称缩写)、单位换算(如“万元”与“元”),并最终用自然语言描述差异点,生成易于理解的报告。
  3. CodeBuddy 沙箱 (安全执行层):这是Agent的“双手”。它接收由LLM生成的、经过格式校验的代码,在一个完全隔离且资源受限的环境中执行。它的价值在于:

    • 安全性:杜绝了恶意代码对主机的攻击。
    • 环境一致性:每次执行都是一个干净的环境,避免了依赖冲突问题。
    • 资源控制:可以限制执行时间、内存和CPU,防止错误代码陷入死循环耗尽资源。

注意:在这个架构中,LLM和CodeBuddy之间需要定义一个清晰的“通信协议”。我采用JSON格式,LLM生成的代码需要包裹在一个特定的结构里,包含任务ID、所需Python库列表(供沙箱预准备环境)、代码正文以及期望的输出格式。这能极大提高交互的可靠性。

3. 核心模块实现与关键技术点

3.1 EdgeOne Makers函数搭建与配置

首先,我们需要在腾讯云EdgeOne控制台创建一个Makers函数。这里我选择Node.js运行时环境,因为它异步处理能力强,适合作为这种IO密集型的流程控制器。

函数初始化与基础框架:

// index.js - 函数入口 exports.main_handler = async (event, context) => { // 1. 解析请求 const { body, headers } = event; let requestData; try { // 支持JSON和FormData(用于文件上传) if (headers['content-type']?.includes('multipart/form-data')) { requestData = await parseMultipartFormData(event); } else { requestData = JSON.parse(body); } } catch (error) { return { statusCode: 400, body: JSON.stringify({ error: '无效的请求格式' }) }; } const { files, instruction } = requestData; // 2. 基础验证 if (!files || files.length < 2) { return { statusCode: 400, body: JSON.stringify({ error: '请至少上传两个文件进行核对' }) }; } // 3. 创建任务会话 const sessionId = `reconcile_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; // 4. 启动异步核对流程(避免函数执行超时) // 在实际生产中,这里应该将任务信息放入消息队列,触发另一个异步处理函数。 // 为简化演示,我们假设处理很快,同步返回。 try { const result = await startReconciliationSession(sessionId, files, instruction); return { statusCode: 200, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sessionId, status: 'completed', result }) }; } catch (error) { console.error('核对流程失败:', error); return { statusCode: 500, body: JSON.stringify({ sessionId, status: 'failed', error: error.message }) }; } }; // 解析FormData的函数(示例,实际需根据EdgeOne的event结构调整) async function parseMultipartFormData(event) { // ... 实现文件解析逻辑,将文件暂存到EdgeOne提供的临时文件目录或COS // 返回 { files: [ { name, path, type } ], instruction: '...' } }

关键配置点:

  • 函数超时时间:在EdgeOne Makers控制台,需要将函数超时时间设置得长一些,例如30秒或1分钟,因为LLM调用和CodeBuddy执行可能需要时间。对于更长时间的任务,务必采用“异步触发”模式,即函数快速返回一个任务ID,实际处理在后台进行,用户通过轮询或Webhook获取结果。
  • 环境变量:将所有敏感信息如AI模型的API Key、CodeBuddy的认证密钥等,通过控制台的环境变量功能注入,避免硬编码在代码中。
  • 临时文件存储:上传的文件可以暂存在EdgeOne函数提供的/tmp目录(有空间和生命周期限制),对于大文件或需要持久化的场景,更好的做法是直接上传到对象存储(如COS),函数只处理文件的URL。

3.2 与大语言模型(LLM)的交互设计

与LLM的交互是整个Agent的“灵魂”。这里的关键是设计好的系统提示词(System Prompt)结构化输出

系统提示词设计:

你是一个专业的财务对账助手AI。你的任务是帮助用户核对两份或多份账单/记录文件中的数据。 你的工作流程如下: 1. 用户会提供文件(可能是PDF、图片、Excel等)和简单的核对指令。 2. 你需要分析指令和文件类型,规划出具体的核对步骤。 3. 对于需要从文件中提取数据的步骤,你将生成安全、简洁、高效的Python代码。这些代码将在受控的沙箱中执行。 4. 你将分析沙箱返回的数据,执行智能对比(包括精确匹配、模糊匹配、单位统一等),并找出所有差异。 5. 最后,生成一份清晰的中文报告,列出所有差异项,并尽可能推测差异原因。 请始终以以下JSON格式回应,包含以下字段: { "thought": "你的思考过程,简要说明接下来的计划。", "action": "下一步动作。只能是以下之一:`need_code`(需要生成代码提取数据)、`need_compare`(需要对比数据)、`final_report`(生成最终报告)。", "code": { // 当action为`need_code`时必填 "task_description": "代码任务的描述,例如:'从发票PDF中提取所有条目的名称、单价、数量和总价'", "required_libraries": ["pandas", "pdfplumber"], // 需要的Python库 "code_body": "具体的Python代码字符串。代码必须从标准输入或指定文件路径读取数据,并将结果以JSON格式打印到标准输出。" }, "data_for_compare": { // 当action为`need_compare`时必填 "dataset_a": [ ... ], // 来自上一个代码执行结果的数据集A "dataset_b": [ ... ], // 数据集B "key_fields": ["order_id", "date"] // 用于关联两个数据集的字段 }, "report": "当action为`final_report`时,这里放置完整的自然语言报告。" }

这个提示词做了几件重要的事:角色定义流程约束输出格式化。它告诉LLM“你是谁”、“你要按什么步骤做事”以及“你必须用什么格式回答”。这极大地提高了响应的可预测性和可解析性。

在EdgeOne函数中调用LLM:

async function callLLM(messages, model = 'gpt-4') { const apiKey = process.env.OPENAI_API_KEY; // 从环境变量获取 const url = 'https://api.openai.com/v1/chat/completions'; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}` }, body: JSON.stringify({ model: model, messages: messages, temperature: 0.1, // 低温度,保证输出稳定 response_format: { type: 'json_object' } // 强制JSON输出,对于支持此功能的模型 }) }); const result = await response.json(); if (!response.ok) { throw new Error(`LLM API调用失败: ${result.error?.message}`); } const content = result.choices[0].message.content; return JSON.parse(content); // 解析为JSON对象 } // 使用示例 const systemPrompt = `...`; // 上面的系统提示词 const userPrompt = `用户上传了两个文件:invoice_jan.pdf 和 system_record_jan.xlsx。请核对发票金额与系统记录是否一致。`; const llmResponse = await callLLM([ { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt } ]); console.log(llmResponse.action); // 例如:'need_code'

3.3 CodeBuddy沙箱的集成与代码执行

当LLM返回的actionneed_code时,我们就需要调用CodeBuddy来安全执行它生成的代码。

CodeBuddy API调用封装:

async function executeInCodeBuddy(codeTask, inputFiles = []) { const codebuddyApiKey = process.env.CODEBUDDY_API_KEY; const codebuddyEndpoint = 'https://api.codebuddy.example.com/v1/execute'; // 示例端点 // 1. 准备请求载荷 const payload = { language: 'python', version: '3.9', files: [ { name: 'main.py', content: codeTask.code_body }, // 可以将上传的文件作为输入文件传入沙箱 ...inputFiles.map(f => ({ name: f.name, content: f.base64Content, encoding: 'base64' })) ], // 限制资源,防止恶意或错误代码 constraints: { timeout: 30, // 秒 max_memory_mb: 256, network_access: false // 禁止网络访问,除非必要 }, // 指定执行入口和参数 command: ['python', 'main.py'], stdin: JSON.stringify({ /* 可以传递一些参数 */ }) // 代码可以通过sys.stdin.read()读取 }; // 2. 调用CodeBuddy API const response = await fetch(codebuddyEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${codebuddyApiKey}` }, body: JSON.stringify(payload) }); const result = await response.json(); // 3. 处理执行结果 if (result.status === 'success') { // 假设代码将结果以JSON格式打印到stdout try { const output = JSON.parse(result.stdout); return { success: true, data: output }; } catch (e) { // 如果输出不是JSON,返回原始文本 return { success: true, rawOutput: result.stdout }; } } else { // 执行失败 console.error('CodeBuddy执行失败:', result.stderr, result.error); return { success: false, error: result.error || '沙箱执行错误', stderr: result.stderr }; } }

LLM生成代码的示例与规范:

为了让CodeBuddy顺利执行,必须严格规范LLM生成的代码。以下是一个从Excel中提取数据的“好代码”示例:

# main.py - 由LLM生成 import sys import json import pandas as pd def main(): # 1. 读取输入参数(从标准输入) try: input_str = sys.stdin.read() params = json.loads(input_str) if input_str else {} file_path = params.get('file_path', '/data/input.xlsx') # 沙箱内文件路径 except Exception as e: print(json.dumps({"error": f"读取输入失败: {str(e)}"})) return # 2. 执行核心任务 try: # 假设文件已在沙箱内,路径由外部传入 df = pd.read_excel(file_path, engine='openpyxl') # 提取所需列,这里逻辑应根据具体任务动态生成 # 例如:提取“订单号”、“金额”、“日期” required_columns = ['订单号', '金额(元)', '日期'] # 处理列名可能存在的空格或差异 df.columns = df.columns.str.strip() result_data = [] for _, row in df.iterrows(): # 构建每条记录 record = { 'order_id': str(row.get('订单号', '')).strip(), 'amount': float(row.get('金额(元)', 0)) if pd.notna(row.get('金额(元)')) else 0.0, 'date': str(row.get('日期', '')).split()[0] if pd.notna(row.get('日期')) else '' # 取日期部分 } # 简单的数据清洗:过滤空订单号 if record['order_id']: result_data.append(record) # 3. 输出结果(必须是JSON格式,且打印到stdout) output = { "status": "success", "record_count": len(result_data), "data": result_data } print(json.dumps(output, ensure_ascii=False, indent=2)) except FileNotFoundError: print(json.dumps({"error": f"文件未找到: {file_path}"})) except Exception as e: print(json.dumps({"error": f"数据处理失败: {str(e)}"})) if __name__ == "__main__": main()

这段代码符合安全执行的最佳实践:捕获所有异常从标准输入读取参数将结果以JSON格式打印到标准输出不进行任何危险操作(如文件写入、网络请求)。

3.4 核对逻辑与报告生成

当所有必要的数据都被CodeBuddy提取并返回后,action进入need_compare阶段。LLM将接收两份结构化数据,执行智能对比。

数据对比的提示词设计:

现在你需要对比以下两份数据集,找出差异。请特别注意: 1. 关键字段匹配:使用提供的 `key_fields`(如 order_id, date)将两个数据集的记录关联起来。 2. 金额/数字对比:容忍微小浮点数误差(如0.01),但需报告超出阈值的差异。 3. 文本字段模糊匹配:对于公司名称、商品名等,允许部分字符差异(如“有限公司” vs “Ltd.”)。 4. 缺失记录:报告在A中存在但在B中缺失的记录,反之亦然。 数据集A: {{dataset_a}} 数据集B: {{dataset_b}} 关键字段: {{key_fields}} 请分析并直接以之前约定的JSON格式回应,其中`action`应为`final_report`,并在`report`字段中生成详细报告。

LLM在接收到这份指令和数据后,会进行推理,输出类似这样的报告:

{ "thought": "已收到两份数据。现在以order_id和date为关键字段进行关联对比。发现3条记录金额不匹配,1条记录在B中缺失。", "action": "final_report", "report": "## 对账差异报告\n\n**核对时间:** 2023-10-27 15:30\n**数据源A:** 发票清单 (共15条记录)\n**数据源B:** 系统入账记录 (共14条记录)\n\n### 一、金额不一致记录\n1. **订单ID:** INV-2023-001, **日期:** 2023-10-01\n - 发票金额: 12,500.00 元\n - 系统金额: 10,000.00 元\n - **差异:** -2,500.00 元 (可能为折扣未录入或录入错误)\n2. **订单ID:** INV-2023-005, **日期:** 2023-10-05\n - 发票金额: 8,300.00 元\n - 系统金额: 8,330.00 元\n - **差异:** +30.00 元 (可能为手续费或四舍五入差异)\n\n### 二、记录缺失情况\n- **系统记录中缺失以下发票:**\n - 订单ID: INV-2023-012, 日期: 2023-10-12, 金额: 5,600.00 元\n - **建议:** 检查该系统订单是否漏登或处于待处理状态。\n\n### 三、核对结论\n本次共发现4处差异,其中3处为金额不符,1处为记录缺失。请根据上述明细进行财务核查与调整。" }

至此,一个完整的“对账核对员”AI Agent的核心流程就闭环了。EdgeOne函数将这份报告返回给用户,任务完成。

4. 部署、测试与优化心得

4.1 完整部署流程

  1. 准备代码仓库:将上述EdgeOne函数代码(包括LLM调用、CodeBuddy集成、流程控制逻辑)整理到一个Git仓库中。注意将package.json中的依赖(如node-fetch)列清楚。

  2. 配置EdgeOne Makers

    • 在腾讯云EdgeOne控制台,进入“Makers”服务。
    • 创建新函数,选择Node.js运行时,上传你的代码包或关联Git仓库。
    • 关键步骤:在“函数配置”中,设置好环境变量,如OPENAI_API_KEYCODEBUDDY_API_KEYCODEBUDDY_ENDPOINT等。这是保护密钥的最佳实践。
    • 设置HTTP触发器,并记下生成的访问域名。
  3. 配置CodeBuddy

    • 根据CodeBuddy服务商(示例)的文档,获取API Key和端点地址。
    • 通常无需部署,直接使用其提供的云服务API即可。
  4. 进行端到端测试

    • 使用Postman或curl,向你的EdgeOne函数地址发送一个POST请求。
    • 请求体可以是一个包含文件Base64编码和指令的JSON,或者直接使用FormData上传文件。
    • 检查返回的响应,是否包含sessionId和最终的报告。

4.2 实测中遇到的典型问题与解决方案

在开发和测试这个Agent的过程中,我踩了不少坑,也总结了一些经验:

问题1:LLM生成的代码不稳定,有时导入不存在的库或语法错误。

  • 现象:CodeBuddy执行失败,stderr报错ModuleNotFoundError: No module named 'some_obscure_lib'SyntaxError
  • 排查与解决
    • 约束库列表:在给LLM的系统提示词中,明确一个“允许列表”,例如“你只能使用以下Python库:pandas, numpy, pdfplumber, PIL, pytesseract, openpyxl, json, sys, re, datetime。”这能极大减少它使用冷门库的概率。
    • 代码验证层:在EdgeOne函数中,调用CodeBuddy之前,增加一个简单的代码静态检查环节。可以用正则表达式快速检查是否有import非允许列表的模块,或者是否有明显的危险函数调用(如os.system,subprocess.run)。
    • 备选方案提示:在提示词中教导LLM:“如果遇到需要复杂处理的情况(如图像识别),请生成调用pytesseract的代码;如果PDF解析失败,请尝试使用pdfplumber的不同解析参数。”
    • 我的心得:不要完全信任LLM第一次生成的代码。设计一个“重试机制”。当CodeBuddy执行失败时,将错误信息(如ModuleNotFoundError)反馈给LLM,让它修正代码再次尝试。通常一两次重试后就能成功。

问题2:处理大文件或复杂PDF时,函数执行超时。

  • 现象:EdgeOne函数返回超时错误(如504 Gateway Timeout),但后台任务可能还在运行。
  • 排查与解决
    • 异步化改造:这是必须的。将核心的核对逻辑移出主HTTP函数。当用户发起请求时,主函数只负责验证、创建任务ID、将任务信息(文件URL、指令)推送到一个消息队列(如EdgeOne EventBridge或云函数触发器),然后立即返回{“sessionId”: “xxx”, “status”: “processing”}。另一个独立的、超时时间更长的“工作函数”从队列中取出任务处理,处理完成后将结果写入数据库或对象存储。用户通过另一个API,凭sessionId轮询获取结果。
    • 文件预处理:对于非常大的文件,可以在调用LLM和CodeBuddy之前,先进行一步预处理。例如,用一个轻量级的函数将PDF的第一页(通常是摘要)转换为图片或文本,先让LLM分析结构,再决定是否需要解析全部内容。
    • 设置合理的超时:确保你的“工作函数”和CodeBuddy的执行超时设置足够长,以覆盖最坏情况。

问题3:数据匹配准确率不高,尤其是模糊文本匹配。

  • 现象:公司名称“北京张三科技有限公司”和系统里的“张三科技(北京)”无法关联,导致大量“缺失记录”误报。
  • 排查与解决
    • LLM智能匹配:这正是发挥LLM长处的地方。在need_compare阶段,不要只做简单的字符串相等判断。将疑似匹配的记录对(如名称相似)连同上下文一起交给LLM,让它判断是否为同一实体。你可以设计这样的提示:“判断以下两个名称是否很可能指代同一家公司:A: ‘北京张三科技有限公司’, B: ‘张三科技(北京)’。请只回答‘是’或‘否’。”
    • 本地标准化预处理:在CodeBuddy提取数据后、交给LLM对比前,可以插入一个简单的标准化步骤。例如,用正则表达式移除所有的“有限公司”、“有限责任公司”、“Inc.”、“Ltd.”等后缀和括号内容,只保留核心字号进行初步匹配,将匹配范围缩小后再交给LLM做精细判断。
    • 我的心得:纯规则匹配(如编辑距离)在复杂场景下效果有限。采用“规则初筛 + LLM精判”的混合策略,能平衡准确率和成本。对于高频、固定的匹配对(如自家供应商名单),可以维护一个映射表,优先使用。

问题4:成本控制,特别是LLM的Token消耗。

  • 现象:处理一份多页PDF账单,由于LLM需要分析大量文本,API调用费用较高。
  • 排查与解决
    • 选择性发送:不要一股脑把整个文件内容都塞进LLM上下文。先用CodeBuddy运行代码,将PDF/Excel转换为结构化的JSON数据(列表、字典)。然后只将这些结构化数据发送给LLM进行对比。结构化数据比原始文本简洁得多,能大幅减少Token用量。
    • 使用更经济的模型:对于任务规划(thought)和代码生成(code)步骤,可以使用能力较强但更贵的模型(如GPT-4)。对于最终的报告生成(report),可以尝试使用更轻量、更便宜的模型(如GPT-3.5-Turbo),因为此时逻辑已清晰,只是做文字组织工作。
    • 缓存与记忆:如果同一个用户经常核对类似格式的账单,可以将LLM生成的解析代码模板缓存起来。下次遇到同类文件,直接使用缓存的代码,省去再次生成代码的步骤和Token。

4.3 性能优化与扩展思路

  1. 流程并行化:如果核对多个独立的部分(如不同月份的账单),可以在规划阶段就让LLM识别出可并行任务,然后同时发起多个CodeBuddy执行请求,最后汇总结果,充分利用Serverless的并发优势。
  2. 支持更多文件类型:当前主要处理PDF、Excel、图片。可以通过扩展LLM的提示词和CodeBuddy的代码库,支持更多格式,如Word文档、CSV、甚至直接从网页截图或电子邮件中提取信息。
  3. 集成外部数据源:让Agent不仅能核对静态文件,还能主动查询。例如,在CodeBuddy代码中(如果沙箱允许出网),加入查询数据库或内部API的代码,让AI能直接拉取系统最新数据进行核对,实现真正的自动化。
  4. 人机协同与确认机制:对于LLM不确定的差异或高风险操作(如金额差异巨大),可以在流程中设置“检查点”,通过EdgeOne函数向用户的通信渠道(如企业微信、钉钉)发送确认消息,待用户确认后再继续或生成报告。

构建这个“对账核对员”AI Agent的过程,是一个典型的将大语言模型的认知能力与安全、可靠的计算环境相结合的成功案例。它不再是简单的聊天对话,而是具备了执行具体任务、解决实际业务问题的能力。EdgeOne Makers提供了敏捷的部署和调度平台,CodeBuddy则确保了整个过程中最不可控的环节——代码执行——变得安全可控。这个模式可以复用到无数类似的场景中,比如自动填写报表、监控日志分析、智能客服工单处理等。

← 返回列表