我有一个ai助手主程序,现在我需要制作ui部分,我有一个api工具
# api_server.py
import threading
import time
from flask import Flask, request, jsonify
from werkzeug.serving import make_server
from flask_cors import CORS # pip install flask-cors
# 假设这些函数来自你的主程序模块
# from Progress.app import get_ai_assistant, get_task_executor, get_tts_engine, get_voice_recognizer
# --- 全局状态共享 ---
current_status = {
"is_listening": False,
"is_tts_playing": False,
"current_timeout": 8.0,
"last_command_result": None,
"timestamp": int(time.time())
}
# --- 模拟服务实例(实际项目中应替换为真实对象)---
class MockAssistant:
def process_voice_command(self, text):
return {"action": "mock_action", "target": text}
class MockExecutor:
def execute_task_plan(self, plan):
return {"success": True, "message": f"已执行 {plan['target']}", "data": {}}
class MockTTS:
def speak(self, text, async_mode=False):
print(f"[TTS] 正在播报: {text}")
if not async_mode:
time.sleep(1) # 模拟播放延迟
else:
def _async_play():
time.sleep(1)
threading.Thread(target=_async_play, daemon=True).start()
class MockRecognizer:
def start_listening(self):
global current_status
current_status["is_listening"] = True
current_status["timestamp"] = int(time.time())
print("🎙️ 开始监听用户语音...")
def stop_listening(self):
global current_status
current_status["is_listening"] = False
current_status["timestamp"] = int(time.time())
# 实例化模拟组件(上线时替换为真实导入)
assistant = MockAssistant()
executor = MockExecutor()
tts_engine = MockTTS()
recognizer = MockRecognizer()
class APIServer:
def __init__(self):
self.app = Flask(__name__)
CORS(self.app) # ✅ 启用跨域支持
self.server = None
self.thread = None
self.running = False
self._add_routes()
def _update_status(self, **kwargs):
"""更新全局状态"""
current_status.update(kwargs)
current_status["timestamp"] = int(time.time())
def _add_routes(self):
"""注册所有 API 路由"""
# 1. GET /api/health - 健康检查
@self.app.route('/api/health', methods=['GET'])
def health():
return jsonify({
"status": "ok",
"service": "ai_assistant",
"timestamp": int(time.time())
})
# 2. GET /api/status - 查询当前状态
@self.app.route('/api/status', methods=['GET'])
def status():
return jsonify({**current_status})
# 3. POST /api/start - 启动助手
@self.app.route('/api/start', methods=['POST'])
def start():
# 可以触发一些初始化逻辑
self._update_status(is_listening=True)
return jsonify({
"status": "running",
"message": "AI 助手已就绪",
"features": ["voice", "tts", "file", "app_control"],
"timestamp": int(time.time())
})
# 4. POST /api/command - 执行用户指令
@self.app.route('/api/command', methods=['POST'])
def handle_command():
try:
data = request.get_json()
if not data or 'text' not in data:
return jsonify({
"success": False,
"response_to_user": "未收到有效指令"
}), 400
text = data['text']
context = data.get('context', {})
options = data.get('options', {})
should_speak = options.get('should_speak', True)
return_plan = options.get('return_plan', False)
print(f"📩 收到命令: '{text}' | 上下文: {context}")
# 👇 调用 AI 助手核心逻辑(请替换为你的真实模块)
# from Progress.app import get_ai_assistant, get_task_executor, get_tts_engine
# assistant = get_ai_assistant()
# executor = get_task_executor()
# tts = get_tts_engine()
decision = assistant.process_voice_command(text)
result = executor.execute_task_plan(decision)
ai_reply = result["message"]
if not result["success"] and not ai_reply.startswith("抱歉"):
ai_reply = f"抱歉,{ai_reply}"
# 更新状态:正在处理
self._update_status(
is_processing=True,
last_command_result={"success": result["success"], "message": ai_reply, "operation": decision.get("action")}
)
# 异步播报
if should_speak:
self._update_status(is_tts_playing=True)
tts_engine.speak(ai_reply, async_mode=True)
# 模拟 TTS 结束后恢复状态
def _finish_tts():
time.sleep(1)
self._update_status(is_tts_playing=False)
threading.Thread(target=_finish_tts, daemon=True).start()
# 构造响应
response_data = {
"success": result["success"],
"response_to_user": ai_reply,
"operation": decision.get("action"),
"details": result,
"should_speak": should_speak,
"timestamp": int(time.time()),
}
if return_plan:
response_data["plan"] = decision
self._update_status(is_processing=False)
return jsonify(response_data), 200
except Exception as e:
print(f"❌ 处理命令失败: {e}")
return jsonify({
"success": False,
"error": str(e),
"timestamp": int(time.time())
}), 500
# 5. POST /api/tts/speak - 主动播报语音
@self.app.route('/api/tts/speak', methods=['POST'])
def speak():
try:
data = request.get_json()
if not data or 'text' not in data:
return jsonify({"error": "Missing 'text'"}), 400
text = data['text']
print(f"[TTS] 请求播报: {text}")
self._update_status(is_tts_playing=True)
tts_engine.speak(text, async_mode=True)
def _finish():
time.sleep(1)
self._update_status(is_tts_playing=False)
threading.Thread(target=_finish, daemon=True).start()
return jsonify({
"status": "speaking",
"text": text,
"timestamp": int(time.time())
})
except Exception as e:
return jsonify({"error": str(e)}), 500
# 6. POST /api/wakeup - 远程唤醒
@self.app.route('/api/wakeup', methods=['POST'])
def wakeup():
try:
data = request.get_json() or {}
device = data.get("device", "unknown")
location = data.get("location", "unknown")
print(f"🔔 远程唤醒信号来自 {device} @ {location}")
# 播放提示音(可通过 pygame 或 winsound 实现)
print("💡 滴—— 唤醒成功!")
# 设置为倾听模式
recognizer.start_listening()
self._update_status(is_listening=True)
return jsonify({
"status": "ready",
"message": "已进入倾听模式",
"timestamp": int(time.time())
})
except Exception as e:
return jsonify({"error": str(e)}), 500
def start(self, host="127.0.0.1", port=5000, debug=False):
"""启动 API 服务(非阻塞)"""
if self.running:
print("⚠️ API 服务器已在运行")
return
try:
self.server = make_server(host, port, self.app)
self.running = True
def run_flask():
print(f"🌐 AI 助手 API 已启动 → http://{host}:{port}/api")
self.server.serve_forever()
self.thread = threading.Thread(target=run_flask, daemon=True)
self.thread.start()
except Exception as e:
print(f"❌ 启动 API 服务失败: {e}")
raise
def stop(self):
"""关闭 API 服务"""
if not self.running:
return
print("🛑 正在关闭 API 服务...")
try:
self.server.shutdown()
except:
pass
finally:
self.running = False
if self.thread:
self.thread.join(timeout=3)
if self.thread.is_alive():
print("⚠️ API 服务线程未能及时退出")
print("✅ API 服务已关闭")
# -----------------------------
# 使用示例
# -----------------------------
if __name__ == '__main__':
api = APIServer()
api.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
api.stop()
和一个api文档
# 🌐 AI 助手 API 接口文档
服务地址: http://127.0.0.1:5000/api
协议: HTTP/HTTPS
编码: UTF-8
内容类型: application/json
跨域支持: ✅ 已启用 CORS
# 🔑 认证方式(可选)暂时不加密钥
目前为本地服务,默认信任内网调用。
如需安全增强,请添加:
http
X-API-Key: your-secret-token
或使用 HTTPS + IP 白名单。
# 📚 接口列表
路径 方法 功能
/health GET 健康检查
/status GET 获取当前运行状态
/start POST 启动或唤醒助手
/command POST 发送自然语言指令
/tts/speak POST 主动播放语音
/wakeup POST 远程唤醒信号
1. GET /api/health - 健康检查
💡 描述
检查后端服务是否正常运行。
请求示例
http
GET /api/health
成功响应
{
"status": "ok",
"service": "ai_assistant",
"timestamp": 1719876543
}
字段 类型 说明
status string 固定为 "ok" 表示存活
service string 服务名称
timestamp number 当前时间戳
✅ 用途:Flutter App 启动时探测服务是否存在。
2. GET /api/status - 查询当前状态
💡 描述
获取语音识别器和 TTS 的实时状态。
请求示例
http
GET /api/status
成功响应
{
"is_listening": true,
"is_tts_playing": false,
"current_timeout": 8,
"last_command_result": {
"success": true,
"message": "正在播放音乐",
"operation": "play_music"
},
"timestamp": 1719876543
}
字段 类型 说明
is_listening boolean 是否正在监听麦克风
is_tts_playing boolean 是否正在播报语音
current_timeout float 下一次监听超时时间(秒)
last_command_result object 上一条命令执行结果
timestamp number 时间戳
📌 用途:
控制前端 UI 显示“AI 正在说话”
防止冲突收音
3. POST /api/start - 启动助手
💡 描述
用于前端点击“启动”按钮时触发。如果服务已运行则返回状态。
⚠️ 注意:不能真正“启动一个进程”,但可以确认服务就绪。
请求示例
http
POST /api/start
Content-Type: application/json
json
{}
成功响应
{
"status": "running",
"message": "AI 助手已就绪",
"features": ["voice", "tts", "file", "app_control"],
"timestamp": 1719876543
}
字段 类型 说明
status string "running"
message string 提示信息
features array 支持的功能列表
timestamp number 当前时间戳
4. POST /api/command - 执行用户指令(核心接口)
💡 描述
发送一条自然语言命令,走完整 AI 决策 → 执行 → 播报流程。
请求参数
{
"text": "打开记事本",
"context": {
"user_id": "U123",
"device": "phone",
"location": "bedroom"
},
"options": {
"should_speak": true,
"return_plan": false
}
}
参数 类型 必填 说明
text string ✅ 用户输入的自然语言文本
context object ❌ 上下文信息(可用于日志追踪)
options.should_speak boolean ❌ 是否让 TTS 播报结果(默认 true)
options.return_plan boolean ❌ 是否返回详细的执行计划(调试用)
成功响应
{
"success": true,
"response_to_user": "已为您打开记事本",
"operation": "open_app",
"details": {
"app_name": "notepad"
},
"should_speak": true,
"plan": { ... }, // 仅当 return_plan=true 时存在
"timestamp": 1719876543
}
字段 类型 说明
success boolean 执行是否成功
response_to_user string 要对用户说的话
operation string 主要操作类型(如 open_app)
details object 操作详情
should_speak boolean 是否应播报语音
plan object 完整任务计划(仅当开启时返回)
timestamp number 时间戳
错误响应(400 Bad Request)
{
"success": false,
"response_to_user": "未收到有效指令"
}
5. POST /api/tts/speak - 主动播报语音
💡 描述
不经过 AI 决策,直接让助手说出一句话。
请求示例
http
POST /api/tts/speak
Content-Type: application/json
json
{
"text": "您的会议将在五分钟后开始"
}
成功响应
{
"status": "speaking",
"text": "您的会议将在五分钟后开始",
"timestamp": 1719876543
}
字段 类型 说明
status string "speaking"
text string 正在播报的内容
timestamp number 时间戳
📌 用途:通知、提醒、异常报警等场景。
6. POST /api/wakeup - 远程唤醒
💡 描述
当手机检测到“小智小智”唤醒词后,发送此请求通知电脑准备接收指令。
请求示例
http
POST /api/wakeup
Content-Type: application/json
设备位置
{
"device": "phone",
"location": "living_room"
}
成功响应
{
"status": "ready",
"message": "已进入倾听模式",
"timestamp": 1719876543
}
后端行为
设置 recognizer.is_listening = True
可播放提示音“滴”一声表示唤醒成功
📌 注意:建议配合 /api/command 使用,唤醒后再发命令。
🧪 测试建议(使用 curl)
# 检查健康
curl http://127.0.0.1:5000/api/health
# 唤醒
curl -X POST http://127.0.0.1:5000/api/wakeup
# 发送命令
curl -X POST http://127.0.0.1:5000/api/command \
-H "Content-Type: application/json" \
-d '{"text": "打开浏览器"}'
# 播报语音
curl -X POST http://127.0.0.1:5000/api/tts/speak \
-H "Content-Type: application/json" \
-d '{"text": "你好,我是你的语音助手"}'
✅ 最佳实践建议
项目 建议
🔐 安全性 生产环境加 Token 或 HTTPS
📦 打包部署 使用 PyInstaller 打包成 .exe 并设置开机自启
🔄 状态同步 前端轮询 /api/status 判断是否可交互
📈 日志记录 记录所有 /api/command 调用用于调试
🧭 唤醒策略 手机端做离线唤醒词检测,再发 /api/wakeup
帮我选择GUI框架,并给我所有代码
最新发布