文章目录
- 前言
- 一、Agent初始化
- 二、话题初始化
- 三、Agent对话
- 四、动态插话
- [五、同步 UI (Streamlit) 与 异步 Agent (Asyncio) 的融合](#五、同步 UI (Streamlit) 与 异步 Agent (Asyncio) 的融合)
- 总结
前言
随着大模型的发展,我们已经不再满足于只和一个 AI 聊天。现在的趋势是多智能体(Multi-Agent)------即创建多个带有不同角色设定的 AI,让它们互相交流、协作甚至辩论,从而完成复杂的任务。它最大的特点就是易用(Pythonic)、鲁棒性强(自带容错机制),并且原生支持分布式部署。
最近,我自己尝试搭建了一个有两个 Agent 参与的"技术脑暴室"。主要用于探讨技术方案,发现这种红蓝对抗的模式对启发思路非常有帮助。这里记录下我的设计流程和踩坑经验。
一、Agent初始化
首先,需要用大模型分别定义两个 Agent,分配好各自的角色和底层设定。 为了让讨论有深度,设计了一个"激进派(AI算法工程师)"和一个"保守派(AI系统架构师)"。
这里用到了 agentscope 提供的 ReActAgent。核心要点在于组件化记忆(Memory):为每个 Agent 配置了独立的 InMemoryMemory,保证了它们各自思考和记忆的连贯性,不会发生"精分"。
python
import agentscope
from agentscope.agent import ReActAgent
from agentscope.formatter import OpenAIChatFormatter
from agentscope.memory import InMemoryMemory
from agentscope.message import Msg
creator_agent = ReActAgent(
name="AI算法工程师",
sys_prompt="你是一个资深的AI算法工程师。你的目标是针对用户提供的话题进行深度技术脑暴。你会提出具体的算法改进方案或前沿技术思路。你会认真听取'AI系统架构师'的反馈并进行迭代讨论。",
model=model,
formatter=OpenAIChatFormatter(),
memory=InMemoryMemory(),
)
critic_agent = ReActAgent(
name="AI系统架构师",
sys_prompt="你是一个资深的AI系统架构师。你的任务是针对'AI算法工程师'提出的想法,从工程落地、系统架构和落地可行性角度进行深度点评和挑战。你会引导讨论触及更底层的细节,并提出互补的方案。",
model=model,
formatter=OpenAIChatFormatter(),
memory=InMemoryMemory(),
)
二、话题初始化
有了 Agent 之后,我们需要定义它们探讨的话题,并控制好对话的轮次。 前端部分我采用了 Streamlit 快速搭建。通过 Streamlit 的组件收集话题,并利用全局状态(session_state)来保存对话历史。
python
total_rounds = st.slider("对话轮数", 1, 10, 2)
default_topic = "讨论一下大规模模型(LLM)在端侧设备上的推理优化方案。"
initial_topic = st.text_area(
"初始话题",
value=default_topic,
height=100,
help="设置对话的起始话题"
)
initial_msg = Msg(name="主持人", content=initial_topic, role="user")
st.session_state.conversation_history.append(msg_to_dict(initial_msg))
if current_round < total_rounds:
st.info(f"正在进行第 {current_round + 1}/{total_rounds} 轮对话...")
三、Agent对话
两个 Agent 想完成连续对话,需要把上一个 Agent 的输出(当前话题)无缝转交给下一个 Agent。 在 AgentScope 中可以直接将 Message 对象作为 Agent 的输入,极大简化了流程。
为了在前端展示,我们需要将双方生成的对话进行提取和存储:
python
# current_msg 初始值为"主持人"发出的话题
st.session_state.current_msg = initial_msg
# 工程师率先发言,针对当前话题给出方案
creator_msg = await creator_agent(st.session_state.current_msg)
creator_dict = msg_to_dict(creator_msg) # 自定义的解析函数,用于提取文本保存到前端
st.session_state.conversation_history.append(creator_dict)
# 架构师紧接着发言,针对工程师的方案进行 review 和挑战
critic_msg = await critic_agent(creator_msg)
critic_dict = msg_to_dict(critic_msg)
st.session_state.conversation_history.append(critic_dict)
# 将架构师的回答更新为当前消息,进入下一轮循环...
st.session_state.current_msg = critic_msg
四、动态插话
系统不只是单纯看两个 AI "表演",在对话执行期间,用户可以通过文本框输入自己的观点("用户插话")。
实现机制:当用户点击插入后,内容不会打断当前正在生成的轮次,而是暂时保存在 st.session_state.pending_user_input 中。当当前轮次(架构师与工程师对话完毕)结束后,系统将其作为普通用户的角色(Role: user)压入消息流中,AI 在下一轮会自动看到并响应用户的介入。这解决了异步并发下的线程安全与对话逻辑混乱的问题。
python
# 1. 获取用户插话并缓存
user_input = st.text_input("插入消息", key="user_message_input")
if st.button("📤 插入") and user_input:
st.session_state.pending_user_input = user_input
st.info("消息已排队,将在当前轮次结束后插入")
# 2. 在当前轮次执行完毕后,检查缓存
if st.session_state.pending_user_input:
user_msg = Msg(
name="用户",
content=st.session_state.pending_user_input,
role="user"
)
# 将用户消息混入历史记录,并设为下一轮的触发消息(current_msg)
st.session_state.conversation_history.append(msg_to_dict(user_msg))
st.session_state.current_msg = user_msg
# 清空缓存
st.session_state.pending_user_input = None
五、同步 UI (Streamlit) 与 异步 Agent (Asyncio) 的融合
这是整个开发中最折腾的部分。Streamlit 本身是基于全局刷新的同步执行框架,但 AgentScope 生成对话、流式输出通常是基于 Asyncio 的异步操作。
如果直接 await 会导致 Streamlit 报错。解决这个问题的核心技术细节是:每次手动创建并接管一个新的事件循环,来桥接同步 UI 和异步大模型调用。
python
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
creator_msg, critic_msg = loop.run_until_complete(run_round())
finally:
loop.close()
总结
基于 Streamlit 结合 AgentScope,可以跑起一个包含 UI、状态管理、人机协同(Human-in-the-loop)完整周期的"自动脑暴系统"。这种 Multi-Agent 的范式,不仅可以做脑暴室,未来还可以挂载不同的 Tool(比如一个负责去搜论文,一个负责写代码),潜力非常巨大。