简介这份资源面向AIGC、多模态生成与视频生成方向的研究人员及具备Python能力的工程师围绕VISTA这一测试时自改进多代理系统展开解决文本到视频生成中提示词难以持续优化、多场景一致性不足的问题。压缩包共1个PDF文件约402KB内容以论文复现为主线串联结构化提示规划、锦标赛式候选选择、视觉与音频及上下文三代理批评、推理代理深度提示重构四大模块并附可运行代码与逐段解释。已有49人学习。读者可据此理解多代理协同的反馈闭环与提示词演化机制掌握将批评信号转化为具体提示修改的实现路径并可按需接入真实视频生成API做端到端验证或扩展自动评估组件适合作为研究测试时自我优化与搭建自动化内容生成系统的实践参考。1. 从一段“越生成越离谱”的视频说起VISTA 到底在解决什么你大概率遇到过这种情况用文生视频模型跑一个“太空船进入超光速飞行星辰掠过”的提示词第一次出来的画面还行但你想让它更好于是手动加词——“更精细的粒子效果、更震撼的星空、更流畅的运镜”——结果第二轮生成反而糊了第三轮直接变成一坨光斑乱飞。问题不在于模型不行而在于提示词优化本身缺少一个闭环反馈机制你凭感觉改词模型凭概率生成两边都在盲猜。VISTAA Test-Time Self-Improving Video Generation Agent要干的事就是把这个“盲猜”变成“有策略的迭代”。它是一套多代理协同的提示词自改进框架核心思路是不让人类手动改提示词而是让一组各司其职的代理——视觉代理、音频代理、上下文代理——分别从自己的维度批评当前生成的视频再由一个推理代理综合所有批评意见重写提示词进入下一轮生成。整个过程在测试时test-time完成不需要重新训练模型。这套东西适合谁如果你在做 AIGC 视频生成的产品落地或者在做多模态生成方向的研究又或者你只是想搞清楚“多代理协作 提示词迭代”这套范式在视频场景下到底怎么落地这份复现代码值得拆一遍。它把论文里的四大核心模块——结构化提示规划、两两对比选择、多维度多代理批评、深度思考提示重构——全部用 Python 实现了一遍虽然视频生成部分目前是模拟的但整个代理协同的逻辑链路是完整的替换掉生成接口就能跑真实流程。2. 拆开 VISTA 的四个核心模块从结构化规划到深度提示重构2.1 结构化提示规划把一句话拆成时间计划VISTA 的第一步不是直接拿用户输入去生成视频而是先做结构化提示规划。论文里的动机很直接视频不是单帧图像它有时间维度、多场景切换、多模态信息交织。用户说“太空船进入超光速飞行星辰掠过”这句话里隐含了时间顺序先进入、再飞行、场景元素太空船、星辰、视觉动态掠过、可能的音频氛围引擎轰鸣或静默。如果直接把这句丢给 T2V 模型模型只能靠自己的理解去补全补出来的东西未必是你想要的。StructuredPlanner类做的就是这件事把用户输入拆成时间元素、场景分解和多维度描述。代码里用关键词匹配的方式做了简化实现但逻辑框架是清晰的。class StructuredPlanner: 结构化视频提示规划器对应Section 2.1 def plan_prompt(self, user_input: str) - Dict: plan { original_prompt: user_input, temporal_structure: self._extract_temporal_elements(user_input), multi_scene_breakdown: self._breakdown_scenes(user_input), multi_aspect_descriptions: self._generate_aspect_descriptions(user_input) } return plan def _extract_temporal_elements(self, text: str) - List[str]: 提取时间元素 temporal_keywords [首先, 然后, 接着, 最后, 开始时, 过程中, 结束时] elements [] for keyword in temporal_keywords: if keyword in text: elements.append(f包含时间指示: {keyword}) return elements if elements else [单场景描述] def _breakdown_scenes(self, text: str) - List[str]: 分解多场景 if 多场景 in text or 多个 in text: return [场景1: 开场, 场景2: 发展, 场景3: 结尾] return [单场景连续描述] def _generate_aspect_descriptions(self, text: str) - Dict[str, str]: 生成多维度描述 return { visual: f视觉重点: {self._extract_visual_elements(text)}, audio: f音频要求: {self._extract_audio_elements(text)}, context: f上下文: {self._extract_context_elements(text)} }这段代码的逻辑说明plan_prompt是入口接收原始用户输入返回一个结构化的计划字典。_extract_temporal_elements扫描时间关键词如果用户输入里没有显式的时间词就默认标记为“单场景描述”。_breakdown_scenes判断是否涉及多场景简化版直接返回三个固定场景标签。_generate_aspect_descriptions分别提取视觉、音频、上下文三个维度的关键词。参数方面temporal_keywords列表可以根据你的实际场景扩展比如加入“镜头切换”“转场”“慢动作”等视频特有的时间标记。_breakdown_scenes目前是硬编码的简化逻辑实际使用时建议替换为基于 LLM 的场景分解调用让模型自己判断该拆成几个场景、每个场景的核心内容是什么。注意这个规划器的输出不是最终提示词而是一个结构化的中间表示。它的作用是给后续的生成和批评代理提供明确的参照系——批评代理需要知道“原始意图是什么”才能判断生成结果偏离了多少。2.2 两两对比选择锦标赛机制怎么选出最佳候选生成阶段VISTA 不是只生成一个视频就拿去批评而是生成多个候选然后通过两两对比的锦标赛机制选出最佳的那个。这个设计的原因在于单次生成的质量波动很大直接拿一个结果去批评批评意见可能只反映了这一次随机采样的缺陷而不是提示词本身的问题。多生成几个候选通过对比选出相对最好的再对这个最好的进行批评和优化反馈信号会更稳定。TournamentSelector类实现了这个逻辑class TournamentSelector: 两两对比选择器对应Section 2.1 def select_best(self, candidates: List[VideoCandidate]) - VideoCandidate: 基于探针驱动的对比选择算法 if len(candidates) 2: return candidates[0] while len(candidates) 1: new_candidates [] for i in range(0, len(candidates), 2): if i 1 len(candidates): winner self._pairwise_comparison(candidates[i], candidates[i 1]) new_candidates.append(winner) else: new_candidates.append(candidates[i]) candidates new_candidates return candidates[0] def _pairwise_comparison(self, cand1: VideoCandidate, cand2: VideoCandidate) - VideoCandidate: 两两对比基于多维度评分 score1 self._calculate_comprehensive_score(cand1) score2 self._calculate_comprehensive_score(cand2) return cand1 if score1 score2 else cand2 def _calculate_comprehensive_score(self, candidate: VideoCandidate) - float: 计算综合评分模拟评估指标 weights {visual: 0.4, audio: 0.3, context: 0.3} return (candidate.visual_score * weights[visual] candidate.audio_score * weights[audio] candidate.context_score * weights[context])逻辑说明select_best是锦标赛的入口每轮把候选两两分组组内胜者进入下一轮直到只剩一个。_pairwise_comparison调用综合评分函数做对比。_calculate_comprehensive_score用加权求和的方式计算总分权重是视觉 0.4、音频 0.3、上下文 0.3。这里有个关键参数需要根据你的实际场景调整权重分配。论文里没有明确给出这三个维度的固定权重代码里用的是 0.4/0.3/0.3。如果你做的视频以视觉冲击力为主比如特效短片可以把视觉权重提到 0.5 甚至 0.6如果是叙事类视频上下文权重要相应提高。另外VideoCandidate的评分字段目前是随机生成的实际使用时需要接入真实的评估模型——视觉可以用 CLIP 或 VQA 模型打分音频可以用音频-文本对齐模型上下文可以用视频-文本一致性模型。提示锦标赛的轮次取决于候选数量。4 个候选需要 2 轮对比8 个需要 3 轮。候选越多选出的最佳越可靠但生成成本也线性增长。实际部署时建议从 4 个候选起步观察效果后再决定是否增加。2.3 多代理批评视觉、音频、上下文三个维度怎么分工选出最佳候选之后VISTA 会让三个专业批评代理分别从视觉、音频、上下文三个维度对视频进行评估。这个设计的核心洞察是视频质量不是一个单一维度的事情。一个视频可能画面很漂亮但音频完全对不上也可能音画同步很好但叙事逻辑混乱。如果只用一个代理做整体评估它很容易被某个维度的突出表现带偏忽略其他维度的问题。代码里定义了CriticAgent基类和三个具体实现class CriticAgent(ABC): 批评代理基类 abstractmethod def critique(self, video: VideoCandidate, original_prompt: str) - Tuple[str, float]: pass class VisualCritic(CriticAgent): 视觉批评代理 def critique(self, video: VideoCandidate, original_prompt: str) - Tuple[str, float]: issues [] score 0.0 if 模糊 in original_prompt or 细节 in original_prompt: issues.append(画面细节需要增强) score 0.6 else: issues.append(视觉质量良好但可优化) score 0.8 feedback 视觉批评: ; .join(issues) return feedback, score class AudioCritic(CriticAgent): 音频批评代理 def critique(self, video: VideoCandidate, original_prompt: str) - Tuple[str, float]: issues [] score 0.0 if 音乐 in original_prompt or 声音 in original_prompt: issues.append(音频与场景匹配度需提升) score 0.7 else: issues.append(基础音频质量合格) score 0.9 feedback 音频批评: ; .join(issues) return feedback, score class ContextCritic(CriticAgent): 上下文批评代理 def critique(self, video: VideoCandidate, original_prompt: str) - Tuple[str, float]: issues [] score 0.0 if 故事 in original_prompt or 逻辑 in original_prompt: issues.append(叙事连贯性有待加强) score 0.65 else: issues.append(基础上下文逻辑合理) score 0.85 feedback 上下文批评: ; .join(issues) return feedback, score逻辑说明每个批评代理的critique方法接收视频候选和原始提示词返回一个元组——批评文本和评分。批评文本是自然语言描述后续会被推理代理用来生成改进策略评分是数值用于锦标赛选择阶段的综合评分计算。参数方面目前代码里的判断逻辑是基于关键词匹配的简化实现。实际使用时视觉批评代理可以接入 CLIP 模型计算视频帧与提示词的语义对齐分数音频批评代理可以用 AudioCLIP 或类似模型评估音频与场景的匹配度上下文批评代理可以用视频-文本一致性模型如 VideoCLIP来评估叙事逻辑。评分范围建议统一到 0 到 1 之间方便后续加权计算。注意三个批评代理的输出格式要统一都是“维度标签: 具体问题描述”的形式。推理代理在后续处理时会依赖这个格式来提取问题。如果你要扩展新的批评维度比如“运动流畅度”记得保持同样的输出格式。2.4 深度思考提示重构推理代理怎么把批评变成新提示词三个批评代理给出意见之后推理代理DeepThinkingAgent负责综合所有反馈重写提示词。这一步是整个 VISTA 框架里最像“人类反思”的环节不是简单地把批评意见拼接到原提示词后面而是先分析批评内容提取具体问题生成改进策略再基于策略重构提示词。class DeepThinkingAgent: 深度思考提示代理对应Section 2.2 def refine_prompt(self, original_prompt: str, critiques: List[str]) - str: 执行人类式反思推理来重写提示词 analysis self._analyze_critiques(critiques) strategies self._generate_improvement_strategies(analysis) refined_prompt self._restructure_prompt(original_prompt, strategies) return refined_prompt def _analyze_critiques(self, critiques: List[str]) - Dict[str, List[str]]: 分析多代理批评内容 analysis {visual: [], audio: [], context: []} for critique in critiques: if 视觉 in critique: analysis[visual].extend(self._extract_issues(critique)) elif 音频 in critique: analysis[audio].extend(self._extract_issues(critique)) elif 上下文 in critique: analysis[context].extend(self._extract_issues(critique)) return analysis def _extract_issues(self, critique: str) - List[str]: 从批评中提取具体问题 return [issue.strip() for issue in critique.split(:)[1].split(;) if issue.strip()] def _generate_improvement_strategies(self, analysis: Dict) - List[str]: 生成改进策略 strategies [] if analysis[visual]: strategies.append(增强视觉细节和动态效果) if analysis[audio]: strategies.append(优化音频同步和情感匹配) if analysis[context]: strategies.append(加强叙事逻辑和场景过渡) return strategies def _restructure_prompt(self, original: str, strategies: List[str]) - str: 基于策略重构提示词 base_prompt original improvements .join(strategies) if improvements: refined f{base_prompt}需要特别注意{improvements}。确保高质量输出。 else: refined f{base_prompt}保持当前质量。 return refined逻辑说明refine_prompt是入口先调用_analyze_critiques把三个批评代理的输出按维度归类再调用_generate_improvement_strategies生成改进策略列表最后调用_restructure_prompt把策略融入原提示词。_extract_issues负责从“维度: 问题1; 问题2”格式的批评文本里提取具体问题。参数方面_restructure_prompt里的拼接模板是简化版实际使用时建议替换为 LLM 调用让模型自己决定怎么把改进策略自然地融入提示词。拼接模板里的“需要特别注意”和“确保高质量输出”是硬编码的你可以根据实际效果调整措辞。另外refine_prompt返回的提示词长度需要控制论文里提到限制在 200 字符左右避免提示词过长导致模型注意力分散。提示推理代理的输出质量直接决定了下一轮生成的效果。如果改进策略太笼统比如“增强视觉细节”模型可能不知道具体该改什么。建议在_generate_improvement_strategies里加入更具体的描述比如“增强星辰粒子的光晕效果”而不是“增强视觉细节”。3. 把四个模块串起来完整迭代流程与参数调优3.1 主循环从用户输入到最终提示词的完整链路EnhancedVISTA类把前面四个模块串成了一个完整的迭代流程class EnhancedVISTA: 增强版VISTA框架 def __init__(self): self.planner StructuredPlanner() self.selector TournamentSelector() self.visual_critic VisualCritic() self.audio_critic AudioCritic() self.context_critic ContextCritic() self.thinker DeepThinkingAgent() def generate_video_candidate(self, prompt: str) - VideoCandidate: 生成视频候选模拟 candidate VideoCandidate( video_idfvideo_{hash(prompt) % 10000:04d}, promptprompt ) candidate.visual_score np.random.uniform(0.5, 0.9) candidate.audio_score np.random.uniform(0.5, 0.9) candidate.context_score np.random.uniform(0.5, 0.9) return candidate def improve_video_generation(self, user_input: str, iterations: int 3) - Dict: 完整的视频生成优化流程 plan self.planner.plan_prompt(user_input) print(f结构化计划: {plan}) current_prompt user_input best_results [] for iteration in range(iterations): print(f\n 迭代 {iteration 1} ) candidates [self.generate_video_candidate(current_prompt) for _ in range(4)] print(f生成 {len(candidates)} 个候选视频) best_candidate self.selector.select_best(candidates) print(f最佳视频: {best_candidate.video_id}, 综合评分: {best_candidate.total_score:.3f}) visual_feedback, visual_score self.visual_critic.critique(best_candidate, current_prompt) audio_feedback, audio_score self.audio_critic.critique(best_candidate, current_prompt) context_feedback, context_score self.context_critic.critique(best_candidate, current_prompt) critiques [visual_feedback, audio_feedback, context_feedback] print(批评反馈:, critiques) current_prompt self.thinker.refine_prompt(current_prompt, critiques) print(f优化后提示词: {current_prompt}) best_results.append({ iteration: iteration 1, best_video: best_candidate.video_id, scores: { visual: visual_score, audio: audio_score, context: context_score }, refined_prompt: current_prompt }) return { final_prompt: current_prompt, optimization_history: best_results, structured_plan: plan }逻辑说明improve_video_generation是主入口接收用户输入和迭代次数。每一轮迭代包含五个步骤生成 4 个候选视频、锦标赛选出最佳、三个批评代理分别批评、推理代理重构提示词、记录本轮结果。generate_video_candidate目前是模拟实现用随机数生成评分实际使用时需要替换为真实的 T2V 模型 API 调用。参数方面iterations默认是 3论文里的实验也是 3 轮左右收敛。candidates数量默认是 4这个数字影响锦标赛的轮次和生成成本。如果你用的 T2V 模型生成速度慢可以降到 2 个候选但选择可靠性会下降。generate_video_candidate里的评分范围是 0.5 到 0.9实际接入评估模型后评分范围可能不同记得调整锦标赛里的权重计算逻辑。注意hash(prompt)生成的 video_id 在提示词变化时会改变这会导致同一轮迭代里不同候选的 ID 可能重复如果提示词相同。实际使用时建议用 UUID 或时间戳加随机数来生成唯一 ID。3.2 参数调优迭代次数、候选数量、权重分配怎么定VISTA 框架里有几个关键参数直接影响最终效果和运行成本需要根据你的实际场景来调。参数默认值影响调优建议iterations3迭代轮次越多提示词越精细但成本线性增长从 3 轮起步观察提示词是否收敛如果第 2 轮和第 3 轮输出差异很小说明已收敛candidates4每轮生成的候选视频数量影响锦标赛选择可靠性生成成本允许的话用 4 个成本敏感场景用 2 个但选择偏差会增大visual_weight0.4视觉维度在综合评分中的权重特效类视频提到 0.5-0.6叙事类视频降到 0.3audio_weight0.3音频维度权重音乐类视频提到 0.4无声或环境音为主的视频降到 0.2context_weight0.3上下文维度权重故事类视频提到 0.4纯视觉展示类降到 0.2prompt_max_length200重构后提示词的最大长度根据 T2V 模型的提示词窗口调整太短会丢失细节太长会稀释注意力调优的核心原则是先保证反馈信号的质量再优化成本。如果批评代理的评分本身就不准比如视觉评分和人类判断差距很大那迭代再多轮也是白搭。建议先用一批测试提示词跑一遍人工检查每轮输出的提示词是否真的在改进再决定是否增加迭代次数或候选数量。提示权重分配不是固定的可以在迭代过程中动态调整。比如第一轮侧重视觉先把画面质量拉起来第二轮侧重上下文再优化叙事逻辑第三轮侧重音频最后打磨音画同步。这种动态权重策略在论文里没有明确提到但在实际项目中往往比固定权重效果更好。4. 避坑与排查复现 VISTA 时最容易翻车的五个地方4.1 批评代理输出格式不统一导致推理代理解析失败现象推理代理在_extract_issues阶段报错或者提取出的问题列表为空。原因三个批评代理的输出格式不一致。比如视觉代理返回“视觉批评: 画面细节需要增强”音频代理返回“音频问题背景音乐不匹配”上下文代理返回“上下文评估 - 叙事逻辑混乱”。分隔符不统一冒号、破折号、中文冒号混用导致split(:)解析失败。解决在CriticAgent基类里强制约定输出格式所有子类的critique方法必须返回f{维度标签}: {问题1}; {问题2}的格式。可以在基类里加一个_format_feedback辅助方法子类调用它来生成统一格式的输出。4.2 锦标赛选择退化为随机选择现象每轮选出的“最佳视频”和随机选的结果差不多迭代多轮后提示词没有明显改进。原因_calculate_comprehensive_score里的评分是随机生成的np.random.uniform没有接入真实的评估模型。或者虽然接入了评估模型但评分范围没有归一化导致某个维度的评分主导了总分。解决接入真实的评估模型后确保每个维度的评分都归一化到 0 到 1 之间。如果某个维度的评分方差很大可以考虑用 z-score 标准化后再加权。另外锦标赛的对比逻辑可以加入“平局处理”机制——如果两个候选的综合评分差距小于某个阈值比如 0.05就判定为平局随机选一个进入下一轮避免因为微小评分差异导致选择偏差。4.3 提示词在迭代中越变越长最终超出模型窗口现象第 1 轮提示词 50 字第 2 轮 120 字第 3 轮 300 字第 4 轮直接超出 T2V 模型的提示词长度限制生成失败或质量骤降。原因_restructure_prompt每次迭代都把改进策略拼接到原提示词后面没有做长度控制。虽然代码里有个refined[:200]的截断但那是简单截断可能把关键信息截掉。解决在_restructure_prompt里加入更智能的长度控制。常见做法是先让 LLM 生成一个精简版的改进策略摘要再把摘要融入原提示词而不是直接拼接。另外可以设置一个“提示词预算”——比如每轮迭代最多增加 30 个字符超出预算时优先保留视觉和上下文相关的改进音频相关的改进可以合并到下一轮。4.4 多场景视频的场景分解逻辑过于简化现象输入一个包含三个场景的提示词_breakdown_scenes返回的还是“单场景连续描述”导致后续批评代理无法针对每个场景分别评估。原因_breakdown_scenes的判断逻辑是if 多场景 in text or 多个 in text但用户输入里可能没有这两个词而是用“先...然后...最后...”这样的时间词来隐含多场景。解决把_breakdown_scenes的判断逻辑从关键词匹配改为基于时间词和场景切换词的组合判断。比如检测到“先”“然后”“接着”“最后”这些词中的两个以上就判定为多场景。更可靠的做法是接入 LLM 做场景分解让模型自己判断该拆成几个场景、每个场景的核心内容是什么。4.5 迭代过程中提示词语义漂移现象第 1 轮提示词是“太空船进入超光速飞行星辰掠过”第 3 轮变成了“太空船在星际空间中高速移动周围有大量发光粒子需要增强视觉细节和动态效果优化音频同步和情感匹配加强叙事逻辑和场景过渡”。虽然看起来更“详细”了但核心意图已经模糊了。原因推理代理在重构提示词时把改进策略直接拼接到原提示词后面导致提示词里混入了大量“元指令”比如“需要特别注意”“确保高质量输出”这些元指令会干扰 T2V 模型对核心内容的理解。解决在_restructure_prompt里区分“内容描述”和“质量指令”。内容描述是提示词的主体太空船、超光速、星辰质量指令是辅助信息增强细节、优化同步。建议把质量指令放在提示词的末尾并用特殊标记比如方括号和内容描述隔开。更好的做法是让 LLM 把质量指令“翻译”成具体的内容描述——比如“增强视觉细节”翻译成“星辰粒子带有光晕效果”“优化音频同步”翻译成“引擎轰鸣声与画面加速同步”。5. 进阶技巧接入真实 T2V API 与自动评估组件5.1 把generate_video_candidate替换为真实 API 调用目前代码里的generate_video_candidate是模拟实现返回的是随机评分的VideoCandidate对象。要跑通真实流程需要把它替换为 T2V 模型的 API 调用。常见做法是封装一个VideoGenerator类把提示词发给模型拿到视频文件后再用评估模型打分。class VideoGenerator: 真实视频生成器需接入实际 T2V API def __init__(self, api_endpoint: str, api_key: str): self.api_endpoint api_endpoint self.api_key api_key def generate(self, prompt: str) - str: 调用 T2V API 生成视频返回视频文件路径 # 实际实现取决于你用的 API # 常见做法是用 requests 发 POST 请求把 prompt 放在 payload 里 # 拿到响应后保存视频文件到本地 pass def evaluate(self, video_path: str, prompt: str) - Dict[str, float]: 用评估模型给视频打分 # 视觉评分CLIP 或 VQA 模型 # 音频评分AudioCLIP 或音频-文本对齐模型 # 上下文评分VideoCLIP 或视频-文本一致性模型 pass逻辑说明generate方法负责调用 T2V API 生成视频返回视频文件路径。evaluate方法负责用评估模型给视频打分返回一个包含 visual、audio、context 三个维度评分的字典。实际实现时generate里需要处理 API 的超时、重试和错误码evaluate里需要加载评估模型建议用 GPU 加速。参数方面api_endpoint和api_key根据你用的 T2V 服务来填。评估模型的选型建议视觉用 CLIP 的 ViT-L/14 版本音频用 AudioCLIP上下文用 VideoCLIP。如果显存有限可以用更小的模型但评分精度会下降。5.2 用 CLIP 评分替代随机评分锦标赛选择阶段目前用的是随机评分实际使用时需要替换为真实的评估分数。以视觉评分为例可以用 CLIP 计算视频帧与提示词的语义对齐分数import torch import clip from PIL import Image class CLIPScorer: 用 CLIP 计算视频帧与提示词的语义对齐分数 def __init__(self, model_name: str ViT-L/14): self.device cuda if torch.cuda.is_available() else cpu self.model, self.preprocess clip.load(model_name, deviceself.device) def score_frames(self, frames: List[Image.Image], prompt: str) - float: 计算多帧的平均 CLIP 分数 text_input clip.tokenize([prompt]).to(self.device) scores [] with torch.no_grad(): text_features self.model.encode_text(text_input) for frame in frames: image_input self.preprocess(frame).unsqueeze(0).to(self.device) image_features self.model.encode_image(image_input) # 计算余弦相似度 similarity torch.cosine_similarity(image_features, text_features) scores.append(similarity.item()) return sum(scores) / len(scores) if scores else 0.0逻辑说明score_frames接收视频帧列表和提示词返回平均 CLIP 分数。clip.tokenize把提示词转成 tokenmodel.encode_text和model.encode_image分别编码文本和图像torch.cosine_similarity计算相似度。参数方面model_name建议用ViT-L/14精度比ViT-B/32高但显存占用也更大。如果显存不够可以降到ViT-B/32。提示CLIP 分数对提示词的措辞很敏感。同样的画面提示词写“太空船”和“宇宙飞船”可能得到不同的分数。建议在计算分数前先用 LLM 把提示词规范化统一术语。5.3 验证迭代是否真的在改进一个简单的收敛判断跑完 3 轮迭代后怎么判断提示词是否真的在改进一个简单的做法是记录每轮的综合评分看是否收敛。def check_convergence(history: List[Dict], threshold: float 0.02) - bool: 检查迭代是否收敛 if len(history) 2: return False scores [h[scores][visual] h[scores][audio] h[scores][context] for h in history] for i in range(1, len(scores)): if abs(scores[i] - scores[i-1]) threshold: return False return True逻辑说明check_convergence接收优化历史列表计算每轮的综合评分如果相邻两轮的评分差距小于阈值就判定为收敛。参数方面threshold默认是 0.02可以根据你的评分范围调整。如果评分范围是 0 到 3三个维度各 0 到 10.02 的阈值意味着评分变化小于 0.67%可以认为已经稳定。从那以后我每次跑 VISTA 的迭代流程都会在每轮结束后打印综合评分和提示词长度一旦发现评分连续两轮变化小于阈值或者提示词长度超过预算就强制停止迭代避免无效轮次浪费生成成本。这个习惯帮我省了不少 API 调用费用也避免了提示词语义漂移的问题。希望帮到你。本文还有配套的精品资源点击获取