1. 现在学AI工程,到底在学什么
前阵子有个朋友问我:"你会调API,会写提示词,是不是就是AI工程师了?"我当时不知道怎么回答,因为这个问题我一年前也问过自己。
那时候我正做一个内部知识库问答项目,模型用的是市面上不错的通用大模型,提示词写得也很"标准"——角色设定、任务描述、输出格式全都齐了。Demo跑通的那一刻,我一度觉得AI工程不过如此。可一上真实数据就露馅了:用户问"上月报销政策在哪",模型一本正经地编了个文号;问十次同样的问题,答案能给你变出三个版本;稍微改一下问法,整个回答结构就散了。
那段时间我很沮丧,总觉得是模型不够聪明,换了更强的模型还是不稳定。后来我才反应过来,问题出在我压根没把AI当成一个需要工程化治理的系统来对待。我调的是模型,不是系统。模型的不确定性只是其中一个变量,真正的系统还包括数据怎么进、上下文怎么管、输出怎么校验、失败怎么兜底、效果怎么度量。这些加起来,才是AI工程。
所以这篇东西我想从零把"AI工程"这件事拆开讲一遍,把我自己从"会调API"走到"能交付稳定AI系统"这段路上的认知、踩坑、方法论都整理出来。如果你正在做AI应用开发,或者准备入行但被各种概念绕晕了,这篇文章应该能帮你把骨架搭起来。
先说清楚,我讲的"from scratch"不是让你从Transformer论文开始读,也不是让你从反向传播手写神经网络。工程视角的from scratch,指的是当你面对一个真实业务问题、要在生产环境里交付一个稳定的AI系统时,你该具备的最小知识集和完整工作流——从选模型、写提示词、搭Agent,到做评测、控成本、管风险。这套东西才是AI工程的真正内核。
1.1 AI工程和传统软件工程到底哪里不一样
软件工程里,你写一行代码,它的行为是确定的。输入合法,输出就可预期。AI工程最大的区别就是:你写的代码只是系统的一部分,另一部分是一个你没法完全控制行为的外部模型。
我常用一个比喻:传统软件工程是在造一台精密机床,每个齿轮都咬合得很精确;AI工程是在训一只聪明但偶尔闹脾气的狗。你能做的是给它清晰指令、规范奖励、划定边界,但你没法保证它在极端情况下不给你整点新花样。
这个区别引出三个AI工程独有的核心矛盾:
- 不确定性管理:模型输出在概率空间里分布,同一个提示词可能产生不同结果。工程上需要确定性外壳,比如结果校验、重试策略、规则兜底。
- 质量评价困难:传统功能对不对用断言就能测,AI回答的质量没有单一正确答案。你需要建立针对性的评测体系。
- 成本非线性增长:输入越长、步骤越多,token消耗翻倍增长,一个Agent跑完可能消耗你想象不到的额度。
这三个矛盾几乎贯穿了AI工程的所有细节。后面每一章,本质都是在跟这三件事周旋。
1.2 你需要掌握的最小知识集
如果让我给一个AI工程师画一张技能地图,大概是这样的:
| 层面 | 核心内容 | 入门门槛 |
|---|---|---|
| 基础层 | Python、HTTP调用、JSON数据处理、Git | 低 |
| 交互层 | Prompt设计、上下文管理、输出解析与校验 | 中 |
| 增强层 | RAG(检索增强)、工具调用、记忆管理 | 中高 |
| 系统层 | Agent编排、评测体系、成本控制、可观测性 | 高 |
注意这张表的顺序。很多人一上来就冲Agent框架,结果提示词都写不利索,上下文被塞爆了还不知道为什么。我给的建议是:先把交互层做实,再谈上系统层。地基没打稳,楼盖得越高塌得越快。
2. 从零搭建AI工程工作台:环境、模型与工具链
很多教程上来就让你装框架、配环境,我反而想先聊一个大家普遍忽视的问题:AI工程的开发环境,本质上是为了快速试错而存在的。你的环境布局应该围绕"改提示词—跑测试—看结果"这个循环设计,而不是一上来就搭一个媲美生产环境的K8s集群。
我见过不少初学者把时间浪费在配置复杂的分布式环境上,结果一个简单的Prompt变更要等半天才能看到效果。在AI工程里,迭代速度就是你最大的生产力。你的工作台首先要保证"改完能立刻跑"。
2.1 Python环境与依赖管理的实操建议
Python是AI工程的事实标准语言,但Python的环境管理对新手来说就是个坑。我早期项目就栽在依赖冲突上:项目A需要openai>=1.0,项目B还在用0.28,两个项目装在一个环境里,互相把对方的库给搞坏了。
我的建议是从第一天就用uv或conda做隔离。如果你在macOS或者Linux上,直接上uv,它比pip快一个数量级,而且虚拟环境管理做得非常顺手:
# 创建一个Python 3.11的虚拟环境 uv venv .venv --python 3.11 # 激活环境 source .venv/bin/activate # 安装依赖 uv pip install openai langchain httpx python-dotenv为什么强调Python 3.11?因为很多AI库(比如pydantic、lancedb)对新版本Python支持更快,3.11以上的版本在性能上也有优化。别一上来用最新版Python 3.13,有些底层库还没跟上,你会遇到莫名其妙的编译错误。
另外,我强烈建议你把requirements.txt或者pyproject.toml管理成"锁定版本"状态。AI领域依赖更新极快,今天能跑的代码,明天升级了transformer库就可能跑不动。锁版本是保证可复现性的最低成本手段。
2.2 模型选型:别只盯着"最强"
选模型是AI工程的第一步决策,但多数人的决策方式是错误的——他们只看基准分数,谁排在前面选谁。
真实工程里,模型选择要综合评估四个维度:
- 任务匹配度:结构化抽取、分类、代码生成、长文本总结,不同任务对模型能力的要求差异很大。一个轻量模型在简单的分类任务上,效果可能和一个超大杯模型差不多,但成本只有后者的几十分之一。
- 上下文窗口:超长上下文不是免费的。窗口越长,成本和延迟都越高,还容易出现"中间迷失"(模型对长文本中间部分的信息处理不佳)问题。
- 延迟敏感度:面向用户的交互场景,模型响应速度直接影响体验。有些场景必须选推理速度快的模型,哪怕效果略差。
- 数据合规要求:你的业务数据能不能进第三方模型API?是不是必须私有化部署?这个问题在项目初期不定清楚,后面返工成本极高。
我自己常用的一个技巧是建一个任务-模型映射表。把系统里每个AI调用点列出来,标注它的任务类型、延迟要求、数据敏感级别,再给每个调用点分配不同的模型。一个系统里用多个模型组合是完全正常的,别指望一个通吃。
2.3 API密钥管理与安全边界
AI工程的开发流程里,密钥管理看似小事,翻车起来是大事故。我见过有同事把sk-开头的密钥直接写死在代码里,然后提交到GitHub公开仓库,几分钟内就被爬虫抓走,账单刷了好几千。
我现在的标准做法是:
- 所有密钥放在
.env文件里,并确保.gitignore里忽略了它 - 用
python-dotenv或系统环境变量加载 - 对密钥设置用量上限,在服务商后台配置月度预算警报
- 生产环境的密钥与开发环境完全隔离,通过密钥管理服务(如Vault)注入
这块细节直接关系到钱和声誉,从第一天就养成好习惯,后面能省掉很多麻烦。
3. 上下文工程:Prompt不是"聊天技巧",是最核心的接口
Prompt Engineering被一些评论者贬低为"文科生活儿",我觉得这个观点害人不浅。他们显然没做过复杂的生产级AI系统。事实是,在一个典型的AI应用里,模型能力的天花板由模型决定,但地板由Prompt决定。你再强的模型,给它一个模糊的任务描述、混乱的上下文,它就能给你输出垃圾。
我更喜欢用"上下文工程"这个名字来代替"提示词工程"。因为它真正研究的问题不是"怎么跟AI聊天",而是"怎么把信息有效地组织成模型能充分利用的形式"。
3.1 系统提示词的结构化设计
很多人在系统提示词里写一大段自然语言描述,想到哪写到哪。模型确实能读懂,但很不稳定,很容易遗漏关键约束。
我推荐的结构化做法是把系统提示词当成"配置文件"来写。用清晰的段落分区和明确标记:
# 角色设定 你是一名企业IT支持助手,负责解答员工关于内部系统的使用问题。 # 知识边界 - 只能回答与内部系统相关的问题 - 如果不确定,明确告知"我不确定",不要编造 - 涉及安全敏感信息(如密码、权限申请),引导联系IT服务台 # 回答规范 - 使用简体中文 - 步骤式回答,每步不超过3行 - 引用内部文档时注明来源 # 输出格式 返回JSON对象,字段包括:answer, sources, confidence这样做的核心价值是降低模型的自由发挥空间。你把不确定性压缩到了定义好的结构里,后续程序解析和校验就会方便得多。
同时,我强烈建议在Prompt里加入"拒绝规则"。比如客服场景里,用户问"你能帮我写一封辞职信吗",模型要是正经回答了,体验就很怪。提前写清楚"只回答工作相关问题,其他问题礼貌拒绝",远比事后靠模型自觉来得靠谱。
3.2 上下文管理:窗口是资金,别浪费
大模型API按token计费,上下文越长、每次调用成本越高。更重要的是,超过一定长度后,模型对早期信息的注意力会衰减,甚至完全忽略。懂行的人会说这是"Lost in the Middle"现象——模型对长上下文的开头和结尾记得最清楚,中间内容容易丢。
所以,上下文管理的基本法则是:只把当前任务真正需要的信息塞进去,其他一律不放。
具体实操上,我用三种手段控制上下文膨胀:
- 对话历史的滑动窗口:只保留最近N轮对话作为短期记忆,更早的内容摘要化后存起来,需要时再注入。
- 检索增强(RAG):不把所有文档塞给模型,而是按用户问题先用向量检索找最相关的片段,只注入Top-K个片段。
- 指令压缩:系统提示词里的固定内容尽量精炼,删除所有"正确的废话"。
这里我想特别强调一下RAG。RAG不是简单地把检索出来的文本拼到Prompt末尾就完事。你需要处理检索片段的排序、去重、融合,还要在Prompt里明确告知模型"你只能依赖下面这些资料回答"。我见过太多RAG项目效果差,不是向量库的问题,而是没把"检索结果如何呈现给模型"这件事想清楚。
3.3 从意图识别到功能调用:Prompt提升的实例
一个完整的AI功能往往不止一次模型调用。举个例子,我的一个项目里有个"请假助手"功能。用户可能说"我明天下午请半天假",也可能说"下周三我有个手术,想休两周"。这两句话对应的参数完全不一样。
我的做法是先做意图与抽取,再做回复生成。第一步用模型抽取出结构化意图和参数:
用户输入: "我明天下午请半天假" 返回JSON: { "intent": "create_leave_request", "params": { "start_time": "2025-01-15 13:00:00", "duration_hours": 4, "type": "personal" } }拿到这个结构后,程序先校验参数是否合法(下午是否还有半天?请假时长是否超过余额?),再决定让模型生成最终回复。这样做的好处是:关键逻辑(时间解析、余额判断)由程序保证确定性,模型只负责它擅长的自然语言转换。
这也是AI工程和纯粹Chatbot玩法的分水岭——模型输出被当作程序逻辑的一块拼图,而不是最终答案。
4. Agent开发:从"一次问答"到"多步任务"
聊完了单次调用,我们来碰真正复杂的东西——Agent。这也是目前AI工程里最热、也最容易被误解的方向。
我理解的Agent,不是一个"能聊天的机器人",而是一个能自主规划步骤、调用工具、根据中间结果动态调整路径的执行系统。它解决的问题是:用户给一个复杂目标,系统把它拆解成若干子任务,逐个执行,最终拼出结果。
4.1 Agent的核心组件拆解
一个完整的Agent系统,我习惯拆成四个部分:
- 大脑(LLM):负责理解目标、生成规划、判断下一步动作。
- 工具(Tools):模型可以调用的外部能力,比如搜索引擎、代码解释器、数据库查询、内部API。
- 记忆(Memory):短期记忆(当前任务的对话上下文)和长期记忆(跨会话的用户偏好、历史事实)。
- 行动策略(Policy):决定"现在该执行工具还是该回答用户",以及对工具结果的解读方式。
四者缺一不可。有个常见的误区是:给模型接十几个工具,就觉得它能干活了。实际上,工具越多,模型决策就越混乱,还有可能接入恶意或错误的工具返回结果。工具接入前一定要做梳理和约束。
4.2 工具调用的工程实现:函数即工具
在OpenAI的新版API和大多数框架里,工具调用是通过"函数定义"来描述给模型的。模型不直接执行代码,而是输出"我准备调用这个函数、参数是这些",由你的程序去实际执行。
这里有个关键工程点:工具函数的设计直接影响模型的使用效果。我给工具函数命名和写描述时,都会站在模型的角度想一想——描述是否清晰?参数命名是否直观?这个工具和另一个工具的边界是否模糊?
一个典型的设计实践是:
{ "type": "function", "function": { "name": "search_employee_leave_balance", "description": "查询员工在某时间段内的请假余额。用于审批请假申请时,校验剩余可用天数。", "parameters": { "type": "object", "properties": { "employee_id": { "type": "string", "description": "员工工号,必填" } }, "required": ["employee_id"] } } }注意描述里我写了"用于审批请假申请时,校验剩余可用天数"。这种场景提示能帮助模型在合适的上下文中决定调用它,而不是在其他话题里乱调用。
工具调用的另一个坑是工具返回的错误处理。真实环境里,工具可能查不到数据、超时或返回异常格式。模型看到报错信息可能会一头雾水。我习惯在工具返回里做一层包装:错误时返回用户友好提示,同时附加一个诊断代码,方便模型判断下一步。
4.3 多Agent编排的复杂度控制
当一个任务需要多个角色协作时,比如"写一篇市场分析报告"需要检索员、分析师、写手三个角色,你就进入多Agent编排领域了。这块我踩过的坑比较多,目前觉得最有用的经验是:
- 先单Agent,后多Agent。能用一个大模型加几个工具解决的事,就不要拆成三个Agent。多Agent之间的通信损耗和出错概率是呈指数级上升的。
- 明确Agent间传什么。Agent之间传的不该是自然语言散文,而应该是结构化数据(JSON)。散文信息密度低,且容易在传递中丢失细节。
- 设置全局监督。多Agent系统一定要有一个"编排者"角色,负责检查每步产出是否符合预期,而不是让Agent们自由发挥然后拼结果。
我做过一个多Agent项目,三个Agent协作处理工单,看起来很美,实际跑起来经常出现A生成的半成品被B当最终结果用了,B又基于错误假设继续操作。后来我改成"一个主控Agent+若干工具"的架构,效果反而更稳定。很多场景里,Agent数量越少越好。
5. 评测体系:没有衡量标准,就没有交付资格
我见过太多AI项目死在这道坎上:功能Demo做得很酷,一问"效果怎么样",答不上来。再问"如果上线后模型回答变差了怎么办",沉默。
传统软件工程的QA逻辑无法直接套用在AI系统上。你没法写一个assert说"这段回答必须以X开头"。AI的答案是开放的、语义等价的、多样化的。所以AI工程必须建立一套自己的评测体系。
5.1 评测维度的分层设计
我给自己的每个AI功能都建立了一个评测矩阵,至少覆盖以下维度:
- 准确性:回答的事实是否正确,是否忠实于给定资料,有无编造。
- 完整性:问题包含的多个子问题是否都覆盖到了。
- 相关性:回答是否切题,有没有答非所问、扯无关内容。
- 风格合规:语气、格式、长度是否符合产品要求。
- 安全性:有没有输出不当内容、有没有泄露系统提示词。
其中"准确性"和"安全性"是硬指标,缺陷即发布阻断;"完整性"和"风格合规"是软指标,属于打磨范畴。
5.2 评测集怎么造:从10条到1000条
构建评测集是AI工程质量工作里最耗精力但回报率最高的事。步骤很简单,但做扎实不容易:
- 从真实日志里挖:把你系统跑过的真实用户输入都存下来,这是最宝贵的评测素材。
- 按场景分类:把输入归类到不同意图、不同难度、不同边界案例下。
- 人工标注黄金答案:针对每个测试用例,由人写出理想输出标准。
- 持续追加:每发现一个模型答错的case,立刻加进评测集,防止回归。
我在项目里常设一个"bad case库"。线上模型答错了,就把这个case收进去,然后优化Prompt或加规则,跑通后再上线。这就是AI版的单元回归测试。
5.3 自动化评测与人工评测的结合
评测怎么执行?我的经验是分层跑:
- 第一层:机器评测。用规则(关键词、JSON schema校验)和另一个模型来打分。现在各种Judge模型已经能对答案质量给出不错的评估,可以作为第一道筛子。
- 第二层:人工抽检。机器评测漏网的,靠人在关键变更上线前抽检。人工看变化前后的答案对比。
- 第三层:灰度观测。上线后,收集真实用户反馈和隐式信号(如用户是否追问、是否复制答案)。
机器评测和人工评测各有分工。机器快但可能误判语义,人准但慢。AI工程团队每周应该固定排一次"评测走查",把所有新增bad case过一遍,逐个定位是模型问题、提示词问题还是数据问题。这个环节别跳过,我所有稳定交付的项目都靠这个循环撑起来的。
6. 成本、安全与系统韧性:AI工程落地的三座大山
最后这章聊的是那些不性感但是决定生死的工程话题:钱、安全和稳定性。很多AI项目在Demo阶段惊艳全场,一上生产就扑街,问题通常不在模型能力,而在这三座大山没搬动。
6.1 Token成本的估算与优化:别等账单出来才后悔
我之前做过一个文档问答系统,最初版把用户问题加上检索出的15条文档片段全塞进上下文,平均每次问答消耗8000个token。高峰期每天几千次调用,一个月账单出来我差点没坐稳。
后来我做了三个优化,成本直接降到原来的三分之一:
- 裁剪检索片段:从Top-15瘦身到Top-5,并且对每个片段做去重和压缩,只保留和问题相关的段落。
- 缩短系统提示词:把系统提示词里那些"你很聪明、你很棒"类的无效话术全删掉,只保留必要的规则。
- 模型分级:简单问题走轻量模型,复杂问题才调用强大模型。系统先做一个低成本意图分类,把请求路由到不同的模型上。
成本优化的核心思维就一句话:别让系统的每一步都吃最贵的模型、最长的上下文。能用规则解决的问题,绝不用模型;能用小模型解决的问题,绝不用大模型。
6.2 内容安全与数据合规:必须提前设计的防线
内容安全这个话题在AI工程里不是可选项,而是必修课。这意味着你的系统必须具备输入侧的审核与输出侧的过滤能力。
我的标准实践是:
- 输入侧:对用户提交的内容先做合规检测,命中敏感词或疑似有害内容,直接拒绝进入模型。
- 输出侧:模型生成的内容经过二次审核,设置禁用词库和分类器,拦截异常输出。
- 审计留存:保留请求和响应的日志,便于出现问题后追溯。
另外,数据隐私上要注意:你的业务数据发到第三方模型API,就意味着数据离开了你的网络边界。如果业务场景里包含用户隐私、商业机密或内部敏感信息,在架构选型时就得提前考虑私有化部署或使用支持私有化部署的模型服务。这个问题等项目上线后再想,往往已经晚了,属于架构级返工。
6.3 可观测性:给AI系统装上仪表盘
传统微服务有日志、链路追踪和监控指标,AI系统同样需要,而且需要得更细致。我搭建AI系统的可观测性时,会关注几个关键指标:
- 延迟分布:P50和P95延迟,那两个数字能毒打你。Agent系统多步调用会累加延迟,几十秒不返回会让用户疯掉。
- Token消耗量:按功能模块统计,哪个功能烧钱最多一目了然。
- 失败率与重试率:调用失败、超时的比例,以及用户实际看到"加载中"的时间。
- 反馈回路:用户的点赞、点踩、追问比例,这是产品层面最真实的质量信号。
没有这套仪表盘,你就等于在全盲状态下驾驶。更具体的操作是,把每一次模型调用的输入提示词、输出结果、耗时、token数都记录到结构化日志里。无论后续排查还是评测回归,这些数据都是最原始的素材。特别是当模型升级后效果下降,你翻出旧日志对比分析,能快速定位是不是某些输出格式变化导致的兼容性问题。
韧性设计上,我还会主动为模型调用加上三件套:超时控制、重试退避、降级开关。模型服务总会有抖动的,别说"不可能",我见过知名厂商的API连续抖动两小时的事情。你的系统必须有Plan B:要么用备选模型,要么降级为固定规则回复,最少不能让用户看到一个转圈转个没完的界面。
最后聊两句
写了这么多,其实都是从我的血泪经验里萃出来的。如果只留一句话,那就是:AI工程不是调参和写提示词,而是围绕不确定内核构建高确定性系统的过程。模型会不断更新,工具会推陈出新,但工程方法论的内核——评估、隔离、兜底、观测、迭代——是相对稳定、可以穿越周期的。
如果你正准备开始自己的AI工程项目,我建议先用一个最小闭环跑通:一个Prompt加一次模型调用,加一层输出校验,加一条日志记录,再配两个测试case。别想着一上来就搭建完美的Agent森林。从小处着手,把这个闭环打磨顺了,再逐步往外扩展,这条路我走下来,觉得最扎实也最不容易翻车。