Hide the training network's record from the AI unless the user shows it
The AI goes by the ready-made ways and skills alone by default; the Gates window's "training network record" shows it the record, and a training round the user starts always does. add_nodes still picks the way that did best either way. The network view says whether the AI sees it now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
67bf5b24c9
commit
6647b059e4
+4
-2
@@ -228,8 +228,10 @@ covered by the `styles.css` manifest.
|
||||
model of its main model (`ai_task_runs._estimate` puts that on the step as `used`; its end makes an
|
||||
entry of `user/anomalous/ai_evidence.json`), and how it went comes from what the user does anyway:
|
||||
a picture picked in a picks panel or kept in the gallery (`kept_images.py`), passed over, or their
|
||||
word under the run (`web/modules/ui_ai_verdict.js`, told to the AI). begin_task and get_toolbox
|
||||
give the AI the record in a few words, add_nodes a way's or the node packs' own; of a use's ways
|
||||
word under the run (`web/modules/ui_ai_verdict.js`, told to the AI). Once the user shows it (the
|
||||
Gates' `record` view, `ai_gates.record_shown`; hidden by default, always shown in a training round)
|
||||
begin_task and get_toolbox give the AI the record in a few words, add_nodes a way's or the node
|
||||
packs' own; of a use's ways
|
||||
that can run, the one that did best on the canvas's model is picked (`reference_blocks.pick(order=…)`);
|
||||
the Gates' `nodes` rule (`ai_gates.node_rule`) lets custom nodes in only by the ways
|
||||
(`tests/test_ai_evidence.py`). A picks panel keeps the AI's own pick (the item it marked
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
- 新增 **训练网络**:AI 工作台右栏多了一个视图,把跑图记录画成一张网:左边是你的模型(按底模分),右边是做法、skill 和跑过的节点包,一起跑过的连一条线,颜色就是效果(绿好、黄一般、红不太行、灰还没人评,短虚线是只有 AI 评过),线越粗跑得越多;点一个点或一条线看详情和最近的图,选中一个点时虚线连着还没试过的组合。**开一轮训练**:选一个 skill(AI 自己写和照建议写,并排比)或一种活的几块做法,选最多 4 个模型和每组几张,交给 AI;AI 按计划一组组跑,AMB 自己对上每次跑图属于哪一组、告诉它下一组,一个模型跑完它就把图并排放进挑图面板、先推荐一张再让你挑。AI 的推荐和你的挑选分开记进网络,你的算数在先;你没空挑时,关卡里设成“按推荐的继续”,它的推荐就作数(记成 AI 判的)。
|
||||
- New: **the training network**, a new view in the AI workbench's side column that draws the run record as a graph: your models on the left (by base model), the ways, skills and node packs that ran on the right, a line for each pair that ran together, its colour how it turned out (green good, yellow so-so, red not quite, grey not judged yet, short dashes when only the AI judged it) and its width how often. A click on a node or a line shows the details and the last pictures; with a node picked, dashed lines lead to what it has not tried yet. **Start a training round**: pick a skill (the AI's own prompts and those written with the advice, side by side) or the ways of one job, up to 4 models and how many pictures each, and hand it to the AI; it runs the trials in turn, Anomalous works out which trial each run was and tells it the next, and once a model's trials are done it puts them side by side in a picks panel, picks one itself, and you pick. Its pick and yours are recorded apart, yours counted first; if you have no time to pick, the Gates window's "go on with the recommended" lets its pick stand (recorded as the AI's).
|
||||
- 训练网络的记录默认 **不给 AI 看**:AI 只按现成的做法和 skill 做(AMB 照样先给它效果最好的那块做法),省得小模型被数字带偏。想让 AI 看,就在关卡窗口把 **训练网记录** 改成“给看”;你自己开的训练轮里,它总能看到。训练网络视图上方写着 AI 现在看不看得到。
|
||||
- The training network's record is **hidden from the AI** by default: it goes by the ready-made ways and skills alone (Anomalous still gives it the way that did best), so a small model is not led astray by numbers. To let the AI see it, set **Training network record** to "Shown" in the Gates window; in a training round you start it always sees it. The top of the training network view says whether the AI sees it now.
|
||||
- 新增 **跑图记录**:AMB 记下 AI 每次跑图用了哪些做法、skill 和第三方节点包,按主模型的底模分开(Illustrious、Anima……),效果好不好从你平常的操作里自动来:挑图面板里选中的、收藏的图算效果好,没被选中的算“没被挑中”;跑完的图下面还有 **效果好 / 不太行** 两个按钮,点了最算数,也告诉 AI。做法面板里每块做法和 skill 下面写着它在这台电脑上的记录(跑过几次、几次效果好、哪些 AI 跑的),没跑过的也写明。AI 开工时就拿到这份记录的摘要,加做法时拿到那块做法的记录;同一种活有几块做法能用时,AMB 先给在画布主模型上记录最好的那块。换哪个 AI 来,一看就知道什么试过、哪里还没试。**关卡** 里新增 **第三方节点**:选“只用做法里的”,AI 自己加节点时只能用做法里搭好的组合和你给任务挑的,ComfyUI 自带的节点照常能用。记录只有名字和次数,没有提示词。
|
||||
- New: **a record of what works**. Anomalous notes the ways, skills and custom node packs of each run the AI starts, by the base model of the run's main model (Illustrious, Anima…), and how it went comes from what you do anyway: a picture picked in a picks panel or kept in the gallery counts the run good, one passed over "not picked"; under a finished run's pictures, **Turned out well / Not quite** is your own word, which counts most and is told to the AI. In the Ways panel each way and skill says how it did on this computer (how often it ran, how often it turned out well, which AI apps ran it), or that it never ran here. The AI gets the record in a few words when it begins a task and a way's own when it adds it, and of the ways that can do a job Anomalous hands it the one with the best record on the canvas's model first, so whichever AI comes next sees what was tried and what was not. The **Gates** window has a new **Custom nodes** row: with "Only the ways'" the AI may add only the nodes of the ready-made ways and what you picked for the task; ComfyUI's built-in nodes stay allowed. The record holds names and counts, never a prompt.
|
||||
- 新增 **隐私模式**:任务标题栏的 **🔒** 一点,这个任务的**图和提示词原文**都不会发给 AI。图一张都不给(放大看图、图片信息、跑完的预览、你递给它的图、AI 软件里任务卡片上的图都一样),它只知道出了几张、成没成功;提示词和图片文件名换成 **[P1]**、**[img1]** 这样的代号:画布上、图片信息里、提示词库、搭配、模型的触发词和介绍、你自己改画布的记录里都一样(只有节点的“文字输入”被换掉,模型名、数字、选项照常给,第三方节点也一样)。AI 拿代号去跑图、写提示词、放挑图面板,AMB 再换回原文,所以它照样能干活,你那边看到的也都是原样。要新的提示词时,AI 会放一个 **提示词框**:你在里面写几条提示词、反向提示词,可以从图库选或拖进参考图,原文只存在 AMB 里;框上方还会按画布主模型的大小提醒你(小模型手容易画坏,可以选简单动作或藏手,只是可选)。新增 skill“隐私模式·怎么干活”,隐私任务里的 AI 开工时会被指过去;隐私任务里 AI 只拿得到这一个 skill,**做法** 面板的 skill 一栏也只显示它,关掉隐私后才换回普通的 skill。**关卡** 窗口里设新任务默认开不开;打开、关掉都记在时间线上并告诉 AI。所有工具的结果出门前都过同一道关,测试会在每个工具的结果里埋“暗号”提示词和图片名,确认一个都漏不出去。
|
||||
|
||||
+25
-1
@@ -14,7 +14,9 @@ workbench gives them a line to paste), or "wait", it waits with run_status; how
|
||||
AI waits for the user's answer to its question (answer_wait, ai_answer_wait.py), and what happens
|
||||
when that time runs out (no_answer): "stop", the AI ends its turn and waits for the user, or
|
||||
"recommended", a choice the AI marked a recommended option for takes it (never a gate's question);
|
||||
and which custom nodes the AI may add itself (node_rule): any, or only those of the ready-made ways.
|
||||
which custom nodes the AI may add itself (node_rule): any, or only those of the ready-made ways;
|
||||
and whether the AI is told the record of what worked here (record_view, ai_evidence.py): hidden
|
||||
unless the user shows it, while a training round they started always shows it (record_shown).
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -28,6 +30,7 @@ from .path_utils import atomic_write_json
|
||||
POLICIES = ("auto", "ask", "never")
|
||||
RUN_WAITS = ("call", "wait")
|
||||
NODE_RULES = ("any", "ways")
|
||||
RECORD_VIEWS = ("hidden", "shown")
|
||||
ANSWER_WAITS = (60, 180, 600) # seconds; the first call waits 30-55 s, get_answers the rest
|
||||
NO_ANSWERS = ("stop", "recommended")
|
||||
DEFAULTS = {"canvas": "auto", "gpu": "auto", "download": "ask", "network": "auto", "files": "ask"}
|
||||
@@ -106,6 +109,27 @@ def set_node_rule(mode):
|
||||
return _set_tool_setting("nodes", mode)
|
||||
|
||||
|
||||
def record_view():
|
||||
"""Whether the AI is told the record of what worked (ai_evidence.py): "hidden" until the user shows it,
|
||||
so it goes by the ready-made ways and skills alone (add_nodes still picks the way that did best)."""
|
||||
chosen = _tool_settings().get("record")
|
||||
return chosen if chosen in RECORD_VIEWS else "hidden"
|
||||
|
||||
|
||||
def set_record_view(mode):
|
||||
if mode not in RECORD_VIEWS:
|
||||
raise ValueError("record is hidden or shown")
|
||||
return _set_tool_setting("record", mode)
|
||||
|
||||
|
||||
def record_shown(task_id):
|
||||
"""The record goes to the AI when the user shows it, or in task `task_id` when it is a training round."""
|
||||
if record_view() == "shown":
|
||||
return True
|
||||
task = ai_tasks.get_task(task_id) if task_id else None
|
||||
return bool((task or {}).get("training"))
|
||||
|
||||
|
||||
def answer_wait():
|
||||
"""How long in all an AI waits for the user's answer, in seconds (one of ANSWER_WAITS)."""
|
||||
chosen = _tool_settings().get("answer_wait")
|
||||
|
||||
@@ -161,11 +161,12 @@ async def api_gates(request):
|
||||
POST {runs: call | wait}
|
||||
how the AI waits for a run (ai_gates.run_wait), POST {answer_wait: 60 | 180 | 600} for the user's answer,
|
||||
POST {no_answer: stop | recommended} what happens when that time runs out,
|
||||
POST {nodes: any | ways} which custom nodes the AI adds itself (ai_gates.node_rule)."""
|
||||
POST {nodes: any | ways} which custom nodes the AI adds itself (ai_gates.node_rule),
|
||||
POST {record: hidden | shown} whether the AI is told the record of what worked (ai_gates.record_view)."""
|
||||
def settings():
|
||||
return {"policies": ai_gates.policies(), "canvas_tab": ai_task_canvas.default_mode(), "privacy": ai_privacy.default_on(),
|
||||
"runs": ai_gates.run_wait(), "answer_wait": ai_gates.answer_wait(), "no_answer": ai_gates.no_answer(),
|
||||
"nodes": ai_gates.node_rule()}
|
||||
"nodes": ai_gates.node_rule(), "record": ai_gates.record_view()}
|
||||
|
||||
if request.method == "GET":
|
||||
return web.json_response(settings())
|
||||
@@ -183,6 +184,8 @@ async def api_gates(request):
|
||||
ai_gates.set_no_answer(body["no_answer"])
|
||||
elif "nodes" in (body or {}):
|
||||
ai_gates.set_node_rule(body["nodes"])
|
||||
elif "record" in (body or {}):
|
||||
ai_gates.set_record_view(body["record"])
|
||||
else:
|
||||
ai_gates.set_policy((body or {}).get("gate"), (body or {}).get("policy"))
|
||||
except ValueError as error:
|
||||
@@ -325,7 +328,7 @@ async def api_blocks(request):
|
||||
|
||||
async def api_training(request):
|
||||
"""GET /anomalous/ai_training: the training network (ai_training.py): the record summed up by base model,
|
||||
the main models here, the ways and skills; POST {title, skill | use, models, each, subject?, picture?}
|
||||
the main models here, the ways and skills, whether the AI is told it; POST {title, skill | use, models, each, subject?, picture?}
|
||||
starts a training round, a task for the next AI that calls."""
|
||||
from . import ai_skills, ai_training, mcp_canvas_edit, reference_blocks
|
||||
from .mcp_tools import ToolError
|
||||
@@ -346,7 +349,8 @@ async def api_training(request):
|
||||
"takes": bool(reference_blocks.BLOCKS[block["name"]].get("takes"))} for block in reference_blocks.status(info)]
|
||||
skills = [skill for skill in ai_skills.status() if not skill["private_only"]]
|
||||
return web.json_response({"record": await asyncio.to_thread(ai_evidence.tally), "models": await asyncio.to_thread(ai_training.models),
|
||||
"blocks": blocks, "skills": skills, "jobs": list(reference_blocks.JOBS)})
|
||||
"blocks": blocks, "skills": skills, "jobs": list(reference_blocks.JOBS),
|
||||
"shown_to_ai": ai_gates.record_view() == "shown"})
|
||||
|
||||
|
||||
def register_routes(app):
|
||||
|
||||
@@ -285,7 +285,10 @@ def add_nodes(ctx, nodes=None, near_node_id=None, replace=False, block=None, ima
|
||||
|
||||
|
||||
def _record(ctx, block, types):
|
||||
"""How block `block`, or the custom node packs of node types `types`, did in this computer's runs (ai_evidence.py)."""
|
||||
"""How block `block`, or the custom node packs of node types `types`, did in this computer's runs (ai_evidence.py),
|
||||
when the user shows the AI the record (ai_gates.record_shown)."""
|
||||
if not ai_gates.record_shown(ctx.get("task") or ai_tasks.active_task_id(ctx.get("client") or "AI", ctx.get("session") or "")):
|
||||
return ""
|
||||
if block is not None:
|
||||
words = ai_evidence.words("way", str(block))
|
||||
return f"Your runs with this way: {words}" if words else ""
|
||||
|
||||
@@ -4,7 +4,7 @@ show_panel / update_panel draw a panel from Anomalous's blocks (ai_panels.py), g
|
||||
reads what the user picked or typed on it, log_outside keeps what the AI did with other tools
|
||||
(ai_outside.py)."""
|
||||
|
||||
from . import ai_answer_wait, ai_decisions, ai_evidence, ai_marks, ai_training, ai_message_refs, ai_outside, ai_panels, ai_repaint, ai_run_control, ai_run_tracking, ai_task_links, ai_task_runs, ai_tasks, ai_toolbox, ai_privacy, ai_skills, reference_blocks
|
||||
from . import ai_answer_wait, ai_decisions, ai_evidence, ai_gates, ai_marks, ai_training, ai_message_refs, ai_outside, ai_panels, ai_repaint, ai_run_control, ai_run_tracking, ai_task_links, ai_task_runs, ai_tasks, ai_toolbox, ai_privacy, ai_skills, reference_blocks
|
||||
from .mcp_tools import MAX_LIMIT, ToolError, _schema
|
||||
|
||||
PACK_TYPES = 150 # node types listed per picked pack
|
||||
@@ -37,9 +37,9 @@ def begin_task(ctx, title, new_task=False):
|
||||
answer["privacy"] = ai_privacy.NOTE # the user writes the prompts and looks at the pictures: no skill for those
|
||||
elif ai_skills.directory():
|
||||
answer["skills"] = ai_skills.directory()
|
||||
record = ai_evidence.overview()
|
||||
record = ai_evidence.overview() if ai_gates.record_shown(task["id"]) else ""
|
||||
if record:
|
||||
answer["record"] = record # what ran here how often and how it went, by model: any AI's runs
|
||||
answer["record"] = record # what ran here how often and how it went, by model: any AI's runs (when the user shows it)
|
||||
if task.get("training"):
|
||||
answer["training"] = ai_training.brief(ai_tasks.get_task(task["id"])) # a round the user started in the training network
|
||||
box = ai_toolbox.effective(ai_tasks.get_task(task["id"]))
|
||||
@@ -247,12 +247,12 @@ def get_toolbox(ctx, task=None, skill=None):
|
||||
except ai_skills.SkillError as error:
|
||||
raise ToolError(str(error))
|
||||
ai_skills.note_use(ctx.get("client") or "AI", answer, session=ctx.get("session") or "", task_id=task or ctx.get("task"))
|
||||
record = ai_evidence.words("skill", str(skill))
|
||||
record = ai_evidence.words("skill", str(skill)) if ai_gates.record_shown(task_id) else ""
|
||||
if record:
|
||||
answer["record"] = f"Runs here after it: {record}" # how runs went with this advice, by model
|
||||
return answer
|
||||
box = ai_toolbox.effective(ai_tasks.get_task(task_id)) if task_id else None
|
||||
record = ai_evidence.overview()
|
||||
record = ai_evidence.overview() if ai_gates.record_shown(task_id) else ""
|
||||
if not box:
|
||||
return {"picked": False, "note": "The user picked nothing for this task; use what fits.", **({"record": record} if record else {})}
|
||||
answer = {"picked": True, "mode": box["mode"], "note": ai_toolbox.words(box), **({"record": record} if record else {})}
|
||||
|
||||
@@ -291,10 +291,11 @@ of ComfyUI's own nodes only); how it went is never asked for: a picture picked i
|
||||
(`ai_panels.answer`) or kept in the gallery (`kept_images.kept_keys`, read when the record is
|
||||
summed up) counts it good, its pictures passed over in a picks panel "not chosen", and the
|
||||
user's word under it (`POST /anomalous/ai_tasks/{id}/runs/{step}/verdict`, a user step the AI
|
||||
gets) goes over both. Names only, never prompt text; picture names stay on this computer. The
|
||||
AI reads it in begin_task and get_toolbox (`record`, at most a few hundred characters, nothing
|
||||
gets) goes over both. Names only, never prompt text; picture names stay on this computer. Once
|
||||
the user shows it (Gates "training network record", `ai_tools.json` `record`, hidden by default;
|
||||
a training round's task always shows it: `ai_gates.record_shown`) the AI reads it in begin_task and get_toolbox (`record`, at most a few hundred characters, nothing
|
||||
while nothing ran), with a way in add_nodes' answer and with a skill in get_toolbox's, with the
|
||||
AI apps that ran it so the next one knows what is untried. `add_nodes(use=…)` puts the use's
|
||||
AI apps that ran it so the next one knows what is untried. Shown or not, `add_nodes(use=…)` puts the use's
|
||||
runnable ways in order by their record on the canvas's base model (asked of the page only when
|
||||
one has a record). With the Gates' "custom nodes: only the ways'" (`ai_tools.json` `nodes`),
|
||||
`mcp_canvas_edit._allowed` refuses a custom node no way builds and the task did not pick.
|
||||
|
||||
@@ -75,7 +75,7 @@ AMB 更新以后,AI 软件还拿着旧的工具列表来调用时,标题栏
|
||||
- 从上往下读,编号 1、2、3……;AI 连着查资料、连着改画布的几步折成一行(`ui_ai_chain.js`),点开看每一步。
|
||||
- 每一步下面写它做了什么(`ui_ai_step_body.js`),出的东西能直接去:图片进看图器、模型进模型页、画布改动能定位和撤销(`ui_ai_results.js`)。
|
||||
- 跑完的图下面是「这次效果:效果好 / 不太行」(`ui_ai_verdict.js`),再点一下收回。点了记进跑图记录,也告诉 AI;不点也行,挑图、收藏会自己记。跑图那一步还写着这次用到的做法。做法面板里每块做法和 skill 下面是它在这台电脑上按模型分的记录(`api/ai_evidence.py`)。
|
||||
- 右栏「训练网络」(`ui_ai_network.js`):左模型、右做法 / skill / 节点包,连线颜色是效果;点点或线看详情。「开一轮训练」(`ui_ai_training_setup.js`)选练什么、哪些模型、每组几张,「交给 AI 开练」建一个等 AI 接的任务并给出要贴的那句话。
|
||||
- 右栏「训练网络」(`ui_ai_network.js`):左模型、右做法 / skill / 节点包,连线颜色是效果;点点或线看详情。「开一轮训练」(`ui_ai_training_setup.js`)选练什么、哪些模型、每组几张,「交给 AI 开练」建一个等 AI 接的任务并给出要贴的那句话。上方一行写着 AI 现在看不看得到这份记录:默认不给看,关卡里「训练网记录」可以打开,训练轮里总给看。
|
||||
- 图片上鼠标移上去有工具(`ui_ai_images.js`):「图片与参数」、「保存为…」、勾两张对比,还有 ✎ 标注。
|
||||
- 时间线和展台里的图先用缩略图(`/anomalous/output_thumbnail`),显示得比缩略图大时才换原图(`/anomalous/output_preview`:超大图换的是 4096 像素的预览),打开任务不用等大图。
|
||||
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ claude mcp add --transport http anomalous http://127.0.0.1:8188/anomalous/mcp
|
||||
|
||||
**AI 改副本**(默认):AI 第一次改画布前,AMB 先把你正开着的工作流复制到一个以任务命名的新标签页(副本),之后 AI 的修改、读画布和运行都只在那一页;你切去别的标签页也没关系,它下次动手前 AMB 会先切回去。你原来的工作流一笔不动。AI 用 `new_workflow` / `open_workflow` 打开的标签页就直接算这个任务的。任务标题栏有 **AI 改副本 ▾**(点开可以换成 **改当前画布**,每种都写着是什么意思)和 **切到副本**(点一下切过去);**关卡** 窗口里的“AI 改画布时”设定新任务的默认做法。
|
||||
|
||||
**跑图记录(哪套组合在哪个模型上好用)**:AI 每次跑图,AMB 都记下这次用了哪些做法、哪些 skill、哪些第三方节点包,主模型是什么底模(比如 Illustrious、Anima)。效果好不好不用你专门去记:在挑图面板选中的图、收藏的图(存成工作流、搭配、提示词)算 **效果好**;挑图时没被选的算 **没被挑中**;跑完的图下面也有 **这次效果:效果好 / 不太行** 两个按钮,你点的那个最算数,还会告诉 AI(点“不太行”它就该换做法、设置或提示词再跑),再点一下收回。做法面板里每块做法和 skill 下面写着它的记录,比如“Illustrious:跑过 4 次,3 次效果好”;没跑过的写“这台电脑上还没跑过”,鼠标停在一行上能看到是哪些 AI 跑的。AI 开工时(`begin_task`)就能看到这份记录的摘要,加做法时也会告诉它这块做法的记录;同一种活有几块做法都能用时,AMB 先给它在画布主模型上记录最好的那块。所以下一个 AI,不管是 Claude、Gemini 还是 GPT,一看就知道什么在这台电脑上试过、效果怎样、哪里还没试。记录只有名字和次数,没有提示词;存在 ComfyUI 的 user 文件夹里(anomalous/ai_evidence.json,最近 2000 次)。**关卡** 窗口里的 **第三方节点** 选“只用做法里的”,AI 自己加节点时就只能用做法里那些搭好的组合,加上你给这个任务挑的;ComfyUI 自带的节点照常能用。
|
||||
**跑图记录(哪套组合在哪个模型上好用)**:AI 每次跑图,AMB 都记下这次用了哪些做法、哪些 skill、哪些第三方节点包,主模型是什么底模(比如 Illustrious、Anima)。效果好不好不用你专门去记:在挑图面板选中的图、收藏的图(存成工作流、搭配、提示词)算 **效果好**;挑图时没被选的算 **没被挑中**;跑完的图下面也有 **这次效果:效果好 / 不太行** 两个按钮,你点的那个最算数,还会告诉 AI(点“不太行”它就该换做法、设置或提示词再跑),再点一下收回。做法面板里每块做法和 skill 下面写着它的记录,比如“Illustrious:跑过 4 次,3 次效果好”;没跑过的写“这台电脑上还没跑过”,鼠标停在一行上能看到是哪些 AI 跑的。同一种活有几块做法都能用时,AMB 先给 AI 在画布主模型上记录最好的那块。记录本身默认不给 AI 看:它只按现成的做法和 skill 做,省得小模型被一堆数字带偏。**关卡** 窗口里的 **训练网记录** 选“给看”,AI 开工时(`begin_task`)就能看到这份记录的摘要,加做法、取 skill 时也会告诉它这块做法、这个 skill 的记录,下一个 AI,不管是 Claude、Gemini 还是 GPT,一看就知道什么在这台电脑上试过、效果怎样、哪里还没试;你自己开的训练轮里,它总能看到。记录只有名字和次数,没有提示词;存在 ComfyUI 的 user 文件夹里(anomalous/ai_evidence.json,最近 2000 次)。**关卡** 窗口里的 **第三方节点** 选“只用做法里的”,AI 自己加节点时就只能用做法里那些搭好的组合,加上你给这个任务挑的;ComfyUI 自带的节点照常能用。
|
||||
|
||||
**训练网络**:AI 工作台右栏的 **训练网络**(脉搏图标)把这份记录画成一张网:左边是你的模型(按底模分,写着各有几个),右边是做法、skill 和跑过的节点包,一起跑过的连一条线,颜色是效果(绿好、黄一般、红不太行、灰跑过还没人评),短虚线表示只有 AI 评过,线越粗跑得越多。点一个模型、一块做法或一条线,下面写着它的记录:跑过几次、你怎么判的、AI 怎么判的、哪些 AI 跑过、最近的几张图;选中一个点时,浅虚线连着它还没试过的组合。**开一轮训练**:选练什么(一个 skill:同一个题材,AI 自己写的提示词和照 skill 建议写的并排比;或者一种活的几块做法并排比)、在哪几个模型上(最多 4 个)、每组几张(同样的种子),点 **交给 AI 开练**,就建好一个等 AI 来接的任务,把显示的那句话贴给你的 AI。AI 按计划一组组跑,AMB 自己认出每次跑图对应计划里哪一组,并在回答里告诉它下一组;一个模型的几组跑完,AI 会把这几张并排放进挑图面板,先推荐一张,再由你挑。你的挑选和 AI 的推荐都记进网络,分开记、你的算数在先;你没空挑时,关卡里“等不到回答时”设成按推荐的继续,AI 的推荐就作数(只记成 AI 判的)。
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"""The record of what works (api/ai_evidence.py): a run counts for the ways it still has, the skills
|
||||
fetched before it and the packs of its nodes, by its main model's base model; the user's picks,
|
||||
keeps and word say how it went; the AI is told it in begin_task, get_toolbox and add_nodes, a use's
|
||||
way that did best is picked first, and the user can let custom nodes in only by the ways.
|
||||
keeps and word say how it went; the AI is told it in begin_task, get_toolbox and add_nodes once the
|
||||
user shows it or in a training round, a use's way that did best is picked first, and the user can
|
||||
let custom nodes in only by the ways.
|
||||
Temporary folders only."""
|
||||
import os
|
||||
import sys
|
||||
@@ -98,6 +99,7 @@ class EvidenceTests(unittest.TestCase):
|
||||
self.assertNotIn("record", mcp_task_tools.begin_task({"client": "Gemini", "task": self.task}, "repaint"), "nothing ran yet")
|
||||
step_id = self.run_with(PROMPT)
|
||||
ai_evidence.set_verdict(self.task, step_id, "good")
|
||||
ai_gates.set_record_view("shown")
|
||||
begun = mcp_task_tools.begin_task({"client": "Gemini", "task": self.task}, "repaint")
|
||||
self.assertIn("inpaint_lanpaint (way) Illustrious: 1 good of 1", begun["record"])
|
||||
self.assertLessEqual(len(begun["record"]), ai_evidence.OVERVIEW_CHARS + 100, "a few words in begin_task")
|
||||
@@ -107,6 +109,24 @@ class EvidenceTests(unittest.TestCase):
|
||||
self.assertIn("(run by Gemini)", fetched["record"], "which AI ran it, for the next one to go on from")
|
||||
self.assertIn("record", mcp_task_tools.get_toolbox({"client": "Gemini", "task": self.task}))
|
||||
|
||||
def test_hidden_from_the_ai_until_the_user_shows_it_or_starts_a_round(self):
|
||||
ai_evidence.set_verdict(self.task, self.run_with(PROMPT), "good")
|
||||
self.assertEqual(ai_gates.record_view(), "hidden", "hidden by default")
|
||||
self.assertNotIn("record", mcp_task_tools.begin_task({"client": "Gemini", "task": self.task}, "repaint"))
|
||||
with mock.patch.object(mcp_task_tools, "_canvas_model", return_value=None):
|
||||
fetched = mcp_task_tools.get_toolbox({"client": "Gemini", "task": self.task}, skill="prompt_pose")
|
||||
self.assertNotIn("record", fetched, "the skill's advice alone")
|
||||
self.assertNotIn("record", mcp_task_tools.get_toolbox({"client": "Gemini", "task": self.task}))
|
||||
self.assertEqual(mcp_canvas_edit._record({"task": self.task}, "inpaint_lanpaint", []), "")
|
||||
self.assertEqual(ai_evidence.order("way", ["inpaint_basic", "inpaint_lanpaint"], lambda: "Illustrious"),
|
||||
["inpaint_lanpaint", "inpaint_basic"], "the way that did best still comes first")
|
||||
with mock.patch.object(ai_gates.ai_tasks, "get_task", return_value={"training": {"kind": "skill"}}):
|
||||
self.assertTrue(ai_gates.record_shown(self.task), "a training round the user started shows it")
|
||||
ai_gates.set_record_view("shown")
|
||||
self.assertIn("Your runs with this way", mcp_canvas_edit._record({"task": self.task}, "inpaint_lanpaint", []))
|
||||
with self.assertRaises(ValueError):
|
||||
ai_gates.set_record_view("some")
|
||||
|
||||
def test_the_way_that_did_best_on_the_model_comes_first(self):
|
||||
asked = []
|
||||
self.assertEqual(ai_evidence.order("way", ["a", "b"], lambda: asked.append(1)), ["a", "b"])
|
||||
|
||||
@@ -1466,9 +1466,15 @@ export const i18n = {
|
||||
aiGateWhy_nodes: "AI 自己往画布上加节点时,第三方节点包的节点能不能随便用。选“只用做法里的”,它就只能用做法面板里那些搭好的组合,加上你给这个任务挑的;ComfyUI 自带的节点照常能用。",
|
||||
aiNodeRule_any: "随便用",
|
||||
aiNodeRule_ways: "只用做法里的",
|
||||
aiGate_record: "训练网记录",
|
||||
aiGateWhy_record: "AI 开工时能不能看到训练网络里的记录(哪块做法、哪个 skill 在哪种模型上效果怎样)。默认不给看:AI 只按现成的做法和 skill 做,AMB 照样先给它效果最好的那块做法。你自己开的训练轮里,它总能看到。",
|
||||
aiRecordView_hidden: "不给看",
|
||||
aiRecordView_shown: "给看",
|
||||
aiRecord_ai_good: ",AI 推荐 {n} 次",
|
||||
aiSideNetwork: "训练网络",
|
||||
aiNetIntro: "左边是你的模型(按底模分),右边是做法、skill 和跑过的节点包。连线是一起跑过的,颜色是效果:绿=好,黄=一般,红=不太行,灰=跑过还没人评;短虚线是只有 AI 评过。线越粗跑得越多。",
|
||||
aiNetSeen_false: "AI 平时看不到这些,只按现成的做法和 skill 做;关卡里的“训练网记录”可以打开。你开的训练轮里它总能看到。",
|
||||
aiNetSeen_true: "AI 开工时会看到这份记录的摘要;关卡里的“训练网记录”可以关掉。",
|
||||
aiNetTrain: "开一轮训练",
|
||||
aiNetModels: "模型",
|
||||
aiNetItems: "做法 / skill",
|
||||
@@ -5052,9 +5058,15 @@ export const i18n = {
|
||||
aiGateWhy_nodes: "Whether the AI may add nodes of any custom node pack when it adds nodes itself. With \"Only the ways'\" it may use only the ready-made combinations of the Ways panel and what you picked for the task; ComfyUI's built-in nodes stay allowed.",
|
||||
aiNodeRule_any: "Any",
|
||||
aiNodeRule_ways: "Only the ways'",
|
||||
aiGate_record: "Training network record",
|
||||
aiGateWhy_record: "Whether the AI is told the training network's record when it starts (how each way and skill did on each kind of model). Hidden by default: the AI goes by the ready-made ways and skills alone, and Anomalous still gives it the way that did best. In a training round you start it always sees it.",
|
||||
aiRecordView_hidden: "Hidden",
|
||||
aiRecordView_shown: "Shown",
|
||||
aiRecord_ai_good: ", the AI's pick {n} times",
|
||||
aiSideNetwork: "Training network",
|
||||
aiNetIntro: "Left are your models (by base model), right the ways, skills and the node packs that ran. A line joins what ran together, its colour how it turned out: green good, yellow so-so, red not quite, grey ran but nobody judged it; short dashes mean only the AI judged it. The thicker, the more it ran.",
|
||||
aiNetSeen_false: "The AI does not see this as a rule: it goes by the ready-made ways and skills. Show it in the Gates window (\"Training network record\"); in a training round you start it always sees it.",
|
||||
aiNetSeen_true: "The AI is told a summary of this record when it starts; hide it in the Gates window (\"Training network record\").",
|
||||
aiNetTrain: "Start a training round",
|
||||
aiNetModels: "Models",
|
||||
aiNetItems: "Ways / skills",
|
||||
|
||||
@@ -149,6 +149,8 @@ export async function openGates() {
|
||||
async mode => (await save({ runs: mode })).runs),
|
||||
choiceRow('nodes', ['any', 'ways'], known.nodes || 'any', mode => t(`aiNodeRule_${mode}`),
|
||||
async mode => (await save({ nodes: mode })).nodes),
|
||||
choiceRow('record', ['hidden', 'shown'], known.record || 'hidden', mode => t(`aiRecordView_${mode}`),
|
||||
async mode => (await save({ record: mode })).record),
|
||||
el('p', 'anomalous-ai-gates-note', t('aiGatesNote')));
|
||||
aiWindow(t('aiGates'), body);
|
||||
}
|
||||
|
||||
@@ -237,6 +237,7 @@ function draw(pane, ctx, redraw) {
|
||||
body.append(trainingSetup(shown, setup, { back: () => { setup = null; redraw(); }, openTask: ctx.openTask }));
|
||||
} else {
|
||||
body.append(el('div', 'anomalous-ai-blocks-note', t('aiNetIntro')),
|
||||
el('div', 'anomalous-ai-blocks-note', t(`aiNetSeen_${shown.shown_to_ai === true}`)),
|
||||
button('anomalous-ai-net-train', t('aiNetTrain'), () => { setup = {}; redraw(); }), ...graphBox(shown, ctx, redraw));
|
||||
}
|
||||
pane.replaceChildren(sideHead(t('aiSideNetwork'), ctx.close), body);
|
||||
|
||||
Reference in New Issue
Block a user