掘金 人工智能 05月09日 14:09
还得是“靠人”!打通大模型与业务的“最后一公里”
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了作者团队落地Python AI Web应用项目的实践经验,强调了大模型与实际业务融合的复杂性和深度。文章指出,简单调用API无法满足复杂业务需求,容易出现上下文丢失、逻辑割裂等问题。通过文档校对、文档生成和智能邮件三个功能,展示了如何利用Python脚本进行数据预处理和后处理,结合大模型生成高质量内容,并探讨了环境兼容性、架构设计和模型思考能力等方面的挑战与解决方案。最终强调,落地大模型应用需要脚本能力、系统集成能力和业务场景的精准判断。

📝文档校对:通过Python解析脚本自动识别文档结构,结合业务规则调用大模型,提高输出质量并减少人工干预。例如,针对代码规范格式或财务报表特定指标进行解析。

📊文档生成:利用Python原生脚本和pandas等工具,将处理好的结构化数据自动填入模板,实现批量文档输出,例如一键打印包含多个合同和表单的文档。

📧智能邮件:结合精准报表结果,让大模型编写语义清晰且业务贴切的邮件内容,再通过Python自动发送邮件,实现无感式的业务流程闭环。通过Prompt控制大模型生成特定格式的会议纪要。

🤝外部对接:规划接入外部系统,实现系统与系统、模型与模型之间的直接交互,扩展应用的功能和范围。

最近,我跟团队落地了一个基于 Python 的 AI Web 应用项目,终于让我体会到,大模型与实际业务融合远比简单调用 API 更复杂,也更值得深究。

很多人觉得“大模型接入业务”不就是简单调用接口、传输数据、接收结果吗?

可当我们实际做了才发现,这种看似顺滑的流程,其实非常脆弱。一旦业务稍微复杂,光靠模型 API 堆功能,马上暴露各种问题:上下文丢失、逻辑割裂、输出格式随意。这就像买了一辆超级跑车,却只在狭窄的车库里来回倒腾,根本发挥不了它的真实价值。

我们要的是,让模型真正融入流程。

我们的 Python AI 应用主要实现了四个功能:文档校对、文档生成、智能邮件,以及未来的系统对接展望。

文档校对

第一大功能是文档校对。很多平台已经支持文件上传,但只是粗放地处理。我们设计了专用的 Python 解析脚本,先自动识别文档结构(比如代码的规范格式、财务报表特定指标等),然后结合明确的业务规则调用大模型。这种细致的前置处理,大大提高了模型的输出质量,降低了人工后续的干预。

功能展示:

代码示例:

      // 开始核对按钮点击事件      document.getElementById('startCheck').addEventListener('click', async function() {        console.log('开始核对按钮被点击');        const preCheckFile = document.getElementById('preCheckFile').files[0];        const billingFiles = document.getElementById('billingReportFiles').files;        const steps = document.querySelectorAll('.step');        // 步骤1:解析预核对表        startStep(steps[0], '正在解析预核对表...');        updateProgressBar(1);        const preCheckFormData = new FormData();        preCheckFormData.append('file', preCheckFile);        try {          console.log('开始发送预核对表解析请求');          const preCheckResponse = await fetch('/parse_excel', {            method: 'POST',            body: preCheckFormData          });          console.log('预核对表解析请求响应状态:', preCheckResponse.status);          if (!preCheckResponse.ok) throw new Error('预核对表解析失败');          const preCheckResult = await preCheckResponse.json();          parseResults.preCheckData = preCheckResult.data;          completeStep(steps[0], `预核对表解析完成,共 ${preCheckResult.data.length} 条记录`);          // 修改调用方式,直接传入数据          showPartialData([preCheckResult.data]);        } catch (error) {          console.error('预核对表解析出错:', error);          failStep(steps[0], error.message);          return;        }        // 步骤2:解析计费报表        startStep(steps[1], '正在解析计费报表...');        updateProgressBar(2);        try {          console.log('开始发送计费报表解析请求');          for (let i = 0; i < billingFiles.length; i++) {            const billingFormData = new FormData();            billingFormData.append('file', billingFiles[i]);            const billingResponse = await fetch('/parse_excel', {              method: 'POST',              body: billingFormData            });            console.log(`第 ${i + 1} 个计费报表解析请求响应状态:`, billingResponse.status);            if (!billingResponse.ok) throw new Error('计费报表解析失败');            const billingResult = await billingResponse.json();            parseResults.billingData.push(billingResult.data);          }          completeStep(steps[1], `计费报表解析完成,共 ${billingFiles.length} 个文件`);          // 修改显示部分解析数据的调用,传入合并后的数据          showPartialData([parseResults.preCheckData, ...parseResults.billingData]);        } catch (error) {          console.error('计费报表解析出错:', error);          failStep(steps[1], error.message);          return;        }        // 步骤3:AI 分析差异        startStep(steps[2], 'AI正在分析差异...');        updateProgressBar(3);        // 先检查是否已经存在加载元素,避免重复创建        let loadingElement = document.getElementById('aiLoading');        if (!loadingElement) {          loadingElement = document.createElement('div');          loadingElement.id = 'aiLoading';          // 创建加载圈元素          const spinner = document.createElement('div');          spinner.className = 'loading-spinner';          // 创建提示文本元素          const text = document.createElement('span');          text.textContent = 'AI 分析中,请稍候...';          // 将加载圈和提示文本添加到加载提示元素中          loadingElement.appendChild(spinner);          loadingElement.appendChild(text);          document.body.appendChild(loadingElement);        }        try {          console.log('开始发送 AI 分析差异请求');          const compareResp = await fetch('/compare_and_ask', {            method: 'POST',            headers: { 'Content-Type': 'application/json' },            body: JSON.stringify({              pre_check: parseResults.preCheckData,              billing: parseResults.billingData            })          });          console.log('AI 分析差异请求响应状态:', compareResp.status);          if (!compareResp.ok) throw new Error('AI分析差异失败');          const compareResult = await compareResp.json();          parseResults.differences = compareResult.data;          // 显示 AI 分析结果          const parsedResultsElement = document.getElementById('parsedResults');          let resultContent = '';          if (compareResult.data) {            if (typeof compareResult.data === 'string') {              resultContent = compareResult.data;              console.log("resultContent", resultContent);            } else if (Array.isArray(compareResult.data) || typeof compareResult.data === 'object') {              resultContent = `<pre style="white-space: pre-wrap; word-wrap: break-word;">${JSON.stringify(compareResult.data, null, 2)}</pre>`;            }          } else {            resultContent = '未获取到有效的 AI 分析结果';          }          if (parsedResultsElement) {            parsedResultsElement.innerHTML = resultContent;          } else {            console.error('未找到 parsedResults 元素');          }          completeStep(steps[2], 'AI分析差异完成');          // 移除加载提示          if (loadingElement) {            document.body.removeChild(loadingElement);          }          // 步骤4:生成核对报告          startStep(steps[3], '正在生成核对报告...');          updateProgressBar(4);          setTimeout(() => {            completeStep(steps[3], '核对报告生成完成');            // 移除切换到核对结果 tab 的逻辑          }, 1000);        } catch (error) {          console.error('AI 分析差异出错:', error);          failStep(steps[2], error.message);          // 移除加载提示          if (loadingElement) {            document.body.removeChild(loadingElement);          }        }      });

文档生成

第二大功能是文档生成。听起来简单,就是数据填报到报表中,但我们测试发现,GPT 之类的大模型并不擅长处理高度结构化和规则复杂的数据填充。这一步只能依靠 Python 原生脚本实现。我们使用 pandas 等工具,将处理好的结构化数据自动填入模板,实现批量文档输出。

可以实现:一键打印全部,包含8个合同、7个表单样式、97页文档,每月至少节省2人/天工作量。

自动邮件

第三大功能是智能邮件生成和发送。看似简单的邮件自动化,如果仅依靠模型生成内容,常常会缺乏具体业务语境。我们选择了一个巧妙的融合方式:通过前面生成的精准报表结果,让大模型编写出语义清晰且业务贴切的邮件内容,再通过 Python 自动发送邮件,实现无感式的业务流程闭环。

prompt 示例:

你是会议纪要生成专家,请根据如下规则,为每个月不同厂商生成标准格式的项目考核纪要。【目录结构】- 每个目录如 `json/3e9f7a``json/2a4b6c` 表示不同月份(如 3e9f7a 表示特定年月);- 每个目录中包含:  - `a1b2c3.json`:包含厂商 A、厂商 B、厂商 C 各厂商的解析服务数据、评分、金额等结算信息;  - `d4e5f6.json`:包含当月各厂商的考核扣分项目和扣分事由;  - `7g8h9i/`:输出纪要存放路径,其中需生成:    - `x1.json` → 厂商A 纪要    - `y2.json` → 厂商B 纪要    - `z3.json` → 厂商C 纪要【任务目标】- 根据 `a1b2c3.json``d4e5f6.json` 两个文件,为每个厂商生成一个标准会议纪要(JSON格式);- 每份纪要内容包括:会议信息、合同名称、考核评分、扣分详情、整改措施、结算信息;- 请按以下映射关系提取数据生成:  - `"厂商A"` 对应 `x1.json`  - `"厂商B"` 对应 `y2.json`  - `"厂商C"` 对应 `z3.json`【输出格式】每个厂商输出一个 JSON 对象,结构统一如下:{  "title": "...",  "meeting": {    "name": "特定年月考核评审会议纪要",    "date": "下一月份",    "participants": {      "公司X": ["人员A", "人员B", "人员C", "人员D", "人员E", "人员F", "人员G"],      "<厂商全称>": ["参会人列表"]    }  },  "contract": {    "name": "...",    "contract_number": "如有则填写,否则省略"  },  "assessment": {    "period": "特定年月",    "score_criteria": {      "指标1": 40,      "指标2": 20,      "指标3": 30,      "指标4": 10    },    "result": {      "评分": "...",      "扣分情况": "...",      "说明": "..."    },    "整改措施": { ...如有扣分则列出... }  },  "settlement": {    ...每个模块的数据...  },  "note": "特此纪要"}【细节要求】- 若某厂商无扣分,写明“扣分情况:无”,说明中突出“支撑稳定、无客户投诉”;- 若有扣分,需写明模块、扣分原因、影响评分、整改方案;- 所有金额含税,税率默认 6%,如有单价不同请按预处理文件给出;- 会议名称与日期需自动根据目录名生成;- 输出格式为 JSON,不能包含其他文字或注释;请依次生成每个厂商的纪要,输出为 `7g8h9i/x1.json``y2.json``z3.json` 文件内容。

外部对接

第四个功能目前还在规划阶段:接入外部系统。我们希望未来实现系统与系统、模型与模型之间的直接交互。

小结

然而,实现前三个功能的过程中,我们也遇到了不少挑战。

1、首先是环境兼容性问题,比如内外网隔离导致的库依赖冲突。为了避免踩坑,我们严格控制依赖版本,争取做到一次构建,到处稳定运行。

2、其次是架构上的博弈。一开始我们希望打造一个通用的文档解析器,但实际运行后发现,业务场景差异巨大,通用型并不能真正适配所有情况。最终我们转向了“通用解析器 + 定制化脚本”的组合模式,既保持了通用性的框架,又能灵活响应不同业务的特殊需求。

3、最棘手的难点在于,大模型本质上并不会真正“思考”。它擅长的是即时响应,却无法贯穿历史上下文,缺乏整体一致性和逻辑重构的能力。为了解决这个问题,我们采用了代码规则前置、输出后验证、必要时人工闭环的三步组合策略,确保模型输出始终稳定可靠。

经过这一系列尝试,我想分享一个关键洞察:真正落地的大模型应用,不能只靠模型 API 堆叠功能,必须依托脚本能力、系统集成能力,以及业务场景的精准判断。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Python AI Web应用 大模型 业务融合
相关文章