尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

从零搭建AI工程实践:提示词、智能体与工作流全攻略

发布时间:2026/9/29 18:59:45

资讯中心
01
ARTICLE

从零搭建AI工程实践:提示词、智能体与工作流全攻略

从零搭建AI工程实践:提示词、智能体与工作流全攻略
这个标题听起来很像是某个GitHub仓库的名字但它其实正是我这几个月在做的真实项目——一份从零开始的AI工程实践记录。我把自己的学习路径、踩坑记录、代码模板和工具选型思路全部收进了一个叫ai-engineering-from-scratch的目录里。今天把这套思路完整展开写给那些想入门AI应用开发、又不想只当“调包侠”的人。1. AI工程从零起步先看清全局地图1.1 什么是“AI工程”它和算法岗、调包侠差在哪先说一个很多人都会问的问题AI工程到底是不是写Python调一下大模型API我觉得不是。算法岗要研究模型结构、训练技巧、评估指标这是偏学术和研究的路线而“调包侠”是拿来一个现成SDK堆几个接口调用能跑通就完事。AI工程师恰好站在两者中间既要知道模型能做什么、不能做什么又要解决实际场景里的工程问题。我在这个项目里最早犯的错误就是把AI工程等同于“调用大模型”。结果写出来的Demo在本地跑得很欢一到真实业务里就崩上下文太长、输出格式飘、API限流、内存暴涨。真正让我意识到问题的是某次做一个文本整理工具模型输出偶尔会多出几句废话用户直接拿这些废话去入库后续流程全乱。那一刻我才明白AI工程的核心从来不是“模型多聪明”而是“怎么让一个不完全可控的东西在可控的流程里稳定工作”。所以这套ai-engineering-from-scratch项目从一开始就定下目标用项目驱动的方式把下面几块拼图凑齐——大模型的接入与调用、提示词的结构化设计、智能体工作流的编排、上下文与记忆管理、异常排查和性能优化。每块内容都配套一个最小可运行的代码示例而不是甩一堆理论链接。1.2 两条学习路线的对比课刷完型 vs 项目驱动型很多入门的朋友喜欢先花两个月把网课刷完把里面每一个概念抄到笔记里再开始动手。我试过效果很一般。因为网课是按知识点组织的而现实项目是按问题组织的。你在题目里学到的“温度系数调低会让输出更确定”到了真实项目里却不知道温度、top_p、max_tokens这几个参数一起变化时到底谁在起作用。项目驱动型的思路完全不同先确定一个足够小的目标小到能在一周内跑出第一版。比如先做一个“能根据我的自然语言输入整理出一份带标题和要点的会议纪要”的脚本。这个目标看起来很窄但它逼迫你在一周内接触至少五块核心知识怎么读取文档、怎么调用大模型、怎么写提示词、怎么解析模型输出、怎么处理输出不合规的情况。我整理过一张对比表放在项目README里这里直接搬过来课刷完型路线项目驱动型路线知识组织按学科划分学完不一定知道用在哪按真实问题划分学了马上能用正反馈周期慢学一个月可能还是不会做东西快一两天就能看到一个能跑的程序记忆保留容易忘概念和场景是脱节的记得牢每个概念都连着一段踩坑经历工程能力偏弱只写过孤立练习题强被迫处理依赖、环境、异常、部署适合人群有大量时间、想系统打底子的在校生在职转方向、想尽快做出东西的人我推荐后者但也不是完全放弃前者。正确姿势是先定一个小项目然后只学“今晚能用到的那点理论”用完再补相关性高的下一块。比如写提示词之前只需要知道模型是按概率生成文本的了解温度和top_p两个参数就够等做到了智能体再去补函数调用的底层实现逻辑。1.3 我的仓库目录结构怎么把零散知识装进一个框架零散的知识如果不装进框架约等于没有。我在ai-engineering-from-scratch里用的目录结构长这样ai-engineering-from-scratch/ ├── 01-basic-env/ # 环境搭建与第一个调用 ├── 02-prompt-basic/ # 提示词基础指令、约束、示例 ├── 03-output-parsing/ # 模型输出的结构化解析 ├── 04-memory-context/ # 上下文管理与记忆机制 ├── 05-agents-workflow/ # 智能体与工作流编排 ├── 06-local-deploy/ # 本地部署与模型选型 ├── 07-debugging/ # 常见问题与排查脚本 └── README.md每个目录里都有一份README.md说明思路一份main.py或main.ipynb放可运行代码一份lessons.md记录当时的坑。这个结构不是为了好看而是为了逼自己在学每一块新知识时都问三个问题这个知识点解决了什么实际问题它能被写成一个最小复现吗如果老手看到这段代码会挑什么毛病事实证明这样组织学得极快。以前我看文章读到“上下文窗口”“检索增强”这些词只是眼熟现在一看到它们脑子里自动浮现出对应的代码文件和出错现场。2. 工具链与运行环境稳比炫技重要2.1 搭建Python环境虚拟环境和依赖锁AI工程里有个很尴尬的现状跑了半天报错最后发现是numpy版本不对。所以环境搭建这一块我放在所有代码之前而且用的是最笨但最稳的方式python -m venv .venv source .venv/bin/activate # Windows下用 .venv\Scripts\activate pip install --upgrade pip pip install openai python-dotenv pydantic pip freeze requirements.lock这里python-dotenv用来管理API密钥绝不让密钥出现在代码里。.env文件长这样LLM_API_KEY你的密钥 LLM_BASE_URLhttps://你的接口地址 LLM_MODEL你使用的模型名用pydantic是提前为输出解析做准备。很多刚入门的朋友不理解为啥要freeze出requirements.lock我举个真实例子某次我把依赖升级了两个小版本结果pydantic从v1切到了v2所有.parse_obj()的写法全部失效。如果没有锁版本这种问题能让人查一整天。如果是Java后端我建议直接看spring ai这套Spring官方生态它对常用模型都有统一接入封装切换模型不乱改业务代码但学原理阶段还是先用Python原因是Python的数据处理生态更直接写实验代码最快。实操心得虚拟环境不是给项目用的是给“你自己”用的。每开一个新实验项目就新建一个虚拟环境别嫌麻烦。定期跑一次pip list看看装了什么没用的包顺手清掉。环境乱了之后排查问题的时间成本远超你一开始多花的那三分钟。2.2 大模型接入的三种方式在线API、SDK封装、本地部署我在项目里总结了大模型接入的三种典型方式它们各有用途别只看名气选。第一种是在线API最省事适合做原型验证和常规业务。只需一个密钥、一个HTTP请求不需要GPU、不需要运维。缺点是数据要出公网部分行业没法接受还有按token计费调得不好成本很高。第二种是SDK封装。官方SDK解决的问题不只是“少写几行HTTP”它帮你处理了重试、超时、请求日志这类基础工程问题。比如Python生态里的openai库、Java生态里做Spring AI封装都不需要我们手写鉴权和连接池。但用SDK也有坑——版本升级非常频繁接口动不动就变。所以我的习惯是在自己的代码里再包一层薄薄的LLMClient类把模型调用集中在一个文件里未来换库、换模型只动这一个文件。第三种是本地部署适合数据敏感、离线运行、需要深度定制代码的场景。这个对硬件有要求显存越大越好。我自己的经验是先在Hugging Face上找量化过的模型优先考虑参数量中等、社区活跃的版本不要一上来就塞一个几百B的巨无霸。本地部署的核心是“能跑起来”优先“效果更好”其次现阶段不少商用模型接口已经足够好用除非必要不建议轻易走本地路线。2.3 AI编程辅助PyCharm AI插件与代码补全的配合再说一个很多人忽视的“隐形工具”——AI编程助手。我用的是PyCharm装了一个官方的AI插件另外开了GitHub Copilot做补全。这两者定位完全不同Copilot管“行级补全”写繁复的样板代码很快AI插件管“对话式分析”适合让它解释报错、生成单元测试、重构函数。但我也想提醒一件事AI编程助手解决的是手速问题不能解决判断问题。它生成的提示词模板、参数配置、异常处理逻辑看起来很像回事但经常埋着逻辑漏洞。有一次我让它帮忙写一个带重试的调用函数它确实写了重试但重试时没有退避也没检查每次响应是不是真的成功结果在限流场景下把错误全吞了。从那以后我给自己定了个规矩AI写的代码必须逐行读懂并且用真实输入跑一遍测试。3. 核心知识拆解提示词、智能体、工作流3.1 提示词工程的基础逻辑指令、约束、示例、格式说到提示词工程Prompt Engineering很多人觉得它就是“把问题问清楚一点”。对了一半。真正工程化的时候提示词不只是一个句子而是一套数据结构。我常用的模板分四个部分【系统指令】你是负责文本整理的中文助手只输出处理后的结果不解释过程。 【用户输入】请把下面这段文字转成三条要点列表每条不超过20字。 【约束条件】不要使用感叹号和问号不要输出任何额外内容。 【输出格式】每条要点以“- ”开头。为什么把约束和格式单独拆出来因为模型对模糊的口语化描述容易按自己的理解发挥。你写“请帮我润色一下”它不知道你要正式还是活泼、要不要保留口语词但你写了“每段开头不要重复”这类具体约束输出稳定性会明显提升。另外还有一个核心技巧给示例。给一个输入和输出的配对示例效果往往比多写三句抽象说明都好。这本质上是让模型在生成时有一个“形态复刻”的锚点。我在项目里专门做过实验同一个任务不带示例的准确率大约七成带一个示例后几乎稳定在九成以上。3.2 用智能体思路组合模型能力从单次调用到自主循环一次调用解决不了所有问题这时就要上“智能体”AI Agent。我之前一直以为智能体是某种神奇框架后来自己动手写了一个极简版本才明白它的本质就是一个循环先观察结果再决定下一步动作然后调用工具再观察直到任务完成。我在05-agents-workflow目录里留了一个最简实现核心逻辑只有不到一百行messages [{role: system, content: system_prompt}] for step in range(max_steps): response client.chat.completions.create( modelconfig[model], messagesmessages, toolstool_definitions, ) if response.choices[0].message.tool_calls: # 解析工具调用执行真实函数把结果追加到对话 handle_tool_call(response, messages) else: final_answer response.choices[0].message.content break这个循环看起来简单但工程点全藏在细节里工具调用协议怎么定义参数执行函数出错后怎么把错误信息传给模型循环最多跑多少步才能防止死循环每一步都涉及大量打磨。我的建议是第一次接触智能体时不要上来就套LangChain之类的重型框架先手写一次这个循环。手写过了再去看框架的抽象设计立刻就能看懂它为什么那么设计。3.3 AI工作流编排把非结构化需求变成结构化任务把多个模型调用、多个工具调用组合成一条生产线就是AI工作流。举个例子做一个短视频文案生成器单独调一次模型只能得到一段文案但引入工作流之后流程可以拆成第一步先根据主题生成三个标题备选第二步让模型对每个标题打分第三步选最高分的标题扩写正文第四步把正文拆成适合口播的短句。每个步骤的输出都作为下一步的输入步骤之间可以插入规则判断。工作流的意义不只是“多调几次模型”而是把不确定性控制在局部。比如第四步的“拆短句”如果交给模型自由发挥它可能会漏掉重点那我可以在第四步后面加一个正则校验逐条检查结果里是不是包含了标题里的关键字。规则可以兜住模型的底模型可以为规则补充灵活性两者配合才是工程实践。我推荐使用json作为步骤间的传输格式因为大部分模型输出都能被解析成JSON字符串后续处理方便。但解析JSON时一定要用异常捕获别假设模型每次都会输出合法JSON。真实情况是模型可能在你格式要求极严时还是顺手输出一段Markdown代码块包裹的假JSON这种坑我踩过不止一次。4. 实战过程从零写一个可运行的AI助手4.1 目标与需求我要做一个什么样的小工具理论讲再多不如动手做一个完整的小工具。我们的目标定为一个“会议纪要整理助手”。它接收一段原始会议记录文本输出结构化的Markdown文档包含会议主题、讨论要点、待办事项三个部分。为什么选这个需求因为它麻雀虽小五脏俱全需要读取输入文本、调用大模型、要求输出结构化数据、又要处理“模型输出跟格式要求不匹配”的常见故障。整个工具不依赖数据库不依赖前端能在一杯咖啡的时间里跑通非常适合作为第一个AI应用的起点。4.2 手敲实现核心代码与关键参数说明我一上来把需求拆成了三块读取输入、构造调用、解析输出。环境用之前配好的虚拟环境模型接口统一走LLMClient。import os import json from dotenv import load_dotenv from openai import OpenAI load_dotenv() client OpenAI( api_keyos.getenv(LLM_API_KEY), base_urlos.getenv(LLM_BASE_URL), ) system_prompt 你是一个会议纪要整理助手。 请根据用户提供的原始会议记录输出JSON格式的结构化结果。 要求 1. meeting_topic: 一句话概括会议主题。 2. discussion_points: 讨论要点列表每条不超过30字。 3. action_items: 待办事项列表每条包含负责人和事项。 不要输出任何解释性文字只输出JSON对象。 def summarize_meeting(raw_text: str) - dict: completion client.chat.completions.create( modelos.getenv(LLM_MODEL), messages[ {role: system, content: system_prompt}, {role: user, content: raw_text}, ], temperature0.3, ) content completion.choices[0].message.content return parse_json_result(content) def parse_json_result(content: str) - dict: if content.startswith(): content content.strip() content content.removeprefix(json).strip() try: return json.loads(content) except json.JSONDecodeError as e: # 真实项目里这里是重试逻辑入口先简单抛异常 raise RuntimeError(f模型输出不是合法JSON: {e})注意这里temperature0.3我刻意调低了随机性因为会议纪要追求的是稳定格式和事实摘要不是发散创作。如果做文案灵感生成温度会调高到0.8甚至1.0。这两个场景在同一套代码里只是参数不同效果完全不同。调通第一版后我发现实际输入里经常有大量口语词、碎片话模型会把那些“嗯嗯啊啊”也整理进讨论要点。于是我在用户输入之前加了一步清洗把常见语气词和重复词用正则先过滤掉。这又印证了一个判断AI应用里一部分问题根本不需要模型解决用传统代码处理更便宜、更稳定。4.3 联调与迭代如何根据输出反推Prompt修正第一次跑通的结果并不理想输出JSON里action_items存在但缺少负责人字段而且会议主题抓偏了。这时候才开始真正有价值的迭代。我的方法很简单——把错误输出当成诊断信息反向去改提示词。第一步我看输出里JSON格式是对的说明格式约束生效了但待办事项缺负责人说明提示词里“每条包含负责人和事项”不够明确。于是我改成了这样的约束action_items: 待办事项列表每个元素必须包含lowner负责人、task任务、due_date截止日期或“待定”三个字段。第二步主题抓偏是因为原始记录里有大量寒暄内容。我在用户输入前面加上一句“忽略寒暄和与业务无关的闲聊只关注实质内容。”这一句看着不起眼实际作用极大。改完提示词再跑结果稳定了不少。但我没停在这里而是继续做了两个增强一是用retry机制当JSON解析失败时把报错信息拼接进系统提示词让模型自己修正二是把关键输入截断到2000字以内避免长文本把输出质量拖垮。这两个增强让工具从“在演示时能用”变成了“实际能用”。5. 问题定位与调试思路AI应用开发的真正门槛5.1 上下文溢出与输出截断我做过一个批量总结的脚本输入是几十份长文档跑着跑着就突然崩溃。排查后发现不是程序崩溃而是模型在超过上下文窗口后直接报错或者输出在某个位置被硬截断后面的内容丢失。上下文管理是AI工程最常见的问题没有之一。解决办法分两层。第一层是输入侧在调用模型之前先估算文本的token数量超过阈值就做分段处理比如按标题分块每块单独调一次模型最后再合并结果。第二层是输出侧把max_tokens设得足够大同时提示模型“先输出结论再补充细节”这样即使被截断核心内容也在。我还加了一个简单函数来估算token数大概是中文字符数乘以1.5到2这是按常见模型的分词行为粗略估的。虽然不精确但用来做阈值判断足够了。关键是不要等到进了模型才报错在代码里提早拦下来。5.2 幻觉、重复和格式漂移模型一本正经地编造不存在的会议结论这就是“幻觉”。这没法彻底根除只能缓解。我的经验是给模型的上下文里放入越多可验证的原始素材幻觉越少。所以提示词里要写“只能基于用户提供的材料作答材料中没有的信息一律输出‘未提及’”这句话能有效压低编造概率。重复也很常见尤其是生成长文本时模型会在后半段反复念叨同一句话。把temperature调低一点、把frequency_penalty调高一点通常能缓解。格式漂移则是模型跑着跑着突然不用而用或者多个字段不按顺序来了。应对方式是用解析后的schema校验兜底不合法就走重试而不是相信模型每次都老实。5.3 限流、超时与异常恢复接在线API时限流和超时是绕不开的。多线程并发调用比单线程更容易触发限流。我在项目里推荐一个简单的“指数退避重试”策略第一次失败后等1秒再试第二次等2秒第三次等4秒最多重试5次。这比自己瞎写time.sleep(1)要可靠得多也避免了对服务端造成额外压力。超时设置也要分场景普通对话请求给30秒足够但碰到需要长思考的复杂任务建议调低到10秒内快速失败改用异步队列异步处理。真实项目里同步调用异步任务队列是两种互补模式而不是非此即彼。5.4 成本与性能平衡策略最后把账算算。我做过一个统计一个客服话题分类应用如果用高精度大模型给每条消息做分类月成本会追上服务器费用。后来我把方案改成“先用小模型做初筛遇到低置信度的样本再升级到大模型”成本直接降了一半还多准确率几乎没有下降。这个策略叫“链路分级”它背后的思路是不要让每一条请求都为最坏情况买单。性能调优也一样prompt里把示例压缩到最短、能用缓存的结果不重复调用、批量请求尽量合并成一个请求批次这些都是实打实的优化手段。6. 事后复盘几条让我少走弯路的经验这个ai-engineering-from-scratch项目做到现在对我最有用的不是某个代码片段而是几条做事原则。第一条任何模型调用都要放在自己封装的函数后面别让第三方SDK直接散落在业务代码里否则换一个模型版本你会想原地离职。第二条一定要准备好“模型不配合”的应急预案JSON解析失败要重试上下文超限要分段并发受限要排队这些不是极端情况而是日常。第三条传统代码能做好的事就不要交给模型正则、字典映射、规则判断既便宜又稳定模型的价值在于处理“规则定义不清楚”的语义问题而不是取代所有代码。我最近还在做一些扩展比如把智能体循环里的工具调用改成异步并发、把工作流的每一步都加上耗时和token统计、把提示词模板变成可以挂在配置中心的参数。每一步都是小而实用的改动但合在一起这个项目才像是真正可落地的AI工程而不是一组脆弱的脚本。如果你也想照这个路线走一遍我的建议很简单别收藏太多资料先照着配好环境跑通一个几十行的调用然后去改它、去拆它、去让它出错。出错一次学到的东西比看十篇文章都多。这就是“从零开始”最大的价值——你不只是学会了工具而是有了自己的判断力。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。