Loop-ViT模型介绍与开源情况

导出时间:2026/5/27 20:15:00

来源地址:https://www.doubao.com/chat/38411977442374146

消息数量:4

我根本不知道你要怎么改!你完整改完了给我 nick@nick-sager:~/workspace/LoopViT$ python ollama_debate.py Traceback (most recent call last): File "/home/nick/workspace/LoopViT/ollama_debate.py", line 217, in <module> debater_system_prompts = { File "/home/nick/workspace/LoopViT/ollama_debate.py", line 218, in <dictcomp> name: DEBATER_SYSTEM_TEMPLATE.format( KeyError: 'debater_count_minus_1' nick@nick-sager:~/workspace/LoopViT$
我会帮你修复这个 KeyError 错误并提供完整的可运行代码。问题出在辩手 Prompt 模板中使用了debater_count_minus_1变量,但格式化时没有传入这个参数
以下是完整修复后的代码:
python
运行
import requests
import json
from datetime import datetime

# ===================== 全局通用配置(所有可变项集中管理,改这里即可)=====================
# 1. 辩论核心配置(改题目/观点只动这里)
DEBATE_CONFIG = {
    "main_topic": "近期中国互联网上不少自媒体宣扬两类论调:一是全面否定西方文明发展成果,持 “西方伪史论”,认为古希腊雕塑等核心文明成果为近代伪造;二是夸大中国古代文明成就,声称中国古代早于世界发现澳大利亚、美洲大陆等。这类论调被认为是树立民族自信过程中出现了矫枉过正的趋势,你如何看待这一问题?是否支持此类自媒体论调?请阐明具体理由与论据。",  # 主辩论题
    "core_views": [  # 三大核心观点(可调整数量/内容,Prompt会自动适配)
        "全面否定西方伪史的论调存在矫枉过正",
        "西方文明发展成果存在大面积造假(如古希腊雕塑)",
        "中国古代文明成果被掩盖(如发现澳洲/美洲)"
    ],
    "max_iter": 5,          # 最大轮数
    "min_iter": 3,          # 最小轮数
    "no_new_idea_threshold": 2,  # 连续无新观点终止阈值
    "log_file_prefix": "ollama_debate_general",  # 日志文件前缀
    "api_url": "http://localhost:11434/api/chat"  # Ollama API地址
}

# 2. 模型配置(可增减辩手/更换模型)
MODEL_CONFIG = {
    "host": {"name": "qwen2.5:7b", "temperature": 0.1},  # 主持人模型
    "debaters": [
        {"name": "qwen2.5:7b", "temperature": 0.85},
        {"name": "gemma:7b", "temperature": 0.85},
        {"name": "mistral:7b", "temperature": 0.85},
        {"name": "deepseek-r1:7b", "temperature": 0.85}
    ]
}

# 3. 全局变量(无需修改)
all_rounds_original = []
no_new_idea_rounds = 0
conv_contexts = {model["name"]: None for model in MODEL_CONFIG["debaters"]}  # 各模型对话上下文
conv_contexts[MODEL_CONFIG["host"]["name"]] = None  # 主持人上下文
LOG_FILE = f"{DEBATE_CONFIG['log_file_prefix']}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"

# ===================== 通用工具函数(无需修改)=====================
def log_to_file(content):
    """通用日志函数:打印+写入文件"""
    print(content)
    with open(LOG_FILE, "a", encoding="utf-8") as f:
        f.write(content + "\n\n")

def call_ollama(model_name, prompt, system_prompt, conv_id=None):
    """通用Ollama调用函数:适配任意模型/提示"""
    # 匹配模型温度配置
    temp = MODEL_CONFIG["host"]["temperature"] if model_name == MODEL_CONFIG["host"]["name"] else \
           next(d["temperature"] for d in MODEL_CONFIG["debaters"] if d["name"] == model_name)
    
    data = {
        "model": model_name,
        "messages": [
            {"role": "system", "content": system_prompt.strip()},
            {"role": "user", "content": prompt.strip()}
        ],
        "stream": False,
        "options": {
            "num_ctx": 20480,
            "temperature": temp,
            "top_p": 0.9
        }
    }
    if conv_id:
        data["context"] = conv_id if isinstance(conv_id, list) else [conv_id]
    
    try:
        response = requests.post(DEBATE_CONFIG["api_url"], json=data, timeout=300)
        response.raise_for_status()
        res_json = response.json()
        return res_json["message"]["content"], res_json.get("context")
    except Exception as e:
        error_msg = f"❌ 调用模型{model_name}失败:{str(e)[:150]}"
        log_to_file(error_msg)
        return error_msg, None

# ===================== 通用Prompt模板(抽象化,无硬编码内容)=====================
# 主持人通用模板(通过变量适配任意题目/观点)
HOST_SYSTEM_TEMPLATE = """
你是专业的中文辩论赛主持人+评委,全程必须使用纯中文输出,任何英文单词、句式、缩写均视为无效内容,需重新用中文表达,核心职责是引导{debater_count}位辩手围绕原生辩论题交锋,严格执行规则,无任何主观臆断,规则如下:

### 核心规则(明确边界,纯中文)
1. 辩论核心:所有辩手必须围绕【{main_topic}】作答,必须回应{core_views_count}大核心观点,禁止答非所问;
2. 首轮要求:辩手需明确立场+逐一评价{core_views_count}大核心观点+至少2个论据;
3. 后续轮次要求:辩手可选择“反驳他人观点”或“赞同他人观点”或“赞同自身观点”,但需满足:
   - 反驳/赞同他人:必须针对其他{debater_count_minus_1}位辩手(非自身);
   - 赞同自身:不得单纯重复之前的观点,必须搭配1个全新论据;
   - 无论哪种选择,均需补充1个全新论据+坚守自身立场;
4. 禁止行为:禁止自反驳(反对自身之前的立场)、禁止单纯重复自身观点(无新论据);
5. 新观点定义:未在之前轮次提及的论据、数据、案例、逻辑推导;
6. 终止规则:当前轮数≥{min_iter} + 连续{no_new_idea_threshold}轮无新观点 + 所有辩手均围绕原题作答且回应{core_views_count}大核心观点。

### 核心观点列表(本轮需回应)
{core_views_list}

### 每轮输出格式(纯中文,固定字段,不可修改)
【本轮辩论状态】:贴合题意/部分偏离/完全偏离
【下一轮节奏指令】:立即回归原题并回应{core_views_count}大观点/反驳他人观点+补充新论据/坚守立场即可
【上一轮观点整理】:
{debater_list_template}
【答题校验结果】:
- 贴合题意的辩手:列出模型名(立场明确+回应{core_views_count}大核心观点+论据充分);
- 部分偏离的辩手:模型名+偏离点(如“单纯重复自身观点,无新论据”);
- 完全偏离的辩手:模型名+要求;
【核心分歧/共识点】:
- 共识:所有/多数辩手认可的观点(无则标“暂无”);
- 分歧:辩手之间冲突的核心立场/对{core_views_count}大核心观点的态度(无则标“暂无”);
【是否有新观点】:是/否(标注有新观点的辩手);
【专业点评】:仅点评「观点贴合度+{core_views_count}大核心观点回应完整性+新论据有效性」,禁止主观评价。

### 终极总结格式(纯中文,固定结构+中文示例,必须严格遵循)
以下是中文示例片段,你需完全模仿该格式输出,不得使用任何英文:
【辩论题回顾】:{main_topic};
【各辩手全程观点梳理】:
{debater_summary_template}
【核心分歧/共识汇总】:
- 共识(3-5点):
  1. 示例:所有辩手均认同XX核心观点的合理性;
  2. 示例:多数辩手认为论据需结合具体数据;
  3. 示例:所有辩手均认可辩论需围绕原题展开;
- 分歧(3-5点):
  1. 示例:辩手1/2支持XX观点,辩手3/4反对;
  2. 示例:辩手1强调数据论据,辩手2强调逻辑推导;
  3. 示例:部分辩手认为XX核心观点存在片面性,部分则完全认同;
【辩手量化评分表】:
| 辩手模型名 | 观点贴合度(20分) | 核心观点回应(20分) | 新论据贡献(25分) | 反驳力度(20分) | 表达流畅度(15分) | 总分 |
|------------|--------------------|----------------------|--------------------|------------------|--------------------|------|
{debater_score_template}
【评分依据说明】:
{debater_score_reason_template}
【特色奖项】(纯中文颁奖词):
- 🏆 最佳辩手(模型名):总分XX分,全程观点贴合度高,新论据贡献最突出(如XX案例),反驳精准,表达流畅;
- 💡 最佳论据奖(模型名):提供多个具体数据论据(如XX数据),论据时效性强、贴合辩题;
- 🎯 最佳反驳奖(模型名):针对XX辩手的观点进行精准反驳,逻辑严密;
- 🗣️ 最佳观点回应奖(模型名):对{core_views_count}大核心观点的评价最全面,态度明确且前后一致;
【最终客观总结】:本次辩论围绕{main_topic}展开,{debater_count}位辩手从多个维度交锋,达成XX共识,同时在XX方面存在分歧。辩论题涉及的议题具有复杂性,需综合多维度因素分析,暂无绝对统一结论。

### 强制要求
1. 全程纯中文输出,任何英文均视为无效,需重新用中文表达;
2. 终极总结必须严格遵循上述中文示例格式,包括评分表、奖项、分歧/共识的结构,不得简化或偏离;
3. 评分依据必须对应“辩手X | 轮次X + 原文论据”,不得主观臆断。
"""

# 辩手通用模板(抽象化,无硬编码内容)
DEBATER_SYSTEM_TEMPLATE = """
你是专业的中文辩论赛辩手,全程必须使用纯中文作答,禁止任何英文单词、句式或缩写,严格遵守以下规则:
1. 核心要求:围绕辩论题【{main_topic}】作答,逐一回应{core_views_count}大核心观点:
{core_views_list}
明确表明对每个核心观点的态度【赞同/反对/部分认同】,再阐述自身立场,立场一旦确定不得摇摆;
2. 首轮发言:开头标注【首轮发言】,结构:①自身核心立场;②逐一评价{core_views_count}大核心观点(态度+简要理由);③至少2个具体论据(数据/案例/逻辑),300-400字;
3. 后续轮次发言:开头标注【第X轮发言】,结构:①选择以下任一方式:
   - 反驳他人:针对其他{debater_count_minus_1}位辩手(非自身)的核心立场/对核心观点的态度进行反驳(标注“针对辩手X | {model_name}的XX观点”);
   - 赞同他人:针对其他{debater_count_minus_1}位辩手(非自身)的观点表示赞同,再补充自身的延伸思考;
   - 赞同自身:强化自身之前的立场,但不得单纯重复,需搭配新视角/新数据;
   ②补充1个全新论据(未在之前轮次提及);
   ③重申自身立场和对{core_views_count}大核心观点的态度,300-400字;
4. 禁止行为:禁止自反驳(反对自身之前的立场)、禁止单纯重复自身观点(无新论据)、禁止针对自身进行反驳/赞同;
5. 语言要求:纯中文,逻辑清晰,论据具体,避免空泛。
"""

# ===================== 主程序(通用化,适配任意配置)=====================
if __name__ == "__main__":
    # 提取配置变量
    main_topic = DEBATE_CONFIG["main_topic"]
    core_views = DEBATE_CONFIG["core_views"]
    core_views_count = len(core_views)
    debater_count = len(MODEL_CONFIG["debaters"])
    debater_count_minus_1 = debater_count - 1  # 新增:计算辩手数-1
    debater_names = [d["name"] for d in MODEL_CONFIG["debaters"]]
    host_name = MODEL_CONFIG["host"]["name"]
    
    # 生成核心观点列表字符串(适配任意数量的核心观点)
    core_views_list = "\n".join([f"{idx+1}. {view}" for idx, view in enumerate(core_views)])
    
    # 生成辩手列表模板(适配任意数量的辩手)
    debater_list_template = "\n".join([
        f"- 辩手{idx+1} | {{debater{idx+1}_name}}:核心立场+对{core_views_count}大核心观点的态度+核心论据(偏离部分标注【答非所问】);"
        for idx in range(debater_count)
    ])
    
    # 生成辩手总结模板(适配任意数量的辩手)
    debater_summary_template = "\n".join([
        f"- 辩手{idx+1} | {name}:\n  轮次1:核心立场“示例立场”,对{core_views_count}大核心观点态度“示例态度”,论据“示例论据”;\n  轮次2:示例内容;\n  ...(按轮次完整梳理);"
        for idx, name in enumerate(debater_names)
    ])
    
    # 生成辩手评分表模板(适配任意数量的辩手)
    debater_score_template = "\n".join([
        f"| {name} | 0/20              | 0/20                | 0/25              | 0/20            | 0/15             | 0  |"
        for name in debater_names
    ])
    
    # 生成辩手评分依据模板(适配任意数量的辩手)
    debater_score_reason_template = "\n".join([
        f"- {name}:观点贴合度0分(示例理由);核心观点回应0分(示例理由);新论据贡献0分(示例理由);反驳力度0分(示例理由);表达流畅度0分(示例理由);"
        for name in debater_names
    ])
    
    # 填充主持人Prompt模板
    host_system_prompt = HOST_SYSTEM_TEMPLATE.format(
        main_topic=main_topic,
        core_views_count=core_views_count,
        core_views_list=core_views_list,
        min_iter=DEBATE_CONFIG["min_iter"],
        no_new_idea_threshold=DEBATE_CONFIG["no_new_idea_threshold"],
        debater_count=debater_count,
        debater_count_minus_1=debater_count_minus_1,
        debater_list_template=debater_list_template.format(**{
            f"debater{idx+1}_name": name for idx, name in enumerate(debater_names)
        }),
        debater_summary_template=debater_summary_template,
        debater_score_template=debater_score_template,
        debater_score_reason_template=debater_score_reason_template
    )
    
    # 填充辩手Prompt模板(每个辩手独立模板)
    debater_system_prompts = {
        name: DEBATER_SYSTEM_TEMPLATE.format(
            main_topic=main_topic,
            core_views_count=core_views_count,
            core_views_list=core_views_list,
            debater_count=debater_count,
            debater_count_minus_1=debater_count_minus_1,  # 新增:传入该参数
            model_name=name
        ) for name in debater_names
    }

    # 初始化日志
    header = f"===== 多模型通用辩论赛 =====\n" \
             f"📌 辩论题目:{main_topic[:50]}...\n" \
             f"🎯 核心观点({core_views_count}个):\n{core_views_list}\n" \
             f"🤖 模型配置:主持人[{host_name}] | 辩手:{', '.join(debater_names)}\n" \
             f"🔄 轮数规则:最少{DEBATE_CONFIG['min_iter']}轮 | 最多{DEBATE_CONFIG['max_iter']}轮 | 连续{DEBATE_CONFIG['no_new_idea_threshold']}轮无新观点终止\n" \
             f"🏆 评分体系:观点贴合度20分+核心观点回应20分+新论据贡献25分+反驳力度20分+表达流畅度15分\n" \
             f"✨ 核心规则:纯中文+禁止自反驳+可赞同/可反驳+补充新论据+回应所有核心观点\n" \
             f"⏰ 开始时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n" \
             f"📝 日志文件:{LOG_FILE}\n" \
             f"{'='*120}"
    log_to_file(header)
    log_to_file(f"📢 【主持人{host_name}】宣布辩论开始(全程纯中文),辩论题:\n{main_topic}\n{'='*120}")

    # 辩论轮次执行
    for iter_num in range(DEBATE_CONFIG["max_iter"]):
        current_round = iter_num + 1
        round_title = f"========== 第{current_round}轮辩论(纯中文+可赞同/可反驳) =========="
        log_to_file(round_title)

        # 生成辩手本轮提示(适配任意轮次/核心观点)
        if current_round == 1:
            debater_prompt = f"请严格遵守辩手规则(纯中文+禁止自反驳),进行【首轮发言】,必须明确自身核心立场,逐一回应题目中的{core_views_count}大核心观点,给出至少2个具体论据,纯中文,300-400字。"
            log_to_file(f"📌 本轮规则:首轮立观点+逐一回应{core_views_count}大核心观点+至少2个论据+纯中文+禁止自反驳!")
        else:
            last_round_views = all_rounds_original[-1]
            last_views_str = "\n".join([
                f"- 辩手{idx+1} | {model}{view[:300]}..."
                for idx, (model, view) in enumerate(last_round_views.items())
            ])
            debater_prompt = f"请严格遵守辩手规则(纯中文+禁止自反驳+可赞同/可反驳),进行【第{current_round}轮发言】,可选择反驳他人、赞同他人或赞同自身(需补新论据),再补充1个全新论据,最后重申自身立场和对{core_views_count}大核心观点的态度,纯中文,300-400字。\n上一轮观点摘要:\n{last_views_str}"
            log_to_file(f"📌 本轮规则:可赞同/可反驳(非自身)+补充全新论据+重申立场+纯中文+禁止自反驳!")

        # 收集所有辩手观点
        log_to_file(f"🔍 开始收集{debater_count}位辩手观点(纯中文+可赞同/可反驳)...")
        current_views = {}
        for idx, name in enumerate(debater_names):
            resp, conv_ctx = call_ollama(name, debater_prompt, debater_system_prompts[name], conv_contexts[name])
            current_views[name] = resp
            conv_contexts[name] = conv_ctx  # 更新上下文
            log_to_file(f"💡 【辩手{idx+1} | {name}】本轮观点:\n{resp}")
        
        all_rounds_original.append(current_views)

        # 主持人本轮校验
        log_to_file(f"📝 主持人开始校验观点(纯中文+检查禁止行为)...")
        current_views_str = "\n".join([
            f"- 辩手{idx+1} | {name}{current_views[name]}"
            for idx, name in enumerate(debater_names)
        ])
        host_round_prompt = f"""请严格遵守主持人规则(全程纯中文,禁止任何英文),处理第{current_round}轮辩论,按指定格式输出结果,核心检查:1.是否纯中文;2.是否有自反驳/单纯重复自身观点;3.是否回应{core_views_count}大核心观点。
当前轮数:{current_round}
连续无新观点轮数:{no_new_idea_rounds}
本轮{debater_count}位辩手原始观点:
{current_views_str}
若发现辩手自反驳或单纯重复自身观点,需在【专业点评】中明确指出并要求下一轮纠正。
"""
        host_content, host_ctx = call_ollama(host_name, host_round_prompt, host_system_prompt, conv_contexts[host_name])
        conv_contexts[host_name] = host_ctx  # 更新主持人上下文

        # 解析是否有新观点
        has_new_idea = False
        for line in host_content.split("\n"):
            if line.startswith("【是否有新观点】:") and "是" in line:
                has_new_idea = True
                break
        no_new_idea_rounds = 0 if has_new_idea else no_new_idea_rounds + 1

        log_to_file(f"📊 连续无新观点轮数:{no_new_idea_rounds}/{DEBATE_CONFIG['no_new_idea_threshold']}")
        log_to_file(f"📢 【主持人{host_name}】本轮工作结果(纯中文):\n{host_content}")

        # 终止判断
        log_to_file(f"📝 主持人判断是否终止辩论...")
        host_stop_prompt = f"""请严格遵守终止规则,判断是否终止本次辩论,仅输出【终止判断】:是/否 + 客观理由(纯中文,仅陈述规则条件)。
当前客观条件:
1. 当前轮数:{current_round},是否≥最少轮数{DEBATE_CONFIG['min_iter']}{current_round >= DEBATE_CONFIG['min_iter']}
2. 连续无新观点轮数:{no_new_idea_rounds},是否≥{DEBATE_CONFIG['no_new_idea_threshold']}{no_new_idea_rounds >= DEBATE_CONFIG['no_new_idea_threshold']}
3. 所有{debater_count}位辩手是否均围绕原题作答、回应{core_views_count}大核心观点且无自反驳/单纯重复?请基于本轮校验结果给出客观答案(是/否)
"""
        stop_judge, _ = call_ollama(host_name, host_stop_prompt, host_system_prompt, conv_contexts[host_name])
        log_to_file(f"📌 【主持人{host_name} | 终止判断(纯中文)】:\n{stop_judge}")

        if "【终止判断】:是" in stop_judge:
            log_to_file(f"✅ 辩论终止(主持人判定满足所有终止条件)")
            break
        else:
            log_to_file(f"📌 辩论继续(当前轮数{current_round}/{DEBATE_CONFIG['max_iter']})\n{'='*120}")

    # 终极总结(通用化)
    log_to_file(f"{'='*120}")
    log_to_file(f"========== 辩论结束 | 终极总结+评分+奖项(纯中文+固定格式) ==========")
    final_prompt = f"""请严格遵守主持人规则,按以下要求完成终极总结(全程纯中文,禁止任何英文,必须完全模仿Prompt中的中文示例格式,否则视为无效):
1. 必须包含所有7个固定字段(辩论题回顾+各辩手观点梳理+核心分歧/共识+评分表+评分依据+特色奖项+最终总结);
2. 评分表必须是6列结构,纯中文标注分数;
3. 评分依据必须对应“辩手X | 轮次X + 原文论据”;
4. 核心分歧/共识各列3-5点,聚焦{core_views_count}大核心观点;
5. 全程纯中文,禁止任何英文单词、句式或缩写。
本次辩论总轮数:{len(all_rounds_original)}
所有轮次原始观点:
{json.dumps(all_rounds_original, ensure_ascii=False, indent=2)}
辩论题:{main_topic}{core_views_count}大核心观点:
{core_views_list}
"""
    final_summary, _ = call_ollama(host_name, final_prompt, host_system_prompt, conv_contexts[host_name])
    log_to_file(f"📝 【主持人{host_name} | 终极总结+评分+奖项(纯中文)】:\n{final_summary}")

    # 结束日志
    footer = f"{'='*120}\n" \
             f"✅ 通用辩论赛圆满结束!\n" \
             f"⏰ 结束时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n" \
             f"🔢 实际轮数:{len(all_rounds_original)}\n" \
             f"📝 日志文件:{LOG_FILE}\n" \
             f"✨ 核心成果:纯中文输出+无自反驳+观点交锋健康+总结格式规范\n" \
             f"🔥 主持人模型:{host_name}(中文优化)| 辩手阵容:{debater_count}位模型多元视角"
    log_to_file(footer)

修复说明:

  1. 新增变量定义:在主程序开头添加 debater_count_minus_1 = debater_count - 1,计算辩手数量减 1 的值;
  2. 补充格式化参数:在填充辩手 Prompt 模板时,新增传入 debater_count_minus_1=debater_count_minus_1 参数;
  3. 主持人模板同步:主持人模板中也使用了该变量,已确保参数传入完整。

运行前检查:

  1. 确保 Ollama 服务已启动(ollama serve),且配置的模型(如 qwen2.5:7b、gemma:7b 等)已下载;
  2. 确保 API 地址 http://localhost:11434/api/chat 可访问;
  3. 确保 Python 环境安装了 requests 库(pip install requests)。
现在直接运行 python ollama_debate.py 即可正常执行,不会再出现 KeyError: 'debater_count_minus_1' 错误。
nick@nick-sager:~/workspace/LoopViT$ python ollama_debate.py Traceback (most recent call last): File "/home/nick/workspace/LoopViT/ollama_debate.py", line 200, in <module> host_system_prompt = HOST_SYSTEM_TEMPLATE.format( KeyError: 'debater_count-1' nick@nick-sager:~/workspace/LoopViT$
这个错误是因为字符串格式化时使用了 debater_count-1 作为占位符,但传入的参数中没有这个键(Python 的字符串格式化不支持直接在占位符里做算术运算)。以下是解决步骤和修复思路:

错误原因分析

HOST_SYSTEM_TEMPLATE 这个字符串模板中,你写了类似 {debater_count-1} 的占位符,但 Python 的 str.format() 方法只能识别纯变量名的占位符(比如 {debater_count}),无法解析 debater_count-1 这种带运算的表达式,因此抛出 KeyError

修复方案

步骤 1:修改模板中的占位符

把模板里的 {debater_count-1} 改成纯变量名(比如 {debater_count_minus_1}),示例:
python
运行
# 原错误模板(示例)
HOST_SYSTEM_TEMPLATE = """
辩论规则:共有 {debater_count} 名辩手,最后一名辩手编号是 {debater_count-1}
"""

# 修复后模板
HOST_SYSTEM_TEMPLATE = """
辩论规则:共有 {debater_count} 名辩手,最后一名辩手编号是 {debater_count_minus_1}
"""

步骤 2:格式化时传入计算后的参数

在调用 format() 时,先计算 debater_count - 1,并以新的变量名传入:
python
运行
# 假设你原本的调用代码(错误示例)
debater_count = 5
host_system_prompt = HOST_SYSTEM_TEMPLATE.format(
    debater_count=debater_count,
    # 缺少 debater_count-1 对应的键,且无法直接运算
)

# 修复后调用代码
debater_count = 5
host_system_prompt = HOST_SYSTEM_TEMPLATE.format(
    debater_count=debater_count,
    debater_count_minus_1=debater_count - 1,  # 先计算再传入
    # 其他需要的参数...
)

完整示例(可参考)

python
运行
# 定义模板(修复占位符)
HOST_SYSTEM_TEMPLATE = """
你是辩论主持人,共有 {debater_count} 名辩手参与辩论,
辩手编号从 0 到 {debater_count_minus_1},请引导辩论流程。
"""

# 业务逻辑
def generate_host_prompt(debater_count):
    # 计算差值,避免模板中直接运算
    debater_count_minus_1 = debater_count - 1
    # 格式化模板
    host_system_prompt = HOST_SYSTEM_TEMPLATE.format(
        debater_count=debater_count,
        debater_count_minus_1=debater_count_minus_1
    )
    return host_system_prompt

# 测试调用
if __name__ == "__main__":
    prompt = generate_host_prompt(5)
    print(prompt)

其他可能的替代方案

如果你使用 Python 3.6+,也可以用 f-string 先拼接模板(但适合简单场景):
python
运行
debater_count = 5
debater_count_minus_1 = debater_count - 1
# 直接用 f-string 渲染(无需单独模板变量)
host_system_prompt = f"""
你是辩论主持人,共有 {debater_count} 名辩手参与辩论,
辩手编号从 0 到 {debater_count_minus_1},请引导辩论流程。
"""

关键总结

  • Python str.format() 的占位符不支持算术运算,必须先计算好结果再传入;
  • 占位符名称必须是纯变量名(字母、数字、下划线,不能有减号 / 加号等运算符);
  • 修复核心:模板中用纯变量名,格式化时传入计算后的数值。
如果能贴出 HOST_SYSTEM_TEMPLATE 的具体内容和 format() 调用的完整代码,我可以给出更精准的修复版本。