拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

AI工程从零到一:提示词工程、RAG链路与多智能体协作实战

AI工程从零到一:提示词工程、RAG链路与多智能体协作实战

做AI工程这件事,我从“只会调API”到能独立搭起一套完整的多智能体协作系统,大概花了四个月。如果你现在准备从零开始,我想告诉你:这个领域最难的其实不是模型,而是工程化的思维。项目标题叫ai-engineering-from-scratch,说的就是这么一件事——把散落的模型调用、提示词、数据管道、评测方法,组织成一套像样的工程系统。

这篇文章适合三类人:刚入门想找方向的开发者、已经在做传统软件想转型的程序员、以及那些手里有业务场景但不知道怎么落地AI的人。我会把这条路上的路线规划、核心技能、实操项目、选型思路、踩坑记录全部摊开来讲,争取让你读完之后,能自己动手搭起第一个真正“工程化”的AI应用。

1. 先想清楚:AI工程到底在做什么

1.1 它和传统软件开发的本质区别

很多人把AI工程理解成“调用大模型接口写个聊天机器人”,这个认知会害了你。传统软件开发的核心是确定性逻辑——你写一个函数,输入同样的参数,输出永远是同样的结果;而AI工程的核心是不确定性系统——同样一句用户问题,模型今天给你的回答和明天给你的回答可能就不同,温度参数调一下风格就变了。

这就带来一个根本转变:你不能用“正确/错误”来验收AI应用,而要用“质量/召回/延迟/成本”这套指标来评估。传统开发的测试用例是断言返回值,AI工程的测试用例是一批覆盖典型场景的评测集,跑完之后人工打标或让另一个模型打分。

我在刚开始做的时候就犯过这个错误。第一次搭对话机器人,我花了两个星期把代码写得特别“健壮”——异常捕获、重试机制、日志系统全上,结果模型回答经常跑偏,用户反馈很差。后来我才明白:AI工程的主轴不是代码健壮性,而是数据质量、提示词稳定性和评测闭环。代码是骨架,数据是血液,评测是眼睛。

1.2 工程化思维的两个核心组成部分

AI工程要落地,必须拆成两条线:模型应用链路和工程支撑体系。

模型应用链路指的是:从用户输入到模型输出这一路上要做的所有事——意图识别、上下文管理、检索增强、提示词构造、输出格式校验。工程支撑体系则是:数据准备、模型选型、成本控制、评测回归、日志追踪、版本管理。这两条线缺一条都不行。

我在做企业级项目时遇到过一种典型情况:算法同事把模型效果做得很好,demo演示效果惊艳,但一部署上线就崩——并发上来延迟线性增长、日志里全是上下文截断的报错、用户多轮对话偶尔串话题。原因就是只关注了链路,忽略了支撑体系。你把这些支撑能力补上之后,才算真正“工程化”了。

2. 从零开始的AI工程路线规划

2.1 零基础到入门的三个月路线表

我把自己的学习路径整理成表格,照这个顺序走,能避免很多弯路:

阶段周期核心内容交付物
基础打底第1~2周Python基础、HTTP调用、JSON处理能写脚本调用一个开源模型API
单点突破第3~6周提示词工程、上下文管理、常见模型能力边界做一个单轮问答机器人
链路打通第7~10周数据清洗、向量数据库、RAG链路、评测方法做一个带知识库的文档问答系统
工程化提升第11~12周Agent编排、多智能体协作、工作流设计、性能优化做一个多工具协作的Agent系统

这个路线不是随便排的。单人开发AI应用最容易遇到的瓶颈,就是还没学会走就想跑——基础没打好就去搞Agent编排,结果连提示词都调不稳,排查问题时不知道是哪一环出了问题。循序渐进地把每一层都踩实,后面才能走得快。

2.2 哪些知识其实不用深究

从零开始最怕的就是贪多。我见过太多人耗在数学公式里出不来,学了三个月微积分和线性代数还没碰过模型API,这种学习方式不适合追求工程落地的人。AI工程需要的数学知识,用到的时候再查完全来得及。

同样,不建议一开始就死磕模型训练和微调。开源的指令微调框架和部署方案文档很多,但那是另一个深水区。做应用工程的核心是先学会用别人的模型,把数据、提示词、检索、评测这些“外围功夫”练好,这些才是日常工作中占比最高的部分。

我自己有一个判断标准:一个知识点如果三天内用不上,就先不学。这个标准帮我过滤掉了很多看似热门但短期用不上的内容,让我把时间都花在了刀刃上。

3. AI工程的核心技术点逐个击破

3.1 提示词工程:不是“写提示词”而是“调试提示词”

很多人把提示词工程想得太简单了,以为就是学会用“请帮我...”这种话术。真正做过的人会告诉你,提示词工程的核心是结构化调试。你的提示词要拆成几个固定模块:角色设定、任务描述、输入输出格式、约束条件、示例引导。

举个例子,我做一个合同审查助手时,初始提示词写的是“请审查这份合同的风险点”,效果极差——模型回答笼统且不专业。后来我把提示词改成结构化模板:角色是资深法务顾问,任务分三类(条款缺失、责任不清、风险预警),输出用JSON格式包含条款编号、风险等级、解释、修改建议,每一步都给了具体示例。效果提升非常明显,这说明提示词不是“写”出来的,而是“调”出来的。

调试提示词有一个非常实用的方法论——对比测试。你准备十个典型输入,每次改完提示词就把十个输入都跑一遍,记录输出质量和格式稳定性。很多人改提示词只拿一两个例子试,看着效果不错,上线之后才发现其他场景全崩。专业的做法是建一个小的回归测试集,每次改动都跑全量。

3.2 RAG检索增强:知识问答系统的地基

RAG(检索增强生成)是把外部知识注入模型的一种工程方案。既然大模型学到的知识有截止时间,又容易在专业领域瞎编,那就干脆不让它凭记忆回答,而是先从一个知识库中检索出相关片段,再把片段和用户问题一起送入模型做总结。

RAG链路里的关键参数很多人不会调。第一个是分块大小,我一般按300到500字切分,太小了语义被切断,太大了检索精度下降;第二个是召回数量,默认给4个片段,然后根据评测结果往上调,调整到6个时回答质量最高,超过8个反而下降——因为无关信息变多了,模型容易被带偏;第三个是重排序,粗召回50个片段,精排取前5个,这一步能明显提升核心回答的准确率。

我要特别强调一个数据清洗问题:知识库文档里如果有表格、图片、特殊符号,直接塞进分块器会出现大量乱码和语义割裂。我的经验是先做文档结构解析,把标题层级、表格转成文本、图片内容转成文字描述,再进入分块流程。这一步消耗的精力比模型调试多得多,但恰恰决定了RAG系统的上限。

3.3 Agent与多智能体协作:从“工具调用”到“任务编排”

Agent是当下AI工程绕不开的概念。我个人理解,Agent的本质是让模型具备“观察环境-做出决策-执行动作-观察反馈”的循环能力。工程落地时从简单到复杂会经历三个层次:单Agent调用外部工具、多个Agent各司其职、一个编排层管理多个Agent协作。

我建议你从单Agent练起,比如给模型配一个计算器工具,让它遇到数学问题时自动调用。过程中你会接触到函数调用(function calling)的机制:模型输出一段结构化指令,你的代码解析并执行对应工具函数,再把结果返回给模型。这一步能走通,后面多Agent也就是水到渠成。

做多智能体协作时,最常见的问题是Agent之间互相“抢话”或“甩锅”。我的解决方案是给每个Agent写一份极简的SOP:这个Agent负责什么、什么情况不归它管、输出必须是什么格式。单独一个Agent的提示词可以追求“聪明”,但多Agent协作时更应追求“规矩”。把每一步的输入输出定义清楚,比提升单个Agent能力更重要。

3.4 AI工作流:把重复劳动固化下来

工作流是AI工程落地的另一个关键。我的一个原则是:任何一份提示词,只要我用过三次以上,就必须把它固化成一个流程。举个例子,我在做行业分析时,以前每次都要对一堆资料重复执行“摘要→提炼→报告”三步,后来我用代码把这三步编排成一条流水线——自动读取待处理的文档列表、逐个执行摘要、汇总成章节、最后按模板生成周报。

固化工作流的好处有三点:一个是稳定,不会因为每次手写提示词的细微差异导致输出质量波动;一个是可复用,换一批数据就能跑出同类型的结果;一个是可优化,所有环节都参数化之后,做A/B测试只需要改配置。我个人建议你用JSON或YAML来定义工作流步骤,把每个节点的模型、提示词、输入来源、输出目标写清楚,比在代码里硬编码更容易维护。

4. 从0到1:搭一个AI问答Agent的完整案例

4.1 项目设计与技术选型

我拿自己最近做的一个“会议纪要智能问答Agent”来完整拆解。需求很简单:公司每周产生大量会议纪要文档,散落在共享盘里,员工想查“上个月关于预算调整的会议结论是什么”时只能人工翻文件。项目目标就是让用户用自然语言提问,Agent从所有历史会议纪要中找到答案。

技术选型上,我用的是LangChain作为编排框架 + OpenAI兼容API调用模型 + 向量数据库做检索 + Streamlit搭一个最小可用界面。你可能会问为什么不用LlamaIndex或者直接裸写,我的考虑是:LangChain的组件抽象比较成熟,LCEL(LangChain表达式语言)支持组合式管道定义,遇到结构变化时改起来不伤筋动骨。如果你就做一个最简单的知识问答,LlamaIndex上手的曲线更低一点,但考虑到后续还要扩展Agent能力,LangChain更合我的习惯。

聊天UI选Streamlit是因为它足够快,一段Python代码就能生成前端界面,对于内部工具来说完全够用。你要给外部客户做产品,那另说,但做验证和内部提效,它是效率最高的选择。

4.2 从文档清洗到向量化的完整流程

处理会议纪要文档的坑,比我想象中多。第一版我直接拿.docx文件转纯文本,结果发现三个问题:页眉页脚混入正文、列表层级信息丢失、会议室地名和参会人信息污染了检索结果。我的清洗顺序是这样的:

先用python-docx库读取文档结构,只提取正文段落和表格;然后过滤掉包含“会议地点”“记录人”“审核人”关键词的行;接下来做段落合并——会议纪要里经常一句话一个段落,如果直接切分,每个分块只有几十个字,语义太弱,我按照主题相关性把连续短段落合并到300字左右;最后把清洗后的文本交给嵌入模型生成向量,存入Chroma向量数据库。

这里有个嵌入模型的选择经验:中文场景下使用bge-m3的效果很不错,比同时期的英文模型在中文语义匹配上更稳定。但要注意,嵌入模型的一致性一定要保持——入库和在线检索必须用同一个模型,否则向量空间不一致,检索结果会非常奇怪。

4.3 核心代码实现与参数解读

完整的调用链路核心代码不长,我把关键部分写出来,你对着梳理一遍就能理解整体逻辑:

from langchain_community.document_loaders import DirectoryLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_community.vectorstores import Chroma from langchain_community.chat_models import ChatOpenAI # 第一步:加载文档目录中的所有 .docx 文件 loader = DirectoryLoader("./meetings/", glob="**/*.docx") documents = loader.load() # 第二步:按语义切分文档,chunk_size=300,overlap=50 text_splitter = RecursiveCharacterTextSplitter( chunk_size=300, chunk_overlap=50, separators=["\n\n", "\n", "。", ";", ",", " "] ) chunks = text_splitter.split_documents(documents) # 第三步:生成向量并写入数据库 embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-m3") vectorstore = Chroma.from_documents( documents=chunks, embedding=embeddings, persist_directory="./chroma_db" ) vectorstore.persist()

有几个参数值得认真琢磨。chunk_overlap我设为50,相邻分块之间保留一部分重叠文字,这样当一句话恰好被切到两块时,模型至少有一边能看到完整语义;separators的写法,是把中文句号和分号也作为切分点,避免英文默认的按空格和换行切分导致中文句子被拦腰截断;嵌入模型路径写BAAI/bge-m3时,首次运行会自动从魔搭社区下载权重,之后离线也能用。

4.4 查询链路与提示词模板的完整设计

数据入库之后,真正对用户提问的回答过程是这样的:先把用户问题转成向量,在数据库里做相似度检索取回TopK个片段,再把这些片段拼到提示词模板里,连同原始问题一起送进大模型。我给出查询侧的核心代码:

from langchain_core.prompts import ChatPromptTemplate # 检索器:k=6,检回6个相关片段 retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 6}) # 提示词模板:明确要求模型只依赖给定内容回答 prompt_template = ChatPromptTemplate.from_messages([ ("system", """你是会议纪要问答助手。请根据下面给定的资料回答问题。 如果资料中没有相关内容,请如实说“资料中未找到相关信息”,不要编造。 回答时请标注信息来源,格式为[片段序号]。 资料: ---------- {context} ---------- """), ("human", "用户问题:{question}") ]) def query(question: str): docs = retriever.invoke(question) context = "\n\n".join( f"[片段{i+1}] {doc.page_content}" for i, doc in enumerate(docs) ) messages = prompt_template.format_messages(context=context, question=question) response = chat_model.invoke(messages) return response.content, docs

我在调试阶段最常改的就是k值这参数。设得太大,无关片段混进来,模型容易答非所问;设得太小,又会出现漏掉关键信息的情况。对会议纪要这种短文档场景,k=6在大部分问题上表现都很稳。你上线第一版时别贪多,也先按这个值来,再根据自己的评测结果调。

另外提示词里“不要编造,没有就说没有”这句约束十分关键。不加这句约束时,模型经常在资料覆盖不到的地方自作聪明地补一段“推测”,这在企业内部工具里是绝对不能接受的。信息追溯的需求强烈时,还要强制模型在每条回答后面列出它依据的片段序号,方便回到原始文档核验。

5. 工程化落地:模型、成本与评测的三角平衡

5.1 模型选型的关键维度:性能、成本、延迟

同一个AI应用,模型选型不同,落地体验天差地别。以我的问答Agent为例,在大模型API选型上我做了三个候选:顶级旗舰模型、均衡型模型和开源本地部署模型。对比维度如下:

方案单次回答成本延迟回答质量适用阶段
旗舰大模型高1~3秒很强,长文总结能力强上线初期、口碑验证期
均衡型模型中0.5~1秒良好,精简任务够用日常运行、成本敏感期
开源模型本地部署极低(算力另算)0.3~1秒中等,依赖硬件数据敏感、离线场景

我的建议是:第一版绝不贪便宜,先用旗舰模型把体验滚起来,跑通业务闭环后再评估量化收益。内部工具阶段把模型切换成均衡型是性价比最高的操作——回答质量略有下降,但成本能降一个量级。数据敏感的企业场景必须做本地部署,这不只是成本问题,合规压力的权重远大于模型性能差距。

5.2 评测闭环:让AI应用可以迭代

AI工程最容易被忽视的是评测。没有评测,你就说不清一次提示词改动、一次模型升级到底是变好了还是变坏了。我建评测集的思路很简单:从真实用户历史问题中抽50条,覆盖高频场景和疑难边界场景;每条问题写好标准答案模板,答案模板不需要是完美答案,但必须标注关键信息点。

跑评测的方式有两种:低成本初筛人工看,高成本精标用模型打分。我每周跑一次评测流程:用当前线上的配置跑一遍50个问题,然后用一个更强的模型按“正确性、完整性、格式规范”三个维度打分,再从中随机抽10条人工复核。这套方法让我在迭代模型和提示词时有了客观依据,不再凭感觉改动。

5.3 多Agent与多AI协作的经验边界

当你开始做多Agent协作时,评测与成本问题会更复杂。多个Agent串行工作,任何一个环节出错都会传导到最终答案,所以要为每个中间环节定义独立的评测点。成本上,一个复杂的多Agent任务,单次完整执行的token消耗可能是一个简单问答的十到二十倍,必须把模型的“能不用就不用”策略用到极值——简单问题走轻量模型,复杂问题才调度大模型和多个Agent协作。

我现在使用的一个策略是分层路由:用户提问先经过一个轻量意图识别模型,判断问题简单还是复杂;简单问题只走单Agent单模型,复杂问题自动升级到多Agent协作链路。这套机制上线后,整体成本下降了接近六成,而复杂问题的用户满意度没有明显变化。这类经验在Transformer的背书上你是查不到的,全靠实际业务数据慢慢磨出来。

6. 实操中的典型问题与排查技巧

6.1 检索效果差的三大原因与调优顺序

知识问答系统的用户抱怨“答非所问”,大部分时候不是模型不行,而是检索不行。我复盘自己项目中的问题,总结出三类头号原因:

第一是切分不合理。如果分块太小,一个完整的论点被拆散,检索到的片段缺头少尾;分块太大又导致一个片段包含多个主题,模型会被无关信息干扰。调整方法是先做文档结构分析,看语义边界在什么地方,再定分块参数。

第二是嵌入模型与领域不匹配。通用嵌入模型在专业领域的效果可能很差,比如法务、医疗、技术术语多的场景,常识相似度与实际语义相关度经常背道而驰。解决办法就是换用领域微调的嵌入模型,或者做小样本的微调。

第三是召回策略太单一。只用向量相似度,遇到关键词完全不同的表达就抓瞎。我现在的标准方案是“关键词检索+向量检索”双路召回,然后用重排序模型融合排序。实现时用BM25配一个CrossEncoder重排,效果立竿见影。

6.2 常见的提示词陷阱与我总结的排查顺序

模型输出格式不稳定是我被问得最多的问题。你说“给我JSON格式”,它偶尔给你来段解释性文字。最有效的解法是:在Python里做强制解析和重试循环——解析失败就带着报错信息重新请求模型,让它修正输出。这个机制我把代码贴在下面:

import json import re def extract_json(text: str): # 提取第一个JSON对象或数组 pattern = r"(\{.*\}|\[.*\])" matches = re.findall(pattern, text, re.DOTALL) if not matches: raise ValueError("no json found") return json.loads(matches[0]) def ask_with_json_retry(prompt, max_retries=3): for i in range(max_retries): response = chat_model.invoke(prompt).content try: return extract_json(response) except Exception as e: prompt += f"\n上次输出格式错误,请重新输出,必须严格符合JSON格式。错误信息:{e}" raise RuntimeError("failed after retries")

6.3 排查问题时的信息收集习惯

AI应用出了Bug,最大的痛点是没有“现场”。传统软件可以打日志定位问题,AI应用经常输出结果看起来合理但细究细节是错的,必须记录更多元的信息。我建议从第一行代码就记录用户原始问题、关键词检索TopK的露出顺序与得分、送入模型的完整Prompt、模型原始输出、最终展示内容,这五层信息缺任何一层都可能让问题无法复现。

这套日志体系建立之后,排查效率提升非常显著。有一次用户反馈回答里的引用信息乱,我翻了日志才发现是重排序模型把段落顺序打乱了,但Prompt模板里用的是检索原始顺序的片段编号,导致标注对不上。这类问题不靠完整链路日志,你猜十天也猜不出来。

7. 一些从实战中沉淀下来的个人体会

回头看过这几个项目的推进过程,我最大的感受是:AI工程从零开始,本质上练的不是“会用AI”,而是“会拆解问题”。我把自己经历过的那些弯路、反复踩过的坑,沉淀成一条对新手最有用的建议——用最小闭环先跑通一个端到端的应用,再回头补齐体系。不要一开始就规划一个宏伟的多Agent平台,那样会在架构设计里耗掉大量时间和热情。

最后分享一个小工具习惯:我用一个名为prompt_registry的Python文件管理所有的提示词版本,每次改动就复制一个新版本号,实验过程中使用什么版本一目了然。这节省的排查时间,远超写这个文件本身花费的时间。

AI工程这条路,每三个月就会冒出一批新概念和新工具,但底层的数据意识、评测闭环、工程素养不会过时。从今天开始跑通你的第一个问答Agent,后面的事会越来越顺。

返回列表