Commit Graph
785 Commits
Author SHA1 Message Date
qing d29bb5504a feat(aibox): L-batch profile polish (display name, prefix escape, temperature, reasoning aliases)
L1 display name: client.name now resolves to the profile's
display_name field, falling back to the profile key — the dialogue
context no longer labels Kimi/Qwen sessions "DeepSeek". The legacy
flat api section keeps "DeepSeek" (zero breakage).
_resolve_model_profile now returns (profile, model, profile_name).

L2 prefix escape: "model:NAME" forces bare-model semantics even when
a profile happens to be named NAME; "profile:NAME" forces profile
semantics and raises a clear error (listing available profiles) when
missing, instead of silently falling back to bare-name behavior.
Empty prefixes are rejected. Wired through --model / create_llm_client
/ subagent model params.

L3 profile temperature: new profile field "temperature" becomes the
client's default_temperature. chat_completion/stream_chat treat
temperature=None as "use profile default, else the old hardcoded
0.3/0.7", so explicit caller values still win. DeepSeekChat and
run_light_subagent resolve CLI > profile > constants.DEFAULT_TEMPERATURE.

L5 reasoning field aliases: _parse_delta recognizes
reasoning_content / reasoning / thinking / thinking_content (first
non-empty wins), so non-DeepSeek vendors' thinking streams are no
longer silently dropped.

L4 (cross-profile failover) intentionally deferred: streaming
failover needs request-replay semantics and is feature-level work.

Tests: new TestLBatch (16 cases); 7 existing unpack sites updated to
the 3-tuple. Full suite 315 passed.
2026-08-18 00:06:23 +08:00
qing a583f44d5d refactor(aibox): make profile reasoning_enabled a constructor param (M3)
Profile-level reasoning_enabled was attached as an instance attribute
after construction only when a profile matched; the base class never
declared it and consumers probed with double getattr. Any code that
accidentally set client.reasoning_enabled would silently override the
global switch.

The flag is now an explicit LLMClient constructor parameter with
three-state semantics: True/False (profile-level explicit, or the
global api.reasoning_enabled value concretized when the profile omits
the field) and None (no profile -> consumer falls back to global).
create_llm_client passes it at construction and no longer mutates the
client afterwards; DeepSeekChat._reasoning_enabled simplifies to a
single getattr probe that still tolerates clients without the attr.

Tests: TestM3ReasoningConstructor (4 cases) covering profile True,
profile-omitted -> global concretized, base default None, and the
None -> global fallback at the consumer; one legacy assertion updated
to the new contract (attribute exists, value None). Full suite 299
passed.
2026-08-17 23:58:45 +08:00
qing 5f3ca9a246 fix(aibox): sync compressor and snapshots on client swap via set_client (M1)
run_full_subagent replaced sub_chat.client by direct assignment after
construction, leaving ConversationCompressor (bound to the original
client in DeepSeekChat.__init__) and the api_key/name snapshots
pointing at the default model — compression requests silently kept
using the default endpoint/model while the dialogue itself used the
requested one.

DeepSeekChat gains set_client(): swaps self.client and refreshes
api_key, name, and compressor.llm_client in one place. run_full_subagent
now routes model overrides through it.

Tests: new TestM1SetClient (2 cases: full reference refresh on a real
DeepSeekChat instance, and run_full_subagent calling set_client with
the new client); full suite 295 passed.
2026-08-17 23:48:40 +08:00
qing 77262f8c3a fix(aibox): inject available model profile names into create_subagent (M2)
The LLM had no way to know which profile names exist in the models
config section; a hallucinated name fell through to bare-name semantics
(default endpoint + bogus model) and failed at request time with API
400.

SubAgentTool now builds the model hint dynamically from config via
_model_names_hint(): description and the model parameter's JSON Schema
description both list the profile names, with the default profile
(api.default_model) marked. Empty or malformed models sections keep
the original wording untouched (zero breakage); exceptions degrade to
no hint.

README: tool table note, test count 293, new v3.4 changelog entry
summarizing the H1/H2/H3/M2 profile-hardening batch.

Tests: new TestM2SubAgentModelHint (5 cases); full suite 293 passed.
2026-08-17 23:42:04 +08:00
qing 84a3f6dd5e fix(aibox): make --model effective in WebSocket server mode (H3)
--model was accepted by parse_args but only consumed inside
handle_once_mode, so `python aibox.py --model kimi` (server mode)
silently ignored the override.

The model now flows as a process-wide override:
main() -> EnhancedAIManager(model=...) -> DeepSeekChat(model=...) in
all three AI creation paths: add_ai (main dialogue),
WebSocketHandler._create_session_ai (per-connection sessions), and
TaskScheduler._create_task_ai (scheduled tasks). Manager logs
"CLI 模型覆盖已启用" at startup for observability. --once mode
plumbing is unchanged; --model=None keeps config-driven behavior.

Tests: new TestH3ModelPlumbing (6 cases) mocking DeepSeekChat to
assert the constructor kwarg across manager/session/task paths plus
parse_args; full suite 288 passed.
2026-08-17 23:37:59 +08:00
qing 0e9efe4895 fix(aibox): validate model profile schema at config source (H2)
Profiles previously had no validation, so config errors surfaced far
from their origin and cryptically:
- explicit profile missing `model` fell back to the profile NAME as the
  model (a profile named "local" would send "model": "local")
- default profile missing `model` with no model param produced
  "model": null -> API 400
- missing `api_url` surfaced as requests InvalidURL

_resolve_model_profile now runs _validate_profile (dict type + api_url)
before reading fields and _require_model on the effective model,
raising ValueErrors that name the profile, the missing field, and the
config.json path to fix. Bare model names still legally substitute for
a default profile's missing model field.

Tests: new TestH2SchemaValidation (6 cases: missing model/api_url,
null-model via default profile, bare-name substitution, non-dict
profile, e2e create_llm_client); full suite 282 passed.
2026-08-17 23:31:06 +08:00
qing 4480bce684 fix(aibox): never fall back to deepseek.key for model profile endpoints (H1)
~/.cert/deepseek.key is a DeepSeek-only credential; when a models profile
specified its own api_key_env (e.g. MOONSHOT_API_KEY) but the env var was
unset, resolve_api_key silently read that file and sent the DeepSeek key
as Bearer to a third-party endpoint (cross-vendor credential leak).

resolve_api_key gains allow_key_file (default True for the legacy flat
api section); create_llm_client passes allow_key_file=profile is None so
any profile path raises a clear RuntimeError instead, pointing users to
set the env var or use "" for local keyless endpoints.

Tests: new TestH1KeyIsolation (4 cases) with a mocked readable
deepseek.key proving the profile path errors out while the flat api
section still reads the file; full suite 276 passed.
2026-08-17 23:28:25 +08:00
qing 58725c8a12 docs: sync async inference loop into module docs
pybot --loop HEF 后端异步闭环(执行上一步动作与 NPU 推理并行)与 actpred predict_async 流水线落地后未同步文档,本次补齐:

- pybot/README:--loop 补异步推理路径说明(滞后一拍,~16ms→~12ms)

- actpred/README:Hailo 节新增 predict_async 小节(缓冲语义/2.6× 实测)

- 根 README、MODULES.md、ARCHITECTURE.md:pybot 行与机器人数据链同步

- MODULES.md:docs md 计数 70→76;ARCHITECTURE §9 挂 panel 设计稿规划项
2026-08-17 22:56:30 +08:00
qing 90f5544673 docs(aibox): changelog F2 (registry timeout cleanup + reader finalization)
Batch F bullet now split into F1/F2 entries; F2 covers unified
timeout-path cleanup of tool streaming attributes and reader-thread
finalization with the CPython stream-lock correction; test count 272.
2026-08-17 22:49:45 +08:00
qing 5bcf22f9a7 fix(aibox): registry timeout cleanup + reader thread finalization (F2/N6+N4)
N6: both streaming-forward timeout paths (deadline hit, join(5)
expiry) previously returned early and skipped the
tool.streaming_output / tool.output_queue cleanup, leaving the daemon
thread writing through the instance attribute — zombie output could
leak into the next session's queue once the attribute got reassigned.
Now unified through a timed_out flag with cleanup at the single exit;
stream_tool_timeout becomes an instance attribute (3600s default,
test-tunable).

N4: reader-thread finalization after timeout/grace break. First
implementation followed the audit suggestion (close stdout + join),
but PoC regression proved close() blocks: CPython stream objects hold
an internal lock, so closing while readline is blocked parks until
readline returns (PoC-1 regressed 3s -> 15.2s, exactly the
Start-Sleep duration). Corrected strategy: when reader already got
EOF, close stdout to release the pipe fd; when reader is still
blocked, only join(timeout=2) then give up (daemon-bounded, thread
ends naturally when the grandchild exits and EOF arrives), keeping
the main flow prompt. Audit report updated with this correction.

Tests: new tests/test_f2_fixes.py (5 cases), PoC regression 5/5
(PoC-1/4 back to ~5s), full suite 272 passed.
2026-08-17 22:47:37 +08:00
qing 6ef5d11d9d docs(aibox): sync README with Batch E/F security fixes
- feature list & tool table: set_proxy password semantics (memory-only,
  password_env for persistence)
- config example: fix stale flat proxy section to actual proxy.socks5
  structure with password_env; add plaintext-not-persisted note
- changelog: new v3.3 section covering Batch E (command exec protection
  chain) and Batch F (credential protection), test count 267
2026-08-17 22:41:24 +08:00
qing eb88a77238 fix(aibox): never persist SOCKS5 proxy password to disk (F1/N1, +N11)
- config.set_proxy gains password_env (aligned with api_key_env
  convention): config file persists only the env var name; plaintext
  password lives in memory for the current session only
- _save_config deep-copies and nulls proxy.socks5.password before
  json.dump, so every save path is sanitized (defense in depth)
- get_proxy resolves password as in-memory plaintext first, then via
  password_env from os.environ; downstream consumers (llm_client,
  web tool curl args) unchanged
- legacy migration on load: plaintext found on disk is kept in memory
  for the session, file is immediately rewritten sanitized
- SetProxyTool exposes password_env and reports password source
- registry debug logs mask password/api_key/token/secret/authorization
  kwargs (N11)

Tests: new tests/test_config.py (3 cases: no plaintext on save,
password_env resolution, legacy migration); full suite 267 passed.
Audit report updated with Batch F progress.
2026-08-17 22:37:30 +08:00
qing a833cd0d5f fix(memdb): expire semantics + Boost 1.83 portability + backlog & test harness
- expire 改为 update+refresh_ttl:键不存在返回 false,与 del/update 约定一致
- _require_string 适配 Boost 1.83(boost::json::string 已非 std::string)
- 新增 --backlog(默认 128,libmsg 默认 10 短连接突刺易丢连接)
- Makefile 补 HOST/PORT 默认值,test-memdb 用 PID 文件替代失效的 kill %1
- 补测试:复制构造/源销毁后副本有效/refresh 延长 TTL/expire 不存在键
2026-08-17 14:29:41 +00:00
qing 207137c0dd fix(libmemdb): deep-copy semantics so indices point into the copy's own list
默认复制只拷贝容器,keys/time_touch 中的迭代器仍指向源对象的 list 节点,
源销毁或改动后副本悬垂(UB)。改为保留时间戳的深拷贝构造 + copy-and-swap 赋值。
2026-08-17 14:29:39 +00:00
qing b2ecb8e12b fix(libmsg): close fd-reuse race silently killing short-lived connections
worker 收 EOF 失败后过早清除 busy 标记,事件循环对同一 fd 重复投递任务,
迟到的失败标记经 fd 复用落在新连接上被 _reap_failed 误杀(客户端收到空 EOF)。
失败路径改由 _reap_failed 统一清除 busy 并关闭;_handle_client 增加防重复投递守卫。
memdb 短连接压力测试错误率从 5-9% 降至 0。
2026-08-17 14:29:37 +00:00
qing 910ab8aa38 feat(pybot): 闭环异步推理——执行上一步动作与 NPU 推理并行
run_loop 自动检测 predictor.predict_async 走异步路径:提交推理后并行
执行上一步动作(滞后一拍,10Hz 下 100ms),隐藏真实 I2C 执行耗时;
同步路径不变。pybot 97 测试全过(新增异步路径 + 滞后一拍执行验证)。
2026-08-17 21:59:25 +08:00
qing 8de7f6696c feat(actpred): HailoPredictor 异步推理接口——run_async 流水线 2.6× 吞吐
新增 predict_async()(4 缓冲池 + 完成回调 + _AsyncJob.result),与同步
predict 语义/输出完全一致(重构公共 _prepare_inputs/_fill_bindings/
_postprocess)。真实 HEF 实测:连续吞吐 6.0ms vs 同步 15.5ms;扩展测试
10 seed 随机/60 任务乱序对应/混合调用/缓冲压力/300 次稳定性/4 线程并发
全部 0 差异,190 单测 OK。
2026-08-17 21:46:26 +08:00
qing 1348660cd8 docs(aibox): second-round audit re-review at HEAD 177a9ac
- Batch E fixes re-verified: H1/H3/M1 solid, H2 solid but with two
  residuals (reader thread leak, subagent timeout blind spot), M2
  incomplete (timeout paths skip tool attribute cleanup)
- Legacy M3/M4/L1/L3 confirmed unfixed; L1 found second instance at
  db.py:459 (get_immediate_memos)
- New findings: 1 high (SOCKS5 proxy password persisted in plaintext),
  9 medium (drain thread leak, event-loop blocking RLock, FTS5 keyword
  injection, streaming bypass of result length cap, persistent prompt
  injection storage, TOCTOU on mark_as_triggered, etc.), 7 low
- Updated compliance matrix and proposed Batch F fix plan (F1-F6)
2026-08-17 17:51:43 +08:00
qing 177a9ac9a6 fix(aibox): close audit findings H1-H3/M1-M2 (command exec protection chain)
- H1: CommandLineTool.execute_streaming now purely delegates to injected
  executor; removes 150-line duplicate Popen loop that bypassed 1MB cap,
  cancel() and timeout protections
- H2: thread the blocking readline into a daemon reader thread; main loop
  polls queue with 0.1s ticks so timeout/1MB checks fire even for silent
  commands (verified: 3s timeout on 15s sleep, was 15s+ before)
- H3: stdin=DEVNULL on both Popen sites; stdin-waiting commands now hit
  EOF instead of deadlocking the tool thread forever
- M1: heredoc delimiter uniquification in write_file guidance (content
  line equal to AIBOX_EOF no longer truncates into shell injection)
- M2: 3600s total deadline on registry streaming forward loop

Verification: PoC regression 5/5 PASS (timeout/1MB/cancel/delegation),
full unit suite 264 passed. Audit report updated with Batch E results.
2026-08-17 17:28:41 +08:00
qing ce142fe32f docs(aibox): sync once-mode docs (MODULES/ARCHITECTURE/dev-doc)
- MODULES.md/ARCHITECTURE.md:aibox 条目补 --once CLI 与 models 多模型档案(三处同步惯例)
- 开发文档新增第 7 节实施状态:四批提交映射、与计划的 4 处偏差(--once-timeout 改名/models 默认空/worker-only 精简 prompt/退出码 1 边界)、验证结果
- 原 7/8 节顺延为 8/9
2026-08-17 17:12:15 +08:00
qing d03dbc7f91 feat(aibox): batch D multi-model profiles + docs
- models 配置节:多 OpenAI Chat Completions 兼容端点按档案名切换,默认空 dict 零破坏回退旧 api 节
- --model 双语义:档案名(命中 models 节完整采用)/ 裸模型名(同端点换模型)
- resolve_api_key 档案级 env 三级语义:未配置回退 api.api_key_env / 显式名称 / 空串免密(Ollama/vLLM)
- 档案级 reasoning_enabled 附加 client 属性,DeepSeekChat._reasoning_enabled 优先读取
- llm_client 增加 openai_compatible/openai provider 别名
- README 更新:aibox/README 六处(特性/配置/多模型档案专节/CLI 参数/更新日志 v3.2/测试计数 264)+ 根 README aibox 小节
- 单测 17 项新增(test_models_profile.py),全套 264 项全过
2026-08-17 16:58:33 +08:00
qing a5af4bb404 feat(aibox): batch C once mode hardening
- SQLite WAL:subsystems/db.py 建库时 PRAGMA journal_mode=WAL,缓解多 CLI 进程并发写锁
- --worker-only CLI 参数:纯执行面模式(tool_profile=worker),注入精简 system prompt 避免人格/身份提示词污染
- --model / --temperature 覆盖参数:DeepSeekChat 构造透传,create_llm_client 与 stream_chat 两处生效
- 子代理工具失败透传:run_full_subagent(outcome) → SubAgentTool 打 _SUBAGENT_TOOL_FAILED_MARKER → _handle_tool_calls 检测置 orchestrator stats.tool_failed 并剥离标记
- Batch C 单测 5 项:worker profile 工具集、model/temperature 构造、子代理失败标记透传与剥离
2026-08-17 16:32:22 +08:00
qing 9e0d39c912 feat(aibox): batch B once mode refinements
- parse_args 新增 --no-save-memory / --show-reasoning
- DeepSeekChat.__init__ 增加 enable_memory 参数,干净禁用 MemoryTool(注册层不加入 schema)
- 修复 _think_and_respond_impl 压缩提示 print 污染 stdout:改走 output_callback(line)
- handle_once_mode 接入新参数:reasoning 默认静默 + show_reasoning 显式开启 + quiet 最高优先级
- 退出码 1 覆盖 orchestrator 工具异常(stats.tool_failed);worker 子代理非零码透传留 Batch C
- 新增 tests/test_once_mode.py(10 项:enable_memory 开关/回调分流/退出码状态/压缩提示不污染 stdout)
2026-08-17 16:00:45 +08:00
qing ce3fb7fc74 feat(aibox): add CLI once mode (--once/--quiet/--once-timeout)
- parse_args 新增 --once/--quiet/--once-timeout 参数
- 新增 handle_once_mode:stdout chunk 流式、stderr 过程行、SIGINT 三层取消、超时 Timer
- 退出码:0 成功 / 2 API 失败 / 3 中断 / 4 超时;与 WebSocket 零回归
- 配套开发文档:docs/reports/aibox_cli_once_mode_dev_doc.md
- 附带修复:memdb/test_memdb.py 并发测试硬编码端口
2026-08-17 15:45:06 +08:00
qing 2b133f1531 docs: cv2.LUT 优化验收测试报告 + 方案文档实测数据更新
200 次均值端到端 16.1ms(3.3×),分段 3.0/12.5/0.6ms——瓶颈已转移至
NPU 本身;一致性 7 类输入 + 8 seed 随机全 0 差异;10Hz 预算占用 16%。
2026-08-17 15:28:15 +08:00
qing 40523f6f8a feat(actpred): HailoPredictor cv2.LUT 快路径——归一化+量化合并,端到端 3.3×
帧预处理从 26.5ms 降至 1.7ms(15.8×),端到端 52.4 → 16.0ms。惰性导入 cv2、
无 cv2 自动回退 float 路径;非 uint8/非 3 通道/尺寸不匹配输入走 PIL 转换
与 float 路径语义一致(7 类输入实测 max_diff=0)。OpenCV 5.0 仅支持单通道
LUT,逐通道应用后 merge。依赖加入 requirements.txt。
2026-08-17 15:10:40 +08:00
qing 8a5162c912 docs: 修订 Hailo 预处理优化方案——查表法实测证伪,改合并乘加为主
原型实测:numpy 高级索引查表无加速(26.6 vs 28.5ms),预期 18-20ms 不成立。
主方案改为合并系数乘加(-5ms,0 LSB 等价),cv2.LUT 列为可选激进路径;
预期收益修正为 ~47ms(纯 numpy)/ ~25-30ms(cv2)。
2026-08-17 14:48:26 +08:00
qing 116d6b63bd docs: actpred Hailo 预处理优化方案——查表法合并归一化+量化
新 640×480 数据集实测端到端 52.4ms,预处理 35.9ms 占 68%(float 归一化
27.2ms + 量化绑定 9.1ms,存在中间 float 冗余)。方案:256 项查表合并
归一化与量化(数值等价),预计预处理降至 3-6ms、端到端 ~18-20ms。
2026-08-17 14:41:15 +08:00
qing 0fa32cb5e7 feat(actpred): HailoPredictor 适配 v4 onehot HEF——1864 logits 解码 + 固定列覆盖
v4 onehot 模型 HEF 输出 (1,1,1864),原回归假设(输出=action_dim)导致
输入分类与维度校验失败。_classify_inputs 改为 pred_token 先判(s[1]==1)、
其余 3 维归 history;_derive_dims 识别 TOTAL_BINS 输出;predict 经 bins.decode
期望值解码并固定权重 0 列(与 predict.py 同语义),新增 column_weights 参数。
_npu_test.py 指向 v4 并增加 onehot 参考分支,NPU 实测 4 角 PASS、
HEF vs torch max_diff 0.5°。
2026-08-17 14:29:21 +08:00
qing 63c29680ce docs: panel 微服务开发文档——背景视图聚合控件片段
设计稿:panel:9201 提供背景视图,各服务以 /panel-widget/<id>
暴露前端片段,面板拉取聚合后以 iframe 沙箱插入;含 postMessage
协议、BFF 转发、CSP 分层隔离与 M1-M4 实现阶段划分
2026-08-17 00:43:02 +00:00
qing 76afa37c6b fix(pybot): 录制 spk.F 恒 0 改为动态列查找——不依赖固定列号
原 recorder 按固定索引 SPK_F_COL=10 写 0,脚本列布局变化时会写错列;
改为 RobotStruct 录制前按设备名+参数名动态定位 frequency 列(无 Speaker
块返回 None 跳过),与模型固定输出契约一致,语义与 286e632 相同。
2026-08-16 16:17:55 +00:00
qing 293d71e86b fix(actpred): gen_calibration --deploy 的 is_range_mode 未导入即使用
import 在 if 分支内滞后于首次调用,fixed_range 归一化模型生成校准集
时直接 NameError;导入提前到 build_deploy_set 开头。
2026-08-16 16:17:10 +00:00
qing d8b601ab9a feat(bot4cj/scripts): 12 个 mtc DSL 源声明 Camera——录制免注入
动作脚本统一加入 Camera("cam0",640,480,30,8)(record_stand.py 已有),
编译产物自带 @Camera 块,pybot --record 直接可录,取代 v2 的
"注入式录制"变体方案。手写 .mt 保持不动(bot4cj 共享、美化格式)。
2026-08-15 19:48:16 +08:00
qing 286e632288 fix(pybot): 录制 spk.F 列恒 0——与模型 FIXED_OUTPUT 对齐
F2 方案下推理端 spk.F 固定输出 0(bins.FIXED_OUTPUT),而脚本真值
可达 1000Hz,保留真值产生"模型 0 vs 数据 1000"的评估伪影(14.5K)。
录制时写常量 0 消除伪影;spk.delay 微步录制下恒 10.0 已与模型一致。
data_v3(296MB 可复现录制产物)加入 .gitignore。
2026-08-15 19:48:09 +08:00
qing 37feb09185 fix(actpred): 固定 0 列未被覆盖——掩码按权重而非常量值
fixed_zero_columns 对 spk.F 返回常量 0,调用处掩码 fixed!=0 将其
排除,spk.F 垃圾预测(69-423Hz)继续进闭环。改为按权重<=0 掩码
覆盖(含固定 0 的列)。修正后舵机闭环 MSE 14477 假象 → 293 真实
(hand 类 55K 是固定 0 vs 真值 1000 的指标伪影)。+1 回归测试。
2026-08-15 10:02:49 +00:00
qing 8a9a061662 fix(aibox): 子代理返回截断修复——收尾报告自生成替换外部摘要器 2026-08-15 14:27:27 +08:00
qing 0be9e5d0d2 feat(bot4cj/scripts): 13 个 .mt 脚本的 mtc DSL 源码(新格式)
std/stdd/tilt-r/l/f/b/lie-down/jump/rght-hand/left-hand/left-turn/t0/record_stand 全部转为 Python DSL(mtc 编译器输入),与原 .mt 执行级等价:经 RobotStruct dry-run + EpisodeRecorder 验证,actions.npy 形状一致且逐元素相等,record_stand 的 imu.npy (100,8) 形状一致,编译零告警。

关键语义依据:pybot 微步对舵机列线性插值、对 spk.F 列不插值(行级阶跃),分别对应 SetTo 斜坡段与 Beep 恒值段;首行 delay=200 恒等分解对应 stand() 的 10ms 瞬时到位段。原 .mt 保留未动,可用各文件头注释中的编译命令重新生成。
2026-08-15 14:25:59 +08:00
qing a80aaabffe feat(actpred): 动作历史角度抖动增强——对抗微步样本相关性
微动作插值使相邻样本高度相关,有效多样性远低于样本数(过拟合根因
之一)。--action-jitter >0 时对输入历史加高斯噪声(σ=比例×列物理
范围,如 0.01=舵机±1.8°),制造虚拟邻近状态;且与闭环自预测历史
噪声同源,增强反馈鲁棒性。目标保持干净不抖动。默认 0=关,+2 测试。
2026-08-15 06:15:16 +00:00
qing 01126a5786 feat(mtc): .mt 脚本编译器落地 + pybot 扬声器静音语义
mtc 新模块:命令式动作脚本(Python DSL)→ .mt 矩阵编译器,非阻塞时间轴 IR(重叠截断/rest 静止值)+ 10ms 栅格化,产物可由 pybot/bot4cj 直接执行;34 测试全绿(含 pybot parser e2e)。

pybot speaker.py:frequency<=0 改为静音节拍(仅 sleep 保时序,不再钳到 min_f 低鸣),对齐仓颉版 sleep 占位语义;mtc Beep 通道 rest=0,段前/段间/段后回落静音,两侧语义闭环。

修复 test_actpred_compatibility 过时断言(99c1bc1 首行分解为重复微步 19→20 帧时漏改,14→15)。

文档三处同步:根 README 回填 memdb/pybot/actpred 并新增 mtc(模块表+端口一览+章节),MODULES/ARCHITECTURE 同步 mtc,新建 mtc/README.md。
2026-08-15 13:54:47 +08:00
qing 205a60f039 docs: 同步 MODULES/ARCHITECTURE 至 services.yaml 现状(memdb:8011/pybot/libmemdb) 2026-08-15 13:54:47 +08:00
qing 13beba09b4 docs(actpred): 研究方向 R8 细化——三层流水线离线 RL + 样本级验证集报告
R8 细化:预训练→监督微调→离线 RL 流水线定稿;IQL/CQL/DT 选型对比;
IMU 奖励工程四分量(姿态稳定/抖动/平滑/任务进度);三阶段落地路径。
新增样本级验证集划分实验报告(整集 60 样本噪声大 → 样本级 142 样本
更稳,F2b 在更难验证集上取得更低 val)。实现:val_split_mode 默认
sample,dataset sample_indices 过滤 + zscore 统计口径保持训练集专属。
2026-08-15 03:52:27 +00:00
qing 8cf3dd2d93 fix(fsys): dnfs 页面底部中文输入时页面反复横跳
IME composition 期间每个拼音字母都触发 input 事件,autoResizeTextarea 的塌陷测量(height='auto' 后读 scrollHeight 强制整页同步布局)使页面总高度反复变化,滚到底部时 scrollTop 被浏览器钳制又回弹。

- composition 期间跳过高度调整,compositionend 后统一调一次

- 塌陷测量后补偿被钳制的滚动位置,非 IME 场景(英文/粘贴/删除)同样防跳
2026-08-15 10:46:50 +08:00
qing 9000bb4b04 docs(actpred): 模型 B zscore 等权稳定基线文档 + spk 两列固定常量
B 是六模型闭环评估中唯一稳定配置(2445/0.082),固化完整方案作为
部署基线与实验对照基准,并总结归一化系列失败机理(反馈回路需误差
有界且收缩)。配套实现:spk.F/spk.delay 权重归零、推理/反馈固定
常量(bins.FIXED_OUTPUT),拔除闭环发散源,为 B2(zscore+v2)与
F2(onehot+固定)铺路。
2026-08-15 02:01:04 +00:00
qing 7f21b65428 fix(aibox): FTS5 中文检索 + Token 压缩阈值生效——Compressor 抽离解耦
- db.py: FTS5 改用 trigram 分词(中文可检索),旧 unicode61 表自动迁移回灌;search_memories 增加 LIKE 兜底(%/_ 转义、MATCH 异常防护)
- conversation_compressor.py: should_compress 补齐 Token 阈值判断(原为死配置),Token 触发时按比例压缩早期消息
- ConversationCompressor 抽离至 subsystems,注入 llm_client 打破与 DeepSeekChat 循环引用;aibox.py 3517→3018 行
- 新增 21 项测试(中文检索/旧表迁移/LIKE 转义/token 估算/压缩流程/失败回退),全量 232 项通过
2026-08-15 09:51:59 +08:00
qing 26de527a09 feat(memdb×libmemdb): memdb 服务化落地——RPC 服务端 + 构建/测试/部署闭环
- libmemdb: 补全 flush() 惰性 TTL 驱逐;修复 explicit 误用/头文件缺失/
  时间戳碰撞误删;size()/get_db() 前 flush 消除脏读;三处双重哈希查找
  合并;index_keys 去冗余字段;update(refresh_ttl) 改原地重索引,
  免 remove+insert 的拷贝与重复 flush
- memdb: 重写 RPC 服务端(libmsg RpcServer, :8011, 9 路由, mutex 保护);
  补全 Makefile/_set.sh/_run.sh 与 --instance/--log-level CLI;
  SIGINT/SIGTERM 优雅退出;注册 services.yaml
- 测试: libmemdb 单元测试 22 例 + memdb RPC 集成测试 12 场景(含并发)
- 清理: 删除误合入的 db2/create_sqlite3.sql 旧版(scripts/ 下为权威版)
2026-08-15 09:27:12 +08:00
qing a18a7de1ca feat(actpred): 多头 one-hot 分类输出——18 组独立 softmax 头替代连续回归
分箱(bins.py):舵机 1°/箱 ×10(180 箱,匹配 0.75° 微动作插值粒度)、
spk.F/spk.delay 对数 32 箱 ×2,共 1864 logits;保留位无头。软标签
(onehot_sigma=1.0 高斯扩散)缓解小样本数据稀疏;期望值解码恢复
连续分辨率(箱生活在原始空间,无反变换放大)。

训练损失为逐头加权 CE(列权重沿用),闭环反馈经解码→范围归一化
回写历史;predict 输出仍为 18 维原始量纲,pybot 契约零变化。

结构性消除尺度放大(每箱等距)与物理界问题(箱天然有界),
为 A-E 归一化实验失败后的正解路线。要求 normalize_mode 为范围类,
与 predict_delta 互斥。测试 +10(含 CLI 映射回归)。
2026-08-15 00:17:58 +00:00
qing 99c1bc1739 fix(pybot×actpred): 微动作录制时间轴均匀化——首行分解为重复步,delay 列权重归零
pybot run():带 delay 的首行(无前序状态)不再单步执行,分解为
N=delay//10 个重复微步(插值退化恒等),录制数据全 10ms 均匀节拍,
delay 列恒 10ms——行级时长信息已隐式编码在步数中,消除首行 200ms
造成的时间采样不均(frame_len/history_len 等间隔假设被破坏)。

actpred default_column_weights:spk.delay 权重 0.2→0.0(步级恒值列
无信号,与保留位同级);spk.F 保持 0.2。

新录制数据集(952 样本,delay 恒 10)存于 data/pybot_record_v2(不入库)。
2026-08-14 21:56:01 +00:00
qing 1cf428f384 feat(actpred): log_range 归一化——spk 两列对数尺度修正精度错配
fixed_range 线性 min-max 下常用值挤在低端(10Hz→0.002),闭环反馈
中小绝对误差=大相对误差(模型 C/D 发散根因)。新增 normalize_mode=
log_range:spk.F/spk.delay 用 log10(1+x) 对数尺度(10Hz→0.27),
舵机列保持线性。全链路接入(dataset/pretrain/predict/onnx/hailo/
calibration/export),与 v3 审计 none 模式/元数据自动识别合并。
2026-08-14 21:38:14 +00:00
qing fc310c9081 Merge branch 'dev_shufeng2012' into main
合入 dev_shufeng2012 分支:libmemdb 头文件 KV 库 + memdb 重构 + db2 SQLite schema

冲突解决:
- _inst.sh:保留 main 版本(已有 captcha2/smtp3/liblogc,dev 新增项重叠)

合入内容:
- libmemdb/:C++20 模板头文件 Memdb<T,U>(list+unordered_map+multiset,TTL KV 存储)
- memdb/:重构为 libmemdb 客户端 + RPC 服务骨架(含 src/memdb.cpp,Makefile/_run.sh/_set.sh 空文件占位)
- db2/create_sqlite3.sql:Users/Notes/Logs 三表 schema(含四个索引)

测试:pybot 89 passed,actpred 148 passed/18 skipped(全绿)
2026-08-15 04:58:29 +08:00
qing 9179281420 fix(pybot×actpred): v3 审计 P2 清零——验收链 fixed_range + 导出断言 + overrun 节流
- v3-P2-1: _npu_test/_onnx_validate 按 normalize_mode 分支(fixed_range 免 stats,
  HailoPredictor 透传模式,torch 参考同口径反归一化)
- v3-P2-2: export_deploy/export_onnx 一致性 diff 超 1e-4 即 sys.exit(P2-f 闭环)
- v3-P2-3: run_loop overrun 告警节流(第1次+每100次),降 hz 建议仅 >10% 输出
- P2-a1: default_column_weights 扩展列(action_dim>18)默认 1.0
- P2-c: 补 predictor 异常清理路径测试(异常传播 + finally 落盘)
- P2-d/P2-e: Resize 口径与 resume scheduler T_max 语义文档化
- R2-4: _set.sh 安装后断言 CPU 版 torch,误装 CUDA 即拦截
测试: pybot 89 passed (+1)、actpred 148 passed/18 skipped
2026-08-14 23:01:56 +08:00