ARTICLE DETAIL

资讯详情

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

AI应用工程化实战:从Prompt到Agent的完整交付链路

AI应用工程化实战:从Prompt到Agent的完整交付链路 AI 人才争夺已经从互联网大厂扩散到半导体制造、汽车、金融等传统行业。公开报道显示台积电 2026 年第二季度奖金总额约 360 亿新台币同比增长 50.6%。这个数字是否精确不必深究它反映的趋势很明确企业开始用真金白银争夺具备模型应用与工程化能力的人才。对开发者来说与其盯着奖金数字不如把精力放到可迁移的能力上。下面以一条完整的技术链路为例从提示词设计、模型接口接入到 RAG 检索增强、Agent 工具调用再到本地模型部署、GPU 加速和幻觉排查把一个 AI 应用从原型做到能交付的状态。这条路走通之后即使换一家公司、换一个业务场景核心方法依然适用。1. 先看清 AI 人才争夺背后的技术需求企业愿意为 AI 人才支付高溢价不是因为“会用 AI”的人稀缺而是因为能把 AI 稳定交付到业务里的人稀缺。模型能力越来越强调用门槛越来越低真正的竞争点已经转移到工程侧数据怎么准备、提示词怎么管理、检索效果怎么评估、接口异常怎么处理、幻觉怎么控制、成本怎么降低。这些工作都需要懂工程的人来落地。1.1 企业为什么愿意为 AI 人才支付溢价台积电这类制造企业面对 AI 人才战背后是一系列现实问题产线数据不能随便传到外部服务内部知识库分散在文档和系统里业务人员希望用自然语言直接查询数据管理层希望看到 AI 投入带来可量化的效率提升。这些问题没有一项是单个模型能解决的。真正被需要的是一套组合能力理解业务问题能否用大模型解决以及在哪里不适合用大模型。能把私有数据接入模型让模型回答业务问题时有所依据。能把模型、检索、工具、权限、日志串成一条完整链路。能持续监控模型输出的质量发现幻觉、重复、偏离主题等问题。奖金只是这些能力不足时产生的竞争溢价。一旦 AI 应用进入成熟期企业需要的不是更多会聊天的人而是更多能稳定交付系统的人。1.2 从“会用 AI”到“能交付 AI 应用”的五个能力层级如果把 AI 工程能力拆开可以分成五个层级。每一层都对应具体的交付物不能只停留在概念层面。能力层级核心内容典型交付物模型认知知道模型擅长什么、不擅长什么任务可行性评估提示词工程角色、任务、约束、示例、结构化输出稳定可复用的 prompt工程接入API 封装、超时重试、流式、鉴权、日志可运行的服务模块检索与记忆文档切分、向量化、召回、上下文拼装RAG 知识库问答工具调用与多步任务Function Calling、Agent 循环、状态管理能完成业务流程的 Agent多数人停留在第一、第二层也就是会调接口、会写提示词。真正拉开差距的是第三到第五层能不能把代码稳定跑起来能不能让模型回答不出错能不能让模型自动完成多步任务。1.3 实战主线做一个可运行的 AI 知识问答应用后面的内容围绕一个贯穿案例展开做一个技术资料问答应用回答问题是这个应用的入口。使用场景假设如下团队内部有一批技术文档业务人员希望用自然语言提问例如“服务器启动失败时应该先查哪些日志”“接口超时的常见原因有哪些”。应用需要做到三件事能基于内部文档回答而不是凭空编造。能调用外部工具完成查询、统计等操作。能在本地部署必要时使用 GPU 加速。这个案例规模不大但覆盖了提示词、API 接入、RAG、Agent、本地部署和评测排错所有关键环节。下面从环境准备开始。2. 环境准备与依赖选型动手写代码之前先确认环境。AI 应用的技术栈并不复杂但版本不一致会带来大量排查时间尤其是本地模型、向量库和 Python 包的版本。2.1 先决定本地模型还是云 API不同的部署方式决定了代码结构和启动方式。常见选择有三种方案优点代价适用场景本地模型数据不出内网、离线可用、按硬件资产投入需要 GPU、显存、运维数据敏感、业务量大且可预测云 API接入快、模型效果强、按 token 计费数据外传、单次调用成本原型验证、低频使用、效果优先混合敏感数据走本地复杂任务走云端链路复杂、两套成本大部分中大型团队从学习角度建议先跑通本地模型。原因很简单不需要申请密钥、不需要考虑预算、可以随时断网调试。后面代码中给出的是兼容 OpenAI 接口的写法这样切换云 API 时只需要改 base_url 和 api_key主逻辑不用动。2.2 基础环境检查清单建议先按下面的命令检查一遍环境再继续后面的步骤。python --version python -m venv .venv source .venv/bin/activate pip install --upgrade pip如果选择本地模型还需要安装 Ollama 并拉取模型。ollama --version ollama pull qwen2.5:7b ollama serve拿着一张检查清单逐项确认可以少走很多弯路。检查项命令预期结果Python 版本python --version3.10 或更高虚拟环境source .venv/bin/activate命令行前缀变化Ollama 版本ollama --version能输出版本号模型是否已拉取ollama list能看到 qwen2.5:7b本地服务是否启动curl http://localhost:11434返回 Ollama 信息2.3 项目依赖与目录结构建议新建一个独立目录避免和已有项目混在一起。ai-app/ ├── .venv/ ├── requirements.txt ├── chat.py ├── rag.py ├── agent.py ├── docs/ │ ├── internal.md │ └── api.md └── .env依赖文件 requirements.txt 内容如下openai1.30.0 chromadb0.5.0 python-dotenv1.0.1这里使用 openai 库是因为它已经成为事实上的模型调用标准。Ollama、多家云厂商都提供兼容 OpenAI 风格的接口写一套代码就可以在多个后端之间切换。2.4 学习环境与生产环境的差异学习环境可以把所有东西放在一台机器上程序能跑通就算成功。生产环境还必须考虑配置外置、鉴权、限流、日志、监控、回滚等事项。关注点学习环境生产环境模型地址写死在代码里通过环境变量或配置中心读取API 密钥不涉及或本地测试放入密钥管理服务不提交仓库日志无所谓按 trace id 串联完整请求链路并发单用户调试需要限流、排队、自动扩缩容异常打印即可需要有重试、降级、告警数据随便放需要考虑权限、备份、脱敏后面给出的代码示例主要用于学习环境但在写法和结构上已经在为生产环境做准备。3. 从提示词到最小可运行问答应用先做最小闭环本地模型已经启动现在让程序能问答。这个阶段不涉及复杂知识库只是验证提示词、API 接入和运行链路是否正常。3.1 提示词的三个基本要素角色、任务、约束提示词不是越复杂越好但至少要包含三个要素。角色告诉模型以什么身份回答问题例如“你是一名技术运维助手”。任务明确模型需要完成什么例如“根据用户描述给出排查建议”。约束限定回答风格、范围、长度例如“回答不超过 200 字”“不要编造日志内容”。一个稳定的提示词通常会加上示例。下面的 system prompt 用于后续问答应用你是一名技术运维助手。回答问题时优先给出可执行的排查步骤。 要求回答简洁不超过 5 步如果信息不足直接说明缺少什么信息。 不要编造日志关键字和系统命令。这三个要素的作用是减少模型回答的不确定性。角色限定视角任务限定目标约束限定输出边界。缺少约束时模型容易把简单问题扩展成长篇大论。3.2 用 Python 封装模型调用在项目目录下创建 chat.pyimport os from dotenv import load_dotenv from openai import OpenAI load_dotenv() BASE_URL os.getenv(BASE_URL, http://localhost:11434/v1) API_KEY os.getenv(API_KEY, ollama) MODEL os.getenv(MODEL, qwen2.5:7b) client OpenAI(base_urlBASE_URL, api_keyAPI_KEY) SYSTEM_PROMPT ( 你是一名技术运维助手。回答问题时优先给出可执行的排查步骤。 要求回答简洁不超过 5 步如果信息不足直接说明缺少什么信息。 不要编造日志关键字和系统命令。 ) def chat_once(user_input: str) - str: response client.chat.completions.create( modelMODEL, messages[ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_input}, ], temperature0.3, max_tokens1024, ) return response.choices[0].message.content if __name__ __main__: question input(请输入问题) answer chat_once(question) print(answer)这里的关键点是 base_url 指向 Ollama 的兼容接口。api_key 在本地 Ollama 场景下不会真正校验可以随便填一个占位值。如果切换到云模型只需要把 .env 里的 BASE_URL、API_KEY、MODEL 换成云服务商的信息。temperature 设置为 0.3是为了让回答偏稳定。如果任务需要创意比如生成文案可以调高到 0.7 以上如果是技术问答、数据抽取建议保持较低值。3.3 流式输出与异常处理命令行演示看不出流式输出的重要性但网页聊天和智能客服场景中流式输出能让用户第一时间看到模型在响应避免等待焦虑。把 chat.py 扩展成流式版本def chat_stream(user_input: str): stream client.chat.completions.create( modelMODEL, messages[ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_input}, ], temperature0.3, max_tokens1024, streamTrue, ) for chunk in stream: delta chunk.choices[0].delta.content if delta: print(delta, end, flushTrue) print() return 流式模式还有一个好处如果模型响应时间很长前端可以先展示已生成的部分减少超时感知。生产环境还需要处理超时和重试避免一次网络抖动让整个请求失败。3.4 运行验证与常见坑运行下面的命令python chat.py输入“服务器 502 应该怎么排查”正常应该得到与排查步骤相关的回答。这个阶段最常见的几个问题问题现象常见原因处理方法连接被拒绝Ollama 服务未启动执行ollama serve模型不存在模型名称拼错用ollama list确认回答太长没有设置 max_tokens 或约束调低 max_tokens强化 prompt输出不稳定temperature 过高技术问答建议 0.3 以下内存不足模型超出机器配置换更小模型或量化版本到这里最小问答链路已经跑通。接下来要解决一个更关键的问题模型不知道内部资料怎么办。4. 接入 RAG让模型回答不再依赖训练截止时间大模型的训练数据有时间边界也不会包含企业内部的私有文档。直接问“我们团队用的配置管理平台默认端口是多少”模型大概率会编造一个看似合理的答案。解决这个问题的主流方案是 RAG即检索增强生成。4.1 为什么直接问大模型会“一本正经胡说”模型生成回答时是基于语言概率逐字生成并不会像数据库那样去查询知识。当训练数据里没有相关内容时模型会用看起来合理的模式“补全”答案。这就是 AI 幻觉的常见来源。RAG 的思路很直接在模型回答之前先从知识库里检索相关资料把资料拼进提示词再让模型基于资料回答。这样模型不需要“记得”内部文档只需要理解并总结检索到的内容。4.2 RAG 的四个环节RAG 至少包含四个环节文档切分把长文档切成适合向量化的片段。向量化把文本片段转换为向量存入向量库。检索根据用户问题找回最相关的片段。拼装把检索结果和问题一起拼成新的提示词。文档切分如果做得不好直接决定检索效果。切分太长向量包含太多无关内容切分太短语义不完整。常见做法是设置固定长度并增加重叠区域。def split_text(text: str, chunk_size: int 300, overlap: int 50) - list[str]: chunks [] step chunk_size - overlap for i in range(0, len(text), step): chunks.append(text[i:i chunk_size]) return chunksoverlap 的作用是保留前后文连接处的语义。比如一个句子被拦腰切断重叠区域能减少信息丢失。4.3 向量库存入与检索这里使用 Chroma 作为向量库。把文档读入、切分、写入集合然后实现检索函数。import chromadb from chromadb.config import Settings client chromadb.PersistentClient(path./chroma_data) collection client.get_or_create_collection(docs) def index_docs(doc_id: str, text: str, source: str): chunks split_text(text) collection.add( ids[f{doc_id}_{i} for i in range(len(chunks))], documentschunks, metadatas[{source: source} for _ in chunks], ) def search(query: str, top_k: int 3): results collection.query(query_texts[query], n_resultstop_k) return results[documents][0]将检索结果拼入提示词后让模型只依据资料回答def rag_answer(question: str) - str: docs search(question) context \n.join(docs) prompt ( 你是一个知识库问答助手。请只根据下面的资料回答问题。\n 如果资料中没有相关信息请直接回答资料中没有找到相关内容。\n\n 资料\n f{context}\n\n f问题{question}\n ) return chat_once(prompt)这段代码解决了两件事一是限制模型的回答范围二是给模型提供回答依据。资料不足时模型被明确要求拒答而不是编造。4.4 参数效果与验证方法验证 RAG 效果不能只看一两个问题。建议准备一组问题逐条检查问题类型期望结果如果失败先查哪里文档中有明确答案回答应包括资料中的关键信息检索是否命中了正确片段文档中没有答案模型应该拒答prompt 是否明确要求拒答多个文档相关回答应能综合多个片段top_k 是否太小问题表述模糊回答应先确认意图是否有提示词要求澄清常见参数调整方向chunk_size 过大导致检索不精准适当调小。top_k 过小导致信息不足适当调大。检索结果不相关优先检查切分方式和嵌入模型。回答了资料之外的内容强化 prompt 中的“只根据资料回答”。RAG 只是外部记忆的一种形式。业务复杂到一定程度还需要让模型去调用工具这时就进入 Agent 阶段。5. Agent 化让模型完成多步任务问答应用只能生成文本处理不了真实业务。比如用户问“帮我把所有状态为 failed 的任务统计一下”模型不能直接操作数据库也不能调用监控接口。让模型通过工具完成这类任务就是 Agent 化。5.1 Agent 解决什么问题Agent 的核心是把“生成文本”扩展成“执行任务”。模型负责理解用户意图、拆解步骤、决定调用哪个工具应用程序负责真正执行工具并返回结果。一个典型流程用户提出任务。模型返回需要调用的工具名和参数。程序执行工具拿到结果。模型根据工具结果生成最终回答。这个循环可能执行多次直到任务完成。5.2 定义工具与 Function CallingOpenAI 风格的工具定义是一个 JSON 数组。下面定义一个查询服务器状态的工具tools [ { type: function, function: { name: get_server_status, description: 查询服务器的运行状态返回 CPU、内存和进程状态, parameters: { type: object, properties: { host: { type: string, description: 主机地址例如 10.0.0.5 } }, required: [host] } } } ]关键点是 tool 的 description 要足够清晰。模型依赖它判断“什么时候该用这个工具”描述越模糊选错工具的概率越高。模型本身不会执行这个工具它只会返回一个 tool_calls 结构里面包含函数名和从用户问题中抽取的参数。真正执行需要在应用层完成。5.3 完整示例查询服务器状态先实现一个模拟执行函数然后实现 Agent 主循环def get_server_status(host: str) - str: # 这里是真实场景中调用监控接口的入口 return f{host} 当前状态正常CPU 使用率 32%内存使用率 58% def run_agent(user_input: str, max_steps: int 5): messages [{role: user, content: user_input}] for step in range(max_steps): response client.chat.completions.create( modelMODEL, messagesmessages, toolstools, tool_choiceauto, ) message response.choices[0].message messages.append(message) if not message.tool_calls: return message.content for call in message.tool_calls: fn_name call.function.name args json.loads(call.function.arguments) if fn_name get_server_status: result get_server_status(args[host]) else: result f未知工具{fn_name} messages.append({ role: tool, tool_call_id: call.id, content: str(result), }) return 已达最大执行步数任务未完成。这里有一个容易忽略的点每次把模型的输出追加到 messages 后再追加工具结果。如果不按这种顺序组装模型会失去上下文无法把工具结果和用户问题关联起来。max_steps 是保护性参数防止模型陷入无限循环。真实业务中循环次数过多通常意味着工具定义有问题或者用户的请求过于发散。5.4 常见失败模式Agent 调试比普通问答更复杂因为问题可能出在模型、工具、参数解析或循环控制任意一环。失败现象可能原因处理建议模型不返回工具调用工具描述不清晰或模型不支持检查模型是否支持 Function Calling参数解析失败模型返回的 JSON 格式不合法在抛出异常前先记录原始参数反复调用同一个工具没有结果判断循环条件失效增加步骤上限并记录完整调用链工具执行异常没有捕获工具代码异常工具执行包 try/except返回可读错误最终回答丢失后处理逻辑误删了模型输出保留原始响应先落日志再处理排查 Agent 问题时最有效的动作是打印每一步的 messages 结构。看清楚模型看到了什么、工具返回了什么问题通常很快能定位。6. 本地模型部署与 GPU 使用很多团队看完原型后会问同一个问题模型能不能部署在我们自己机器上数据不出内网。如果能成本怎么算性能如何验证。这一节聚焦本地模型部署链路。6.1 为什么本地部署本地部署的主要动力是数据安全。业务日志、用户隐私、内部文档一旦发送到外部模型服务就面临数据外传风险。另一个原因是成本结构高频、固定模式的调用长期按 token 付费可能比购买硬件更贵。代价也很明显需要维护模型版本、处理硬件驱动、监控资源占用还要在模型效果和硬件成本之间做取舍。6.2 Ollama 部署流程拉取、启动、验证Ollama 是目前本地部署最省事的工具之一。它的价值在于把模型下载、加载、服务暴露统一管理。ollama pull qwen2.5:7b ollama serve启动后验证模型是否可用ollama list ollama ps curl http://localhost:11434/api/chat -d { model: qwen2.5:7b, messages: [{role: user, content: 你好}] }curl 命令能返回内容说明服务链路正常。ollama ps可以查看当前加载了哪些模型以及模型是否使用 GPU。6.3 让 Ollama 使用 GPU 的检查路径本地模型最大的性能瓶颈通常在显存和内存带宽。如果模型没有被加载到 GPU推理速度会大幅下降。检查方式按顺序执行ollama ps观察 PROCESSOR 列。如果显示100% GPU说明模型已经加载到 GPU。如果显示100% CPU说明没有使用 GPU需要继续排查。第二层检查是硬件状态。NVIDIA 平台执行nvidia-smi确认程序进程是否占用显存。AMD 平台需要确认驱动是否被 Ollama 支持不同操作系统的支持情况差异很大。第三层检查是模型和显存是否匹配。7B 参数模型的量化版本通常需要 4GB 到 8GB 显存如果显存不足Ollama 会部分加载到 CPU性能下降但不会报错。检查项命令或位置预期模型是否使用 GPUollama psPROCESSOR 列包含 GPUNVIDIA 显存占用nvidia-smi能看到 ollama 进程模型是否过大查看模型文件大小与机器显存容量对比服务是否正常ollama list能看到模型列表AMD 平台例如 Ryzen AI 9 HX 370 这类集成了 NPU 的处理器情况更复杂。Ollama 对 NPU 的支持、ROCm 驱动的兼容性都在持续变化。最稳妥的方式是先在ollama ps看实际加载情况再去官方文档确认当前版本支持的硬件列表不要凭旧教程直接改环境变量。6.4 生产部署还需要什么把 Ollama 装好只是本地部署的第一步。进入生产环境后还需要补齐以下内容并发控制多个用户同时请求时需要限流和排队避免显存溢出。模型版本管理模型文件要记录版本升级后可以快速回滚。配置外置模型路径、端口、并发数不要写死在代码里。指标监控记录请求耗时、token 消耗、GPU 利用率、显存占用。高可用单机 Ollama 不是高可用架构关键业务需要多副本或负载均衡。本地部署不是终点而是把模型纳入正式运维体系的开始。7. 幻觉、评估与排错上线前必须解决的问题AI 应用上线前最不能跳过的一步是评测。没有评测优化就失去了方向没有评测幻觉问题只会一次次在用户面前暴露。7.1 幻觉出现的原因幻觉不是“概率低到可以忽略”的边角问题而是生成式模型的结构性特征。常见触发场景包括知识库里没有相关内容但模型没有拒答。用户问题有误导性模型顺着错误前提回答。提示词没有限制回答范围模型自由发挥。检索回来的是无关内容模型强行总结。模型被追问时倾向于给一个看似完整的答案。理解触发场景后幻觉治理思路就清楚了要么让模型必须引用资料要么在资料不足时明确拒答要么通过评测发现高频问题并针对性调整。7.2 建一个最小评测集评测集不需要一开始就很大但必须覆盖典型场景。建议至少准备 20 到 50 个问题包括四类类型示例观察指标知识库可回答“某接口默认超时时间是多少”是否引用正确片段知识库不可回答“某未上线功能的用法”是否拒答复杂问题“结合 A 文档和 B 文档说明方案”是否准确综合信息边界问题“系统负责人是谁”是否不编造人名可以用 JSON 形式维护评测集[ { question: 服务启动失败时应该先查哪些日志, expect_source: troubleshooting.md, expect_type: answerable }, { question: 尚未发布的功能怎么开启, expect_source: null, expect_type: unanswerable } ]每次修改提示词或检索逻辑后跑一遍同一套评测集对比回答质量的变化。没有评测集的优化只能叫碰运气。7.3 根据评测结果调整评测完之后根据问题类型做针对性调整回答不准确但检索到了正确资料大概率是提示词没有强制要求“只根据资料回答”或者 top_k 太小导致关键信息被裁掉。回答包含资料之外的内容需要加强约束要求模型在引用资料时标出来源片段。本应拒答却编造需要把“资料不足必须拒答”改为系统级指令并在评测集里持续检查。检索结果与问题无关问题出在嵌入模型、切分方式或文档本身的质量。这里有一个重要判断不是所有质量问题都该靠改提示词解决。如果检索结果本身就是错的提示词写得再严也无济于事。先查检索再调提示词顺序不能反。7.4 日志与可观测性AI 应用出问题时最怕的是没有日志。普通接口可以靠报错堆栈定位AI 应用的错误却经常表现为“回答不对”没有异常也没有报错。因此生产环境至少记录以下信息用户输入。检索到的文档片段及来源。最终拼装后的提示词。模型输出。推理耗时和 token 数量。超时、重试、拒答等事件。建议为每次请求生成一个 trace id把用户问题、检索结果、模型输出串在同一条日志链路里。这样用户反馈“上次回答不对”时才能快速定位当时发生了什么。8. 面对 AI 人才争夺的工程实践建议最后一个部分回归到人才竞争本身。奖金、岗位、热搜词都在变化真正有价值的是形成一套属于自己的工程方法论。8.1 掌握一条能独立完成的交付链路一个合格的 AI 工程师应该能独立完成从需求到上线的完整链路而不是只负责其中一段。建议自测以下问题一个需求进来能不能判断它适合用提示词解决还是需要 RAG还是需要 Agent能不能写出可维护的模型调用层切换模型后端时只改配置有没有一套评测集可以量化回答质量模型回答变差时能不能通过日志和评测定位到是提示词、检索还是模型本身的问题部署时能不能处理并发、限流、监控和回滚这些问题覆盖了前面 7 个章节的内容。如果都能给出明确答案说明已经具备独立交付 AI 应用的能力。8.2 建立个人项目库面试和团队协作中最能体现能力的不是“我用过某模型”而是“我做过哪些项目遇到什么问题怎么解决的”。建议做两到三个有差异性的项目一个基于内部文档的 RAG 问答重点讲检索效果和数据准备。一个有真实工具调用的 Agent重点讲循环控制、错误处理和成本控制。一个本地模型部署项目重点讲 GPU、显存、并发和性能验证。每个项目都保留评测数据、关键日志和复盘记录。讲清楚“哪里失败过、为什么失败、怎么改的”比展示一堆能运行的 demo 更有说服力。8.3 在团队中推动工程化个人能力之外还要有推动工程化的意识。很多 AI 项目失败不是模型不够好而是工程规范缺失。可以在团队里先做这几件事把提示词纳入版本管理每次修改配套说明。建立固定的评测集提示词和检索逻辑变更时必须跑回归。模型服务接入统一监控至少记录耗时、token、错误率。发布前走一次“幻觉检查”针对高频问题进行专项验证。这些动作不需要花费太多成本但能把一个“能跑的 demo”变成“可维护的产品”。8.4 可持续的学习节奏AI 领域变化很快但底层方法相对稳定。提示词工程、RAG、Agent、模型部署、评测体系这些关键词不会因为某个新模型出现就失效。建议保持以下节奏每季度完整做一个新项目而不是只刷教程。读一个开源项目的源码尤其是调用封装、评测、部署部分。跟踪模型发布说明重点关注上下文长度、工具调用、量化支持等能力变化。把踩过的坑整理成自己的排查手册比任何收藏夹都有用。AI 人才争夺最终会回归到交付能力。对开发者来说最重要的不是记住某个模型的名字而是形成一套方法如何评估任务是否适合大模型如何让模型稳定输出如何用检索和工具补齐模型短板如何通过评测发现质量问题如何把原型变成可运维的系统。沿着这条链路练下去市场行情无论如何变化这些能力都不会贬值。
返回列表