AI 辅助编程
概述
DarraRT IDE 内置AI 编程助手, 在 SCL / LAD / CFC 编辑器中按 Ctrl+I 唤出 AI 面板, 通过自然语言指挥大模型生成代码、解释报警、排错、生成测试。AI 不替代工程师, 但能把工程师从重复劳动中解放出来:
标准 PID 模板、常见状态机、查手册翻寄存器地址、Nelson 规则硬编码这些都可以边说边生成。
安全边界: AI 生成的代码必须人工审核, 绝不允许 AI 直接部署到生产 PLC。IDE 会在 AI 写入的代码块上打 @ai-generated 标签, 提交前强制工程师签核。
适用场景
| 场景 | 输入 | 输出 |
|---|---|---|
| 代码生成 | 自然语言需求 + IO 映射 | SCL / LAD 片段 |
| 调试辅助 | 报错堆栈 + 日志 | 根因分析 + 修复建议 |
| 单元测试 | FB 签名 | 测试用例 (多组输入输出) |
| 报警解读 | 故障码 + 上下文 | 人话解释 + 建议 |
| 代码审查 | 已有 SCL | 风险提示 / 风格建议 |
| 文档生成 | FB 签名 + 注释 | Markdown 帮助 |
支持的模型
| 模型 | 部署 | 擅长 | 合规 |
|---|---|---|---|
| Claude Sonnet 4.5 / Opus 4.7 | Anthropic API | 代码 / 长上下文 | 海外 |
| OpenAI GPT-4.1 / o3 | OpenAI API | 通用 / 工具调用 | 海外 |
| DeepSeek V3 / R1 | DeepSeek / 国内代理 | 成本低 / 中文好 | 国内 |
| Qwen 2.5 Max / Plus | 阿里云 DashScope | 中文 / 工业术语 | 国内 |
| Ollama (本地) | 本机 / 内网 | 离线 / 数据不出厂 | 隔离环境 |
IDE 配置 (用户级 ~/.darra/ai.yaml):
ai:
default_provider: anthropic
providers:
anthropic:
api_key: ${ANTHROPIC_API_KEY}
model: claude-sonnet-4-5
max_tokens: 8192
openai:
api_key: ${OPENAI_API_KEY}
model: gpt-4.1
deepseek:
api_key: ${DEEPSEEK_API_KEY}
model: deepseek-chat
base_url: https://api.deepseek.com/v1
ollama:
base_url: http://localhost:11434
model: qwen2.5-coder:32b
temperature: 0.2
safety:
require_human_review: true
ban_deploy: true # AI 禁止触发部署
max_code_lines_per_request: 500
前置条件
- IDE 版本 ≥ 2.4
- AI Provider API Key 或本地 Ollama 运行
- 已登录 DarraRT (用于审计)
- 网络可达 (海外模型需代理 / 企业白名单)
提示词工程
给足上下文
差: "写个 PID"
好:
参考我当前工程:
- 变量: PT01 (REAL, 压力 bar)
- 输出: Y01 (4-20mA, 0..100%)
- 目标: MW200 (REAL, 目标压力)
需求: 恒压控制功能块
- 闭环 PID, Kp/Ki/Kd 可运行时调整
- 压力超过 3 bar 安全限立即停泵
- 积分分离: |误差| > 0.5 时不积分
- 抗饱和: 输出夹到 0-100%
- 启停由 M10.0 控制, 启动时平滑输出 (3s 斜坡)
请生成 SCL 代码, 以 `FUNCTION_BLOCK FB_PressControl` 声明。
约束输出
总是显式要求:
- 严格 IEC 61131-3 SCL 语法
- 变量类型标注完整 (REAL / INT / BOOL)
- 不得使用未声明变量
- 行数控制在合理范围
- 关键注释中文
分步思考 (Chain of Thought)
让 AI 先分析再写代码, 准确率提升明显:
第 1 步: 分析需求, 列出输入 / 输出 / 中间变量
第 2 步: 画状态机 (如果有)
第 3 步: 写 VAR / VAR_INPUT / VAR_OUTPUT 块
第 4 步: 写逻辑主体
第 5 步: 自检 (边界条件 / 除零 / 溢出)
多轮精化
第一轮让 AI 写骨架, 第二轮补边界, 第三轮加注释。不要一次问到位。
IDE 内嵌面板
按 Ctrl+I 唤出:
┌─────────────── AI 助手 (Claude Sonnet 4.5) ────┐
│ │
│ 工程上下文: [已附加 36 个变量, 4 个 FB] │
│ 选中代码: [10 行 (OB1:124-133)] │
│ │
│ 请输入需求 (Ctrl+Enter 提交, Esc 取消): │
│ ┌─────────────────────────────────────────────┐ │
│ │ 帮我给这段 PID 加抗饱和, 输出夹到 0..100%, │ │
│ │ 并把积分项限制在 ±50 │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ [插入] [替换] [对比] [放弃] │
└─────────────────────────────────────────────────┘
工作流:
- 光标所在 SCL 代码自动成为上下文
- 工程中已声明的变量表 / UDT / FB 签名作为上下文自动提供给 AI
- AI 返回的代码在面板显示, 支持对比 (左原始 / 右建议) 和部分采纳
- 采纳后自动打
// @ai-generated标签, Git 提交时 hook 强制审核
示例提示词
例 1: 计量泵恒压控制
给我写一个计量泵恒压控制 FB:
- 输入: PT01 (压力变量 REAL, 单位 bar)
- 输入: setpoint (目标压力 REAL, 绑 MW200)
- 输入: kp, ki, kd (REAL, 调节参数)
- 输入: start (BOOL, 启停)
- 输入: safetyLimit (REAL, 默认 3.0 bar)
- 输出: Y01 (4-20mA 模拟量 REAL, 0..100)
- 输出: alarm (BOOL, 超限报警)
要求:
1. 闭环 PID
2. 启动时 3 秒斜坡 (0→PID 输出)
3. 压力超 safetyLimit → Y01 = 0, alarm = TRUE, 锁定直到复位
4. 抗饱和: 积分夹 ±50, 输出夹 0..100
5. 停止时平滑降到 0 (1 秒斜降)
例 2: 解读报警
PLC 报警:
- 代码: 0xE1004
- 模块: EtherCAT
- 时间: 2026-04-18 14:23:11.456
- 上下文: WKC=9 实际=7, Slave[6] 消失
- 刚刚操作: 工程师热插拔了伺服电缆
请解释这是什么问题, 根因是什么, 如何恢复。
AI 应回答:
解读: WKC=9 是期望的工作计数器 (9 个从站各响应 1), 实际收到 7 说明
有 2 个从站没有响应. 结合 "Slave[6] 消失" 和 "刚热插拔伺服电缆",
根因基本可以确定: 伺服电缆拔出后, 第 6 号从站及其下游拓扑链路中断.
恢复步骤:
1. 恢复插线, 确认锁紧. DarraRT 的 L3 热插拔恢复会自动重建拓扑.
2. 若 2s 内未自动恢复, 在 IDE "诊断 → 网络诊断" 查看拓扑图,
确认 Slave[6] 重新在线 (APWR 身份校验通过).
3. 如果有 Ring 冗余且 Ring 闭合, 此次可能未触发产线停机.
4. 查 service_*.log 搜 L3Recovery 关键字确认恢复路径.
预防: 关键设备尽量用锁止型 M12 接头, 热插拔走 DarraRT 推荐流程
(先发 STOP 指令再拔线).
例 3: 生成测试
我有这个 FB:
FUNCTION_BLOCK FB_Limit
VAR_INPUT x : REAL; min_val : REAL; max_val : REAL; END_VAR
VAR_OUTPUT y : REAL; clipped : BOOL; END_VAR
IF x < min_val THEN y := min_val; clipped := TRUE;
ELSIF x > max_val THEN y := max_val; clipped := TRUE;
ELSE y := x; clipped := FALSE;
END_IF;
给我生成 10 组测试用例, 覆盖: 正常 / 边界 / 反转区间 / NaN / 最小最大 REAL.
AI 与工具调用
DarraRT IDE 让 AI 通过内置工具调用 (函数调用) 访问工程内部函数:
# 工具示例 (DarraRT 预置)
tools = [
get_variable_list,
get_fb_signature,
simulate_fb, # 本地仿真 FB 看输入输出
search_library, # 查标准库 FB
lint_st_code, # SCL 语法检查
read_plan, # 读 plan.md
write_plan,
]
AI 会主动调用工具, 比如"我先查一下库里有没有现成的 FB_Ramp, 再决定写新的还是复用"。
安全最佳实践
| 做 | 不做 |
|---|---|
| AI 代码人工审核后提交 | 直接 commit AI 代码 |
| 只给 AI 必要上下文 | 把整个密码文件发给 AI |
| 生产部署前过单元测试 | 相信一次生成就对 |
| 用 PR + CI 流程卡住 | AI 权限直连生产 |
| 审计所有 AI 请求日志 | 无记录 |
| 本地敏感项目用 Ollama | 敏感数据发公网 API |
排错
| 现象 | 原因 | 处理 |
|---|---|---|
| API 超时 | 网络 / 模型慢 | 改 timeout_s, 换 provider |
| 输出跑偏 | 温度太高 | temperature: 0.1 |
| 代码不能编译 | 上下文不全 | 附加变量表 + lint_st_code 工具 |
| 费用爆炸 | 频繁全工程附加 | 开 "选中范围" 模式 |
| 模型拒答 | 安全策略触发 | 换 provider 或降需求 |
高级技巧
- Prompt 模板库: 把常用提示词保存为
.prompt.md, 团队共享 - 角色化: 系统提示词设定 "你是 DarraRT 工程师, 只回答相关问题"
- 多模型裁判: 同一需求让 Claude 和 DeepSeek 都写, 工程师选
- RAG 文档检索: 知识库引擎把
docs/**做向量库, AI 自动引官方文档 - 离线微调: 把企业内部库 10 万行 SCL 作 LoRA 训练, Ollama 本地跑