feat(v2): 架构与算法优化二轮——推理机不变量外提、知识库匹配预编译、协作循环增量索引
- inference.py(/chat/legacy 热路径):kb.match 循环不变量外提(原每步全量重扫+重排序, 最坏 O(steps×rules×patterns));fired 查重 list→set - knowledge.py:Rule patterns 注册侧懒缓存小写副本(原每条规则每次匹配重复 lower); match() 文本只 lower 一次(原逐规则重复);load() 的 yaml 文件名集合提到循环外 - worker.py:本地端点生成器 httpx.AsyncClient 懒建复用(原每步新建/销毁连接, 对齐 ArchitectClient 惯用法;协作循环最多 10 次生成免重复建连) - pipeline.py(协作循环):plan_by_id O(1) 步定义查找;done 集合增量维护 (原每轮重建 progress+archive 扫描);领域只解析一次(原 _artifact_name 每步 全领域 kb.match);_deps_done 支持传入预填集合(保持旧签名兼容) - v2stats.py:回合数分布改增量聚合(sum/max/分桶计数),summary() O(n)→O(1), 不再持有无界 list(修长时运行内存增长) - gateway/agent.py + api.py:AgentService 运行计数 O(1) 化(原 register 全量扫描), 状态迁移收敛到 _transition_state 单一入口(api.py cancel/异常两处绕过点一并接入, 消除计数与状态脱节隐患);21 项 agent 测试全绿(两轮全量 230 passed 复核)
This commit is contained in:
+21
-10
@@ -110,20 +110,24 @@ class CollaborativePipeline:
|
||||
plan = brief.get("plan") or []
|
||||
pending = [p.get("id") for p in plan]
|
||||
plan_ids = {p.get("id") for p in plan} # 用于 _deps_done 过滤
|
||||
plan_by_id = {p.get("id"): p for p in plan} # O(1) 步定义查找(原每轮线性扫描)
|
||||
done_ids = self._done_ids(ws) # 增量维护的完成集(原每轮重建)
|
||||
base_domain = self._guess_domain(query) # ws["query"] 恒定,领域只解析一次
|
||||
while pending and not ws.exhausted():
|
||||
progressed = False
|
||||
for sid in list(pending):
|
||||
step = next((p for p in plan if p.get("id") == sid), {})
|
||||
step = plan_by_id.get(sid, {})
|
||||
deps = step.get("deps") or []
|
||||
# 只检查在 plan 中的依赖;不在 plan 的 ID 视为"不存在"→自动满足
|
||||
relevant = [d for d in deps if d in plan_ids]
|
||||
if not self._deps_done(ws, relevant):
|
||||
if not all(d in done_ids for d in relevant):
|
||||
continue
|
||||
existing = self._read_artifact(request_id, self._artifact_name(sid, ws))
|
||||
existing = self._read_artifact(request_id, self._artifact_name(sid, ws, domain=base_domain))
|
||||
outcome = await self.worker.run_step(ws, sid, existing_artifact=existing,
|
||||
hint=self._last_decision_for(ws, sid))
|
||||
if outcome.status == "done":
|
||||
pending.remove(sid)
|
||||
done_ids.add(sid)
|
||||
self._save_artifact(request_id, outcome.artifact_name, outcome.artifact_text)
|
||||
ws.rollup()
|
||||
route.append(f"step:{sid}:done")
|
||||
@@ -230,9 +234,10 @@ class CollaborativePipeline:
|
||||
return hits[0].domain
|
||||
return "general"
|
||||
|
||||
def _artifact_name(self, sid: str, ws: Workspace) -> str:
|
||||
def _artifact_name(self, sid: str, ws: Workspace, domain: Optional[str] = None) -> str:
|
||||
from .worker import artifact_name_for
|
||||
domain = self._guess_domain(ws["query"])
|
||||
if domain is None:
|
||||
domain = self._guess_domain(ws["query"])
|
||||
# 用 brief.tags 优先
|
||||
tags = (ws.get("brief") or {}).get("tags") or []
|
||||
for t in tags:
|
||||
@@ -241,8 +246,10 @@ class CollaborativePipeline:
|
||||
break
|
||||
return artifact_name_for(sid, domain)
|
||||
|
||||
def _deps_done(self, ws: Workspace, deps: List[str]) -> bool:
|
||||
# progress 中 done 的条目;done 条目 rollup 后移到 archive(字符串格式如 "s1: ...")
|
||||
@staticmethod
|
||||
def _done_ids(ws: Workspace) -> set:
|
||||
"""收集已完成 step id 集合:progress 中 done 的条目 + archive 折叠行
|
||||
(done 条目 rollup 后移到 archive,字符串格式如 "s1: ...")。"""
|
||||
done = {p["step"] for p in ws.get("progress", []) if p.get("status") == "done"}
|
||||
for entry in ws.get("archive", []):
|
||||
if isinstance(entry, dict):
|
||||
@@ -251,9 +258,13 @@ class CollaborativePipeline:
|
||||
sid = entry.split(":")[0].strip() if ":" in entry else ""
|
||||
else:
|
||||
sid = ""
|
||||
if sid in deps:
|
||||
done.add(sid)
|
||||
return all(d in done for d in deps)
|
||||
done.add(sid)
|
||||
return done
|
||||
|
||||
def _deps_done(self, ws: Workspace, deps: List[str], done_ids: Optional[set] = None) -> bool:
|
||||
if done_ids is None:
|
||||
done_ids = self._done_ids(ws)
|
||||
return all(d in done_ids for d in deps)
|
||||
|
||||
def _last_decision_for(self, ws: Workspace, sid: str) -> str:
|
||||
"""取最近一条针对该 step 的决策 reply,作为 worker hint。"""
|
||||
|
||||
Reference in New Issue
Block a user