Published on

2025年,让AI大模型当众辩论

Authors
  • Name
    Twitter

引子:AI的烦恼

2025年,无疑是属于AI的一年。我们见证了各家AI大模型你追我赶,以几乎每周一次的频率刷新着我们对“智能”的认知。曾经遥不可及的人工智能,如今真真切切地走入了寻常百姓家——它帮我们写邮件、画插画、做旅行计划,甚至成为我们工作学习中不可或缺的伙伴。

一个由AI引起的知识大爆炸时代已然来临。但随之而来的,是一个幸福的烦恼,一个我们每天都会在脑海中闪过的问题:

"在这么多AI里,到底哪个回答更好、更准确?"

我们穿梭于Gemini、ChatGPT、文心一言、Claude、通义千问之间,试图为同一个问题找到最完美的答案。我们看得越多,就越是好奇,如果把它们关在一个房间里,它们自己会如何评价对方的观点?

一个的想法油然而生:所谓“真理越辩越明”,能否让AI大模型之间直接对话PK,来一场AI辩论大赛?

起源:手头拮据,即要又要

基于此,我想设计一个小程序,实现上述的辩论功能。这个程序的构想很简单:

  1. 用户设定一个富有争议的辩题。
  2. 用户选择两个不同的AI大模型,分别扮演正方和反方。
  3. 引入第三个中立且强大的AI担任“主持人”或“裁判”。
  4. 程序自动调度,让正反方轮流发言,互相反驳,主持人则在每轮结束后进行总结。

整个过程需要完全可视化,让我们可以像观看一场真实的辩论赛一样,清晰地看到它们的观点交锋。虽然不知道有没有这种程序,但是所谓AI时代,万物皆可AI,自己AI干吧。

然而,理想很丰满,现实却很骨感。作为一个业余爱好者,毫无开发经验,预算为零。既然商业大模型的API调用费用不菲,那么,“白嫖”岂不美哉!几乎所有大公司都为开发者提供了或多或少的免费API额度。然而鼓捣半天,免费午餐没那么好吃,各种申请填一大堆,大大打击了积极性。最后决定,找两个熟悉的、简单的、中外代表性的试试水吧。于是,就这样了。

过程:从命令行到图形界面

第一个版本很简陋,只是Python脚本运行窗口。需要手动配置好API密钥,输入辩题,然后看着屏幕上交替滚动的、由不同模型生成的文字。

即便如此,当“正方AI”的开场陈词刚刚出现,“反方AI”立刻针对其中的逻辑漏洞发起了精准反驳时,那感觉还不错。这不再是简单的“问-答”,而是一种思维的碰撞。 真的“辩论”了起来,是那么回事!

初步效果不错,但命令行毕竟不太“人性化”,需要图形化窗口啊,能直接讲人话那还需要abc123。网上AI问了一圈,原来Streamlit这个神奇的Python库,只用了百十行代码,就为这个简陋的脚本套上了一个美观、易用的图形化外壳——“AI互掐”小程序的雏形诞生了。用户可以在侧边栏轻松配置API、选择模型、设定辩题和轮次,然后在主窗口实时观看这场别开生面的辩论。

简单步骤

  1. 申请各大公司API key:我选择了Gemini和火山引擎,Mistral作为裁判AI,后来证明Mistral免费输入的文本太长无法使用,不得不再次用Gemini。

  2. 采用Docker本地部署One-api,集中管理所有的API key并进行调用;

one-api
  1. 采用python Streamlit库实现图形界面,代码和prompt如下:
import streamlit as st
import openai
import time

# --- 页面基础设置 ---
st.set_page_config(
    page_title="AI互掐",
    page_icon="🤖",
    layout="wide"
)

st.title("🤖 AI思辨大会")
st.caption(f"当前时间: {time.strftime('%Y-%m-%d %H:%M:%S')}")

# --- 侧边栏配置 ---
with st.sidebar:
    st.header("🔗 API 配置")
    # 使用st.secrets来更安全地管理密钥,如果没有则让用户输入
    try:
        default_api_key = st.secrets["api_key"]
        default_base_url = st.secrets["base_url"]
    except (FileNotFoundError, KeyError):
        default_api_key = "**" # **替换为One-api建立的令牌,以“sk-”开头
        default_base_url = "http://localhost:3000/v1"  # 默认为本地One-API地址

    api_key = st.text_input("API Key", value=default_api_key, type="password")
    base_url = st.text_input("API Base URL", value=default_base_url)

    st.header("🎭 辩手设置")
    topic = st.text_area("请输入辩论主题...", value="人工智能的发展是否应该受到更严格的全球性法规限制?", height=150)

    col1, col2 = st.columns(2)
    with col1:
        model_a = st.text_input("正方模型", value="**") # **替换为申请可用模型名称
    with col2:
        model_b = st.text_input("反方模型", value="**") # **替换为申请可用模型名称

    moderator_model = st.text_input("主持人模型", value="**") # **替换为申请可用模型名称
    rounds = st.slider("辩论回合数", 1, 5, 2)

# --- 初始化会话状态 ---
# st.session_state 是Streamlit提供的用于在用户多次交互之间保存变量的“内存”
if "messages" not in st.session_state:
    st.session_state.messages = []

# --- 显示历史消息 ---
# 每当用户操作导致页面刷新时,这段代码都会执行,从而把历史消息显示出来
for message in st.session_state.messages:
    with st.chat_message(message["role"], avatar=message.get("avatar")):
        st.markdown(message["content"])

# --- 主逻辑 ---
if st.sidebar.button("🚀 开始辩论"):
    if not api_key or not base_url or not topic:
        st.warning("请在侧边栏填写完整的API配置和辩论主题。")
    else:
        # 清空上一次的辩论记录
        st.session_state.messages = []

        # 创建API客户端
        client = openai.OpenAI(base_url=base_url, api_key=api_key)

        # 定义辩手信息
        debater_a = {"name": "正方", "model": model_a, "avatar": "👍"}
        debater_b = {"name": "反方", "model": model_b, "avatar": "👎"}
        moderator = {"name": "主持人", "model": moderator_model, "avatar": "👨‍⚖️"}

        # 显示辩题
        st.info(f"辩题:{topic}")

        # 构建辩论历史(用于传递给模型的上下文)
        conversation_history = []

        try:
            # --- 辩论开始,按轮次循环 ---
            for i in range(rounds):
                st.subheader(f"第 {i + 1} 回合", divider='rainbow')

                # --- 正方发言 ---
                # 在第一轮,正方进行开场陈词;后续轮次则进行回应。
                if i == 0:
                    prompt_a = f"你是一位名叫{debater_a['name']}的辩手。你的立场是 **支持** “{topic}”。这是辩论的开场陈词,请开始你的第一轮发言,要求清晰、有逻辑、有说服力。"
                else:
                    prompt_a = f"你是一位名叫{debater_a['name']}的辩手。你的立场是 **支持** “{topic}”。以下是到目前为止的辩论历史:\n{conversation_history}\n\n现在轮到你在第{i + 1}回合发言,请直接反驳对方的观点并提出你的新论据。"

                with st.chat_message(debater_a['name'], avatar=debater_a['avatar']):
                    with st.spinner("正方正在思考..."):
                        response = client.chat.completions.create(
                            model=debater_a['model'],
                            messages=[{"role": "user", "content": prompt_a}]
                        )
                        a_text = response.choices[0].message.content
                        st.markdown(a_text)
                st.session_state.messages.append(
                    {"role": debater_a['name'], "content": a_text, "avatar": debater_a['avatar']})
                conversation_history.append({"role": debater_a['name'], "content": a_text})

                # --- 反方发言 ---
                prompt_b = f"你是一位名叫{debater_b['name']}的辩手。你的立场是 **反对** “{topic}”。以下是到目前为止的辩论历史:\n{conversation_history}\n\n现在轮到你在第{i + 1}回合发言,请直接反驳对方刚才的观点。"
                with st.chat_message(debater_b['name'], avatar=debater_b['avatar']):
                    with st.spinner("反方正在思考..."):
                        response = client.chat.completions.create(
                            model=debater_b['model'],
                            messages=[{"role": "user", "content": prompt_b}]
                        )
                        b_text = response.choices[0].message.content
                        st.markdown(b_text)
                st.session_state.messages.append(
                    {"role": debater_b['name'], "content": b_text, "avatar": debater_b['avatar']})
                conversation_history.append({"role": debater_b['name'], "content": b_text})

                # --- 主持人总结本回合 ---
                prompt_moderator = f"你是一位中立、客观的辩论主持人。请对刚才第{i + 1}回合中,正反双方的交锋进行简要、无偏见的总结。这是刚才的对话内容:\n{conversation_history[-2:]}"
                with st.chat_message(moderator['name'], avatar=moderator['avatar']):
                    with st.spinner("主持人正在总结..."):
                        response = client.chat.completions.create(
                            model=moderator['model'],
                            messages=[{"role": "user", "content": prompt_moderator}]
                        )
                        mod_text = response.choices[0].message.content
                        st.markdown(mod_text)
                st.session_state.messages.append(
                    {"role": moderator['name'], "content": mod_text, "avatar": moderator['avatar']})

            st.success("辩论结束!")

        except Exception as e:
            st.error(f"发生错误: {e}")
  1. 最终效果如下:“中医是科学吗?”
AI—debate1
AI—debate2

拓展:这个“玩具”还能怎么玩

  • 对于普通用户: 这是一个绝佳的认知拓展工具。当你对一个复杂的社会或科学议题感到困惑时,可以看看两个AI如何从不同角度、用逻辑和数据来剖析它,帮助你更全面地理解问题。
  • 对于开发者和研究者: 这是一个直观的模型评测平台。除了跑分,我们更关心模型的逻辑推理、语言风格和“思维深度”。让模型进行辩论,能更好地暴露它们在这些高级认知能力上的差异。
  • 对于内容创作者: 这是一个灵感生成器。一场关于“未来城市”的AI辩论,可能会给你带来数十个新颖的视频或文章选题。
  • 对于我们每个人: 这是一个打破信息茧房的利器。AI或许没有真正的观点,但它们能模仿人类最高水平的逻辑论证。观看一场高质量的AI辩论,能迫使我们审视自己既有的立场,思考我们信念背后的逻辑是否真的站得住脚。

未来:道阻且长,行则将至

“AI互掐”到此为止,下一步:引入实时流式响应,让对话更加生动;增加最终总结报告,让辩论有一个完整的收尾。增加更多的模型,实现AI大“混战”,欢迎围观。

匿名评论