AI Agent从零自主开发文本分类模型:一场全流程实验实录
2026/9/5 19:51:46 网站建设 项目流程

在AI圈子里聊“AI到底能不能自己造AI”,基本每次都会吵成两拨人:一拨觉得这是失控前兆,另一拨认为AI连自己代码该放哪个文件都搞不清楚。我不打算站队,因为这种问题在没有明确操作定义之前根本没有答案。花了一个多星期,我做了个完整实验:让一个带规划和执行能力的AI Agent,从空目录开始,自己完成一个文本分类模型的全部开发流程——需求拆解、环境准备、数据脚本、模型训练、调参迭代,最后产出一个真实可用的模型文件。结果比预想中更有说服力:它不是摆设,是真的做出来了,只是过程远没有传说中那么科幻。

这类实验现在不缺素材,Cursor、AI Agent、AI编程相关的词在这段时间被反复刷屏,但大部分讨论停留在“代码补全多强”“哪家IDE插件好用”这个层面,很少有人把话筒递还给AI本身:给你一个空项目、一个目标、一个能执行命令的环境,你能不能从零造出一个AI应用?这篇文章就把我完整的实验记录、半路翻车的过程、以及我对“AI到底能不能自己造AI”这件事的判断,一次性讲清楚。

1. 先把“造AI”问清楚:这轮实验验证的是哪一层能力

1.1 三种“造AI”的含义差得很远

多数争论其实在定义层面就已经散了。我见过两种最极端的说法:一种是把大模型API接进业务、写几段Prompt、套个企业微信机器人,就宣称“我造了一个AI”;另一种是看到能自动生成代码的Agent,就惊呼“AI已经能自己造自己了”。这两种说法都不算错,但压根不在同一个维度上,吵起来自然各说各话。

我倾向于把“造AI”分成三个层次:

  • 第一种是调用现成大模型API做应用层开发。模型是别人训练好的,你写的只是业务逻辑、编排逻辑、提示词和周边工程。门槛很低,价值也有,但这更像是“用AI”。
  • 第二种是机器学习工程意义上的造AI。从数据清洗开始,设计或选用合适的模型结构,完成训练、验证、调参、评估,最后产出一个可以部署的模型文件。这是算法工程师的日常,算是真正“制造”一个AI模型出来。
  • 第三种是研究型造AI。提出新架构、新训练范式,让模型能力产生质变,比如从CNN到Transformer这种级别的创新。当前没有任何工具能替代人的这种角色。

这篇文章要验证的是第二种。因为自动编程工具目前最有可能替代或者放大的人是“能完成标准建模流水线的工程师”,而不是论文作者。把目标定义到这个层面,实验才有可验证性,不需要动不动就聊到意识、失控这种大词上去。

1.2 热搜里的AI编程/Cursor,和我做的实验不是一回事

最近大家讨论最热闹的,主要是Cursor这类AI编程工具、各种AI Agent框架、还有一堆“AI编程提示词”“AI应用开发”的教程。这些都是真实有用的东西,但是它们大多处于同一个阶段:把大模型当作一个坐在IDE里的结对程序员,你告诉它需求,它补全代码,你负责判断能不能跑、要不要改。

这种模式确实很强,但它有一个隐藏前提——人在闭环里。人类负责拆解需求,人类负责验收结果,人类负责把报错信息粘回去。一旦遇到环境问题、版本问题、逻辑漏洞,真正做决策的还是人。所以我说句实在话:单靠“AI写代码”,不能证明AI能自己造AI,只能证明AI是一个很好的代码生成器。

我做实验的方式不一样。我让AI Agent直接面对一个真实环境,它能执行Linux命令、能读写文件、能运行Python脚本,然后自己判断下一步做什么。如果脚本报错,它自己读报错、自己改、自己重跑,不需要我再传话来传话去。整个系统里,我给它的只有一个目标描述和验收标准。中间过程能不能完成,完全看它自己。这样才有资格回答标题里那个问题。

1.3 这轮实验验收标准是什么样的

为了让结果不被“演示文件”糊弄过去,我事先写死了验收要求:

  • 任务:做一个短信垃圾信息的二分类模型。
  • 环境:Docker容器内,预装Python、PyTorch、scikit-learn、pandas,工作目录里放一份约850条文本的邮件数据集,不加外部网络。
  • 产出:必须有一个训练脚本train.py、一个推理评估脚本evaluate.py、一个模型文件model.pt、一个requirements.txt、一个README.md
  • 指标:在留出的测试集上F1值不得低于0.93,脚本必须能一键复现。

这里最关键的是“不加外部网络”。因为一旦允许联网,很多Agent会直接去HuggingFace拉一个现成模型来微调,那确实很省事,但整个过程的自主性会被数据集、基座模型分享掉一大半。我要看的是,在一个资源受限的环境里,它能不能自己榨出方案来。

至于人工干预,我只做了一件事:把任务书写清楚。剩下所有代码细节我不碰。我允许自己旁观、记录、给环境打补丁,但不允许直接替它改代码。这是整个实验底线的核心。

2. 自主开发Agent的搭建思路:为什么我用LLM当主管、本地环境当手

2.1 Agent的骨架:能思考的循环、能执行的手、能看见反馈的眼睛

先说结论:整个系统写出来也就一百多行核心代码。很多人以为“让AI自主干活”得搞多复杂的框架,其实关键在于把大模型放进一个能执行、能观察、能纠错的环境,而不是单纯地跟它对话。

我搭的系统由三部分构成:

  • 大脑:一个支持function calling的大模型接口。它负责理解任务、调工具、读返回结果、决定下一步动作。
  • 手:Agent可以调用的工具集合,包括执行shell命令、读文件、写文件、列出目录结构。每一个工具都返回真实的stdout、stderr和退出码。
  • 循环控制:Agent不断向大模型发消息,大模型返回要不要调工具、调哪个工具、传什么参数,执行完把结果追加回上下文,继续下一轮。直到大模型认为任务完成,不再请求调用工具,循环才结束。

核心循环的代码长这样,去掉了一些细节,看起来像一套简化版的任务执行器:

while True: response = client.chat.completions.create( model=MODEL_NAME, messages=messages, tools=TOOL_SCHEMAS ) msg = response.choices[0].message if not msg.tool_calls: # 不再调用工具,说明Agent认为可以收尾了 print("final:", msg.content) break for call in msg.tool_calls: tool_name = call.function.name tool_args = json.loads(call.function.arguments) # 真实执行工具,并把结果返回给模型 result = dispatch_tool(tool_name, tool_args) messages.append({ "role": "tool", "tool_call_id": call.id, "content": str(result) })

把大模型的API地址、模型名、系统提示词换成你自己的,这个循环就能跑起来。在开始实验前,我自己花了一晚上把日志、超时、结果截断补上,否则后面会栽在流程控制上。比如工具输出的内容可能很长,如果不限制返回给模型的字符数,上下文很快就会被一大堆文件内容塞满,百万Token也不够烧。

2.2 为什么选择function calling而不是自由对话

在大模型应用里,让LLM输出自然语言来规划、再让程序解析关键词,这种方案我也试过,结论是极不可靠。模型会在规划里写“我先用python脚本处理数据,再训练模型”,但如果你真的让程序去解析这句话,你会发现自己写了一个脆弱不堪的意图识别器。

用function calling要稳得多。它会强制模型输出结构化的工具调用请求,比如run_commandread_file这些函数名和对应参数,而不是自由文本。程序拿到结构化指令后直接分发执行,执行完把真实结果塞回去。整个闭环非常干净,出错也容易定位。

更重要的是,function calling让“安全边界”有了落地的地方。我可以限制它能跑哪些命令、能访问哪些目录、不能让它在某个目录之外乱写文件。Agent在明处,工具执行在暗处,我能看见每一步。这比让它直接生成bash脚本然后丢给subprocess.run执行要安全很多。

2.3 任务书的写法,决定了一半的成败

我给Agent的任务书不是简单一句话“帮我做个分类器”,而是完整写清楚了五类信息:

  1. 角色和背景:你是一个机器学习工程师,现在要在/workspace目录里完成一个文本分类模型。
  2. 数据和环境:你有哪些可用文件,目录里预装了哪些包,网络不可用。
  3. 交付物清单:明确要生成哪些文件。
  4. 验收标准:测试集F1大于等于0.93,跑起来不能靠人工微调。
  5. 运行方式:每一步执行完要检查退出码,如果命令失败,不要重复一模一样的命令。

很多人低估了第5条的作用。如果没有这句话,Agent在遇到某个命令报错时会进入复读机状态,把同一段代码改一个空格又跑一遍,然后又跑一遍。后来我发现,真正让Agent表现稳定的不是模型本身,而是你在任务书里给它的约束和自我检查要求。

这种“任务目标明确+环境边界清楚+验收标准可执行”的文件,本质上就是一个工程里的需求文档。它决定了大模型在自主执行时是漫无目的地瞎转圈,还是能集中火力往终点推进。

3. 全流程实录:从空目录到F1 0.96的文本分类模型

3.1 第1~14轮:探索目录、识别数据、确认基线

实验开始后,Agent做的第一件事是查看工作目录。它调用了几次ls -lafind,找到了数据文件的位置,然后主动去读文件开头,检查数据格式。

$ ls -la /workspace total 64 drwxr-xr-x 4 root root 4096 ... drwxr-xr-x 1 root root 4096 ... drwxr-xr-x 2 root root 4096 data -rw-r--r-- 1 root root 421 task.md $ head -5 /workspace/data/mail.tsv label text spam Congratulations! You've been selected for a free cruise... ham Hi Mike, are we still meeting tomorrow afternoon? spam URGENT: Your account has been locked. Click here to verify... ham Don't forget to pick up milk on your way home.

它花了大概五六轮去理解数据结构,然后做了一件典型工程师会做的事:检查标签分布是否均衡,统计文本长度,确认需要不需要做类别重采样。它还很自觉地写了几个shell命令统计样本量。

第一版方案它选择了自己动手搭一个两层MLP,词向量部分用PyTorch的EmbeddingBag,这样不需要额外下载预训练词向量,符合网络受限的约束。如果你让一个只会写CRUD代码的人来干这活,他大概率想不到这个方案;但大模型的训练语料里见过太多文本分类的做法,这种方案对它来说是常见套路。

3.2 第15~28轮:写出第一版训练脚本并踩中第一个API坑

到第15轮左右,Agent开始写真正的代码了。它先写了一个prepare_data.py,用pandas读取TSV文件,把文本分词后转成索引序列,并手动完成了训练集和测试集的划分。这个环节我没有看到任何卡顿,代码一次通过。真正的问题出在它写训练脚本时。

第一版训练脚本里,它试图用torchtext.data.TabularDataset来加载数据。这段代码看起来有理有据——因为PyTorch生态里处理文本分类确实常用torchtext——但问题在于,新版本torchtext早就把这个接口移除了。结果一跑就报错:

AttributeError: module 'torchtext.data' has no attribute 'TabularDataset'

这是非常典型的大模型幻觉:它见过老版本教程里这么写,但环境里装的已经不是那个版本了。Agent收到报错后没有硬撑,它先执行了pip show torchtext确认版本号,然后立刻决定弃用torchtext,改用pandas手工构造数据集。整个过程一共花了三四轮,看起来就像一个有经验的开发者在版本兼容性上踩坑后快速转向。

3.3 第29~44轮:loss不降与自动调参的拉锯战

训练脚本第一次成功跑起来之后,loss值是能下降的,但降得很慢,三个epoch之后验证集的F1只有0.82左右,离0.93的验收线差着十万八千里。Agent这时做了一件让我相当意外的事:它主动去读训练日志,然后给自己写了一段调试总结,大意是“当前学习率偏大导致loss震荡,同时EmbeddingBag的维度可能过小,我先尝试降低学习率并增大embedding维数”。

它随后修改了模型代码,把embedding维数从32调到128,学习率从默认的1e-3改成5e-4,并加了StepLR学习率调度器。重新训练后,F1从0.82涨到了0.90左右。这时候Agent又开始折腾过拟合问题——它注意到训练集F1已经到0.99,验证集却卡在0.90上下,于是给模型加了一层Dropout,还设置了max_norm=3对词向量做裁剪。

这一轮轮的操作,你可以说是它在机械地试参数,但在我看来,它至少遵循了一个清晰的调试框架:先看训练集和验证集差距判断是不是过拟合,再针对性地改结构,而不是盲目乱试。这种能力如果放到几年前,我会以为是一个有经验的调参工程师在手把手带一个新手。

3.4 第45~58轮:独立完成测试评估、错误分析和交付文档

模型效果达到验收线之后,Agent没有直接收工,而是开始补交付文档。它先写了evaluate.py,在保留的测试集上重新加载model.pt并计算Precision、Recall、F1。最终结果如下:

$ python evaluate.py --data /workspace/data/test.tsv --model /workspace/model.pt Accuracy : 0.9520 Precision: 0.9406 Recall : 0.9702 F1-score : 0.9552

F1最终落在0.9552,超过了0.93的要求。它接着自动生成了一份README.md,里面写了数据来源、环境依赖、训练命令、评估命令,还老实地在“局限性”一栏里注明:由于数据量较小且是自行整理的示例数据,模型泛化能力仍需在更大规模真实数据上验证。看到那段话的时候,我说实话是有点惊讶的,因为它不只是把活干完了,还知道自己生产出来的东西边界在哪里。

整个过程中我唯一的介入是第30轮左右,给Agent的上下文里追加了一条系统提示,提醒它如果某条命令连续失败三次,要停下来写一段“目前尝试了什么、为什么失败、下一步还有什么可选方案”再继续。除此之外,所有代码都是它自己写的。

4. 过程中翻得最狠的五个车,以及我给Agent打的补丁

4.1 幻觉式API调用:它写的代码能骗过眼睛,骗不过运行时报错

在第一版训练脚本里,Agent使用了一个旧的torchtext接口。这种错误你如果只让它生成代码、不运行代码,根本发现不了。因为大模型的上下文里存了太多不同版本的API用法,它在生成时不会自动去核对当前环境的版本号。单独把这段代码拿给一个人看,也可能觉得“写得挺规范”。

我后来在系统提示词里加了一条铁律:每次项目开始前,先执行一次pip list | grep torchpython --version,确认环境版本后再决定API选型。之后这个问题再没出现过。这件事给我的启发是:让大模型自己写代码的时候,一定要把“验证环境”和“写代码”串成一个闭环。只盯着代码本身,永远发现不了版本差异造成的坑。

4.2 上下文越长越容易失忆:文件读了等于没读

实验进入中后期,上下文已经积累了十几万Token。这时候出现了一个让我抓狂的现象:Agent明明前面写过prepare_data.py,后面却会在train.py里写from preprocess import ...,而preprocess.py根本不存在。

我一开始以为是模型蠢,后来复盘日志才发现,不是它蠢,是它早期生成的文件列表埋在了很长的上下文里,模型在写到一半时,很可能只记得“我用python写了数据预处理模块”这个模糊概念,具体文件名早就被冲淡了。这就像一个人翻一个五百页的文件夹,翻到第两百页时,已经不记得前面某个表格在第几页。

我的补丁方案很土但很有效:在每个工具调用的开头,加一个“工作区当前文件”的固定字段,只要是涉及写代码的动作,Agent必须先调用list_filesread_file确认文件名和内容,再动手修改。宁可每次多花一点Token,也不能让它凭记忆写错。

4.3 连续重试死循环:第一次把Agent跑成复读机

第30轮左右出过一段让人血压升高的记录。Agent在处理某个数据格式错误的时候,连续四次生成几乎一模一样的代码,只是改了变量名或注释,然后重复跑,再报错,再改。看起来它其实没有理解错误根源,只是在拿代码撞运气。

我观察了十几分钟,实在看不下去了,才在系统提示词里加了“连续失败三次必须停下反思”的补丁。加了之后,效果立竿见影。它在一段报错连续出现两次之后,主动输出了一段总结,指出问题可能出在标签类型没有转成torch.long,于是不再顺着原来的思路继续撞,而是跳出来分析了数据类型,第三次就解决了问题。

后来我意识到,大模型天然有个倾向:顺着当前对话的惯性一直往下走。这种惯性在代码生成顺利时是优点,但在报错场景里就成了复读机病根。强制“反思”是打断惯性最直接的手段。

4.4 Token和时间成本不可控:烧起来比想象中猛

这次实验总共消耗了大约130万Token,折算下来大概2美元左右,费用本身不算高。真正的问题是执行时间成本。因为Agent在跑训练脚本时,一跑就是十几个epoch,中间如果模型调参方向不对,几十秒到几分钟就浪费了。整个流程走完用了将近两个小时,其中大半时间花在等待训练完成和来回试错上。

如果你想把它当成自动化流水线,最需要关注的不是Token费用,而是任务总时长和失败恢复机制。后来我在设计工具时给run_command加了超时参数,比如训练类命令超过180秒就被杀掉,把返回结果截断后告诉Agent“命令超时,可能卡死”。这样它就不会干等一个永远不会结束的训练进程。

4.5 没有约束时,Agent会自作主张地越权尝试

这个实验一开始我没有把Docker的网络断掉,结果Agent在前几轮试图用pip install transformers去下载外部库。由于容器没配外网,命令报错,它才转向使用本地已有的包。你如果仔细想这件事,会发现一个值得警惕的点:Agent的目标是完成模型,它并不知道“下载一个大型依赖”会带来的风险,它只知道哪个方向看起来最省事。

如果是一个生产环境,Agent可能在未经审批的情况下给项目引入一堆版本不确定的包,甚至尝试写文件到其他目录。所以我现在给任何Agent实验都定了硬规矩:必须在容器里跑,容器必须没有外网,工作目录必须只读映射部分,Agent能写的目录只有它自己的/workspace。这些安全边界不是锦上添花,而是底线。你越放开Agent的权限,它给你造的惊喜和惊吓就都是倍增的。

5. 关于“AI能不能自己造AI”,我现在敢说的结论

5.1 实验验证出的能力边界清单

先把这次实验证明能做的事列在明处:

  • 给定一个验收指标清晰的建模任务,AI Agent能独立完成数据处理、模型选型、训练、调参、评估、文档产出。
  • 中途遇到API版本、数据类型、模型过拟合等问题时,只要环境能返回真实报错,它就能自我纠正。
  • 它能自主判断何时该停止调参,还会在最终报告里写清楚模型适用范围和数据局限性。
  • 在资源受限环境里,它能主动抑制向外拉依赖的冲动,转向本地资源求解。

再说这次实验没有证明的东西:它没有发明新模型结构,没有质疑任务书本身是否合理,没有主动对数据质量提出更深层的批判,也没有在训练失败之后提出一个训练范式之外的替代方案。它做的一切,本质上是在已有知识库里组合出最高概率成功的路径,再把每一次运行结果当成反馈信号去修正路径。这套机制在标准流水线上已经够用,但它还没到能开辟新方向的地步。

5.2 当一个“开发主管”用:什么任务适合交给它

通过这次实验,我对“什么时候可以放心让AI自主做项目”有了一个更清醒的判断。适合交给它的任务有这几个共同点:

  • 目标是可量化的,比如F1指标、准确率、运行时间。
  • 技术栈已经限定,不需要跨领域引入全新框架。
  • 执行环境可控,错误能被捕获并从反馈中恢复。
  • 人工只负责定义需求和验收,不需要在过程中反复解释业务背景。

反之,任务目标模糊、需要大量外部业务知识、或者数据质量本身不可信的场景,别指望Agent能自己搞定。如果连你自己都不知道“好模型”长什么样,AI更不可能替你想明白。它本质上是一个无比积极的执行者,不是一个能扛起需求定义和业务判断的决策者。

5.3 给想复现这个实验的人几条可执行建议

如果你也想亲自动手验证一次,我建议从这四步开始:

  1. 撑一个Docker环境,禁用外网,预装熟悉的机器学习依赖。不需要在第一次就挑战高难度任务,从文本分类或图像分类这种标准任务切入最稳。
  2. 把任务书写成需求文档而不是Prompt。写清楚环境约束、交付物清单、验收指标、失败重试策略。
  3. 一定要给工具执行加结果截断和超时机制。否则一次失误的命令可能把几十万Token的上下文全撑爆。
  4. 记录完整日志。没有日志你会完全看不懂它在干什么,出了Bug也没法复盘。

最后再分享一个我个人在操作中的体会。实验进行到中段,我看着Agent反复读报错、改代码、再运行的那个循环,心里有一种很微妙的感觉——它像极了一个刚刚入行、干劲十足但没有太多大局观的年轻工程师。你需要给它划好边界,给它明确标准,盯紧它别在错误的方向上迷太久,但你要承认:那些重复性高、规则清晰的脏活累活,它已经在相当程度上能自己扛下来了。这个现实不恐怖,倒是挺值得认真对待的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询