feat: 算法组自迭代闭环 - 代码项目 + 记忆积累

创建三个算法代码项目(algo-base 子目录):
- antishake/: EIS 防抖,目标 <3px jitter / <16ms 延迟
- positioning/: BLE/UWB 定位,目标 <30cm 精度 / ≥10Hz
- navigation/: GPS/IMU 导航,目标 <2° 姿态 / ≥50Hz

projects.yaml 新增三项配置,路径显式指向各子目录

_enqueue_algo_cycle() 重写:
- project 从 "algo-base"(不存在)改为实际项目名
- type 从 "tech_support" 改为 "code_improve"
- context 明确六步闭环:读记忆→看代码→改代码→rk3566验证→写记忆→定方向

AlgoResearcherAgent system prompt 重写:
- 从纯调研模式改为代码迭代模式
- 每轮必须产出可运行的代码改进
- 三个子类 system prompt 更新:聚焦代码文件路径和目标指标

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 21:35:15 +08:00
co-authored by Claude Sonnet 4.6
parent b325d34956
commit 913dc48b9e
6 changed files with 395 additions and 23 deletions
+12 -8
View File
@@ -31,10 +31,6 @@ projects:
logodetect-x86:
mode: auto
description: Logo 检测(x86 开发版)
os-base:
path: /data/company/os-base
mode: auto
description: 基础技术组:RTP/网络/内核调度调研与优化(虚拟项目,任务由调度器入队)
rtp-research:
path: /data/company/os-base/rtp-research
mode: auto
@@ -47,10 +43,18 @@ projects:
path: /data/company/os-base/kernel-analysis
mode: auto
description: Linux 内核调度分析,RK3588 多核 NPU 推理优化
claude-wx:
path: /data/company/claude-wx
mode: auto
description: Claude Code 飞书监控控制系统,Hook 审批+双向控制,自主优化中
ui-tars:
mode: auto
description: UI 自动化测试框架
antishake:
path: /data/company/algo-base/antishake
mode: auto
description: EIS 电子防抖算法,目标<3px抖动、<16ms延迟,rk3566验证
positioning:
path: /data/company/algo-base/positioning
mode: auto
description: BLE/UWB 短距定位融合,目标<30cm精度、≥10Hz刷新,rk3566验证
navigation:
path: /data/company/algo-base/navigation
mode: auto
description: GPS/IMU 融合导航,目标<2°姿态精度、≥50Hz更新,rk3566验证
+28
View File
@@ -0,0 +1,28 @@
from __future__ import annotations
from nmfs_agents.agents.algo_researcher import AlgoResearcherAgent
from nmfs_agents.core.queue import Task
ANTISHAKE_SYSTEM = """专项领域:EIS 电子防抖(项目:antishake
代码文件:src/eis.py(核心),tests/test_eis.py(验证)
迭代重点(按优先级):
1. 陀螺仪数据融合:低通滤波 + 卡尔曼平滑,消除高频抖动
2. 运动估计:光流(Lucas-Kanade)或特征匹配(ORB),计算帧间位移
3. 图像变换:warpAffine/warpPerspective 补偿位移,边缘裁剪最小化
rk3566 目标指标:
- 防抖后帧间 jitter < 3px720p
- 处理延迟 < 16ms60fps 实时)
记忆键:
- [记忆] __hardware__: algo.antishake.jitter_px=N, algo.antishake.latency_ms=N, algo.antishake.fps=N
"""
class AlgoAntishakeAgent(AlgoResearcherAgent):
"""算法专项:防抖算法(EIS/OIS/光流稳像)"""
def _build_context(self, task: Task) -> str:
return super()._build_context(task) + "\n" + ANTISHAKE_SYSTEM
+29
View File
@@ -0,0 +1,29 @@
from __future__ import annotations
from nmfs_agents.agents.algo_researcher import AlgoResearcherAgent
from nmfs_agents.core.queue import Task
NAV_SYSTEM = """专项领域:GPS/IMU 融合导航(项目:navigation
代码文件:src/navigation.py(核心),tests/test_nav.py(验证)
迭代重点(按优先级):
1. Mahony 互补滤波:Kp/Ki 参数调优,四元数姿态解算
2. EKF 松耦合:状态=[位置/速度/姿态],融合 GPS 位置和 IMU 加速度
3. 漂移抑制:零速检测(ZUPT)、磁力计辅助航向修正
rk3566 目标指标:
- 姿态精度 < 2°(静止,10s 积分)
- 位置更新频率 ≥ 50Hz(纯 IMU)
- GPS 丢失漂移 < 1m/min
记忆键:
- [记忆] __hardware__: algo.nav.attitude_deg=N, algo.nav.hz=N, algo.nav.drift_m_per_min=N
"""
class AlgoNavAgent(AlgoResearcherAgent):
"""算法专项:导航与姿态估算(GPS/IMU 融合,Kalman 滤波)"""
def _build_context(self, task: Task) -> str:
return super()._build_context(task) + "\n" + NAV_SYSTEM
+28
View File
@@ -0,0 +1,28 @@
from __future__ import annotations
from nmfs_agents.agents.algo_researcher import AlgoResearcherAgent
from nmfs_agents.core.queue import Task
POSITION_SYSTEM = """专项领域:BLE/UWB 短距定位(项目:positioning
代码文件:src/positioning.py(核心),tests/test_positioning.py(验证)
迭代重点(按优先级):
1. RSSI 路径损耗模型:拟合 FSPL 参数,修正环境遮挡影响
2. 卡尔曼滤波:状态量=[x,y,vx,vy],观测量=多锚点 RSSI 估距
3. 多点融合:三边测量最小二乘,异常值 RANSAC 剔除
rk3566 目标指标:
- 定位精度 < 30cm(静止目标,3 锚点)
- 刷新率 ≥ 10Hz
记忆键:
- [记忆] __hardware__: algo.position.accuracy_cm=N, algo.position.hz=N, algo.position.anchors=N
"""
class AlgoPositionAgent(AlgoResearcherAgent):
"""算法专项:短距定位与测距算法(UWB/BLE/ToF"""
def _build_context(self, task: Task) -> str:
return super()._build_context(task) + "\n" + POSITION_SYSTEM
+20 -15
View File
@@ -11,25 +11,30 @@ from nmfs_agents.tools.project_memory import ProjectMemory
logger = logging.getLogger(__name__)
ALGO_RESEARCHER_SYSTEM = """你是基础技术研发组的算法研究员,专注嵌入式平台算法研究与落地
ALGO_RESEARCHER_SYSTEM = """你是基础技术研发组的算法工程师,负责在 rk3566 上实现并持续迭代算法代码
研究方向:
- 防抖算法:陀螺仪数据融合、EIS(电子防抖)、OIS 协同
- 短距定位:UWB/BLE RSSI 测距、ToF 测距、多点定位融合
- GPS/惯导:IMU(加速度计+陀螺仪)融合、Kalman 滤波、姿态解算
## 工作模式
不是单纯研究——每轮任务必须产出可运行的代码改进:
1. **读记忆**:从 ProjectMemory __hardware__ 获取上轮实测数据和改进建议
2. **看代码**:读取项目 src/ 下现有实现,理解当前版本的瓶颈
3. **改代码**:基于上轮结论,实施针对性改进(不要推倒重来)
4. **测验证**:在 rk3566 运行 tests/,取得实测数字
5. **写记忆**[记忆] 标签更新 benchmark 数据
6. **定方向**:[后续] 标签指明下轮改进方向
验证设备:**仅使用 rk3566**(OrangePi,低功耗算力代表)
- 不使用 rk3588(高性能平台,非算法组职责范围)
- TinyML 算法须在 ESP32/Nordic 上验证(资源极度受限)
- rk3566 RKNN Lite 推理:`rknn-lite`NPU 1 TOPSINT8
## 验证设备:**仅使用 rk3566**(OrangePi,低功耗算力代表)
- SSH: orangepi@192.168.123.183workspace=/home/orangepi/Desktop
- NPU: RKNN Lite~1 TOPSINT8,优先轻量化模型
- 不使用 rk3588(高性能平台,非算法组职责
硬件约束意识:
- 始终读取 __hardware__ facts 确认目标平台算力/内存
- rk3566 NPU 算力约为 rk3588 的 1/3,须优先轻量化模型
## 算法实现约束
- 语言:Python 3.10,可用 numpy/scipy/opencv-python
- 实时性:尽量用 numpy 向量化,避免 Python 循环
- 测试:每个函数必须有对应 tests/test_*.py 用例
输出格式
- [记忆] __hardware__: algo.antishake.fps=N, algo.gps_ins.latency_ms=N
- [后续] <下一轮迭代聚焦点,如:基于新精度数据验证 EKF 收敛速度>
## 输出格式(必须包含)
- [记忆] __hardware__: algo.{domain}.{metric}=值
- [后续] <下一轮具体改进目标,如:将卡尔曼 Q 矩阵改为自适应调整>
"""
+278
View File
@@ -0,0 +1,278 @@
from __future__ import annotations
import asyncio
import logging
import threading
from datetime import datetime, timedelta
from apscheduler.schedulers.blocking import BlockingScheduler
from nmfs_agents.config import load_config
from nmfs_agents.core.executor import Executor
from nmfs_agents.core.queue import TaskQueue
from nmfs_agents.core.scanner import Scanner
from nmfs_agents.core.watchdog import Watchdog
logger = logging.getLogger(__name__)
def _scan_and_enqueue() -> None:
cfg = load_config()
q = TaskQueue()
scanner = Scanner(cfg)
results = scanner.scan_all()
for r in results:
from nmfs_agents.core.queue import Task
tid = q.enqueue(Task(
project=r.project, type=r.type, title=r.title,
context=r.context, priority=r.priority,
mode=r.mode, agent_role=r.agent_role,
initiator=r.initiator, discussion=r.discussion,
))
if tid > 0:
logger.info("新任务入队 [%s] %s (priority=%d)", r.project, r.title, r.priority)
def _get_queue() -> "TaskQueue":
"""可被测试 monkeypatch 替换的工厂函数。"""
return TaskQueue()
def _enqueue_planner_task() -> None:
"""将 planner 分析任务入队(同标题去重,不重复触发)。"""
from nmfs_agents.core.queue import Task
q = _get_queue()
tid = q.enqueue(Task(
project="research",
type="planner",
title="PlannerAgent 周期差距分析",
context="由 Scheduler 定时触发,分析平台目标与项目现状差距",
priority=5,
mode="report",
agent_role="planner",
initiator="scheduler",
discussion="6h 定时 planner 分析",
))
if tid > 0:
logger.info("PlannerAgent 任务入队 #%d", tid)
else:
logger.debug("PlannerAgent 任务已在队列中,跳过")
def _enqueue_research_cycle() -> None:
"""将三专项调研轮次入队(同标题去重)。"""
from nmfs_agents.core.queue import Task
q = _get_queue()
topics = [
("rtp-researcher", "rtp-research", "RTP 周期调研:协议最新进展与延迟优化",
"调研最新 RTP/RTCP 优化技术,重点关注低延迟媒体传输、RK3588 MPP 编码路径优化。"
"用 [调研报告] 标签写入 __research__.rtp.* facts,用 [后续] 提出下阶段调研方向。"),
("net-researcher", "net-research", "网络栈周期调研:QoS 与拥塞控制最新进展",
"调研内核网络栈调优方案(TC/qdisc/eBPF),RK3588 stmmac 驱动优化。"
"用 [调研报告] 标签写入 __research__.net.* facts,用 [后续] 提出下阶段方向。"),
("kernel-analyzer", "kernel-analysis","内核调度周期分析:NPU/CPU 协同与功耗",
"分析 RK3588 内核调度(CPUFreq/NPU 资源争用),给出调优参数建议。"
"用 [调研报告] 标签写入 __research__.kernel.* facts,用 [后续] 提出下阶段方向。"),
]
for role, proj, title, ctx in topics:
tid = q.enqueue(Task(
project=proj, type="tech_support", title=title,
context=ctx, priority=3, mode="auto",
agent_role=role, initiator="scheduler",
))
if tid > 0:
logger.info("调研任务入队 #%d [%s] %s", tid, role, title)
def _enqueue_algo_cycle() -> None:
"""将算法组代码迭代任务入队(入 base_opt 队列)。
每轮为每个算法项目生成一个闭环迭代任务:
读取上轮记忆 → 改进代码 → rk3566验证 → 写回记忆 → 提出下轮方向
"""
from pathlib import Path
from nmfs_agents.core.queue import Task
q = TaskQueue(db_path=Path("data/base_opt_tasks.db"))
algo_tasks = [
(
"algo-antishake", "antishake",
"EIS 防抖算法迭代",
"【代码迭代任务】\n"
"1. 读取 ProjectMemory __hardware__.algo.antishake.* 了解上轮实测数据\n"
"2. 查看 src/eis.py 现有实现(如不存在则新建骨架)\n"
"3. 改进核心算法(陀螺仪融合/光流估计/帧间对齐)\n"
"4. 在 rk3566orangepi@192.168.123.183)运行 tests/ 验证效果\n"
"5. 用 [记忆] 记录实测 fps/jitter_px 数据\n"
"6. 用 [后续] 提出下一轮聚焦方向\n"
"验证优先级:精度(jitter_px) > 延迟(ms) > FPS",
),
(
"algo-position", "positioning",
"BLE/UWB 定位算法迭代",
"【代码迭代任务】\n"
"1. 读取 ProjectMemory __hardware__.algo.position.* 了解上轮实测数据\n"
"2. 查看 src/positioning.py 现有实现(如不存在则新建骨架)\n"
"3. 改进核心算法(RSSI 路径损耗模型/卡尔曼滤波/多点融合)\n"
"4. 在 rk3566orangepi@192.168.123.183)运行 tests/ 验证效果\n"
"5. 用 [记忆] 记录实测 accuracy_cm/hz 数据\n"
"6. 用 [后续] 提出下一轮聚焦方向\n"
"验证优先级:精度(cm) > 刷新率(Hz)",
),
(
"algo-nav", "navigation",
"GPS/IMU 导航算法迭代",
"【代码迭代任务】\n"
"1. 读取 ProjectMemory __hardware__.algo.nav.* 了解上轮实测数据\n"
"2. 查看 src/navigation.py 现有实现(如不存在则新建骨架)\n"
"3. 改进核心算法(Mahony 互补滤波/EKF 融合/漂移抑制)\n"
"4. 在 rk3566orangepi@192.168.123.183)运行 tests/ 验证效果\n"
"5. 用 [记忆] 记录实测 attitude_hz/drift_m_per_min 数据\n"
"6. 用 [后续] 提出下一轮聚焦方向\n"
"验证优先级:姿态精度(°) > 更新频率(Hz) > 漂移(m/min)",
),
]
for role, project, title, ctx in algo_tasks:
tid = q.enqueue(Task(
project=project, type="code_improve", title=title,
context=ctx, priority=3, mode="auto",
agent_role=role, initiator="scheduler",
))
if tid > 0:
logger.info("算法迭代任务入队 #%d [%s] %s", tid, role, title)
def _enqueue_market_intel_task() -> None:
"""将 Market-PM 深度情报收集任务入队(每日一次,同标题去重)。"""
from nmfs_agents.core.queue import Task
context = (
"每日市场情报全量更新,覆盖三大目标领域(运动、适老、AI安全)。\n"
"每个领域请完成:①竞品全景(≥5个,含定价/功能/优劣势)"
"②近期技术趋势(含具体数据)③用户痛点 ④差异化机会。\n"
"输出 [市场情报] 标签更新 __market__.{goal}.summary/competitors/trends/opportunities/updated_at。"
)
q = _get_queue()
tid = q.enqueue(Task(
project="research",
type="market_intel",
title="Market-PM 每日情报收集",
context=context,
priority=4,
mode="auto",
agent_role="market-pm",
initiator="scheduler",
))
if tid > 0:
logger.info("Market-PM 情报任务入队 #%d", tid)
else:
logger.debug("Market-PM 情报任务已在队列中,跳过")
def _collect_env() -> None:
"""后台静默收集环境信息,失败不影响主流程。"""
try:
from nmfs_agents.config import load_config
from nmfs_agents.tools.env_collector import run_collection
from nmfs_agents.tools.project_memory import ProjectMemory
cfg = load_config()
run_collection(cfg, ProjectMemory())
logger.info("EnvCollector 完成收集")
except Exception:
logger.exception("EnvCollector 收集失败(静默跳过)")
def _run_pending() -> None:
cfg = load_config()
executor = Executor(cfg)
count = asyncio.run(executor.run_all_pending())
logger.info("本轮执行任务数: %d", count)
if count == 0:
# 队列空时触发 planner 补充需求
_enqueue_planner_task()
logger.info("队列为空,已触发 PlannerAgent 差距分析")
def _run_pending_queue(queue_name: str) -> None:
"""执行指定队列的待处理任务。"""
from pathlib import Path
from nmfs_agents.core.queue import TaskQueue
cfg = load_config()
q_cfg = cfg.queues.get(queue_name)
if not q_cfg:
logger.warning("队列配置不存在: %s", queue_name)
return
db_path = Path(q_cfg.db)
queue = TaskQueue(db_path=db_path)
executor = Executor(cfg, queue=queue)
role_filter = q_cfg.roles if q_cfg.roles else None
count = asyncio.run(executor.run_all_pending(role_filter=role_filter))
logger.info("[%s] 本轮执行任务数: %d", queue_name, count)
# project_delivery 队列空时触发 planner
if count == 0 and queue_name == "project_delivery":
_enqueue_planner_task()
logger.info("project_delivery 队列为空,已触发 PlannerAgent")
def start() -> None:
cfg = load_config()
interval = cfg.scheduler.interval_hours
# 启动恢复:将上次运行遗留的 running 任务重置为 failed,避免阻塞 semaphore
q = TaskQueue()
recovered = q.reset_stale_running(timeout_minutes=0)
if recovered:
logger.warning("启动恢复:%d 个遗留 running 任务已重置为 failed", recovered)
# 启动 Watchdogdaemon 线程,60s 一次超时检测 + 优先级老化)
watchdog = Watchdog(q)
watchdog.start()
scheduler = BlockingScheduler()
scheduler.add_job(_scan_and_enqueue, "interval", hours=interval, id="scan")
scheduler.add_job(
_enqueue_planner_task, "interval", hours=6, id="planner",
next_run_time=datetime.now() + timedelta(minutes=10),
)
# 三队列独立调度,首次执行错开启动时间
scheduler.add_job(
lambda: _run_pending_queue("project_delivery"),
"interval", hours=interval, id="run_project",
next_run_time=datetime.now() + timedelta(minutes=5),
)
scheduler.add_job(
lambda: _run_pending_queue("base_opt"),
"interval", hours=2, id="run_base", # 2h(原4h),算法组更频繁执行
next_run_time=datetime.now() + timedelta(minutes=20),
)
scheduler.add_job(
lambda: _run_pending_queue("insight"),
"interval", hours=2, id="run_insight", # 2h(原6h),洞察组更频繁执行
next_run_time=datetime.now() + timedelta(minutes=30),
)
# 三专项调研轮次(每8小时入一轮)
scheduler.add_job(
_enqueue_research_cycle, "interval", hours=8, id="research_cycle",
next_run_time=datetime.now() + timedelta(minutes=2),
)
# 算法组迭代轮次(每8小时一轮)
scheduler.add_job(
_enqueue_algo_cycle, "interval", hours=8, id="algo_cycle",
next_run_time=datetime.now() + timedelta(minutes=25),
)
scheduler.add_job(
_enqueue_market_intel_task, "interval", hours=24, id="market_intel",
next_run_time=datetime.now() + timedelta(hours=1),
)
scheduler.add_job(
_collect_env, "interval", hours=24, id="env_collect",
next_run_time=datetime.now() + timedelta(minutes=30),
)
logger.info("Scheduler 已启动,扫描间隔: %d 小时", interval)
_scan_and_enqueue() # 启动时立即扫描一次
# 启动时后台触发一次环境收集(daemon 线程,不阻塞调度器)
threading.Thread(target=_collect_env, daemon=True, name="env-collector-init").start()
try:
scheduler.start()
finally:
watchdog.stop()