Eric's Blog 时光荏苒,岁月如梭

从零开始理解如何制作自己的 AI 助手

2026-02-25
Eric Wong

大约一年前,我开始关注 AI 相关的内容。从一开始的简单代码补全,到后来的文本对话,再到工具调用,新技术层出不穷,确实令人兴奋。 但最近我发现,有些人刻意制造新概念,试图将它们包装成新技术来吸引流量,这让我感到十分反感。

于是,我决定从零开始学习 AI 相关知识,并着手开发 AI 相关的 Neovim 插件。 整个过程踩了不少坑,但也逐渐理解了用户与 AI 之间的沟通逻辑。 因此,我想把这些内容整理成文字,帮助大家更好地理解用户与 AI 沟通时的底层逻辑, 同时也便于区分什么是真正的新技术,什么是人为包装的伪概念。

那就从简单的 DeepSeek 官网开发者文档 开始吧。

与服务器互动的基本原理

与大模型之间的沟通,通常是通过 API 请求完成的。比如向 DeepSeek 发送一句 Hello!,实际上执行的命令是:

curl https://api.deepseek.com/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \
  -d '{
        "model": "deepseek-chat",
        "messages": [
          {"role": "system", "content": "You are a helpful assistant."},
          {"role": "user", "content": "Hello!"}
        ],
        "stream": false
      }'

得到的回复大致如下:

{
  "id": "930c60df-bf64-41c9-a88e-3ec75f81e00e",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "Hello! How can I help you today?",
        "role": "assistant"
      }
    }
  ],
  "created": 1705651092,
  "model": "deepseek-chat",
  "object": "chat.completion",
  "usage": {
    "completion_tokens": 10,
    "prompt_tokens": 16,
    "total_tokens": 26
  }
}

为了方便展示,我移除了一些额外内容,只保留核心部分。实际上发送给服务器的消息数据是:

[
  { "role": "system", "content": "You are a helpful assistant." },
  { "role": "user", "content": "Hello!" }
]

而得到的回复也是一个单独的消息:

{
  "role": "assistant",
  "content": "Hello! How can I help you today?"
}

此时,如果我们想要保留会话历史并继续发送内容 What's the weather in SF?,就需要将服务器返回的消息追加到消息列表中,然后添加新的用户消息。于是,我们发送给服务器的消息变成这样:

[
  { "role": "system", "content": "You are a helpful assistant." },
  { "role": "user", "content": "Hello!" },
  { "role": "assistant", "content": "Hello! How can I help you today?" },
  { "role": "user", "content": "What's the weather in SF?" }
]

服务器除了返回文本内容外,有时还会返回 tool_call。这意味着返回的 JSON 中包含要调用的函数名称和参数,你收到的消息大致如下:

{
  "id": "call_123abc",
  "type": "function",
  "function": {
    "name": "get_weather",
    "arguments": "{\"location\": \"San Francisco\", \"unit\": \"celsius\"}"
  }
}

然后,你的助手软件实际上会做的是:根据这个 tool_call 内容调用对应的本地功能函数, 执行完成后,将结果连同上面的 tool_call 一起再次“自动”发送给服务器。 于是,发送给服务器的消息大致如下:

[
  { "role": "system", "content": "You are a helpful assistant." },
  { "role": "user", "content": "Hello!" },
  { "role": "assistant", "content": "Hello! How can I help you today?" },
  { "role": "user", "content": "What's the weather in SF?" },
  {
    "role": "assistant",
    "tool_calls": [
      {
        "id": "call_123",
        "type": "function",
        "function": {
          "name": "get_weather",
          "arguments": "{\"location\": \"San Francisco\"}"
        }
      }
    ]
  },
  {
    "role": "tool",
    "tool_call_id": "call_123",
    "content": "{\"temperature\": 18, \"conditions\": \"Sunny\", \"humidity\": 65}"
  }
]

服务器给你返回的内容如果任然是 tool_call 那么就可以继续调用本地工具执行完成后返回给服务器。 这样的“自动”请求步骤循环下去,就形成了一个自动化的智能助手假象。

直到服务器返回的内容不再是 tool_call 而是 content,就可以将内容前台展示给用户了:

{
  "role": "assistant",
  "content": "The weather in San Francisco is currently 18°C and sunny with 65% humidity."
}

以上内容就是一个最基本的智能助手低层网络请求的逻辑。

消息角色(role)

从上面的请求消息内容可以看到,消息的角色(role)目前有四种:systemuserassistanttool

各角色详解:

user:这是用户输入的内容,对应聊天界面中输入框输入的信息。

assistant:服务器返回的内容,有两种形式:

  1. content:文本消息内容,直接显示在聊天界面
  2. tool_call:函数调用指令,告诉客户端需要执行什么功能

tool:当客户端收到 tool_call 后,执行相应功能并将结果以 tool 角色发送给服务器。

system:(这里需要重点澄清) 很多应用没有提供设置 system 角色的界面,但这个角色不是简单的“底层内容”,而是对话的“基础指令集”。它的主要作用是:

  1. 设定助手的行为准则:如”你是一个专业的编程助手”
  2. 定义回答风格:如”用简洁的语言回答,避免冗长”
  3. 设置安全边界:如”不回答涉及暴力、违法内容的问题”
  4. 提供上下文信息:如”当前项目使用 TypeScript 5.0”

一个标准的 system 消息示例:

{
  "role": "system",
  "content": "你是一个专业的软件开发助手。回答问题时请提供代码示例,并解释关键概念。如果用户的问题涉及不道德或违法内容,请礼貌拒绝。"
}

那些”新概念”文件到底是什么?

我开头所说的伪新概念,指的是目前在社区中流传的各种”配置文件”,比如:

实际存在的配置文件

AGENTS.md

  • 实际用途:为AI编码代理提供项目上下文和指令
  • 类比:项目的”README for agents”
  • 现状:已被6万多个开源项目使用,确实有实际价值
  • 示例内容:项目结构、构建命令、编码规范等

CLAUDE.md

  • 实际用途:Claude Code的配置文件,定义AI子代理的行为
  • 位置:通常位于 .claude/ 目录下
  • 功能:配置工具调用、代码风格偏好等

过度包装的概念

SOUL.md(灵魂文件)

  • 宣称功能:定义AI代理的”性格”、”价值观”、”沟通风格”
  • 实际本质:就是加了营销术语的 system 指令
  • 示例:原本的 system 消息换个文件名就成了”灵魂”

SKILLS.md(技能文件)

  • 宣称功能:列出AI能执行的所有”技能”
  • 实际本质:工具函数(tool_call)的文档化列表
  • 问题:与代码中的工具定义重复,维护成本高

如何看待这些概念

文件类型 实际价值 创新程度
AGENTS.md 中等(提供了标准化格式)
CLAUDE.md 低(平台特定配置)
SOUL.md 极低(换名不换药)
SKILLS.md 极低(文档化工具列表)

核心观点

  1. 技术本质没变:这些文件底层还是通过 system 消息或工具定义来实现
  2. 创新 vs 包装
    • 真创新:AGENTS.md 提供了标准化的项目上下文传递方式
    • 伪概念:SOUL.md 等只是给现有技术换了个好听的名字
  3. 开发建议
    • 使用 AGENTS.md 提升AI编码效率 ✓
    • 不要被”灵魂”、”技能”等营销术语迷惑 ✗
    • 理解底层的 systemtool_call 机制才是关键

实际开发中的选择

# 推荐的配置方式

## 1. 核心配置(必需)

- `system` 消息:定义助手基本行为
- 工具函数:实际可用的功能

## 2. 项目配置(推荐)

- AGENTS.md:项目级AI辅助配置

## 3. 避免过度设计

- 不需要 SOUL.md、SKILLS.md 等冗余文件
- 保持配置简洁,避免维护负担

真正的技术创新应该解决实际问题,而不是发明新名词。理解了消息传递的底层机制,就能一眼看穿哪些是真正有用的工具,哪些只是华丽的包装。


版权声明:本文为原创文章,遵循 署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)版权协议,转载请附上原文出处链接和本声明。


分享到:

评论

目录