1. 从“会聊天”到“能干活”LLM 接入开发工作流的整体设计思路很多人第一次接触大语言模型停留在网页对话框里问几句、答几句觉得新鲜但关掉页面之后它跟自己的日常工作没有任何关系。这个项目要解决的核心问题就是把这层“新鲜感”变成“生产力”——让模型真正嵌入到写代码、查资料、处理文本、生成结构化数据的日常流程里。我把它定位成一本“初学者手册”的第三部分前两部分讲的是基础概念和调用方式这一部分重点落在“融入”两个字上不是单独写一个脚本调一次接口而是让模型成为你开发工作流里的一个常规环节像用 Git 提交代码、像用格式化工具整理文件一样自然。为什么强调“工作流”而不是“应用”因为初学者最容易犯的错是上来就想做一个完整的聊天产品结果卡在界面、部署、并发这些跟模型本身无关的事情上学了两周还在调按钮颜色。而工作流是更底层、更通用的能力你写一个函数输入一段文本输出一段结构化结果这个函数可以被脚本调用、被编辑器插件调用、被定时任务调用。掌握了这个你再去包界面、做产品就是水到渠成的事。这也是我选择从“工作流”切入的核心理由——先让模型在你的终端里跑起来再谈其他。这个内容适合谁如果你已经能跑通一次最简单的模型调用知道 API Key 怎么配、请求怎么发但不知道下一步该往哪走那这份手册就是为你写的。如果你是完全零基础建议先补一下前两部分至少手动发过一次请求、看过一次返回的 JSON 结构再来读这篇会更顺。整篇内容我会围绕四个核心环节展开整体设计思路、核心细节与实操要点、完整实操过程、常见问题排查。每个环节都会给出可以直接抄作业的代码和配置也会解释每一步为什么这么做避免你只会复制粘贴、换个场景就懵。在开始之前先明确一个原则模型是工具不是魔法。它的输出不稳定、会犯错、有成本所以工作流设计的第一要务是“可控”。可控体现在三个层面输入可控提示词模板化、输出可控结构化解析、异常可控失败重试与降级。后面所有的设计都是围绕这三个“可控”来展开的。理解了这一点你就不会盲目追求“一次调用解决所有问题”而是会像搭积木一样把复杂任务拆成多个小步骤每一步都让模型做它最擅长的事。2. 核心细节解析与实操要点把模型调用变成可复用的函数2.1 提示词模板化别在代码里手写大段文字初学者最常见的写法是在代码里直接拼字符串prompt 请帮我总结这段话 text。这种写法在 demo 阶段没问题一旦你要处理不同任务、不同格式代码就会变成一团乱麻。我的做法是把提示词抽成独立的模板文件用占位符标记变量代码只负责填充。这样做的好处有三个一是修改提示词不用动代码逻辑二是同一个模板可以复用到不同项目三是方便做版本管理哪天效果变差了可以回滚。具体实现上我习惯用简单的字符串模板比如{input_text}、{language}这样的占位符然后用编程语言自带的格式化方法填充。不推荐一上来就用复杂的模板引擎对初学者来说增加理解成本收益不明显。模板文件建议按任务命名比如summarize.txt、extract_keywords.txt、translate.txt放在一个prompts目录下。每个模板里除了任务指令还要写清楚输出格式要求比如“只输出 JSON不要有任何额外解释”这一点非常关键后面讲输出解析时会详细说。注意模板里的指令要具体避免“帮我处理一下”这种模糊表述。模型不会读心你说得越清楚它输出越稳定。比如“总结”要说明总结成几句话、面向什么读者“提取关键词”要说明提取几个、是否允许重复。2.2 输出结构化让模型返回能直接用的数据模型默认返回的是一段自然语言人看着舒服但程序处理起来很痛苦。工作流里真正有价值的是结构化数据比如 JSON、列表、键值对。让模型输出 JSON 有两种常见做法一种是在提示词里明确要求“以 JSON 格式输出”另一种是使用模型平台提供的结构化输出功能如果有的话。初学者建议先用第一种通用性强不依赖特定平台。这里有个坑模型有时候会在 JSON 外面包一层解释文字比如“好的以下是结果{...}”。直接解析会报错。我的处理方式是两步走先用正则表达式把 JSON 部分抠出来再做解析。正则不用写得太复杂匹配第一个{到最后一个}就行。解析失败时不要直接崩溃而是记录原始输出方便排查是提示词问题还是模型抽风。另外JSON 里的字段名建议用英文避免中文编码带来的各种奇怪问题值可以是中文不影响。2.3 异常处理与重试模型调用失败是常态网络请求会超时、接口会限流、模型会返回空结果这些都是常态不是异常。初学者写的脚本往往一次失败就整个崩掉这在手动运行时还能接受一旦放进定时任务或批量处理就是灾难。我的做法是给每次调用包一层重试逻辑失败后等待一小段时间再试最多试三次。等待时间建议用指数退避比如第一次等 1 秒第二次等 2 秒第三次等 4 秒避免短时间内反复冲击接口。重试之外还要有降级方案。比如批量处理 100 条数据其中 3 条反复失败不应该让整个任务卡住。我的做法是记录失败项跳过继续处理最后统一输出失败列表人工决定是重跑还是手动处理。这样即使部分失败整体任务也能完成效率高很多。还有一点重试时要区分错误类型网络超时值得重试参数错误重试多少次都没用反而浪费时间和额度。判断方法很简单看错误信息里有没有“超时”“连接”这类词有就重试没有就直接记录失败。2.4 成本与速度的平衡不是所有任务都需要最强模型初学者容易陷入一个误区所有任务都用最大最强的模型。实际上不同任务对模型能力的要求差别很大。简单的文本分类、格式转换用小模型就够了速度快、成本低复杂的推理、长文总结才需要上大模型。我的经验是先用小模型跑一遍看效果能不能接受不能接受再换大模型。这样能在保证效果的前提下把成本压到最低。速度方面批量处理时可以考虑并发调用但要注意接口的速率限制。盲目开几十个并发很容易触发限流反而更慢。建议从 3 到 5 个并发开始试观察有没有报错再逐步调整。另外把多个小任务合并成一次调用也能减少请求次数。比如要提取一篇文章的关键词和摘要可以写一个提示词让模型同时输出两者而不是调两次接口。这样既省时间又省钱缺点是提示词会变长需要权衡。3. 实操过程与核心环节实现从零搭一个文本处理工作流3.1 环境准备与依赖安装先说一下环境。我用的是 Python版本 3.9 以上太老的版本有些库不支持。依赖方面核心就两个一个是 HTTP 请求库用来调接口一个是 JSON 处理Python 自带不用额外装。如果你要用异步并发再加一个异步 HTTP 库。安装命令很简单一行搞定pip install requests如果你打算用异步就换成pip install httpx不建议一上来就装一堆框架什么 LangChain、LlamaIndex对初学者来说是黑盒出了问题不知道从哪查。先用最原始的方式把流程跑通理解每一步在干什么之后再考虑用框架提效。这是我踩过坑之后的建议框架能帮你省事但也会掩盖细节基础不牢的时候用框架等于把命运交给别人。3.2 配置文件管理API Key 不要写死在代码里API Key 是敏感信息绝对不能硬编码在代码里更不能提交到代码仓库。我的做法是放在一个独立的配置文件里比如config.ini或.env文件代码运行时读取。.env文件要加到.gitignore里避免误提交。配置内容至少包括接口地址、API Key、默认模型名称、超时时间。示例配置如下[api] base_url https://api.example.com/v1 api_key your_key_here model small-model timeout 30读取配置用 Python 自带的configparser就行不用装额外库。这样做的好处是换环境、换 Key 只需要改配置文件代码一行不用动。团队协作时每个人用自己的 Key互不干扰。还有一点配置文件里不要写注释说明 Key 的用途避免泄露更多信息。3.3 核心调用函数的实现接下来是核心部分写一个通用的调用函数。这个函数接收提示词和输入文本返回模型输出。内部负责组装请求、发送、解析响应、处理异常。我把它拆成几个小函数每个只做一件事方便调试和复用。第一个函数负责读取提示词模板并填充变量def build_prompt(template_name, **kwargs): with open(fprompts/{template_name}.txt, r, encodingutf-8) as f: template f.read() return template.format(**kwargs)第二个函数负责发送请求import requests def call_model(prompt, config): headers { Authorization: fBearer {config[api_key]}, Content-Type: application/json } payload { model: config[model], messages: [{role: user, content: prompt}], temperature: 0.3 } response requests.post( f{config[base_url]}/chat/completions, headersheaders, jsonpayload, timeoutconfig[timeout] ) response.raise_for_status() return response.json()[choices][0][message][content]这里有几个参数值得说明。temperature控制输出的随机性范围一般是 0 到 1值越低输出越稳定、越保守适合做数据提取、格式转换这类任务值越高输出越多样适合创意写作。我默认设 0.3兼顾稳定和灵活。timeout设 30 秒大部分请求够用长文本可以适当调大。raise_for_status()会在 HTTP 状态码不是 200 时抛异常配合前面的重试逻辑使用。3.4 输出解析与结果落盘模型返回的是字符串需要解析成结构化数据才能用。我写一个解析函数先尝试直接解析 JSON失败则用正则提取再解析import json import re def parse_json_output(text): try: return json.loads(text) except json.JSONDecodeError: match re.search(r\{.*\}, text, re.DOTALL) if match: return json.loads(match.group()) raise ValueError(f无法解析输出: {text[:200]})解析成功后结果要落盘保存。我习惯用 JSON Lines 格式每行一条记录方便追加和后续处理。文件名带上时间戳避免覆盖。保存函数很简单import json from datetime import datetime def save_result(result, output_file): with open(output_file, a, encodingutf-8) as f: f.write(json.dumps(result, ensure_asciiFalse) \n)ensure_asciiFalse是为了让中文正常显示不然会变成一堆转义字符人没法看。输出文件建议放在output目录下和输入数据分开保持目录结构清晰。3.5 批量处理的完整流程把上面的零件组装起来就是一个完整的批量处理脚本。流程是读取输入文件、逐条构建提示词、调用模型、解析输出、保存结果、记录失败项。伪代码如下def process_batch(input_file, template_name, output_file): config load_config() failed [] with open(input_file, r, encodingutf-8) as f: lines f.readlines() for i, line in enumerate(lines): text line.strip() if not text: continue prompt build_prompt(template_name, input_texttext) try: raw call_model_with_retry(prompt, config) result parse_json_output(raw) result[_source] text save_result(result, output_file) except Exception as e: failed.append({index: i, text: text, error: str(e)}) if failed: save_result(failed, output_file.replace(.jsonl, _failed.jsonl))这个流程看起来简单但每一步都有讲究。读取输入时跳过空行避免浪费调用保存时带上原始文本方便回溯失败项单独存一个文件方便重跑。我实测下来处理几百条数据成功率一般在 95% 以上剩下的失败项多半是网络波动或模型偶发抽风重跑一次基本都能过。4. 常见问题与排查技巧实录4.1 模型返回格式不对怎么办这是最高频的问题。你要求返回 JSON它给你返回一段带解释的文字。排查思路分三步第一检查提示词里有没有明确说“只输出 JSON不要任何额外文字”措辞要强硬不要用“请尽量”这种软绵绵的表达第二检查temperature是不是太高调低到 0.1 试试第三如果还是不行就在解析函数里做容错用正则提取 JSON 部分。如果正则也提取不到说明模型根本没按格式来这时候要考虑换模型或者把任务拆得更细。还有一个技巧在提示词里给一个输出示例模型模仿能力很强看到示例就知道你要什么格式。示例要简短一个字段就够不用写完整数据。比如输出格式示例{keywords: [关键词1, 关键词2]}4.2 调用超时或连接失败超时和连接失败通常跟网络环境有关排查顺序是先确认接口地址能不能访问用浏览器或命令行工具试一下再确认 API Key 有没有过期或额度用完最后看是不是并发太高被限流了。如果是限流降低并发数或者在请求之间加一点延迟。我一般会在批量处理时每处理 10 条就暂停 1 秒给接口喘口气实测能明显降低失败率。重试逻辑这里要再强调一次不要所有错误都重试。参数错误、认证失败这类问题重试一百次也没用只会浪费时间。判断方法前面说过看错误信息关键词。我的重试函数里会先判断错误类型只有网络类错误才重试其他直接抛出让上层记录失败。4.3 结果不稳定同样输入两次输出不一样这是模型的固有特性不是 bug。temperature大于 0 时输出就有随机性。如果你的任务要求完全可复现把temperature设为 0但即使这样不同批次的模型版本也可能有细微差异。我的建议是对稳定性要求高的任务不要追求完全一致而是追求“结果在可接受范围内”。比如提取关键词两次结果可能措辞不同但核心词都在这就够了。如果确实需要完全一致那就要在提示词里把要求写到极致并且接受偶尔的偏差。4.4 成本失控怎么控制成本失控通常是因为两个原因用了过大的模型或者调用了太多次。控制方法第一按任务分级简单任务用小模型复杂任务才用大模型第二合并请求能一次调用完成的不拆成两次第三加缓存同样的输入不要重复调用把结果存下来下次直接读缓存。缓存可以用输入文本的哈希值做键简单有效。我做过统计加缓存之后重复数据的处理成本能降一半以上。4.5 常见问题速查表问题现象可能原因排查方法解决方式返回格式不对提示词不明确或温度过高检查提示词措辞和 temperature强化格式要求降低温度加正则容错调用超时网络波动或并发过高测试接口连通性查看并发数降低并发加重试延长超时时间结果不稳定模型随机性对比多次输出降低温度接受合理波动成本过高模型过大或重复调用统计调用次数和模型分级用模型加缓存合并请求部分失败网络或限流查看失败项错误信息记录失败项单独重跑4.6 几个我踩过的坑第一个坑把 API Key 写在了代码里提交到了公开仓库虽然发现后立刻删了但已经暴露了一段时间。从那以后我所有项目都用.env文件并且第一件事就是配.gitignore。第二个坑批量处理时没加失败记录一条失败整个脚本崩掉前面处理的全白费。后来改成逐条捕获异常失败项单独存任务再也没中断过。第三个坑提示词写得太随意模型输出五花八门解析代码写了一堆兼容逻辑。后来把提示词规范化输出格式固定解析代码简化了一大半。这些坑说到底都是“图省事”造成的前期多花十分钟规范流程后期能省几个小时排查。5. 把工作流用起来几个真实场景的落地思路5.1 场景一批量整理会议纪要手头有一堆会议记录格式混乱需要提取出“决议事项”“负责人”“截止时间”三个字段。做法是写一个提示词模板要求模型以 JSON 输出这三个字段然后批量跑一遍。跑完之后结果直接导入表格工具人工核对一遍就能用。这个场景的关键是字段要固定提示词里把字段名和含义写清楚模型输出就很稳定。我实测过几十份纪要准确率在 90% 以上剩下的主要是负责人名字识别错误人工改一下就行。5.2 场景二代码注释批量生成有一批老代码没有注释读起来费劲。做法是写一个脚本遍历代码文件把每个函数体提取出来让模型生成注释再写回文件。这个场景要注意的是模型生成的注释可能不准确尤其是业务逻辑复杂的函数。我的做法是先生成到一个单独的文件里人工审核后再合并不要直接写回原文件。另外提示词里要说明注释风格比如“用中文简洁说明函数用途和参数含义”不然模型可能生成一大段废话。5.3 场景三文本分类打标签有一批用户反馈需要按主题分类。做法是定义好类别列表让模型从列表里选输出类别名称。这个场景的关键是类别要互斥、覆盖全面不然模型会纠结。提示词里把类别定义写清楚每个类别给一两个例子效果会好很多。分类任务用小模型就够速度快、成本低。如果类别多可以分批分类每次给模型几个类别让它选比一次性给几十个类别准确率高。5.4 场景四定时任务自动处理把上面的脚本挂到定时任务里比如每天早上跑一次处理前一天新增的数据。这个场景要注意的是日志记录每次运行的时间、处理条数、成功失败数都要记下来出问题好排查。另外定时任务里的脚本要加锁避免上一次还没跑完下一次又启动了。简单做法是运行时创建一个锁文件跑完删除启动前检查锁文件是否存在。6. 进阶方向从单次调用到多步协作6.1 任务拆解让模型分步思考复杂任务一次调用往往做不好拆成多步效果更好。比如“分析一篇文章并生成摘要和关键词”可以拆成两步第一步提取关键词第二步基于关键词生成摘要。每一步的提示词都更聚焦输出质量更高。拆解的粒度没有固定标准我的经验是如果一次调用的输出里包含多个不相关的部分就考虑拆开。拆开之后每一步的输出都可以单独校验出问题容易定位。6.2 结果校验用规则兜底模型输出不能全信关键结果要用规则校验。比如提取的日期格式对不对、数字范围合不合理、必填字段有没有缺失。校验不通过就重试或者标记人工处理。规则校验的代码很简单但能挡住大部分低级错误。我一般会在解析之后加一层校验函数检查字段类型、长度、取值范围不通过就抛异常走失败处理流程。6.3 人工审核环节的设计完全自动化的流程听起来很美但实际落地时关键结果还是需要人工审核。设计工作流时要把人工审核作为一个正式环节而不是事后补救。具体做法是模型输出先存到一个“待审核”文件人工审核后移到“已确认”文件后续流程只读“已确认”的数据。这样既保证了效率又控制了风险。审核界面不用太复杂一个表格工具打开 JSON Lines 文件就能看改完保存即可。6.4 持续优化收集 bad case 反哺提示词工作流跑起来之后要持续收集效果不好的案例分析原因反过来优化提示词。我习惯建一个bad_cases目录把模型输出不对的输入输出对存进去每周看一次找规律。常见的问题有提示词有歧义、缺少示例、格式要求不明确。针对性地改一改效果往往立竿见影。这个过程是长期的没有一劳永逸的提示词只有不断迭代的提示词。7. 一些个人体会和实用建议这套工作流我用了大半年最大的感受是模型的能力上限很高但你的流程设计决定了它的下限。同样的模型有人用起来得心应手有人用起来处处碰壁差别就在流程上。提示词模板化、输出结构化、异常可控化这三件事做到位模型就能稳定地为你干活。反之如果每次都随手写提示词、随手解析输出、出了问题就重跑那效率还不如自己手动做。另一个体会是不要追求一步到位。我见过太多人想做一个“全能助手”结果什么都做不好。正确的做法是从一个小场景切入把流程跑通再逐步扩展。比如先做文本分类跑顺了再加摘要再加关键词一步步来。每加一个功能都要保证不影响已有的流程。这样积累下来工作流会越来越强大而且每一步都是可控的。最后分享一个小技巧给每个任务写一个简单的测试用例包含输入和期望输出改提示词之后跑一遍测试看有没有退化。测试用例不用多三五个就够覆盖典型场景和边界情况。这个习惯能帮你避免“改了一个地方坏了另一个地方”的尴尬。测试用例用 JSON 文件存脚本读进来跑对比输出简单有效。