1. 先说说我为什么折腾这套拍照解题起因其实挺简单。我那段时间经常要帮家里小孩看作业从小学数学到初中物理都混着来。试过市面上一些拍照搜题App答案倒是快但有两件事让我很不爽一是它只给答案不解释思路小孩看一眼答案抄上去下次照样不会二是碰到稍微偏一点的题它就给你匹配出莫名其妙的相似题答案驴唇不对马嘴。后来我干脆想既然手头有DeepSeek的API又一直在用Dify做各种自动化流程能不能自己搭一个拍照→识别题目→大模型分步讲解的闭环DeepSeek负责逻辑推理和讲解Dify负责把图像识别、问题重构、模型调用这些环节串起来。这套东西不用写多复杂的代码Dify的可视化编排能省掉我大量的工程时间最后落地确实比我想象中顺利。这篇文章就是那份实验手册的整理版。我默认你和我一样用过或者至少听说过Dify知道它是个能编排大模型应用的开源平台也知道DeepSeek是个API价格相对亲民、推理能力在线的对话模型。如果你完全没接触过这两样也能照着手册跑通只是中间有些概念需要自己补一下课。我要把整套系统的拆解思路、Dify里的具体配置步骤、以及我跑了一周之后遇到的各种识别翻车案例全部分享出来。适合谁看想用现有大模型能力捣鼓一个实际工具的开发者、教育行业里想给内部做答疑系统的朋友还有那些手里有API但不知道该做什么的玩家。这套东西的价值不在于解题本身而在于它演示了一条完整的路径怎么把图片内容变成模型能读懂的文本怎么让模型按照你想要的格式输出怎么在不写后端代码的情况下把它变成一个可调用的服务。2. 照片怎么变成DeepSeek能看懂的东西链路拆解2.1 大模型不直接吃图片这是第一个要解决的问题DeepSeek的对话模型目前只吃文本你没法直接把一张试卷照片扔给它。所以第一步必须想清楚图片里的题干怎么变成文字这里有个常见的认知误区很多人以为OCR识别一下就行实际做起来根本不是那么回事。试卷和作业题里不只有印刷体汉字还混着数学公式、几何图形、分数表达式、上下标普通OCR引擎对纯文本的识别率很高但一碰到公式就乱套。我最早拿通用文字识别接口试过把一道二次函数题拍进去识别出来的是g ax2 bx c这种半死不活的文本公式里的指数全部变成了普通数字模型拿到这种输入推理方向直接偏了。所以在系统设计一开始就要把识别拆成两路一路走通用OCR识别题干文字另一路单独处理公式和图形信息。很多OCR服务商都提供了公式识别专用的接口对数学符号的重建能力远好于通用接口。如果你不想接第三方服务也可以考虑用开源的离线公式识别模型但部署成本会高一些作为实验项目我建议先走商用接口跑通再优化。2.2 Dify里的流程图识别、清洗、推理三段式整个工作流在Dify里分成三个逻辑段。第一段是预处理把用户上传的图片交给OCR能力拿到原始文本。这一步的关键不是怎么调接口而是怎么把OCR返回的结果整理成模型能用的输入。OCR返回的内容往往带坐标信息、段落标记、甚至误识别的符号这些噪声一边会让DeepSeek理解困难一边还会白白消耗token。我习惯在Dify里用一个文本处理节点做清洗去坐标、去空行、把全角符号统一成半角、把明显的OCR错误做一轮字典映射比如把0误识别成O、把l误识别成1这些高频错误先替换掉。第二段是结构重构把清洗后的文本组合成一道完整题目的描述。这里不要直接扔给模型就完事而是要上一段提示词让DeepSeek先做题目转述——也就是把OCR文本重新组织成一句完整、语义明确的问题陈述。为什么要多此一举因为OCR文本本身可能顺序混乱或者把题目条件拆得七零八落模型直接基于这种文本推理准确性没有保障。经过一轮转述之后模型自己先理解了题目在说什么后续的推理质量会明显提升。第三段才是真正的解题把重构后的问题交给DeepSeek要求它按已知条件→解题思路→分步计算→最终答案的结构输出。这一步的提示词设计我后面单开一章详细讲这里先记住一个总原则给模型的指令一定要具体到输出格式最好让它返回结构化内容而不是自由发挥。2.3 为什么选Dify而不是自己写代码如果只做一次性的脚本自己写代码当然更直接。但如果要长期维护并且让不懂代码的同事也能改流程Dify的价值就出来了。我自己最初就是用Python脚本调的API写得很爽但真正用起来发现几个问题每换一个OCR厂商就要改代码题目进来了想加一个先判断学科、再走不同解题模板的逻辑得重写分支最重要的是家里人想用总不可能让他们去跑命令行。Dify把这些都变成了可视化操作OCR节点、模型节点、分支判断节点都做成了积木想改哪块就改哪块。此外Dify本身提供WebApp和API两种调用方式手机浏览器打开就能拍照上传比什么客户端都好使。3. 在Dify里编排解题工作流的完整过程3.1 先把应用骨架搭起来我当时在Dify里新建的是一个工作流类型的应用不是聊天助手类型。原因很简单聊天助手偏自由对话工作流可以严格控制节点顺序和分支走向每一步做什么都是确定的不会跑偏。骨架信息如下应用类型工作流输入变量image文件类型接收用户上传的拍照图片输出变量结构化解题结果包含题目重述、分步解答、最终答案三个字段新建完之后第一件事是配置模型供应商。Dify支持接入DeepSeek的方式有两种一种是在模型供应商列表里直接选DeepSeek填入API Key另一种是通过OpenAI兼容模式接入。用第一种更省事它会自动帮你把模型列表拉出来对话模型直接勾选即可。当时我把温度调成了0.2因为这个场景需要的是稳定推理而不是发散创造温度太高模型容易给自己加戏明明条件不足还硬凑一个答案。然后按顺序拖入节点第一个节点是工具类型的HTTP请求节点用来调OCR接口。Dify里有现成的工具市场也可以直接配置自定义HTTP节点把图片base64编码后POST给你的OCR服务商。这一步需要注意你传过去的图片最好先压一下尺寸手机原图动不动几MB网上传太慢也会浪费OCR服务商的流量额度。我一般控制在1200px以内JPG格式质量80%就行识别率几乎不掉。3.2 核心节点配置连接SamplingResponse与OCR实现在Dify的工作流里OCR这块可以写成HTTP节点串接SamplingResponse节点。SamplingResponse本质上是把HTTP调用返回的响应体按你的需求提取出来喂给下一个节点。我在HTTP节点里设置的响应体结构是JSON内容大致长这样{ words_result: [文字块1, 文字块2], formula_result: [公式1, 公式2] }然后处理节点里做清洗与拼接。清洗逻辑我写了一段简单的伪代码思路把数组中所有文字块合并成一个大字符串去掉两两之间的空行和多余空格英文符号统一转半角对一组高频OCR混淆词做替换如r1→x1之类的公式结果单独拼到文本末尾标记为[公式区域]这些写起来不复杂但在Dify里要找到对应的代码执行节点。Dify的代码节点支持Python我在里面写了这段清洗逻辑有几步是直接能跑通的。3.3 提示词设计让DeepSeek的输出稳定可用在整个环节里提示词设计是最能拉开效果差距的地方。我最初的提示词写得特别随意就一句请解答这道题结果模型输出格式五花八门有的只回一句话有的长篇大论写小作文解析出来的答案还得靠人工二次整理完全没法用。后来我把提示词标准化成了这个结构你是一名严谨的理科教师。请基于以下题目信息完成解答。 题目文本 {{cleaned_text}} 要求 1. 先用自己的话重述题目确保不遗漏已知条件。 2. 判断题目的学科类型数学/物理/化学等。 3. 给出完整的解题思路说明用到了哪个知识点。 4. 分步骤计算每一步都保留推导过程。 5. 最终答案单独一行输出格式为答案xxx。 6. 如果题目信息不完整不要强行猜测直接指出缺失条件。这里有几个细节值得说明一下。第一先重述题目不是为了凑字数而是让模型在输出之前先内化一遍题目的条件能显著降低漏条件的情况。第二分步骤计算对数学题几乎是必需的模型如果一次性推出结果中间很容易跳步出错。第三缺失条件时要直说这一条是我吃了好几张模糊照片的亏之后才加上的——有时候OCR识别出来的题干本身就少了几个字符模型最怕的是在残缺信息下强行合理化告诉你一句如果按照你的题意就编出一个答案来这在教育场景里非常致命。实践下来这样设计的提示词让输出稳定性提升了一大截而且天然适合解析——因为格式基本是固定的我可以用一个简单的正则把答案后面的内容摘出来存到结构化字段里这就为后续对接外部应用打好了基础。3.4 工作流里最容易忽略的失败出口工作流不是只有一条成功路径你必须在设计之初就想到失败的情况。我在Dify里加了两个分支出口OCR节点返回空结果或者识别置信度过低时走识别失败分支输出一句提示告诉用户照片不清晰请重新拍摄而不是让模型硬猜。DeepSeek节点返回内容里没有答案关键字时走解析失败分支把模型原始输出原样返回给用户至少让用户看到推理过程。这两个分支看上去不起眼但它们决定了这个系统能不能日常使用而不闹笑话。没有失败出口的流程一旦翻车轻则返回垃圾内容重则直接报错中断体验极差。4. 拍照端到端调试与识别失败的真实排查链路4.1 第一轮翻车现场白底纸上的红色批注系统搭好之后我兴冲冲拍了一张数学卷子测题目是已知二次函数y x² - 2x 3求顶点坐标。结果OCR把题干里的数字2全部识别成了整个题目文本变成求顶点坐标这种状态DeepSeek拿到之后直接告诉我题目信息不足。排查第一步我查看了OCR接口返回的原始JSON发现识别框里把红笔批注这题错了也当成正文识别了而且因为红色批注覆盖了部分印刷体导致附近区域的字符识别度严重下降。这算是拍照场景的经典问题试卷上往往有红笔痕迹、涂抹、折痕阴影这些都会干扰OCR。我的解决办法分两层第一层是拍照引导在应用前端上传页面写清楚请尽量在光线均匀的环境下拍摄、避免红笔批注、保持纸面平整第二层是图像预处理在OCR之前先用代码做一次简单的亮度和对比度增强并把饱和度降低让红色批注在灰度图上和印刷体区分度变大。代码节点里我塞了一段基于OpenCV的灰度化与自适应二值化处理代码不长但对改善识别率帮助非常明显。4.2 第二轮翻车现场公式的下标和分式这个问题我在前文提过但真正调试时比我想象的更麻烦。一道含分式、根号、下标的数学题通用OCR往往把x₁识别成x1、√x识别成Vx、3/4识别成3 4。这种错乱对自然语言理解还没太大影响但对数学符号来说是致命的。我换成了带公式识别能力的OCR接口之后情况好了不少但依然有崩塌的时候。最常见的场景是分数和括号混排比如1/(x2)被识别成1/(x2)时括号丢失变成1/x2模型理解出来的公式完全变了。即便公式识别引擎也有自己的脾气。针对这个情况我在清洗代码里加了启发式修复规则检测到分母位置后面没有括号闭合时自动补括号检测到连续数字之间有异常空白时合并为乘号或小数点再结合上下文判断。这个方案不是百分百准但能把模型的误判率拉低一个档次。真要彻底解决得走公式结构解析的专用模型作为实验项目暂时不做这么重。4.3 第三轮翻车现场一个问题里有两个问号然后是逻辑层面的翻车。一道应用题有第一问和第二问OCR文本也识别得完整但DeepSeek在重述题目的时候没有区分两个子问题的不同条件把两个问号的条件混在一起推导最后自然是错的。排查之后发现问题出在提示词上。我没有在重述环节要求拆分子问题模型默认把整段文本当作一个整体。修复方式简单粗暴在重述要求里增加一条如果题目包含多个小问请以列表形式分别列出每个小问的已知条件。这一改模型输出结构立刻清晰了后续的解题也能分别对应。这个案例让我意识到OCR只是把像素变成字符模型真正需要的是信息的结构化。我们在工作流里做的一切清洗、重述、拆分本质上都是在帮模型把非结构化的文本变成逻辑上可推理的知识单元。4.4 排查方法论先看哪一环节的问题跑了两周之后我形成了一套排查顺序遇到结果不对先定位问题在哪一段效率会高很多如果OCR返回的文本明显不通顺先怀疑拍照条件和OCR选型去看原始响应体不要急着调提示词。如果OCR文本没问题但DeepSeek重述出来跑偏去看提示词里有没有对输出结构的明确约束。如果重述没问题但解题结果不对可能是模型对该题型自身能力不足这时候换更强的模型版本而不是继续调提示词。如果整个链路都正常但最终返回格式不对去看工作流的代码节点里解析逻辑有没有bug。这套排查思路大概帮我砍掉了百分之六十的无效调试时间。5. 从解题器到答疑助手实测数据、成本与还能怎么玩5.1 我跑了两周的实测记录我拿小学到初中的数学、物理题各测了五十道整体情况统计下来比预期好。印刷体题目的端到端成功率达到八成以上所谓成功是指题目完整读出来、模型解题思路正确、最终答案和参考答案一致。手写体题目就明显吃力尤其是手写数字潦草时OCR识别率低一大截成功率大致只有五成上下。单次完整链路耗时差不多在三到六秒之间大头花在图片上传和OCR返回上。DeepSeek本身的推理时间反而不长因为题目文本量不大生成内容也不长。如果用户网络环境好一点体感上几乎是拍完照两三秒出答案完全能达到日常使用标准。成本这块OCR按次计费深度学习的识别模型也都便宜单次几乎忽略不计DeepSeek的API按token计费一次解题生成的token数也就一千到两千之间换算成钱基本是几厘到几分钱。哪怕每天测几十道题成本也就是一杯饮料钱都不到。这个成本结构决定了你可以大胆地把它做成一个内部小工具不用像商业搜题产品那样花大价钱。5.2 这套架构还能长出什么跑通解题不是终点Dify工作流的架构给我的感觉是解题只是第一个积木。我后来在它基础上又加了几块逻辑已经在内部实验了。一是学科分类分支。在题目重述之后先让DeepSeek判断学科和年级然后不同学科走不同的解题模板比如数学题强调分步推导语文阅读题强调原文定位物理题强调单位和公式引用。这样一套工作流可以服务多学科而不是只有数学一条路。二是错题本数据回流。Dify的工作流结果可以作为记录节点把每次拍照识别出的题目文本、模型解答、用户反馈一起存到数据库或表格里。累积一段时间后就能看出这个孩子错题集中在哪些知识点甚至可以反向生成针对性的练习建议。三是多轮追问机制。最初我把它做成纯拍照解题后来发现小孩经常看完答案还要问一步这一步为什么这么变单纯一次性回答满足不了。于是在Dify里把输出结果的文本摘要和原始题目上下文都保留到会话变量中下次用户追加问题时工作流会带着上次的对话背景再次调用DeepSeek形成连续的答疑对话。这个改动其实不大但对使用体验的提升是质的。5.3 如果你也想照葫芦画瓢这几条经验先拿走首先OCR选型直接决定系统天花板。通用识别和公式识别的差距在这个场景里有质的区别预算有限也至少要选带公式支持的接口否则后面调试提示词的时间会让你怀疑人生。其次提示词里一定要包含信息缺失时直说的兜底指令。教育场景里最忌讳的就是生成幻觉答案模型一本正经地编一个步骤拿给小孩看就是误人子弟。加了兜底之后虽然偶尔会得到题目不完整无法解答的回复但这比错误的答案体面得多。再次别忘了给工作流加失败出口。任何一个环节都可能挂挂的时候用户应该得到友好提示而不是看到一个报错堆栈。这一点在Dify里做起来并不复杂但很多人第一次设计流程时根本不考虑。最后自己动手之前先想清楚服务的对象。做给自家孩子用和做给全班用、做给机构老师用设计逻辑完全不同。给自家孩子我可以牺牲点通用识别率优先追求界面极简做给机构用就得考虑批量导入、权限管理、结果存档这些杂七杂八的东西。别一上来就照着大而全做做厚了反而难以坚持用下去。我到现在还经常用这套系统拍小朋友的错题每拍一次都能发现一点需要调优的细节。这大概就是这个项目最迷人的地方——它不是交付完就寿终正寝的Demo而是一个能一直陪着实际生活迭代的工具。DeepSeek负责思考Dify负责编排我负责在旁边修修补补、踩坑排雷这个过程本身就挺有成就感。如果你也在折腾类似的工具实验希望这份手册能帮你少走几段弯路尤其是那几轮翻车现场大概率你也躲不过。