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 --version | 3.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 内容如下:
openai>=1.30.0 chromadb>=0.5.0 python-dotenv>=1.0.1这里使用 openai 库,是因为它已经成为事实上的模型调用标准。Ollama、多家云厂商都提供兼容 OpenAI 风格的接口,写一套代码就可以在多个后端之间切换。
2.4 学习环境与生产环境的差异
学习环境可以把所有东西放在一台机器上,程序能跑通就算成功。生产环境还必须考虑配置外置、鉴权、限流、日志、监控、回滚等事项。
| 关注点 | 学习环境 | 生产环境 |
|---|---|---|
| 模型地址 | 写死在代码里 | 通过环境变量或配置中心读取 |
| API 密钥 | 不涉及或本地测试 | 放入密钥管理服务,不提交仓库 |
| 日志 | 无所谓 | 按 trace id 串联完整请求链路 |
| 并发 | 单用户调试 | 需要限流、排队、自动扩缩容 |
| 异常 | 打印即可 | 需要有重试、降级、告警 |
| 数据 | 随便放 | 需要考虑权限、备份、脱敏 |
后面给出的代码示例主要用于学习环境,但在写法和结构上已经在为生产环境做准备。
3. 从提示词到最小可运行问答应用
先做最小闭环:本地模型已经启动,现在让程序能问答。这个阶段不涉及复杂知识库,只是验证提示词、API 接入和运行链路是否正常。
3.1 提示词的三个基本要素:角色、任务、约束
提示词不是越复杂越好,但至少要包含三个要素。
- 角色:告诉模型以什么身份回答问题,例如“你是一名技术运维助手”。
- 任务:明确模型需要完成什么,例如“根据用户描述给出排查建议”。
- 约束:限定回答风格、范围、长度,例如“回答不超过 200 字”“不要编造日志内容”。
一个稳定的提示词通常会加上示例。下面的 system prompt 用于后续问答应用:
你是一名技术运维助手。回答问题时优先给出可执行的排查步骤。 要求:回答简洁,不超过 5 步;如果信息不足,直接说明缺少什么信息。 不要编造日志关键字和系统命令。这三个要素的作用是减少模型回答的不确定性。角色限定视角,任务限定目标,约束限定输出边界。缺少约束时,模型容易把简单问题扩展成长篇大论。
3.2 用 Python 封装模型调用
在项目目录下创建 chat.py:
import 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_url=BASE_URL, api_key=API_KEY) SYSTEM_PROMPT = ( "你是一名技术运维助手。回答问题时优先给出可执行的排查步骤。" "要求:回答简洁,不超过 5 步;如果信息不足,直接说明缺少什么信息。" "不要编造日志关键字和系统命令。" ) def chat_once(user_input: str) -> str: response = client.chat.completions.create( model=MODEL, messages=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user_input}, ], temperature=0.3, max_tokens=1024, ) 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( model=MODEL, messages=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user_input}, ], temperature=0.3, max_tokens=1024, stream=True, ) for chunk in stream: delta = chunk.choices[0].delta.content if delta: print(delta, end="", flush=True) 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))], documents=chunks, metadatas=[{"source": source} for _ in chunks], ) def search(query: str, top_k: int = 3): results = collection.query(query_texts=[query], n_results=top_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 Calling
OpenAI 风格的工具定义是一个 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( model=MODEL, messages=messages, tools=tools, tool_choice="auto", ) 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,性能下降但不会报错。
| 检查项 | 命令或位置 | 预期 |
|---|---|---|
| 模型是否使用 GPU | ollama ps | PROCESSOR 列包含 GPU |
| NVIDIA 显存占用 | 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 人才争夺最终会回归到交付能力。对开发者来说,最重要的不是记住某个模型的名字,而是形成一套方法:如何评估任务是否适合大模型,如何让模型稳定输出,如何用检索和工具补齐模型短板,如何通过评测发现质量问题,如何把原型变成可运维的系统。沿着这条链路练下去,市场行情无论如何变化,这些能力都不会贬值。