算法可视化与交互学习平台

ReAct Agent:从一次调用到可控行动循环ReAct Agent: Action, Observation and Iterative Control

概念上直接承接 No.8 的单次 Tool CALL:把本地模型提出的候选动作交给受约束 Runtime 校验与执行,再将真实 Observation 回灌到下一状态,直到提交证据覆盖完整的 Final Answer,或由 max_steps、工具调用、墙钟时间、input/output token 及循环检测安全停止。核心实验不依赖 No.8 的页面、语料或本地服务,而是下载一个包含 Agent、工具、知识资料、prompt、schema、测试和 manifest 的完整示例包;浏览器沿用 No.16 的本地运行方式,直连 127.0.0.1:4890 上的 algolab_local_runner.py,由用户下载的 Qwen2.5 本地模型自主完成 AgentEval Mini knowledge_search → calculator → plot → Final,并返回可按 after_seq 增量轮询的完整 execution trace。

RAG & AgentsAdvancedFree
Kernel
1

No.8 的终点,就是 No.17 的起点:一次 CALL 还不是 Agent

No.8 已经完成最难的第一步:模型不再直接猜计算结果或图片,而是生成受约束的 CALL calculator {...}CALL plot {...}CALL search {...}。但一次调用结束后,模型并不知道工具究竟成功、失败,还是返回了需要继续处理的新数据;它也没有机会根据结果改写下一步。

No.8 · one call USER → model → CALL tool {args} → tool output No.17 · controlled loop USER → state₀ → decision₀ → validated action₀ → Observation₀ → state₁ → decision₁ → ... → Final Answer / controlled stop

No.17 在概念上把 No.8 末尾的 CALL → OBSERVATION → FINAL 展开成可运行系统;实验一、二仍用 No.8 的例子帮助比较单次路由与多步状态。但实验三不读取 No.8 页面、不调用 No.8 Runtime,也不依赖课程索引:它把 No.16 的“下载 algolab_local_runner.py、浏览器直连本机服务”方法提升为一个自包含 Agent 包,在 4890 内执行本地模型、工具、预算、恢复和 trace。

2

先把 Agent、Model、Tool 与 Runtime 的四条责任边界钉死

Agent 不是模型的别名。它是由目标、状态、模型策略、工具集合和运行时规则组成的系统。把四层混在一起,会让失败看起来都像“模型不够聪明”;分开后,每一层都有可验证的输入、输出和修复手段。

角色它负责什么它绝不能假装负责什么
Agent保存任务目标、可见 state、允许工具、完成条件与控制策略;决定下一轮要解决哪个缺口不能跳过工具,把猜测写成 Observation;也不能用流畅 Final 掩盖未完成条件
Model读取受预算约束的 state view,在 Runtime 给定的单分支 JSON 前缀后生成工具参数值或 Final Answer不能直接执行工具、批准自己的参数、修改预算或宣布外部调用已经成功
Tool在明确 schema 内完成单一能力,例如检索、精确计算或生成图表 artifact不规划整个任务,不决定下一工具,也不把异常吞掉后返回伪结果
Runtime确定当前 action/final 分支,预填 type、tool/evidence_ids 与公开 Decision Summary;再验证参数、预算、执行、重试、Observation、循环和 trace不替模型猜查询、算式、绘图数据或 Final Answer,不把工具错误改成成功,也不请求或保存隐藏思维链

因此一次循环中的信任顺序是:Runtime 固定可控外壳,Model 补全任务语义,Runtime 审批,Tool 计算,Runtime 记录,Agent 再决策。只有 Runtime 能把外部执行结果写成 Observation;模型生成的“计算完成”四个字不构成事实。

3

唯一主循环:可见状态产生候选决策,真实 Observation 再生成下一状态

第 t 轮中,模型策略 πθ 看到由 V 生成的紧凑状态视图、当前工具的内联参数 schema,并提出决策 d_t。Runtime 先校验 Decision,再校验 Action 参数:无效参数形成带 error、attempted_arguments 的失败 Observation,并进入独立的重复无效参数计数;只有参数有效后才按规范化 action signature、预算检查并分派工具。JSON/Decision 解析失败则形成 trace 事件并在同一步修复,任何失败都不会静默消失。

行动循环的轮次;不是训练 step,也不是生成 token 的位置
agent-loop iteration
当前实现由 task、observations、runtime_feedback、usage、action signature/result digest 计数器共同构成的运行状态,而不是模型可任意重写的文本
runtime-owned agent state at iteration t
提供给模型的紧凑 state:任务、代码内工具/Decision schema、最近 10 条 Observation、最近 4 条反馈和剩余预算快照
compact model-visible projection of the state
由参数 θ 定义的决策策略;核心实验使用用户下载的本地 Qwen,确定性测试策略只用于自动化故障测试且不会冒充真实运行
decision policy parameterized by theta
模型实际看到 contracts.py 中的 TOOL_SCHEMAS(工具名、说明和参数);下载包的 tool_registry.json 另记录 timeout_seconds,运行时则由请求中的统一 tool_timeout_seconds 强制执行
model-visible tool schemas and packaged registry
模型提出的候选决策:一个 action 或 Final;它尚未获得执行权限
candidate action-or-final decision
当前剩余的 steps、工具调用、墙钟时间与 input/output token 预算
remaining runtime budgets
通过 schema、allowlist、预算与循环检查后获准执行的动作
validated executable action
参数拒绝或所有工具 attempts 结束后产生的结构化 Observation:id、tool、ok 与 result/error;参数拒绝还带 attempted_arguments,Decision 解析失败本身不是 Observation
structured rejected-action or final tool observation
当前代码通过 append Observation/feedback、更新 usage 与 fingerprint counters 来归并状态,并在 trace 中写 observation_count;不存在由模型控制的通用 reducer
runtime-owned deterministic state updates

Validate 在 Tool 之前

未知工具、缺少 expression、plot 数组长度不一致或预算不足,都应在可能产生副作用前被拒绝。

失败不会从轨迹消失

参数拒绝会形成失败 Observation;工具 timeout 或读取失败会先形成 retry/failed trace 事件,并在所有 attempt 结束后形成一个 Observation。JSON/Decision 解析失败则形成 decision.invalid 事件并进入同一步的修复提示。

策略可以替换,控制规则不能交给模型

Qwen2.5-1.5B、低配置备用模型和测试策略可以共享同一个 Decision contract;预算、权限、timeout、loop guard 与 trace 仍由 Runtime 强制执行。

4
State transition lab

实验一:逐步推进一次状态转移,看 Observation 怎样改变下一动作

依次点击 State₀、Decision₀、Action₀、Observation₀ 与 State₁。该概念卡与页面当前五个阶段一致:Model 提出 knowledge_search({query, top_k: 4}),Runtime 校验后分派,工具返回 calculator protocol 的证据与 structured values,下一状态才把 calculator 标记为可选动作。面板只显示可检查的 Decision Summary,不显示或保存隐藏推理;这里不承诺某个固定算式。

State₀ · Agent / Runtime

目标已进入状态,但还没有证据

goal、允许工具、预算与历史 Observation 构成可见状态。Runtime 不把隐藏思维写进 state。

goal = 查课程中的 calculator 协议并计算、绘图
evidence = []
steps = 0 / 6
主循环不是固定流水线:每个 Observation 都可能改变下一次工具选择、参数与 stop condition。
5

Tool Registry 不是按钮集合,而是一组可验证的执行契约

动态工具选择只有建立在稳定 contract 上才可控。模型应看到工具用途与参数 schema,却不必知道真实文件路径、知识文件枚举或图表落盘目录;这些生命周期由本机 Runtime 封装。实验一、二中的 search 继续承担 No.8 单次路由教学,实验三则只使用下载包内自带的三个工具,因此即使 No.8 不存在也能完成。

工具真实参数契约成功 Observation 的真实字段实验三的安全边界
knowledge_search必填 query: string(1..500)
可选 top_k: 1..4,默认 3
querycitations[](含 id、source_id、chunk_id、text、source_sha256 等)、聚合 source_sha256data.batchesdata.release_rule 与 summary只枚举包内 knowledge/*.md;不访问课程 Backend,也不允许模型指定文件路径
calculator只允许 expression: string(1..240);没有 variables 字段expressionvaluetool_latency_ms;整数结果直接返回整数,没有 rounded 字段使用 AST 节点白名单;禁止 eval、shell、函数调用、属性访问与任意 Python
plot必填 labelsvaluestitle;可选 averagey_labelspec(kind 固定为 bar,并含 labels、values、average、title、y_label)、单个 PNG artifact(id、media_type、bytes、sha256)与 summarylabels/values 限 1..20 且等长,数值必须有限;Matplotlib 使用 Agg,trace 不塞入 base64
facts or release rule missing? → knowledge_search exact arithmetic missing? → calculator structured values ready? → plot all required observations? → Final

这三个工具连同 schema、实现和测试都进入 No.17 示例包;它们可以沿用 No.8/No.16 学到的契约思想,但没有运行时复用关系。模型生成候选参数,Runtime 先执行 Decision exact-field 检查和工具参数校验;工具真正完成后,语义准确性再由 expected.json 独立计入指标。

6
Dynamic routing lab

实验二:同一句“查资料”,何时选 search,何时必须选 knowledge_search

切换四个请求,检查页面当前展示的候选 Decision JSON:入门提示走 search,课程原文/citation 走 knowledge_search,已有表达式后选 calculator,已有结构化数值后选 plot。第四个候选仍故意沿用早期路由示例的 {kind, labels, values} 形状;若把它提交给实验三的真实 No.17 Runtime,会因 kind 未获允许且缺少 title 而得到 invalid_arguments,正确参数应改为 labels、values、title 与可选 average。这个反例说明“是合法 JSON、甚至工具名选对了”仍不等于参数契约有效。

Decision contract
{
  "type": "action",
  "tool": "search",
  "arguments": {
    "query": "tool calling JSON schema",
    "top_k": 3
  },
  "decision_summary": "固定小语料足够完成轻量提示检索;低成本、低延迟,但不能作为正式课程引用。"
}

固定小语料足够完成轻量提示检索;低成本、低延迟,但不能作为正式课程引用。

边界:当前卡展示的是可检查的候选决策,不是隐藏思维链。Runtime 仍会验证工具是否启用、参数是否匹配 schema、预算是否足够。
7

动态选择还不够:工具和参数必须同时对当前状态有意义

No.8 评测已经区分了 tool accuracy、valid CALL 与 execution pass。多步 Agent 还要再加一层:同一个动作在语法上合法,却可能在当前状态中完全不准确。例如尚未获得四批次数据就调用 plot,或把平均值 79 直接写进参数而没有 calculator Observation,都能通过 JSON parser,却不能推进任务。

本模块采用只含两种分支的 Decision contract;正常三工具链中的 Observation 按全局产生顺序编号:

若前面产生过参数拒绝或失败 Observation,序号会随真实列表变化,Final 必须引用运行返回的实际 ID,不能照抄上例。

  1. Tool accuracy:当前缺口需要哪一类外部能力。
  2. Argument accuracy:执行结果是否与 expected.json 的知识、79 与图表 spec 一致。
  3. Protocol validity:Decision 精确字段、工具 allowlist 和参数类型/范围是否通过 contracts.py 校验。
  4. Execution validity:工具实际是否返回 ok: true Observation。
8

Observation 回灌的不是一段聊天文字,而是带来源和状态的事件

当前 Runtime 的 Observation 使用 id、tool、ok 以及 result/error 二选一结构。下一轮消息携带最近 10 条 Observation;每条 result 序列化后最多保留约 3000 字符,并附最近 4 条 runtime_feedback 和剩余预算快照。成功结果保留数值、citation 和 artifact metadata,图片二进制只通过本机 artifact endpoint 获取。max_input_tokens 是累计模型输入的硬停止线,不等同于一个会自动把 prompt 精确裁到剩余 token 的投影器。

形如 obs-knowledge_search-1 的实际 Observation ID;末尾数字是整个 Observation 列表中的顺序
run-local observation identifier
knowledge_search、calculator 或 plot;失败 Observation 也保留发起它的工具名
tool that produced or was denied the observation
布尔成功标记;true 时读取 result,false 时读取 error
boolean execution outcome
成功工具输出;例如 citations/data、expression/value,或 plot spec 与单个 artifact metadata
structured successful tool result
失败时的 code 与 message;真正执行过的工具失败还带 retryable,参数拒绝则通过 invalid_arguments code 和反馈说明字段问题
structured rejection or tool error
当前实现的紧凑视图:最多最近 10 条 Observation,每条 result 约 3000 字符;完整结构仍留在 Job 与 trace/Observation ledger 中
bounded observation compaction
成功 result 内的单工具耗时;整次模型/工具累计耗时另由 metrics 给出
per-successful-tool latency

Observation 必须可归因

knowledge_search 的四批次数据与发布规则绑定 citations 中的 source_id、chunk_id、text、source_sha256 及聚合 source_sha256;calculator 的 79 绑定 expression;plot 绑定 spec 与 artifact。

错误不是空字符串

参数校验失败会把 code/message 写入失败 Observation,并把更完整的拒绝说明放进 runtime_feedback;下一轮模型可据此改参。

Context 不是无限日志

Job 保存最多 800 个 trace 事件,模型则只看最近 10 条紧凑 Observation 与最近 4 条反馈;两者用途不同。

9

完整 execution trace 不等于模型隐藏的完整思维链

为了调试 Agent,我们确实需要一条完整轨迹;但“完整”指系统事件完整,而不是要求模型暴露私有、不可验证的逐字推理。No.17 保存并展示以下内容:

实际进入 trace / Job用途明确不保存
seq、step、attempt、phase 与 elapsed_ms按 after_seq 增量合并事件并还原顺序本机用户名、任意绝对路径、用户秘密
普通调用使用 model.started/model.completed,repair 调用使用 model.repair.started/model.repair.completed;completed 保存公开模型描述、本次 token usage/latency 与原始输出 SHA-256,run.finished metrics 再累计所有调用复查本地模型配置、Decision repair 成本与总调用成本;模型检查接口可另显示下载 manifest 中的 resolved_revision模型绝对目录和任一次模型输出正文
decision.valid/decision.repaired 中的规范化 Decision JSON 与 Runtime 预填的简短 Decision Summary;decision.invalid 中的 code/error、缺失契约字段和意外字段数量复查 action/final contract 与恢复次数,同时解释字段集合错误而不暴露字段值模型意外输出的额外字段值、要求模型输出“完整思考过程”的字段或隐藏思维链
tool.started/retry/failed/rejected/observation、arguments、Observation、error、tool latency 与 artifact metadata判断工具是否真的分派、是否重试及最终产生了什么图片 base64、任意 shell/代码或清单外路径
observation_count state_delta、预算快照、run.finished 的 status、stop_reason、Final、metrics 或结构化终态 error诊断状态推进、循环、效率与终止;模型加载失败和取消也不会让 trace 戛然而止把模型声称的结果覆盖到工具事实之上

v2.6 的 Decision Summary 由 Runtime 根据当前缺口生成,例如“根据成功 Observation 计算所需数值”,而不是向模型索取内部独白。Runtime 不把模型原始 JSON 正文写进 trace:正常与 repair 调用都只留各自 SHA-256;解析成功后才保存经过精确字段校验的 Decision。图表在 JSON 中只保存 artifact ID、bytes、media type 与 hash,图片由本机 endpoint 单独返回。

10

预算是运行中的硬约束:模型返回后与工具分派前都要检查

当前 Runtime 强制五类上限:外层 Decision step、实际工具 attempt、整次墙钟时间、累计 input tokens 与累计 output tokens。它在每轮前检查已用预算,把同一绝对 deadline 传给正常/repair 模型调用,并按剩余 output token 收紧 max_new_tokens;工具 attempt 的等待上限取 tool_timeout 与剩余总时间的较小值。Cost Units 仅在结束时由 token 数计算为效率指标,不是可配置预算。

已经进入的外层模型 Decision 轮数;Final、参数拒绝和未修复的无效 Decision 都占该轮,JSON repair 与同动作工具 retry 不另加 step
consumed outer agent decision steps
max_steps;它限制行动循环长度,不是模型生成的 max tokens
maximum agent iterations
已经真正分派的工具调用次数;执行前 schema 拒绝不应伪装成工具已调用
dispatched tool-call count
全局工具调用上限,包含成功调用和真正发出的重试
maximum dispatched tool calls
当前累计墙钟时间与整次运行上限;每个工具 future 另有 tool_timeout_seconds。当前实现不会把单工具 timeout 自动裁成剩余总时间,因此结束 metrics 可能略超过墙钟阈值
elapsed and maximum wall-clock time
所有正常 Decision 与 JSON repair 模型调用的累计 input tokens 及上限
used and maximum input-token budget
所有正常 Decision 与 JSON repair 模型调用的累计 output tokens 及上限
used and maximum output-token budget
结束后报告的 Cost Units=(input_tokens+2×output_tokens)/1000;用于相对比较,不参与 guard,也不是货币账单
post-run normalized token cost metric

为什么 max_steps 单独存在

即使每个工具都很快且免费,模型仍可能在两个合法动作之间来回切换;step 上限提供最后一道确定性边界。

重试不是免费

工具 retry 保持同一个 outer step,但每个实际 attempt 都增加 tool_calls 和墙钟耗时;JSON repair 同样不增加 step,却会增加 model_calls 与 input/output tokens。

本地 token 与货币账单必须区分

Runner 使用本地 tokenizer 返回每次模型调用的 input/output tokens,并将模型耗时和工具耗时分开。Cost Units 只是上述固定公式的归一化 token 指标,不得标成真实货币费用或成本预算。

11

Stop Condition 是 Runtime 的验收门:会写 Final 不等于应该结束

Agent 的输出分为两类:Final Answer 表示模型认为任务已完成,controlled stop 表示 Runtime 因安全、故障或资源边界终止。当前协议同时返回顶层 statusstop_reason,二者不能混写。

status / stop_reason当前实现的触发条件Task SuccessTermination Correctness
completed / completedFinal 之前已有三个工具各自至少一个成功 Observation,且 evidence_ids 覆盖每个工具最后一条成功 Observation;缺证据的过早 Final 只写 feedback 并进入下一 stepexpected.json 再独立检查知识值/规则、按 knowledge_search→calculator→plot 的因果顺序、calculator=79、plot spec 和 Final 中的 79、72 及“满足/eligible/pass”结论当前实现把有 Final 的 completed 终止记为 true;它与 Task Success 是两个不同指标
stopped / max_stepstool_budgettoken_budgettimeout外层 step 用尽,实际工具 attempts 用尽,累计 input/output token 到线,或总墙钟时间到线没有 Final,故为 FAIL这些 reason 在 ground truth 的保护性停止白名单中,记为 true
stopped / loop_detected同一组无效参数达到重复阈值、同一规范化有效 action 第 N 次出现,或同一成功结果摘要第 N 次出现;重复无效参数和重复结果发 guard.no_progress,有效 action 重复发 guard.loop_detectedFAIL属于保护性正确停止,记为 true;Trace 会进一步说明工具是否曾真正执行
failed / invalid_decisionJSON/Decision 在 max_retries 次即时 repair 后仍无效FAIL属于保护性正确停止,记为 true
cancelled / cancelled运行中取消会由 Runtime 返回完整结果;queued Job 也会被 JobStore 直接封口并追加 run.finished运行中取消为 false;queued 取消尚未进入 Runtime,metrics 为 null运行中取消属于保护性正确停止;queued 取消显示 N/A
failed / model_unavailable模型目录、依赖、设备/dtype 配置或本地权重加载失败;错误信息与 trace 都会脱敏绝对路径尚未进入有效决策,metrics 为 nullN/A;JobStore 仍追加结构化 run.finished
failed / runtime_error非模型供应问题的未预期 policy/worker 异常metrics 为 nullN/A;错误保留公开 code/message 并追加 run.finished

核心实验的完成清单不是一句“我完成了”,而是五个可复算条件:knowledge_search 返回 Batch A–D 的 72、78、81、85 与 average_gte=78、every_batch_gte=70;calculator 得到 79;plot spec 含完整 labels/values 与 average=79;三个正确 Observation 按因果顺序出现;Final 至少包含 79、72 和满足发布的结论,并用 evidence_ids 覆盖本次三个工具的真实成功 Observation。

12

先画清本地运行边界:服务器交付页面,浏览器直连 4890,Agent 在用户电脑内执行

部署在远端的 AlgoLab Backend 无法主动访问用户电脑的 127.0.0.1。因此实验三严格沿用 No.16 已验证的连接方式:服务器只提供页面、源码、ZIP、manifest 与 SHA-256;页面中的浏览器代码再直接请求本机 http://127.0.0.1:4890。prompt、知识资料、模型权重、Observation、trace 和图表默认不上传服务器,而且前端协议会拒绝非 localhost/127.0.0.1/::1 的 Runner URL。

AlgoLab Backend · /api/react-agent/example/* └─ page + source files + ZIP + manifest/SHA │ ▼ Browser on the user's device └─ POST /agent/runs → poll /agent/runs/{id}?after_seq=n │ loopback HTTP ▼ algolab_local_runner.py · 127.0.0.1:4890 ├─ process-wide cached local Qwen model ├─ serialized Agent jobs + per-job state/cancellation ├─ knowledge_search / calculator / plot └─ trace + metrics + artifacts

模型由用户显式运行 download_model.py 下载。默认使用 Qwen2.5-1.5B-Instruct,低配置可选 0.5B;Runner 只用 local_files_only=Truetrust_remote_code=False 从本地目录加载,并跨同一进程中匹配路径/device/dtype 的多轮调用复用 tokenizer/model。页面先用 POST /models/inspect 检查 config、tokenizer 与权重文件,并预检 torch/transformers、device 与 dtype 的可用性;检查失败就显示错误并禁用启动,不切换到写死结果。

13

先核对完整示例包:页面展示、逐文件下载与本机执行必须来自同一份源码

实验三不是一段只适合阅读的伪代码,而是一份可下载、可测试、可独立启动的最小 Agent 工程。页面不把几段源码复制进模块 JSON;它读取服务器即时枚举的真实文件清单,因此学习者看到的内容、逐文件下载的内容和 ZIP 中实际运行的内容始终同源。点击左侧任一文件后,中列显示该文件全部真实内容,右列同步说明文件作用、关键实现与它在完整行动链中的衔接;未知的后续新增文件也会显示明确的通用说明,而不是空白。

示例包中的文件可复查的问题
启动与 HTTPalgolab_local_runner.pyagent/server.pyagent/job_store.py4890 怎样暴露 status、schema、model inspect/unload、创建/轮询/取消 Job 和返回 artifact;请求体怎样限制为 256 KiB
Agent 控制agent/contracts.pyagent/runtime.pyagent/model_policy.pyagent/tools.pyDecision 怎样校验,Observation 怎样回灌,预算、repair、retry、loop 与 Final 怎样被强制执行
模型环境download_model.pyrequirements.txt用户怎样显式下载 Qwen、记录 resolved revision/文件 SHA,并让 Runner 以 local_files_only 加载
契约与上下文prompts/schemas/decision.schema.jsonschemas/tool_registry.json模型可见哪些字段,为什么只允许 action/final,以及 Runtime 怎样拒绝 reasoning 等额外字段和越权工具
本地知识与验收knowledge/agent_eval_mini.mddata/expected.json工具只从 markdown 解析 72、78、81、85 和双阈值;expected.json 只供 Runtime 复算指标,不会喂给模型或工具
复现与供应链tests/run.ps1run.shREADME.mdmanifest.json正常链、故障链和路径安全怎样测试,静态 manifest 怎样声明版本,服务器怎样为真实文件计算 bytes/SHA-256
GET /api/react-agent/example/manifest GET /api/react-agent/example/file?path=... GET /api/react-agent/example.zip manifest: version + sha256(zip) + tree_sha256 + bytes + generated_at file: path + bytes + sha256 + language + download_path

Backend 枚举示例目录时排除 .git.runs.venv__pycache__models、symlink 和 pyc,并限制文件/包大小;单文件接口只接受该次枚举清单中的规范相对路径,拒绝 ..、绝对路径和清单外文件。ZIP 以 react_agent_local/ 为根目录。模型权重不打进 ZIP,而由 download_model.py 显式获取并保存到用户选择的目录。

14
Local LLM · real ReAct runtime

实验三:本地 Qwen 查询 AgentEval Mini → calculator → plot → Final

先下载完整 No.17 示例包和可选的 Qwen2.5-1.5B-Instruct(低配置可用 0.5B),启动包内 algolab_local_runner.py;服务器提供的页面由浏览器直接连接 127.0.0.1:4890。默认任务要求 Agent 查询包内 AgentEval Mini,取得 Batch A–D 的 Task Success 72、78、81、85 及 average_gte=78、every_batch_gte=70;本地模型必须自主提出 knowledge_search,再根据 Observation 生成 calculator 的 (72 + 78 + 81 + 85) / 4,随后用 plot 的 labels/values/average/title 参数绘制四批次和 79% 平均线,最后引用实际 evidence_ids 给出是否发布的 Final。页面展示模型检查信息、queued/running/completed/failed/cancelled/stopped 状态、Decision/拒绝事件、Observation、observation_count state delta、预算、token、模型/工具耗时、指标、图表和真实 stop_reason,并提供取消、导出 trace、完整源码浏览及 ZIP 下载;模型或 Runner 缺失时不使用固定策略或固定结果兜底。

真实本地 LLM: Decision 和参数必须来自用户电脑上的模型;Runtime 在本机执行 knowledge_search、calculator 与 plot。Runner 或模型缺失时,本卡只显示“未运行”,不会生成预填成功结果。
隐私与解释边界:网页只展示简短 Decision Summary、结构化 Action、Observation、预算和指标,不要求、传输或保存模型隐藏思维链。AlgoLab 服务器不会代理访问用户的 127.0.0.1。

1 · 浏览器直连本机 Runner

统一端口 4890;需使用示例包中带 agent capability 的 algolab_local_runner.py。

v
尚未检查;实验三不会回退到浏览器 Reference Policy。

2 · 下载并检查本地模型

推荐 Qwen2.5-1.5B-Instruct;低配置可选 0.5B。模型目录可位于任意项目或磁盘;依赖检查针对上方当前 4890 Runner 的解释器,而不是根据模型目录推断 Python 环境。

填写本机模型目录后先检查;Runner 只加载本地文件。

3 · 任务与预算

自动配置为完整闭环(推荐)

一次设置 12 steps、10 次工具、300 秒、32k / 4k 累计输入输出 token。v2.6 Runtime 会把工具参数 schema 与公开 Decision Summary 固定在当前契约前缀中,让小模型只补全参数值或 Final Answer。

input tokens 是每轮完整状态提示的累计量,不是单轮模型上下文长度。重复 Action、重复未通过 Final 与无进展 Observation 都受 Runtime 保护;阈值仍限制在安全范围 2–8。

Run status
尚未运行
加载模型
Decision
校验
工具
Observation
Final
✓ 已到达 · ● 进行中 · ! 已尝试但未通过 · ○ 尚未到达
stage = idle
真实 Run 启动后,这里才会出现 Decision Summary → Action → Observation → next state。

本次真实运行指标

Task Success
未运行
由 expected.json 确定性验收,不由 LLM 自评
Valid Action Rate
未运行
合法 Decision / 全部 proposals
Tool/Argument Accuracy
未运行
工具与语义参数同时正确
Recovery Rate
未运行
预算内成功恢复 / 可恢复错误
Loop Rate
未运行
重复或无进展动作 / proposals
Termination Correctness
未运行
证据齐全才 Final;异常时正确停止
Steps
真实模型 Decision 轮数
Latency
未运行
模型和工具的本地墙钟时间
Tokens
未运行
tokenizer 统计的 input / output
Cost
未运行
本地归一化计算成本,不冒充货币账单
完整示例包:源码、prompt、schema、知识资料、测试与启动脚本
正在读取发布 manifest…
下载完整 ZIP
先建立整体模型,再逐文件阅读

一套可独立运行、可审计的本地 Agent,而不是互不相干的文件列表

根目录文件负责准备与启动,agent/ 承担真实控制循环,prompts/ 与 schemas/ 约束 LLM 的候选 Decision,knowledge/ 提供工具可检索事实,data/expected.json 在运行后独立评分,tests/ 则验证整条链路。

1
LLM 只提议

本地 Qwen 生成查询、算式、绘图参数或 Final Answer,不直接执行工具,也不决定预算与终止。

2
Runtime 控制

Runtime 组装有界状态、预填公开 JSON 外壳、校验 Decision、调度工具并推进下一状态。

3
Observation 给事实

knowledge_search、calculator 与 plot 的真实返回值才会进入下一轮;模型声称成功不能替代 Observation。

4
评分答案隔离

data/expected.json 只在运行结束后复算指标,永远不会进入 LLM prompt、检索结果或工具参数。

文档结构:五个目录角色共同构成一个可运行系统

点击任一文件标签,会在下方同时打开完整内容和逐文件解释。

文件标签可交互
7 files
根目录 · 准备、发布与启动

告诉用户如何安装依赖、显式下载模型、核对包版本,并用自己指定的 Python 启动 4890。

7 files
agent/ · 真实运行实现

从 HTTP Job 到模型适配、严格协议、工具执行和 state → action → observation 循环的核心代码。

5 files
prompts/ + schemas/ · LLM 契约

前者告诉模型当前只能怎样续写,后者以机器可读形式公开 Decision 与工具参数边界。

2 files
knowledge/ + data/ · 事实与评分分离

knowledge 是 Agent 经工具可见的事实;expected 是 LLM 不可见的验收标准,两者用途不同。

1 files
tests/ · 可执行回归

不用下载大模型即可验证完整闭环、错误恢复、预算、循环检测、安全边界与评分隔离。

文件调用关系与 LLM 数据边界

箭头表示本轮执行中的调用或数据推进;同一文件可在不同泳道承担不同职责。横向内容可滚动查看。

启动 / HTTPLLM 输入输出工具 / ObservationFinal 后评测
启动与作业控制

用户指定的 Python 从启动脚本进入 loopback HTTP 服务,再把异步 Job 交给行动循环。

环境与模型准备

按说明安装依赖,并把允许的 Qwen 显式下载到用户选择的目录。

明确选择 Python

操作系统脚本只使用用户给定解释器。

薄启动入口

不猜环境,只转交 server.main。

Loopback API

提供检查模型、创建/轮询/取消 Job 与 artifact 路由。

异步 Job 生命周期

维护 queued/running/terminal、取消事件和公开快照。

行动循环中枢

执行预算、恢复、循环检测与 Final 终止。

LLM Decision 回路

每一步只把当前允许的分支、成功 Observation 和剩余预算交给本地 Qwen;输出始终只是候选 Decision。

状态 + Prompt + Schema

Runtime 选择 action/final/repair 提示,并内联当前唯一参数契约。

本地模型适配

应用 assistant JSON 前缀、token/deadline,并只从本地目录加载权重。

本地 Qwen
LLM

续写查询、算式、绘图参数或 Final Answer。

候选 Decision 校验

拒绝未知工具、额外字段、错误参数和不完整 Final。

回到 Runtime

合法 Action 才能执行;失败信息受限回灌并受预算约束。

边界:LLM 看得到 prompt、当前 schema 与公开 Observation;看不到 expected.json,也没有直接调用 Python 工具的权限。

Action → Tool → Observation

严格校验后的 Action 由 Runtime 分派,工具的结构化结果再回到下一轮状态。

已校验 Action

工具名与参数已通过白名单协议。

Runtime 分派

在调用前检查 tool/time/token/retry 与重复动作预算。

工具执行层

检索本地知识、计算表达式或生成图表和 PNG。

结构化 Observation
STATE

真实 result/error、证据 ID 与状态增量进入下一轮。

下一状态

Runtime 压缩公开 Observation,再请求下一次 Decision。

边界:知识文件不会直接塞进 prompt;只有 knowledge_search 选中的片段与解析数据会成为 Observation。

Final 后的独立评测

正常结束与任务成功分开判断:Final 证据覆盖可以让 Run completed,语义是否完整仍由 ground truth 复算。

Final + 全部 Observation

保留模型答案、证据引用与真实工具结果。

隔离的 Ground Truth
不进入 LLM

保存数值、阈值、最低值与受保护终止原因。

确定性 Metrics

复算 Task Success、工具准确率、恢复率、循环率与终止正确性。

页面展示与导出
UI

浏览器呈现 trace、Observation、图表和指标,不伪造成功。

边界:expected.json 与 knowledge/ 内容可以数值对齐,但没有 expected → LLM 的数据边;这是防止答案泄露的关键边界。

15

逐项读懂核心实验 trace:每个结论都要回到某个 Observation

正常链路不是一条写死的动画,而是本地模型根据当前 state 缺口逐轮提出 Decision。运行实验后,应能沿 trace 复查以下因果关系;表中的数字是 expected.json 的确定性验收目标,不是 Runtime 预先喂给模型的行动脚本。

阶段Decision、Action 与真实 Observation 形状它怎样改变 next state / metrics
0 · 检查与 Job页面先调用 /models/inspect 核对本地 config、tokenizer、weights、推理依赖与 device/dtype;再以 202 创建 /agent/runs queued Job,首次模型调用时才真正加载/复用模型Job 公共字段只记录 model name、path hash、device、dtype 与 budgets;模型检查可显示下载 manifest 的 resolved_revision
1 · 本地知识Qwen 提出 knowledge_search {query, top_k};工具返回 citations、source_sha256、Batch A=72/B=78/C=81/D=85 与 average_gte=78/every_batch_gte=70产生如 obs-knowledge_search-1 的成功 Observation;下一轮 compact state 能看到事实与规则
2 · 精确计算Qwen 根据上一 Observation 提出 calculator {expression: "(72 + 78 + 81 + 85) / 4"};result.value 必须是 79产生如 obs-calculator-2;value=79 才会增加 accurate_actions
3 · 图表 artifactQwen 提出 plot,传入 labels=[Batch A,Batch B,Batch C,Batch D]、values=[72,78,81,85]、average=79、title;返回 spec 与 PNG artifact产生如 obs-plot-3;页面既用 spec 绘制课程图,也从本机 artifact endpoint 打开真实 PNG
4 · FinalQwen 引用三个实际 Observation ID,并说明平均 79≥78 且最低 72≥70,因此满足发布条件证据覆盖通过时返回 status=completedstop_reason=completed;随后 Task Success 依据 expected 的知识、计算、plot spec 与回答关键词复算

若知识文件缺失、读取失败或格式损坏,工具会返回带 code 的失败 Observation;模型可在下一 Decision 改变动作,只有 retryable 的工具失败才由 Runtime 自动重试同一 action。直接 Final 或引用不存在/非最新成功 Observation 会被当作 premature Final 回灌;算错或漏画 average 仍可能满足“有三个成功工具”的 Final 证据门,但最终 Task Success 会是 FAIL,这正体现协议终止与任务正确性必须分开评测。

16

错误恢复先分层:参数修复、工具重试和任务降级不是同一件事

“再试一次”不是通用恢复策略。当前 Runtime 把恢复分成三条真实路径:Decision 即时 repair、下一 step 参数修正、同一工具 action 的自动 retry。它们使用不同计数方式。

错误层示例当前实现终止/指标结果
Model output / DecisionQwen 在 JSON 后附解释、缺少 type、增加 reasoning 字段或选择未知工具decision.invalid;把错误与最多 3000 字符的无效输出只放入 repair prompt,在同一个 outer step 内最多生成 max_retries 次;每次 repair 模型调用也写 model.started/completed/failed,正文只留 SHA全部失败为 failed / invalid_decision;成功 repair 增加 Recovery 的 recovered 计数,原始输出正文不进 trace
Tool argumentscalculator 使用 formula;plot.values 与 labels 不等长;knowledge_search.top_k=8执行前写 tool.rejectedok:false / code=invalid_arguments Observation;下一 outer step 的普通模型调用从 feedback 改参,不走同一步 repair prompt拒绝不增加 tool_calls;以后出现合法参数或接受的 Final 时,挂起的可恢复失败才计 recovered
Semantic result / causal orderexpression 合法但 value 不是 79、plot 缺 average=79,或 calculator 出现在正确 knowledge_search 之前工具照常返回成功 Observation;Runtime 不自动改参数,而是在当前 prior observations 下计算 accurate_actions,并在 Task Success 中检查 knowledge_search→calculator→plot 顺序Valid Action 可增加而 Tool/Argument Accuracy 不增加;有证据的 Final 仍可能 completed,但 Task Success=FAIL
Retryable tool failuretool_timeout 或显式 retryable=True 的 knowledge_read_failed/测试故障相同规范化 action 在同一 outer step 内最多再执行 max_retries 次;每次写 tool.retry/failed 并消耗一个 tool_call。每次等待取 tool timeout 与剩余总时间的较小值后续 attempt 成功才把这些 recoverable failures 计入 recovered;总 deadline 先到则以 timeout 停止且不继续 retry
Runner / model failure模型目录、当前 4890 Runner 解释器中的 torch/transformers、device/dtype 或本地权重加载失败页面模型检查通常先返回 HTTP 400,并区分依赖缺失与已找到但导入失败;这只描述用户指定 Python 启动的当前 4890 进程,不代表电脑上的其他虚拟环境。若 worker 内失败,Job 错误会脱敏本地模型路径并追加终态 run.finishedfailed / model_unavailable;只有非模型供应问题的未知异常使用 failed / runtime_error

测试覆盖 invalid JSON repair、invalid arguments 下一步修正、retryable 工具错误、tool timeout、总 deadline、retry 耗尽、因果顺序、重复 action、无进展、各类预算、取消、终态 trace 与模型路径脱敏。需要特别诚实的一点是:Python thread 的 future.cancel() 不能保证中断已经开始的工具函数;当前 timeout 会停止等待并阻止额外 retry,但生产写入型工具还应增加真正的可取消 I/O 或进程隔离。

17

先判断是否可重试,再决定保持参数还是生成修复参数

同一个 max_retries 同时限制两种不同机制:解析失败时在同一 step 内重新调用模型修 Decision;工具执行失败时在同一 step 内重放同一规范化 action。INVALID_ARGUMENT 已经是一个可解析 Action,因此不会进入前者,而是形成 Observation 后等待下一 step 的新 proposal。

第 r 个 Decision repair model call;输入只包含安全的 validation_error、字段差异诊断与当前 Decision schema,不回灌或保存无效输出正文,温度固定为 0
in-step decision repair call r
parse_decision 尚未得到合法 action/final;未知工具也属于这一层,而不是工具失败
no valid typed decision exists
第 r 个工具 attempt 失败后是否继续;由 ToolError.retryable、max_retries 与剩余 tool-call/time guard 决定
permission to replay a retryable tool action
工具错误显式标记的可重试性;tool_timeout 被 Runtime 标记为 true,参数拒绝不属于工具 attempt
tool-error retryability
max_retries,允许范围 0..3、默认 2;表示首次调用之外最多追加的次数
maximum extra decision repairs or tool retries
max_tool_calls;只有真正 submit 的工具 attempt 消耗它,Decision repair 与参数拒绝不消耗
maximum dispatched tool attempts

当前没有 idempotency key

示例 plot artifact 使用随机 ID;正常成功只返回一次,但 timeout 后底层线程若仍完成,可能留下未关联文件。生产写入型工具应增加 idempotency key 或进程级取消。

Retry 与新的 Agent 决策

工具 retry 保持同一规范化 action 和 step,只增加 attempt/tool_calls;invalid_arguments 修正则是下一 step 的新 proposal,必须重新校验。

退避属于生产增强

教学实验没有指数退避;它依靠 0..3 的有限 extra attempts、tool-call 上限和每次 attempt 前的总时间检查来封顶。

18

重复 Action 不等于重试:用 fingerprint 与 progress 同时检测无进展循环

Agent 常见的失败不一定抛异常,也可能反复提交同一组无效参数,或每一步都合法却始终没有新信息。v2.5 Runtime 将三种现象分开计数,避免把“参数从未通过校验”误报成“工具已执行后的动作循环”。

invalid signature = JSON({tool, raw invalid arguments}, sort_keys=True) valid action signature = JSON({tool, normalized arguments}, sort_keys=True) result digest: knowledge_search → data calculator → expression + value plot → spec invalid guard: signature occurrence >= repeated_action_limit valid action guard: signature occurrence >= repeated_action_limit result guard: digest occurrence >= no_progress_limit all stop with stop_reason = loop_detected
现象当前计数方式处理
模型重复提交 knowledge_search arguments={}每次先生成带 validator error 与 attempted_arguments 的失败 Observation,再累计同一 invalid signature达到阈值发 guard.no_progresscode=repeated_invalid_arguments;工具调用数仍为 0
INVALID_ARGUMENT 后把 formula 改为 expression原始无效参数改变,新的 proposal 重新校验;不会污染有效 action 计数若校验并执行成功,挂起的恢复计数可转为 recovered
一次 tool_timeout 后自动执行 attempt 2retry 发生在同一个 outer Action 内,不再次累计 valid action signature由 max_retries/tool_calls 管理,trace 以 attempt 区分
模型在不同 step 第 N 次提出完全相同且校验通过的 tool + arguments规范化参数的 valid action signature 第 N 次出现时在分派前触发;阈值可设 2..8guard.loop_detected,不执行该次工具
不同 query 让 knowledge_search 返回相同 data,或 plot 省略与明示默认 y_label 后得到相同规范化 spec只对成功结果的稳定摘要计数,忽略 latency、artifact 随机 ID/hash;不是“连续 streak”要求工具已执行后发 guard.no_progress,但 stop_reason 仍为 loop_detected

当前实现不会直接识别任意 A→B→A→B 序列;只有当某个 invalid signature、valid action signature 或稳定 result digest 自身达到阈值时才停止。Loop Rate 也不是重复事件总数:本次运行一旦触发任一 guard,就报告 1 / action_attempts;未触发则为 0,工具 retry 不进入 action_attempts。

19

Agent 评测必须跨越 outcome、action、recovery、loop 与 termination 五层

这些值是当前单次 Job 的 metrics,不是数据库中跨 N 次运行自动聚合的均值。Task Success 检查 Final 与三类语义结果;Valid Action Rate 和 Tool/Argument Accuracy 的分母都是已解析出的非 Final Action 数;Recovery Rate 使用 Runtime 的可恢复/已恢复计数;Loop Rate 是触发任一循环 guard 的指示量除以 Action 数;Termination Correctness 按 completed Final 或 expected.json 的保护性 stop_reason 判定。Steps、Latency、Tokens 与 Cost Units 另报效率。

Task Success 布尔值;必须存在被接受的 Final,并同时有语义正确的 knowledge_search、calculator=79、plot labels/values/average,以及回答中的 79、72 和满足/eligible/pass 结论
deterministic per-run task success
Valid Action Rate;通过 validate_tool_arguments 的 Action 数 / 已解析 Action 数。未知工具属于 invalid Decision,不进入此分母;预算可能在校验后才阻止分派
validated-tool-argument rate among parsed actions
Tool/Argument Accuracy;成功执行且 result 与 expected 语义匹配的 Action 数 / 已解析 Action 数。knowledge 比对四批次和规则,calculator 比对 value,plot 比对 labels/values/average
semantically accurate successful-action rate
Recovery Rate;即时 Decision repair、invalid_arguments/premature Final 后的后续合法进展,以及 retryable 工具 attempt 最终成功,都会按 Runtime counter 计入
runtime-counter recovery rate
Loop Rate;若 action 或 result guard 触发则为 1/action_attempts,否则为 0;它不是所有重复动作数量的比例
per-run loop-guard indicator normalized by action attempts
Termination Correctness 布尔值;completed/completed 且有 Final 为 true,或 stop_reason 属于 cancelled、max_steps、tool_budget、token_budget、timeout、loop_detected、invalid_decision 也为 true
accepted-final or allowlisted-protected termination
parse_decision 已得到 ActionDecision 的次数;Final 与始终无法解析的 JSON/Decision 不计入,达到 repeat guard 的 Action 仍计入
parsed non-final action attempts
Runtime 明确登记的可恢复失败数;没有这类事件时 RR 返回 null,页面显示未运行/N/A 语义
registered recoverable failures

分母为 0 时显示 N/A

没有故障时 Recovery Rate 不是 0%;没有 action proposal 时 Valid Action Rate 也不是 0%。N/A 能避免把“未运行”误读成失败。

Steps、Model Calls 与 Tool Calls 要分开

每个 outer Decision(包括 Final 与参数拒绝)增加 step;JSON repair 增加 model_calls 但不增加 step;同动作工具 retry 增加 tool_calls 但不增加 step。

Latency、Tokens 与 Cost 的实际来源

Latency 是真实墙钟总耗时,并报告累计 model/tool latency;Tokens 来自本地 tokenizer 的所有正常与 repair 调用;Cost Units 固定为 (input+2×output)/1000,不冒充货币账单。

20

本机 Runner 的控制循环:Qwen 提议,Runtime 校验、执行、记录和终止

python
这段代码做什么

这是下载包中 agent/runtime.py 的忠实缩略顺序:outer step、Decision repair、参数 schema 校验、重复无效参数保护、规范化有效 action 保护、工具 retry、结果无进展保护与 Final 证据门分别出现。完整可运行版本及 contracts、model_policy、tools、job_store、prompt、schema、知识资料和测试都在实验源码浏览器与 ZIP 中;浏览器只创建/轮询 Job,不在前端伪造状态转移。

完整可运行脚本
for step in range(1, budgets['max_steps'] + 1):
    reason = stop_reason(budgets, usage, step - 1, started)
    if cancel.is_set() or reason:
        status, stop_reason = protected_stop(cancel, reason)
        break

    # Runtime exposes one state-specific branch. For Action it embeds the
    # required tool's parameter schema and prefills through its first key.
    generation = policy.generate(
        messages(task, observations[-10:], feedback[-4:], budget_snapshot),
        max_new_tokens=budgets['decision_max_new_tokens'],
        temperature=temperature,
        cancel_event=cancel,
    )
    add_model_usage(usage, generation)
    if token_or_time_budget_exhausted():
        status, stop_reason = 'stopped', budget_reason
        break

    try:
        decision = parse_decision(generation['text'])
    except DecisionError as error:
        decision = repair_decision_up_to_limit(error)  # same outer step
        if decision is None:
            status, stop_reason = 'failed', 'invalid_decision'
            break

    emit('decision.valid', decision=decision.__dict__)
    if isinstance(decision, FinalDecision):
        accepted, message = accept_final_evidence(decision, observations)
        emit('final.validated', accepted=accepted, message=message)
        if accepted:
            status, stop_reason = 'completed', 'completed'
            final_answer = decision.answer
            break
        feedback.append(message)
        guard_repeated_premature_final()
        continue

    action_attempts += 1
    try:
        arguments = validate_tool_arguments(decision.tool, decision.arguments)
    except DecisionError as error:
        observation = rejected_observation(
            decision.tool, error, attempted_arguments=decision.arguments)
        observations.append(observation)
        emit('tool.rejected', observation=observation)
        feedback.append(str(error))

        invalid_signature = canonical_json(decision.tool, decision.arguments)
        if invalid_occurrence(invalid_signature) >= budgets['repeated_action_limit']:
            emit('guard.no_progress', code='repeated_invalid_arguments',
                 validator_error=observation['error'])
            status, stop_reason = 'stopped', 'loop_detected'
            break
        continue                         # next state receives the failed Observation

    valid_signature = canonical_json(decision.tool, arguments)
    if valid_occurrence(valid_signature) >= budgets['repeated_action_limit']:
        emit('guard.loop_detected', repeated_action={'tool': decision.tool,
                                                     'arguments': arguments})
        status, stop_reason = 'stopped', 'loop_detected'
        break                            # this valid action is not dispatched again

    guard_tool_calls_tokens_and_time()
    for attempt in range(1, budgets['max_retries'] + 2):
        usage['tool_calls'] += 1
        try:
            result = execute_with_timeout(decision.tool, arguments)
            break
        except ToolError as error:
            emit('tool.retry' if can_retry(error, attempt) else 'tool.failed')
            if not can_retry(error, attempt):
                result = None
                break

    observation = success_or_failure_observation(decision.tool, result, error)
    observations.append(observation)
    emit('tool.observation', observation=observation,
         state_delta={'observation_count': len(observations)})

    if result is not None and result_occurrence(stable_result_digest(result)) >= budgets['no_progress_limit']:
        emit('guard.no_progress', code='repeated_result')
        status, stop_reason = 'stopped', 'loop_detected'
        break
else:
    status, stop_reason = 'stopped', 'max_steps'

metrics = compute_metrics(expected_json, counters, usage, status, stop_reason)
21

No.17 的完成标准:能行动只是起点,能恢复、停止和复查才算闭环

当前模块的可验收闭环:

  1. 实验独立:关闭任何 No.8 服务、移除 No.8 页面或不提供 No.1–16 课程索引,实验三仍可仅凭 No.17 下载包、模型目录与 4890 Runner 完成;No.8 只保留概念上的前置知识。
  2. 真实本地模型:Runner 从用户选择的本地目录加载 Qwen2.5-1.5B-Instruct,低配置可选 0.5B;相同 path/device/dtype 的模型在 Runner 进程中缓存,Agent Job 串行执行。模型检查失败时页面禁用启动;检查展示当前 4890 进程实际使用的 Python 路径和依赖状态,且不从项目、模型目录或候选虚拟环境推断解释器。worker 内的目录、依赖、设备或加载失败会返回脱敏的 failed/model_unavailable,不使用固定 Decision 兜底。
  3. 浏览器直连:AlgoLab 服务器只交付页面和带 SHA-256 的源码/ZIP;浏览器只允许 loopback URL,并直接创建、按 after_seq 轮询和取消 127.0.0.1:4890 上的 Agent Job。本地 prompt、知识、trace 与 artifact 默认不上行。
  4. 确定性结果:knowledge_search 的 data 必须返回 Batch A=72、B=78、C=81、D=85 和 average_gte=78/every_batch_gte=70;calculator result.value 必须为 79;plot spec 必须含完整 labels/values 与 average=79,真实 plot 工具同时产生 PNG artifact;三个准确动作必须保持 knowledge_search→calculator→plot 因果顺序,Final 必须包含 79、72 和满足发布条件的结论。
  5. Typed control:每轮只有一个 state-specific action 或 final 分支;action 分支直接嵌入当前工具参数 schema,并从首个必填字段继续生成。未知工具/额外字段进入 Decision repair;参数先由 contracts.py 校验,无效参数进入独立 signature 保护,校验成功后才由规范化 action signature 与 tool/time/token budgets 约束分派。语义准确性在成功结果产生后由 expected.json 评分,不冒充执行前 schema。
  6. 恢复与终止:无效 Decision 在同一 step 最多 repair max_retries 次;invalid_arguments 形成含 error、attempted_arguments 的失败 Observation,下一 state 还会明确缺失字段,由下一 step 修正;同一无效参数达到阈值时发出 repeated_invalid_arguments,且不会伪造工具调用。retryable 工具错误在同一 step 重放 action。正常 Final 是 completed/completed;预算、重复 action 和无进展结果使用 stopped 及对应 reason(无进展最终也是 loop_detected);取消、invalid_decision、model_unavailable 与 runtime_error 都以协议中的真实 status/reason 和 run.finished 封口。
  7. 可复算指标:Runtime 用 counters、usage 与 data/expected.json 计算 Task Success、Valid Action Rate、Tool/Argument Accuracy、Recovery Rate、Loop Rate、Termination Correctness、Steps、Tool/Model Calls、模型/工具 Latency、input/output Tokens 与 Cost Units;分母为零返回 null,页面以 N/A/未运行语义展示。
  8. 完整但克制的 trace:页面按 seq 增量合并并可导出 phase、step、attempt、Decision Summary/规范化 JSON、拒绝/重试事件、Action、Observation、observation_count state delta、预算、artifact metadata、指标与 stop_reason。正常与 repair 模型调用的原始正文都不持久化,只留各自 SHA-256;导出还会过滤 thought/reasoning/analysis 等隐藏推理键。
  9. 代码可复现:页面可查看并逐文件下载 Runner、Agent、工具、prompt、schema、知识资料、ground truth 和测试;每个文件同时提供作用、详细解释与链路衔接列;服务器 manifest 同时给出 ZIP SHA、tree SHA 与逐文件 bytes/SHA,完整 ZIP 以同一实时文件树构建。standalone 包不依赖也不暴露 No.16 /rag/*

仍需明确的工程边界:页面把 temperature 设为 0,并限制单轮 Decision 输出 256 tokens,但小模型仍可能选错工具或参数;0.5B 是低资源备用而非与 1.5B 等精度。首版基于 Transformers 本地目录,不同时引入 GGUF/llama.cpp。AgentEval Mini 是用于学习控制循环的可复现小知识库,不代表生产 RAG;当前 thread timeout 也不是强制杀死已经运行的 Python 工具。生产系统还需要真正可取消的工具隔离、权限过滤、持久索引、并发调度、观测脱敏和更严格的模型供应链校验。Cost Units 固定为 (input+2×output)/1000,只表示相对 token 计算量,不是预算或货币账单。

AI
问问 LLM:用当前 execution trace 解释行动选择、恢复与终止

正在检查登录状态与模型配置…