全部版块 我的主页
论坛 数据科学与人工智能 人工智能
39 0
2025-12-09

案例目标

本项目致力于构建一个具备多智能体交互能力的辩论系统,通过模拟持有不同立场的智能体围绕特定议题展开多轮对话,实现类人化的思辨过程。系统整合了外部工具(如文档检索与网络搜索),为各方论点提供事实支撑,从而提升辩论的真实性与说服力。主要实现目标包括:

  • 设计支持持续交互的多轮对话智能体架构
  • 建立智能体调用外部工具的技术机制
  • 实现多个智能体之间的协调控制与流程管理
  • 展示智能体如何借助工具强化论证逻辑
  • 体现多智能体协同应对复杂问题的潜力

技术栈与核心依赖

系统基于以下关键技术组件构建:

  • LangChain:作为智能体运行的核心框架
  • ChatOpenAI:提供底层语言模型支持
  • FAISS:用于本地向量存储与高效文档检索
  • Tavily:接入实时网络信息搜索功能

所需关键依赖包如下:

pip install langchain langchain-openai langchain-community
pip install faiss-cpu tiktoken
pip install tavily-python

环境配置要求

在启动系统前,需完成相关API密钥的配置工作,确保所有外部服务能够正常调用。请将获取到的认证信息设置为环境变量以保障安全性。

# 设置OpenAI API密钥
export OPENAI_API_KEY="your-openai-api-key"

# 设置Tavily搜索API密钥
export TAVILY_API_KEY="your-tavily-api-key"

系统实现流程

1. 核心类与工具定义

DialogueAgent 类
该类为基本对话单元,负责维护个体的消息历史并处理通信逻辑。

class DialogueAgent:
    def __init__(self, name: str, system_message: SystemMessage, model: ChatOpenAI) -> None:
        self.name = name
        self.system_message = system_message
        self.model = model
        self.prefix = f"{self.name}: "
        self.reset()
    
    def reset(self):
        self.message_history = ["Here is the conversation so far."]
    
    def send(self) -> str:
        """
        将对话历史发送给聊天模型并获取响应
        """
        message = {"role": "system", "content": self.system_message.content}
        messages = pd.Series([message] + self.message_history)
        
        response = self.model(messages)
        return response.content
    
    def receive(self, name: str, message: str) -> None:
        """
        接收来自其他参与者的消息并添加到对话历史中
        """
        message_history = f"{name}: {message}"
        self.message_history.append(message_history)

DialogueSimulator 类
作为对话协调中枢,控制多个智能体之间的发言顺序与整体流程推进。

class DialogueSimulator:
    def __init__(
        self,
        agents: List[DialogueAgent],
        selection_function: Callable[[int, List[DialogueAgent]], int],
    ) -> None:
        self.agents = agents
        self._step = 0
        self.select_next_speaker = selection_function
    
    def reset(self):
        for agent in self.agents:
            agent.reset()
    
    def inject(self, name: str, message: str):
        """
        用初始消息开始对话
        """
        for agent in self.agents:
            agent.receive(name, message)
        self._step += 1
    
    def step(self) -> str:
        """
        推进对话一轮
        """
        speaker_idx = self.select_next_speaker(self._step, self.agents)
        speaker = self.agents[speaker_idx]
        message = speaker.send()
        
        for receiver in self.agents:
            receiver.receive(speaker.name, message)
        
        self._step += 1
        return f"{speaker.name}: {message}"

DialogueAgentWithTools 类
在基础类之上扩展工具调用能力,使智能体可主动查询外部知识源。

class DialogueAgentWithTools(DialogueAgent):
    def __init__(
        self,
        name: str,
        system_message: SystemMessage,
        model: ChatOpenAI,
        tools: List[Tool],
        chat_history: List[BaseMessage] = [],
    ) -> None:
        super().__init__(name, system_message, model)
        self.tools = {tool.name: tool for tool in tools}
        self.chat_history = chat_history
    
    def send(self) -> str:
        """
        将对话历史发送给聊天模型并获取响应
        """
        agent_chain = initialize_agent(
            self.tools,
            self.model,
            agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
            verbose=True,
        )
        
        message = AIMessage(content=self.system_message.content)
        
        if len(self.chat_history) > 0:
            new_message = HumanMessage(content="\n".join(self.message_history))
            self.chat_history.append(new_message)
        
        response = agent_chain.invoke({"input": self.message_history[-1]})
        return response["output"]

2. 文档检索功能实现

利用 FAISS 构建本地向量数据库,打造专用的知识检索工具,为智能体提供领域内权威资料支持。

# 加载支持医学院扩招的文档
support_loader = TextLoader("./data/Support_for_Medical_School_Expansion.txt")
support_documents = support_loader.load()

# 加载反对医学院扩招的文档
opposition_loader = TextLoader("./data/Opposition_to_Medical_School_Expansion.txt")
opposition_documents = opposition_loader.load()

# 文本分割
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=50)
support_chunks = text_splitter.split_documents(support_documents)
opposition_chunks = text_splitter.split_documents(opposition_documents)

# 创建向量数据库
support_vectorstore = FAISS.from_documents(support_chunks, OpenAIEmbeddings())
opposition_vectorstore = FAISS.from_documents(opposition_chunks, OpenAIEmbeddings())

# 创建检索器
doctor_retriever = support_vectorstore.as_retriever()
gov_retriever = opposition_vectorstore.as_retriever()

# 创建检索工具
doctor_retriever_tool = create_retriever_tool(
    doctor_retriever,
    "document_search",
    "搜索关于支持医学院扩招的文档。如果问题与医学院扩招的支持论点有关,请使用此工具!"
)

gov_retriever_tool = create_retriever_tool(
    gov_retriever,
    "document_search",
    "搜索关于反对医学院扩招的文档。如果问题与医学院扩招的反对论点有关,请使用此工具!"
)

3. 网络搜索能力集成

通过接入 Tavily 搜索 API,赋予智能体实时访问互联网信息的能力,增强其对新兴事件和动态数据的响应水平。

# 创建网络搜索工具
search = TavilySearchResults()
search_tool = Tool(
    name="Search",
    func=search.run,
    description="当需要回答关于当前事件的问题时使用此工具"
)

4. 辩论参与者设定

明确参与角色、讨论主题及辩论规则,形成结构化输入,为后续角色生成和行为约束奠定基础。

# 定义参与者名称
names = {
    "韩国医学会": ["document_search"],
    "政府": ["document_search", "Search"]
}

# 定义参与者名称和搜索工具的映射
names_search = {
    "韩国医学会": [doctor_retriever_tool],
    "政府": [gov_retriever_tool, search_tool]
}

# 辩论主题
topic = "2024年韩国医学院扩招是否必要"
word_limit = 50  # 每轮发言字数限制

5. 智能体初始化与配置

角色描述生成
借助大语言模型自动生成符合议题背景的智能体人物设定,提升角色真实感。

def generate_agent_description(name: str, tools: List[str], topic: str) -> str:
    agent_description_prompt = f"""{conversation_description}
    名称: {name}
    角色: 您是参与辩论的参与者。
    目标: {topic}
    
    以下是您可以使用的工具列表:
    {tools}
    
    请根据您的角色和目标,生成一个简洁的描述,说明您在辩论中的角色和立场。
    """
    agent_description_prompt_template = PromptTemplate(
        input_variables=["name", "tools", "topic"],
        template=agent_description_prompt
    )
    
    agent_description_chain = LLMChain(
        llm=ChatOpenAI(model="gpt-4", temperature=0.5),
        prompt=agent_description_prompt_template
    )
    
    agent_description = agent_description_chain.run(
        name=name,
        tools=tools,
        topic=topic
    )
    
    return agent_description.strip()

# 为每个参与者生成描述
agent_descriptions = {name: generate_agent_description(name, tools, topic) 
                     for name, tools in names.items()}

系统消息构建
为每个智能体制定专属系统提示词,明确其立场、表达风格与行为边界。

def generate_system_message(name: str, description: str, tools: List[str]) -> SystemMessage:
    system_prompt = f"""{conversation_description}
    
    你的名字是 {name}。
    你的角色描述如下: {description}。
    你的目标是辩论以下主题: {topic}。
    
    以下是你可以使用的工具列表:
    {tools}
    
    辩论规则:
    1. 每轮发言不超过 {word_limit} 字。
    2. 你必须使用工具来支持你的论点。
    3. 使用工具时,必须引用来源。
    4. 不要重复已经提出的观点。
    5. 保持专业和礼貌的语气。
    """
    
    return SystemMessage(content=system_prompt)

# 为每个参与者创建系统消息
agent_system_messages = {
    name: generate_system_message(name, description, tools)
    for name, description, tools in zip(
        agent_descriptions.keys(), 
        agent_descriptions.values(), 
        names.values()
    )
}

实例化带工具的智能体
创建具备检索与搜索能力的具体智能体对象,并完成参数注入与状态初始化。

# 创建具有工具能力的对话智能体
agent_with_tools = {
    name: DialogueAgentWithTools(
        name=name,
        system_message=system_message,
        model=ChatOpenAI(model="gpt-4", temperature=0.5),
        tools=tool_list,
        chat_history=[]
    )
    for (name, system_message), tool_list in zip(
        agent_system_messages.items(), 
        names_search.values()
    )
}

6. 执行辩论模拟流程

启动对话模拟器,驱动智能体按序发言,在实际交互中展现工具使用策略与推理能力。

# 定义选择下一个发言者的函数
def select_next_speaker(step: int, agents: List[DialogueAgent]) -> int:
    idx = step % len(agents)
    return idx

# 创建对话模拟器
simulator = DialogueSimulator(
    agents=list(agent_with_tools.values()),
    selection_function=select_next_speaker
)

# 重置模拟器
simulator.reset()

# 注入初始消息
simulator.inject("主持人", f"欢迎来到关于'{topic}'的辩论。请韩国医学会首先发言。")

# 运行辩论模拟
max_iters = 6
n = 0

while n < max_iters:
    name, message = simulator.step().split(": ", 1)
    print(f"{name}: {message}\n")
    n += 1

案例成果展示

本系统成功实现了完整的多智能体辩论流程,展现出以下几个方面的显著成效:

  • 多智能体协作能力:两个持不同观点的智能体能够在统一框架下有序互动,完成结构化辩论,体现出良好的协同机制。
  • 工具融合应用:智能体能主动调用文档检索和网络搜索工具获取证据,使论述更具事实依据和可信度。
  • 自然语言表达:输出内容连贯流畅,贴合角色定位,充分展现了大模型在拟人化对话中的优势。
  • 流程可控性:系统可精准掌控发言轮次与规则执行,避免混乱或偏离主题的情况发生。

示例输出结果如下:

韩国医学会: 韩国医学院扩招是必要的,因为我国医生严重不足,特别是农村地区。根据我们的研究,每千人医生数量远低于OECD平均水平。

政府: 虽然医生短缺确实存在,但扩招需要考虑教育资源质量和培训能力。盲目扩招可能导致医疗教育质量下降,最终影响患者安全。

韩国医学会: 我们建议分阶段扩招,并加强师资培训。根据搜索结果,日本通过类似方法成功解决了医生短缺问题,同时保持了教育质量。

政府: 政府已计划投资医学院基础设施,并与现有医院合作增加临床培训机会。这将在保证质量的前提下逐步增加医生数量。

设计思路解析

  1. 智能体架构设计
    采用面向对象方法构建基础类,再通过继承方式逐步扩展功能模块。这种分层设计提升了代码可读性与可维护性,便于后期迭代升级。

  2. 工具集成方案
    借助 LangChain 提供的工具抽象接口,统一接入多种外部资源(如文档库与搜索引擎),使得智能体可根据上下文自主选择合适的工具进行调用。

  3. 对话流程管理
    引入模拟器类来统筹全局交互,通过选择函数决定下一发言者,并持续记录对话历史,确保回应具备上下文一致性。

  4. 角色生成与行为约束
    利用 LLM 自动生成符合主题的角色设定,并结合系统消息设定行为规范,既保证个性鲜明又不失控制力,维持辩论的有效性和相关性。

未来扩展方向

  • 增加参与主体:引入更多角色类型(如专家评审、公众代表等),构建多方博弈场景,更贴近现实决策环境。
  • 添加评估体系:开发辩论质量评分机制,从逻辑严密性、证据充分性等维度自动评估论点优劣。
  • 支持动态立场调整:允许智能体根据辩论进展重新评估观点,实现立场迁移,增强模拟真实性。
  • 拓展多媒体支持:集成图像识别、视频检索等功能,让智能体可用多样化媒介佐证主张。
  • 实现实时事实核查:对接权威数据库或核查工具,自动验证陈述真伪,提高内容准确性。
  • 支持多语言交流:加入翻译中间层,使不同语种的智能体可在同一平台开展跨语言辩论,促进多元文化理解。

总结

本案例成功搭建了一个功能完备的多智能体辩论平台,充分体现了 LangChain 在复杂智能系统构建中的强大支撑能力。通过整合外部工具链,智能体不再局限于文本生成,而是能够基于真实数据展开有理有据的讨论。整个系统采用模块化设计理念,各组件职责清晰,易于扩展与维护,为后续开发更高级别的多智能体应用提供了良好范式。

其核心价值在于展示了如何有效组织多个智能体共同解决开放性问题,以及如何通过工具增强手段显著提升其认知能力。该模式可广泛应用于决策辅助、教育培训、舆情分析等多个实际场景,为人工智能走向深度社会融合开辟了新路径。

关键经验总结

  • 多智能体架构擅长模拟复杂的社交与决策互动
  • 工具集成是突破纯语言模型局限的关键路径
  • 合理的系统结构设计有助于提升可解释性与可扩展性
  • 大语言模型可用于动态生成角色设定与行为准则,增强灵活性
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群