ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI工程从零到生产:Prompt、数据、评测与可靠性实战指南

AI工程从零到生产:Prompt、数据、评测与可靠性实战指南 1. AI工程不是调API先弄清楚它在解决什么问题过去两年我见过太多从传统开发切过来的工程师拿到大语言模型API的第一反应是这不就是个接口吗传参数拿返回值而已。然后他们很快发现一套基于大模型的系统真正难的不是把模型跑起来而是让它在各种边界场景下稳定、可控、可迭代地输出业务结果。这就是我理解的AI工程AI Engineering from Scratch的起点——从零开始围绕概率性的模型能力构建确定性的工程系统。AI工程和传统软件工程之间最核心的分水岭在于你面对的对象不再是一段行为完全确定的代码而是一个每秒钟都可能给出不同答案的智能体。传统工程里你写if x 0x只要是正数就永远走这条路而在AI工程里同样的Prompt同样的输入两次调用的输出可能完全不同。这种不确定性不是bug而是模型的固有属性。工程化要做的恰恰是在这种不确定性的前提下通过数据、约束、评测、兜底策略把整个系统拉回到可控的轨道上。所以AI工程涵盖的范围远不止写Prompt或者调模型这么简单。我个人的定义是AI工程是一套围绕模型能力构建的生产体系包括数据准备、模型选型、提示词编排、工具调用也就是现在很热门的Harness Engineering、输出校验、评测回归、监控告警以及成本和延迟的持续优化。你把这些环节全部串起来才谈得上一个真正能交付、能维护、能演进的AI项目。这篇文章我就围绕这条主线把从零构建AI工程能力的过程拆开讲清楚。这篇文章适合两类人一类是从传统后端或前端转过来的开发者想系统补全AI工程的知识拼图另一类是已经在用API做Demo但项目一上生产环境就崩、一有边缘情况就翻车、不知道如何系统化迭代的实践者。我会尽量少讲抽象理论多给可直接落地的做法和我在一线踩过的坑。2. 打通第一公里编程基础、数学底子和工具链的取舍2.1 Python能力要练到什么程度才算够用很多教程告诉你学AI工程要先精通Python但精通这个词太模糊了。我实际工作下来真正高频用到的Python知识其实是有边界的你按这个清单去查漏补缺比漫无目的地刷语法书高效得多。首先是类型标注和Pydantic类的使用。AI工程里模型的输出需要被严格解析成结构化对象类型标注不只是给人看的注释更是运行时数据校验的第一道防线。我几乎所有的模型输出解析都依赖Pydantic v2它能自动帮我做字段校验、类型转换、嵌套结构解析配合大模型的JSON输出模式能把脏数据挡在业务逻辑之外。其次是异步编程。真实项目里你要并发调用多个模型、批量处理数据、做流式输出asyncio和httpx的异步客户端是必备技能。我见过不少同事用同步循环一个一个调模型100条数据等十分钟换成异步批量之后十几秒搞定。这个差距在生产环境中就是天壤之别。然后是装饰器、上下文管理器、日志模块的熟练运用。这些是构建可观测系统的砖瓦。比如我会用一个retry装饰器统一封装模型调用的重试逻辑用自定义的log_context管理每次请求的trace_id追踪一次用户请求从入口到模型再到工具返回的全链路日志。没有这套东西线上出问题你根本不知道是哪一步在捣乱。最后是工程习惯虚拟环境管理我推荐uv速度和体验都远好于传统方案、版本控制不只是代码还有Prompt和评测数据集的版本、以及基础的shell和Git操作。这些看着不起眼但恰恰是从零到生产最容易绊倒人的地方。2.2 线性代数、概率和统计的够用清单很多想入门的朋友被数学基础劝退其实AI工程日常用到的高等数学远没有想象中那么多。我自己整理了一个够用清单基本覆盖日常工作的需求线性代数方面把向量和矩阵的点乘、矩阵乘法、余弦相似度搞懂就够起步了。因为模型API返回的embedding向量你需要计算两个文本的相似度、做向量检索这些都是基础的向量运算。函数和导数的直观理解知道梯度是函数上升最快的方向也有助于理解模型训练和微调但如果你不打算从零训练模型这部分不需要深挖。概率统计方面需要理解条件概率和贝叶斯定理的基本思想。做RAG检索时如何权衡检索结果的置信度、做Agent时如何判断工具调用是否成功本质都是概率判断。更重要的是理解方差和分布模型输出的波动方差、评测指标采样的置信区间这些概念决定了你能否科学地判断这次改动到底是变好了还是只是运气好。我的建议是不要去买一本厚厚的教科书从头啃。先用最小可用的数学知识往前走遇到具体问题再针对性补充。AI工程的核心难点从来不是数学推导而是系统设计和工程取舍。2.3 LangChain到底要不要学我的真实看法现在一提AI工程很多人的第一反应是学LangChain或LlamaIndex。我的观点可能和一些教程不一致初期不要直接上框架先用原生代码把每个环节跑通再引入框架提升效率。原因有几个。第一框架的抽象层级高它帮你封装了Prompt模板、工具调用、记忆管理等逻辑但封装的越多你对底层机制的理解就越模糊。一旦框架版本升级导致行为变化或遇到框架没覆盖的边缘场景你就会束手无策。第二AI工程的核心调试点比如Prompt质量、输出解析、工具调用的失败恢复恰恰是框架最薄弱的环节如果你不懂底层逻辑在这些地方只能对着黑盒猜。我的学习路径建议是先用原生HTTP或openaiSDK实现三轮调用流程——基础对话、结构化输出解析、工具调用当你理解了每一步发生了什么再去看LangChain等框架怎么抽象这些环节自然就能判断哪些能力该用、哪些该绕过。等进入生产阶段我自己通常还会保留一套原生核心逻辑只在非关键路径上使用框架能力这是后话。3. Prompt、Harness、数据、评测与测试五个核心组件的拆解3.1 Prompt Engineering把业务需求翻译成模型能执行的指令我从零开始搭建AI工程时第一个集中攻克的点是Prompt Engineering它也是几乎所有热词搜索的起点。这里的核心哲学是模型不像人那样能理解你看着办式的模糊需求你必须把上下文、约束、输出格式、兜底行为全部显式写清楚。一个可复用的Prompt结构我通常拆分成六块角色设定、任务描述、输入数据、输出格式、边界约束、示例。角色设定让模型选择合适的语体和行为模式任务描述要写清楚做什么、为谁做、产出什么输入数据放在独立的界定符里头防止Prompt注入输出格式最好用JSON Schema或模板明确锁定边界约束要写明什么情况下回答不知道、什么情况下拒绝回答示例通常给两到三个能显著提升输出质量的稳定性。我日常实践中积累的三个关键要点第一少样本示例的价值往往大于对任务描述的长篇大论三五个高质量示例比一大段抽象描述管用得多第二指令要写要做什么更要写不要做什么——比如不要编造日志中不存在的信息这类否定性约束能明显降低幻觉率第三把动态数据与指令模板分离变量只占据固定位置这不仅方便维护还能避免用户输入中的干扰信息污染指令本身。关于思维链和推理能力现在流行的做法是让模型在回答前先展示思考过程Chain of Thought这在复杂的多步推理场景下确实有效。但要注意如果你用的是带隐藏推理能力的API通常不需要在Prompt中显式要求请一步一步思考模型自己就会在内部推理。实践中我倾向于在输出格式上要求先给简要推理依据再给结论既能保留可解释性又不破坏输出的结构化。3.2 Harness Engineering真正让模型进入系统的骨架行业内新近讨论较多的Harness Engineering指的是构建在模型调用之外的马具层——所有让模型接入外部世界的机制。类比来说模型是一台高性能发动机Harness就是离合器、变速箱、刹车和仪表盘它决定了这台发动机能否平稳地驱动整车。完整案例里Harness通常包含结构化输出控制、工具定义与调用、上下文管理、错误恢复、以及安全护栏。结构化输出是Harness的基石。我给所有生产级模型调用都启用JSON输出模式OpenAI的response_format参数或厂商的等效能力配合Pydantic做二次校验。这样模型输出的内容在进入业务逻辑前已经被双重确认过格式和类型。工具调用Function Calling是Agent能力的核心定义工具时描述必须极其精确包括参数名、类型、枚举、必填项和什么时候才应该调用这个工具的条件说明。模型决定调用工具之后你的代码要负责执行真实操作并把执行结果传回给模型做下一步决策。上下文管理也是Harness的关键环节。一次真实Agent任务可能有多轮工具调用每一步产生的中间信息都要被组织成可追加、可截断、可压缩的上下文结构。我会实现一个简单的消息管理器按角色和来源区分消息根据总token数触发老消息压缩策略摘要或删除工具调用细节确保最关键的当前任务信息始终在上下文窗口内。错误恢复方面模型可能在工具调用时给出不存在的函数名或错误参数Harness必须捕获错误、格式化报错信息再交回模型修正而不只是崩溃退出。安全护栏和兜底策略同样是Harness的职责设定用户的权限边界、给工具调用添加审批环节、对模型的输出做敏感词和合规过滤、在模型连续多次失败时切换人工兜底流程。这套工程骨架才是Agent能够稳定完成多步任务的真正秘诀。3.3 数据高质量的输入决定高质量的输出AI工程里最容易被低估的组件是数据。这里说的数据不只是训练数据更包括运行时输入数据的准备工作。我自己的数据工程流程分为四层。第一层是数据采集就是把业务相关的文本、日志、文档、对话记录从各源系统同步到统一存储这步要关注接口权限和数据量预估。第二层是清洗与去重文本中常见的乱码、HTML标签、重复段落要提前处理一个常见坑是采集的文档里混杂了大量页面导航信息不清理的话模型会被这些噪声带偏。第三层是切分与入库如果要做RAG需要按语义粒度把长文档切分成合适块我常用500到800字符加重叠区再用embedding模型向量化写入向量数据库这里每月都要关注切分策略是否适合当前文档类型——技术手册、合同条款、聊天记录各自适合不同的切分粒度。第四层是运行时数据增强比如在检索前做同义改写、在回答生成时引用检索来源、在评测时构造反例输入。关于数据版本管理这一点多说一句。AI工程和传统工程的重大区别是模型的输出质量是数据和Prompt的耦合产物。你改了一条数据可能导致之前通过评测的用例回归。所以我会用类似DVC的工具或至少用Git管理所有数据的版本每次变更都记录对应的模型版本和Prompt版本形成可回溯的数据-代码-模型三元组。这在后续定位线上问题时能省下天大功夫。3.4 评测没有评测体系AI工程就是玄学我在多个项目里反复强调一个结论AI工程是做精度工程本质是在概率模型上构建确定性系统。而要做到这一点评测体系不是锦上添花是地基。没有量化评测你根本无法判断一次Prompt修改是优化还是劣化也无法向团队或客户证明系统的能力边界。评测集的建设从领域内真实命中样本入手。我通常会从历史日志、用户真实反馈、以及人工构造的边界案例中抽几百条样本形成一个Golden Set黄金评测集每条样本标注期望输出或评分维度。这个集合要覆盖常见场景、边界场景、异常输入、恶意输入四个层次。规模不用一开始就大但质量必须高因为它是后续一切迭代的标尺。评测执行分两层。第一层是自动化指标适合有明确事实答案的任务可以用答案匹配率、Rouge分数、语义相似度、JSON Schema通过率、工具调用成功率等客观指标。第二层是模型辅助评测LLM-as-Judge适合主观性强的任务用一个更高能力模型对输出进行打分但要注意Judge模型自身的偏差我会用多维打分相关性、忠实度、完整性、格式合规并多次采样取平均降低随机性。我还会定期抽一批结果做人工复核校正自动指标和Judge的偏差。最能体现没有评测就是玄学的例子是我的系统升级了一个模型版本看起来回答质量提升了但上线后发现特定类型的请求全面崩坏了。这种情况几乎无法绕过评测集提前发现——只有当你有一组固定样本、固定的评分维度、以及升级前必须过评测评测线的硬性门禁才能避免这种看起来变好、实际局部退化的陷阱。3.5 AI系统的测试与确定性软件测试完全不同传统软件的单元测试是输入确定、输出确定而AI系统的测试策略必须适配概率性输出的特点。我在团队里推行的测试分层如下。单元层面对函数做确定性测试——数据清洗函数、输出解析器、工具执行器这些纯代码逻辑照常写断言即可。集成层面把模型调用封装成可控依赖测试时用一个Mock响应器返回预定义的不同版本模型输出正常、缺字段、格式错误、恶意内容验证你的Harness层能否正确处理。这一层能拦截大多数模型输出稍微异常就崩的问题。端到端层面从黄金评测集里抽出冒烟用例每次部署前自动跑一遍设置通过率红线比如95%不达标就阻断发布。这里要特别关注概率性带来的假阳性通过问题。模型输出有随机性一次通过不代表永远通过。我的做法是关键用例重复执行三次取多数投票结果对必现项比如涉及个人信息时必须脱敏输出必须符合JSON格式写独立专项断言不依赖模型的泛化能力线上持续收集低置信度输出并转人工复核反哺测试集和评测集。AI系统的测试本质上是代码测试 数据测试 模型行为测试三者的结合远不是跑一个pytest就够了。4. 从零落地一个AI日志分析助手完整工程实录4.1 选一个合适的起点项目日志分析助手理论学习再多不如动手做一个完整项目。我推荐从AI日志分析助手这个方向入手因为它业务边界清晰、数据容易获取、评测也相对客观——日志里是否有异常、异常出现在哪一行答案是明确的。我下面把整个构建过程拆开讲包括选型理由、代码结构、踩坑点你可以照着复现。第一步明确需求输入一段原始日志文本系统要做三件事——检测日志级别和异常类型、提取关键字段时间戳、服务名、错误码、IP等结构化信息、给出处理建议。选Python写核心逻辑数据库直接用SQLite即可向量检索可以留着第二阶段再加。选这个项目的原因是你不需要先解决用户意图理解这个最难的问题而能把注意力集中在Prompt编排、输出解析、评测构建这些AI工程基本功上。4.2 从Prompt到Harness的完整实现核心代码我给出一个精简但生产可用的版本。首先定义输出结构用Pydantic模型锁定from pydantic import BaseModel, Field from typing import List, Optional class LogEntry(BaseModel): level: str Field(description日志级别DEBUG/INFO/WARN/ERROR/FATAL) service: Optional[str] Field(defaultNone, description服务名无则null) error_code: Optional[str] Field(defaultNone, description错误码无则null) anomaly_type: str Field(description异常类型无/超时/连接失败/空指针/资源耗尽/其他) key_fields: dict Field(default_factorydict, description其他关键字段) suggestion: str Field(description针对该日志的处置建议不超过50字)然后构建Prompt模板把日志内容放在界定符内明确要求JSON输出PROMPT_TEMPLATE 你是一个资深运维工程师请分析以下日志并提取结构化信息。 要求 1. 只依据日志文本本身不得编造信息 2. 按JSON格式输出字段包括level, service, error_code, anomaly_type, key_fields, suggestion 3. anomaly_type必须从给定枚举中选择无法判断填未知 4. suggestion要具体可执行控制在50字以内。 日志内容 log {log_content} /log 请直接输出JSON def parse_analysis(text: str) - LogEntry: # 清理可能包裹的markdown代码块再解析JSON cleaned text.strip().removeprefix(json).removesuffix().strip() return LogEntry.model_validate_json(cleaned)接下来是Harness的核心模型调用封装、重试、以及错误修正。一个关键的工程细节是当模型输出的JSON解析失败时不要直接放弃而是把解析错误信息回传给模型让它修正。这能显著提升整体成功率async def analyze_log(client, log_text: str, max_attempts: int 3) - LogEntry: messages [ {role: system, content: 你是日志分析专家输出严格JSON。}, {role: user, content: PROMPT_TEMPLATE.format(log_contentlog_text)}, ] for attempt in range(max_attempts): try: resp await client.chat.completions.create( modelyour-model-name, messagesmessages, response_format{type: json_object}, temperature0.1, ) return parse_analysis(resp.choices[0].message.content) except Exception as e: messages.append({role: assistant, content: resp.choices[0].message.content}) messages.append({role: user, content: f输出解析失败{e}。请按要求重新输出JSON。}) # 指数退避或简单sleep避免限流 await asyncio.sleep(1.5 * (attempt 1)) raise RuntimeError(f日志分析失败JSON格式连续{max_attempts}次错误)温度参数这里设置为0.1是因为结构化提取任务希望输出尽可能稳定不需要创造性。我见过很多人忽略temperature对稳定性影响的权重在提取类任务里temperature高一点输出格式错误的概率就会明显上升这个参数值得花时间调。4.3 数据准备和黄金评测集构建数据从哪里来可以找开源的日志数据集更推荐的方式是从自己日常项目中导出真实日志。拿一千条真实日志人工标注一小部分作为种子评测集剩下的作为开发集做离线自测。种子评测集我建议控制在100到200条涵盖正常日志占一半、超时和连接失败各占两成、各类业务错误码、以及几条约定噪声日志。评测指标怎么定这里不追求完美至少有四个客观维度一是JSON解析成功率满分为100%二是level字段准确率建议90%以上三是error_code提取的精确率和召回率目标85%以上四是anomaly_type的准确率这是最难的一个因为有些日志从字面上很难判断类型。每周跑一次评测记录指标变化所有的Prompt优化都以这些数字是否提升为准绳。有了基线数字后续的Prompt迭代就不再是凭感觉看起来变好了而是有数据支撑的持续改进。4.4 结果评测与迭代优化我踩过的三个坑第一次跑完整流程时我的系统在日志分析上犯了三个经典错误写在这里供你参考。第一个坑是JSON双重嵌套。我的Prompt要求模型输出JSON而模型有时会在JSON外套一层Markdown代码块或者用单引号替代双引号。所以我加了清理函数但更稳妥的方案是强制使用response_format参数从模型侧锁死JSON输出再配合清理逻辑做双保险。第二个坑是temperature和随机性。我在初版把temperature设成了默认值结果同一个日志连续跑5次有3次结果不同评测指标忽高忽低。后来改成0.1重复跑5次的结果才基本一致。对于任何结构化提取任务低temperature是基线配置需要在一致性和多样性之间找到平衡点。第三个坑是评测集样本偏差。我最初用真实日志构建评测集结果模型对日志的泛化还行但一碰到人工构造的边界输入比如空的日志、纯符号日志、超长几十KB的日志就崩。把评测集补齐这些异常样本后系统的鲁棒性才真正上去。这个经验直接说明了评测集覆盖错和怪比覆盖多更重要。5. 进阶路径与可靠性从能跑到靠谱5.1 Agent、多AI协作与工作流编排下一个能力台阶日志分析助手还属于单模型单任务模式但真实业务里很多需求天然是工作流。比如日志分析助手要真正落地运维监控还需要对接工单系统、执行重启脚本、通知值班人员——这个链条就涉及Agent和工具调用了。再进一步是多AI协作Multi-Agent一个Agent负责日志初筛一个Agent负责根因分析一个Agent负责对外沟通它们共享上下文、互相校验结果、按需唤醒。我在一个内部项目中实现过一个四Agent协作的故障分析系统整体准确率比单Agent提升了约25%主要原因是分工之后每个Agent的Prompt更加聚焦不被不相关的任务干扰。多Agent编排的核心工程挑战是上下文隔离和结果汇聚。我的做法是通过事件总线传递消息每个Agent只读取关心的事件更新自己的状态再发布新事件。这样系统的可观测性非常强每个环节都能知道是谁、在什么时间、基于什么上下文、产出了什么结果。推荐你在这个阶段阅读LangGraph这类编排框架的源码理解状态机和路由是怎么设计的而不是直接用。5.2 可靠性工程监控、兜底、成本和延迟模型一旦真正上线可靠性的维度就开始爆炸式增长。我在生产环境里最看重的四个指标错误率模型抛异常的比率、重试率并发的重试触发比例、超时分布P50、P95、P99以及单位请求成本。日志分析助手这类文本提取任务P99延迟目标应当控制在2到3秒内单次调用的成本应尽量控制在特定的分钱级别以下。系统兜底的策略也很重要。我通常设计三级兜底第一级是复用经典正则规则和启发式规则在模型输出明显异常时直接采用规则结果第二级是降级模型优先用快速便宜的模型失败再切换到高精度模型第三级是人工审核通道把低置信度样本推送给人做二次确认同时回填到评测集。没有这套兜底任何一个线上小波动都可能变成用户投诉。成本控制方面我的经验是过路的车都值得搭第一优先使用上下文缓存减少重复token第二小任务用轻量模型只有根因分析这类高难度任务才动用大模型第三对流式输出消费端做节流不等完整回答、按片段实时处理。成本优化和延迟优化往往是一体的设计时就要一起考虑。5.3 几条避坑建议和一个学习路径参考最后分享几个我在一线实战中反复撞墙后总结的避坑建议没有任何技术含量但每一分都是切肤之痛。第一Prompt版本必须纳入版本管理。我在Git里单独建了一个prompts/目录每个Prompt文件标注了适用模型版本、上线时间和评测得分。改Prompt前先复制一份到experiments/跑完评测再决定是否合并。这一习惯让团队在追线上回归时少吵了无数架。第二警惕评测集过拟合。你的Prompt和评测指标绑定久了评测集上的得分会虚高因为模型记住了这组样本的偏好。我的办法是每两周从线上日志里抽一批全新样本加入评测集保持评测集的新鲜度和难度。第三不要害怕用笨方法。我见过不少团队花几周时间设计复杂的Agent编排最后发现一个简单规则加两个Prompt就解决了80%的问题。从简单方案起步用数据说话复杂方案只在你真的需要时引入。如果你从零开始我的建议路径是理解Prompt和结构化输出1周→ 完成一个包含评测的简单提取项目2周→ 加入工具调用和Agent能力3到4周→ 构建多Agent协作的完整工作流4到8周→ 最后回来打磨可靠性和成本。每一步都要有能拿得出手的Demo和数值指标这样的学习才不是空中楼阁。我这两年最深的体会是AI工程的核心竞争力不在于你掌握了多少新概念和框架而在于你有没有一套快速验证、量化迭代、稳定兜底的工程循环。
返回列表