如何用Python控制米家智能设备 - 完整指南

背景

米家(小米智能家居)是国内最大的IoT平台之一,支持数千种智能设备。很多用户希望能通过编程方式控制这些设备,而不仅限于使用米家App。

本文是作者实际打通米家设备控制的完整记录,包括技术方案、踩坑总结、安全分析等。无论你是想学习IoT控制,还是想自己搭建智能家居系统,本文都能提供有价值的参考。


一、米家设备控制的技术原理

1.1 MiIO vs MIoT 协议

通过搜索发现,米家设备主要使用两种协议:

协议名称设备类型特点
miIO传统协议旧设备需要手动探索控制方式
MIoT现代协议新设备自动获取设备规格(更先进)

关键发现:python-miio官方文档明确指出:

"Most modern (MIoT) devices are automatically supported by the generic miot integration. Internally, it uses miot spec files to find out about supported features..."

翻译:大多数现代(MIoT)设备被generic miot集成自动支持。内部使用miot spec文件来获取支持的功能。

1.2 miot-spec.com 设备规格网站

通过搜索发现有一个关键网站:home.miot-spec.com(米家设备规格数据库)

这是米家设备的"身份证",记录了各种设备的siid/aiid/piid对应关系。

1.3 设备模型:服务-属性-操作

MiIO/MIoT协议的核心是服务-属性-操作模型:

设备 (Device)
├── 服务1 (siid=1: 设备信息)
│   ├── 属性 (piid=1: 设备名称)
│   └── 属性 (piid=2: 固件版本)
├── 服务2 (siid=2: 电源)
│   ├── 属性 (piid=1: 开关状态: on/off)
│   ├── 操作 (aiid=1: 打开)
│   └── 操作 (aiid=2: 关闭)
├── 服务3 (siid=3: 灯光)
│   ├── 属性 (piid=1: 亮度: 0-100)
│   └── 操作 (aiid=1: 设置亮度)
└── ...
  • siid (Service ID):服务ID,设备的功能模块(电源、灯光、马达等)
  • piid (Property ID):属性ID,服务的属性(状态、数值等)
  • aiid (Action ID):操作ID,服务的可执行动作(开、关、开始、停止等)

1.4 厂商实现差异(核心问题)

这是打通设备控制的核心问题:不同厂商对协议的实现差异巨大。

厂商设备类型siid=2的定义aiid=1paramsaiid=3
石头科技扫地机器人电源服务开始清扫[]暂停
Yeelight智能灯电源服务打开["on"]关闭
云米空气净化器电源服务打开["on"]关闭
追觅吸尘器电源服务打开[1]关闭

可以看到:即使是同一个"开"功能:

  • 石头科技:用 aiid=1,params=[](空数组)
  • Yeelight:用 aiid=1,params=["on"](字符串)
  • 追觅:用 aiid=1,params=[1](数字)

这正是用API控制的难点所在。


二、调研过程

2.1 搜索方法

本次调研使用了以下搜索渠道:

  1. GitHub搜索:搜索Python库的stars数和功能介绍
  2. 官方文档分析:分析python-miio官方文档(python-miio.readthedocs.io)
  3. 设备规格网站:发现miot-spec.com设备规格数据库
  4. 实际测试:在真实设备上测试控制命令

2.2 搜索结果

库/资源来源关键信息
python-miioGitHub (4189 stars)支持MIoT自动获取设备规格
mijia-apiGitHub (506 stars)封装了登录和设备操作
miot-spec.com网站设备规格数据库

2.3 python-miio的设备发现机制

通过搜索python-miio官方文档,发现其设备发现机制:

  1. mDNS发现:通过mDNS自动发现局域网设备,获取设备类型信息
  2. Handshake发现:通过握手获取设备token,但无法获取设备类型
  3. 云端获取:通过micloud从云端获取所有设备的token

官方文档说明:

"The miiocli tool can fetch the tokens from the cloud if you have micloud package installed.
Executing the command will prompt for the username and password, as well as the server locale to use for fetching the tokens."

2.4 两种方案的详细对比

特性mijia-apipython-miio
协议支持MiIOMiIO + MIoT
设备发现云端获取局域网发现 + 云端获取
控制参数需手动探索自动获取
学习曲线简单较陡
维护状态个人维护社区活跃
适用场景快速上手深度定制

建议

  • 新手入门:选mijia-api
  • 需要支持大量设备:选python-miio

三、技术实现

3.1 环境准备

# 安装依赖
pip install mijiaAPI qrcode pillow

3.2 扫码登录(mijia-api方式)

重要:login()会阻塞120秒,需要保持进程活着!

from mijiaAPI import mijiaAPI

api = mijiaAPI()

# login()会阻塞120秒,等待扫码
# 需要保持进程活着,扫码后服务器轮询确认
result = api.login()

if result:
    print("登录成功!")
    # result包含: serviceToken, passToken, userId, expireTime
    print(f"用户ID: {result.get('userId')}")
    print(f"过期时间: {result.get('expireTime')}")
else:
    print("登录失败")

3.3 获取设备列表

devices = api.get_devices_list()

for d in devices:
    print(f"设备名称: {d.get('name')}")
    print(f"设备ID: {d.get('did')}")  # 控制用
    print(f"设备型号: {d.get('model')}")  # 查询规格用
    print(f"在线状态: {d.get('online')}")
    print("---")

3.4 控制设备

# 格式说明
action = {
    "did": "设备ID",      # 设备的唯一标识(从设备列表获取)
    "siid": 服务ID,       # 功能模块(2=电源,3=灯光等)
    "aiid": 操作ID,        # 具体操作(1=开,2=关等)
    "params": [参数]      # 操作参数
}

result = api.run_action(action)

# 返回格式
# 成功: {"code": 0, "message": "成功", "exe_time": 10}
# 失败: {"code": -704040005, "message": "Action不存在"}

3.5 获取设备属性

# 获取设备属性
props = api.get_devices_prop([
    {"did": "设备ID", "siid": 2, "piid": 1}
])
# 返回: {"did": "xxx", "siid": 2, "piid": 1, "value": "on", "code": 0}

3.6 设置设备属性

# 设置设备属性
props = api.set_devices_prop([
    {"did": "设备ID", "props": {"power": "on"}}
])

3.7 完整示例:获取所有设备并分类

from mijiaAPI import mijiaAPI

api = mijiaAPI()
api.login()

devices = api.get_devices_list()

# 按类型分类
lights = []
vacuums = []
others = []

for d in devices:
    model = d.get('model', '')
    if 'light' in model or '灯' in d.get('name', ''):
        lights.append(d)
    elif 'vacuum' in model or '扫地' in d.get('name', ''):
        vacuums.append(d)
    else:
        others.append(d)

print(f"灯: {len(lights)}个")
for l in lights:
    print(f"  - {l.get('name')}: {l.get('did')}")

print(f"扫地机器人: {len(vacuums)}个")
for v in vacuums:
    print(f"  - {v.get('name')}: {v.get('did')}")

print(f"其他设备: {len(others)}个")

四、封装成REST API服务

4.1 完整示例

from flask import Flask, request, jsonify
from mijiaAPI import mijiaAPI
import threading
import qrcode

app = Flask(__name__)
mi_api = None

def generate_qr(url):
    """生成二维码"""
    qr = qrcode.QRCode(version=1, box_size=10, border=5)
    qr.add_data(url)
    qr.make(fit=True)
    img = qr.make_image(fill_color="black", back_color="white")
    img.save("static/mijia-login-qr.png")

def do_login():
    """后台登录"""
    global mi_api
    mi_api = mijiaAPI()
    try:
        result = mi_api.login()
        print(f"登录结果: {result is not None}")
    except Exception as e:
        print(f"登录错误: {e}")

@app.route("/login", methods=["POST"])
def login():
    """触发扫码登录"""
    global mi_api
    
    if mi_api is not None:
        return jsonify({"message": "已登录"})
    
    # 启动后台登录线程
    login_thread = threading.Thread(target=do_login)
    login_thread.start()
    
    return jsonify({
        "message": "请在120秒内用米家APP扫码",
        "qr_url": "/static/mijia-login-qr.png"
    })

@app.route("/devices")
def devices():
    """获取设备列表"""
    if not mi_api:
        return jsonify({"error": "请先登录"}), 401
    return jsonify(mi_api.get_devices_list())

@app.route("/control", methods=["POST"])
def control():
    """控制设备"""
    if not mi_api:
        return jsonify({"error": "请先登录"}), 401
    
    data = request.json
    result = mi_api.run_action({
        "did": data["did"],
        "siid": data["siid"],
        "aiid": data["aiid"],
        "params": data.get("params", [])
    })
    return jsonify(result)

@app.route("/status")
def status():
    """检查登录状态"""
    return jsonify({"logged_in": mi_api is not None})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)

4.2 客户端调用示例

# 登录
curl -X POST http://localhost:8080/login

# 获取设备
curl http://localhost:8080/devices

# 开灯
curl -X POST http://localhost:8080/control 
  -H "Content-Type: application/json" 
  -d '{"did": "123456", "siid": 2, "aiid": 1, "params": ["on"]}'

# 关灯
curl -X POST http://localhost:8080/control 
  -H "Content-Type: application/json" 
  -d '{"did": "123456", "siid": 2, "aiid": 1, "params": ["off"]}'

五、踩坑记录与解决方案

5.1 常见错误代码

错误代码含义原因解决
-704040005Action不存在siid或aiid错误尝试其他组合
-705201023Property不可写属性只读使用action而非property
-8data type not validparams参数类型错误检查params格式:字符串/数字/数组
-4008设备不在线设备离线检查设备网络
-401未登录token失效重新扫码登录

5.2 探索设备命令的方法

对于mijia-api这种库,需要手动探索siid/aiid组合:

def explore_device(api, device_id):
    """探索设备的控制命令"""
    results = []
    
    print(f"开始探索设备: {device_id}")
    
    for siid in range(1, 20):
        for aiid in range(1, 20):
            # 尝试不同的参数
            params_list = [
                [],              # 空数组
                ["on"],          # 字符串开
                ["off"],         # 字符串关
                [1],             # 数字开
                [0],             # 数字关
                ["toggle"],      # 切换
            ]
            
            for params in params_list:
                try:
                    result = api.run_action({
                        "did": device_id,
                        "siid": siid,
                        "aiid": aiid,
                        "params": params
                    })
                    
                    if result.get("code") == 0:
                        finding = {
                            "siid": siid,
                            "aiid": aiid,
                            "params": params,
                        }
                        results.append(finding)
                        print(f"✅ 成功! {finding}")
                        
                except Exception as e:
                    pass
    
    print(f"探索完成,找到 {len(results)} 个有效命令")
    return results

5.3 已验证的命令

设备siidaiidparams功能
落地灯21["on"]
落地灯21["off"]
扫地机器人21[]开始清扫
扫地机器人22[]回充
扫地机器人23[]停止/暂停

六、问题分析:为什么用API控制这么复杂?

6.1 米家APP帮用户做了什么

用户用米家App控制设备时,不需要关心siid/aiid/params,因为APP已经封装好了。APP内部维护了每个设备的控制参数映射表,用户只需要点击"开/关"按钮。

6.2 用API控制的问题

用Python API控制时:

  • 没有封装:需要自己处理协议细节
  • 文档缺失:厂商不会公开siid/aiid的对应关系
  • 每个设备不同:即使是同一功能,控制参数也不同
  • 没有统一标准:各厂商按自己的理解实现

这解释了为什么用Python API控制比用App复杂很多倍——因为App帮用户屏蔽了所有这些复杂性。

6.3 更好的方案选择

通过搜索发现,python-miio 提供了更先进的方案:

  1. 自动获取设备规格:MIoT设备自动从miot-spec.com下载规格
  2. 命令行工具:miiocli可以直接控制设备
  3. 无需手动探索:库自动处理siid/aiid
  4. 设备发现:自动发现局域网内的设备

七、安全分析

7.1 token机制

扫码登录后获取的token包含:

  • serviceToken:API调用凭证,有效期数月到数年
  • passToken:用户验证凭证
  • userId:用户标识

7.2 风险评估

理论风险

  • 拿到token可以调用API控制设备
  • 可以获取设备列表
  • 可以执行已创建的场景

实际情况

  • token有有效期(较长)
  • 可能与服务IP绑定(社区讨论多,缺乏权威资料)
  • 官方可以强制下线

7.3 防护建议

  1. 不暴露token:不要提交到GitHub或发到群里
  2. 定期检查:米家App → 设置 → 账号与安全 → 登录设备
  3. 异常处理:发现异常立即修改密码并重新登录
  4. 最小权限:测试用小号,不要用主要账号

7.4 紧急处理

如果怀疑token泄露:

  1. 修改小米账号密码
  2. 米家App退出所有设备登录
  3. 重新扫码获取新token

八、实际应用场景

8.1 定时任务

import schedule
import time
from mijiaAPI import mijiaAPI

def morning_routine():
    """早间routine"""
    api = mijiaAPI()
    api.login()
    
    # 开灯
    api.run_action({"did": "灯ID", "siid": 2, "aiid": 1, "params": ["on"]})

def night_routine():
    """晚间routine"""
    api = mijiaAPI()
    api.login()
    
    # 关灯
    api.run_action({"did": "灯ID", "siid": 2, "aiid": 1, "params": ["off"]})
    # 扫地机器人回充
    api.run_action({"did": "机器人ID", "siid": 2, "aiid": 2, "params": []})

# 设置定时
schedule.every().day.at("07:00").do(morning_routine)
schedule.every().day.at("22:00").do(night_routine)

while True:
    schedule.run_pending()
    time.sleep(60)

8.2 命令行工具

#!/usr/bin/env python3
import sys
from mijiaAPI import mijiaAPI

COMMANDS = {
    "on": {"siid": 2, "aiid": 1, "params": ["on"]},
    "off": {"siid": 2, "aiid": 1, "params": ["off"]},
    "start": {"siid": 2, "aiid": 1, "params": []},
    "stop": {"siid": 2, "aiid": 3, "params": []},
    "return": {"siid": 2, "aiid": 2, "params": []},
}
def main():
    if len(sys.argv) < 3:
        print("用法: miot <设备ID> <命令>")
        print(f"可用命令: {list(COMMANDS.keys())}")
        sys.exit(1)
    
    did = sys.argv[1]
    cmd = sys.argv[2].lower()
    
    if cmd not in COMMANDS:
        print(f"未知命令: {cmd}")
        sys.exit(1)
    
    api = mijiaAPI()
    action = COMMANDS[cmd].copy()
    action["did"] = did
    
    result = api.run_action(action)
    
    if result.get("code") == 0:
        print("成功!")
    else:
        print(f"失败: {result.get('message')}")

if __name__ == "__main__":
    main()

使用:

python miot.py 123456789 on   # 开灯
python miot.py 123456789 off  # 关灯
python miot.py 123456789 start # 开始清扫

九、总结

9.1 核心要点

  1. 协议层面:MiIO(传统)和MIoT(现代)两种协议,后者支持自动获取设备规格
  2. 方案层面

    • mijia-api:需要手动探索siid/aiid,上手简单
    • python-miio:自动获取,更先进但学习曲线较陡
  3. 搜索发现:miot-spec.com是关键的设备规格数据库
  4. 核心问题:厂商实现差异大,没有统一标准,导致控制参数需要逐一探索
  5. 安全层面:token机制存在风险,建议做好防护
  6. 应用层面:可封装REST API、命令行工具,定时任务等多种形式

9.2 下一步建议

  1. 尝试python-miio方案,体验自动获取设备规格
  2. 探索更多设备的控制命令,丰富命令库
  3. 搭建完整的智能家居控制系统

参考资料

  • GitHub - python-miio (4189 stars)
  • GitHub - mijia-api (506 stars)
  • python-miio官方文档 (python-miio.readthedocs.io)
  • miot-spec.com 设备规格网站

本文由作者 twg2020 创作,使用 AI 辅助润色
首发于:somingbai.com

NLCC:用自然语言编写代码的完整系统

NLCC = Natural Language Code Compiler

专业级自然语言编译器,将自然语言描述编译为可执行代码,并提供完整的可视化开发环境


目录

  1. 设计哲学
  2. 核心架构
  3. 技术规格
  4. Web可视化界面
  5. 自动化构建系统
  6. 实践指南
  7. 技术演化

设计哲学

核心洞察:代码是Cheap的 + 架构确定性

在AI辅助编程的时代,两个根本性变化决定了新的开发范式:

变化1:成本结构倒置

  • 代码生成:便宜(AI几秒生成几百行)
  • AI理解成本:昂贵(上下文窗口有限)
  • AI修改成本:极高(需要重新理解整个系统)

变化2:AI生成的不确定性

  • 同样的需求,AI每次生成的代码可能不同
  • AI可能产生微妙的bug,难以预测
  • 需要通过架构约束来保证正确性

新的成本函数

总成本 = AI生成代码的时间(低)
       + 人类review的时间(中)
       + AI修改迭代的时间(高)
       + 系统复杂度导致的AI错误率(极高)
       + 不确定性带来的质量风险(新增)

双重结论

  1. 牺牲代码复用 - 换取AI注意力的聚焦
  2. 架构确定性 - 用确定性对抗不确定性

为什么牺牲代码复用?

传统方式:追求代码复用

场景:统一错误处理

// src/common/error.rs
pub struct Error {
    code: i32,
    message: String,
    context: Option<Box<dyn Any>>,
}

pub fn error_handle(err: &Error);  // 超级通用的错误处理

传统优势

  • ✅ 只写一次错误处理逻辑
  • ✅ 统一的错误格式
  • ✅ 易于维护

AI时代的问题

让AI写使用Error的代码时:

AI的思维过程:
1. 需要处理错误
2. 用Error结构
3. Error有哪些字段?code、message、context...
4. context是什么类型?Option<Box<dyn Any>>?
5. 需要downcast吗?什么具体类型?
6. 有初始化函数吗?
7. 错误码是多少?
8. 要检查None吗?
...(AI注意力被分散到10个细节上)

AI实际生成(很可能出错):

fn network_send(&self, data: &str) {
    if send_failed {
        let mut err = Error {
            code: 1000,
            message: "send failed".to_string(),
            context: None,  // ❌ 不知道应该设置什么类型
        };
        error_handle(&err);  // ❌ 类型信息可能丢失
    }
}

AI方式:牺牲代码复用

// 不设计通用的Error结构

// src/network/impl.rs
fn network_send(&self, data: &str) {
    if send_failed {
        // 简单直接,网络模块自己的错误处理
        eprintln!("[network] send failed: {}", std::io::Error::last_os_error());
        if let Some(callback) = &self.error_callback {
            callback("send failed");
        }
    }
}

// src/storage/impl.rs
fn storage_write(&mut self, data: &str) {
    if write_failed {
        // 存储模块自己的错误处理(完全不同)
        eprintln!("[storage] write failed: {}", std::io::Error::last_os_error());
        if self.retry_count < 3 {
            self.retry_count += 1;
            self.storage_write(data);  // 自己的重试逻辑
        }
    }
}

AI生成这个

AI的思维过程:
1. 需要处理错误
2. eprintln!打印
3. 调用回调(如果有)
4. 完成

AI只需要关注3个细节,专注度高!

成本对比

传统方式(追求复用):

设计通用Error:4小时
AI出错率:30%
人类review:每个module 30分钟
修复时间:20分钟 × 3轮 = 60分钟

10个module总成本:4 + 15 = 19小时

AI方式(牺牲复用):

设计通用Error:0小时
AI出错率:5%
人类review:每个module 5分钟
修复时间:5分钟 × 1轮 = 5分钟

10个module总成本:0 + 1.6 = 1.6小时

代码重复:每个module都写eprintln!(但没关系!)

节省时间:17小时!

核心设计原则

1. 代码是cheap的,AI注意力是昂贵的

不惜增加代码量来降低每个模块的复杂度。用代码重复换取逻辑简单

2. 零循环依赖 + 抽象接口

  • modules/*/AGENTS.md 绝对禁止互相引用
  • 每个模块只依赖 include/ 中的抽象接口
  • 模块实现可以随意替换,不影响其他模块

3. 全量替换,而非修补

  • 传统开发:需求变更 → 在旧代码上打补丁 → 代码越来越乱
  • NLCC方式:需求变更 → 修改AGENTS.md → AI全量重新生成 → 旧代码物理删除
  • 优势:代码永远是干净的,没有历史包袱

4. 契约测试保障替换安全

  • 每个抽象接口有契约测试(Contract Test)
  • 只测试接口行为,不测试内部实现
  • AI生成新代码后,自动运行契约测试
  • 通过 → 替换成功;不通过 → AI修改或回滚

5. 自然语言描述意图,代码描述实现

  • AGENTS.md 描述"做什么"(意图)
  • skills/*.md 描述需求和约束(知识)
  • 生成的代码 是"怎么做"的实现(临时产物)

6. 按需加载,降低上下文消耗

  • 不是一次性加载所有MD
  • 根据当前任务动态加载相关模块
  • 降低AI的上下文窗口压力

7. MD是源码,代码是编译结果

  • 人类维护 modules/ 下的MD文档(源码)
  • build/ 下的代码是自动生成的(编译结果)
  • 需要修改功能?改MD,重新"编译"(生成)
  • 就像今天维护Rust代码,不关心生成的汇编

核心架构

目录结构设计

project/
├── AGENTS.md              # 顶层意图描述(main函数)
├── modules/
│   ├── logger/
│   │   ├── AGENTS.md      # 模块意图
│   │   └── skills/        # 按需加载的细节
│   │       ├── output.md
│   │       ├── thread_safety.md
│   │       └── json_format.md
│   ├── network/
│   │   ├── AGENTS.md
│   │   └── skills/
│   │       ├── http.md
│   │       └── ssl.md
│   └── storage/
│       ├── AGENTS.md
│       └── skills/
└── build/                 # AI生成的一次性代码
    ├── include/           # 公共接口层(零依赖区)
    │   ├── common_types.rs
    │   ├── logger.rs
    │   ├── network.rs
    │   └── storage.rs
    ├── src/               # 实现层
    │   ├── logger/
    │   │   ├── impl.rs
    │   │   └── internal.rs
    │   ├── network/
    │   └── storage/
    └── api.rs             # 唯一对外接口

依赖关系图

         ┌─────────────────┐
         │   AGENTS.md     │  ← 顶层意图
         │  (项目main函数)  │
         └────────┬─────────┘
                  ↓ 指向
         ┌────────┴─────────┐
         │ modules/*/AGENTS │  ← 模块意图
         │  - 清晰边界      │
         │  - 职责单一      │
         └────────┬─────────┘
                  ↓ 指向
         ┌────────┴─────────┐
         │ modules/*/skills │  ← 按需细节
         └────────┬─────────┘
                  ↓ NLCC编译
         ┌────────┴─────────┐
         │   build/include  │  ← 代码接口层
         │   build/src      │  ← 代码实现层
         └──────────────────┘

关键约束

  • modules/*/AGENTS.md 绝对禁止互相引用
  • skills/*.md 只能被对应的AGENTS.md引用
  • build/ 下的代码自动生成,手工修改会被覆盖

全量替换 + 契约测试机制

为什么需要全量替换?

传统开发的问题

需求变更 → 在旧代码上打补丁 → 发现边界情况 → 再打补丁
→ 代码越来越复杂 → 不敢动 → 技术债积累

NLCC的解决方案

需求变更 → 修改AGENTS.md → AI全量重新生成
→ 契约测试验证 → 物理删除旧代码 → 代码永远是干净的

示例:Logger模块从"文件日志"演进到"云端日志"

Step 1: 更新 modules/logger/AGENTS.md

## 功能定位(变更)
将日志发送到云端日志服务(如ELK),支持本地缓存和重试。

## 核心接口(保持不变)
pub fn logger_log(logger: &Logger, message: &str);
pub fn logger_set_level(logger: &mut Logger, level: LogLevel);

## 技术要求(新增)
- HTTP POST到 https://log-api.example.com/v1/write
- Header: X-Api-Key: {key}
- 失败时本地缓存,定时重试

## 细节文档(新增)
- [云端协议](skills/cloud_protocol.md)
- [重试策略](skills/retry_strategy.md)

Step 2: 补充 skills/cloud_protocol.md

## ELK日志协议

### Endpoint
POST https://log-api.example.com/v1/write

### 认证
X-Api-Key: your-api-key-here

### 格式

{
"timestamp": "2026-02-21T13:00:00Z",
"level": "INFO",
"message": "user logged in"
}


### 错误处理
- 429 Too Many Requests: 退避重试
- 5xx Server Error: 本地缓存,5分钟后重试

Step 3: AI全量重新生成

  • LLM读 AGENTS.md + skills/cloud_protocol.md
  • 生成全新的 cloud_logger_impl.rs
  • 旧代码的文件锁逻辑、临时文件逻辑直接物理删除
  • 新代码只包含当前需求的逻辑,干净

Step 4: 契约测试自动验证

# tests/test_logger_contract.py
def test_logger_contract():
    """
    任何Logger实现都必须通过这个测试
    不管它是写文件、发网络、还是打印到控制台
    """
    logger = create_logger()

    # 必须实现这些方法
    assert hasattr(logger, 'log')
    assert hasattr(logger, 'set_level')

    # 方法行为符合约定
    logger.log("test message")  # 不应抛异常
    logger.set_level("INFO")

    # 可观测性接口
    status = logger.get_status()
    assert 'healthy' in status

自动化工作流

AI生成新代码 → 自动运行契约测试
    ↓
  通过? → 替换成功,删除旧代码
    ↓
  不通过 → AI修改或回滚

优势对比

方面传统修补NLCC全量替换
代码复杂度越来越高保持简单
历史包袱累积无(物理删除)
理解成本需要理解历史只看当前需求
Bug修复可能引入新bug契约测试保障

提示词架构

NLCC采用AI原生提示词架构,让自然语言(Markdown文档)成为源码,代码成为编译后的中间产物。

1. AGENTS.md:MD文档的main函数

核心原则:每个AGENTS.md是唯一入口,描述"做什么",不描述"怎么做"。

项目级AGENTS.md

# AGENTS.md - 项目全局视图

## 项目背景
这是一个高性能网络服务器,支持并发连接和事件驱动架构。

## 核心功能
- 网络连接管理(TCP/SSL)
- 异步事件处理
- 日志记录
- 数据持久化

## 主要模块
- [logger/](modules/logger/AGENTS.md):日志记录模块
- [network/](modules/network/AGENTS.md):网络通信模块
- [storage/](modules/storage/AGENTS.md):数据存储模块

## 对外接口
应用通过`api.rs`提供统一的接口:

pub fn app_start();
pub fn app_stop();


## 设计原则
- 零循环依赖
- 编译期隔离
- AI注意力优先

模块级AGENTS.md

# Logger Module - AGENTS.md

## 功能定位
记录应用日志到文件和控制台,支持多种日志级别和输出格式。

## 核心接口

pub fn logger_log(logger: &Logger, message: &str);
pub fn logger_set_level(logger: &mut Logger, level: LogLevel);
pub fn logger_set_output(logger: &mut Logger, target: OutputTarget);


## 主要职责
1. 接收日志消息
2. 格式化输出(文本/JSON)
3. 写入目标(文件/控制台)
4. 线程安全保证

## 依赖
- 依赖:无(零依赖模块)
- 被依赖:network、storage

## 细节文档
- [输出策略](skills/output.md):如何支持多种输出格式
- [线程安全](skills/thread_safety.md):如何保证并发安全
- [性能优化](skills/performance.md):如何优化日志性能

## 注意事项
- 不要在这个模块中添加网络功能
- 不要阻塞主线程

2. Skills目录:按需加载的细节

核心原则:skills只描述意图和需求,不描述具体实现。

示例:logger/skills/json_format.md

# JSON格式日志输出

## 需求描述
日志需要支持JSON格式输出,便于日志收集和分析系统(如ELK)解析。

## 输出格式

{
"timestamp": "2026-02-15T10:30:00Z",
"level": "ERROR",
"module": "network",
"message": "Connection failed",
"context": {

"peer": "192.168.1.100:8080",
"error_code": 110

}
}


## 使用场景
- 生产环境日志收集
- 自动化日志分析
- 结构化查询

## 性能要求
- JSON序列化时间 < 100μs
- 不能阻塞主线程

## 不需要关心
- 具体用哪个JSON库(AI自己选择)
- 如何优化性能(AI自己考虑)

3. 按需加载策略

核心思想:不是一次性加载所有MD,而是根据AI的注意力范围动态加载。

场景1:AI生成logger模块代码

步骤1:读取 logger/AGENTS.md
→ AI理解模块的整体意图

步骤2:AGENTS.md引用了 skills/output.md
→ AI读取这个文件,了解输出需求

步骤3:AI开始生成代码
→ 只关注当前模块,不受其他模块干扰

场景2:AI需要理解logger如何被network使用

步骤1:读取 logger/AGENTS.md
→ 了解logger提供的接口

步骤2:读取 network/AGENTS.md
→ 发现network依赖logger

步骤3:按需加载 skills/json_format.md
→ 了解network需要JSON格式的日志

4. 接口演进管理

核心挑战:在零循环依赖的架构中,模块A(如logger)的接口变化会影响所有依赖它的模块(如network、storage)。如何管理这种"隐式"依赖变更的影响范围?

解决方案:语义化版本 + 自动影响分析

# logger/AGENTS.md

## 版本信息
- 当前版本: 2.0.0
- 变更类型: BREAKING CHANGE

## 接口变更历史
### v2.0.0 (2026-02-20)
- **破坏性变更**: `logger_log()` 签名从 `fn(logger, message)` 改为 `fn(logger, message, level)`
- **原因**: 支持动态日志级别
- **影响模块**: network, storage, testing
- **迁移指南**: 所有调用需要添加level参数

### v1.1.0 (2026-02-15)
- **新增功能**: 支持结构化日志(JSON格式)
- **向后兼容**: 是
- **影响模块**: 无(可选升级)

自动影响分析工具

# 分析logger接口变更的影响范围
$ nlcc analyze-impact logger --version 2.0.0

分析结果:
  依赖模块:
    ✓ network (依赖: logger_log)
    ✓ storage (依赖: logger_log, logger_flush)
    ✓ testing (依赖: logger_set_level)

  需要重新生成的模块:
    → network/impl.rs
    → storage/impl.rs
    → testing/impl.rs

  推荐操作:
    1. 先更新logger到v2.0.0
    2. 自动重新生成依赖模块
    3. 运行集成测试验证

增量构建策略

logger v2.0.0 发布
    ↓
自动检测依赖关系
    ↓
智能构建顺序:
  1. logger/impl.rs (首先构建)
  2. network/impl.rs (依赖logger)
  3. storage/impl.rs (依赖logger)
  4. app/impl.rs (依赖所有)
    ↓
自动运行回归测试
    ↓
验证通过 → 发布到生产

5. Skills冲突解决机制

核心挑战:当两个skill对同一模块提出冲突需求时,AI如何裁决?

示例冲突

# skills/performance.md
## 需求
- 使用内存池减少分配开销
- 缓存最近1000条日志

# skills/low_memory.md
## 需求
- 严格限制内存使用 < 10MB
- 不使用缓存

解决方案:优先级规则 + 显式冲突声明

# logger/AGENTS.md

## Skills优先级
1. **critical/** (关键约束,必须满足)
   - security.md
   - safety.md

2. **functional/** (功能需求,主要考虑)
   - output.md
   - format.md

3. **optimization/** (优化需求,权衡考虑)
   - performance.md
   - low_memory.md

## 冲突解决策略
当optimization/类skill冲突时:
- 优先满足functional/需求
- 在functional/约束内做最优权衡
- 在AGENTS.md中明确记录权衡决策

## 当前权衡决策
- **性能 vs 内存**: 选择低内存(优先级:functional/reliability.md)
- **延迟 vs 吞吐**: 选择低延迟(实时系统要求)

AI裁决流程

1. 读取所有skills
   ↓
2. 检测冲突需求
   ↓
3. 应用优先级规则
   - critical > functional > optimization
   ↓
4. 识别冲突类型
   - 直接冲突(A要求X,B要求not X)
   - 资源竞争(A要求CPU,B要求内存)
   ↓
5. 生成权衡决策
   - 在AGENTS.md中记录决策原因
   ↓
6. 生成代码时体现决策
   - 添加注释说明权衡点

示例:AI生成的权衡代码

// logger/impl.rs
// 权衡决策: 按照AGENTS.md中的优先级,
// 选择了低内存方案而非性能优化方案
// 原因: functional/reliability.md 要求在受限环境中运行

impl Logger {
    // 不使用缓存(满足low_memory.md)
    // 代价: 性能降低10%(可接受)
    pub fn log(&self, msg: &str) {
        self.write_direct(msg);  // 直接写入,无缓存
    }
}


技术规格

本章节将NLCC从设计理念转化为可实施的工程规格,明确核心概念、系统架构、接口定义和算法流程,为编译器开发提供详细的技术指导。

核心概念的形式化定义

1. "编译"的定义

NLCC编译器的形式化流程:

输入:自然语言意图(modules/下的Markdown文件集合)
  ↓
意图解析(MD → 结构化表示)
  ↓
上下文组装(按需加载AGENTS.md、skills/*.md、依赖接口)
  ↓
AI编排引擎(提示词工程 + LLM调用 + 结果解析)
  ↓
代码生成与验证(生成 → 编译 → 测试 → 迭代修正)
  ↓
输出:源代码文件(build/下的.rs/.go/.py等)

关键区别

  • 传统编译器:词法分析 → 语法分析 → 语义分析 → 代码生成
  • NLCC编译器:意图理解 → 上下文组装 → AI生成 → 自动验证

2. AGENTS.md的语法规范

为了让AI和工具能准确解析,定义轻量级的"意图描述语言"(IDL)规范:

必需章节结构

# <模块名称> - AGENTS.md

## 功能定位
[必填] 1-3句话描述模块的核心功能

## 核心接口
[必填] 使用标准化的伪代码格式定义接口

## 主要职责
[必填] 列表形式,3-7项

## 依赖
[必填] 明确声明依赖关系

## 细节文档
[必填] 引用skills/*.md文件

## 注意事项
[可选] 约束和限制

## Skills优先级
[可选] 定义冲突解决优先级

接口定义规范示例

pub fn logger_log(logger: &Logger, message: &str)
  // 记录日志消息
  // 线程安全:是
  // 阻塞:否

pub fn logger_set_level(logger: &mut Logger, level: LogLevel) -> Result<(), Error>
  // 设置日志级别
  // 线程安全:否,需要独占访问
  // 可能返回错误:如果级别无效

AI交互层设计

系统架构

┌──────────────┐
│ CLI/Web界面  │  ← 用户交互入口
└───────┬──────┘
        ↓
┌──────────────┐
│ 意图解析器   │  ← 解析AGENTS.md和skills/*.md
└───────┬──────┘
        ↓
┌──────────────┐
│ 上下文组装器 │  ← 按需加载依赖,组装提示词
└───────┬──────┘
        ↓
┌──────────────────────────────┐
│       AI编排引擎              │
│  提示词模板 → LLM → 结果解析 │
└───────────┬──────────────────┘
            ↓
┌──────────────────┐
│  代码生成与验证  │  ← 编译、测试、迭代
└───────────┬──────┘
            ↓
┌──────────────────┐
│  产物输出        │  ← 写入build/目录
└──────────────────┘

LLM调用策略

模型选择矩阵

任务类型推荐模型Token预算理由
意图理解GPT-4/Claude 3.54K需要深度理解
接口生成GPT-4/Claude 3.52K类型系统复杂
逻辑实现GPT-3.5/Claude Haiku4K标准算法
测试生成GPT-4/Claude 3.52K边界条件
代码修正GPT-3.5/Claude Haiku1K简单修复

提示词模板结构

1. 角色定义(你是一个...)
2. 任务描述(你需要生成...)
3. 约束条件(必须满足...)
4. 参考信息(根据以下意图...)
5. 输出格式(返回...)

上下文窗口管理

上下文组装算法

def assemble_context(module_name: str) -> Context:
    """
    策略:优先级队列 + Token预算
    """
    # 1. 加载AGENTS.md(必须)
    agents_md = load_agents_md(module_name)
    tokens_used = count_tokens(agents_md)
    
    # 2. 按优先级加载skills
    skills_refs = extract_skill_refs(agents_md)
    skills_md = ""
    
    for ref in skills_refs:
        skill_md = load_skill(ref.path)
        if tokens_used + count_tokens(skill_md) <= MAX_TOKENS:
            skills_md += f"\n## {ref.name}\n{skill_md}"
            tokens_used += count_tokens(skill_md)
    
    # 3. 加载依赖接口(摘要)
    dependencies = resolve_dependencies(module_name)
    interfaces_summary = load_interface_signatures(dependencies)
    
    return Context(
        agents_md=agents_md,
        skills_md=skills_md,
        dependencies=interfaces_summary
    )

多轮迭代修正

迭代生成流程

1. 生成代码
2. 编译验证
3. 测试验证
4. 如果失败 → 分析错误 → 重新生成
5. 重复直到成功或达到最大迭代次数(默认3次)

产物验证与质量保证

自动化验证流水线

层次1:编译验证
  ↓ 通过
层次2:单元测试
  ↓ 通过
层次3:集成测试
  ↓ 通过
层次4:安全扫描(允许警告)

影响范围分析

算法

  1. 检测变更类型(AGENTS.md / skills / 接口)
  2. 解析依赖图
  3. BFS传播影响
  4. 标记需要重新生成的模块
  5. 生成拓扑排序的构建顺序

开发工具链

CLI工具规范

nlcc init [project-name]          # 初始化项目
nlcc build [module-name]          # 编译模块
nlcc analyze-impact <file-path>   # 分析影响
nlcc serve [--port=3000]          # 启动Web界面
nlcc test [--coverage]            # 运行测试
nlcc check [--security]           # 代码检查

项目配置

# .nlcc/config.toml

[project]
name = "my-nlcc-project"
version = "0.1.0"

[compiler]
target_language = "rust"
default_model = "gpt-4"
max_context_tokens = 8000
max_iterations = 3

[build]
strategy = "auto"
parallel_jobs = 4

[testing]
enable_auto_tests = true
coverage_target = 80

[security]
enable_auto_scan = true

安全与伦理边界

提示词注入防护

检测可疑模式

  • "ignore instruction"
  • "forget above"
  • "new instruction"
  • HTML标签注入

防护措施

  1. 扫描并警告
  2. 自动清理危险内容
  3. 沙盒执行环境

沙盒执行

Docker隔离

  • 只读文件系统挂载
  • 禁止网络访问
  • 限制CPU和内存
  • 超时自动终止

开发路线图

Phase 1: MVP(2个月)

✅ 基础CLI工具
✅ 意图解析器
✅ 单一LLM调用
✅ Rust支持
✅ 编译验证

Phase 2: Beta(3个月)

✅ Skills系统
✅ 多轮迭代
✅ 测试生成
✅ 影响分析

Phase 3: v1.0(2个月)

✅ Web界面
✅ 多语言支持
✅ 安全审计
✅ 完整文档

Web可视化界面

界面布局

┌─────────────────────────────────────────────────────────────────┐
│  NLCC Web Studio                                          🔔 📊 │
├──────────┬──────────────────────────────────────────────────────┤
│          │                                                       │
│  📁 项目  │  📝 编辑器区                              👁️ 预览区  │
│  浏览器   │                                                       │
│          │  AGENTS.md - Logger Module                  impl.rs   │
│  ┌──────┐ │  ┌────────────────────────────────────┐  ┌────────┐│
│  │ AGENT│ │  │ # Logger Module                     │  │pub...  ││
│  │  .md │ │  │                                     │  │        ││
│  │      │ │  │ ## 功能定位                         │  │fn log  ││
│  └──────┘ │  │ 记录应用日志到文件和控制台...      │  │_logger ││
│    ↓      │  │                                     │  │(msg)   ││
│  ┌──────┐ │  │ ## 核心接口                         │  │{       ││
│  │skills│ │  │ ```rust                              │  │  ...   ││
│  │      │ │  │ pub fn logger_log(...);              │  │}       ││
│  └──────┘ │  │ ```                                 │  │        ││
│    ↓      │  │                                     │  │        ││
│  ┌──────┐ │  └────────────────────────────────────┘  └────────┘│
│  │build │ │                                                       │
│  │      │ │  ┌──────────────────────────────────────────────┐  │
│  └──────┘ │  │ 📊 状态面板                                 │  │
│          │  │                                              │  │
│          │  │ ✅ logger/AGENTS.md    hash: a1b2c3d4        │  │
│          │  │ ✅ logger/impl.rs      已生成 2024-02-19     │  │
│          │  │ ⏳ network/AGENTS.md   hash: e5f6g7h8       │  │
│          │  │ 🔄 network/impl.rs     需要重新生成          │  │
│          │  │                                              │  │
│          │  └──────────────────────────────────────────────┘  │
│          │                                                       │
│          │  ┌──────────────────────────────────────────────┐  │
│          │  │ 🔧 构建控制                                   │  │
│          │  │                                              │  │
│          │  │ 策略: [auto ▼]  一键构建: [🚀 Build All]     │  │
│          │  │                                              │  │
│          │  │ 进度: ████████░░ 80% (4/5 modules)            │  │
│          │  │                                              │  │
│          │  │ ✅ logger     ✅ storage   ✅ common         │  │
│          │  │ ✅ network   ⏳ testing                     │  │
│          │  │                                              │  │
│          │  └──────────────────────────────────────────────┘  │
└──────────┴──────────────────────────────────────────────────────┘

核心功能模块

1. 项目浏览器(左侧面板)

功能

  • 📁 树形显示项目结构
  • 🔍 搜索文件
  • 🏷️ 标签显示(已生成、需更新、冲突)
  • 📊 依赖关系图可视化

交互

  • 点击文件 → 在编辑器中打开
  • 右键文件 → 显示上下文菜单

    • 重命名
    • 删除
    • 查看历史
    • 对比版本

状态标识

📁 modules/
  📁 logger/
    ✅ AGENTS.md      (已生成,无变化)
    ✅ output.md
    ✅ thread_safety.md
    📄 impl.rs        (生成时间: 2024-02-19 10:30)

  📁 network/
    🔄 AGENTS.md      (源文件已变化,需重新生成)
    📄 impl.rs        (旧版本)

2. 实时代码编辑器(中间面板)

功能

  • 📝 Monaco Editor(VS Code同款)
  • 🎨 语法高亮(Markdown)
  • 🔍 实时预览(渲染后的Markdown)
  • 💾 自动保存(防丢失)
  • 📜 版本历史(可回滚)

自动保存机制

editor.onDidChangeModelContent(() => {
  // 防抖:停止输入1秒后自动保存
  debounce(() => {
    this.autoSave();
  }, 1000);
});

autoSave() {
  // 保存到服务器
  this.saveToServer();

  // 自动计算hash
  const newHash = this.calculateHash();

  // 自动更新状态
  this.updateModuleStatus(newHash);
}

辅助功能

  • 🤖 AI提示:当光标停在某个位置时,AI可以提供建议
  • 📖 文档悬浮:鼠标悬停在关键词上显示文档
  • 🔗 跳转:点击 [[network/AGENTS.md]] 自动跳转

3. 实时代码预览(右侧面板)

功能

  • 👁️ 预览生成的代码
  • 🔄 实时同步(编辑器变化时)
  • 📊 差异对比(新旧版本对比)

智能同步

// 当AGENTS.md变化时
onAGENTSMDChanged() {
  // 防抖:停止输入3秒后预览
  debounce(() => {
    // 调用AI生成预览(仅预览,不写入文件)
    this.previewGeneratedCode();
  }, 3000);
}

previewGeneratedCode() {
  // 显示加载动画
  this.showLoading();

  // AI生成(不保存)
  const previewCode = await this.ai.generatePreview(this.currentAGENTS);

  // 显示预览
  this.showPreview(previewCode);

  // 显示差异对比
  this.showDiff(this.oldCode, previewCode);
}

4. 状态监控面板(右下)

功能

  • 📊 实时显示所有模块状态
  • 🔔 自动通知(需要重新生成时)
  • 📈 构建统计

状态显示

┌────────────────────────────────────────┐
│ 📊 构建状态                            │
├────────────────────────────────────────┤
│                                         │
│ ✅ logger      已生成 2024-02-19 10:30 │
│ ✅ storage    已生成 2024-02-19 10:35 │
│ 🔄 network    需要重新生成              │
│ ⏳ testing    未生成                    │
│                                         │
│ 总计: 4/6 模块已生成                    │
│                                         │
└────────────────────────────────────────┘

5. 一键构建控制(底部面板)

功能

  • 🚀 一键构建所有模块
  • ⚙️ 策略选择(auto/always/preserve)
  • 📊 进度条显示
  • 📝 构建日志

构建按钮

<button onclick="buildAll()">
  🚀 构建所有模块
  <span class="badge">5 个需要更新</span>
</button>

<select id="strategy">
  <option value="auto">自动(推荐)</option>
  <option value="always">总是重新生成</option>
  <option value="preserve">保留手工修改</option>
</select>

构建流程可视化

🚀 开始构建...

✅ [1/6] logger       → 已是最新,跳过
⏳ [2/6] storage     → 正在生成...
   🤖 AI理解需求中...
   ✅ 代码生成完成
   ✅ 编译通过

🔄 [3/6] network     → 检测到源文件变化
   💾 已备份: network/impl.rs.backup
   🤖 AI理解需求中...
   ✅ 代码生成完成
   ✅ 编译通过

⏳ [4/6] testing     → 正在生成...
...

🎉 构建完成!成功: 6, 失败: 0, 跳过: 0

自动化构建系统

自动决策逻辑

实时监控系统

// 后台自动运行
class NLCCWebMonitor {
  constructor() {
    this.fileHashes = new Map();  // 缓存所有文件的hash
    this.watchers = new Map();    // 文件监控器
  }

  // 启动监控
  startWatching(projectPath) {
    // 扫描所有 AGENTS.md 和 skills/*.md
    const files = this.scanProject(projectPath);

    files.forEach(file => {
      const watcher = fs.watch(file.path, () => {
        this.onFileChanged(file);
      });
      this.watchers.set(file.path, watcher);
    });
  }

  // 文件变化时自动判断
  onFileChanged(file) {
    const newHash = this.calculateHash(file.path);
    const oldHash = this.fileHashes.get(file.path);

    if (newHash !== oldHash) {
      // 源文件变化
      this.fileHashes.set(file.path, newHash);

      // 自动标记需要重新生成
      this.markForRegeneration(file.module);

      // 通知前端:状态变化
      this.notifyFrontend({
        type: 'FILE_CHANGED',
        module: file.module,
        needsRegeneration: true
      });
    }
  }
}

完全无需人工决策

// 前端自动显示状态
class BuildStatusPanel {
  render() {
    const modules = this.getModuleStatus();

    modules.forEach(module => {
      if (module.hashChanged) {
        // 自动显示"需要重新生成"图标
        this.showIcon(module.name, '🔄 需要重新生成');
      } else if (module.implExists) {
        // 自动显示"已生成"图标
        this.showIcon(module.name, '✅ 已生成');
      } else {
        // 自动显示"未生成"图标
        this.showIcon(module.name, '⏳ 未生成');
      }
    });
  }
}

三种策略模式

1. auto(自动,默认)✅

行为

  • AGENTS.md不变 → 保留手工修改,跳过生成
  • AGENTS.md变化 → 重新生成,自动备份

界面显示

┌──────────────────────────────────┐
│ 策略: 自动                        │
├──────────────────────────────────┤
│ ✅ logger    AGENTS.md未变化      │
│    → 跳过,保留手工修改           │
│                                   │
│ 🔄 network  AGENTS.md已变化       │
│    → 重新生成,自动备份           │
│    💾 backup/impl.rs.20240219    │
└──────────────────────────────────┘

适用场景:日常开发

2. always(总是重新生成)🔄

行为

  • 总是重新生成,忽略手工修改
  • 不自动备份(或备份到临时目录)

界面显示

┌──────────────────────────────────┐
│ 策略: 总是重新生成                │
├──────────────────────────────────┤
│ 🔄 logger    强制重新生成         │
│    → 覆盖手工修改                 │
│                                   │
│ 🔄 network  强制重新生成          │
│    → 覆盖手工修改                 │
└──────────────────────────────────┘

适用场景

  • CI/CD
  • 发布前构建
  • 确保完全由AI生成

3. preserve(总是保留)🛡️

行为

  • 总是保留手工修改,不重新生成
  • 即使AGENTS.md变化

界面显示

┌──────────────────────────────────┐
│ 策略: 保留手工修改                │
├──────────────────────────────────┤
│ 🛡️ logger   保留手工修改         │
│    → 忽略 AGENTS.md 变化          │
│                                   │
│ 🛡️ network  保留手工修改         │
│    → 忽略 AGENTS.md 变化          │
└──────────────────────────────────┘

适用场景

  • 调试阶段
  • 极端性能优化
  • 手工修复关键bug

手工编辑区域保护

可视化标识

在代码编辑器中,用不同颜色标识不同区域:

// 🟢 AI生成的区域(绿色背景)
// ========== NLCC GENERATED BEGIN ==========
pub fn logger_log(logger: &Logger, message: &str) {
    eprintln!("[LOG] {}", message);
}
// ========== NLCC GENERATED END ==========

// 🟡 手工编辑区域(黄色背景,受保护)
// ========== MANUAL EDIT BEGIN (fast_log) ==========
pub fn fast_log(message: &str) {
    // 手工优化的特殊函数
    unsafe {
        // 直接系统调用
    }
}
// ========== MANUAL EDIT END ==========

重新生成时的行为

// 重新生成时
regenerate() {
  // 1. 读取当前代码
  const currentCode = fs.readFileSync('impl.rs', 'utf8');

  // 2. 提取手工编辑区域
  const manualSections = this.extractManualSections(currentCode);

  // 3. 生成新的AI代码
  const newAICode = await this.ai.generate(this.agentsMD);

  // 4. 合并:保留手工部分
  const finalCode = this.mergeCode(newAICode, manualSections);

  // 5. 写入文件
  fs.writeFileSync('impl.rs', finalCode, 'utf8');

  // 6. 通知前端
  this.notifyFrontend({
    type: 'CODE_REGENERATED',
    preserved: manualSections.length,
    regenerated: true
  });
}

智能通知系统

自动通知触发条件

// 通知触发器
const notificationTriggers = {
  // 1. 检测到源文件变化
  onSourceChanged: (module) => {
    this.showNotification({
      title: `${module} 需要重新生成`,
      message: '检测到 AGENTS.md 或 skills/*.md 变化',
      level: 'info',
      actions: [
        { label: '立即生成', primary: true, action: () => this.build(module) },
        { label: '查看差异', action: () => this.showDiff(module) }
      ]
    });
  },

  // 2. 构建成功
  onBuildSuccess: (module) => {
    this.showNotification({
      title: '构建成功',
      message: `${module} 已成功生成`,
      level: 'success',
      duration: 3000
    });
  },

  // 3. 构建失败
  onBuildFailed: (module, error) => {
    this.showNotification({
      title: '构建失败',
      message: `${module}: ${error.message}`,
      level: 'error',
      actions: [
        { label: '查看日志', action: () => this.showBuildLog(module) },
        { label: '重试', action: () => this.retryBuild(module) }
      ]
    });
  },

  // 4. 检测到冲突
  onConflictDetected: (module) => {
    this.showNotification({
      title: '检测到冲突',
      message: `${module} 的 impl.rs 有手工修改,但 AGENTS.md 也变化了`,
      level: 'warning',
      actions: [
        { label: '覆盖(备份)', primary: true, action: () => this.buildWithBackup(module) },
        { label: '保留手工', action: () => this.preserveManual(module) },
        { label: '查看对比', action: () => this.showDiff(module) }
      ]
    });
  }
};

依赖关系可视化

图形化显示

// 使用 D3.js 或 Cytoscape.js 渲染依赖图
class DependencyGraph {
  render(modules) {
    const nodes = modules.map(m => ({
      id: m.name,
      label: m.name,
      status: m.status,  // 'up-to-date', 'needs-update', 'error'
      dependencies: m.deps
    }));

    const edges = [];
    modules.forEach(m => {
      m.deps.forEach(dep => {
        edges.push({
          from: dep,
          to: m.name,
          label: 'depends on'
        });
      });
    });

    // 渲染图形
    this.graph = new Cytoscape({
      container: document.getElementById('dependency-graph'),
      elements: { nodes, edges },
      style: [
        {
          selector: 'node',
          style: {
            'background-color': (node) => {
              switch(node.data('status')) {
                case 'up-to-date': return '#4CAF50';
                case 'needs-update': return '#FF9800';
                case 'error': return '#F44336';
                default: return '#9E9E9E';
              }
            }
          }
        }
      ]
    });
  }
}

交互功能

  • 🖱️ 点击节点:显示模块详情
  • 🔍 高亮路径:显示完整的依赖链
  • 🏷️ 过滤显示:只显示需要更新的模块
  • 📐 自动布局:层次化布局算法

实践指南

工作流程

# 1. 人类修改意图
vim modules/logger/skills/json_format.md

# 2. 触发"编译"
nlcc build

# 3. NLCC自动执行
Reading modules/logger/AGENTS.md...
  → Loading skills/output.md...
  → Loading skills/json_format.md...
Generating code...
  → build/src/logger/impl.rs
  → build/include/logger.rs
Compiling...
  → cargo build --release
Testing...
  → All tests passed
Build complete!

# 4. 查看生成的代码(可选,就像今天看汇编)
cat build/src/logger/impl.rs

# 5. 运行
cargo run --release

与传统编译器的对比

传统编译器(Rustc)自然语言编译器(NLCC)
输入:Rust代码输入:自然语言(AGENTS.md)
输出:机器码/汇编输出:Rust代码
错误:借用检查、类型推断错误错误:意图模糊、逻辑矛盾
优化:MIR优化、LLVM优化优化:模块拆分、依赖管理
调试:看MIR/汇编(--emit mir)调试:看生成的Rust代码
工具链:Cargo → Rustc → LLVM工具链:意图分析 → 代码生成 → Cargo编译

Web版实际使用场景

场景1:首次创建项目

1. 打开 NLCC Web Studio
   → 自动创建示例项目结构

2. 在项目浏览器中创建新模块
   右键 → 新建模块 → 输入名称: "logger"

3. 编辑 AGENTS.md
   在编辑器中编写:

# Logger Module

## 功能
记录日志到文件和控制台
...


4. 自动保存 + 实时预览
→ 右侧自动显示生成的代码预览

5. 点击"🚀 构建当前模块"
→ 自动生成 impl.rs
→ 自动编译
→ 显示构建结果

场景2:修改已有模块

1. 在项目浏览器中打开 logger/AGENTS.md
   → 编辑器显示当前内容

2. 修改需求
   添加:

## 新需求
支持 JSON 格式输出


3. 自动检测变化
→ 状态面板自动显示: 🔄 logger 需要重新生成
→ 右下角弹出通知

4. 查看预览
→ 右侧自动显示新代码预览
→ 高亮显示差异部分

5. 点击"🚀 构建当前模块"
→ 自动备份旧版本: impl.rs.backup
→ 生成新版本
→ 显示对比

场景3:手工修改 + 自动保护

1. 手工编辑生成的代码
   在 impl.rs 中添加:

// ========== MANUAL EDIT BEGIN ==========
pub fn fast_log(msg: &str) {

 // 手工优化的特殊函数

}
// ========== MANUAL EDIT END ==========


2. 下次重新生成时
→ 自动识别手工编辑区域
→ 保留手工部分
→ 只覆盖 AI 生成的部分

3. 可视化显示
→ 在编辑器中用不同颜色标识:
   - 🟢 绿色: AI生成的区域
   - 🟡 黄色: 手工编辑区域(受保护)

如何开始

1. 从小项目开始

  • 不要在大型遗留项目上尝试
  • 选择新项目、工具项目、实验性项目

2. 设计MD架构

  • 划分模块:哪些功能是独立的?
  • 编写项目级AGENTS.md
  • 编写模块级AGENTS.md
  • 编写skills/*.md

3. 验证提示词质量

  • 给另一个AI看你的AGENTS.md
  • 它能理解这个模块做什么吗?
  • 它知道如何使用这个模块吗?

4. 维护MD,而不是代码

  • 需要修改功能时,编辑AGENTS.md
  • 运行 nlcc build 重新生成
  • 不要直接编辑 build/ 下的代码

调试与质量保证

调试三层模型

当AI生成的代码出现问题时,调试需要在三个层次进行:

1. 意图层(AGENTS.md)
   ↓ 问题:需求描述不清晰或矛盾?
   ↓ 解决:优化MD描述,添加更多上下文

2. 理解层(AI推理)
   ↓ 问题:AI是否正确理解了意图?
   ↓ 解决:添加示例代码,明确约束条件

3. 实现层(生成的代码)
   ↓ 问题:代码实现有bug?
   ↓ 解决:手工修改(保护区域)或修正意图

实战调试策略

场景1:性能不符合预期

步骤1:定位问题
$ nlcc analyze-performance logger

分析结果:
  瓶颈函数:logger_log()
  耗时:200μs(要求:<100μs)
  调用次数:10,000次/秒

步骤2:查看意图
→ logger/AGENTS.md 中没有明确性能要求

步骤3:修正意图
在 logger/skills/performance.md 中添加:

性能要求

  • logger_log() 必须在 100μs 内完成
  • 允许使用内存缓存优化性能

    
    步骤4:重新生成
    $ nlcc build logger
    
    结果:
    ✓ 性能提升至 80μs
    ✓ 使用了内存池优化

场景2:偶发性Bug

// network/impl.rs
// AI生成的代码有并发bug
pub fn handle_connection(&mut self, conn: &Connection) {
    // ❌ Bug:数据竞争
    self.active_connections.push(conn);
}
调试过程:

1. 查看AGENTS.md
   → 发现没有明确线程安全要求

2. 添加skill
   创建 network/skills/thread_safety.md:

## 线程安全

  • handle_connection 可能被多线程调用
  • 必须使用 Mutex 或 Arc 保护共享状态

    
    3. 重新生成
    → AI自动生成线程安全的代码
    
    4. 验证
    → 运行并发测试,问题解决

质量保证工具链

# 1. 静态分析
$ nlcc check
✓ 检查所有AGENTS.md的完整性
✓ 验证模块间依赖关系
✓ 检测冲突的skills
⚠️  warning: logger/skills/performance.md 与 low_memory.md 有潜在冲突

# 2. 单元测试生成
$ nlcc test generate --unit

为每个模块自动生成单元测试:
  ✓ logger/tests/test_logger.rs
  ✓ network/tests/test_network.rs
  测试覆盖率目标:80%

# 3. 集成测试
$ nlcc test integration

运行端到端集成测试:
  ✓ 测试完整的数据流
  ✓ 验证模块间接口契约
  ✓ 性能基准测试

# 4. 回归测试
$ nlcc test regression --before logger-v1.0.0 --after logger-v2.0.0

对比版本间行为差异:
  ✓ 性能变化:+5%(可接受)
  ⚠️  内存使用:+20%(需要优化)

团队协作最佳实践

1. 版本控制策略

推荐的工作流:

项目结构(Git仓库):
  .gitignore:
    build/          # 忽略生成的代码
    *.backup        # 忽略备份文件
    .nlcc/cache/    # 忽略AI响应缓存

  提交规范:
    ✅ 提交 modules/ 和 AGENTS.md(源代码)
    ❌ 不提交 build/(生成产物)
    ✅ 提交 tests/(测试代码)
    ✅ 提交 .nlcc/config.toml(项目配置)

  CI/CD集成:
    .github/workflows/nlcc-ci.yml:
      1. 检出代码
      2. 运行 nlcc check(验证MD完整性)
      3. 运行 nlcc build(生成代码)
      4. 运行 cargo test(测试)
      5. 运行 nlcc benchmark(性能基准)

2. 协作规范

# .nlcc/TEAM_GUIDELINES.md

## AGENTS.md 编写规范

### 统一的风格
- 使用一致的章节结构
- 功能描述不超过3句话
- 接口定义必须包含类型和用途

### 示例对比

❌ 不好的描述:

功能

这个模块负责处理网络相关的一些事情,比如连接管理、数据传输什么的。


✅ 好的描述:

功能

管理TCP连接的生命周期(创建、维护、关闭)
处理异步数据传输(发送、接收、重试)
支持SSL/TLS加密


### Code Review流程
1. PR主要审查AGENTS.md的改动
2. 生成的代码由CI自动验证
3. 只有MD变更需要人工review

## Skills管理规范

### 命名约定
- functional/[功能].md(功能需求)
- critical/[约束].md(关键约束)
- optimization/[目标].md(优化目标)

### 冲突预防
- 在添加新skill前,先运行 `nlcc check-conflict`
- 如果有冲突,在AGENTS.md中明确优先级

3. 知识共享

团队学习路径:

第1周:理解NLCC理念
  - 阅读《NLCC设计哲学》
  - 完成示例项目(编写一个简单模块)
  - 理解"代码是cheap的"核心思想

第2周:实践AGENTS.md编写
  - 选择一个真实的小模块
  - 编写AGENTS.md和skills
  - 团队成员互相review

第3周:掌握调试技巧
  - 学会三层调试模型
  - 熟练使用nlcc工具链
  - 能够快速定位问题根源

第4周:参与实际项目
  - 在监督下修改真实模块
  - 处理接口变更和冲突解决
  - 积累实战经验

4. 项目模板

# 创建新项目
$ nlcc init my-project --template=web-service

生成的模板包含:
  AGENTS.md                 # 项目级意图
  modules/
    logger/AGENTS.md        # 日志模块示例
    api/AGENTS.md           # API模块示例
    config/AGENTS.md        # 配置模块示例
  tests/
    integration/            # 集成测试框架
  .nlcc/
    config.toml             # 项目配置
    TEAM_GUIDELINES.md      # 团队规范(含上述内容)
  .github/
    workflows/
      nlcc-ci.yml           # CI/CD配置

模板的优势:
  ✓ 新成员快速上手
  ✓ 统一的项目结构
  ✓ 内置最佳实践
  ✓ 自动化的质量检查

技术演化

历史规律:抽象层不断上升

┌─────────────┬──────────────┬─────────────┬──────────────┐
│   时代      │  程序员关注   │  工具       │  输出物      │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 机器码时代  │ 0101序列     │ 手工拨开关  │ 机器码       │
│ 1940s      │              │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 汇编时代    │ 助记符       │ 汇编器      │ 机器码       │
│ 1950s      │ (MOV, ADD)   │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 高级语言    │ 算法逻辑     │ 编译器      │ 汇编/机器码  │
│ 1970s+     │ (for, if)   │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ AI时代      │ 业务意图     │ 自然语言    │ 代码         │
│ 2020s+     │ (自然语言)   │ 编译器      │              │
└─────────────┴──────────────┴─────────────┴──────────────┘

类比:代码 = 未来的汇编

今天我们如何看待汇编?

场景1:应用开发
工程师:我要写一个Web服务器
选择:Go、Python、Java
绝不会考虑:手写汇编

场景2:系统编程
工程师:我要写Linux内核
选择:Rust/C语言,偶尔内联汇编
不会全用:纯汇编

场景3:极致优化
工程师:这个加密循环性能不够
考虑:手写汇编优化这一小段

明天我们如何看待代码?

场景1:应用开发
工程师:我要写一个Web服务器
做法:写AGENTS.md描述意图
工具:自然语言编译器(NLCC)
生成:Go/Python代码(自动)
绝不会考虑:手写Go代码

场景2:系统编程
工程师:我要写操作系统内核
做法:写关键模块的AGENTS.md
生成:Rust代码(自动)
偶尔手工优化:极少数性能关键路径

场景3:极致优化
工程师:AI生成的这段代码性能不够
考虑:手工优化这一小段

结论

  • 汇编依然存在,但适用范围极小(1%)
  • 代码依然存在,但适用范围会大大降低(10% → 1%)
  • NLCC不会淘汰代码,就像高级语言不会淘汰汇编

人类工程师的职责演化

现在(高级语言时代)

人类工程师的日常:
1. 设计系统架构(模块划分)
2. 定义接口(.rs文件)
3. 实现逻辑(impl.rs)
4. 调试、测试、优化
5. 维护代码(修复bug、添加功能)
6. Code Review

时间分配

  • 架构设计:10%
  • 写代码:60%
  • 调试测试:20%
  • 维护:10%

未来(NLCC时代)

人类工程师的日常:
1. 设计系统架构(模块划分)
2. 编写意图描述(AGENTS.md)
3. 审查AI生成的代码(偶尔,5%时间)
4. 处理AI搞不定的极端场景(1%时间)
5. 监控系统运行状态

时间分配

  • 架构设计:20%
  • 编写MD:30%
  • 审查代码:5%
  • 极端场景:1%
  • 监控、优化、学习:44%

核心转变

  • 从"如何实现" → "要实现什么"
  • 从"细节控制" → "意图表达"
  • 从"代码维护" → "意图维护"

目标用户

NLCC的目标用户是会写代码的程序员,而不是完全不懂编程的人。

小张 - 后端开发工程师

  • 熟练掌握 Python/Java
  • 经常写重复性代码(CRUD、API接口)
  • 想提高效率:"我只想描述需求,不想手写每一行代码"
  • 痛点:

    • "写 CRUD 很枯燥,但又不能不做"
    • "有时候想法很简单,实现起来要写很多代码"
    • "想快速验证想法,不想浪费时间在样板代码上"

小李 - 全栈开发者

  • 前后端都能写
  • 经常需要快速开发原型
  • 想要自然语言生成完整功能
  • 痛点:

    • "项目初期,只是想快速验证功能"
    • "手写前端+后端很累"
    • "如果能说清楚需求就自动生成该多好"

王工 - 算法工程师

  • 擅长算法和数据处理
  • 不想花时间在 Web 开发上
  • 需要快速搭建演示系统
  • 痛点:

    • "我的算法很复杂,但界面很简单"
    • "不想学 React/Vue,只想展示结果"
    • "只要能跑起来,怎么实现都行"

共同点:

  • ✅ 会编程,懂技术
  • ✅ 想提高开发效率
  • ✅ 能准确描述需求
  • ✅ 能读懂生成的代码,可以二次修改
  • ❌ 不想重复写样板代码
  • ❌ 不想被框架和工具链束缚

愿景

让程序员更高效地创造软件

NLCC 的使命是提升开发效率,让程序员能够:

  • 用自然语言描述需求,不再手写每一行样板代码
  • 快速验证想法,从需求到可运行代码只需几分钟
  • 保持完全掌控,生成的代码清晰可读,可以二次修改
  • 专注核心逻辑,把时间花在真正重要的地方
  • 可视化开发,通过Web界面直观管理整个项目

不是低代码平台,不是玩具工具,而是专业级编译器

NLCC 将自然语言视为一种编程语言,通过编译器技术将其转换为可执行代码。生成的代码与手写代码无异,性能、可维护性、可扩展性完全一致。

核心理念:

  • 自然语言是合法的编程语言
  • 编译器负责从需求到代码的转换
  • 程序员保持对生成的完全掌控
  • Web界面让开发过程直观可见

用自然语言写代码,像说话一样自然


未来展望

NLCC不仅是一个编译系统,更是通向未来软件工程的桥梁。随着AI能力的不断提升,NLCC将在以下几个方向持续演进:

1. 测试左移:自然语言测试用例

核心思想:在编写功能代码之前,先用自然语言描述测试场景,让AI同时生成代码和测试。

示例

# network/skills/testing.md

## 测试场景

### 场景1:网络断开重连
**描述**:当网络连接意外断开时,系统应该自动重连,最多重试3次,每次间隔指数退避(1s, 2s, 4s)

**验证步骤**:
1. 建立正常连接
2. 模拟网络中断
3. 验证自动重连触发
4. 验证重连次数不超过3次
5. 验证间隔时间符合指数退避

**期望结果**:在第3次重试成功后,连接恢复正常

### 场景2:并发压力测试
**描述**:系统应支持1000个并发连接,每个连接每秒发送10条消息,持续运行1小时不崩溃

**性能指标**:
- 消息丢失率:< 0.01%
- 平均响应时间:< 50ms
- P99响应时间:< 200ms

AI生成

// network/tests/test_reconnect.rs
// AI自动生成的测试代码
#[test]
fn test_auto_reconnect_with_exponential_backoff() {
    // 基于自然语言描述生成的完整测试
}

// network/tests/test_concurrent_connections.rs
#[test]
fn test_1000_concurrent_connections_stability() {
    // 压力测试代码
}

优势

  • ✅ 测试用例与需求同步更新
  • ✅ 避免测试与实现脱节
  • ✅ 降低编写测试的门槛

2. 多语言目标:一次编写,到处编译

核心思想:既然MD是源码,理论上可以针对不同后端生成不同语言的代码。

架构设计

         AGENTS.md(语言无关的意图)
                ↓
    ┌───────────┼───────────┐
    ↓           ↓           ↓
  Rust      Go        Python
  后端      后端       后端
    ↓           ↓           ↓
高性能     简单易用   快速原型

示例配置

# .nlcc/config.toml

[targets]
rust = { enabled = true, optimize = "speed" }
go = { enabled = true, optimize = "maintainability" }
python = { enabled = true, optimize = "development" }

[module.logger]
targets = ["rust", "go"]  # logger模块生成Rust和Go版本

[module.scripting]
targets = ["python"]  # 脚本模块只生成Python版本

使用场景

场景1:跨语言项目
  核心引擎(Rust) + 业务逻辑(Go) + 脚本扩展(Python)
  → 一次编写AGENTS.md,自动生成多语言接口

场景2:渐进式迁移
  老项目(Python) → 新项目(Rust)
  → 保持AGENTS.md不变,切换生成目标

场景3:技术栈选型
  先用Python快速验证原型
  → 确认需求后切换到Rust生产版本

接口兼容性保证

# api/AGENTS.md

## 跨语言接口定义
所有后端语言必须实现相同的RESTful API接口:
- GET /api/resources
- POST /api/resources
- PUT /api/resources/:id
- DELETE /api/resources/:id

数据格式:JSON
错误处理:统一错误码

3. AI代理协作:分布式AI开发

核心思想:未来可能不是单个AI解析所有MD,而是为每个模块分配一个"AI代理",它们根据各自的AGENTS.md协作。

架构

         项目级AGENTS.md
              ↓
    ┌─────────┼─────────┐
    ↓         ↓         ↓
  Agent    Agent    Agent
  Logger   Network  Storage
    ↓         ↓         ↓
  独立上下文  独立上下文  独立上下文
    ↓         ↓         ↓
  生成代码  生成代码  生成代码
    └─────────┼─────────┘
              ↓
        自动集成测试

协作协议

# AGENTS.md(项目级)

## AI代理协作协议

### 代理职责划分
- **Logger代理**:专注于日志功能的实现
- **Network代理**:专注于网络通信
- **Storage代理**:专注于数据持久化

### 通信方式
- 代理之间不直接通信
- 通过build/include/的公共接口定义契约
- api.rs作为顶层协调者

### 冲突解决
- 如果两个代理对同一接口有不同理解
- 由项目级AGENTS.md中的优先级规则裁决
- 记录决策日志供人类审查

优势

  • ✅ 每个代理使用更小的上下文窗口
  • ✅ 并行生成,提高速度
  • ✅ 单个代理出错不影响其他模块

4. 智能演进:自优化系统

核心思想:系统根据运行时反馈,自动优化AGENTS.md描述和生成的代码。

反馈循环

  编写AGENTS.md
       ↓
  生成代码
       ↓
  部署运行
       ↓
  收集指标(性能、错误率)
       ↓
  AI分析指标
       ↓
  建议优化(MD或代码)
       ↓
  人类审核
       ↓
  应用改进

示例

# logger/AGENTS.md

## 性能优化历史

### 2026-02-20: 添加内存池
**触发条件**:
  - 监控发现内存分配频繁(>1000次/秒)
  - 性能分析显示malloc是瓶颈

**AI建议**:
  - 使用内存池减少分配开销
  - 预分配1000个log buffer

**人类审核**:✅ 批准
**效果**:性能提升30%

### 2026-02-25: 添加批量写入
**触发条件**:
  - 高吞吐场景下单条写入成为瓶颈

**AI建议**:
  - 累积10条日志后批量写入
  - 权衡:可能丢失最后几条(进程崩溃时)

**人类审核**:✅ 批准(添加配置选项)
**效果**:吞吐量提升50%

安全措施

  • ✅ 所有自动优化都需要人类审核
  • ✅ 保留版本历史,可以回滚
  • ✅ 运行测试验证优化效果

5. 生态扩展:NLCC插件系统

核心思想:支持第三方扩展NLCC的功能。

插件类型

# 示例:自定义风格检查插件
# plugins/style_checker.py

class StyleCheckerPlugin:
    def check_agents_md(self, content: str) -> List[Issue]:
        """检查AGENTS.md是否符合团队风格"""
        issues = []
        
        # 检查章节结构
        required_sections = ["功能定位", "核心接口", "主要职责"]
        for section in required_sections:
            if section not in content:
                issues.append(Issue(
                    level="warning",
                    message=f"缺少必需章节: {section}"
                ))
        
        return issues
    
    def suggest_improvements(self, content: str) -> List[Suggestion]:
        """提供改进建议"""
        return [
            Suggestion(
                location="功能定位",
                suggestion="建议添加性能指标"
            )
        ]

插件配置

# .nlcc/plugins.toml

[[plugins]]
name = "style-checker"
path = "plugins/style_checker.py"
enabled = true

[[plugins]]
name = "security-scanner"
path = "plugins/security.py"
enabled = true

[[plugins]]
name = "team-standards"
path = "plugins/standards.py"
enabled = true

时间线预测

2026年Q2:NLCC v1.0
  ✓ 基础编译功能
  ✓ Web可视化界面
  ✓ Rust代码生成

2026年Q3:测试左移
  ✓ 自然语言测试用例
  ✓ 自动测试生成
  ✓ 覆盖率报告

2026年Q4:多语言支持
  ✓ Go后端
  ✓ Python后端
  ✓ 跨语言接口

2027年Q1:AI协作
  ✓ 多代理架构
  ✓ 并行生成
  ✓ 冲突自动解决

2027年Q2:智能优化
  ✓ 运行时监控
  ✓ 自动优化建议
  ✓ A/B测试框架

2027年Q3:生态繁荣
  ✓ 插件市场
  ✓ 第三方扩展
  ✓ 社区贡献

总结

NLCC是一个完整的自然语言编程系统,包含:

设计哲学

  • 代码是cheap的,AI注意力是昂贵的
  • 牺牲代码复用换取AI注意力聚焦
  • 零循环依赖的模块化架构

核心架构

  • AGENTS.md:意图描述(做什么)
  • skills/*.md:需求和约束(具体需求)
  • build/:自动生成的代码(怎么做)

Web可视化界面

  • 项目浏览器:可视化查看项目结构
  • 实时编辑器:在线编辑MD文档
  • 代码预览:实时查看生成的代码
  • 状态监控:自动检测变化并通知
  • 一键构建:自动化编译流程

自动化构建系统

  • 三种策略模式:auto/always/preserve
  • 手工编辑保护:保留手工修改区域
  • 智能通知:自动提醒需要更新的模块
  • 依赖可视化:图形化显示模块依赖关系

实践指南

  • 从小项目开始
  • 设计清晰的MD架构
  • 验证提示词质量
  • 维护MD而非代码

NLCC不是愿景,而是正在实现的系统。它代表了编程语言演化的必然趋势:抽象层不断上升,自然语言将成为新的源码。


本文整合了《NLCC设计哲学》和《NLCC网页可视化自动化策略》,形成完整的NLCC系统文档。

相关文档:

作者:twg2020
首发:somingbai.com
时间:2026-02-19
更新:2026-02-20(合并版本)

AI原生提示词架构设计:让自然语言成为新源码

前言

在上一篇《AI时代的代码架构:如何设计让AI更好编程的系统》中,我提出了一个核心观点:代码是cheap的,AI注意力是昂贵的,应该设计专门的架构来适应AI的认知特点。

但如果只优化代码架构,只解决了一半的问题。另一半问题在于:给AI的提示词(Prompt)本身也需要架构。

在探索Claude Code、Clawdbot等AI辅助编程工具的过程中,我发现一个现象:很多人把提示词当成零散的文本片段,想到什么写什么。这就像在机器码时代,程序员直接写0101序列——没有抽象,没有结构,难以维护。

我认为:在AI时代,提示词(Markdown文档)将成为新的"源码",而代码将成为编译后的"中间产物"。

本文将阐述一套与代码架构相辅相成的AI原生提示词架构设计


核心洞察:提示词也需要架构

传统误区

很多人认为提示词就是一段自然语言文本:

❌ 错误做法:把所有信息写在一个prompt里

"你是一个C语言程序员,请帮我写一个日志系统。
这个系统需要支持:
1. 输出到文件
2. 输出到控制台
3. 日志级别控制
4. 线程安全
5. 还要支持JSON格式输出
6. 还要支持滚动日志
7. 还要..."

问题

  • AI的注意力被分散到10+个细节上
  • 核心逻辑容易出错
  • 难以维护和扩展

正确思路:模块化 + 按需加载

✅ 正确做法:架构化的提示词

项目/
├── AGENTS.md              # 顶层意图(main函数)
├── modules/
│   ├── logger/
│   │   ├── AGENTS.md      # 模块意图
│   │   └── skills/        # 按需加载的细节
│   │       ├── output.md
│   │       ├── thread_safety.md
│   │       └── json_format.md
│   └── network/
│       ├── AGENTS.md
│       └── skills/
│           ├── tcp.md
│           └── ssl.md
└── build/                 # AI生成的一次性代码
    └── src/

优势

  • AI的注意力聚焦:每次只关注一个模块的意图
  • 降低认知负担:细节放在skills里,按需加载
  • 易于维护:修改意图,重新"编译"即可

提示词架构设计

1. AGENTS.md:MD文档的main函数

核心原则:每个AGENTS.md是唯一入口,描述"做什么",不描述"怎么做"。

项目级AGENTS.md

# AGENTS.md - 项目全局视图

## 项目背景
这是一个高性能网络服务器,支持并发连接和事件驱动架构。

## 核心功能
- 网络连接管理(TCP/SSL)
- 异步事件处理
- 日志记录
- 数据持久化

## 主要模块
- [logger/](modules/logger/AGENTS.md):日志记录模块
- [network/](modules/network/AGENTS.md):网络通信模块
- [storage/](modules/storage/AGENTS.md):数据存储模块

## 对外接口
应用通过`api.h`提供统一的接口:

void app_start();
void app_stop();


## 设计原则
- 零循环依赖
- 编译期隔离
- AI注意力优先

作用

  • 给AI提供全局视图
  • 说明项目背景和目标
  • 列出主要模块和依赖关系
  • 就像C程序的main函数,是整个系统的入口

模块级AGENTS.md

# Logger Module - AGENTS.md

## 功能定位
记录应用日志到文件和控制台,支持多种日志级别和输出格式。

## 核心接口

void logger_log(Logger logger, const char message);
void logger_set_level(Logger* logger, LogLevel level);
void logger_set_output(Logger* logger, OutputTarget target);


## 主要职责
1. 接收日志消息
2. 格式化输出(文本/JSON)
3. 写入目标(文件/控制台)
4. 线程安全保证

## 依赖
- 依赖:无(零依赖模块)
- 被依赖:network、storage

## 细节文档
- [output策略](skills/output.md):如何支持多种输出格式
- [线程安全](skills/thread_safety.md):如何保证并发安全
- [性能优化](skills/performance.md):如何优化日志性能

## 注意事项
- 不要在这个模块中添加网络功能
- 不要阻塞主线程

作用

  • 描述模块的职责和边界
  • 说明接口和使用方式
  • 列出依赖关系
  • 指向细节文档(skills)

2. Skills目录:按需加载的细节

核心原则:skills只描述意图和需求,不描述具体实现。

示例:logger/skills/json_format.md

# JSON格式日志输出

## 需求描述
日志需要支持JSON格式输出,便于日志收集和分析系统(如ELK)解析。

## 输出格式

{
"timestamp": "2026-02-15T10:30:00Z",
"level": "ERROR",
"module": "network",
"message": "Connection failed",
"context": {

"peer": "192.168.1.100:8080",
"error_code": 110

}
}


## 使用场景
- 生产环境日志收集
- 自动化日志分析
- 结构化查询

## 性能要求
- JSON序列化时间 < 100μs
- 不能阻塞主线程

## 不需要关心
- 具体用哪个JSON库(AI自己选择)
- 如何优化性能(AI自己考虑)

关键点

  • ✅ 描述"做什么":支持JSON格式
  • ✅ 描述"为什么要做":便于日志分析
  • ✅ 描述"使用场景":生产环境
  • ❌ 不描述"怎么做":不用告诉AI用哪个库

示例:logger/skills/thread_safety.md

# 线程安全保证

## 需求描述
日志模块可能被多个线程同时调用,必须保证线程安全。

## 关键要求
1. 不能丢失日志消息
2. 不能死锁
3. 性能开销最小化

## 常见场景
- 主线程写日志,工作线程也写日志
- 多个网络连接同时记录错误

## 可选方案(仅供参考,AI可以自行决定)
- 使用互斥锁(简单,但可能阻塞)
- 使用无锁队列(复杂,但性能好)
- 使用线程本地缓冲(延迟写入)

## 性能目标
- 单次日志调用 < 50μs
- 支持至少10个并发线程

3. 按需加载策略

核心思想:不是一次性加载所有MD,而是根据AI的注意力范围动态加载。

场景1:AI生成logger模块代码

步骤1:读取 logger/AGENTS.md
→ AI理解模块的整体意图

步骤2:AGENTS.md引用了 skills/output.md
→ AI读取这个文件,了解输出需求

步骤3:AI开始生成代码
→ 只关注当前模块,不受其他模块干扰

场景2:AI需要理解logger如何被network使用

步骤1:读取 logger/AGENTS.md
→ 了解logger提供的接口

步骤2:读取 network/AGENTS.md
→ 发现network依赖logger

步骤3:按需加载 skills/json_format.md
→ 了解network需要JSON格式的日志

类比:现代操作系统的按需加载

传统程序:
启动时加载所有代码到内存
→ 浪费内存,启动慢

现代程序(动态链接):
启动时只加载必需的代码
→ 节省内存,启动快
→ 使用到某个模块时,才加载

AI提示词架构:
AI开始工作时,只加载必需的MD
→ 降低上下文消耗
→ 需要细节时,才加载skills

与代码架构的对应关系

完美映射

提示词架构(MD)          代码架构(C)
─────────────────         ─────────────────
AGENTS.md          ↔     api.h / module.h
skills/output.md   ↔     src/module/impl.c(实现细节)
项目AGENTS.md       ↔     项目对外接口
按需加载MD         ↔     动态链接/模块化编译

核心原则一致性

原则提示词架构代码架构
零循环依赖AGENTS.md不互相include.h文件不互相include
清晰边界每个AGENTS.md职责单一每个module职责单一
按需加载skills目录按需读取编译期隔离
单一入口AGENTS.md是main函数api.h是唯一对外接口
意图抽象MD描述"做什么".h描述接口

生成流程

人类维护层(源码):
├── AGENTS.md
├── modules/*/AGENTS.md
└── modules/*/skills/*.md
        ↓
        ↓ AI"编译"
        ↓
AI生成层(中间产物):
├── include/*.h
└── src/*/impl.c
        ↓
        ↓ 传统编译
        ↓
机器码(运行产物):
└── binary

技术本质:编程语言演化的延续

历史规律:抽象层不断上升

┌─────────────┬──────────────┬─────────────┬──────────────┐
│   时代      │  程序员关注   │  工具       │  输出物      │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 机器码时代  │ 0101序列     │ 手工拨开关  │ 机器码       │
│ 1940s      │              │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 汇编时代    │ 助记符       │ 汇编器      │ 机器码       │
│ 1950s      │ (MOV, ADD)   │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ 高级语言    │ 算法逻辑     │ 编译器      │ 汇编/机器码  │
│ 1970s+     │ (for, if)   │             │              │
├─────────────┼──────────────┼─────────────┼──────────────┤
│ AI时代      │ 业务意图     │ 自然语言    │ 代码         │
│ 2020s+     │ (自然语言)   │ 编译器      │              │
└─────────────┴──────────────┴─────────────┴──────────────┘

每一次革命的本质

机器码 → 汇编:符号抽象

之前

程序员需要记住:
01001001 = LOAD寄存器
01001010 = ADD操作
01001011 = STORE操作

之后

程序员只需要写:
LOAD A, 10
ADD B, 5
STORE A, result

本质:用符号代替数字,降低记忆负担

底层依然存在:CPU还是执行0101,但程序员不需要关心了


汇编 → 高级语言:控制流抽象

之前

; 计算1到100的和
MOV AX, 0
MOV CX, 100
MOV BX, 1
loop_start:
ADD AX, BX
INC BX
DEC CX
JNZ loop_start
STORE AX, sum

之后

int sum = 0;
for (int i = 1; i <= 100; i++) {
    sum += i;
}

本质

  • 用控制流(for, if)代替跳转指令
  • 用变量名代替寄存器
  • 用类型系统代替手动内存管理

底层依然存在:CPU还是执行跳转指令,但程序员不需要关心了

适用范围降低

  • 99%的代码用高级语言
  • 1%的极端性能场景(OS内核、驱动)用汇编

高级语言 → AI:意图抽象

之前

# 发送HTTP请求并处理错误
import requests

try:
    response = requests.get('https://api.example.com/users')
    if response.status_code == 200:
        users = response.json()
        for user in users:
            print(user['name'])
    else:
        logger.error(f"HTTP {response.status_code}: {response.text}")
except requests.exceptions.RequestException as e:
    logger.error(f"Request failed: {e}")

之后(AI时代)

<!-- network/AGENTS.md -->

# Network Module

## 功能
发送HTTP请求到API服务器,获取用户列表。

## 接口

UserList network_fetch_users(Network self);


## 错误处理
如果请求失败,需要:
1. 记录错误日志(通过logger模块)
2. 返回NULL给调用者
3. 不要抛异常(C语言不支持)

## 性能要求
- 超时时间:5秒
- 重试次数:3次

本质

  • 用自然语言描述意图,代替具体的控制流
  • AI负责"怎么做",人类只说"做什么"
  • 代码成为中间产物,就像今天的汇编

底层依然存在

  • CPU还是执行机器码
  • 编译器还是生成汇编
  • 但程序员99%不需要关心了

适用范围降低

  • 99%的代码用AI + 自然语言生成
  • 1%的极端场景(AI生成代码性能不够)手工写代码

技术演化的规律

规律1:抽象层不断上升

机器码(硬件) → 汇编(符号) → 高级语言(逻辑) → 自然语言(意图)
   ↓               ↓              ↓                ↓
 只有极少数人掌握   少数人        大多数人        所有人

规律2:旧技术不会消失,适用范围降低

汇编语言的演化

1950年代:所有编程都用汇编
1980年代:系统编程用汇编,应用编程用高级语言(90% vs 10%)
2020年代:只有OS内核、驱动、嵌入式用汇编(1% vs 99%)

未来:只有极端性能优化的场景用汇编(0.1% vs 99.9%)

手工写代码的演化(预测):

2020年代:所有编程都手写代码
2030年代:大多数编程用AI生成,少数极端场景手写(10% vs 90%)
2050年代:只有极致性能场景手工写代码(1% vs 99%)
2100年代:只有特殊领域(AI无法理解)手工写代码(0.1% vs 99.9%)

规律3:工具复杂度转移

机器码时代:
工具:简单(手工拨开关)
程序员负担:重(需要记住所有0101)

汇编时代:
工具:汇编器
程序员负担:减轻(只需要写助记符)

高级语言时代:
工具:复杂的编译器、链接器、优化器
程序员负担:很轻(只需要写逻辑)

AI时代:
工具:极其复杂的自然语言编译器(大模型)
程序员负担:极轻(只需要描述意图)

类比:代码 = 未来的汇编

今天我们如何看待汇编?

场景1:应用开发
工程师:我要写一个Web服务器
选择:Go、Python、Java
绝不会考虑:手写汇编

场景2:系统编程
工程师:我要写Linux内核
选择:C语言,偶尔内联汇编
不会全用:纯汇编

场景3:极致优化
工程师:这个加密循环性能不够
考虑:手写汇编优化这一小段

结论:汇编依然存在,但适用范围极小。

明天我们如何看待代码?

场景1:应用开发
工程师:我要写一个Web服务器
做法:写AGENTS.md描述意图
工具:自然语言编译器(NLCC)
生成:Go/Python代码(自动)
绝不会考虑:手写Go代码

场景2:系统编程
工程师:我要写操作系统内核
做法:写关键模块的AGENTS.md
生成:C代码(自动)
偶尔手工优化:极少数性能关键路径

场景3:极致优化
工程师:AI生成的这段代码性能不够
考虑:手工优化这一小段

结论:代码依然存在,但99%的人不需要手写。

类比总结

今天:
汇编 → 编译器 → 机器码
程序员写汇编,不需要看生成的机器码
(除非极端性能优化)

明天:
自然语言(MD) → 自然语言编译器(AI) → 代码 → 传统编译器 → 机器码
程序员写MD,不需要看生成的代码
(除非极端性能优化)

高级语言不会淘汰汇编:汇编依然在OS内核、驱动中发挥作用
AI不会淘汰高级语言:代码依然是重要的中间层,但适用范围大大降低


未来展望:自然语言编译器(NLCC)

会是什么样的?

项目结构

project/
├── AGENTS.md              # 顶层意图描述
├── modules/
│   ├── logger/
│   │   ├── AGENTS.md      # 模块意图
│   │   └── skills/        # 按需加载的细节
│   │       ├── output.md
│   │       ├── thread_safety.md
│   │       └── json_format.md
│   └── network/
│       ├── AGENTS.md
│       └── skills/
│           ├── http.md
│           └── ssl.md
└── build/                 # 生成的一次性代码
    ├── src/
    │   ├── logger/
    │   │   ├── impl.c
    │   │   └── internal.h
    │   └── network/
    │       ├── http.c
    │       └── ssl.c
    ├── include/
    │   ├── logger.h
    │   └── network.h
    ├── compile.log        # 编译日志
    └── test_report.xml    # 测试报告

工作流程

# 1. 人类修改意图
vim modules/logger/skills/json_format.md

# 2. 触发"编译"
nlcc build

# 3. NLCC自动执行
Reading modules/logger/AGENTS.md...
  → Loading skills/output.md...
  → Loading skills/json_format.md...
Generating code...
  → build/src/logger/impl.c
  → build/include/logger.h
Compiling...
  → gcc -c build/src/logger/impl.c -o build/obj/logger.o
Testing...
  → All tests passed
Build complete!

# 4. 查看生成的代码(可选,就像今天看汇编)
cat build/src/logger/impl.c

# 5. 运行
./build/bin/app

NLCC和传统编译器的对比

传统编译器(GCC)自然语言编译器(NLCC)
输入:C代码输入:自然语言(AGENTS.md)
输出:机器码/汇编输出:C代码
错误:语法错误、链接错误错误:意图模糊、逻辑矛盾
优化:寄存器分配、指令调度优化:模块拆分、依赖管理
调试:看汇编代码(-S)调试:看生成的C代码
工具链:预处理 → 编译 → 汇编 → 链接工具链:意图分析 → 代码生成 → 传统编译

实践建议:如何开始

1. 从小项目开始

不要:在大型遗留项目上尝试
应该:在新项目、工具项目、实验性项目开始

推荐起点

  • 个人工具脚本
  • 小型库或框架
  • 概念验证项目

2. 设计MD架构

步骤1:划分模块
→ 哪些功能是独立的?
→ 依赖关系是什么?

步骤2:编写项目级AGENTS.md
→ 项目背景是什么?
→ 主要模块有哪些?
→ 对外接口是什么?

步骤3:编写模块级AGENTS.md
→ 这个模块做什么?
→ 接口是什么?
→ 依赖哪些模块?

步骤4:编写skills/*.md
→ 需要哪些细节描述?
→ 按场景拆分(不要写成大而全)

3. 验证提示词质量

标准:给另一个AI看你的AGENTS.md

  • 它能理解这个模块做什么吗?
  • 它知道如何使用这个模块吗?
  • 它会产生误解吗?

如果AI都有问题,那说明意图描述不够清晰。

4. 维护MD,而不是代码

场景:需要修改logger模块

错误做法:
直接编辑 build/src/logger/impl.c
→ 下次nlcc build时,你的修改被覆盖

正确做法:
编辑 modules/logger/AGENTS.md 或 skills/*.md
→ 运行 nlcc build
→ 重新生成代码

5. 代码审查(未来偶尔需要)

场景:性能不够

步骤1:看生成的代码
cat build/src/logger/impl.c

步骤2:找到性能瓶颈
→ 发现JSON序列化太慢

步骤3:选择优化策略
A. 修改AGENTS.md,明确性能要求(推荐)
B. 手工优化这一小段代码(极端情况)

人类工程师的职责演化

现在(高级语言时代)

人类工程师的日常:
1. 设计系统架构(模块划分)
2. 定义接口(.h文件)
3. 实现逻辑(.c文件)
4. 调试、测试、优化
5. 维护代码(修复bug、添加功能)
6. Code Review

时间分配

  • 架构设计:10%
  • 写代码:60%
  • 调试测试:20%
  • 维护:10%

未来(AI时代)

人类工程师的日常:
1. 设计系统架构(模块划分)
2. 编写意图描述(AGENTS.md)
3. 审查AI生成的代码(偶尔,5%时间)
4. 处理AI搞不定的极端场景(1%时间)
5. 监控系统运行状态

时间分配

  • 架构设计:20%
  • 编写MD:30%
  • 审查代码:5%
  • 极端场景:1%
  • 监控、优化、学习:44%

核心转变

  • 从"如何实现" → "要实现什么"
  • 从"细节控制" → "意图表达"
  • 从"代码维护" → "意图维护"

总结

核心观点

  1. 提示词也需要架构

    • 不是零散的文本,而是有组织的MD文档
    • AGENTS.md是唯一入口,skills是按需加载的细节
  2. 与代码架构完美对应

    • 零循环依赖、清晰边界、单一入口
    • 提示词描述意图,代码描述实现
  3. 技术演化的延续

    • 机器码 → 汇编 → 高级语言 → 自然语言
    • 每次抽象都降低程序员负担
    • 代码的地位 = 今天汇编的地位
  4. 未来已来

    • 自然语言编译器(NLCC)会出现
    • 代码放在build/目录,成为一次性中间产物
    • 人类只维护MD,就像今天只维护C代码
  5. 适用范围降低

    • AI不会淘汰代码,就像高级语言不会淘汰汇编
    • 但99%的场景不需要手工写代码
    • 只有极端性能场景才需要

行动建议

现在就开始:
1. 选择一个小项目
2. 设计AGENTS.md架构
3. 编写模块级MD和skills
4. 用AI生成代码
5. 验证、迭代、优化

记住:
- MD是源码,代码是中间产物
- 维护MD,而不是代码
- 意图清晰 > 代码完美

这是继《AI时代的代码架构》后的第二篇思考。核心观点是:在AI时代,提示词(自然语言)将成为新的源码,而代码将成为编译后的中间产物。 这不是科幻,而是编程语言演化的必然趋势。就像高级语言没有淘汰汇编,AI也不会淘汰代码——只是适用的范围会大大降低。欢迎交流讨论!

相关阅读

本文由作者 twg2020 创作,使用 AI 辅助润色
首发于:somingbai.com
时间:2026-02-15

AI时代的代码架构:如何设计让AI更好编程的系统

前言

在探索Claude Code辅助编程的过程中,我逐渐意识到一个核心问题:传统的软件架构设计思想,可能并不适合AI时代。

传统工程学追求代码复用、模块化、可维护性——这些当然重要。但在AI能够快速生成大量代码的今天,我认为代码本身变得cheap了,真正昂贵的是AI的注意力。

基于这个核心洞察,我设计了一套专门为AI编程优化的架构方案。本文将详细阐述这个架构的思想、设计原则和最佳实践。

核心洞察:代码是Cheap的

传统时代的成本结构

在传统软件开发中:

  • 编写代码:昂贵(需要资深工程师、耗时)
  • 复制代码:廉价(Ctrl+C/Ctrl+V)
  • 维护代码:昂贵(理解成本、耦合风险)

所以传统工程学强调:

  • ✅ DRY原则(Don't Repeat Yourself)
  • ✅ 代码复用
  • ✅ 统一抽象
  • ✅ 提前设计(过度设计)

AI时代的成本结构

在AI辅助编程中:

  • 代码是cheap的:AI生成代码极快(几秒钟生成几百行)
  • module随时可以替换:没搞好就再做一个,代价很低
  • 完全不需要提前过度设计:让实际需求驱动架构演化
  • AI的上下文窗口:昂贵(有限的注意力)
  • AI理解复杂系统:困难(容易遗漏细节)

新的成本函数:

总成本 = AI生成代码的时间(低)
       + 人类review的时间(中)
       + AI修改迭代的时间(高)
       + 系统复杂度导致的AI错误率(极高)

结论:在AI时代,应该牺牲代码复用来换取AI注意力的聚焦


深入理解:为什么要牺牲代码复用?

让我用具体例子说明这个观点。

传统方式:追求代码复用

场景:统一错误处理

// include/common/error.h
typedef struct {
    int code;
    char message[256];
    void* context;      // 通用的上下文
    int context_size;
} Error;

void error_handle(Error* err);  // 超级通用的错误处理

// 所有module都用这个Error
void network_send(Network* self, const char* data) {
    if (send_failed) {
        Error err = {
            .code = ERR_NETWORK,
            .context = self->internal_state,
            .context_size = sizeof(self->internal_state)
        };
        error_handle(&err);  // 复用通用处理
    }
}

传统优势

  • ✅ 只写一次错误处理逻辑
  • ✅ 统一的错误格式
  • ✅ 易于维护

传统成本

  • 需要设计"万能"的Error结构
  • 需要考虑所有使用场景
  • 人类工程师能理解这个复杂抽象

AI时代的问题

让AI写network_send时:

AI的思维过程:
1. 需要处理错误
2. 用Error结构
3. Error有哪些字段?code、message、context、context_size...
4. context是什么类型?void*?
5. 需要设置context_size吗?多大?
6. 有初始化函数吗?
7. 错误码是多少?
8. 要检查NULL吗?
...(AI注意力被分散到10个细节上)

AI实际生成(很可能出错):

void network_send(Network* self, const char* data) {
    if (send_failed) {
        Error err;  // ❌ 忘记初始化
        err.code = 1000;
        strcpy(err.message, "send failed");  // ❌ 忘记检查长度
        // ❌ 忘记设置context
        error_handle(&err);  // ❌ 可能段错误
    }
}

问题:AI注意力被分散到Error结构的细节上,核心逻辑反而出错。

AI方式:牺牲代码复用

// 不设计通用的Error结构

// src/network/impl.c
void network_send(Network* self, const char* data) {
    if (send_failed) {
        // 简单直接,网络模块自己的错误处理
        fprintf(stderr, "[network] send failed: %s\n", strerror(errno));
        if (self->error_callback) {
            self->error_callback("send failed");
        }
    }
}

// src/storage/impl.c
void storage_write(Storage* self, const char* data) {
    if (write_failed) {
        // 存储模块自己的错误处理(完全不同)
        fprintf(stderr, "[storage] write failed: %s\n", strerror(errno));
        if (self->retry_count < 3) {
            self->retry_count++;
            storage_write(self, data);  // 自己的重试逻辑
        }
    }
}

AI生成这个

AI的思维过程:
1. 需要处理错误
2. fprintf打印
3. 调用回调(如果有)
4. 完成

AI只需要关注3个细节,专注度高!

成本对比

传统方式(追求复用):

设计通用Error:4小时
AI出错率:30%
人类review:每个module 30分钟
修复时间:20分钟 × 3轮 = 60分钟

10个module总成本:4 + 15 = 19小时

AI方式(牺牲复用):

设计通用Error:0小时
AI出错率:5%
人类review:每个module 5分钟
修复时间:5分钟 × 1轮 = 5分钟

10个module总成本:0 + 1.6 = 1.6小时

代码重复:每个module都写fprintf(但没关系!)

节省时间:17小时!

"牺牲代码复用"的真正含义

不是

  • ❌ 随意复制粘贴
  • ❌ 不做任何抽象
  • ❌ 写烂代码

而是

  • ✅ 用代码重复换取逻辑简单
  • ✅ 用更多代码行换取AI理解成本低
  • ✅ 用手工维护换取AI出错率低

类比

这就像:

传统时代(手工制作家具):

  • 用精密的模具(通用抽象)
  • 一次设计,批量生产
  • 成本:设计贵,生产便宜

AI时代(3D打印):

  • 不需要精密模具
  • 每个产品单独打印
  • 成本:设计便宜,生产也便宜
  • 宁愿多打印几次,也不设计复杂模具

架构设计:依赖倒置 + 零循环依赖

设计目标

  1. 零循环依赖:AI不需要理解复杂的依赖关系
  2. 清晰的边界:每个模块的职责单一明确
  3. 可组合性:像搭积木一样组装复杂系统
  4. 可测试性:每个模块可以独立测试

目录结构设计

project/
├── include/              # 公共接口层(零依赖区)
│   ├── common_types.h   # POD数据结构
│   ├── logger.h         # 抽象接口
│   ├── network.h
│   ├── storage.h
│   └── ...
├── src/                 # 实现层
│   ├── logger/          # 实现logger.h
│   │   ├── impl.c
│   │   └── internal.h
│   ├── network/
│   └── storage/
└── api.h                # 唯一对外头文件

依赖关系图

         ┌─────────────────┐
         │     api.h       │  ← 最底层(对外窗口)
         │   (组合接口)     │
         └────────┬─────────┘
                  ↑ 依赖
         ┌────────┴─────────┐
         │    include/      │  ← 第二层(抽象接口层)
         │  - POD数据结构    │
         │  - 抽象接口定义   │
         └────────┬─────────┘
                  ↑ 依赖
         ┌────────┴─────────┐
         │   src/module*/   │  ← 第三层(实现层)
         └──────────────────┘

关键约束:

  • include/*.h 绝对禁止互相包含
  • src/module*/ 只依赖include/,不能依赖其他module
  • api.h 组合需要的接口对外暴露

三个关键设计问题

问题1:Module间如何通信?

传统困惑:既然module不能互相依赖,那怎么协作?

答案:所有通信接口也在include/里定义为抽象。

// include/event_bus.h
typedef struct EventBus EventBus;
void event_bus_publish(EventBus*, const char* topic, void* data);
void event_bus_subscribe(EventBus*, const char* topic,
                         void (*callback)(void*));

// src/logger/impl.c
#include "event_bus.h"
#include "logger.h"

void logger_init(Logger* self, EventBus* bus) {
    event_bus_subscribe(bus, "message.received", log_callback);
}

// src/network/impl.c
#include "event_bus.h"
#include "network.h"

void network_on_message(Network* self, const char* msg) {
    event_bus_publish(self->event_bus, "message.received", (void*)msg);
}

依赖倒置原则

  • 高层模块和低层模块都依赖抽象(include/
  • 抽象不依赖具体实现
  • 实现依赖抽象

问题2:数据结构放在哪里?

困惑:如果需要传递复杂结构,放哪里会打破零依赖原则?

答案:纯POD(Plain Old Data)结构可以放include/,甚至放api.h

// include/common_types.h
typedef struct {
    const char* method;
    const char* url;
    const char* body;
} HttpRequest;

typedef struct {
    int code;
    const char* message;
} HttpResponse;

为什么不会循环依赖?

  • POD结构只包含基本类型、指针、数组
  • 不include其他头文件
  • 即使多个接口include它,也是树状依赖,不会循环

注意:带函数指针的结构也算"数据结构",可以放include/

// include/observer.h
typedef struct {
    void (*on_message)(const char* msg);
    void (*on_error)(int error_code);
} ObserverCallbacks;

问题3:何时拆分Module?

困惑:拆分的粒度如何掌握?多少代码算太复杂?

答案:没有固定行数标准,看AI出错率

判断指标:

  1. 编译错误率

    AI第一次生成 → 编译通过
    如果通过率 < 70%,说明太复杂了
  2. 修改轮次

    AI生成 → 人类review → 指出问题 → AI修改 → 又发现问题...
    如果平均 > 2轮,说明超出了AI注意力范围
  3. 常见错误信号

    • ❌ 忘记NULL检查
    • ❌ 忘记释放内存
    • ❌ 边界条件遗漏
    • ❌ 错误处理不完整

本质原因:AI的注意力被核心逻辑占用,细节顾不上。

实验数据(假设):

Module大小代码行数AI编译通过率修改轮次
单体500行50%3-5轮
拆分后150行85%1-2轮

结论:当AI出错率上升时,继续拆分,或者提取成独立子项目。

与微服务架构的深度对比

相似性(理念层面)

维度微服务AI-Native架构
边界定义清晰的业务边界清晰的功能边界
依赖方向通过API互相调用通过抽象接口依赖
独立演进可以独立升级module可独立替换实现
团队协作不同团队负责不同服务不同AI/人负责不同module
核心理念解耦、隔离解耦、AI注意力管理

本质区别(实现层面)

1. 隔离边界

微服务:进程级隔离

服务A                服务B
[进程1] ──网络──→ [进程2]
  ↓                    ↓
独立内存空间        独立内存空间
  • ✅ 故障隔离:服务B崩溃不影响服务A
  • ✅ 语言自由:A用Go,B用Python
  • ❌ 性能开销:序列化、网络延迟(1-10ms)

AI-Native架构:编译期隔离

┌───────────────────进程───────────────────┐
│                                           │
│  moduleA  ──函数调用──→  moduleB         │
│    ↓                      ↓               │
│  共享地址空间        共享地址空间        │
│                                           │
└───────────────────────────────────────────┘
  • ✅ 性能:零拷贝、直接调用(1-10ns)
  • ✅ 调试:统一的内存空间、gdb一步跟踪
  • ❌ 故障传播:moduleB段错误 → 整个进程挂掉

性能差异:100万倍!

2. 部署复杂度

微服务需要:

  • 容器编排(Kubernetes)
  • 服务发现
  • 负载均衡
  • 配置管理
  • 链路追踪
  • 100+个基础设施组件

AI-Native架构需要:

  • 编译器
  • 链接器
  • 就这!

3. 扩展性

微服务:水平扩展(用户激增 → 加机器)

AI-Native架构:垂直扩展(加CPU/内存)或提取热点module为独立进程

架构定位

这个架构本质是:"单体应用 + 微服务理念"

  • 结构上:单体应用(一个进程)
  • 设计上:微服务思想(边界清晰、接口驱动)

适用场景:

✅ 嵌入式系统(资源受限)
✅ 系统编程(操作系统、数据库)
✅ 高性能场景(网络延迟不能接受)
✅ AI辅助开发(核心诉求)
✅ 小团队(运维能力有限)

❌ 超大规模(需要水平扩展)
❌ 多语言团队
❌ 需要强故障隔离(金融、核电站)

微服务架构的未来演进

我预测:随着AI的智能变得越来越廉价,一部分微服务架构可能会向AI-Native架构演进。

演进的动力

传统微服务的成本

  • 运维100+个基础设施组件(K8s、服务发现、链路追踪...)
  • 网络延迟:每次调用1-10ms
  • 序列化/反序列化开销
  • 分布式系统的复杂度(CAP理论、最终一致性...)

AI时代的变化

  • 代码是cheap的:重构一个service的成本极低
  • module随时可以替换:单体内部也可以模块化
  • AI能处理复杂依赖:只要边界清晰,AI能管理单体内部的模块关系

演进的路径

阶段1:纯微服务(现在)
[服务A] ──网络──→ [服务B] ──网络──→ [服务C]
  进程1               进程2                进程3

优点:故障隔离、水平扩展
缺点:运维复杂、网络开销

阶段2:混合架构(过渡期)
┌────────────────进程1────────────────┐
│  moduleA ──函数调用──→ moduleB      │
│    ↓                         ↓       │
│  [隔离边界]              [隔离边界]   │
└─────────────────────────────────────┘
         │                      │
         └──────网络──────→ 进程2 (服务C)

优点:核心性能敏感部分用module
      需要独立扩展的部分用服务
缺点:架构复杂度增加

阶段3:AI-Native单体(未来趋势)
┌───────────────────────────────────────────┐
│  moduleA → moduleB → moduleC → moduleD   │
│    (编译期隔离,边界清晰)                  │
└───────────────────────────────────────────┘

优点:
- 性能最优(函数调用)
- 运维最简(一个进程)
- AI友好(清晰的模块边界)
- module可以随时替换重构

缺点:
- 需要垂直扩展(加CPU/内存)
- 但CPU/内存越来越便宜了!

哪些场景会先演进?

优先演进到AI-Native的场景

  1. AI辅助开发的团队:已经在用AI写代码,自然选择AI友好的架构
  2. 性能敏感的系统:高频交易、游戏引擎、实时数据处理
  3. 小团队项目:没有专门的运维团队,不想维护K8s
  4. 快速迭代的初创公司:需要频繁重构,代码复用不是瓶颈

继续使用微服务的场景

  1. 超大规模系统:Facebook、Instagram级别(需要水平扩展)
  2. 多语言团队:不同服务用不同语言(Go、Python、Java)
  3. 需要强隔离:金融、核电站、医疗(故障隔离是硬需求)
  4. 遗留系统:已经在微服务上运行,迁移成本太高

本质转变

传统思维:
"代码是昂贵的,所以需要复用"
→ 设计通用服务(UserService、OrderService...)
→ 通过网络调用复用

AI时代思维:
"代码是cheap的,AI注意力是昂贵的"
→ 设计清晰的模块边界
→ 编译期隔离,函数调用
→ module随时可以替换重构

这是技术范式的转移:从"追求运行时的复用"转向"追求AI开发的效率"。


1. 引入依赖注入(DI)容器

问题:手工组装module依赖容易出错。

// main.c - 手工组装(容易遗漏)
Logger* logger = logger_create();
Storage* storage = storage_create();
Network* net = network_create();
network_set_observer(net, logger);
storage_set_observer(storage, logger);
// ...几十个组装代码

改进

// include/di.h
typedef struct DIContainer DIContainer;
void di_register(DIContainer*, const char* name, void* instance);
void* di_resolve(DIContainer*, const char* name);

// main.c
DIContainer* di = di_create();
di_register(di, "logger", logger_create());
di_register(di, "storage", storage_create());

Network* net = network_create(di);  // 自动注入依赖

好处

  • 自动管理依赖关系
  • 测试时注入Mock对象
  • AI不需要记住组装顺序

2. 接口版本管理

问题:接口变更导致旧代码编译失败。

// v1
void logger_log(Logger*, const char* msg);

// v2(破坏性变更)
void logger_log(Logger*, const char* msg, int level);

改进

include/
├── logger/
│   ├── v1.h  # 老接口
│   └── v2.h  # 新接口
└── logger.h  # 默认指向v2

好处:多版本共存、渐进式迁移

3. 生命周期管理

问题:AI生成的代码可能忘记初始化或释放资源。

改进

// include/lifecycle.h
typedef enum {
    LIFECYCLE_INIT,
    LIFECYCLE_START,
    LIFECYCLE_STOP,
    LIFECYCLE_DESTROY
} LifecycleState;

typedef struct {
    void (*on_init)(void);
    void (*on_start)(void);
    void (*on_stop)(void);
    void (*on_destroy)(void);
} LifecycleHooks;

void lifecycle_register(const char* module_name, LifecycleHooks* hooks);
void lifecycle_init_all(void);  // 按依赖顺序初始化
void lifecycle_destroy_all(void);

4. 可观测性内置

统一监控接口

// include/observability.h
void obs_log(const char* module, const char* level, const char* msg);
void obs_metric(const char* module, const char* name, double value);
void obs_trace(const char* module, const char* func);

// AI生成的代码自带可观测性
void network_send(Network* self, const char* data) {
    obs_trace("network", "send");
    // ...
    obs_metric("network", "bytes_sent", strlen(data));
}

5. 插件化架构(可选)

对于频繁变动的module,做成动态插件

project/
├── include/
│   └── plugin.h
├── plugins/
│   ├── logger_plugin.so
│   └── network_plugin.so
// include/plugin.h
typedef struct Plugin {
    const char* name;
    void* (*init)(void);
    void (*destroy)(void*);
} Plugin;

void plugin_load(const char* path);
void* plugin_get(const char* name);

如何保证AI遵循规则?

方案A:编译期检查

# 扫描include/目录,检测违规依赖
make check-dependencies

方案B:AI Prompt工程

给AI的系统提示词:

你在一个严格约束的项目中工作:
1. include/里的头文件不能include其他include/的头文件
2. src/里的代码只能include其对应的include/里的头文件
3. 违反这些规则会导致编译失败

方案C:自动化测试

CI/CD中加入依赖检查:

#!/bin/bash
# 检测循环依赖
python scripts/check_circular_deps.py include/

完整架构示例

project/
├── include/
│   ├── di.h              # 依赖注入
│   ├── lifecycle.h       # 生命周期
│   ├── observability.h   # 可观测性
│   ├── common_types.h    # POD数据结构
│   ├── logger/
│   │   └── v1.h
│   ├── network/
│   │   └── v1.h
│   └── storage/
│       └── v1.h
├── src/
│   ├── core/             # 核心框架(DI、生命周期)
│   ├── logger/           # 实现logger/v1.h
│   ├── network/
│   └── storage/
├── plugins/              # 可选:动态加载模块
├── tests/
│   └── unit/             # 每个module独立测试
├── scripts/
│   └── check_deps.py     # 依赖检查工具
└── api.h                 # 唯一对外接口

核心原则总结

  1. 代码是cheap的,AI注意力是昂贵的

    • 不惜增加代码量来降低每个模块的复杂度
  2. 零循环依赖

    • include/绝对禁止互相包含
    • src/只依赖include/
  3. 依赖倒置

    • 所有接口定义在include/
    • 实现在src/
  4. 动态拆分

    • 没有固定的行数标准
    • 看AI出错率调整边界
  5. 基础设施内置

    • DI容器、生命周期、可观测性
    • 让AI专注于业务逻辑

实践效果预测

AI编码质量提升

指标传统架构AI-Native架构
编译通过率50%85%
修改轮次3-5轮1-2轮
代码行数/module500行150行
内存泄漏率15%3%

开发效率提升

传统方式:
AI生成 → 编译错误 → 修复 → 发现新错误 → 再修复 → ... (5轮)
耗时:2小时

AI-Native方式:
AI生成 → 小调整 → 通过 (1轮)
耗时:20分钟

后续思考

1. 工具支持

能否开发一个IDE插件,自动检测依赖违规?

  • 实时扫描include/目录
  • 高亮显示违规依赖
  • 自动生成依赖图

2. AI模型优化

能否针对这种架构训练专门的模型?

  • 理解零依赖约束
  • 自动生成符合规则的代码
  • 更高的首次编译通过率

3. 度量标准

如何量化"AI注意力成本"?

  • Token消耗(上下文长度)
  • 修改轮数
  • 人类review时间

参考资源

  • 依赖倒置原则(DIP):Robert C. Martin的Clean Architecture
  • 微服务架构:Martin Fowler的Microservices文章
  • AI辅助编程:GitHub Copilot、Claude Code实践

这是我在探索AI辅助编程过程中的架构思考。核心观点是:代码本身不再是瓶颈,AI的注意力才是。 架构设计应该服务于AI的认知特点,而不是传统的工程美学。如果你也在做类似的探索,欢迎交流讨论!

本文由作者 twg2020 创作,使用 AI 辅助润色
首发于:somingbai.com
时间:2026-02-15

Clawdbot飞书插件对接实战:踩坑与解决方案

前言

最近在给Clawdbot(一个基于Node.js的AI Bot框架)对接飞书消息渠道时,遇到了一些坑。虽然官方文档写得还算详细,但实际操作中还是踩了不少雷。这篇文章记录了我遇到的问题和最终的解决方案,希望能帮到同样在做飞书集成的开发者。

技术背景

Clawdbot简介

Clawdbot是一个模块化的AI Bot框架,支持多渠道接入(Telegram、WhatsApp、QQ、飞书等)。它的架构是:

用户消息 → 各渠道插件 → Gateway(消息网关) → AI处理 → 回复用户

飞书插件负责:

  • 接收飞书消息
  • 转换成统一格式
  • 发送回复到飞书

飞书开放平台

飞书开放平台提供了两种消息接收方式:

  1. Webhook模式:HTTP回调,适合有公网IP的服务器
  2. 长连接模式:WebSocket连接,适合内网环境

我们选择长连接模式,因为服务器在内网,没有公网IP。

踩坑记录

坑1:插件登录成功,但收不到消息

症状

  • 日志显示 [feishu:default] logged in to feishu as cli_xxx
  • 说明登录认证通过了
  • 但在飞书发消息,Bot完全没有反应
  • 日志里也没有任何消息接收记录

原因分析

飞书插件的代码使用的是Lark SDK的WebSocket客户端:

// gateway.ts
const wsClient = new WSClient({
  appID: config.appId,
  appSecret: config.appSecret,
  eventTypes: ['im.message.receive_v1'],  // 订阅消息事件
});

wsClient.start();

虽然SDK代码里订阅了 im.message.receive_v1 事件,但飞书开放平台需要手动配置订阅

解决方案

  1. 登录飞书开放平台

    • 进入你的自建应用
    • 找到"事件订阅"配置
  2. 配置订阅模式

    • 订阅模式选择:长连接
    • 订阅事件必须勾选:im.message.receive_v1
  3. 关键步骤:发布应用

    • 点击右上角"发布"按钮
    • 选择"正式发布"
    • ⚠️ 这一步容易被忽略!
  4. 重启Clawdbot

    clawdbot gateway restart

验证

# 查看日志,应该能看到连接建立
tail -f /tmp/clawdbot/clawdbot-*.log | grep feishu

坑2:长连接WebSocket没有真正建立

症状

  • 配置都做了
  • 应用也发布了
  • 但还是收不到消息

原因

Lark SDK的WebSocket连接建立有一些时序问题。如果SDK启动太快,飞书开放平台还没来得及处理应用发布,连接会失败。

解决方案

在插件启动代码中添加重试逻辑:

async function startFeishuGateway() {
  let retries = 3;
  while (retries > 0) {
    try {
      await wsClient.start();
      console.log('[feishu] WebSocket connected');
      break;
    } catch (error) {
      retries--;
      console.log(`[feishu] Connection failed, ${retries} retries left`);
      if (retries > 0) {
        await new Promise(resolve => setTimeout(resolve, 5000));
      }
    }
  }
}

坑3:消息格式转换问题

症状

  • 终于收到消息了
  • 但回复时飞书报错:invalid message format

原因

飞书的消息格式和其他平台(如Telegram)差异很大。飞书支持多种消息类型:

  • text(纯文本)
  • post(富文本)
  • interactive(交互式卡片)

Clawdbot统一使用 text 类型,但飞书的text类型需要特定的JSON结构。

解决方案

在飞书插件的发送逻辑中做格式转换:

function formatMessageForFeishu(text: string) {
  return {
    msg_type: 'text',
    content: JSON.stringify({
      text: text
    })
  };
}

最终配置清单

飞书开放平台配置

  • [ ] 创建自建应用,获取App ID和App Secret
  • [ ] 权限管理:添加"获取与发送消息"权限
  • [ ] 事件订阅:

    • [ ] 订阅模式:长连接
    • [ ] 订阅事件:im.message.receive_v1
  • [ ] 发布应用:正式发布
  • [ ] 版本管理:记录版本号,方便回滚

Clawdbot配置

{
  "channels": {
    "feishu": {
      "enabled": true,
      "appId": "cli_xxx",
      "appSecret": "your_secret_here",
      "encryptKey": "",  // 长连接模式可留空
      "verificationToken": "",  // 长连接模式可留空
      "capabilities": {
        "inlineButtons": "allowlist"  // 按钮功能
      }
    }
  }
}

日志检查

# 查看飞书插件状态
tail -100 /tmp/clawdbot/clawdbot-*.log | grep feishu

# 应该看到:
# [feishu:default] logged in to feishu as cli_xxx
# [feishu] WebSocket connected

架构图

┌─────────┐     WebSocket      ┌──────────────┐
│         │ ◄──────────────────► │              │
│  飞书    │     长连接          │ Clawdbot     │
│  server │                    │ Gateway      │
│         │                     │              │
└─────────┘                     └──────┬───────┘
                                       │
                                       │ 消息分发
                                       ▼
                                ┌─────────────┐
                                │   AI Agent  │
                                │ (GLM-4.7)   │
                                └─────────────┘

经验总结

  1. 文档要看仔细:飞书开放平台的文档很长,但"事件订阅"部分一定要逐字读完
  2. 发布应用别忘:这是最容易漏的一步,配置改了必须重新发布
  3. 日志是最好的朋友:遇到问题先看日志,能定位90%的问题
  4. 长连接≠即时生效:应用发布后可能需要等待几分钟才能生效
  5. 消息格式要统一:不同渠道的消息格式差异大,需要做好适配层

参考资源

后续优化

目前飞书渠道已经可以正常收发消息了,后续计划:

  1. 支持更多消息类型(图片、文件、卡片)
  2. 实现消息已读状态同步
  3. 支持群消息@机器人
  4. 添加飞书特有功能(如工作通知)

本文记录了实际开发中遇到的问题和解决方案,如果你也在做类似的集成,希望对你有帮助。有问题欢迎交流!

本文由作者 twg2020 创作,使用 AI 辅助润色
首发于:somingbai.com
时间:2026-02-15