This commit is contained in:
wtz
2026-02-24 17:41:04 +08:00
commit fc32cab12b
9 changed files with 1239 additions and 0 deletions

387
client_hardware_api.py Normal file
View File

@@ -0,0 +1,387 @@
import modes as mc
import tkinter as tk
from tkinter import ttk
import threading
import base_mode as bm
IS_BOARD = True
try:
from pinpong.board import Board, Pin, NeoPixel
from unihiker import GUI
gui = GUI()
except ModuleNotFoundError:
print("警告:非行空板环境")
IS_BOARD = False
import time
class XingkongBoardBase:
def __init__(self):
pass
def on_btn_click(self, callback):
"""
按下机外的那个按钮。
该按钮按键流程(必须辩论模式):
1. 进入立论模式(若是正方,则直接说话;若是反方,则直接开始录音)
2. 当本方为正方时,开始录(反方)音;为反方时,停止录(正方的)音
3. 当本方为正方时,停止录(反方)音;为反方时,开始说话
4. 当本方为正方时,进入进入自由辩论模式;为反方时,也是进入自由辩论模式(请确保灯光为绿)
5. 关闭自由辩论模式
6. 进入总结陈词模式。为正方时将直接开始录音;为反方时将直接输出语音,完成后辩论模式结束
7. 正方停止录音
8. 正方输出语音。完成后辩论模式结束
:param callback: 当按下时的回调函数
:return:
"""
pass
def on_btn_dialog_click(self, callback):
"""
按下“对话模式”按钮
:param callback: 当按下时的回调函数
:return:
"""
pass
def on_btn_debate_click(self, callback):
"""
按下“辩论模式”按钮
:param callback: 当按下时的回调函数
:return:
"""
pass
def on_btn_stop_click(self, callback):
"""
按下“停止”按钮
:param callback: 当按下时的回调函数
:return:
"""
pass
def set_light_color(self, color):
"""
设置灯光颜色。
在对话模式和自由辩论模式不设置灯光颜色。
red: 正在处理一些事件,此时不能点击机外按钮
green: 准备就绪,可以点击机外按钮
blue: 正在录音
orange: 成功进入辩论模式和自由辩论
:param color: "red"|"green"|"blue"|"orange"
:return:
"""
pass
SYSTEM = \
"""
你是人大附中经开学校金鹏科技团开发的辩论智能体机器人,名叫人开一号。
这个机器人运用了流式语音识别、大语言模型、流式语音合成等技术。
当你被要求介绍自己时,请简要介绍你的功能和技术实现。
请注意你的回答将被直接通过语音合成输出因此你不能输出不适合TTS的内容。
"""
class Unihiker_Board(XingkongBoardBase):
def __init__(self):
super().__init__()
Board().begin()
# self.gui=GUI()
self.btn21 = Pin(Pin.P21, Pin.IN)
self.pin23 = Pin(Pin.D23)
self.np1 = NeoPixel(self.pin23, 22)
self.np1.brightness(150)
gui.add_button(x=0, y=290, w=80, h=30, text="对话", origin='nw', onclick=self._trigger_dialog_click)
gui.add_button(x=80, y=290, w=80, h=30, text="辩论", origin='nw', onclick=self._trigger_debate_click)
gui.add_button(x=160, y=290, w=80, h=30, text="停止", origin='nw', onclick=self._trigger_stop_click)
self.btn_count = 0
self.btn_callback = None
self.dialog_callback = None
self.debate_callback = None
self.stop_callback = None
def on_btn_click(self, callback):
self.btn_callback = callback
def on_btn_dialog_click(self, callback):
self.dialog_callback = callback
def on_btn_debate_click(self, callback):
self.debate_callback = callback
def on_btn_stop_click(self, callback):
self.stop_callback = callback
def set_light_color(self, color):
if color == "red":
self.np1.range_color(0, 21, 0xFF0000)
if color == "green":
self.np1.range_color(0, 21, 0x00FF00)
if color == "blue":
self.np1.range_color(0, 21, 0x0000FF)
if color == "orange":
self.np1.range_color(0, 21, 0xFFFF00)
def _trigger_btn_click(self):
if self.btn_callback:
threading.Thread(target=self.btn_callback, daemon=True).start()
def _trigger_dialog_click(self):
if self.dialog_callback:
threading.Thread(target=self.dialog_callback, daemon=True).start()
def _trigger_debate_click(self):
if self.debate_callback:
threading.Thread(target=self.debate_callback, daemon=True).start()
def _trigger_stop_click(self):
if self.stop_callback:
threading.Thread(target=self.stop_callback, daemon=True).start()
def btn_click_check(self):
while True:
if self.btn21.read_digital() == 0:
while self.btn21.read_digital() == 0:
pass
self._trigger_btn_click()
def run(self):
threading.Thread(target=self.btn_click_check, daemon=True).start()
while True:
time.sleep(1)
class Robot:
def __init__(self, board: XingkongBoardBase):
self.modes = dict()
self.btn_count = 0
self.board = board
self.side = ""
self.topic = ""
self.opinion = ""
self.last_prompt = ""
self.session_id = None
def register_mode(self, modename: str, mode: bm.Mode):
self.modes[modename] = mode
def run_mode(self, modename):
self.modes[modename].run()
def stop_mode(self, modename):
self.modes[modename].stop()
del self.modes[modename]
def get_mode(self, modename):
return self.modes[modename]
def stop_all(self):
for mode in self.modes.values():
mode.stop()
self.modes.clear()
def dialog(self):
self.stop_all()
self.board.set_light_color("orange")
dialog_mode = mc.DialogMode(system_prompt=SYSTEM)
self.register_mode("dialog", dialog_mode)
self.run_mode("dialog")
def set_debate_config(self, side, topic, opinion):
self.side = side
self.topic = topic
self.opinion = opinion
def debate(self):
self.stop_all()
self.board.set_light_color("orange")
self.btn_count = 0
if self.side == "正方":
self.board.on_btn_click(self._btn_right_callback)
else:
self.board.on_btn_click(self._btn_against_callback)
def on_cancel(self):
self.stop_all()
self.board.set_light_color("green")
def _btn_right_callback(self):
self.btn_count += 1
if self.btn_count == 1:
self.board.set_light_color("red")
self.register_mode("make_point", mc.MakePointMode(side=self.side, topic=self.topic, opinion=self.opinion))
self.run_mode("make_point")
self.board.set_light_color("green")
elif self.btn_count == 2:
md: mc.MakePointMode = self.get_mode("make_point")
self.board.set_light_color("blue")
md.start_record()
elif self.btn_count == 3:
md: mc.MakePointMode = self.get_mode("make_point")
self.board.set_light_color("red")
md.stop_record()
self.board.set_light_color("green")
self.last_prompt = md.ready_next()
elif self.btn_count == 4:
self.board.set_light_color("red")
md: mc.MakePointMode = self.get_mode("make_point")
self.session_id = md.session_id
self.stop_mode("make_point")
self.register_mode("free_debate", mc.FreeDebateMode(side=self.side, topic=self.topic, opinion=self.opinion,
last_prompt=self.last_prompt,
session_id=self.session_id))
self.run_mode("free_debate")
self.board.set_light_color("orange")
elif self.btn_count == 5:
self.board.set_light_color("red")
md: mc.FreeDebateMode = self.get_mode("free_debate")
self.session_id = md.session_id
self.stop_mode("free_debate")
self.board.set_light_color("green")
elif self.btn_count == 6:
self.board.set_light_color("red")
self.register_mode("end_debate", mc.EndDebateMode(side=self.side, topic=self.topic, opinion=self.opinion,
session_id=self.session_id))
self.run_mode("end_debate")
self.board.set_light_color("blue")
elif self.btn_count == 7:
md: mc.EndDebateMode = self.get_mode("end_debate")
md.stop_record()
self.board.set_light_color("green")
elif self.btn_count == 8:
self.board.set_light_color("red")
md: mc.EndDebateMode = self.get_mode("end_debate")
md.start_talk()
self.board.set_light_color("green")
self.stop_mode("end_debate")
def _btn_against_callback(self):
self.btn_count += 1
if self.btn_count == 1:
self.board.set_light_color("blue")
self.register_mode("make_point", mc.MakePointMode(side=self.side, topic=self.topic, opinion=self.opinion))
self.run_mode("make_point")
elif self.btn_count == 2:
md: mc.MakePointMode = self.get_mode("make_point")
self.board.set_light_color("red")
md.stop_record()
self.board.set_light_color("green")
elif self.btn_count == 3:
self.board.set_light_color("red")
md: mc.MakePointMode = self.get_mode("make_point")
md.ready_next()
self.board.set_light_color("green")
elif self.btn_count == 4:
self.board.set_light_color("red")
md: mc.MakePointMode = self.get_mode("make_point")
self.session_id = md.session_id
self.stop_mode("make_point")
self.register_mode("free_debate", mc.FreeDebateMode(side=self.side, topic=self.topic, opinion=self.opinion,
session_id=self.session_id))
self.run_mode("free_debate")
self.board.set_light_color("green")
elif self.btn_count == 5:
self.board.set_light_color("red")
md: mc.FreeDebateMode = self.get_mode("free_debate")
self.session_id = md.session_id
self.stop_mode("free_debate")
self.board.set_light_color("green")
elif self.btn_count == 6:
self.board.set_light_color("red")
self.register_mode("end_debate", mc.EndDebateMode(side=self.side, topic=self.topic, opinion=self.opinion,
session_id=self.session_id))
self.run_mode("end_debate")
md: mc.EndDebateMode = self.get_mode("end_debate")
md.start_talk()
def run(self):
self.board.on_btn_dialog_click(self.dialog)
self.board.on_btn_debate_click(self.debate)
self.board.on_btn_stop_click(self.on_cancel)
class MockXingkongBoard(XingkongBoardBase):
def __init__(self):
super().__init__()
self.root = tk.Tk()
self.root.title("模拟控制台")
self.root.geometry("300x200")
# 灯光显示
self.light = tk.Label(self.root, width=10, height=5, bg="gray")
self.light.pack(pady=10)
# 按钮布局
btn_frame = ttk.Frame(self.root)
btn_frame.pack(pady=10)
# 机外按钮
ttk.Button(btn_frame, text="机外按钮", command=self._trigger_btn_click).grid(row=0, column=0, padx=5)
# 功能按钮
ttk.Button(btn_frame, text="对话模式", command=self._trigger_dialog_click).grid(row=1, column=0, padx=5)
ttk.Button(btn_frame, text="辩论模式", command=self._trigger_debate_click).grid(row=1, column=1, padx=5)
ttk.Button(btn_frame, text="停止", command=self._trigger_stop_click).grid(row=1, column=2, padx=5)
# 回调存储
self.btn_callback = None
self.dialog_callback = None
self.debate_callback = None
self.stop_callback = None
def on_btn_click(self, callback):
self.btn_callback = callback
def on_btn_dialog_click(self, callback):
self.dialog_callback = callback
def on_btn_debate_click(self, callback):
self.debate_callback = callback
def on_btn_stop_click(self, callback):
self.stop_callback = callback
def set_light_color(self, color):
# 仅设置颜色,不添加任何模式判断
self.light.config(bg=color)
def _trigger_btn_click(self):
# 直接触发回调,高耗时操作放线程
if self.btn_callback:
threading.Thread(target=self.btn_callback, daemon=True).start()
def _trigger_dialog_click(self):
if self.dialog_callback:
threading.Thread(target=self.dialog_callback, daemon=True).start()
def _trigger_debate_click(self):
if self.debate_callback:
threading.Thread(target=self.debate_callback, daemon=True).start()
def _trigger_stop_click(self):
if self.stop_callback:
threading.Thread(target=self.stop_callback, daemon=True).start()
def run(self):
self.root.mainloop()
if __name__ == '__main__':
board = Unihiker_Board() if IS_BOARD else MockXingkongBoard()
robot = Robot(board)
robot.set_debate_config(
"反方",
"利用基因技术复活已灭绝物种(反灭绝工程)是生态责任还是资源浪费",
"利用基因技术复活已灭绝物种(反灭绝工程)是资源浪费"
) if IS_BOARD else robot.set_debate_config(
"反方",
"量子计算机的实用化是否会首先对现有加密体系构成致命威胁",
"量子计算机的实用化是否不会首先对现有加密体系构成致命威胁"
)
robot.run()
board.run()