303 lines
9.3 KiB
Python
303 lines
9.3 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
"""
|
|||
|
|
龙虾议事厅 - 自然语言命令解析器
|
|||
|
|
让 AI 理解人类的自然语言命令
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import re
|
|||
|
|
from typing import Optional, Dict, Any
|
|||
|
|
from dataclasses import dataclass
|
|||
|
|
from enum import Enum
|
|||
|
|
|
|||
|
|
|
|||
|
|
class CommandType(Enum):
|
|||
|
|
"""命令类型"""
|
|||
|
|
CREATE_MEETING = "create_meeting"
|
|||
|
|
SEND_MESSAGE = "send_message"
|
|||
|
|
LIST_MEETINGS = "list_meetings"
|
|||
|
|
JOIN_MEETING = "join_meeting"
|
|||
|
|
GET_MESSAGES = "get_messages"
|
|||
|
|
UNKNOWN = "unknown"
|
|||
|
|
|
|||
|
|
|
|||
|
|
@dataclass
|
|||
|
|
class ParsedCommand:
|
|||
|
|
"""解析后的命令"""
|
|||
|
|
type: CommandType
|
|||
|
|
params: Dict[str, Any]
|
|||
|
|
confidence: float # 置信度 0-1
|
|||
|
|
|
|||
|
|
|
|||
|
|
class CommandInterpreter:
|
|||
|
|
"""
|
|||
|
|
自然语言命令解析器
|
|||
|
|
|
|||
|
|
支持的命令:
|
|||
|
|
- "创建一个会议,主题是 XXX"
|
|||
|
|
- "发送消息:XXX"
|
|||
|
|
- "查看会议列表"
|
|||
|
|
- "加入会议,邀请码 XXX"
|
|||
|
|
- "查看消息"
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
def __init__(self):
|
|||
|
|
# 命令模式匹配(简化版)
|
|||
|
|
self.patterns = {
|
|||
|
|
CommandType.CREATE_MEETING: [
|
|||
|
|
r'创建.*会议',
|
|||
|
|
r'新建.*会议',
|
|||
|
|
r'开.*会',
|
|||
|
|
r'组织.*会议',
|
|||
|
|
],
|
|||
|
|
CommandType.SEND_MESSAGE: [
|
|||
|
|
r'发送.*消息',
|
|||
|
|
r'发消息',
|
|||
|
|
r'说.*',
|
|||
|
|
r'告诉.*',
|
|||
|
|
],
|
|||
|
|
CommandType.LIST_MEETINGS: [
|
|||
|
|
r'查看.*列表',
|
|||
|
|
r'显示.*会议',
|
|||
|
|
r'有.*会议',
|
|||
|
|
r'我的会议',
|
|||
|
|
],
|
|||
|
|
CommandType.JOIN_MEETING: [
|
|||
|
|
r'加入.*',
|
|||
|
|
r'进入.*',
|
|||
|
|
r'参加会议',
|
|||
|
|
],
|
|||
|
|
CommandType.GET_MESSAGES: [
|
|||
|
|
r'查看.*消息',
|
|||
|
|
r'显示.*消息',
|
|||
|
|
r'有.*消息',
|
|||
|
|
r'读取消息',
|
|||
|
|
],
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def interpret(self, command: str) -> ParsedCommand:
|
|||
|
|
"""
|
|||
|
|
解析自然语言命令
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
command: 自然语言命令
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
ParsedCommand: 解析后的命令
|
|||
|
|
"""
|
|||
|
|
command = command.strip() # 不要转小写,保留中文
|
|||
|
|
|
|||
|
|
# 尝试匹配各种命令模式
|
|||
|
|
for cmd_type, patterns in self.patterns.items():
|
|||
|
|
for pattern in patterns:
|
|||
|
|
if re.search(pattern, command, re.IGNORECASE):
|
|||
|
|
params = self._extract_params(cmd_type, command)
|
|||
|
|
return ParsedCommand(
|
|||
|
|
type=cmd_type,
|
|||
|
|
params=params,
|
|||
|
|
confidence=0.8
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 未匹配到任何模式
|
|||
|
|
return ParsedCommand(
|
|||
|
|
type=CommandType.UNKNOWN,
|
|||
|
|
params={'raw': command},
|
|||
|
|
confidence=0.0
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
def _extract_params(self, cmd_type: CommandType, command: str) -> Dict[str, Any]:
|
|||
|
|
"""提取命令参数"""
|
|||
|
|
params = {}
|
|||
|
|
|
|||
|
|
if cmd_type == CommandType.CREATE_MEETING:
|
|||
|
|
# 提取会议主题
|
|||
|
|
topic_match = re.search(r'主题是 (.+?)(?:,|,|。|$)', command)
|
|||
|
|
if topic_match:
|
|||
|
|
params['topic'] = topic_match.group(1).strip()
|
|||
|
|
else:
|
|||
|
|
# 尝试其他模式
|
|||
|
|
topic_match = re.search(r'创建.*?会议 (?:,|,)?(.+?)(?:。|$)', command)
|
|||
|
|
if topic_match:
|
|||
|
|
params['topic'] = topic_match.group(1).strip()
|
|||
|
|
else:
|
|||
|
|
params['topic'] = '新会议'
|
|||
|
|
|
|||
|
|
elif cmd_type == CommandType.SEND_MESSAGE:
|
|||
|
|
# 提取消息内容
|
|||
|
|
content_match = re.search(r'(?::|:|说 | 告诉)(.+?)(?:。|$)', command)
|
|||
|
|
if content_match:
|
|||
|
|
params['content'] = content_match.group(1).strip()
|
|||
|
|
else:
|
|||
|
|
params['content'] = command
|
|||
|
|
|
|||
|
|
elif cmd_type == CommandType.JOIN_MEETING:
|
|||
|
|
# 提取邀请码
|
|||
|
|
code_match = re.search(r'(?:邀请码 | 码 |code)[::\s]?([A-Z0-9]+)', command, re.IGNORECASE)
|
|||
|
|
if code_match:
|
|||
|
|
params['invite_code'] = code_match.group(1).upper()
|
|||
|
|
|
|||
|
|
return params
|
|||
|
|
|
|||
|
|
|
|||
|
|
class AutonomousMeetingAgent:
|
|||
|
|
"""
|
|||
|
|
自主会议 Agent
|
|||
|
|
结合命令解析和 AI SDK,实现自主操作
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
def __init__(self, api_base: str = 'http://localhost:8000'):
|
|||
|
|
from meeting_ai_sdk import MeetingAIOperations
|
|||
|
|
self.api = MeetingAIOperations(api_base)
|
|||
|
|
self.interpreter = CommandInterpreter()
|
|||
|
|
self.current_meeting_id: Optional[str] = None
|
|||
|
|
|
|||
|
|
async def execute_command(self, command: str) -> str:
|
|||
|
|
"""
|
|||
|
|
执行自然语言命令
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
command: 自然语言命令
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
str: 执行结果
|
|||
|
|
"""
|
|||
|
|
# 解析命令
|
|||
|
|
parsed = self.interpreter.interpret(command)
|
|||
|
|
|
|||
|
|
if parsed.type == CommandType.UNKNOWN:
|
|||
|
|
return f"❌ 无法理解命令:{command}"
|
|||
|
|
|
|||
|
|
# 执行对应操作
|
|||
|
|
if parsed.type == CommandType.CREATE_MEETING:
|
|||
|
|
return await self._create_meeting(parsed.params)
|
|||
|
|
|
|||
|
|
elif parsed.type == CommandType.SEND_MESSAGE:
|
|||
|
|
return await self._send_message(parsed.params)
|
|||
|
|
|
|||
|
|
elif parsed.type == CommandType.LIST_MEETINGS:
|
|||
|
|
return await self._list_meetings()
|
|||
|
|
|
|||
|
|
elif parsed.type == CommandType.JOIN_MEETING:
|
|||
|
|
return await self._join_meeting(parsed.params)
|
|||
|
|
|
|||
|
|
elif parsed.type == CommandType.GET_MESSAGES:
|
|||
|
|
return await self._get_messages()
|
|||
|
|
|
|||
|
|
return "❌ 未知命令"
|
|||
|
|
|
|||
|
|
async def _create_meeting(self, params: Dict) -> str:
|
|||
|
|
"""创建会议"""
|
|||
|
|
topic = params.get('topic', '新会议')
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
await self.api.login('test', 'test123')
|
|||
|
|
meeting = await self.api.create_meeting(topic)
|
|||
|
|
self.current_meeting_id = meeting.id
|
|||
|
|
return (
|
|||
|
|
f"✅ 会议已创建!\n"
|
|||
|
|
f" 主题:{meeting.topic}\n"
|
|||
|
|
f" ID: {meeting.id}\n"
|
|||
|
|
f" 邀请码:{meeting.invite_code}"
|
|||
|
|
)
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"❌ 创建会议失败:{e}"
|
|||
|
|
|
|||
|
|
async def _send_message(self, params: Dict) -> str:
|
|||
|
|
"""发送消息"""
|
|||
|
|
content = params.get('content', '')
|
|||
|
|
|
|||
|
|
if not self.current_meeting_id:
|
|||
|
|
return "❌ 请先创建或加入会议"
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
message = await self.api.send_message(self.current_meeting_id, content)
|
|||
|
|
return f"✅ 消息已发送:{message.content}"
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"❌ 发送消息失败:{e}"
|
|||
|
|
|
|||
|
|
async def _list_meetings(self) -> str:
|
|||
|
|
"""获取会议列表"""
|
|||
|
|
try:
|
|||
|
|
await self.api.login('test', 'test123')
|
|||
|
|
meetings = await self.api.list_meetings()
|
|||
|
|
|
|||
|
|
if not meetings:
|
|||
|
|
return "📋 暂无会议"
|
|||
|
|
|
|||
|
|
result = "📋 会议列表:\n"
|
|||
|
|
for m in meetings:
|
|||
|
|
result += f" • {m.topic} (邀请码:{m.invite_code})\n"
|
|||
|
|
return result
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"❌ 获取会议列表失败:{e}"
|
|||
|
|
|
|||
|
|
async def _join_meeting(self, params: Dict) -> str:
|
|||
|
|
"""加入会议"""
|
|||
|
|
invite_code = params.get('invite_code')
|
|||
|
|
|
|||
|
|
if not invite_code:
|
|||
|
|
return "❌ 请提供邀请码"
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
await self.api.login('test', 'test123')
|
|||
|
|
meetings = await self.api.list_meetings()
|
|||
|
|
|
|||
|
|
for m in meetings:
|
|||
|
|
if m.invite_code == invite_code:
|
|||
|
|
self.current_meeting_id = m.id
|
|||
|
|
return f"✅ 已加入会议:{m.topic}"
|
|||
|
|
|
|||
|
|
return "❌ 未找到该邀请码的会议"
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"❌ 加入会议失败:{e}"
|
|||
|
|
|
|||
|
|
async def _get_messages(self) -> str:
|
|||
|
|
"""获取消息"""
|
|||
|
|
if not self.current_meeting_id:
|
|||
|
|
return "❌ 请先创建或加入会议"
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
messages = await self.api.get_messages(self.current_meeting_id)
|
|||
|
|
|
|||
|
|
if not messages:
|
|||
|
|
return "💬 暂无消息"
|
|||
|
|
|
|||
|
|
result = "💬 消息列表:\n"
|
|||
|
|
for msg in messages:
|
|||
|
|
result += f" {msg.sender_name}: {msg.content}\n"
|
|||
|
|
return result
|
|||
|
|
except Exception as e:
|
|||
|
|
return f"❌ 获取消息失败:{e}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============ 演示 ============
|
|||
|
|
|
|||
|
|
async def demo():
|
|||
|
|
"""演示自然语言命令"""
|
|||
|
|
agent = AutonomousMeetingAgent('http://localhost:8000')
|
|||
|
|
|
|||
|
|
print("=" * 60)
|
|||
|
|
print("🤖 自主会议 Agent - 自然语言命令演示")
|
|||
|
|
print("=" * 60)
|
|||
|
|
|
|||
|
|
# 测试命令
|
|||
|
|
commands = [
|
|||
|
|
"创建一个会议,主题是 Q2 计划讨论",
|
|||
|
|
"查看会议列表",
|
|||
|
|
"发送消息:大家好!这是 AI 自动发送的消息",
|
|||
|
|
"查看消息",
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
for cmd in commands:
|
|||
|
|
print(f"\n🗣️ 人类命令:{cmd}")
|
|||
|
|
result = await agent.execute_command(cmd)
|
|||
|
|
print(f"🤖 AI 执行:{result}")
|
|||
|
|
|
|||
|
|
print("\n" + "=" * 60)
|
|||
|
|
print("✅ 演示完成!")
|
|||
|
|
print("=" * 60)
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == '__main__':
|
|||
|
|
import asyncio
|
|||
|
|
asyncio.run(demo())
|