2016年3月,AlphaGo 与李世石的第四盘棋,第37手落下时,几乎所有讲解围棋的人都说“看不懂”。传统的棋理、定式、经验,在这一步面前全部失效。然而事后回看,正是这一步,让 AlphaGo 彻底掌控了那一盘的局面,也第一次让真实世界看到:AI 不是只会记住人类教给它的答案,它能在没有标准答案的领域里,自己走出一条路来。
近十年过去,Move 37 正在从棋盘上扩散到每一个和“决策”有关的地方。现在的 AI,不再只是下棋,它能写代码、读文档、调接口、分析日志、参与产品设计,甚至在企业的业务流程里独立完成某些环节。它不再是一个演示视频里的“惊叹点”,而是普通开发者每天都会打开的工具,是应用后端的一个模块,是生产环境里的一个服务。
这篇文章想用开发者的视角,把从 Move 37 到今天 AI 工程化落地之间的变化拆开讲清楚。我们会先理解 Move 37 为什么重要,再看它背后的能力如何演变成现在的 AI Agent、RAG、提示词工程,最后落到实践上:一个最小可复用的 Agent 代码、一个检索增强示例、一套可执行的评估方法,以及生产环境里最重要的权限、成本和回滚问题。
1. Move 37 到底意味着什么:AI 第一次走出人类经验
1.1 这步棋为什么让人类棋手震惊
围棋是一个复杂度极高的博弈游戏,历史上人类棋手经过几千年,积累了大量被反复验证的定式和棋理。AlphaGo 和李世石对阵之前,主流观点仍然是“AI 至少还需要十年才能挑战顶尖棋手”。因为围棋的可能局面数量远超国际象棋,传统的暴力搜索根本不可行。
第 37 手是一步看起来“不合常理”的下法。它放弃了局部最明显的争夺,转而在更宏观的位置落子。按当时人类棋手的理解,这步棋局部有损失,后续也未必能直接形成进攻。但它真正的价值在于改变了整盘棋的“势”,让 AlphaGo 后续的战略推进变得极其顺畅。
这里面最关键的并不是“AI 赢了”,而是 AI 提出了一种人类经验之外的新解。它证明了一个重要问题:当模型在海量对局中训练到足够充分的程度,它的决策质量有机会超过“由人类经验总结出的最优解”。这就是 Move 37 的真实含义——AI 第一次走出人类经验的边界。
1.2 从技术和机制上理解这步棋
早期围棋程序靠的是人工编写规则和搜索算法,它们无法应对围棋庞大的分支。AlphaGo 的做法完全不同,它用深度卷积神经网络分别学习“当前局面下哪里值得下”和“当前局面谁更有利”,再用蒙特卡洛树搜索把两者结合,让搜索过程只沿着最有希望的路径展开。
这个结构放到今天的 AI 应用里,会发现惊人的相似性:
- 策略网络,相当于现在大模型里的“生成能力”,负责提出候选动作。
- 值网络,相当于“评估能力”,负责判断这个候选动作值不值得继续。
- 蒙特卡洛树搜索,相当于“规划与验证”,让 AI 不止是猜一个答案,而是在多个可能性里推演并选择更稳定的那一条。
当时我们很难想象这套机制能迁移到软件工程里。现在再看,代码补全、AI Agent 的工具调用、RAG 的检索重排,本质上都在做同一件事:先生成多个候选,再评估它们的价值,最后选一个执行。这和 AlphaGo 的下棋逻辑是一脉相承的。
1.3 Move 37 的真正遗产是“决策能力”
很多人把 AlphaGo 的成就归结为“算力强”,这是个误解。计算力只是一个基础条件,真正的突破来自训练方式:让模型自己从数据里总结规律,而不是由人类把规则写死。
Move 37 的遗产,是让整个行业意识到,AI 的核心价值不在于它能记住多少人类知识,而在于它能生成“人类可能不会想到但客观有效”的方案。过去这只能在围棋这样规则封闭的领域实现,因为局面可以清晰评估,输赢有明确标准。而今天,代码的正确性、业务流程的效率、用户转化的提升,正在成为新的“评估函数”。AI 的方案不再需要是人类熟悉的方案,只要最终指标变好,它就是有价值的。
2. 从棋盘到代码:AI 正在成为软件工程的基础设施
2.1 开发者的工作方式已经被重写
过去几年里,AI 在软件工程领域的落地速度,远超大多数人的预期。最早是代码补全工具,在一个函数里自动提示下一行;后来是代码生成,用自然语言写需求,AI 直接给出完整模块;再往后是 AI 代码评审、自动化测试生成、Bug 定位、文档转换、数据库查询优化。
对这些工具,我个人的判断是:它们真正降低的不是“打字成本”,而是“从想法到代码之间的翻译成本”。一个后端开发者,以前要先把需求拆成接口设计、数据库表结构、业务逻辑、异常处理,再逐行实现。现在可以把需求描述清楚,让 AI 生成初版,然后再去审查、修正、补充边界情况。这就意味着,一个工程师能承担的工作范围变大了。
热搜词里出现大量“AI 编程”“Cursor AI 编程”“AI Agent 开发”,这背后并不是炒作,而是真实的工程变化。GitHub Copilot、Cursor 这类工具已经不再只是“高级自动补全”,它们能跨文件理解项目结构,能根据 issue 修改代码,能在测试失败后自己调整实现。如果你还没把这些工具纳入日常开发流程,那在第一层就已经落后了。
2.2 软件工程师的核心竞争力正在迁移
如果 AI 能完成越来越多“写代码”的工作,那工程师的价值在哪里?我的答案是:定义问题和判断结果的能力。
过去,写代码本身就是核心技能,因为从需求到实现的路径很长,需要大量专业知识。现在,AI 承担了实现层的很大一部分,人类的价值逐渐集中在:
- 能不能把模糊的业务需求,拆解成 AI 能理解的清晰任务。
- 能不能判断 AI 生成的代码是否满足性能和安全要求。
- 能不能设计一套验证机制,在 AI 输出可能出错的前提下,保证系统依然可靠。
这和 AlphaGo 的“教练”角色很像。教练不需要亲自落子,但他要能读懂 AI 的意图,判断哪一步走得好,哪一步有风险,然后在战略层面做决策。
2.3 对团队协作方式的直接影响
AI 进入工程流程后,最明显的变化是:代码审查成为更重要的环节。以前审查代码主要是查逻辑错误、风格问题和潜在 Bug,现在还需要审查“这段 AI 生成的代码,有没有引入未预期的依赖、有没有泄露内部逻辑、有没有做足输入校验”。
团队里开始出现新的角色分工。有人专门负责维护提示词模板,有人负责搭建评估集,有人负责 Agent 工具链的权限管控。这些在今天看起来还是少数团队的配置,但会逐步变成软件工程团队的基础设施。
3. AI Agent:从“聊天”到“做事”的关键一步
3.1 什么是 AI Agent
先说结论:AI Agent 是“能够自主执行任务的大模型应用”。它和普通聊天机器人的区别,不在于模型本身,而在于它被赋予的工具和行动边界。
一个聊天机器人只能生成文本,你说一句它回一句。AI Agent 则可以做更多事:查数据库、调接口、发消息、写文件、执行命令,甚至在一个流程里连续做多步操作,直到完成任务。
要拆开看,Agent 通常包含四个部分:
- 大模型:负责理解任务、生成决策。
- 工具集合:包括函数调用、API、数据库查询、文件操作等。
- 记忆:短期记忆保存当前任务上下文,长期记忆保存用户偏好和历史结果。
- 行动循环:不断重复“理解、决策、执行、观察结果、再决策”的过程。
这套结构,和人类处理复杂任务的思路是一致的。你接到一个“把订单报表发到群里”的任务,不会只做一步,而是先查数据,再整理格式,再发送,最后确认是否成功。Agent 就是把这种多步操作自动化。
3.2 从 Chatbot 到 Agent 的差别
很多人以为给聊天机器人加一个插件就是 Agent,这是不准确的。它们的核心差异在“自主程度”。
Chatbot 是一问一答,每一步都由用户驱动。Agent 则有一个目标,可能在执行过程中自己决定先调用哪个工具、如何处理异常、是否需要重试。这个“自主判断”的能力,让 Agent 能完成更复杂的任务,同时也带来了新的风险:你无法完全预测它每一步会做什么。所以生产环境里的 Agent,必须配权限控制、审计日志和人审环节。
3.3 为什么现在 Agent 才被大范围讨论
Agent 的概念其实很早就有了,但过去受限于模型能力,效果不好。最早的做法是用规则引擎写死任务流程,复杂场景几乎无法维护。现在的变化在于大模型拥有了更强的意图理解、推理和工具调用能力,Agent 才真正从一个“玩具”变成“工程组件”。
热搜词里“AI Agent开发”持续出现,背后是真实需求:企业级的 AI 应用,不满足于“问一句答一句”,而是要解决实际业务问题。比如自动化运维、智能客服工单处理、代码仓库管理、数据分析报告生成,这些任务天然是多步骤的,只有 Agent 形态才能完成。
4. AI 应用开发真正要过的关:评估与治理
4.1 最大的问题不是“模型不够聪明”,而是“不知道好不好用”
开发 AI 应用时,很多人第一个想法是“找最强的模型”。但实际工程里,最大的瓶颈往往不是模型能力,而是缺乏一套可靠的评估机制。
传统软件工程里,功能对不对,可以用测试用例判断。AI 应用不一样,同一个问题,模型今天答得好,明天升级版本后可能就答偏了;同一个模型,换一种提问方式,结果差异也很大。如果没有评估集,你根本不知道一次改动是变好了还是变坏了。
4.2 评估集怎么建
一个合格的 AI 应用评估集,至少应该覆盖三类样本:
- 典型场景:覆盖 80% 的正常问题,确保基本能力不退化。
- 边界情况:包括空输入、超长输入、含糊问题、多轮对话中的歧义,确保模型不会崩溃。
- 高风险场景:比如涉及删除操作、资金操作、权限变更的对话,确保模型不会给出危险建议。
每一条样本,除了输入,还要有预期结果和质量标准。质量标准不一定是标准答案,也可以是“必须包含哪些关键要素”“是否拒绝执行禁止操作”“回复是否简洁明确”。
4.3 没有评估,就没有迭代
如果团队准备把 AI 应用放到生产环境,我建议从第一天就开始积累评估样本。每次线上用户反馈问题,都可以转成一条回归用例。这样模型版本升级、提示词修改、RAG 召回策略调整,都有了可对照的基准。
另外,不要只看模型自己的回答质量,还要看端到端的效果。比如一个客服 Agent,最终指标是“工单解决率”而不是“回答通顺度”。模型回答得很流畅,但如果没解决用户问题,这个流程就是失败的。
5. 一个可落地的最小 Agent 示例
5.1 核心思路:ReAct 循环
我们用一个最小示例来理解 Agent 的工作方式。它的核心叫 ReAct,也就是“思考 + 行动”的循环:模型先思考当前该做什么,然后调用工具,观察返回值,再决定下一步做什么。循环反复进行,直到模型认为任务已经完成。
下面这个示例,我会用 Python 实现一个极简的 Agent 调度器,它能识别用户问题、选择工具、执行并返回结果。为了防止读者被某个 SDK 绑定,我会把大模型调用封装成一个函数,你可以替换成任何自己使用的模型服务。
5.2 定义工具集与系统提示词
# 文件:react_agent_demo.py import json def search_qa(query: str) -> str: """模拟内部知识检索工具""" doc_db = { "订单超时时间": "订单默认超时时间为30秒,可在 config/order.yaml 中修改。", "发布计划": "v3.0 计划在 2026 年 Q3 发布。", "数据库连接池": "连接池默认上限为20,生产环境建议根据压测结果调整。" } return doc_db.get(query, "未检索到相关知识") def execute_sql(sql: str) -> str: """模拟只读 SQL 查询工具""" if not sql.strip().upper().startswith("SELECT"): return "仅允许执行 SELECT 查询" return "模拟查询完成,返回 42 行结果" TOOLS = { "search_qa": search_qa, "execute_sql": execute_sql, } SYSTEM_PROMPT = """你是一个运维助手。请你根据用户问题,按以下格式输出 JSON: { "thought": "你对当前任务的思考", "action": "要调用的工具名,如果不需要调用工具则填 none", "action_input": "工具的入参", "answer": "如果你认为任务已完成,这里填最终回答;否则留空" } 可用工具:search_qa, execute_sql 注意:json 中只能包含以上字段,不要额外输出文字。"""系统提示词里,我刻意要求模型输出 JSON,这样调度器可以稳定解析结果。这比直接让模型输出自由文本更可靠,也是生产环境里常用的做法:用结构化输出约束模型行为。
5.3 实现大模型调用
为了让读者能真正跑通,我这里使用通用的 HTTP 调用方式,兼容大多数提供 Chat 接口的服务。
# 文件:llm_client.py import os import requests def call_llm(messages, model="gpt-4o-mini"): """ 调用 Chat 兼容接口。 请通过环境变量设置 LLM_API_KEY 和 LLM_BASE_URL。 base_url 示例:https://api.openai.com/v1 """ api_key = os.getenv("LLM_API_KEY") base_url = os.getenv("LLM_BASE_URL", "https://api.openai.com/v1") payload = { "model": model, "messages": messages, "temperature": 0.2, "response_format": {"type": "json_object"} } resp = requests.post( f"{base_url}/chat/completions", headers={"Authorization": f"Bearer {api_key}"}, json=payload, timeout=30 ) resp.raise_for_status() return resp.json()["choices"][0]["message"]["content"]如果你使用的是本地部署模型或国内大模型服务,通常只需要修改环境变量LLM_BASE_URL和LLM_API_KEY,请求格式基本兼容。这里强调一个工程原则:不要把 API Key 硬编码在代码里,一律通过环境变量或配置中心读取。
5.4 实现 Agent 主循环
# 文件:react_agent_demo.py def main(): user_input = "订单模块的超时时间是多少?" messages = [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user_input} ] for step in range(4): content = call_llm(messages) data = json.loads(content) print(f"[Step {step + 1}] 思考:{data.get('thought')}") action = data.get("action", "none") if action != "none": tool_func = TOOLS.get(action) if tool_func: result = tool_func(data.get("action_input", "")) print(f"[Step {step + 1}] 调用 {action},返回:{result}") messages.append({ "role": "user", "content": json.dumps({"tool_result": result}, ensure_ascii=False) }) continue print(f"[完成] {data.get('answer')}") break else: print("[失败] 达到最大循环次数,任务可能未完成") if __name__ == "__main__": main()这个主循环里,有三个值得注意的地方:
第一,设置了最大循环次数。生产环境里,Agent 如果陷入死循环,会浪费大量 token 和接口调用资源,必须设置上限。
第二,把工具返回结果追加到 messages 里,让模型在下一次生成时能看到工具的返回值。这是 ReAct 循环的关键,模型必须“看到结果”才能继续决策。
第三,每一步都打印日志。这在调试阶段非常重要,因为 Agent 出错时,你至少要能看出它是在哪一步做错了决策。
运行方式:
export LLM_API_KEY=你的APIKey export LLM_BASE_URL=https://api.openai.com/v1 python react_agent_demo.py预期结果是:模型先查找search_qa工具,检索“订单超时时间”相关内容,然后输出最终答案。如果失败,优先检查 API Key 是否正确、网络是否能连通模型服务、返回内容是否能被json.loads解析。
6. RAG 与提示词工程:企业落地的主干技术
6.1 为什么大多数企业场景需要 RAG
大模型的训练数据有截止时间,它无法知道你公司内部的接口文档、业务规则、故障记录。如果直接让模型回答内部问题,它大概率会编造答案。RAG(Retrieval-Augmented Generation)就是为了解决这个问题。
RAG 的基本流程是:先把企业文档切分成块,建立索引;用户提问时,先从索引里检索出最相关的文档片段;再把“用户问题 + 文档片段”一起拼进提示词,让模型基于给定资料回答。
这个过程的好处是,不需要重新训练模型,只要更新文档库,模型就能回答新问题。对于绝大多数企业来说,RAG 比微调更实际、成本更低、更新更及时。
6.2 一个简单可复现的 RAG 检索示例
先说明:下面这个示例,我故意没有引入向量数据库,而是用字符级倒排索引做演示,目的是让你看清 RAG 的完整流程。生产环境建议用 Elasticsearch、Milvus 或专门向量数据库。
# 文件:simple_rag.py from typing import List def chunk_text(text: str, size: int = 150, overlap: int = 20) -> List[str]: """按固定字符长度切分文本,保留重叠,避免切断语义。""" chunks = [] start = 0 while start < len(text): end = min(start + size, len(text)) chunks.append(text[start:end]) if end == len(text): break start = end - overlap return chunks def build_char_index(chunks: List[str]): """最简单的字符倒排索引:记录每个字符出现在哪些 chunk 中。""" index = {} for idx, chunk in enumerate(chunks): for ch in set(chunk): index.setdefault(ch, set()).add(idx) return index def retrieve(query: str, index: dict, chunks: List[str], top_k: int = 2) -> List[str]: """根据字符命中数量排序,返回最相关的 top_k 个片段。""" query_chars = set(query) scores = [] for idx, chunk in enumerate(chunks): hit = len(query_chars & index.get(idx, set())) if hit > 0: scores.append((hit, idx)) scores.sort(reverse=True) return [chunks[idx] for _, idx in scores[:top_k]] if __name__ == "__main__": document = ( "订单系统默认超时时间为30秒。用户下单后,如果支付回调在30秒内未到达," "系统会自动将订单标记为超时。超时订单会在后台任务中被关闭,库存会回滚。" "生产环境建议根据压测结果调整超时时间。订单模块的配置位于 config/order.yaml。" ) chunks = chunk_text(document) index = build_char_index(chunks) for c in retrieve("订单超时时间", index, chunks): print(c) print("---")这个示例按字符做索引,对中文没有分词依赖,能跑通流程。它的问题是精度低,同一个字命中次数多但语义可能无关。生产环境替换为向量检索后,整体流程依然一致,只是“召回”这一步的质量更高。
6.3 提示词工程是 RAG 的最后一公里
RAG 检索到文档片段后,如何组织提示词,直接影响回答质量。一个常见的失败模式是:检索结果正确,但模型被无关片段干扰,最后答非所问。所以提示词必须“明确限定信息来源”。
一个推荐的模板:
你是一个技术支持助手。请只根据下面提供的资料回答问题。 如果资料中没有相关信息,请直接回答“资料中未找到相关信息”,不要自己编造。 资料: {retrieved_chunks} 问题:{user_question}同时,我会在提示词里加上稳定性要求:不要重复问题内容,不要输出思考过程,回答控制在 200 字以内。这些细节看起来简单,但在真实场景里,能明显减少“正确但啰嗦”和“自信但错误”的输出。
很多团队一开始把 RAG 的难点放在召回率上,实际排查多了以后会发现,提示词导致的“串味”才是最频繁的问题。检索到的多个片段之间如果有冲突,模型往往会选择后出现的那个,或者把两个片段的内容混在一起。解决方式有两种:一是调整检索数量,减少干扰片段;二是在提示词里明确“如果资料之间存在冲突,请指出冲突并选择证据更充分的那一个”。
7. 生产环境避坑指南:权限、成本、回滚
7.1 AI Agent 的权限设计要遵循最小化原则
AI Agent 能自己做决定,这在带来便利的同时,也带来风险。如果一个 Agent 拥有完整数据库权限,又因为提示词注入被恶意引导,后果不堪设想。
生产环境里,Agent 的工具权限应该做到:
- 任何工具只能使用最小权限,比如数据库查询只读账号,文件操作限定指定目录。
- 危险操作必须有人工审批环节,比如批量删除、资金转账、权限变更。
- 所有工具调用必须写入审计日志,记录调用时间、入参、返回结果。
- 在正式环境操作前,先在小规模测试环境验证,并准备备份和回滚方案。
如果你在开发内部工具,不要觉得“只是内部用就无所谓”,很多安全事故就发生在内部工具上。
7.2 成本控制:Token 是不可忽视的预算维度
AI 应用和传统后端不一样,每次请求都要消耗 token,而 token 是有成本的。Agent 一次任务可能调用模型多次,如果循环失控,费用会快速累积。
常用的控制手段包括:
- 设置单次任务的最大模型调用次数。
- 合理控制上下文长度,不要把所有历史消息都带进请求。
- 缓存高频请求的答案,相同问题直接复用。
- 使用性价比模型处理简单任务,强模型只处理复杂分支。
从运维视角看,AI 应用的监控应该同时关注延迟、可用率和 token 消耗。一个 Agent 任务如果总是需要 10 次模型调用才能完成,即使模型本身很快,整体体验也会变差。
7.3 灰度发布与回滚是硬要求
模型升级、提示词修改、检索策略调整,都会影响最终输出。每次改动都应该先跑一遍评估集,再通过灰度发布逐步放量。灰度期间,需要对比新旧版本的业务指标,比如用户满意度、工单解决率、代码评审通过率,而不是只看模型回答“好不好”。
如果新版本表现不如旧版本,要能一键回滚。这也意味着,模型版本、提示词版本、检索配置都要纳入版本管理,不能只覆盖代码库里的一个文件。
8. 不同角色的开发者,从哪条路径切入 AI
8.1 后端开发者:从接入模型到编写工具
后端开发者最容易上手的路径,是设计 Agent 能调用的工具。工具的本质就是函数,输入是模型生成的参数,输出是结构化结果。这块恰好是后端工程师最擅长的。
建议路径:
- 先写一个简单的 HTTP 接口,供模型调用。
- 再封装一个小型 Agent,串联 2 到 3 个接口。
- 关注权限、日志、重试和超时处理。
8.2 前端开发者:从界面体验到交互创新
前端开发者可以从 AI 交互界面的角度切入。传统的表单交互正在被对话式、流式输出、意图预览等新交互取代。前端要做的是让模型输出在界面上“可理解、可纠错、可操作”。
8.3 算法工程师:从训练模型到建设评估
算法工程师的价值不只是训练模型,更在于建立评估体系。一个 AI 应用团队,最缺的往往是能定义“好”与“坏”的人。算法工程师对数据敏感,做评估集、分析失败样本,是天然适合的切入点。
8.4 测试与运维:从手工检查到自动化守护
测试工程师可以研究 AI 输出断言,为自然语言回答建立自动校验规则。运维工程师可以搭建 AI 应用的可观测体系,把 token 消耗、Agent 执行链路纳入监控。这些方向目前都非常缺人。
如果你使用的是 Java 技术栈,可以关注 Spring AI 这类框架,它把模型调用、向量存储、工具调用封装成统一抽象,降低了集成成本。如果使用 Python,LangChain 和 LlamaIndex 生态同样值得跟进。但我的建议是,不要一开始就扎进框架细节,先把手动调用模型、手动写工具、手动拼提示词这条路走一遍,理解原理后,再用框架提高效率。
9. 写在最后:Move 37 正在以另一种方式重演
Move 37 让我们第一次意识到,AI 给出的方案可以违反人类的直觉,但仍然正确。今天,当你在代码评审时看到 AI 写出的陌生写法,在数据分析时看到模型提出一个不符合经验但指标更好的建议,在 Agent 执行日志里看到一条你认为“不该走”但结果正确的链路,那时的感觉,和 2016 年棋手看到第 37 手时是一样的。
AI 正在从“模仿人类经验”走向“创造超出人类经验的新方案”,而且这个过程已经不再局限于围棋棋盘,而是发生在软件工程的每一个角落。对开发者来说,最需要转变的不是学会某个工具,而是建立一种新的判断体系:当 AI 给出一个你没有想过的答案时,不急着否定它,先去验证它。这恰恰是从 AI 使用者走向 AI 工程师的关键一步。
如果你想真正进入这个领域,我的建议很直接:从今天开始,就选一个你日常工作中重复、枯燥、需要查文档的任务,把它变成一个 Agent 工具。不要等完美的框架,不要等最强的模型,先跑通一个最小闭环。这个过程,就是你自己的 Move 37。