首页
/ HOMECORE-RECORDER 全解析:RuView 中用 HA 兼容 SQLite Schema 与 ruvector HNSW 构建的状态历史与语义检索

HOMECORE-RECORDER 全解析:RuView 中用 HA 兼容 SQLite Schema 与 ruvector HNSW 构建的状态历史与语义检索

2026-09-07 16:14:23作者:裴锟轩Denise

导读

homecore-recorder 是 RuView 项目 HOMECORE 生态(ADR-126 主导的原生 Rust Home Assistant 移植计划)中负责持久化状态历史语义检索的 Rust crate。它以 SQLite 为存储引擎,完整镜像 Home Assistant Recorder schema v48 的四张表结构与去重键约定,使 HOMECORE 可以直接读取用户已有的 HA home-assistant_v2.db;同时通过 feature-gated 的 ruvector 语义索引,把「查询历史状态」从传统的 SQL BETWEEN 升级为 HNSW 上的 k-NN 向量近邻检索。本文以 ADR-132 为骨架,结合 crate 源码逐层拆解其表结构、捕获链路、去重原理、双写架构、文本/语义双查询路径与安全加固结论,并给出可直接运行的构造与查询示例。

读完本文,你将掌握:HA Recorder schema v48 的关键表结构及其在 schema.rs 中的落地方式、RecorderListener 如何挂接 HOMECORE 事件总线、DedupEngine/FNV-1a 哈希去重的实现细节、P2 哈希嵌入语义检索的边界与 P3 演进方向,以及该 crate 经安全评审确认的各项加固(有界查询、事务化 purge、fail-closed 写入)。


1. 为什么 HOMECORE 需要一个 Recorder(决策上下文)

1.1 迁移与共存:复用 HA 的 on-disk Schema

ADR-126 决定用 Rust 原生重实现 Home Assistant 的数据模型与 API 契约。而 HA 本身把每次状态变更都写入一个 SQLite recorder 数据库,下游的历史曲线、logbook、长期统计、引用历史状态的自动化条件全部读取这份存储。HOMECORE 因此需要一条持久的"状态历史主干"。

决策由两股力量驱动:

  1. 迁移/共存成本。采用 HA 的用户手上已经有一份 HA 的 recorder 数据库。与其另起炉灶发明新 schema,不如直接复用 HA 的 on-disk schema——这样 HOMECORE 既能直接读取既有的 HA home-assistant_v2.db,HA 生态的工具也能直接读取 HOMECORE 生成的历史库。这与 ADR-165homecore-migrate 处理 .storage/*.json 时遵循的是同一条信任边界思路。
  2. 语义化查询的缺口。HA 的历史检索本质是 SQL BETWEEN/WHERE 行扫描,不支持自然语言语义查询。而 HOMECORE 平台已携带 ruvector(ADR-124)向量检索能力,所以 recorder 可以额外把状态变更向量化,用 k-NN 回答类似「下午 3 点哪些厨房设备是热的?」这类问题——这是 HA 本身不具备的能力。

1.2 Recorder 的承重定位

Recorder 是 HOMECORE 的 durable-state surface(持久化状态面):如果它出错,历史、logbook、基于历史条件的自动化会全部出错。ADR-164(ADR 语料缺口分析)曾将该 crate 标为 CRITICAL 覆盖缺口(Gap G3)——一个如此承重的 crate 却缺少治理性 ADR。本 ADR 属于 retroactive(追溯性)文档:crate 的 Cargo.tomlREADME.md、各源码文件都引用 "ADR-132",但它以 ADR-126 系列映射中规划的条目形式随 crate 一并发布;本文档记录的是已构建、已测试代码已蕴含的决策,不引入新设计。

说明:本 ADR 的「Deciders = ruv」,正式批准状态为 Accepted,日期对齐 crate intake 时期(2026-05-25),真实实现落盘提交 7c8071145 在 2026-06-11。


2. 决策总览:三阶段交付

ADR-132 的决策是把 homecore-recorder 做成一个带 HA 兼容 schema 的 SQLite 状态历史记录器,外加可选的 ruvector 语义索引,分三个阶段落地:

阶段 内容 状态 验证方式
P1 SQLite 结构化持久化(HA schema v48 兼容) 已构建、已测试 cargo test -p homecore-recorder --no-default-features(14 个测试)
P2 ruvector HNSW 语义索引(feature-gated,哈希嵌入) 已构建、已测试 cargo test -p homecore-recorder --features ruvector(20 个测试)
P3 ruvector-attention 真句向量嵌入(dim → 384) 计划中(未实现) README 与 Cargo.toml 中显式标注

lib.rs 的模块注释给出了 P1 数据流骨架:

StateMachine ──broadcast──► RecorderListener ──► Recorder
                                                    │
                                            ┌───────┴──────────┐
                                        states            state_attributes
                                        events            recorder_runs

Cargo.toml 头部注释则记录了 feature 矩阵与测试命令。默认构建不开启任何额外 feature(default = []),ruvector feature 只在显式指定 --features ruvector 时引入 ruvector-coresha2


3. P1 存储层:SQLite + HA Recorder Schema v48

3.1 依赖选型:只带 SQLite 后端的 sqlx

Cargo.toml 中的依赖取舍值得注意:

  • 通过 sqlx-core + sqlx-sqlite(均锁定 =0.8.6)而非 umbrella sqlx 包接入,避免把未使用的 MySQL 后端(及其易受攻击的 rsa 依赖)解析进 Cargo.lock。这也是一个供应链安全层面的刻意决策。
  • 时间处理用 chrono,序列化用 serde/serde_json,错误处理用 thiserror,结构化日志用 tracing,异步 trait 用 async-trait
  • SQLite 驱动开启 bundled(自带 SQLite),连接池上限为 4(见 db.rsopen_with_index)。

3.2 四张核心表:与 HA 1:1 对齐

schema.rs 用常量字符串形式给出了完整 DDL,镜像 HA 2025.1 引入的 schema v48

state_attributes —— 共享属性 JSON 块(按哈希去重)

CREATE TABLE IF NOT EXISTS state_attributes (
    attributes_id  INTEGER PRIMARY KEY NOT NULL,
    shared_attrs   TEXT    NOT NULL,
    hash           INTEGER NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS ix_state_attributes_hash
    ON state_attributes (hash);

shared_attrs 存 TEXT(JSON 块);hash 是对该 JSON 串做 FNV-1a 64-bit 后按有符号 i64 存储——这与 HA 的去重键完全一致。多个状态共享同一份属性时只保留一行,显著减少高频轮询传感器的写入 I/O。

states —— 每次状态写入一行

CREATE TABLE IF NOT EXISTS states (
    state_id         INTEGER PRIMARY KEY NOT NULL,
    entity_id        TEXT    NOT NULL,
    state            TEXT,
    attributes_id    INTEGER,
    last_changed_ts  REAL,
    last_updated_ts  REAL    NOT NULL,
    context_id       TEXT
);
CREATE INDEX IF NOT EXISTS ix_states_entity_id_last_updated_ts
    ON states (entity_id, last_updated_ts);
CREATE INDEX IF NOT EXISTS ix_states_last_updated_ts
    ON states (last_updated_ts);

entity_id 是校验过的 domain.name 字符串;state"on"/"off"/"20.5" 之类的状态值;attributes_id 外键指向 state_attributes(为 HA 兼容允许 NULL);last_changed_ts/last_updated_ts 为 REAL Unix 秒;context_id 为 UUID 文本,用于串联因果链。

events —— 领域事件

CREATE TABLE IF NOT EXISTS events (
    event_id      INTEGER PRIMARY KEY NOT NULL,
    event_type    TEXT NOT NULL,
    event_data    TEXT,
    time_fired_ts REAL NOT NULL,
    context_id    TEXT
);
CREATE INDEX IF NOT EXISTS ix_events_event_type_time_fired_ts
    ON events (event_type, time_fired_ts);

event_type 形如 "state_changed""call_service"event_data 为 JSON 块。

recorder_runs —— 启动/关停的边界记录

CREATE TABLE IF NOT EXISTS recorder_runs (
    run_id    INTEGER PRIMARY KEY NOT NULL,
    start_ts  REAL    NOT NULL,
    end_ts    REAL
);

记录每次 start/stop 对,供历史 API 标注数据缺口。

四张表的 DDL 全部使用 CREATE TABLE IF NOT EXISTS,因此 apply_schema幂等的——每次启动时重复应用都安全。实现细节见 db.rssqlx::query 不支持多语句字符串,代码先把每个 DDL 块按 ; 切分、逐条执行。

3.3 FNV-1a 去重哈希:与 HA 逐字节对齐

dedup.rs 实现了 HA db_schema.pyfnv64a 的精确副本,用于指纹化共享属性块:

  • Offset basis:0xcbf29ce484222325;Prime:0x100000001b3;每字节 hash = (hash XOR byte) * prime
  • 位重解释(bit-reinterpret)方式转成有符号 i64(而非数值转换),与 HA 完全一致。

源码注释里给出三个基准值,且均有单测锁定(见 dedup.rs):

输入 有符号 i64 结果
空串 "" -3750763034362895579
"a" -5808556873153909620
{"state": "on"} 3947789143477681127

在写入路径(db.rs record_state)中,该哈希承担属性去重职责:序列化 new_state.attributes → 计算 fnv64a_hash → 先按 hash 查已有 attributes_id 并复用,否则插入新 state_attributes 行。测试 same_attrs_dedup_to_one_row 验证了「两个实体共享同一份属性时只生成一行 state_attributes、却各自拥有独立 states 行」。

3.4 持久化位置与直接可查性

默认持久化路径为 .homecore/home.db(可通过构造函数入参配置),在 README.md 中有明示。Recorder::open 接收任意路径字符串,传 "sqlite::memory:" 即可获得内存库(测试广泛使用),传其余路径时以 create_if_missing(true) 自动建库建表。

选择标准 SQLite 意味着没有任何私有导出格式:任何能读 SQLite 的工具都能直接查询历史,无需经过 HOMECORE API。


4. P1 捕获层:监听事件总线,落库状态变更

4.1 RecorderListener 的订阅模型

listener.rs 实现了事件总线监听者:

  • RecorderListener::new(state_machine, recorder) 在构造时就调用 state_machine.subscribe() 完成订阅,而不是在 spawn() 之后——这保证 new()spawn() 之间触发的事件被缓冲在 receiver 队列中,不会被漏掉(源码注释明确说明了这一顺序性设计)。
  • spawn() 返回 JoinHandle,在优雅关停时调用 handle.abort() 即可。
  • 运行循环 run() 中三种退出/降级分支:
    • 正常收到 Ok(event) → 调 recorder.record_state(&event)
    • Lagged(n)(订阅者落后超过 4,096 个事件)→ 记录 warning 后从下一个可用事件继续,而非崩溃退出,因为「丢弃监听者」等同于静默停止持久化;
    • Closed(StateMachine 关停)→ 记录 debug 日志后正常退出。

Recorder 本身用 Arc 承载 SqlitePool 与语义索引,因此 Clone 极廉价,可以把副本同时交给监听者与 API 历史处理器。

4.2 谁把事件推进总线

ADR-126 的架构图里,homecore-recorder 订阅的是 ADR-127 定义的 HOMECORE 状态机 + Tokio broadcast 事件总线。crate 依赖 homecorepath = "../homecore"),并从 homecore::state::StateMachine 订阅 StateChangedEventlistener.rs 的集成测试展示了最小闭环:建内存 recorder → new + spawnsm.set(...) 触发两次状态变更 → 从 get_state_history 读回两行且顺序为 on/off。


5. P2 语义检索:ruvector HNSW(feature-gated)

5.1 SemanticIndex trait 与 NullSemanticIndex

db.rs 定义了可插拔的语义索引 trait:

  • insert_state(state_id, state):在 SQLite 插入成功之后被调用(state_id 即行 id,用于把向量结果映射回 SQLite 行);不得把错误回传给 recorder——失败只记日志,不阻断持久化(fail-closed 语义的另一面)。
  • search(query, k):嵌入自由文本查询,返回 (state_id, score) 升序距离列表。
  • NullSemanticIndex:在 ruvector feature 关闭时提供零分配的 no-op 实现,满足 trait bound,使结构化的存储主干不依赖 ruvector 即可独立发布。语义索引是可加的、feature 门控的——这是 ADR 列出的关键正面收益之一。

Recorder 内部用 Arc<RwLock<dyn SemanticIndex>> 持有索引,因此 trait 的 &mut self 方法无需调用方持有 &mut Recorder

5.2 P2 嵌入策略:SHA-256 哈希向量(诚实的占位)

semantic.rs 中,P2 嵌入刻意采用确定性哈希程序,避免在 P2 引入 ML 模型依赖:

  1. 把状态规范化为字符串 "{entity_id}={state}|{attributes_json}"
  2. SHA-256 → 32 字节;
  3. 每 4 字节解释为一个大端 i32,转成 f32,共 8 维;
  4. L2 归一化得到单位向量(norm > 1e-10 守卫)。

EMBEDDING_DIM = 8。搜索用余弦距离(匹配单位归一化向量)。crate 自述明确:哈希嵌入不捕捉语义相似度——两个状态值相同但实体 ID 不同的状态向量会不同。ADR 与 README 均反复强调:这是诚实的占位实现,提供了可工作的 HNSW 表面,但不得被引用为语义质量已验证

5.3 HNSW 配置与端到端行为

RuvectorSemanticIndex::new(max_elements) 使用 ruvector-coreVectorDB,配置如下(见 semantic.rs):

  • dimensions = 8distance_metric = Cosine
  • HnswConfig { m: 16, ef_construction: 100, ef_search: 50, max_elements }
  • 索引完全驻留进程内存——重启即清空,P3 才引入持久化。

文本兜底路径search_semantic(query, k)db.rs)先从向量索引取 top-k,若命中为空(默认 NullSemanticIndex 或尚无向量可查),则透明回退到真实 SQL 文本检索 search_states_by_text——调用方永远得到真实匹配行,而不是静默的空 Vec。该行为由测试 search_semantic_falls_back_to_text_with_null_index 锁定。

5.4 SQL 文本检索与 LIKE 元字符转义

search_states_by_text与 feature 无关的查询路径:大小写不敏感的 LIKEentity_idstate 值或属性 JSON 上做匹配,按 last_updated_ts DESC 取最近 k 条;空查询返回"最新活动"视图。所有参数均以 ? 绑定,其中唯一用 format! 构造的是 LIKE 的 pattern 串——该串本身作为绑定参数传入,并带 ESCAPE '\'% _ \ 转义。语义见测试 like_metacharacters_in_query_are_literal_not_wildcards:搜索文本中的 % 只会字面匹配 100%,而不是变成通配符。

5.5 语义查询示例(P2 形态)

--features ruvector 下,可构造最小可运行端到端流程:

use std::sync::Arc;
use tokio::sync::RwLock;
use homecore_recorder::{Recorder, semantic::RuvectorSemanticIndex, db::SemanticIndex};

let idx = Arc::new(RwLock::new(RuvectorSemanticIndex::new(1000)?));
let semantic: Arc<RwLock<dyn SemanticIndex>> = idx;
let recorder = Recorder::open_with_index("sqlite::memory:", semantic).await?;

// record_state(...) 之后,insert_state(state_id, state) 由 Recorder 内部自动调用。
// 用与嵌入相同的规范串查询,即可经 HNSW 找回对应 state_id:
let rows = recorder.search_semantic(&query, 5).await?;

注意:如上所述,P2 嵌入是哈希而非句子级语义,README 以注释形式保留了 P3 语义索引的调用设想(index.search("find all warm rooms at 3pm", 5)),并明确标注"尚未实现"。


6. 查询、恢复与清理:Recorder 的完整操作面

crate README 的能力表与 db.rs 的方法一一对应:

能力 类型 方法 说明
记录状态变更 监听 RecorderListener 订阅 HOMECORE 事件总线,写 SQLite
查询状态历史 SQL get_state_history / get_state_history_limited 标准 SQLite,处处可查
清理旧状态 维护 Recorder::purge(older_than) 事务化、exclusive 截止、GC 孤儿属性块
恢复最新状态 启动 Recorder::restore_latest(states, limit) 按实体 ID 排序、有界、隔离坏行
写入去重 去重 fnv64a_hash 属性哈希不变则复用行
语义索引 索引 SemanticIndex::insert_state(P2) 哈希嵌入;P3 换真句向量
语义搜索 搜索 search_semantic / search_states_by_text 向量优先、SQL 文本兜底

6.1 直接 SQL 查询示例(可复制运行)

读写直接经由 SQLite,README 给出了两条开箱即用的 SQL:

-- 近一小时内 light.kitchen 的全部状态变化
SELECT state, attributes, last_changed
FROM states
WHERE entity_id = 'light.kitchen'
  AND last_changed > datetime('now', '-1 hour')
ORDER BY last_changed DESC;

-- 按小时聚合亮度均值(JSON_EXTRACT)
SELECT
  strftime('%Y-%m-%d %H:00:00', last_changed) AS hour,
  JSON_EXTRACT(attributes, '$.brightness') AS brightness
FROM states
WHERE entity_id = 'light.kitchen'
GROUP BY hour;

6.2 启动恢复:latest_statesrestore_latest

latest_states(limit)db.rs)的核心是窗口函数查询:用 ROW_NUMBER() OVER (PARTITION BY entity_id ORDER BY last_updated_ts DESC, state_id DESC) 选取每个实体最新的一行,按实体 ID 升序输出,上限 100,000 行(MAX_RESTORE_STATES);坏行(非法 entity_id、缺 state、JSON 属性解析失败、非法时间戳、非法 context UUID)被逐个跳过并生成类型化 warning,单条损坏不影响其余实体恢复。restore_latestContext::restoration(parent_id) 标记恢复上下文,states.restore(state) 装回状态机且不产生新 recorder 事件,随后才启动 recorder 监听者与自动化引擎(见 ADR-132 §3a)。

6.3 事务化 purge:有界磁盘增长的答案

ADR 记载了一段真实教训:README 曾宣传 Recorder::purge,但长期缺失 retention 路径导致磁盘无界增长(Disk-DoS)。补齐后的 purge(older_than)db.rs)具备三重保障:

  1. Exclusive(排他)cutoff:只删 last_updated_ts < cutoff 的行,等于 cutoff 那一刻的行被保留——幂等、无 off-by-one,杜绝「保留窗口刚打开瞬间的行被误删」。
  2. 单事务原子性statesevents 删除与 state_attributes 孤儿清理(NOT IN (SELECT attributes_id FROM states ...))在同一事务内,中途失败整体回滚,绝不出现半清理状态。
  3. 共享块延迟 GC:被去重共享的属性块只有在最后一个引用它的 states 行消失后才会被回收。

测试 purge_gcs_orphaned_attributes_but_keeps_shared 精确验证:删除 sensor.a 时共享块仍被 sensor.b 引用 → 保留;再删除 sensor.b → 块孤儿 → 被 GC。purging 释放的是逻辑行;SQLite 会复用已释放页面,因此周期性 purge 下即便不做 VACUUM,磁盘增长也是有界的。


7. 有界查询:内存-DoS 防线(2026-06 安全评审修复)

ADR-132 §3a 记载了 2026-06 在 ADR-154–159 之后的一轮专项安全评审,homecore-recorder 被确认清理项与修复项如下。

7.1 修复项 1:get_state_history 无界 → 现在封顶

原实现无 LIMIT:宽时间窗 × 高频实体(如每秒轮询的功率传感器,约 86k 行/天)会把数百万行一次性载入内存 Vec。修复后 get_state_history 在 SQL 层硬性封顶 MAX_HISTORY_ROWS = 1_000_000db.rs),get_state_history_limited 允许调用方自选上限但再次取 min 封顶;需要更宽跨度的调用方必须收窄窗口分页读取。测试 history_query_carries_a_limit_clausehistory_caller_limit_is_applied_before_materialization 锁定「LIMIT 在物化前生效」。兄弟路径 search_states_by_text/search_semantic 本身已按 k 有界。

7.2 修复项 2:文档化但缺失的 purge

即上文 6.3 的事务化 purge 补齐(README 广告与实现之间的缺口被闭合,测试 19 → 25 / 25 → 31 全绿)。

7.3 确认无风险的项

  • SQL 注入 —— 干净db.rs 每个查询使用绑定 ? 参数,无任何用户或实体可影响的字符串经 format!/拼接进入 SQL;唯一 format! 只构造 LIKE pattern 且自身作为绑定参数 + ESCAPE '\'。测试 malicious_entity_id_is_stored_literally_not_executed 用一个状态值 '; DROP TABLE states; -- 证明 states 表完好且内容逐字往返。
  • NaN 索引投毒 —— 结构上不可能:嵌入为 SHA-256 → i32f32i32→f32 转换恒有限(绝不 NaN/Inf),全零摘要由 norm > 1e-10 守卫;空索引搜索、空串查询、k=0 均返回 Ok(0) 不 panic。语义索引路径无任何原始传感器 float 进入索引(与 calibration/vitals/geo 路径不同)。
  • Fail-closed 写入:移除事件返回 Ok(None);语义索引失败只记日志不阻断 SQLite 持久化;EntityId 解析失败回退到哨兵值(unknown.unknown)而非 panic。
  • 启动状态恢复latest_states(limit)(last_updated_ts, state_id) 决胜取每实体最新行、按实体 ID 排序、请求封顶 100,000 行、坏行带类型化 warning 跳过;restore_latest 保留原始时间戳并以 homecore.restore 上下文安装快照。

7.4 评审后的测试规模

homecore-recorder 测试规模从 19 → 25(--no-default-features)、25 → 31(--features ruvector),0 失败;Python 确定性证明不变(recorder 不在信号证明路径上)。


8. 后果与诚实边界(ADR-132 原文)

正面后果:

  • HA-schema 兼容令迁移与共存变便宜:HOMECORE 可直接读既有 HA recorder.db,任何 SQLite 工具也可读 HOMECORE 的历史库。
  • 语义索引是增量、feature-gated 的:承重的结构化 recorder 对 ruvector 无硬依赖,存储主干先行发布。
  • 标准 SQLite:无专有导出格式,历史直接可查。

负面 / 诚实限制:

  • P2 语义检索用哈希嵌入而非真句向量——查询质量在 P3 前有限;已在 crate 文档与本 ADR 双重披露,不得被引用为语义质量已验证
  • 尚无 per-crate 基准:README 中的延迟数字(状态写入 p50 < 2 ms、1 M 记录下语义搜索 < 10 ms)是设计目标/估算,需以 criterion 基线验证cargo bench -p homecore-recorder --features ruvector)。
  • 钉在 HA schema v48 上,把 HOMECORE 与特定 HA recorder schema 代际耦合;未来 HA schema 升级需要显式迁移步骤。

中性:

  • 本 ADR 只治理 recorder crate。recorder 数据之上的查询/REST 面属 ADR-130(P3);基于历史状态的自动化条件属 ADR-129(P3)。

性能参考口径(README 性能节,均标注"尚无 per-crate 基准,后续 issue 跟踪基线测量"):

  • 状态写入 p50 < 2 ms(SQLite WAL 追加)、p99 < 15 ms(磁盘 fsync);
  • 索引实体 ID 查询 < 1 ms;全表范围扫描 < 50 ms;
  • P2 语义搜索:1 M 状态记录下 k-NN < 10 ms(ruvector HNSW);
  • 每百万条记录内存开销约 ~10 MB(SQLite 索引开销);每条状态约 2–4 KB 磁盘(entity_id + 属性 + 时间戳)。

9. 快速上手:构建、测试与最小接线

在仓库 v2/ 工作区中:

# P1(无 feature):14 个测试
cargo test -p homecore-recorder --no-default-features

# P2(ruvector 语义索引):20 个测试
cargo test -p homecore-recorder --features ruvector

# 构建 P2
cargo build -p homecore-recorder --features ruvector

# criterion 基准(基线尚待建立)
cargo bench -p homecore-recorder --features ruvector

最小接线(P1,取自 crate README 的 Usage,整理为可直接阅读形态):

use homecore_recorder::{Recorder, RecorderListener};
use homecore::HomeCore;

#[tokio::main]
async fn main() {
    let homecore = HomeCore::new();

    // 创建 recorder(默认写 .homecore/home.db)
    let recorder = Recorder::new(".homecore/home.db").await.expect("init recorder");

    // 创建并 spawn 监听者(订阅在 new() 时立即生效)
    let listener = RecorderListener::new(homecore.state_machine(), recorder);
    listener.spawn();

    // 此后所有 StateChanged 事件都会持久化到 SQLite
}

注意:RecorderListener::new 在 crate 源码中接收 &StateMachine 并在内部 subscribe();上面 homecore.state_machine() 为示意调用形态,实际以 homecore crate(ADR-127)暴露的 API 为准。


10. 相关资源索引

综合来看,homecore-recorder 的价值在于双轨历史:一条 SQLite 结构化轨道承担「可迁移、可审计、可直接 SQL 查询」的持久事实;一条可选的 HNSW 向量轨道(P2 诚实占位、P3 演进到真句向量)为未来「用自然语言问历史」的能力铺路。若你正在 RuView 仓库中研究 HOMECORE 的历史子系统或规划 HA 兼容的本地智能家居枢纽,本文所述的 schema、去重、双写与加固结论都可直接作为源码级参考。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391