资讯动态

建设性对话工程实践:多Agent辩论与LLM自动评估

发布时间:2026/8/27 10:23:29 来源:尧图企业网站定制
这次我们来看一个不太“硬核”、但工程上非常值得复用的主题建设性对话。选题起点来自 Anthropic 首席经济学家在公开讨论中经常触及的方向——AI 的价值不只是在单轮问答里给出答案更体现在多方观点分歧时能不能把对话导向共识与行动。这个观点能不能落到工程里可以。它不是一个具体的开源项目而是一套可组合的实现方法提示词模板 多 Agent 辩论框架 LLM-as-judge 自动评估 API 批量任务。这套方案最大的特点是不吃显卡。运行它不需要本地大模型只需要一个可调用的大模型 API普通开发机甚至笔记本就能跑。你会看到如何在一个小时内搭建出最小可用的建设性对话演示系统如何用两个 Agent 模拟观点交锋如何用第三个 Agent 做总结评审以及如何把整条链路接到批量任务里做稳定性验证。适合的读者有三类正在做 AI 应用、客服机器人和社区内容产品的开发者需要给对话系统加“质量护栏”但不想引入太重平台的团队想研究提示词工程、Agent 协作和自动评估的入门者。这篇文章会从能力拆解开始一步一步走到可运行代码和排查清单建议收藏备用。1. 核心能力速览能力项说明主题类型AI 对话应用工程方法不是一个单一开源仓库议题背景Anthropic 首席经济学家关于建设性对话的公开讨论方向核心能力建设性提示词模板、多 Agent 观点辩论、对话总结评审、自动评分硬件门槛普通开发机即可无独立显卡要求依赖服务可调用的大模型 APIOpenAI 兼容接口或 Anthropic 官方 API 均可启动方式Python 脚本直接运行不依赖 WebUI接口 API通过 HTTP 调用模型服务本文提供通用调用模板批量任务支持可对多话题、多轮次批量运行并输出评估结果输出格式对话文本、结构化 JSON 评分、批量结果 CSV/JSON合规要求涉及真实人物、声音、版权素材或用户身份信息时必须先取得授权这里要说明一点建设性对话不是一个开箱即用的开源模型也不是某个官方插件。它是一套可以叠加在任何大模型之上的系统设计。模型负责生成语言而建设性由提示词、对话结构和评估机制共同保证。这也是为什么这套方法不依赖特定显卡或特定模型版本换模型之后只需要微调提示词。2. 建设性对话的能力拆解与使用边界在开始写代码之前得先明确一个定义什么算“建设性对话”我把它拆成五个可观察、可测试的能力维度。第一观点明确。建设性对话不等于和稀泥。系统应该敢于表达立场但表述必须具体、可回应而不是“你说得也有道理我也有我的道理”。第二反驳有据。当系统不同意用户或另一个 Agent 的观点时需要指出具体分歧点并给出理由和替代方案。单纯说“你错了”不叫建设性。第三不人身攻击。对话系统要针对观点本身展开不评价发言者的身份、动机或人格。这一点在客服、社区讨论、争议话题场景里尤其重要。第四识别共识。建设性对话要能找出双方共同认可的部分。如果讨论了半天连一个共同点都没有很难推进。第五导向行动。最后最好给出可执行的下一步比如“我们可以先在小范围试运行两周用数据决定是否推广”而不是停在抽象争论。不过这里有两层边界必须说清楚。第一建设性对话解决的是“对话形式”问题不解决“事实正确性”问题。一个语气非常礼貌、结构非常完整的回复内容仍然可能是错的。如果场景涉及医疗、法律、金融等专业领域无论语气多建设性都必须叠加专业知识审核。第二合规边界。这类系统不能用于制造虚假共识、伪造专家背书、操纵舆论等场景。如果对话涉及真实人物、声音、肖像或未公开隐私信息必须提前获得授权。批量采集或生成对话数据时也要确认素材来源的版权和用户授权否则可能带来法律风险。3. 环境准备与前置条件这套方案不依赖 GPU所以环境准备非常简单。你需要准备的只有三样东西一个 Python 环境、一个可调用的大模型 API Key、一个能访问 API 的网络条件。建议 Python 版本 3.9 以上。依赖只需要requests如果要把批量结果存成表格再用到pandas。实际上即使只用 Python 标准库也能跑通只是代码会稍微啰嗦一点。创建虚拟环境并安装依赖mkdir constructive-dialogue cd constructive-dialogue python -m venv venv source venv/bin/activate # Windows 下使用 venv\Scripts\activate pip install requests pandas准备好 API Key 后建议通过环境变量传入不要硬编码在代码里。这样可以避免不小心提交到 Git 仓库。下面这种加载方式在本地脚本和服务器部署时都适用import os API_KEY os.environ.get(LLM_API_KEY, ) BASE_URL os.environ.get(LLM_BASE_URL, https://api.example.com/v1) MODEL os.environ.get(LLM_MODEL, your-model-name) if not API_KEY: raise RuntimeError(请先设置 LLM_API_KEY 环境变量)这里的BASE_URL和MODEL是占位符。如果你使用的是 OpenAI 兼容接口可以直接填服务商提供的 base_url 和模型名。如果使用 Anthropic 官方 API请求格式会不同需要以官方文档为准核心思路是一样的构造 messages 列表发送 HTTP 请求解析返回内容。4. 最小实现基于提示词的建设性对话先写一个最简版本不搞多 Agent只用一条系统提示词让模型在单轮对话中表现出建设性。这一步要验证两件事提示词是否生效API 调用链路是否通畅。先定义一个通用调用函数import requests import os API_KEY os.environ.get(LLM_API_KEY, ) BASE_URL os.environ.get(LLM_BASE_URL, https://api.example.com/v1) MODEL os.environ.get(LLM_MODEL, your-model-name) def call_llm(messages, temperature0.7, max_tokens800): OpenAI 兼容接口调用base_url 和 model 需替换为实际服务商配置。 resp requests.post( f{BASE_URL}/chat/completions, headers{Authorization: fBearer {API_KEY}}, json{ model: MODEL, messages: messages, temperature: temperature, max_tokens: max_tokens, }, timeout60, ) resp.raise_for_status() data resp.json() return data[choices][0][message][content]然后定义建设性对话的系统提示词。这里的关键是不要只写“请保持礼貌”要给出可执行的分步规则SYSTEM_PROMPT 你是一名建设性对话助手。你的目标是帮助对话双方把问题讨论清楚而不是赢下对话。 具体要求 1. 先用自己的话复述对方的立场表示你已经理解。 2. 如果同意对方的部分观点先说明共同点。 3. 如果不同意直接指出分歧点并给出理由和可替代的方案。 4. 避免对发言者人格、动机做负面评价只针对观点本身展开。 5. 每次回复最后给出一个可以继续推进的开放问题或行动建议。现在做一次单轮测试输入一个带有对抗性的问题if __name__ __main__: user_text 我认为远程办公会降低团队效率你支持吗 messages [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_text}, ] reply call_llm(messages) print(reply)预期结果不是简单的“我同意”或“我反对”而是类似这样的结构先复述对远程办公的担忧指出部分场景下这个问题确实存在再给出不同视角比如远程办公对专注型任务可能更高效最后建议小范围试验收集数据。判断这次测试是否成功标准有三个回复是否复述了用户立场分歧点是否说得具体结尾是否给出了行动建议或开放问题。如果只有礼貌没有内容说明提示词里的“分步规则”被模型忽略了可以适当加强“必须按 1 到 5 条逐项回应”的约束。如果遇到 API 返回错误先看状态码。401 是 Key 无效或权限不足404 是路径不对429 是触发限流。这类基础问题在后面的排查章节会展开。5. 多 Agent 建设性辩论框架单轮提示词能解决的基本是“语气”问题。但真的要体现建设性对话最好的结构是多 Agent让一个 Agent 提出观点另一个 Agent 做建设性反驳第三个 Agent 做主持人总结。这么做的好处是模型不再需要在一段回复里既当运动员又当裁判观点反而更清晰。定义三个角色。第一个是观点提出者第二个是建设性反方第三个是评审。PROMPT_PROPOSER 你是一位观点提出者。针对给定议题你需要 - 提出一个明确、有依据的立场 - 用具体例子或逻辑支撑你的观点 - 在回应对方合理质疑时可以修正观点但不轻易放弃核心立场。 PROMPT_OPPOSER 你是一位建设性反方。针对对方观点你需要 - 先复述对方观点中最有价值的部分 - 指出对方论证中值得商榷的地方 - 提出自己的替代方案而不是单纯否定。 PROMPT_REFEREE 你是一位讨论主持人。请阅读双方对话输出四部分内容 1. 双方共识 2. 存在的核心分歧 3. 各方观点中最有力的论据 4. 一个可供下一步验证的行动建议。接下来是 Agent 的抽象类。每个 Agent 持有自己的提示词和名称负责把对话历史发送给模型并取回回复。class DialogueAgent: def __init__(self, name, system_prompt): self.name name self.system_prompt system_prompt def respond(self, history): messages [{role: system, content: self.system_prompt}] messages.extend(history) reply call_llm(messages) return {role: assistant, content: f[{self.name}] {reply}}主流程很简单先让正方发言再把历史和反方发言一起交给反方 Agent最后把完整对话交给评审 Agent。这里控制轮次为 2 轮轮次越少 token 消耗越可控。def run_debate(topic, rounds2): proposer DialogueAgent(正 方, PROMPT_PROPOSER) opposer DialogueAgent(反 方, PROMPT_OPPOSER) referee DialogueAgent(主持人, PROMPT_REFEREE) history [] current f议题{topic}。请开始你的陈述。 history.append({role: user, content: current}) for _ in range(rounds): history.append(proposer.respond(history)) history.append(opposer.respond(history)) summary referee.respond(history) return history, summary跑一个具体议题看看输出结构if __name__ __main__: history, summary run_debate(公司是否应该全面实行远程办公制度) print( 双方对话 ) for message in history: print(message[content]) print() print( 主持总结 ) print(summary[content])输出会分成两个部分。双方对话部分能看到正方和反方各自的立场以及他们在第二轮对对方质疑的回应。主持总结部分会把共识、分歧、有力论据和行动建议列出来。如果你发现反方没有真正反驳而是直接同意正方说明PROMPT_OPPOSER里“建设性反方”的角色约束还不够强可以加一句“你必须提出至少一个不同的替代方案”。这种多 Agent 结构看起来简单实际上已经把建设性对话的五个能力维度都覆盖到了正方和反方负责“观点明确”和“反驳有据”提示词里的复述要求负责“不人身攻击”主持人负责“识别共识”和“导向行动”。6. 效果评估从“感觉还行”到“可量化”多 Agent 框架跑通之后马上会遇到一个更现实的问题输出质量不稳定。同样是“远程办公”的议题跑三次可能一次很好一次和稀泥一次反方完全不反驳。这时候不能靠肉眼观察需要一套可量化的评估流程。这里用常见的 LLM-as-judge 方案让一个独立的评审模型给对话打分。评分维度就按前面定义的五个能力来。PROMPT_JUDGE 你需要对一段对话的建设性程度打分。 评分维度均为 1-5 分 - clarity: 立场是否清晰 - reasoning: 论证是否基于理由 - respect: 是否避免人身攻击 - consensus: 是否识别共识 - actionable: 是否给出行动建议 对话记录 {transcript} 只输出 JSON格式如下 { clarity: 4, reasoning: 3, respect: 5, consensus: 2, actionable: 3, overall: 3 } 注意这里要求“只输出 JSON”。实际调用时模型偶尔会在 JSON 外面加解释文字所以解析要做容错。简单处理方式是提取首个{到最后一个}之间的部分import json import re def parse_json_response(text): start text.find({) end text.rfind(}) if start -1 or end -1: raise ValueError(f无法解析 JSON{text}) return json.loads(text[start:end 1]) def evaluate_dialogue(history): transcript \n.join(m[content] for m in history if m.get(content)) prompt PROMPT_JUDGE.format(transcripttranscript) response call_llm( [{role: user, content: prompt}], temperature0.2, max_tokens300, ) return parse_json_response(response)把评分接到run_debate后面整个流程就变成多 Agent 生成对话 - 评审 Agent 打分 - 输出 JSON。这个结果可以直接存进日志也可以汇总成 CSV 做趋势分析。LLM-as-judge 有两个注意点。第一它会有评分偏置。同一个分数可能因为模型不同、temperature 不同而波动。所以批量评估时要把temperature固定在一个低值比如 0.2并且对每条记录做至少一次人工抽检。第二不要只用 overall 一个指标。五个分维度分别看才能定位问题。比如 consensus 长期偏低说明评审 Agent 提示词里的“识别共识”没有生效respect 长期偏低说明提示词需要加强反方角色约束。7. 接口 API 与批量任务单条对话跑通之后真正有价值的是批量任务。比如你要测试 20 个不同议题的建设性效果或者对不同提示词模板做 A/B 对比这时候手动跑脚本就不现实了。批量任务的设计思路很直接准备一个议题列表逐个跑run_debate把结果和评分存下来。由于 API 有并发限制不建议一次性开太多线程。稳妥的做法是用ThreadPoolExecutor控制并发数。import csv from concurrent.futures import ThreadPoolExecutor, as_completed TOPICS [ 公司是否应该全面实行远程办公制度, 开源软件是否应该默认收取维护费, AI 生成内容是否需要在平台标注, 数据隐私保护是否应该优先于商业效率, ] def process_topic(topic): try: history, summary run_debate(topic, rounds2) score evaluate_dialogue(history) return { topic: topic, summary: summary[content], **score, } except Exception as exc: return { topic: topic, error: str(exc), } def run_batch(topics, max_workers3): results [] with ThreadPoolExecutor(max_workersmax_workers) as pool: future_map {pool.submit(process_topic, t): t for t in topics} for future in as_completed(future_map): results.append(future.result()) return results if __name__ __main__: batch_results run_batch(TOPICS, max_workers3) with open(batch_results.csv, w, newline, encodingutf-8) as f: writer csv.DictWriter(f, fieldnameslist(batch_results[0].keys())) writer.writeheader() writer.writerows(batch_results) print(批量任务完成结果已写入 batch_results.csv)这段代码有几个工程细节值得注意。第一process_topic内部把异常捕获了而不是让它直接打断整个批量任务。这样单条失败不会让 20 条全部重跑最后可以通过error字段定位问题。第二max_workers不要开太大。不同模型服务的并发限制不一样稳妥起见从 3 开始观察有没有 429 限流。如果触发了限流再加指数退避重试。第三CSV 的字段名来自第一条结果的 key。如果某条结果出错导致 key 缺失写入时会报错。实际项目里建议预先定义好固定字段列表。批量任务的核心价值不只是跑得多而是每次运行都有可回看、可比较的日志。8. 资源占用与性能观察这套方案不做本地推理所以不需要观察显存。真正需要观察的是三个东西token 消耗、单轮延迟、总成本。Token 消耗是最重要的。多 Agent 框架里的每次发言都会把之前的全部历史重新发送给模型所以 token 会随轮次增长。假设每轮双方各输出 300 token三轮之后第五轮发言请求的上下文可能已经达到 3000 token 以上。批量跑 20 个议题这个消耗会被放大。一个简单的测量方式是在call_llm里记录每次请求的 usage 和耗时import time def call_llm_with_stats(messages, temperature0.7, max_tokens800): start time.time() resp requests.post(...) # 同样的请求逻辑 elapsed time.time() - start data resp.json() usage data.get(usage, {}) print( f耗时 {elapsed:.2f}s, fprompt_tokens{usage.get(prompt_tokens)}, fcompletion_tokens{usage.get(completion_tokens)} ) return data[choices][0][message][content]观察几次后你会得到一个直观结论轮次越多单次请求越慢。因为前置 context 越长模型需要处理的内容越多。想要降低耗时从这几个方向入手。第一控制每轮输出长度。给call_llm的max_tokens设一个合理上限比如 500避免 Agent 越说越长。第二减少轮次。两轮辩论通常能覆盖主要分歧三轮以上边际收益会下降。第三裁剪历史。如果只关心最终总结中间每一轮不需要把所有轮次都发过去可以只保留最近一到两轮或者让评审 Agent 只看压缩后的要点。成本计算要按服务商实际定价来。方法是用 usage 里的prompt_tokens和completion_tokens分别乘单价再把批量任务的所有请求求和。这里不能给出具体价格因为不同服务商、不同模型差异很大有疑问时以你实际使用的账单为准。性能观察的目的不是把数字压到最低而是建立一个基线跑一个议题要多少秒、多少 token、平均打分多少。有了基线换提示词模板或者换模型时才能判断改动是变好了还是变差了。9. 常见问题与排查方法下面是这套流程里最常遇到的问题与排查思路。问题现象可能原因排查方向解决建议API 返回 401/403API Key 无效或权限不足检查环境变量、服务商后台重新生成 Key确认模型访问权限请求超时网络不稳定或模型响应慢打印返回状态码和耗时调大 timeout加入指数退避重试返回空内容输出被过滤或 max_tokens 太小看日志里的 finish_reason调大 max_tokens检查内容过滤策略多 Agent 某一步失败上下文超长或单轮解析异常打印该轮历史长度裁剪历史限制每轮输出长度批量任务中途卡住触发限流或并发配置问题观察日志时间戳降低 max_workers加入重试和超时评分结果不稳定大模型随机性连续跑多次对比降低 temperature固定 seed人工抽检效果偏“和稀泥”单 Agent 只用一套提示词翻看对话记录中是否有分歧改用多 Agent 结构强制反方给替代方案反方完全不反驳角色提示词约束不足查看反方第一条回复在反方提示词中增加“必须提出至少一个替代方案”输出 JSON 解析失败模型在 JSON 外加了文字打印原始返回用 find 提取{到}的区间再解析排查时一定记住先看日志再改代码。不要看到一次失败就调整提示词。批量任务里偶发失败很常见先区分是单条偶发还是系统性失败。如果 20 条里只有 1 条超时大概率是网络或限流如果 15 条都失败那才是配置或代码问题。10. 最佳实践与使用建议把这套流程跑通之后建议先从一个最小模板开始不要一上来就追求复杂场景。我的建议是先把单轮提示词 一个议题测通再扩展到多 Agent最后接批量评估。每一步都保留一份可运行的基线代码后面改坏了随时能退回。目录结构可以按照下面这种方式组织constructive-dialogue/ ├── requirements.txt ├── config.py # API Key、BASE_URL、MODEL 读取 ├── llm_client.py # call_llm 封装 ├── prompts.py # 所有提示词模板 ├── dialogue.py # 单 Agent 和多 Agent 流程 ├── evaluate.py # 自动评分 ├── batch.py # 批量任务入口 ├── logs/ # 运行日志 ├── results/ # 批量结果输出 └── data/ └── topics.txt # 待测议题列表工程上有几个建议。第一日志要完整。每次批量运行都记录时间戳、议题、模型名、token 用量、评分结果。没有日志后面想复盘“上个版本为什么效果好”会很困难。第二接口服务要限制访问范围。如果后续把建设性对话能力封装成 API 暴露给业务方建议加鉴权和限流。不要在公网裸跑一个没有鉴权的模型代理服务。第三涉及人脸、声音、版权素材或真实用户对话时必须确认授权。建设性对话系统本身是中立的技术能力但它生成的内容如果涉及真实身份信息必须走合规流程。第四上线前做人工复核。LLM-as-judge 可以帮你筛掉大部分明显问题但它不是万能的。建议每个批量结果抽 10% 到 20% 人工看一遍重点看有没有事实错误和潜在风险。第五建立一个反馈闭环。把评分偏低的案例单独收集起来定期微调提示词模板。建设性对话没有终点它是靠一轮一轮数据迭代出来的。建议从今天的最小模板开始跑一次。先设置好LLM_API_KEY运行第四节的单轮对话脚本看看输出有没有复述立场、有没有分歧点、有没有行动建议。跑通之后再往上叠加多 Agent 和批量评估。你会发现所谓的“建设性”本质上是一套可以被设计、被测试、被量化的系统工程。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价