ThearchyHelios
|
d18a496ef9
|
问数据整轮放到服务端跑(后端):一轮是一个后台任务,建图、运行、复核、按复核重来、落库都在服务端,页面断了也会跑完
为什么:一轮问数据以前是浏览器在推(store/chat.ts 的 plan / launch / settle):网络一抖建图那条流就断、建了一半的图丢掉;
发起运行、复核、重来、落库都要页面在,页面一关这一轮就停在 running,15 分钟后才被判成断了(总方案 §0 的调查结论)。
做了什么:
- 流程和评测共用一份:eval/answer.Driver 里的流程抽到 chat/drive.TurnDriver,差异写成子类给的几项(生成的请求、目录视图、
改图、入口、发起参数、停在审批上怎么办、复核等多久)。评测的 Driver 成了它的子类,行为和测试一字不变(test_eval_* 照跑)。
- chat/job.py:问数据的一轮是 core/job_runtime 上的后台任务(不占数据源的队,并发归「交互」类,第 2 波再给上限和优先级)。
停在审批上照旧等人(评测是取消);复核最多等 25 秒,晚到的那次用量照记(review.late);按复核自动重来一次;用户点的
重试本轮、重新运行、放宽步数、跑一下、继续运行、接着收尾都是同一轮里的一次尝试,上一次的结局归档进 meta.attempts。
- 事件日志(新表 chat_turn_events,models_chat.py,不进运行的封存范围):每一步按 seq 落库再叫醒订阅方,订阅方按 seq
回库里读——回放和实时是同一段代码;心跳一拍也回库里看一次,第 2 波多进程时别的进程写的最迟一拍送到。
- 接口 api/chat_turns.py:POST /api/chat/turns(202 带 turn_id)、GET /{id}、GET /{id}/stream?after=(SSE:先回放、再推
实时、带心跳、结束补 stream.end)、POST /{id}/cancel。挂 chat_scope,每个接口按这一轮所属的对话核对归属;访问密钥调不了。
- conversation_turns 那一行由服务端写(chat/record.py:状态、运行 id、答案、复核、meta 各项和页面以前写的一一对应);失败
只记原因(meta.cause),说法留在界面层按 lib/explain 讲。TurnOut 带这一轮的任务(job),列表判「还在跑」先看任务。
- 使用者的问数据运行规则(白名单、自己的记忆范围、遮罩、只读)抽到 chat/launch.user_chat_run,POST /api/runs 和服务端的
一轮共用,说法一字不变。
- 服务重启:还在建图的标中断(可重试本轮);已发起运行的接着等那次运行、照常复核收尾;和调度循环同一个开关,拷来的数据
目录启动时不替人收尾,页面打开对话时再请服务端接着收尾(mode=resume)。老轮次停在建图中的同样标中断。
- 删对话时先停掉它正在跑的几轮(取消各自的运行),任务和事件日志一并删。
测试:tests/test_chat_turns.py——一轮跑完不依赖页面、直接回答与反问、开流前被拒、实时流回放后接实时与按 seq 重连(补齐、
不重复)、思考合并、建图中与运行中停止、重启时建图中标中断与已发起运行的接着收尾、开关关着时等人来接、等审批后收尾、
按复核重来、用户重试归档、一段对话一次一轮、继续运行被拒照 /runs 的说法、删对话停掉这一轮、使用者的归属与遮罩只读、
访问密钥调不了、驳回与失败与发起被拒的原因、晚到的复核、跑一下与重新运行不重建。去掉几处关键实现回跑,相应的测试都会失败。
|
2026-10-18 16:05:53 +08:00 |
|
ThearchyHelios
|
3dc5f5add4
|
助手只写了思考、一个操作都没给时自动重来一次:问数据和评测走同一个决定
真实模型验收里 deepseek 偶发只出思考、不出操作,生成过程交出 error「助手本轮未完成:模型没有给出任何修改,也没有说明
原因」,问数据这一轮照实报了,但不会自动重来——而这种偶发情况重来一次多半就好,「重来一次」的规矩本来就有
(chat/turn 的 MAX_ATTEMPTS = 2,含第一次)。
- chat/turn:error 也由 next_step 判:机读码是 EMPTY_GENERATION(copilot_empty)的判 retry,别的仍判失败(被截断的不重来:
额度不变,重来还是截断);error_reason 取重来时交给助手的原因(error 带的 reason,没有就去掉「助手本轮未完成:」前缀);
- api/copilot.answer_ops:一个操作都没给时 CopilotIncomplete 带上这个码;error 操作多带 reason 和 next(retry | fail),和
final 的 next 一样由服务端定;
- 问数据页(store/chat.ts)照 error.next 走:retry 就带着原因重来一次(同 retry_instruction 的从零重建措辞,次数照
MAX_ATTEMPTS),试满了才照实报;进度写「助手上一次没有给出任何操作,正在重新生成工作流…」(lib/terms 的 CHAT_RETRY_TEXT);
第一次建图的用量照样记进这一轮;
- 评测(eval/answer.Driver.drive)用同一个 next_step / error_reason / retry_instruction:先重来一次,还不行才记建图失败、
助手调用失败;每次自动重来的原因照实记在 turn.retries(没过检查、复核判不可用的重来也记),评测页逐题明细写出来。
测试:test_chat_turn_policy.py 的 test_next_step_branches(error 的两支和 error_reason)、
test_the_frontend_retries_an_error_the_server_says_to_retry、test_answer_ops_says_to_retry_an_empty_generation、
test_the_eval_driver_retries_an_empty_generation_once(重来后回答 / 重来还不行,两次的用量都算);
test_copilot_answer_ops.py 的 SSE 对照多认 error 上新加的 next、reason、code。去掉修复回跑都失败。
浏览器:check-chat 新加 emptyretry 一节(重来一次后照常回答、交回去的话带原因、两次用量都记;两次都不行照实报、不试第三次),
check-chat 840 项全过。
|
2026-10-17 11:51:34 +08:00 |
|
ThearchyHelios
|
3c4dbe0c02
|
没做完的模型调用也计一次:挑表超时被取消的那次不再漏掉
真实模型验收里,挑表(look/pick 的 asyncio.wait_for)超时被取消的那次调用一点都不计:LangChain 的 ainvoke 被取消时
卡在 agenerate 的 gather 上,on_llm_error 根本走不到;astream 被取消时会回调,可一段都没收到的又被当成「请求刚发出去
就被拒了」不计。问数据一轮、评测按角色的调用次数因此少一次。
providers/usage.Meter 现在多记一项 unfinished(汇总里是 unfinished_calls):被取消、超时(按异常类型认,含各家 SDK 的
…Timeout)、流读到一半被关掉的调用都记一次调用、标未完成,token 只计已经报了的(一段都没收到的记 0、算没报全,
金额也就估不出);开始了、到汇总(和嵌套并入外层)时还没有结束回调的调用一并算未完成。请求一发出去就被拒的仍不计。
评测汇总相加(eval/answer._add_usage)带上这一项;评测页按角色的用量写「其中 N 次未完成」;问数据页的这一轮用量
相加时也留着它。
测试:test_usage_meter.py::test_a_call_cancelled_before_any_result_still_counts_as_an_unfinished_call(ainvoke 被
wait_for 取消、look/pick._ask 超时、astream 收到一段输入用量后被取消、被拒的不计);by_model 的形状多了一项,
test_metering_counts_by_model_and_prices_from_the_catalog 和评测同口径那条跟着改。去掉修复回跑失败。
|
2026-10-17 11:36:50 +08:00 |
|
ThearchyHelios
|
df6c3ce10d
|
定时页照实显示非工作流目标;评测停止时几臂一起收尾;工作流题的测试
为什么:这一波后端开始接受评测题集、数据源维护这两种定时目标(总方案 X4),定时页要能把它们照实列出来、点进去
不报错;界面上不能有点了没用的入口。
- 定时页列表:非工作流目标写种类(评测题集 / 数据源维护)和目标名,不标运行类别,「编辑」写成「查看」
- 详情:非工作流目标的设置只读地列出名称、目标、频率、时区、补发宽限,不出工作流那张表单(选工作流、输入模板、
Webhook 对它们不适用);页头的启用、立即运行、删除和触发历史照常
- 立即运行发起的是一次评测时说「已发起一次评测」(以前会落到「未能发起运行」);触发历史写评测的编号
- types.ts:Schedule 加 target_kind / target_id / target_label / target_name / target_exists,触发记录加 eval_run_id;
文案进 SCHEDULE_TEXT
- check-schedules 加一段「目标不是工作流的定时任务」
- runner:还没准备好就被停下、出错时,按 pair_id 找全几臂一起收尾
- 测试:工作流题按钉住版本跑探索运行(不发正式运行、不建图);钉住基线的接口
- 后端几句给人看的话按文案规范改(不用「跑」「钉」)
|
2026-10-16 17:04:05 +08:00 |
|
ThearchyHelios
|
2371e75f17
|
评测执行的主干:后台评测、无头作答、评分、统计、对比与 A/B、清理(下一轮第 3 波 W3-c 第一段)
为什么:第 2 波只有题集和期望答案的来源,评测本身跑不起来。这一段把细案 01 做法 9–12、16、17 的后端接上,
量的是用户在问数据页拿到的同一轮,而不是另抄一份编排。
- eval/answer.py:无头作答,串起 answer_ops → chat/turn 的决定 → launch_run(origin=eval,带目录视图、只读、遮罩)
→ 等终态(停在审批的取消、记「评测不代批」;驳回记路径「被驳回」)→ review_of_run → 按同一规则重来一次;
工作流题按钉住版本的图跑探索运行(不发正式运行,免得被 pick_base 和应用视图取到)。用量按角色记
- eval/runner.py:用 core/job_runtime,一次评测一个任务,题 × 重复 × 臂一项;A/B 几臂共用期望、同一题同时开跑;
开评拍目录快照、记上传表格版本和表结构哈希的前后;并发不超过 max_parallel 和全局并发的四分之一;每题时限;
评测单独一本账(开跑前估算、每题预留后找补、触顶不再开新题);止损;能停、只重试没做完的、重启标中断不续跑
- eval/score.py:六种期望、五种结论(量纲不同单列)、维度配对与弱匹配、路径不对直接不通过、口径 dual 两版都报;
逐题 E1 用口径账本的 compare_queries(总方案 X2,不另写 signals);SCORER_VERSION 可重评(eval/rescore.py,只读封存)
- eval/judging.py:结论裁判走按需裁判同一条路(evidence._judge_now),文字要点由裁判判、单列不计准确率;花费经
judge.charged_to 记在评测那本账上(engine/judge.py 只加了一个上下文变量和取账本的一处)
- eval/stats.py、eval/compare.py:准确率与可追溯准确率 + Wilson 区间、各项分布、P50/P90、按角色成本、引用率、逐题 E1;
选基准、逐题转移与归因、指纹差异、A/B 配对表与精确 McNemar;「目录贡献」预设对照(当前 vs 关,可加只用已核实)
- eval/cleanup.py + core/artifact_store.forget:保留最近 N 次 + 钉住的基线 + A/B 另几臂,删结果、明细工件、底下的运行和
引用行,工件文件一条引用都不剩才删;总表永久保留
- engine/tolerance.py:双盲复算的 _agree / _delta_pct 原样搬来共用(dual_check 改 import,行为不变)
- 设置加 eval 一组(builder 读、admin 写)和 GET /api/settings/eval/spend;题集预算在全站缺省上覆盖,每日上限只能往下收
- api/evals.py:发起(单臂 / A/B / 目录贡献预设)、估算、进度、逐题、停止、重试、重评、钉基线、和上一次比、配对表、清理
- main.py 的 lifespan:影子起草和评测的启动整理、关停(评测先于运行停,停时取消自己发起的运行)
- 测试:test_eval_e2e(dual_check_shop + 剧本模型:按支付日 330 通过且 SQL 等价,按下单日 310 不通过、差在 time;
目录对照 1:0;和上一次比找到退步、归因做法变);通知事件、定时接口形状的老测试按新事件和新字段更新
|
2026-10-16 16:38:09 +08:00 |
|