FunPackStudio combines Refinement Key, Scene Builder, Refiner V2,
Advisor LLM, LoRA loading, and Conditioning Adjust under a single node
with a tabbed popup editor. Rating widget stays on the node face;
everything else is in the popup.
Python:
- FunPackStudio.run() chains all subsystems: scene builder prompt
construction, advisor LLM load (using shared cache), LoRA loading via
FunPackLoraLoader, FunPackVideoRefinerV2.refine_v2(), and
FunPackConditioningAdjust.adjust(). No code duplication.
- Added optional _seed parameter to FunPackVideoRefinerV2.refine_v2()
so Studio can generate a seed and output it for wiring to samplers.
- Added /funpack/available_loras endpoint for the LoRA picker.
JS (funpack_studio.js):
- Tabbed popup: Session, Scene, Refiner, Advisor, LoRA, Adjustments.
- Session: refinement key, reset toggle, scene builder mode selector.
- Scene: scene load/save, phrase bank from memory, positive prompt
editor (active when scene builder is not Pass-through).
- Refiner: all V2 settings, feedback prompt, intent override.
- Advisor: LLM enable toggle, model path, dtype.
- LoRA: dynamic list of LoRAs with name/type/model-weight/clip-weight,
loaded from /funpack/available_loras.
- Adjustments: phrase/strength pairs with session phrase bank.
- Settings serialized as JSON in hidden studio_settings widget.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The node was extracting pooled_output from the conditioning meta dict,
which is None for LTX/Gemma3 text encoders. Adjustments were silently
skipped for every phrase.
Use conditioning.mean(dim=(0,1)) on the sequence tensor itself - same
approach V2 uses for all its conditioning memory operations. Phrase
vectors are encoded the same way (mean of their sequence tensor). The
accumulated direction shift is then applied as a uniform broadcast
across all sequence positions so the tensor shape stays intact.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
addCustomWidget failed silently in this ComfyUI version. Switch to
node.addWidget("button",...) which is natively supported. Also add the
same hideWidget retry timing pattern Scene Builder uses (rAF + two
setTimeout calls) so the adjustments text widget reliably disappears
after the node is created or reconfigured.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When refinement_key_input is connected (from FunPack Refinement Key
Loader), the popup fetches phrase_memory from that session via a new
/funpack/phrase_memory endpoint and shows all learned phrases as
clickable chips grouped by category. Click a chip to add it to the
adjustment list with a default strength of 0.1.
Search field filters phrases live. Phrases are sorted by evidence count
so the most-seen ones appear first within each category.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inserts between Refiner V2 and the sampler. Takes CONDITIONING + CLIP,
lets the user specify phrase/strength pairs in a floating popup panel.
For each active pair: encode the phrase, compute unit-norm direction from
base conditioning toward phrase conditioning (in pooled space), apply at
user-set strength. Positive = push toward that phrase, negative = away.
Bypasses V2's category classification entirely - adjustments target the
exact phrase the user typed, no mis-categorization possible.
Popup hides the raw JSON widget, shows "Edit Adjustments" button on the
node face with a compact summary of active adjustments. Close saves.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two issues prevented diagnostics from reliably appearing in Full mode:
1. The analysis prompt asked for "root cause of recurring patterns" which
is too vague for early sessions with no history. Now adapts: simple
per-run analysis when no session history exists, pattern analysis when
history is available.
2. When the LLM fails or produces empty output after thinking-token
stripping, analysis was silently "" and nothing was stored. Added a
rule-based fallback that builds a diagnostic from axis_feedback
(regressed/missing/wrong axes) so the history always accumulates
even when the LLM produces nothing useful.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both _v2_apply_perfect_repair_phrases (injects phrases from previously
Perfect-rated runs) and _v2_emphasized_prompt (repeats existing phrases
matching missing axes) were running unconditionally regardless of the
prompt_repair toggle. With prompt_repair=False they should be no-ops -
the user has explicitly said they do not want the node modifying the
prompt text from memory.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When Pass 1 generates a diagnostic, append it to the system prompt of
Pass 2 so the LLM has the session root-cause analysis at the highest
priority level rather than only as a user-message field. The analysis
remains in the user message too for reference.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The diagnostic analysis pass now reasons over session history instead of
just the current prompt. It receives the axis feedback (what's missing,
regressed, resolved, wrong), current rating, and the accumulated session
history, and its output asks for root cause identification across runs
rather than per-run "what to fix" instructions.
Diagnostics are now recorded for all advisor modes that generate them
(Full and Only diagnostics), not only "Only diagnostics". Previously the
Full mode ran analysis but discarded the result without storing it, so
the history never built up and subsequent repairs had no session context
to draw on.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Added explicit rules against metaphors, prose, and emotional language.
Requires every output phrase to describe something a camera can directly
capture. Targets the tendency of instruction-tuned LLMs to produce
poetic rewrites that video diffusion models cannot interpret.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Qwen3 encodes <think> and </think> as special token IDs (151648/151649).
With skip_special_tokens=True they are stripped silently before the regex
runs, leaving raw reasoning content concatenated with the response and no
way to separate them. The thinking content then bleeds into the repaired
prompt.
Fix: always decode with skip_special_tokens=False so the thinking delimiters
are present in the string. Strip complete <think>...</think> blocks first,
then truncated blocks (no closing tag, model ran out of budget), then clean
remaining special tokens like <|im_end|> with a separate pattern.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removed three tests that exclusively tested negative conditioning/prompt
functionality which was removed in 2.5.0:
- test_refiner_v2_negative_advisor_repairs_negative_prompt_and_exports_one_string
- test_refiner_v2_returns_empty_negative_conditioning_when_negative_blank
- test_negative_prompt_repair_adds_poorly_rated_tags_persistently
Fixed six tests with stale assertions caused by API changes since they
were written: updated return-value unpack positions after negative output
was removed, dropped CONDITIONING-owned/CLIP-owned status checks that no
longer appear in any output, dropped Gemma3 tokenizer status check that
is only present in the error path now, updated Learning section header
name, and updated RETURN_NAMES assertion to check by value not position.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When pad_token == eos_token the model cannot infer the attention mask
from input_ids, so it warns and attends to all positions including
padding. In practice this causes the model to echo the input prompt
unchanged, randomly drop spaces, or produce garbled output depending
on sampling temperature. Passing an all-ones attention_mask explicitly
tells the model exactly which positions are real input tokens.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
apply_chat_template(..., tokenize=True, return_tensors="pt") returns a
BatchEncoding in newer transformers versions instead of a plain tensor.
Accessing .shape[1] on a BatchEncoding raises AttributeError because it
looks up "shape" in the data dict and finds nothing.
Extract input_ids from the result with hasattr check before calling
.to(device) and computing prompt_length. Applied to both the normal
chat-template path and the skip_template encode() path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Perfect is not a ceiling. If the user has an active advisor mode and
provides feedback_prompt, the advisor must honor it regardless of the
rating. Two guards were blocking this:
- Analysis pass (pass 1): was skipped when is_perfect=True even with no
feedback, so Full/Only-diagnostics mode produced no analysis for
Perfect runs. Removed the not-is_perfect restriction so analysis runs
whenever mode requires it and no explicit feedback was given.
- Repair guard (pass 2): had an explicit is_perfect-and-not-has_feedback
branch that silently blocked repair for every Perfect run with no user
text. Removed it entirely. The only remaining guard is the existing
allow_prompt_change check (Learning mode / advisor mode Off).
Now for Perfect + user feedback: advisor honors the feedback fully.
For Perfect + no feedback + Full mode: analysis runs, repair runs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Strip <think>...</think> blocks in decode so Qwen3 chain-of-thought
doesn't pollute the repaired prompt and cause validation to reject it
- Pass enable_thinking kwarg to apply_chat_template (with TypeError
fallback for models that don't support it); propagate thinking flag
through tokenize -> generate so the token budget is expanded by 2048
when thinking mode is active, giving room for reasoning + response
- Return 1.0 from _v2_text_semantic_similarity when the clip has no
encode_from_tokens_scheduled - generation-only clips can't compute
similarity so they shouldn't be penalized with a 0.0 semantic gate
- Add FunPackAdvisorLLM to standalone (non-package) imports in
__init__.py so tests can run without the full ComfyUI runtime
- Update three stale advisor tests: 5-value _v2_prompt_advisor unpack,
"Encoded as:" prefix change, 6-return-value unpacking after negative
conditioning was removed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a phrase injected by the perfect-repair system is present during a
generation rated Awful or Wrong Appearance, it is now hard-deleted from
perfect_repairs in the intent family slot. One bad rating is enough to
stop the re-injection permanently. Evicted phrase names are reported in
the intent family status line.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- _v2_direction_readout: new helper showing each direction slot's status
in plain language ("warming up 2/3 runs", "active 8 runs, mag 0.412",
"away from learned pattern") for liked, bad, and all three axes.
- _v2_apply_conditioning_memory: return replaced with multi-line readable
block showing strength, reward trend, streak, which mode each slot is
using, and what axis adjustments were applied.
- training_info Adaptation section: now includes the full direction
readout so users can see exactly what memory state the refiner is in.
- Model patch status: expanded from one line to a readable block showing
which direction slots are active with their run counts, and lists the
phrase texts being emphasized (up to 4) alongside position range count.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TextGenerate calls tokenize(prompt, skip_template=bool, image=..., thinking=...)
and generate(..., min_p=..., presence_penalty=...). Wrapper now handles all of:
- skip_template=True: raw encode without chat template (for nodes like
TextGenerateLTX2Prompt that pre-format with role tokens)
- skip_template=False (default): apply model's own chat template via
apply_chat_template, with optional system_prompt kwarg
- min_p, presence_penalty: forwarded to model.generate() with progressive
fallback stripping unsupported params via TypeError catch
- All other kwargs absorbed silently so future TextGenerate params don't break
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FunPackAdvisorLLM:
- Loads any HuggingFace CausalLM via AutoModelForCausalLM.from_pretrained
- Wraps it in _FunPackAdvisorLLMWrapper which exposes tokenize/generate/decode
matching the interface _v2_generate_advisor_text already uses
- tokenize() accepts system_prompt kwarg, applies the model's own chat
template via apply_chat_template, absorbs unsupported kwargs silently
- generate() uses max_new_tokens (not max_length) so prompt length does
not eat into the generation budget
- Model cached in _FUNPACK_ADVISOR_LLM_CACHE by (path, dtype) - no
reload on repeated runs
- Returns CLIP type so it plugs directly into advisor_clip input
- Default: huihui-ai/Huihui-Qwen3-8B-abliterated-v2
Session reset fix:
- _v2_empty_state was missing intent_expansion_memory, session_source_mean_count,
liked_dir, bad_dir - these survived reset via setdefault on next run.
Added all four to the empty state so reset is complete.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both _v2_advisor_prompt and _v2_advisor_analysis_prompt now build natural
language user messages instead of structured FIELD: value format that only
instruction-following models can interpret.
System prompt reduced to one line: "You are a video prompt editor. Rewrite
the prompt to fix the specific issue. Output only the corrected prompt."
Simple enough to not conflict with enhancement models' own system prompts.
Repair user message: Issue description, user note, scene context, past
feedback, suggestions, analysis, then "Prompt to fix: ... Write the
corrected prompt." - reads as a natural enhancement request.
Analysis user message: same context then "What specifically needs to
change? One or two sentences, reference actual words from the prompt."
This works for:
- Enhancement models (Sulphur/Qwen): see a natural prompt improvement
request they were trained on, produce useful output
- Instruction models: follow the clear natural language request
- The label-free output is already handled by the raw-text fallback
in _v2_parse_advisor_response
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
generate/decode/return were inside the except TypeError block so they
only ran when layer 1 failed. When layer 1 succeeded (system_prompt kwarg
accepted), tokens was set but the function fell off the end returning None,
causing 'cannot unpack non-iterable NoneType' at the call site.
Restructure: tokenize into tokens=None, try each layer in order using
if tokens is None as the gate, then generate/decode/return always runs
after tokenization regardless of which layer succeeded.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CLIP.tokenize() passes **kwargs to tokenize_with_weights, so wrappers
that natively handle system/user separation (like Sulphur/Qwen) just
work by passing system_prompt= as a kwarg. Three-layer fallback:
1. clip.tokenize(user, system_prompt=system) - native kwarg support
2. apply_chat_template via BFS-found HF tokenizer - manual formatting
3. flat string + "Output:" anchor - last resort for bare wrappers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The advisor was sending one flat string to clip.tokenize() so models
expecting ChatML/Gemma role tokens treated the whole thing as a user
message and echoed instructions back into the output.
- _v2_find_chat_tokenizer: BFS through CLIP wrapper hierarchy looking
for a HuggingFace tokenizer exposing apply_chat_template (depth ≤ 5,
checks tokenizer/processor/cond_stage_model/patcher/model attrs).
- _v2_advisor_analysis_prompt and _v2_advisor_prompt now return
(system_str, user_str) tuples instead of one combined string.
- _v2_generate_advisor_text now accepts (system_prompt, user_prompt):
- If chat tokenizer found: applies apply_chat_template with proper
system/user roles and add_generation_prompt=True before tokenizing.
- Fallback (no template): flat concatenation + "Output:" anchor so
the model generates output instead of echoing instructions.
- Updated V2_PROMPT_ADVISOR_SYSTEM_PROMPT to state that inputs arrive
in the user message, so the model knows the structure.
- Updated both call sites in _v2_prompt_advisor.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1.05 repetition_penalty was negligible for a 12B model generating long
sequences. 1.3 is meaningfully aggressive. no_repeat_ngram_size=5 hard-
blocks any 5-gram from repeating, which stops loops that penalty alone
misses. Temperature raised 0.5->0.7 so the peaked distribution doesn't
trap the model in local loops even with penalty applied. Falls back to
no no_repeat_ngram_size if the wrapper doesn't forward that kwarg.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
encode_cache was per-run only - every new rating caused all phrase
encodings to redo from scratch even with unchanged CLIP and text.
_V2_PERSISTENT_ENCODE_CACHE is a module-level dict keyed by
(id(clip), prompt_text), capped at 4096 entries. _v2_encode_prompt
checks persistent cache before encoding, writes to both caches on
miss. If CLIP model is swapped, id(clip) changes so stale entries
are never used (just unused memory until cap evicts them).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MODEL input/output:
- Optional MODEL input; patched MODEL is the 6th output alongside existing 5.
- _v2_apply_model_patches: clones model and installs attn2_patch for
layer-level cross-attention K/V injection using stored direction vectors.
Directions are in text-encoder space [dim] which matches context_attn2
before projection - compatible across all models using attn2 cross-attention.
- Per-layer scale 0.02 x NORM_SCALE(0.3) x avg_active_norm so effect
accumulates gradually across layers without blowing up.
Phrase emphasis via K/V scaling:
- _v2_find_phrase_token_ranges: locates repair candidate phrases in the
full conditioning sequence using cosine similarity between mean-pooled
phrase encoding and each token position. Model-agnostic, no tokenizer
format dependency.
- _v2_build_attn2_patch: scales K and V at matched positions by 1.25,
boosting cross-attention to concepts added by prompt repair/advisor.
Status and training_info cleanup:
- Filter out lines that just say "none", "off", "skipped", "idle" - these
added noise without signal.
- Status now shows only what actually happened: adaptation summary,
repair/advisor actions, flags for special modes.
- training_info reorganized: Run, Memory, Prompt Analysis, Adaptation,
Guidance, LoRA - sections only shown when non-empty.
- Removed negative_memory_status from training_info (negative removed).
- Added model_patch_status to Adaptation section when model connected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The existing full-tensor conditioning storage resets when prompt lengths
change, making the memory useless when prompts change every run. This
adds a parallel direction-based mechanism that is shape-invariant:
- _v2_pool_conditioning: mean-pools [batch, seq, dim] -> [dim]
- _v2_update_session_mean: running mean of raw source conditioning
across all runs, pooled to [dim]. Represents the session baseline.
- _v2_store_direction: stores unit-normalized delta (payload - session_mean)
alongside existing averaged full-tensor. Accumulated per slot as a
running-averaged unit direction + magnitude scalar.
- _v2_apply_direction: applies stored direction to active tokens only
(norm > 1% of max), scaled by strength * NORM_SCALE(0.3) * avg_token_norm.
Active-token masking prevents adjusting padding/near-zero tokens.
Applied everywhere conditioning is stored and applied:
- liked_conditioning: switches to direction mode after 3+ perfect runs
- bad_conditioning: switches to direction repulsion after 3+ bad runs
- axis_conditioning_memory[axis][positive/negative]: per-axis directions
Before 3 runs accumulate per slot, falls back to existing lerp/repel
approach. Both mechanisms are fully backward compatible - old state
keys are preserved alongside new direction keys.
Advisor RATING description updated: Missing details now correctly
describes small actions and micro-interactions, not visual quality.
Missing quality covers visual quality/artifacts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When the previous run was rated Perfect and none of the thaw conditions
are met, the refiner skips all prompt transformations (alignment, repair,
wildcard cleanup, emphasis) and re-uses the previously encoded prompt
directly.
Thaw conditions (any one releases the freeze):
- feedback_prompt is provided (user explicitly wants a change)
- intent prompt changed significantly (body similarity < 0.50)
- source image fingerprint changed from previous run
The advisor analysis pass is also skipped on Perfect ratings with no
feedback - nothing to analyse when the output was already perfect, and
the repair would be blocked by the existing is_perfect guard anyway.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Intent prompts can be short shorthands (e.g. "smoking in bowling club").
As the user provides feedback, those notes are stored in
intent_expansion_memory keyed by the normalized intent prompt and
surfaced to the advisor as INTENT_NOTES alongside ORIGINAL_USER_INTENT.
The advisor system prompt is updated to treat INTENT_NOTES as the true
expanded meaning of the intent and prioritize it during repair.
- _v2_update_intent_expansion: stores feedback per intent key, max 16
- _v2_format_intent_expansions: formats stored notes as a semicolon list
- intent_expansions retrieved before advisor call, stored after each run
with feedback_prompt present
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Skip the analysis pass entirely when feedback_prompt is provided.
The user already described what is wrong; running analysis is redundant
and was producing the echoed instruction text as its output. Repair pass
still runs with the feedback in OPTIONAL_NOTE.
- Rewrite the analysis prompt output instruction to use a placeholder
format (<your specific analysis...>) instead of content words the model
can echo back verbatim.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CHANGELOG: add new Changed and Fixed entries for negative conditioning
removal, advisor system prompt rewrite, token limit increases, Only
prompt double-call fix, and encoded_prompts bug fix.
- README: update 2.5.0 section to cover all of the above.
- docs/FunPackVideoRefinerV2.md: remove negative_prompt input and
modified_negative output; update advisor_mode description with new
structured input format and token budgets; update encoded_prompts
output description with all four possible sections.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The success return was calling _v2_encoded_prompts_output(prompt_to_encode)
with no advisor kwargs, so only "Positive prompt:" ever appeared. Only the
error-path return had the full arguments.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- _v2_prompt_advisor now returns the suggested prompt as 5th value on
both the applied and rejected paths (not just rejected).
- _v2_encoded_prompts_output shows it as "Advisor suggestion (applied):"
or "Advisor suggestion (rejected):" so the generated text is always
visible regardless of whether validation passed.
- Renamed "Advisor:" → "Advisor analysis:" to distinguish diagnostic
text from the suggestion prompt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_v2_prompt_advisor now returns a 5th value (advisor_suggested) carrying
the raw repaired prompt when validation rejected it. This is surfaced in
encoded_prompts as "Advisor suggested (rejected): ..." so the output is
visible even when the repair didn't pass validation.
No suggested prompt is returned for: skipped, no-change, or successfully
applied (in that case it's already the Positive prompt).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When the advisor runs, encoded_prompts now shows:
- Positive prompt (the final/repaired prompt)
- Advisor: <diagnostic> if a diagnostic was returned
- Pre-advisor prompt: <original> if the prompt was actually changed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Drop CONDITIONING 5th return slot (modified_negative) and the
negative_prompt optional input entirely.
- Remove all negative encoding, repair, and advisor call sites from
the processing path.
- Strip negative_* fields from saved prompt_history and last_run state.
- Update status strings and _v2_encoded_prompts_output (positive only).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove _v2_repair_negative_prompt and _v2_negative_prompt_advisor calls from
all execution branches; negative prompt is now passed through unchanged.
This fixes "Only prompt" mode running two AI generation passes (positive +
negative) instead of one, and removes pointless processing at CFG=1.0.
- Replace V2_PROMPT_ADVISOR_SYSTEM_PROMPT with the new structured format:
ORIGINAL_USER_INTENT / LAST_PROMPT / RATING / OPTIONAL_NOTE variables,
with explicit RULES for Missing-X vs Wrong-X repairs.
- Rewrite _v2_advisor_prompt to fill in the four named variables; adds
rating_label parameter (extracted from rating_profile at call site) so
RATING is now properly included in every repair request.
- In "Only prompt" mode the output format block is omitted so the model
returns a plain prompt string with no labels, matching the system prompt's
"Output ONLY the final prompt string" instruction.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Critical fix: do_sample was False, which forces greedy decoding and
silently ignores temperature, top_k, top_p, and min_p entirely. The
model was always picking the single highest-probability token regardless
of instructions or feedback. Changed to do_sample=True with temperature
0.5, top_k 50, top_p 0.92 — focused enough to follow the feedback
override reliably without the rigidity of greedy decoding.
Context clarity: renamed "Current prompt" to "Suggested prompt" in
both the analysis and repair advisor prompts, and moved "User intent"
before it. The advisor now sees intent first (what the user actually
wants), then the suggested prompt (what the LLM enhancer proposed),
making the framing correct for applying feedback on top of an enhancer
output. Same rename applied to the negative advisor prompt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New optional input (default True) that enables or disables the rule-based
prompt repair system. When off, V2 skips _v2_repair_prompt_for_missing_axes
entirely and passes no repair candidates to the advisor. Useful when phrase
memory is sparse or producing irrelevant suggestions that disrupt generation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full mode now runs two sequential LLM calls per generation:
Pass 1 (analysis): a focused prompt asks the model to identify exactly
what needs to change — what to add, what to remove, what to fix — and
output a single DIAGNOSTIC line. Both user feedback and feedback history
are present. Max tokens is halved since only one line is needed.
Pass 2 (repair): builds on pass 1 by including the analysis result as
"Analysis of what needs to change:" before the task instruction. The
model applies the analysis rather than having to simultaneously diagnose
and rewrite in a single response.
Only diagnostics mode runs only pass 1, stores the analysis in
advisor_feedback_history as an advisor-sourced entry (labelled
"Advisor note:" in future history context), and returns without
modifying the prompt — making it useful as a genuine preview step
before switching to Full mode.
Only prompt mode runs only pass 2 directly (no analysis overhead),
unchanged from before.
Both passes receive feedback_prompt and feedback_history.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Advisor context is now minimal and feedback-first:
- User feedback (current run, placed first when present)
- Current prompt
- User intent
- Previous encoded prompt (anchor for feedback — so 'he held her head'
has a referent)
- Suggestions from memory (repair candidates, max 5)
- Past feedback history (last 10 entries, most recent first)
Removed from context: rating label, axis codes, plain-English axis
translation, encoded-vs-original prompt duplication, advisor-poisoning
note, previous advisor diagnostic, perfect example, V2 recommendations,
source image text note (image is fed directly to vision-capable models
via the existing tokenizer image= path)
New persistent store: global_state["advisor_feedback_history"] — up to
10 entries, each {feedback, rating, iteration}. Only populated when
feedback_prompt is non-empty. Updated at the end of each run so the
current run's feedback is available for future runs, not the current.
History format: "Rating: user's exact feedback text" e.g.
"1. Missing details: I asked for smoke but it didn't appear."
"2. Wrong action: he was supposed to hold her hand, not her head."
Removed dead helpers: _v2_find_perfect_example_for_intent,
_v2_build_v2_recommendations, _v2_axes_to_plain_english,
_AXIS_DESCRIPTIONS — none used by advisor context any more.
Cleaned up _v2_prompt_advisor and _v2_negative_prompt_advisor
signatures: removed rating_label, phrases, perfect_example,
v2_recommendations, has_image params; added feedback_history.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>