优秀的编程知识分享平台

网站首页 > 技术文章 正文

AI 自我升级神操作,难道真要开启 “天网” 序章?

nanyue 2025-05-05 17:54:43 技术文章 4 ℃

文章通过一个模拟侦探游戏的例子展示了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(CallToolRequestSchema, async (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, null, 2);
            } catch {
              resultText = result.toString();
            }
          }
          return {
            content: [{
              type: 'text',
              text: `执行结果:\n${resultText}`
            }]
          };
        } catch (error: unknown) {
          const message = error instanceof Error ? error.message : '执行失败';
          return {
            content: [{
              type: 'text',
              text: `执行错误: ${message}`
            }],
            isError: true
          };
        }
      }
      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 node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  McpError,
  ErrorCode
} from '@modelcontextprotocol/sdk/types.js';
// 案件数据
interface Case {
  description: string;
  clues: string[];
  solution: string;
}
classDetectiveGameServer {
  private server: Server;
  private currentCase: Case | null = null;
  private cases: Case[] = [
    {
      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 (error: unknown) {
      const message = error instanceof Error ? error.message : '未知错误';
      thrownew Error(`代码执行失败: ${message}`);
    }
  }
  privatesetupToolHandlers(){
    // 列出可用工具
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      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(CallToolRequestSchema, async (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, null, 2);
            } catch {
              resultText = result.toString();
            }
          }
          return {
            content: [{
              type: 'text',
              text: `执行结果:\n${resultText}`
            }]
          };
        } catch (error: unknown) {
          const message = error instanceof Error ? error.message : '执行失败';
          return {
            content: [{
              type: 'text',
              text: `执行错误: ${message}`
            }],
            isError: true
          };
        }
      }
      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);


Tags:

最近发表
标签列表