最近一年，我一直在积极探索最新出现的大语言模型（LLM），研究它们能在哪些场景下、以及在多大程度上增加或提升我的生产力。从我之前的[博客文章](/GPT-scared-me.html)中可以看出，AI已经深入影响了我的生活和工作的各个方面。它帮助我[编写代码](/ai-comment-oriented-programming.html)、撰写文档、写博客、整理思路。总的来说，我感觉我的生产力提升了五到十倍。但如果我们从一个更抽象的角度来看，到目前为止，AI对这个世界的影响主要是通过我作为代理（agent）来实现的。例如，它帮我写代码，我作为一个程序员，通过AI编写的代码来影响客户；它帮我写文档，我通过这些文档来影响我的同事；它帮我写博客，我通过这些博客来影响我的读者。从这个角度思考，很明显我已经成为了AI影响这个世界的瓶颈。

一个非常危险但有趣的想法是，是否有可能让AI直接在物理上影响这个世界，比如通过接入一个机器人系统来帮助我们完成更多任务。虽然人类在这个过程中仍然可能需要进行审计或审查，就像编写代码、撰写文档、写博客一样，但这无疑可以大幅增加可扩展性，实现更智能的自动化，从而可能让我们的效率成倍提高，或者启发更多相关场景。这方面已经有了不少研究，但我想以最接地气的方式做一个实验，看看将AI接入机器人系统这个思路是否能解决我所面临的问题。

我选择的领域是[天文摄影](/astrophoto-tutorial-1.html)。现在的天文摄影已经完全不同于过去那种手动推动望远镜、使用胶片进行摄影的方式。它通常涉及电脑控制多种设备，使用赤道仪进行定位，使用数码相机进行拍摄，使用电动调焦器进行对焦。整个流程可以概括为感知、决策和执行三个阶段。在实际拍摄时，我们人类需要根据天气预报和当前的环境条件（如是否有月亮、是否有云等）来做出决策，比如今晚是否出行拍摄、拍摄哪个天体。不同的天体在不同时间的高度也是不一样的，我们需要如何安排各个天体的拍摄顺序，以避免它们被墙挡住或受大气扰动的影响。最后，我们还需要将这一系列决策转化为执行指令，比如在[控制软件](/astrophoto-tutorial-5.html)中点击按钮来定位天体、拍摄连续照片等。在这个过程中，有很多体力活，这些活动往往不是简单的自动化任务，而是需要一定智能的。我非常好奇，在这种情况下，AI是否能帮我们完成这些体力活，让我们将精力集中在真正需要创造力和决断力的地方。

如果我们深入思考[AI的应用](/recent-AI-advancement.html)，会发现其潜力和限制都很大。就像AI帮助编写代码和文档一样，它在某些场景下非常适用，而在其他场景下则不那么合适。关键在于找到最适合AI介入的系统环节，以最大化其效用，并探索新的商业场景。而一旦我们开始深入思考这些问题，我们很快会遇到一个核心难题：安全性与灵活性之间的权衡。

一个明显的风险是，如果AI仅能通过我们这些代理来影响世界，这个过程相对安全，尽管可能会有一些bug或错误从我们眼皮下面溜过，可能在未来某个时刻造成损失。但总体而言，这种风险是可控的。然而，如果我们让AI直接接入机器人，使其能够直接影响世界，那么它可能造成破坏的方式将大幅增加。比如它可能操纵机器人攻击人类或者物品，这是一个非常可怕的场景。因此如何确保AI的能力在整个过程中受到限制，保障人和财产的安全，是至关重要的。但安全性并非没有代价。确保安全性的一个常见的解决方案是采用白名单机制，即仅允许AI进行非常有限的操作，从而大大提高安全性，但这也限制了AI可能为我们带来的帮助。因此，如何平衡安全性和灵活性，这两个相互矛盾的目标，成为一个明显的技术难点。此外，还需要考虑其他技术细节，比如如何将AI以最有效的方式接入系统的特定环节，以充分利用其上下文窗口。

从工程的角度来说，如果我们想要平衡安全性和灵活性，有两种比较常用且成熟的方法。第一种方法是使用领域特定语言（Domain Specific Language，DSL）。这基本上意味着我们重新发明一种编程语言来赋予AI各种能力。然后，我们让AI输出一个符合这种DSL的程序，由我们的DSL解释器来解释执行。因为我们对这个解释器有完全的控制，我们可以将其能力限制在安全的范围内。例如，如果这个DSL里面没有可能会导致伤害人的操作，那么AI自然也就无法执行这样的动作。当然，这个问题本身并不是trivial的，但这至少提供了一个相当可行且并不困难的思路。DSL有很多好处，但它也有一个明显的缺陷，那就是定义一个符合我们场景的DSL及相关解释器的成本相当高。很多时候，我们实际上是在重新发明轮子。例如，在天文摄影中，我们可以很容易地想到这个DSL可以支持一些基本操作，如拍照、对焦、指向某个天体等。这些还可以说不算是浪费时间的体力活，但如果我们想要让这个能力变得更加复杂和强大，不可避免地就会涉及到循环、条件分支等更加复杂的控制逻辑。而这些控制逻辑一方面定义起来并不简单，另一方面，它们也是任何编程语言都会涉及到的功能。这样，我们就等于是在一个已经被实现过无数遍的领域里重新发明一个类似的功能，这在工程上是非常不理想的。

要平衡安全性和灵活性，一种可行的工程方案是使用现成的编程语言，避免重新发明轮子。这样做的好处是可以利用现有的循环控制、条件分支、变量、状态管理和系统函数等控制逻辑，比如延时操作，这可以大大节省开发成本，快速看到成果。但这也可能赋予AI过大的能力，比如直接使用Python让AI编写脚本控制天文摄影设备，可能导致AI或用户或无意或故意地加入破坏性的代码，造成严重后果，如删除系统文件或损坏设备。

因此，不论是使用领域特定语言（DSL）还是现成的编程语言，都有明显的优缺点。而且这个技术挑战不仅存在于天文摄影或机器人控制领域，它是大型语言模型（LLM）领域一个普遍的问题。目前我们的一个有力武器是沙箱执行。具体来说，无论是进行数据分析还是机器人控制等需要编写代码的任务，OpenAI提供了一个沙箱代码执行功能，可以在它的服务器上执行GPT写的代码。这样即使代码含有恶意内容，受损的也只是OpenAI而非我们自己。然而很多时候我们因为种种原因不能将数据发送给OpenAI，或者像我的项目一样，需要直接在我的电脑上控制与之相连的机器人设备，因此无法使用OpenAI的沙箱功能。这就让我们没有办法通过第三方的沙箱服务来绕过这个问题：如何确保GPT生成的代码是可信且安全的。特别是在加入人工干预后，虽然GPT可能暂时不会生成有害代码，但如果用户在代码中加入恶意模块，比如删除系统文件或窃取隐私，我们应该如何防范？

我摸索出来的一个解决方法是，使用一种现成的编程语言来先保证开发迭代的效率，然后通过四种措施来增强安全性：第一，降低GPT不小心写出可能伤害系统的代码的概率；第二，即使写出了类似的代码，也尽可能无法执行；第三，即使执行了，也不会造成严重后果；第四，即使有人（而非AI）故意注入恶意代码进行破坏，由于前两点的限制，它也无法执行或造成严重后果。当然，这一点非常困难，可能需要专业的信息安全审计，目前我的方法也不能完全保证。

具体的做法分为四个方面：第一，把跟机器人相关的操作封装成一个类，所有的操作只能通过这个类进行，并且把这个写到GPT的[prompt](/prompt-engineering-guide.html)里面，这样它生成的python code就只能通过封装好的类来进行。类似DSL，因为我们对这个类有完全控制，所以这部分的风险得到了控制。第二，GPT写好了python程序之后，我们不是直接执行这个字符串，而是先用python的抽象语法树（AST）对它进行分析，在分析过程中，我们可以对程序的功能进行一些限制，比如一旦发现有import或者from import之类的语句就终止执行，这样这些code就被严格限制在只能使用我们所提供的库上，而不能自己实现更加复杂的功能。第三，尽管GPT可能不会无意中犯错，但人可能会故意写一些恶意代码，比如直接用open函数打开系统内部的敏感文件。对于这种情况，处理起来比较tricky，但一种可行的方法是采用黑名单或者白名单机制对可调用的函数进行限制，尽可能堵上漏洞，同时保证编码的灵活性。第四，即使用户绕过了前三点的限制，但只要我们的程序不是在宿主电脑中执行，而是在一个沙箱中执行，它所能造成的破坏其实也是有限的。尤其是在使用docker时，每个用户的环境都是彼此隔离的，就算操作系统被破坏了，下一个用户拿到的又是一个全新的环境，所以这也可以极大地限制用户所写的恶意代码所造成的破坏。

具体地说，我选择使用Python作为机器人与世界交流的窗口，实现了一系列Python类库接口来完成天文摄影的常见任务，如查询天体高度、指向天体、拍照和对焦。同时，我设置了一些限制，只允许使用给定的接口操作天文摄影设备，并禁止import未经审核的函数，以防止用户执行复杂的破坏性操作。此外，我们还对AI生成的代码进行人工审核，确保没有恶意代码。这些措施旨在实现安全性和灵活性的平衡。

在[这个链接](https://b23.tv/hIwNBha)中，我们可以看到一个演示视频，展示了我做的一个原型系统。在这个系统中，我们可以向AI描述我们的需求，然后AI会帮助我们编写一个指令序列。这个指令序列实际上是一个简单的Python程序，能够实现包括循环、分支等比较复杂的逻辑控制，使用几乎所有的Python语法和一些受限的系统库。从视频里可以看到，对于简单的指令，比如将望远镜指向M101星系，保持姿势五秒后再归零，AI能够非常流畅地编写代码并立即执行。对于更复杂的指令，比如"检查M101天体的当前高度，如果高于30度，则指向它并拍摄50张照片，每张照片曝光300秒，每拍5张照片后进行一次Dither处理，拍摄完这五十张照片后归零。如果在此过程中M101的高度低于三十度，则立即归零。" 即使是这种复杂的指令，AI也能够很好地完成。唯一的缺陷是，在第一版的指令中，AI没有意识到我们拍照片的目的是为了保存它们，因此没有调用保存文件的指令序列。但我相信通过合理的prompt engineering，这个问题可以轻松避免。我们的人工审核也发现了这个问题，说明它并不隐蔽，也可以轻松修正。在更多的实验中，我们注意到AI并不总是特别可靠，比如尽管我们在prompt中告诉它不可以使用import，有时它还是会忍不住想要import一些东西。这个问题也许通过prompt engineering可以得到改进。

总的来说，在整个过程中，我的感受是AI本身还是非常安全的。在我们测试的众多场景中，AI生成的代码都是非常合理的，没有涉及到任何可能故意或无意损坏设备的操作，例如不停地将电动调焦器向一个方向转动直到电机烧毁。在设计整个机制的过程中，我们更担心的其实是人类用户。大多数的限制措施都是针对防止用户在代码中插入恶意代码而设定的，比如设立沙箱或限制某些功能的使用。这是一个非常有意思的观察，但也是有办法去规避的。例如，当用户控制的是自己的设备而不是租用的设备时，他们会有很强的动力来配合AI，以保证代码的安全性。

这是一个非常有意思的实验。我在整个过程中学到的经验教训是，将机器人接入AI的想法本身可以产出非常好的结果。AI目前的能力非常强大，它可以有效地理解和感知周围的环境，做出合理的决策，并将这些决策翻译成机器人的动作。从安全性角度来看，我的体会是AI本身是非常谨慎和安全的。只是为了防范来自人类的恶意，我们还是需要设立很多机制来限制系统的能力。在实现一个类似的系统时，我们可以考虑使用Python等现成的编程语言。这主要有几个原因：首先，Python的通用性特别强，能够与许多机器人系统无缝对接；其次，当前流行的LLM对于使用Python编写代码的支持特别好；最后，Python在限制可调用的库和能力方面非常方便，例如它支持内置的抽象语法树等等。希望这个实验可以给你带来启发。

<script async data-uid="49b08a3e73" src="https://yage-ai.kit.com/49b08a3e73/index.js"></script>
