W4 教程:整理骨架 + 第一次接触 —— 从"我学过"到"我有东西"
本周交付物:① 一个别人能直接用的骨架仓库;② 一次和 AI 团队负责人的对话。
验收线(计划表原文):骨架能三行命令跑起来;完成第一次接触,知道他们在做什么场景。
本周的重点不在代码。代码只是你敲门时手里拿的东西。
0. 为什么 W4 要停一下
前三周你写了 20 个类,每个都能单独跑。现在有人问你:“你做过什么?”
你的回答会是:“我写了 LlmClient,还写了 ToolAgent,还有 W3Probe……”——这是一份清单,不是一份作品。
差别在哪:
| 清单 | 作品 |
|---|---|
| “我实现了带超时重试的模型调用” | “这个仓库,java -jar一行跑起来,8 种故障注入全通过” |
| “我做了工具调用” | “25 条真实售后问题,工具选择准确率 96%,参数零编造” |
| 对方要相信你 | 对方可以自己验证 |
W4 做的事就是:把清单变成作品,然后带着作品去敲一次门。
1. 骨架的第一个问题:别人跑不起来
先做个实验。把ecom-agent-lab拷给一个同事(或者你自己换个目录),让他跑起来。他会遇到什么?
我实测了一遍,会遇到这些:
| 障碍 | 他的反应 |
|---|---|
| 不知道从哪个类开始跑(有 20 个 main) | “我该跑哪个?” |
| 不知道要设哪些环境变量 | IllegalStateException: 环境变量 LLM_BASE_URL 未设置 |
mvn -q compile之后不知道怎么执行 | 卡住 |
Git Bash 里java -cp路径被转换,ClassNotFoundException | “是不是你代码有 bug?” |
| 输出全是乱码(Windows GBK) | “跑起来了但看不懂” |
| 没有网关额度 | “我试不了” |
这六条里没有一条是代码逻辑问题,但每一条都会让他放弃。
骨架的第一要务不是功能全,是别人能跑起来。所以 W4 的第一步是解决这六条。
解决方式:一个入口 + 一个自检 + 一个 jar
① 统一入口LabMain
W1–W3 每个实验一个 main,学习时清楚,交付时是灾难。骨架只能有一个门:
bashrun.sh config# 打印配置bashrun.sh selftest# 零成本自检bashrun.sh chat 你好bashrun.sh repl# 交互模式② 零成本自检selftest
这是骨架里最重要的一个命令,因为它区分了两件事:
- 骨架能跑—— 配置解析、参数校验、工具执行,不碰网络
- 模型能连—— 依赖网关、额度、网络
混在一起的后果是:出问题时你分不清是"我的代码坏了"还是"网关抽风了"。
selftest的检查顺序按依赖关系排:
[1/3] 配置 → 配置不对,后面全是白搭 [2/3] 参数校验 → 校验层坏了,工具执行的结果不可信 [3/3] 工具执行 → 依赖上面两个都对任何一步失败就停(其实代码里是继续跑完再汇总,便于一次看到所有问题),但报告里明确告诉你哪层坏了。
实测输出:
=== 骨架自检(零成本,不调模型)=== [1/3] 配置 [PASS] 模型=fake 网关=http://127.0.0.1:18083/v1 连接超时=3000ms 读超时=30000ms 重试=3次 工具轮次上限=5 [2/3] 参数校验 [PASS] 合法订单号通过 [PASS] 非法订单号被拦 [PASS] 越权字段被拦 [3/3] 工具执行 [PASS] 查订单返回内容 [PASS] 不存在的订单明确提示 [PASS] 未发货不编造物流 [PASS] 政策按日期过滤 [PASS] 工具 schema 齐全 自检全部通过。骨架可用。③ 一个能独立运行的 jar
mvn-q-Pshadepackage-DskipTestsjava-jartarget/ecom-agent-lab-0.1.0-SNAPSHOT.jar selftest7.1MB,含全部依赖。对方只要有 JDK 17+,不需要 Maven、不需要懂 classpath。
我实测过:把 jar 拷到/tmp,在完全不同的目录下单独运行,自检通过。这一步很关键——它的意思是"这东西不依赖我的环境"。
去和团队聊的时候,带一个 U 盘不如带一条命令。你能当场
java -jar跑给他们看,比讲十分钟架构有用。
2. 配置收拢:AgentConfig
W1–W3 的每个类都在自己读环境变量。想知道"这个服务超时多少秒",得翻五个文件。
AgentConfig把所有可调参数收到一处,并且带启动自检。
自检拦住什么
不是所有配置错误都能靠"跑一下看看"发现。有些错误会让程序跑起来但结果微妙地不对,这种最害人。
AgentConfig.selfCheck()拦四类:
publicvoidselfCheck(){if(!baseUrl.startsWith("http")){thrownewIllegalStateException("LLM_BASE_URL 必须以 http 开头,当前:"+baseUrl);}if(readTimeout.toSeconds()<5){thrownewIllegalStateException("LLM_READ_TIMEOUT_MS 太短("+readTimeout.toMillis()+"ms)。"+"模型响应常见 3~30 秒,低于 5 秒会把正常请求当故障重试,白花钱。");}if(connectTimeout.compareTo(readTimeout)>0){thrownewIllegalStateException("连接超时不应大于读超时");}if(maxRounds<1||maxRounds>20){thrownewIllegalStateException("AGENT_MAX_ROUNDS 必须在 1~20 之间");}}第二条最值得说。读超时设 1 秒,程序不会报错。它会把每一个正常的慢请求当成超时,然后重试 3 次。结果是:
- 成本 × 3
- 延迟 × 3
- 成功率反而下降(正常的请求被重试打乱了)
- 日志里全是 TIMEOUT,你会以为网关有问题
这种错误必须在启动时就拦下来,不能等到跑了一周看账单才发现。
实测四种错误配置全部被拦住:
== 1. 缺环境变量 == 配置有问题:环境变量 LLM_BASE_URL 未设置 == 2. 读超时太短 == 配置有问题:LLM_READ_TIMEOUT_MS 太短(1000ms)。模型响应常见 3~30 秒,低于 5 秒会把正常请求当故障重试,白花钱。 == 3. baseUrl 不是 http == 配置有问题:LLM_BASE_URL 必须以 http 开头,当前:ftp://x/v1 == 4. maxRounds 越界 == 配置有问题:AGENT_MAX_ROUNDS 必须在 1~20 之间,当前:99为什么不用 Spring 的 @ConfigurationProperties
因为骨架要能在没有 Spring 的纯命令行里跑。
这不是拒绝 Spring,是顺序问题:先做纯 Java 的、能独立验证的版本,W6 上 Spring Boot 时,这个类变成一个@Configuration,字段几乎不用改。
反过来做(先上框架再想逻辑)的代价是:每次改一行都要重启容器,学习阶段极慢。
3. README:给别人的使用说明,不是给自己的备忘录
骨架的 README 和普通项目的 README 要求不同。普通项目 README 写给"要改代码的人",骨架 README 写给**“只想用、不想读代码的人”**。
所以结构是反过来的:先用,再说原理。
ecom-agent-lab/README.md的章节顺序:
- 三行命令跑起来—— 最前面,不要任何前置知识
- 没有网关额度怎么办—— 直接给假网关方案
- 命令表—— 每个命令要不要连网关
- 配置项表—— 必需/可选/默认值
- 代码结构—— 才到这里才讲代码
- 已知取舍表—— 每一条都写"选了什么/为什么/什么时候该改"
- 坑—— 8 条已踩的
- 下一步
第 6 项是最容易被忽略、但最能建立信任的部分。
看这条:
| 取舍 | 选了什么 | 为什么 | 什么时候该改 |
|---|---|---|---|
| 工具返回值格式 | 人类可读文本 | 模型利用率高、省 token、错误信息更易懂 | W6 需要抽结构化字段时改 JSON |
一个愿意写"我知道这里有个取舍,我选了 A,理由是 B,将来 C 情况该改"的人,比一个声称"我的方案没问题"的人可信得多。
这也是你面试时最有用的材料。面试官问"你觉得你这个设计有什么问题",大部分人答不出来,因为他们的代码里没有痕迹表明他们想过。你的 README 里有一整张表。
4. Trip 记录:把踩过的坑变成文档
W4 的 README 里有 8 条坑,其中本轮新增的 3 条都很有代表性:
坑 6:mvn exec:java在 Windows 下中文乱码
我一开始以为是程序问题,试了-Dfile.encoding=UTF-8、在 pom 里配exec-maven-plugin的systemProperties,都没用。
最后发现:直接在命令行java -Dfile.encoding=UTF-8 -cp ...是完全正常的,只有经过mvn exec:java才乱码。原因是 exec 插件自己管理输出流,-Dfile.encoding管不到它。
结论:不要为了修一个工具链的显示问题去改程序。换一条执行路径(run.sh或java -jar)就解决了。
坑 7:Git Bash 下 classpath 的 Windows 路径必须转换
# 错的:java 会去找 /c/Users/... 这种 POSIX 路径,找不到java-cp"$(pwd)/target/classes;$CP"...# 对的java-cp"$(cygpath -w "$(pwd)/target/classes");$CP"...这个坑我在 W1 就踩过,W4 写run.sh时又踩了一次。同一个坑踩两次,说明它该被写成脚本,而不是记在脑子里。
坑 8:mvn -o离线模式会因插件依赖未下载而失败
mvn -o compile可以(编译插件早就下好了),但mvn -o exec:java不行。日常编译用-o加速是对的,用 exec/shade 插件时去掉。
5. 本周真正的重头戏:第一次接触
代码部分到这里就完了。下面是 W4 里价值更高的部分。
计划表写的是:“找 AI 团队负责人聊一次天(只问不推销)”。
为什么是"只问不推销"
因为你现在还没有资格推销。
推销失败的代价是不可逆的:你只有一次"第一印象"。如果第一次接触就是"我很想加入你们,我会 Java 会 LangChain4j",对方的分类是"又一个想转岗的",之后你再说什么都要先翻过这个标签。
而"只问不推销"的收益是复利的:你被归到"那个认真研究过我们场景的工程师",第二次接触时你的话会被更认真地听。
W4 的窗口只有 3–6 个月(团队组建期),你输不起一次错误的自我介绍。
你手里有什么
到 W4 为止,你手上有三样东西,都是可验证的:
- 一个能
java -jar跑起来的骨架—— 带两层超时、分类重试、参数强校验 - 一张成本表—— W1 你实测了 20 条售后问题,知道输入/输出 token 比例是 19:1,知道 P95 延迟约 10 秒
- 一份故障演练记录—— 8 种故障注入全通过,400/401 确认零重试
这三样东西的价值不在于"多厉害",而在于它们是新的 AI 团队正在缺的东西。
刚成立的 AI 团队通常处于这个状态:POC 跑得很嗨,但代码里没有超时、没有重试、没有脱敏。他们最缺的不是"更聪明的 prompt",是能把 demo 变成服务的工程底子。
你恰好有 3–5 年这个底子。这就是你唯一但足够强的差异化。
怎么开口
不要发一段长消息。长消息的默认结局是被已读不回。
最好的是:一个具体的问题 + 一个可以直接跑的东西。
参考话术(自己改,不要照抄):
X 老师,我是 XX 部门的后端,做售后这块三四年了。
最近在看 LLM 调用这块,做了个小东西:把模型调用包成带两层超时和分类重试的客户端,还做了个本地故障网关,能注入 429/超时/断连来验证重试逻辑对不对。代码在这(附链接/jar),
java -jar xxx.jar selftest就能跑。想请教一个问题:咱们现在接的是哪个模型网关?我这边写的时候发现网关对
tools字段的支持差别挺大,有的接受但不返回 tool_calls,想确认一下我们这边是哪种,以免我后面的实现方向跑偏。不方便的话也没关系,打扰了。
这段话做了四件事:
| 做了什么 | 为什么 |
|---|---|
| 先说身份 + 业务年限 | 让对方 3 秒内知道"你是内部人,不是外部推销" |
| 给一个可运行的东西 | 从"我说我会"变成"你可以验证" |
| 问一个具体的技术问题 | 具体问题才有具体回答,泛问题只能得到"加油" |
| 说"不方便也没关系" | 给对方退路,降低回复成本 |
最关键的是第三个。“咱们的网关对 tools 字段支持怎么样"这个问题,只有真正动过手的人才问得出来。它同时传递了"我做过"和"我需要你的信息”,而后者让对方有参与感。
要问清的三件事
计划表第 10 节列了"新团队健康检查"的三个问题。第一次接触时不要一次问完,那像面试官。挑一个问,剩下的靠后续接触慢慢了解。
但你自己心里要有数,这三个问题的答案是判断"这个团队值不值得去"的依据:
| 问题 | 想听到的 | 红旗 |
|---|---|---|
| 你们第一个要落地的业务场景是什么? | 具体的、有业务方、有时间的(“售后工单分类,下个月灰度”) | “还在探索”、“先做通用能力” |
| 现在跑到哪一步了? | 有具体的卡点(“prompt 效果不稳定”、“没有评测集”) | 只能说"进展顺利" |
| 模型是怎么接的?有网关吗? | 有统一网关、有成本核算 | “各自申请 API key 自己调” |
第三条对你最直接——它决定 W3 之后你走哪条路。但它同时也是团队成熟度的信号:一个连模型调用都没收拢的团队,还在很早期,机会大但风险也大(计划表第 574 行的风险 4)。
三句话不要说
“我很想转到 AI 方向,希望有机会。”—— 这是求职话术,会触发防御“我最近在学 LangChain4j,学了 W1 到 W4。”—— 对方不关心你的学习进度“你们团队还招人吗?”—— 第一次就问编制,把关系直接变成交易
接触完之后必须做的一件事
当天写下三条:
- 他们第一个要落地的场景是什么(原话)
- 他们现在最卡的地方是什么
- 我的方向要不要调
第三条最重要。计划表第 590 行的风险是:“自己闭门造了一个通用智能助手,内部演示时团队说’我们的场景不一样’”。
早改成本低。W4 改变方向,代价是重写几个工具的假数据;W16 才发现,代价是一个月。
6. 本周自测清单
骨架部分
cd教程/W1-W4/ecom-agent-lab# 1. 编译mvn-qcompile# 2. 零成本自检exportLLM_BASE_URL="http://127.0.0.1:18083/v1"exportLLM_API_KEY="fake-key"exportLLM_MODEL="fake-tool-model"bashrun.sh selftest- 输出
自检全部通过。骨架可用。,9 项全 PASS bash run.sh config能打印完整配置(不含密钥)
# 3. 打 jar 并独立运行(验证"别人拿到能用")mvn-q-Pshadepackage-DskipTestscptarget/ecom-agent-lab-0.1.0-SNAPSHOT.jar /tmp/agent.jarcd/tmp&&java-jaragent.jar selftest- 在别的目录下运行也通过(证明不依赖你的环境)
- jar 大小约 7MB
# 4. 配置自检真的能拦错cd"你的工程目录"LLM_BASE_URL="http://x/v1"LLM_API_KEY=kLLM_MODEL=mLLM_READ_TIMEOUT_MS=1000bashrun.sh config- 明确报错"读超时太短",而不是默默跑起来
接触部分
- 已经把骨架整理好,README 里"三行命令"部分你自己照着做过一遍
- 已发出第一次接触的消息(发出去就算完成,回不回是对方的事)
- 已写下三条记录:他们的场景 / 他们的卡点 / 我的方向要不要调
如果消息没发出去,W4 就没完成。代码是 W1–W3 就能交付的,W4 唯一新增的不可替代的东西就是那次对话。
7. 检查点 1(W4 末)
计划表的检查点:能独立写出带超时重试的模型调用 + 工具调用 + 一次内部接触?
逐条自检:
| 项 | 自检方式 |
|---|---|
| 带超时重试的模型调用 | 能不看代码说出:为什么要两层超时、框架的 maxRetries 有哪三个问题、什么样的错误不该重试 |
| 工具调用 | 能不看代码说出:一次带工具的问答为什么是 2 次模型调用、messages里必须累加哪两种消息、参数校验为什么要"宽进严出" |
| 一次内部接触 | 已发出消息,并写下三条记录 |
“能不看代码说出来”,是这一项真正的验收标准。
能写出来但讲不清,说明你是抄的;能讲清但写不出来,说明你只是看懂了教程。两者都不算过。
8. 三个待核实项
团队那边对"内部转岗"有没有硬性流程(比如必须先干满 X 个月、必须原部门放人)。核实方式:问 HR 或你现在的 leader(问法:“我想了解一下公司内部的岗位流动流程”,这是正常问题,不会引起警觉)。
你们部门对"员工做 AI 相关探索"是什么态度。有的公司鼓励,有的认为是不务正业。核实方式:看有没有内部技术分享机制;问一次你的直属 leader 对 AI 的看法——如果他积极,你可以更 openly 地做;如果他冷淡,W4 的接触就要低调,不要在公司群里公开说。
如果网关不支持 tools,团队是怎么解决的。这个问题在第一次接触时问出来,答案会直接告诉你他们是"务实派"还是"理想派"。核实方式:就问。
9. 本周小结
你现在有:
LabMain—— 统一入口,四个子命令AgentConfig—— 配置唯一来源 + 启动自检(拦 4 类配置错误)run.sh—— 不依赖 Maven 的启动器(解决 Windows 编码与路径问题)pom.xml的 shade profile —— 一个 7MB 的独立 jarREADME.md—— 含"已知取舍表"与 8 条坑- 一次已完成的内部接触 + 三条记录
A 阶段(W1–W4,24 小时)到这里收口。
回头看你四周的路径:
W1 让它跑起来 → 能算出一次调用多少钱 W2 让它不挂 → 8 种故障注入,行为可预期 W3 让它能查 → 工具选择 96%,参数零编造 W4 让别人能用 → 一行命令跑起来 + 一次接触这四步对应的能力,正好是"会写 demo"和"能交付服务"的分界线。
下一阶段(W5–W11,42 小时):
- W5Prompt 工程:把 prompt 从代码里移出去,加版本号,做 A/B
- W6固定工作流:作品 1 开建(售后处理 5 步链)
- W7Routing:5 类意图路由 + 无法归类转人工
- W8状态机 + 有界循环 +第二次接触(给团队交个免费小工具)
- W9错误处理矩阵
- W10电商特有①:钱与风控(工具权限分级)
- W11作品 1 收尾,打 tag,录演示
W5 有一件事要先做:把你 W4 从团队那边了解到的"第一个要落地的场景",和现在这个售后场景对一下。如果对不上,W5 就要调方向——这是你自己在 W4 埋的伏笔,现在去收。
附:文件清单(W4 新增)
ecom-agent-lab/ ├── README.md ← 骨架使用说明(含取舍表 + 8 条坑) ├── run.sh ← 不依赖 Maven 的启动器,解决 Windows 编码/路径问题 ├── pom.xml ← 新增 shade profile:打独立 jar └── src/main/java/com/company/lab/ ├── LabMain.java ← 统一入口:config / selftest / chat / repl └── AgentConfig.java ← 配置唯一来源 + selfCheck(拦 4 类错误)