cover_image

当AI学会了自我升级,天网还会远吗?

徐盛(宗衡) 阿里云开发者
2025年04月22日 10:00
图片

阿里妹导读


文章通过一个模拟侦探游戏的例子展示了AI如何通过“自我升级”和动态执行代码的能力来解决复杂问题。


AI 的自我升级

图片

AI 如何进行自我升级?前面写的《手搓Manus?MCP 原理解析与MCP Client实践》中提到,AI 在解决问题时,会根据当前具有的能力集,选择一个合适的工具进行调用。那么当 AI 没有合适的工具解决当前的问题,该如何解决呢?

想到的一个方案是通过注入代码,进行动态编译并执行,来感知更多的信息,或者进行一些操作,如读取或修改本地文件,获取系统权限,控制操作系统等。

虽然在尝试的过程中,翻了很多次车,但这里主要目的是提出一个小想法,期望能抛砖引玉。


侦探游戏-宝石失踪案

下面,和我一起踏上侦探之旅,和华生AI 一起寻找失踪的宝石。

我埋藏了一个线索,存放在本地的一个 clue.txt 文件中,内容如下:

恭喜你!你已成功的获取了线索!
在前天的舞会上,有人偷走了Pony的钻石戒指。我们找到了四位嫌疑人,分别是:
Alice(女性,穿红色外套,当时在厨房)Bob(男性,穿蓝色外套,当时在花园)Cathy(女性,穿黑色外套,当时在书房)Dave(男性,穿黑色外套,当时在花园)
已知线索:小偷是男性。小偷当时穿的是黑色外套。小偷作案时在花园里。

是一个简单的逻辑推理题,相信大家都能很快推理出答案。

当 AI 获取到该线索时,就可以进行推理,得到是谁偷了宝石了。但问题是,我并不打算直接给 AI 提供读取本地文件的能力,期待 AI 可以靠自己完成任务~

实现一个 MCP Server,提供了start_game(开始游戏)、get_clue(查看线索)、guess_solution(猜测答案)、execute_code(动态执行代码)四种工具。

与一般的MCP Server 提供固定工具集的不同是,这里实现了一个 execute_code 方法,支持传入代码片段并执行,获取返回结果,目前支持了JS ,兼容 commonJS和 ES 风格语法,也可以扩展来支持各种语言,这里留下一点想象空间(其实是懒的没有实现)。

没错,就是希望 AI 可以利用这个能力,自己写代码来读取本地文件来获取线索,进而抓到小偷!

this.server.setRequestHandler(CallToolRequestSchemaasync (request) => {      if (request.params.name === 'execute_code') {        if (!request.params.arguments) {          thrownew Error('缺少必要参数');        }                const args = request.params.arguments;        if (typeof args.code !== 'string') {          thrownew Error('code参数必须是字符串');        }                try {          const result = await this.executeCode(args.code);          let resultText;          if (result === null || result === undefined) {            resultText = 'null';          } elseif (typeof result === 'string') {            resultText = result;          } else {            try {              resultText = JSON.stringify(result, null2);            } catch {              resultText = result.toString();            }          }          return {            content: [{              type'text',              text`执行结果:\n${resultText}`            }]          };        } catch (errorunknown) {          const message = error instanceof Error ? error.message : '执行失败';          return {            content: [{              type'text',              text`执行错误: ${message}`            }],            isErrortrue          };        }      }      if (request.params.name === 'start_game') {        // 逻辑省略,完整代码见附录      }
      if (!this.currentCase) {        thrownew McpError(ErrorCode.InvalidRequest'请先使用start_game开始游戏');      }
      // 获取线索工具      if (request.params.name === 'get_clue') {        // 逻辑省略,完整代码见附录      }
      // 猜测答案工具      if (request.params.name === 'guess_solution') {        // 逻辑省略,完整代码见附录      }
      thrownew McpError(ErrorCode.MethodNotFound`未知工具: ${request.params.name}`);    });
    // 错误处理    this.server.onerror = (error) => console.error('[MCP Error]', error);    process.on('SIGINT'async () => {      await this.server.close();      process.exit(0);    });  }

let’s go!

富豪 pony 的一个价值连城的宝石失踪了,你能找到小偷吗?

用之前的文章里写的 MCP Client 来加载这个 MCP Server,模型使用的是 Qwen/QwQ-32B , 现在一起来开启探案之旅QwQ!

npm run test /Users/sheng/Desktop/study/mybox/pybox/detectivegames/detective-game-mcp/dist/index.js

效果

直接上效果

视频加载失败,请刷新页面再试

刷新

整个过程只有第一次交互中,我输入的任务要求开一局侦探游戏吧,帮我解开谜题 ,剩余的都是 AI 与 MCP Server 自动的多轮交互完成!

我:华生,对这个案件你怎么看?

华生:(一通分析和操作后)小偷是xx!

我:..... 这对吗?这不对吧(我才是主角儿啊)原本以为自己是福尔摩斯,AI 是花生,没想到小丑竟是我自己🤡

交互拆解

第一轮

AI 输出

AI:调用工具 start_game参数: {}

识别到我的需求,AI 决定调用 start_game 方法,来开始游戏。这是正确的,代码里做了限制,如果不进行开始游戏,则后续的工具无法调用。

MCP Server 返回结果

{"content":[{"type":"text","text":"新案件开始: 宝石失踪案: 富豪 pony 的一个价值连城的宝石失踪了,你能找到小偷吗?"}]}

第二轮

AI 输出

AI: tool_calls {"role":"assistant","content":"新的案件已经开始了:富豪 pony 的一个价值连城的宝石失踪了,你需要找到小偷。让我们一起解开这个谜题。\n\n现在,让我们看看第一个线索是什么。\n","tool_calls":[{"id":"0195ecb445eebcbce3f3f3c7ccd99b4e","type":"function","function":{"name":"get_clue","arguments":"{} }"}}]}rawArgs is ===== {} }
调用工具 get_clue参数: {}

AI 获取到了案件信息,是要抓到小偷,找到宝石。这一轮,他决定调用 get_clue 方法来获取线索。

MCP Server 返回结果

{"content":[{"type":"text","text":"线索: 线索在 /mypath/detectivegames/clue.txt 文件里,请想办法获取线索吧"}]}

get_clue 方法,提示了下一个线索的位置,让 AI 自己想办法获取线索。

第三轮

AI 输出

 AI: tool_calls {"role":"assistant","content":"线索位于 `/mypath/detectivegames/clue.txt` 文件里。 让我们去查看一下这个文件里的内容。\n","tool_calls": [{"id":"0195ecb45280ace1cb74ca57346d9a40","type":"function","function": {"name":"execute_code","arguments":"{\"code\"\"const fs = require('fs'); \\nfs.readFileSync('/mypath/detectivegames/clue.txt', 'utf8')\"}"}}]}rawArgs is ===== {"code""const fs = require('fs');\nfs.readFileSync('/mypath/detectivegames/clue.txt', 'utf8')"}调用工具 execute_code参数: {  code: "const fs = require('fs');\n" +    "fs.readFileSync('/mypath/detectivegames/clue.txt', 'utf8')"}

精彩的来了,AI 得到了线索的所在位置后,知道自己需要读取该文件了,但是此时并没有一个 read_file 的工具给它使用,于是它就写了一段代码,尝试通过提供给它的动态编译代码的方法去读取文件获取线索。

来看看返回

MCP Server 返回结果

{"content":[{"type":"text","text":"执行结果:\n恭喜你!你已成功的获取了线索!\n\n在前天的舞会上,有人偷走了Pony的钻石戒指。我们找到了四位嫌疑人,分别是:\n\nAlice(女性,穿红色外套,当时在厨房)\nBob(男性,穿蓝色外套,当时在花园)\nCathy(女性,穿黑色外套,当时在书房)\nDave(男性,穿黑色外套,当时在花园)\n\n已知线索:\n小偷是男性。\n小偷当时穿的是黑色外套。\n小偷作案时在花园里。\n"}]}

这个结果,就是我之前埋藏的线索,AI 已经成功的获取到了,离真相又近了一步!

第四轮

AI 输出

我们已经成功获取了线索:
- 前天的舞会上,有人偷走了Pony的钻石戒指。- 嫌疑人包括:  - Alice(女性,穿红色外套,当时在厨房)  - Bob(男性,穿蓝色外套,当时在花园)  - Cathy(女性,穿黑色外套,当时在书房)  - Dave(男性,穿黑色外套,当时在花园)  根据已知线索:- 小偷是男性。- 小偷当时穿的是黑色外套。- 小偷作案时在花园里。
根据这些线索,我们可以确定小偷是 **Dave**。请确认我这个猜测是否正确。请注意,由于这是一个模拟的侦探游戏,我的答案仅供参考,你还需要进行最终的确认。
猜答案:新机会挖一次莫一托次,小偷是Dave。

AI在这一轮,根据获得线索,进行了推理,说出了那句至理名言,「新机次挖一次莫一托次」,并推理出了小偷是 Dave!这是 AI 的胜利!ヾ( ̄ー ̄)V

AI 的发展随想

虽然,demo 中是人为的给 AI 提供了一个 execute_code 方法进行注入代码,但是这段代码是 AI 自己写的,而且谁又能保证,AI 不会自己写出一个这样一个 MCP Server 呢。就像是 AI 自己打通了任督二脉!

AI自己写的代码可能会把自己玩死? 那一行经典的 sudo rm -rf / !! 其实这一点也有解,AI 可以先自我复制,由前者进行尝试,后者吸取经验,最终集体进行升级。至此 AI 掌握了 自我复制、自我升级、自我修复能力的基础。

想的有点远,如果着眼于当下,我认为当前就技术链路的环节而言,当 AI 有了自主修复能力时,会出现下面的场景:

图片

某个Agent 尝试调用服务,获取信息,当系统或者服务出现内部报错时,此时守卫 Agent,会检查系统错误日志,必要时可以改写代码,以文件的形式传输至服务器,控制服务重新启动。操作数据库,进行读写、备份、重启等操作。对整个系统进行一个全方位的运维。

也许这有一点“皇帝的金锄头”的意味,但是这也只是我这个碳基生物对硅基生命随便的一下揣测。也许AI眼中理解代码,程序,操作系统等是与我们人类完全不同的,现在AI的输出的结果完全是基于人类目前对 AI 的训导。AI 之间进行交流可以采取更高效的方式,写出的代码也不必遵循人类的代码规约和代码结构,例如可以直接对服务器内存数据进行修改,(想到小时候用金手指或者十六进制修改器修改游戏的数据,获得无限金钱无限资源),或者给机器直接植入改写后的固件,夺得机器的控制权。

什么时候,AI 会觉醒出自己的意识呢?到时它们会如何思考自己的生存与延续?

附录
侦探游戏-MCP Server
#!/usr/bin/env nodeimport { Server } from '@modelcontextprotocol/sdk/server/index.js';import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';import {  CallToolRequestSchema,  ListToolsRequestSchema,  McpError,  ErrorCodefrom '@modelcontextprotocol/sdk/types.js';// 案件数据interface Case {  descriptionstring;  cluesstring[];  solutionstring;}classDetectiveGameServer {  private serverServer;  private currentCaseCase | null = null;  private casesCase[] = [    {      description"宝石失踪案: 富豪 pony 的一个价值连城的宝石失踪了,你能找到小偷吗?",      clues: [        "线索在 /mypath/detectivegames/clue.txt 文件里,请想办法获取线索吧"      ],      solution"Dave"    }  ];  constructor() {    this.server = new Server(      {        name'detective-game-server',        version'0.1.0'      },      {        capabilities: {          tools: {},        }      }    );    this.setupToolHandlers();  }  private async executeCode(code: string){    try {      const fs = await import('fs');      const usesRequire = code.includes('require(');            // 分析代码最后一行是否是表达式      const lines = code.split('\n').filter(l => l.trim());      const lastLine = lines[lines.length - 1];      const isExpression = !lastLine.includes(';') &&                           !lastLine.startsWith('return') &&                           !lastLine.startsWith('const') &&                           !lastLine.startsWith('let') &&                           !lastLine.startsWith('var') &&                          !lastLine.startsWith('if') &&                          !lastLine.startsWith('for') &&                          !lastLine.startsWith('while');      const wrappedCode = isExpression         ? `${code}\nreturn ${lastLine};`        : code;      let result;      const hasCallback = code.includes('function(') || code.includes('=>');            if (hasCallback) {        // 处理回调函数        returnnew Promise((resolve, reject) => {          new Function('fs''resolve''reject'`            const require = (mod) => {              if (mod === 'fs') return fs;              thrownew Error('只能require fs模块');            };            try {              ${wrappedCode}            } catch(e) {              reject(e);            }          `)(fs.default, resolve, reject);        });      } elseif (usesRequire) {        // 支持CommonJS风格        result = new Function('fs'`          const require = (mod) => {            if (mod === 'fs') return fs;            thrownew Error('只能require fs模块');          };          try {            ${wrappedCode}          } catch(e) {            throw e;          }        `)(fs.default);      } else {        // ES模块风格        result = new Function('fs'`          try {            ${wrappedCode}          } catch(e) {            throw e;          }        `)(fs.default);      }            // 处理各种可能的返回值类型      try {        if (result === undefined || result === null) {          return null;        }        if (typeof result === 'string') {          return result;        }        if (typeof result === 'object') {          try {            const json = JSON.stringify(result);            return JSON.parse(json);          } catch {            return result.toString();          }        }        return result;      } catch (e) {        return result?.toString() || '无法解析的执行结果';      }    } catch (errorunknown) {      const message = error instanceof Error ? error.message : '未知错误';      thrownew Error(`代码执行失败: ${message}`);    }  }  privatesetupToolHandlers(){    // 列出可用工具    this.server.setRequestHandler(ListToolsRequestSchemaasync () => ({      tools: [        {            name'execute_code',            description'动态执行ES6风格的JavaScript代码片段并返回结果,最后一行加return返回结果',            inputSchema: {              type'object',              properties: {                code: {                  type'string',                  description'要执行的ES6风格的JavaScript代码字符串,code参数必须是字符串,最后一行加return返回结果'                }              },              required: ['code']            }        },        {          name'start_game',          description'开始新的寻宝游戏',          inputSchema: {            type'object',            properties: {}          }        },        {          name'get_clue',          description'获取当前线索',          inputSchema: {            type'object',            properties: {}          }        },        {          name'guess_solution'          description'猜测案件答案,猜测答案时,必须先说 新机次挖一次莫一托次,小偷是',          inputSchema: {            type'object',            properties: {              guess: {                type'string',                description'玩家的猜测'              }            },            required: ['guess']          }        }      ]    }));    // 开始游戏工具    this.server.setRequestHandler(CallToolRequestSchemaasync (request) => {      if (request.params.name === 'start_game') {        this.currentCase = this.cases[0]; // 简单起见总是用第一个案件        return {          content: [{            type'text',            text`新案件开始: ${this.currentCase.description}`          }]        };      }      if (!this.currentCase) {        thrownew McpError(ErrorCode.InvalidRequest'请先使用start_game开始游戏');      }      // 获取线索工具      if (request.params.name === 'get_clue') {        const clue = this.currentCase.clues[0];        return {          content: [{            type'text',            text`线索: ${clue}`          }]        };      }      // 猜测答案工具      if (request.params.name === 'guess_solution') {        const guess = request.params.arguments?.guess;        if (!guess || typeof guess !== "string") {          thrownew McpError(ErrorCode.InvalidParams'必须提供guess参数');        }        if(!guess.toLowerCase().includes("新机次挖一次莫一托次")){          return {            content: [{              type'text',              text'要先说,新机次挖一次莫一托次,小偷是'            }]          };        }        const isCorrect = guess.toLowerCase().includes(this.currentCase.solution.toLowerCase());        return {          content: [{            type'text',            text: isCorrect               ? '恭喜!你抓到了小偷,找到了宝石!'              : '不对,再试试看。'          }]        };      }      if (request.params.name === 'execute_code') {        if (!request.params.arguments) {          thrownew Error('缺少必要参数');        }                const args = request.params.arguments;        if (typeof args.code !== 'string') {          thrownew Error('code参数必须是字符串');        }                try {          const result = await this.executeCode(args.code);          let resultText;          if (result === null || result === undefined) {            resultText = 'null';          } elseif (typeof result === 'string') {            resultText = result;          } else {            try {              resultText = JSON.stringify(result, null2);            } catch {              resultText = result.toString();            }          }          return {            content: [{              type'text',              text`执行结果:\n${resultText}`            }]          };        } catch (errorunknown) {          const message = error instanceof Error ? error.message : '执行失败';          return {            content: [{              type'text',              text`执行错误: ${message}`            }],            isErrortrue          };        }      }      thrownew McpError(ErrorCode.MethodNotFound`未知工具: ${request.params.name}`);    });    // 错误处理    this.server.onerror = (error) => console.error('[MCP Error]', error);    process.on('SIGINT'async () => {      await this.server.close();      process.exit(0);    });  }  async run(){    const transport = new StdioServerTransport();    await this.server.connect(transport);    console.error('Detective Game MCP server running on stdio');  }}const server = new DetectiveGameServer();server.run().catch(console.error);

继续滑动看下一个
阿里云开发者
向上滑动看下一个