机器之心 05月03日 16:21
315 行代码构建编程助手,Go大佬揭开智能体的「神秘面纱」
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

知名Go语言专家Thorsten Ball分享了他用315行代码构建编程智能体的经验,强调通过实践与开源项目揭开技术神秘面纱。文章详细介绍了构建智能体的步骤,从基础的对话循环到添加工具(如read_file、list_files、edit_file),让LLM具备修改上下文之外内容的能力。该项目展示了如何利用大语言模型和工具,实现文件读取、编辑等功能,为初学者提供了学习智能体的良好范例。

💻 Thorsten Ball 通过实践构建了一个编程智能体,其核心是利用大语言模型(LLM)与工具的结合,实现对上下文之外内容的修改。

🔑 构建智能体的关键在于定义工具,包括名称、描述、输入模式以及执行工具的函数,这些定义以特定方式发送给模型。

🛠️ 文章详细演示了如何添加 read_file 工具,通过 JSON 模式定义输入,并使用 Go 语言编写相应的执行函数,使模型能够读取文件内容。

📚 作者进一步介绍了添加 list_files 和 edit_file 工具的方法,扩展了智能体的能力,使其能够列出和编辑文件,展现了智能体的潜力和应用。

2025-05-03 12:19 韩国

通过实践和开源项目揭开技术的「神秘面纱」。


选自ampcode.com

作者:Thorsten Ball

机器之心编译


知名 Go 大佬 Thorsten Ball 最近用 315 行代码构建了一个编程智能体,并表示「它运行得非常好」且「没有护城河」(指它并非难以复制)。



Thorsten Ball 在编程领域以其对系统编程和编程语言的深入研究而闻名,尤其擅长解释器、编译器和虚拟机等主题。他撰写的《用 Go 语言自制编译器》和《用 Go 语言自制解释器》则被视为编译原理领域的「入门平替」。



虽然这个编程智能体无法和 Claude、Gemini 等推出的编码功能相媲美,却为初学者提供了一个探索智能体的良好学习范例。这反映了他一贯的理念:通过实践和开源项目揭开技术的「神秘面纱」。


Thorsten Ball 在博客中分享了他的具体操作步骤。(注:本文中的代码截图可能并不完整,详细内容请参阅原博客。)


博客地址:https://ampcode.com/how-to-build-an-agent


乍看之下,智能体编辑文件、运行命令、自行解决错误似乎很复杂,但实际上只需一个大语言模型、一个循环和足够的 tokens。构建一个小型的智能体并不需要太多工作,少于 400 行代码即可实现,且大部分是样板代码。


接下来将展示如何从零开始逐步构建一个「game changer」,读者可以尝试亲自动手编写代码。


准备工作


首先准备好我们的「文具」:



铅笔出场!让我们直接开始,用四个简单的命令来设置一个新的 Go 项目:



现在,打开 main.go,作为第一步,将需要的东西的框架放入其中:



是的,这还没有编译。但是我们这里有一个 Agent,它可以访问 anthropic.Client(默认情况下,它会查找 ANTHROPIC_API_KEY),并且可以通过从终端上的 stdin 读取来获取用户消息。


现在让我们添加缺少的 Run() 方法:



这并不多,对吧?90 行代码,而其中最重要的就是 Run() 中的这个循环,它让我们能够与 Claude 对话,但这已经是这个程序的核心了。


对于一个核心来说,这个过程相当简单:我们首先打印一个提示,询问用户输入内容,将其添加到对话中,发送给 Claude,然后将 Claude 的回复添加到对话中,打印出回复,然后再循环进行。


你日常使用的 AI 聊天应用其实就是这样的,只不过这是在终端中实现的。


运行它:



然后你可以和 Claude 对话了,就像这样:



注意到我们在多个回合中保持了同一个对话吗?它记住了我们在第一条消息中的名字。每次回合对话都在增长,我们每次都发送整个对话。服务器——准确来说是 Anthropic 的服务器——是无状态的。它只看到 conversation 片段中的内容,维护这一点由我们来负责。


现在继续,因为输出结果很糟糕,这还不是一个智能体。什么是智能体?可以这样定义:一个具有访问工具能力的大语言模型(LLM),这些工具使其能够修改上下文窗口之外的内容。


添加工具


一个具有工具访问能力的大语言模型(LLM)是什么呢?


工具的定义是这样的:你向模型发送一个 prompt,告知它在想要使用「工具」时应以特定方式回复。然后,你接收消息后「使用工具」执行该指令,并返回结果。其他一切都是在这一基础上进行的抽象。


想象一下,你正在与朋友交谈,你告诉他们:「在接下来的交流中,如果你想让我举起手臂,就眨眼。」这种表达方式虽然有些奇怪,但概念非常容易理解。


我们已经能够在不改变任何代码的情况下尝试这种方法。



我们告诉 Claude,当它想知道天气时,就用 get_weather 来「眨眼」。接下来的步骤是举起我们的手臂,并回复「工具的结果」。



第一次尝试非常成功!


这些模型经过训练和微调,能够使用「工具」,并且非常注重利用这些工具。到 2025 年,它们在一定程度上「知道」自己不具备所有信息,因此可以借助工具获取更多信息。(虽然这不是完全准确的描述,但目前这个解释足够了。)


总结关于工具使用的关键点有:



为简化步骤(1),大型模型提供商已经内置了 API,用于发送工具定义。


现在,让我们开始构建我们的第一个工具:read_file。


read_file 工具


为了定义 read_file 工具,我们将使用 Anthropic SDK 建议的类型,但请记住:在底层,这一切最终都会变成发送给模型的字符串。这一切都是「如果你希望我使用 read_file,就眨眼」。


我们要添加的每个工具都需要以下内容:


• 名称

• 描述,告诉模型这个工具的功能、何时使用、何时不使用、返回什么等等。

• 输入模式,描述为 JSON schema,说明该工具期望什么输入以及输入的形式。

• 一个实际执行工具的函数,使用模型发送给我们的输入并返回结果。


那么让我们把这些添加到我们的代码中。



现在我们给出 Agent 工具定义:



并将它们发送到 runInference 中的模型:



用户发送工具定义,Anthropic 在服务器上将这些定义包装在这个系统提示中(并不多),然后将其添加到对话中,如果模型想要使用该工具,它就会以特定的方式回复。


好的,所以工具定义正在发送,但我们还没有定义任何工具。让我们来定义 read_file 工具。



这并不多,是不是?这只是一个函数,ReadFile,以及模型将看到的两个描述:一个是描述工具本身的 Description(Read the contents of a given relative file path. ...),另一个是该工具拥有的单一输入参数的描述(The relative path of a ...)。


ReadFileInputSchema 和 GenerateSchema 之类的工作是做什么的?我们需要这些来为工具定义生成一个 JSON 模式(schema),然后发送给模型。为此,我们使用 jsonschema 包,需要进行导入和下载:



然后运行以下命令:


    go mod tidy


    然后,在 main 函数中,我们需要确保我们使用定义:



    是时候尝试一下了!



    哇哦,它想要使用这个工具!显然,你的输出可能会有些不同,但听起来 Claude 确实知道它可以读取文件,对吧?


    问题是我们没能聆听!当 Claude 给出提示时,我们没有去注意这一点,我们需要解决这个问题。


    通过一个简单、快捷且异常敏捷的动作,我们可以通过替换智能体的 Run 方法来实现:



    可以说,这段过程 90% 是固定格式,只有 10% 是关键部分:当我们从 Claude 收到消息时,我们会检查 Claude 是否要求我们执行某个工具,通过查看内容的类型是否为「tool_use」来判断;如果是这样,我们就交给 executeTool 处理,在本地注册表中通过名称查找该工具,解析(unmarshal)输入,执行它,并返回结果。如果出现错误,我们会翻转一个布尔值。就是这样。


    (是的,的确有一个循环套在另一个循环里,但这不重要。)


    我们执行工具,将结果发回给 Claude,然后再次请求 Claude 的响应,就是这么简单。


      echo 'what animal is the most disagreeable because it always says neigh?' >> secret-file.txt


      这会在我们的目录中生成一个名为 secret-file.txt 的文件,里面包含一个神秘的谜题。


      就在同一个目录中,我们运行新的工具使用智能体,要求它查看该文件:



      你只需要给它一个工具,它就会在认为有助于解决任务时使用它。我们没有说「当用户询问文件时,阅读文件」,也没有说「如果某个东西看起来像是文件名,找出如何读取它」。我们说的是「帮我解决这个文件里的问题」,Claude 就意识到它可以读取文件来回答这个问题,然后就去做了。


      当然,我们可以加以具体引导并鼓励使用某个工具,但它基本上可以自主完成这些任务:



      作者接下来还介绍了添加 list_files(列出文件的工具)和 edit_file(让 Claude 编辑文件的工具)的方法,感兴趣的读者可以阅读博客原文。


      © THE END 

      转载请联系本公众号获得授权

      投稿或寻求报道:liyazhou@jiqizhixin.com

      阅读原文

      跳转微信打开

      Fish AI Reader

      Fish AI Reader

      AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

      FishAI

      FishAI

      鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

      联系邮箱 441953276@qq.com

      相关标签

      编程智能体 Go语言 LLM 开源
      相关文章