Files
RKOneAIDebate/client_hardware_api.py
2026-02-24 17:41:04 +08:00

388 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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()