EnerOS v0.31.0
发布日期:2026-01-18
版本代号:Cortex
Git Tag:v0.31.0
支持状态:稳定(Stable)
Crate 总数:54(新增 6 个)
测试用例数:7200+(新增 700)
概述
EnerOS v0.31.0「Cortex」是「智能化」阶段的关键版本,标志着 EnerOS 正式从「脚本化 Agent」迈向「认知型 Agent」。Cortex 取自大脑皮层之意,寓意 Agent 运行时获得了类似大脑皮层的推理与决策能力。本版本将大语言模型(LLM)作为操作系统的一等公民集成进内核,使每个绑定在电网节点上的 Agent 都能以自然语言进行任务规划、以结构化方式调用内核电力服务,并具备意图识别与自主工具调用能力。
Cortex 的核心设计哲学是「约束即法律」的延续——LLM 生成的任何动作建议都必须经过内核 ConstraintEngine 的强制校验与投影,AI 不能绕过物理约束。这使得 EnerOS 在引入 LLM 不确定性的同时仍能保证电网运行安全。本版本引入五大核心能力:LLM 集成框架、自然语言查询、意图识别、工具调用、Agent 推理链。
关键数据
| 指标 | 数值 | 说明 |
|---|---|---|
| LLM 调用延迟 P99 | 320ms | 远程后端 |
| 意图识别准确率 | 96.8% | 电力领域测试集 |
| 工具调用成功率 | 99.2% | 含约束投影 |
| 自然语言查询响应 | < 500ms | 含向量检索 |
| 新增 Crate | 6 | AI 相关 |
| 新增测试 | 700+ | 含 120 个端到端 |
新特性
1. LLM 集成框架
新增 eneros-llm crate,统一封装主流 LLM 后端的接入,支持本地推理(llama.cpp / candle)与远程 API(OpenAI / Anthropic / Azure / 通义千问 / 文心一言),并内置 Token 预算、流式输出、超时熔断、用量审计四项治理能力。
后端适配器
| 后端 | 协议 | 部署形态 | 适用场景 |
|---|---|---|---|
| OpenAI Compatible | HTTP / SSE | 远程 | 通用、低延迟 |
| Anthropic Claude | HTTP / SSE | 远程 | 长上下文、推理 |
| Azure OpenAI | HTTP / SSE | 远程 | 企业合规 |
| llama.cpp | 本地 | 边缘 / 离线 | 数据不出场 |
| candle | 本地 | 纯 Rust | 嵌入式 |
| 通义千问 | HTTP | 远程 | 国内合规 |
| 文心一言 | HTTP | 远程 | 国内合规 |
统一调用接口
use eneros_llm::{LlmClient, LlmRequest, Message, Role};
// 创建客户端(通过配置文件指定后端)
let client = LlmClient::from_config("llm.openai").await?;
// 构造请求
let request = LlmRequest::new()
.system("你是一个电力调度助手,回答需要符合电网运行规程。")
.user(Message::new(Role::User, "当前 110kV 母线电压 0.88pu,是否需要调整?"))
.temperature(0.2)
.max_tokens(1024)
.timeout(Duration::seconds(15));
// 流式输出
let mut stream = client.stream(request).await?;
while let Some(chunk) = stream.next().await {
print!("{}", chunk.delta?);
}
Token 预算与审计
每个 Agent 拥有独立的 Token 预算账户,避免失控的 LLM 调用消耗过多资源:
use eneros_llm::budget::{TokenBudget, BudgetPolicy};
let budget = TokenBudget::new()
.daily_limit(500_000)
.per_request_limit(8192)
.policy(BudgetPolicy::RejectWhenExceeded);
agent.set_llm_budget(budget);
所有 LLM 调用都会自动落盘审计日志,包含 prompt 摘要、模型版本、Token 数量、耗时、调用者 Agent ID,满足等保 2.0 三级要求。
2. 自然语言查询
新增 eneros-nlq crate,允许运维人员以自然语言查询电网运行状态。NLQ 引擎将自然语言转换为结构化的内核系统调用,底层结合向量检索与 schema-guided 生成。
查询示例
use eneros_nlq::{NlqEngine, NlqQuery};
let engine = NlqEngine::new(&ctx)
.with_schema(&topology_schema)
.with_history_db(×eries)
.build().await?;
// 自然语言查询
let query = NlqQuery::from_text("昨天 14:00 到 16:00 之间,母线 5 的电压变化趋势如何?");
let result = engine.execute(query).await?;
// result 包含:原始问题、生成的系统调用、查询结果、自然语言回答
println!("{}", result.answer);
// "在 2026-01-17 14:00-16:00 期间,母线 5 电压从 1.02pu 下降至 0.97pu,
// 最低点 0.96pu 出现在 15:23,未越限但接近下限。"
查询能力矩阵
| 查询类型 | 示例 | 底层 syscall |
|---|---|---|
| 实时状态 | ”母线 1 当前电压多少” | GetBus / QueryTimeSeries |
| 历史趋势 | ”过去 24 小时负荷曲线” | QueryTimeSeries |
| 拓扑分析 | ”发电机 G1 连到哪条母线” | GetBus / GetNeighbors |
| 约束检查 | ”线路 L-3 是否过载” | CheckConstraint |
| 故障追溯 | ”上次跳闸是什么原因” | QueryEventLog |
| 统计聚合 | ”今天平均频率多少” | QueryTimeSeries + Avg |
3. 意图识别
新增 eneros-intent crate,将用户的自然语言输入分类为电力领域意图,决定后续的执行路径。意图识别结合规则匹配与 LLM 分类,实现高准确率与低延迟。
意图分类体系
| 一级意图 | 二级意图 | 示例 |
|---|---|---|
| 查询 | 实时查询 | ”母线 1 电压多少” |
| 查询 | 历史查询 | ”昨天负荷曲线” |
| 查询 | 拓扑查询 | ”G1 接在哪” |
| 操作 | 开关操作 | ”合上开关 42” |
| 操作 | 出力调整 | ”把发电机 G2 出力调到 80MW” |
| 分析 | 故障分析 | ”为什么线路跳闸了” |
| 分析 | 趋势预测 | ”明天负荷峰值多少” |
| 报告 | 生成报告 | ”生成本周运行周报” |
意图识别器
use eneros_intent::{IntentRecognizer, Intent};
let recognizer = IntentRecognizer::new()
.with_rules(&power_domain_rules) // 规则优先匹配
.with_llm_fallback(client.clone()) // 规则未命中时用 LLM
.confidence_threshold(0.85);
let intent = recognizer.recognize("把母线 3 的电容器投入运行").await?;
match intent {
Intent::Operation { action, target, params } => {
// action = "switch_capacitor"
// target = BusId(3)
// params = { state: "on" }
ctx.syscall(ExecuteCommand(action.into())).await?;
}
_ => { /* ... */ }
}
4. 工具调用
新增 eneros-tool crate,将内核电力服务注册为 LLM 可调用的工具(Tool),使 LLM 能够自主决定调用哪些内核能力。工具调用结果会回灌给 LLM 进行下一步推理,形成 ReAct 循环。
工具注册
use eneros_tool::{ToolRegistry, Tool, ToolSchema};
let mut registry = ToolRegistry::new();
// 注册内核电力服务为工具
registry.register(Tool::new("get_bus_voltage")
.description("获取指定母线的实时电压(标幺值)")
.schema(ToolSchema::object()
.field("bus_id", "integer", "母线编号"))
.handler(|args, ctx| {
let bus_id: u32 = args.get("bus_id")?;
let bus = ctx.syscall(GetBus { id: bus_id })?;
Ok(json!({ "voltage_pu": bus.voltage.magnitude }))
}))?;
registry.register(Tool::new("set_generation")
.description("设置发电机出力(MW)")
.schema(ToolSchema::object()
.field("bus_id", "integer", "发电机所在母线")
.field("mw", "number", "目标出力"))
.handler(|args, ctx| {
let bus_id: u32 = args.get("bus_id")?;
let mw: f64 = args.get("mw")?;
ctx.syscall(SetGeneratorOutput { bus: bus_id, mw })?;
Ok(json!({ "success": true }))
}))?;
ReAct 循环
use eneros_reasoning::{ReactAgent, ReactConfig};
let agent = ReactAgent::new(client, registry)
.max_steps(8) // 最多 8 轮推理
.step_timeout(Duration::seconds(10));
let result = agent.run(
"母线 1 电压偏低,请调整发电机出力使其恢复到 0.98pu 以上"
).await?;
// Agent 自主执行:
// 1. 调用 get_bus_voltage(bus_id=1) -> 0.92pu
// 2. 调用 list_generators(island=...) -> [G1, G2]
// 3. 调用 set_generation(bus_id=1, mw=90)
// 4. 调用 get_bus_voltage(bus_id=1) -> 0.99pu
// 5. 输出:"已将发电机 G1 出力调整至 90MW,母线 1 电压恢复至 0.99pu"
工具调用安全模型
所有工具调用都经过安全网关的约束校验:
let result = agent.run("把发电机 G1 出力调到 200MW").await?;
// 内核约束校验:G1 额定容量 100MW
// LLM 建议被投影为 100MW,并返回警告
5. Agent 推理链
新增 eneros-reasoning crate,提供结构化的推理链,支持 ReAct、Plan-and-Execute、Tree-of-Thoughts 三种推理模式。
推理模式对比
| 模式 | 适用场景 | 步数 | 延迟 | 准确率 |
|---|---|---|---|---|
| ReAct | 实时交互 | 1-8 | 低 | 高 |
| Plan-and-Execute | 复杂任务 | 10-50 | 中 | 很高 |
| Tree-of-Thoughts | 决策优化 | 20-100 | 高 | 最高 |
改进
- Agent 通信:Agent 间消息序列化从 JSON 改为 bincode,延迟降低 40%
- 向量检索:
eneros-memory向量索引支持 HNSW,检索延迟从 50ms 降至 3ms - Token 审计:审计日志支持按 Agent、按模型、按时段多维聚合查询
- 约束投影:约束投影器新增序列二次规划(SQP)求解器,收敛速度提升 3 倍
- 安全网关:工具调用路径增加沙箱隔离,限制文件系统与网络访问
Bug 修复
- 修复
eneros-llm在流式输出时连接池耗尽导致后续请求阻塞的问题(#3102) - 修复
eneros-reasoning在 ReAct 循环中工具调用失败后未正确回退的问题(#3108) - 修复
eneros-intent规则匹配器在中文分词时内存越界的问题(#3115) - 修复
eneros-nlq时序查询时区转换错误导致结果偏移 8 小时的问题(#3120) - 修复
eneros-tool工具 schema 校验对嵌套对象处理不正确的问题(#3125)
破坏性变更
Agent::run签名变更:新增llm_ctx: &LlmContext参数,原签名迁移至Agent::run_classicalToolRegistry::register:返回类型从()改为Result<()>,需处理冲突Intent枚举:Intent::Unknown重命名为Intent::Unrecognized
升级指南
- 更新
Cargo.toml中的eneros依赖至0.31.0 - 运行
eneros migrate 0.31.0自动迁移 Agent 代码 - 在
eneros.toml中配置 LLM 后端与 Token 预算 - 参考迁移文档调整
Agent::run签名
致谢
感谢 22 位贡献者提交的 340+ 个 commit,以及电力行业合作伙伴提供的领域知识验证。