目录
前言
大家好!上篇的聊天程序又更新了,本次更新基于这样一个想法:能不能做一个类似微信的桌面聊天程序,但聊天对象不是真人,而是各种AI助手(比如“知识渊博的历史老师”“幽默的段子手”)?说干就!我用Python和PySide6做了界面,结合大语言模型(LLM)实现了多智能体(Agent)聊天功能。今天就和大家分享这个小项目的实现过程~
一、先看效果:像微信一样和AI聊天
程序运行后,界面是左右分栏设计:
- 左侧是“好友列表”(其实是各种AI Agent),支持右键添加/删除/编辑Agent;
- 右侧是聊天窗口,顶部显示聊天记录,底部是输入框和发送按钮。
我给程序加了个默认AI好友:“Friend A”。输入消息点击发送,AI会自动回复——就像和真人聊天一样!
当然,核心功能不止这些:
✅ 支持动态添加/删除AI好友;
✅ 聊天记录自动保存到本地;
✅ AI好友可以配置不同的“人设”(比如“历史老师”或“情感顾问”);
✅ 底层用大语言模型(如Ollama或OpenAI)生成回复。
二、核心模块拆解:界面、消息中心、AI智能体
整个程序主要分三部分:界面交互、消息中心、AI智能体。下面逐个拆解~
1. 界面交互:用PySide6搭积木
界面部分我用了PySide6
——这是Python的Qt框架绑定,适合快速做桌面程序。简单说,就是把“按钮”“输入框”“列表”这些组件像搭积木一样拼起来。
比如ChatBox
类的initUI
方法(核心代码片段):
def initUI(self):
self.setWindowTitle('AICQ')
self.setGeometry(100, 100, 1000, 600) # 窗口位置和大小
# 主布局:左右分栏(左侧好友列表,右侧聊天区)
main_splitter = QSplitter(Qt.Horizontal)
# 左侧好友列表(支持右键菜单)
self.contact_list = QListWidget()
self.contact_list.setContextMenuPolicy(Qt.CustomContextMenu) # 启用右键菜单
self.contact_list.customContextMenuRequested.connect(self.show_contact_context_menu) # 右键事件
# 右侧聊天区:上下分栏(聊天记录显示区 + 输入区)
chat_splitter = QSplitter(Qt.Vertical)
self.scroll_area = QScrollArea() # 聊天记录滚动区域
self.input_box = QTextEdit() # 输入框
self.send_button = QPushButton('发送') # 发送按钮
self.send_button.clicked.connect(self.send_message) # 点击发送消息
# 组装所有组件
main_splitter.addWidget(self.contact_list)
main_splitter.addWidget(chat_splitter)
self.setLayout(main_splitter)
这段代码的关键是用QSplitter
(可拖动的分隔条)实现了灵活的布局。左侧好友列表支持右键菜单(比如“创建新Agent”),右侧聊天区用滚动区域显示历史记录,输入框和发送按钮放在底部。
2. 消息中心:所有消息的“中转站”
聊天程序的核心是消息的发送和接收。我设计了一个MessageCenter
(消息中心),负责管理所有在线的AI智能体(Agent)和用户,处理消息的转发。
看MessageProcessor
类的run
方法(消息处理线程):
class MessageProcessor(QThread):
def run(self):
while True:
if self.stop:
break
message = self.messages.get() # 从队列取消息(阻塞等待)
print(f"MessageCenter received message: {message}")
try:
if message["type"] == "text":
# 先检查接收者是否是用户(user)
receiver_exists = False
for use in self.uses:
if use.name == message["receiver"]:
use.receive_message(message) # 用户接收消息
receiver_exists = True
break
# 再检查接收者是否是AI Agent
if not receiver_exists:
for agent in self.agents:
if agent.name == message["receiver"]:
agent.receive_message(message) # Agent接收消息
receiver_exists = True
break
if not receiver_exists:
print("接收者不存在")
except Exception as e:
print(f"处理消息出错: {e}")
这里用了多线程:MessageProcessor
是一个后台线程,不断从消息队列(queue.Queue
)中取消息,根据接收者(用户或AI Agent)转发。这样主线程(界面)不会被消息处理卡住,保证了操作流畅性。
3. AI智能体:会聊天的“AI好友”
最有意思的是AI智能体的实现!我封装了LLMClient
类(在ADKAgent.py
中),它集成了大语言模型(如Ollama或OpenAI),能接收用户消息并生成回复。
看LLMClient
的核心方法:
class LLMClient:
def __init__(self, name, model_type, MessageCenter):
self.name = name # AI好友的名字(如“历史老师”)
self.MessageCenter = MessageCenter # 关联消息中心
self.messages = queue.Queue() # 消息队列(接收用户消息)
# 启动消息处理线程
self.thread_message_server = threading.Thread(target=self.run_message_while)
self.thread_message_server.start()
async def run_message_while(self):
while True:
message = self.messages.get() # 从队列取用户消息(阻塞)
# 调用大模型生成回复
res, response_text = self.respond(message["content"], message["sender"])
# 通过消息中心回复用户
if res and self.MessageCenter:
self.MessageCenter.add_message({
"id": message["id"] + 1,
"type": "text",
"content": response_text,
"sender": self.name, # 发送者是当前AI
"receiver": message["sender"] # 接收者是用户
})
def respond(self, user_input, sender):
# 调用大语言模型生成回复(这里用了Google ADK库)
content = Content(role="user", parts=[Part.from_text(text=user_input)])
events = self.runner.run(user_id=sender, new_message=content)
# 提取模型回复的文本
response_text = "".join([part.text for event in events for part in event.content.parts if part.text])
return True, response_text
简单说,LLMClient
做了两件事:
- 接收用户消息(通过消息中心的队列);
- 调用大模型生成回复,再通过消息中心把回复发给用户。
这样,用户发送的消息会先到消息中心,消息中心转发给对应的AI智能体,AI生成回复后再通过消息中心回传给用户,形成完整的聊天闭环。
三、关键功能实现:添加/编辑AI好友
程序支持动态添加AI好友,这是怎么做到的?看ChatBox
类的create_new_agent
方法(右键菜单“创建Agent”的逻辑):
def create_new_agent(self):
# 1. 选择模型类型(Ollama或OpenAI)
model_type, ok0 = QInputDialog.getItem(self, "创建新Agent", "请选择模型类型:", ["ollama", "openai"])
if ok0:
# 2. 输入Agent名称(需符合命名规则)
agent_name, ok1 = QInputDialog.getText(self, "创建新Agent", "请输入Agent名称:")
if ok1:
# 3. 输入描述和提示词(决定AI的“人设”)
description, ok2 = QInputDialog.getText(self, "创建新Agent", "请输入Agent描述:", text="ollama chatbot.")
instruction, ok3 = QInputDialog.getText(self, "创建新Agent", "请输入提示词:", text="You are an unbiased AI.")
if ok0 and ok1 and ok2 and ok3:
# 4. 创建LLMClient实例并添加到消息中心
new_agent = LLMClient(agent_name, model_type, description, instruction, self.MessageCenter)
self.agents.append(new_agent)
self.add_contact_item(agent_name) # 好友列表添加新条目
self.MessageCenter.add_agent(new_agent) # 消息中心注册Agent
用户通过对话框一步步输入信息后,程序会创建一个LLMClient
实例(即新的AI好友),并把它添加到好友列表和消息中心。这样新AI就能接收和回复消息了!
四、遇到的坑:界面更新和线程安全
开发时遇到两个主要问题:
-
界面更新延迟:消息处理在后台线程,但界面更新(比如显示新消息)必须在主线程。解决方法是用PySide6的
Signal
(信号)机制——后台线程处理完消息后,通过信号通知主线程更新界面。
例子:MessageProcessor
类有一个message_processed = Signal(dict)
信号,消息处理完后发送信号,ChatBox
类连接这个信号,触发界面更新。 -
线程安全的消息队列:多个线程可能同时往消息队列里塞消息,需要保证线程安全。Python的
queue.Queue
是线程安全的,直接用它就可以避免竞态条件。
五、总结
这个项目虽然简单,但覆盖了桌面程序开发的多个关键点:界面布局、多线程消息处理、大模型集成。一个有用的组件是“消息中心”在通信系统中的核心作用——它就像邮局,负责把每封“消息邮件”准确送到收件人手里。 后续可以将他单独分离出来,挂到公网上,这样就可以向微信一样连接上网的所有pc上的Agent了。
后续我打算扩展这些功能:
- 支持文件传输(现在只能发文字);
- 添加AI好友的头像自定义;
- 支持语音输入和语音合成(用
pyttsx3
、tts等实现)。 - 加入知识库
- 加入工具等
如果你也对桌面程序或AI应用感兴趣,不妨动手试试!😊
-----------------本篇完------------------
PS.扩展阅读
————————————————————————————————————————
对于python机器人编程感兴趣的小伙伴,可以进入如下链接阅读相关咨询
ps1.六自由度机器人相关文章资源
(1) 对六自由度机械臂的运动控制及python实现(附源码)
ps2.四轴机器相关文章资源
(1) 文章:python机器人编程——用python实现一个写字机器人
(2)python机器人实战——0到1创建一个自动是色块机器人项目-CSDN直播
(3)博文《我从0开始搭建了一个色块自动抓取机器人,并实现了大模型的接入和语音控制-(上基础篇)》的vrep基础环境
(3)博文《我从0开始搭建了一个色块自动抓取机器人,并实现了大模型的接入和语音控制-(上基础篇)》的vrep基础环境
(4)实现了语音输入+大模型指令解析+机器视觉+机械臂流程打通
ps3.移动小车相关文章资源
(1)python做了一个极简的栅格地图行走机器人,到底能干啥?[第五弹]——解锁蒙特卡洛定位功能-CSDN博客
(2) 对应python资源:源码地址
(3)python机器人编程——差速AGV机器、基于视觉和预测控制的循迹、自动行驶(上篇)_agv编程-CSDN博客
(4)python机器人编程——差速AGV机器、基于视觉和预测控制的循迹、自动行驶(下篇)_agv路线规划原则python-CSDN博客
对应python及仿真环境资源:源码链接
ps3.wifi小车控制相关文章资源
web端配套资源源代码已经上传(竖屏版),下载地址
仿真配套资源已经上传:下载地址
web端配套资源源代码已经上传(横屏版),下载地址