18d28be943
- 引入新的`docker-compose.yml`文件,便于后端和MQTT代理(EMQX)的部署。 - 更新多个组件中的API基本检索,使用函数进行动态解析。 - 加强了多个组件中API调用的错误处理和日志记录。 - 优化了AI聊天面板离线场景的回退响应。 - 更新DataScreen和MediaScreen组件中的数据显示和统计,以反映准确的指标。 - 重构MQTT连接逻辑,以支持动态凭证和客户端ID。
175 lines
11 KiB
Python
175 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""AI 助手工具调用引擎
|
|
后端收到对话 → 规则引擎判断意图 → 产出文字回复 + 工具调用列表
|
|
工具执行时通过 MQTT 广播 opc/display/command,前端(所有大屏)同步响应
|
|
工具:navigate(切页) / control(媒体控制) / alert(通知) / show_card(展示卡片)
|
|
"""
|
|
|
|
from .mqtt import hub
|
|
|
|
# ---------------- 工具执行 ----------------
|
|
|
|
def execute_tool(tool):
|
|
"""执行一个工具调用:发布 MQTT 控制指令,返回是否发布成功"""
|
|
t = tool.get("type")
|
|
params = tool.get("params") or {}
|
|
if t == "navigate":
|
|
return hub.publish_command("navigate", {"page": params.get("page", "home")}).get("published", False)
|
|
if t == "control":
|
|
action = params.get("action")
|
|
if action in ("play", "pause", "next", "prev"):
|
|
return hub.publish_command(action).get("published", False)
|
|
if action == "set_mode":
|
|
return hub.publish_command("set_mode", {"mode": params.get("mode", "auto")}).get("published", False)
|
|
return False
|
|
if t == "alert":
|
|
return hub.publish_command("alert", {"title": params.get("title", "提示"), "content": params.get("content", "")}).get("published", False)
|
|
if t == "show_card":
|
|
return hub.publish_command("show_card", params).get("published", False)
|
|
return False
|
|
|
|
|
|
def run_tools(tools):
|
|
"""执行一组工具,返回 [{type, ok}] 并汇总是否全部发布成功"""
|
|
results = []
|
|
all_ok = True
|
|
for tool in tools or []:
|
|
ok = bool(execute_tool(tool))
|
|
results.append({"type": tool.get("type"), "ok": ok})
|
|
all_ok = all_ok and ok
|
|
return results, all_ok
|
|
|
|
|
|
# ---------------- 意图 → 回复 + 工具 ----------------
|
|
|
|
PAGES = {
|
|
"home": "/", "数据大屏": "/", "首页": "/",
|
|
"twin": "/twin", "数字孪生": "/twin", "3d": "/twin", "孪生": "/twin",
|
|
"ai": "/ai", "ai助手": "/ai", "智能助手": "/ai",
|
|
"screen": "/screen", "媒体": "/screen", "轮播": "/screen", "媒体轮播": "/screen",
|
|
}
|
|
|
|
RULES = [
|
|
{
|
|
"match": ["入驻", "申请", "入孵", "入园", "如何加入", "怎样加入"],
|
|
"reply": "入驻流程(按《入驻管理规程》,每年原则上两次):\n\n1. 提出申请:提交《入驻申请表》《创业计划书》、身份证(外籍提供护照签证)、学历证明、营业执照、资质专利证书等材料\n2. 项目初审:服务机构初审,材料不齐一次性告知补全\n3. 入驻评审:从《昆明市就业创业导师库》抽取 3 名评审专家,路演答辩,量化打分 100 分制,80 分及以上通过\n4. 评审公示:报主管部门备案后在昆明市人社局官网公示\n5. 签署协议:签订《入驻孵化协议》,分配场地/工位,正式入驻\n\n按官方统计(2026年7月)园区实际入驻企业 38 家。咨询电话:18087174891。",
|
|
"tools": [{"type": "show_card", "params": {"card": "overview"}}],
|
|
},
|
|
{
|
|
"match": ["政策", "补贴", "优惠", "扶持", "减免", "奖励", "资助"],
|
|
"reply": "园区政策服务覆盖「七位一体」中的政策维度:\n\n· 场地租金减免:符合条件的大学生创业项目可享受场地优惠\n· 创业补贴:协助对接省、市两级创业补贴与一次性创业资助\n· 税费优惠:对接小微企业所得税减免、增值税优惠等政策\n· 项目申报:协助高新技术企业认定、科技型中小企业备案申报辅导\n\n更多政策细节可咨询园区政策服务窗口(电话:18087174891)。",
|
|
"tools": [],
|
|
},
|
|
{
|
|
"match": ["场地", "办公室", "工位", "租金", "收费", "面积", "多少钱", "价格"],
|
|
"reply": "园区建筑面积约 3000 ㎡(官方统计口径),可容纳约 50 个创业团队,按发展阶段设置四大孵化区域(《宣传册》):\n\n· OPC创业空间:AI技术支撑、数字经济/AI应用/软件开发/文创设计/电商直播等轻资产领域,拎包入驻,最长 2 年\n· 创业苗圃区:创意阶段未注册团队,开放式共享工位,最长 2 年\n· 孵化加速区:已注册初创企业,独立办公空间,基础 2 年可延 1 年(累计≤3年)\n· 国际创客区:归国/外籍留学生,个性化办公空间,参照加速区\n\n办公场地免费提供(含桌椅、文件柜、高速网络等基础配套),水电网络全配套、拎包入驻。",
|
|
"tools": [{"type": "show_card", "params": {"card": "zones"}}],
|
|
},
|
|
{
|
|
"match": ["企业", "公司", "名录", "名单", "入驻企业", "有哪些企业", "查企业"],
|
|
"reply": "按官方统计(2026年7月),园区实际入驻企业 38 家;《入驻企业信息表》收录本期入驻企业(项目)名录 39 家,包括云南派音人工智能科技(PineSound)、米勒克尔蓝宝石珠宝、云南宸中低空经济、仰光客厅、中越生物医疗、酷享野农AI农业、研X同行者网络等。\n\n行业分布:人工智能 7 家、跨境电商 5 家、教育培训 4 家、文旅康养 4 家、文化创意 4 家、生物医药 4 家、低空经济 3 家、现代农业 3 家、绿色环保 2 家、企业服务 2 家、新材料 1 家。\n\n我已在屏幕上为您展示企业分布卡片。",
|
|
"tools": [{"type": "show_card", "params": {"card": "companies"}}],
|
|
},
|
|
{
|
|
"match": ["融资", "投资", "资金", "贷款", "估值", "资本"],
|
|
"reply": "园区融资服务包含:\n\n· 融资对接:定期组织路演与投资机构对接活动\n· 经营成效:入驻团队累计经营收入约 2.19 亿元(省级绩效累计口径,截至2026年5月)\n· 金融支持:协助对接银行创业贷款、政府创业担保贷款\n· 财务辅导:提供融资方案设计与商业计划书辅导",
|
|
"tools": [],
|
|
},
|
|
{
|
|
"match": ["就业", "招聘", "岗位", "人才", "用工"],
|
|
"reply": "园区就业数据(口径说明):\n\n· 官方统计(2026年7月):当年累计带动就业 213 人\n· 省级绩效累计口径(截至2026年5月):累计带动就业 1,529 人(本年度 106 人)\n\n· 企业招聘:在驻企业持续发布岗位\n· 人才对接:与在昆高校共建实习实训基地\n· 创业带动:园区鼓励以创业带动就业",
|
|
"tools": [],
|
|
},
|
|
{
|
|
"match": ["导师", "培训", "课程", "辅导", "孵化服务", "孵化器"],
|
|
"reply": "园区组建创业指导专家团队 50 人(省级绩效材料口径),提供全周期孵化服务:\n\n· 一对一辅导:创业导师定期坐诊,覆盖商业模式、法律财税、市场营销\n· 培训课程:创业训练营、行业专题沙龙、政策解读会\n· 资源对接:技术、供应链、渠道等产业资源链接\n· 公共服务:工商注册、知识产权、法律咨询一站式代办",
|
|
"tools": [],
|
|
},
|
|
{
|
|
"match": ["AI", "模型", "算力", "tokens", "token", "工具", "智能", "赋能", "大模型"],
|
|
"reply": "园区 AI 赋能服务是「七位一体」的核心特色:\n\n· 大模型推理:接入 DeepSeek-V3、通义千问、智谱 GLM-4、豆包、讯飞星火等多模型\n· 工具调用:文档生成、数据查询、图像创作、代码执行、语音合成等智能工具\n· 算力与成本:实时提供 token 消耗统计与速率监控\n\n今日园区 AI 推理任务持续运行,服务节点 12/12 在线。",
|
|
"tools": [],
|
|
},
|
|
{
|
|
"match": ["加速区", "国际区", "成长区", "分区", "区域", "区别", "布局"],
|
|
"reply": "园区按创业企业(项目)发展阶段设置四大孵化区域(《宣传册》《入驻管理规程》):\n\n· OPC创业空间:AI技术支撑、轻资产领域,拎包入驻,孵化周期最长 2 年\n· 创业苗圃区:创意阶段未注册团队,共享工位,最长 2 年\n· 孵化加速区:已注册初创企业,独立办公,基础 2 年可延 1 年(累计≤3年)\n· 国际创客区:归国/外籍留学生,个性化空间,参照加速区\n\n我已在屏幕上为您展示分区介绍卡片。",
|
|
"tools": [{"type": "show_card", "params": {"card": "zones"}}],
|
|
},
|
|
{
|
|
"match": ["切", "去", "打开", "显示", "进入"],
|
|
"reply": None, # 由下方页面/控制规则补充
|
|
},
|
|
{
|
|
"match": ["你好", "您好", "hi", "hello", "嗨", "在吗"],
|
|
"reply": "您好!我是 OPC 园区 AI 智能助手。\n\n可以问我:入驻流程、政策扶持、场地收费、AI 赋能、企业名录、融资服务等问题;也可以让我「切换到数字孪生页」「打开媒体轮播」或「展示企业卡片」。",
|
|
"tools": [],
|
|
},
|
|
{
|
|
"match": ["谢谢", "感谢", "好的", "明白"],
|
|
"reply": "不客气,随时为您服务。您也可以让我展示园区数据卡片,或切换到任意展示页面。",
|
|
"tools": [],
|
|
},
|
|
]
|
|
|
|
DEFAULT_REPLY = "园区提供「空间 + 孵化 + 融资 + 政策 + 资源 + AI 赋能 + 综合服务」七位一体服务。\n\n按官方统计(2026年7月):实际入驻企业 38 家,当年累计带动就业 213 人,当年生产经营总额 252.15 万元;省级绩效累计口径(截至2026年5月):累计孵化企业 181 家、累计带动就业 1,529 人、累计经营收入约 2.19 亿元。\n\n您可以这样问我:\n· 如何申请入驻园区?\n· 展示入驻企业卡片\n· 切换到数字孪生页面"
|
|
|
|
|
|
def _detect_page(text):
|
|
for key, path in PAGES.items():
|
|
if key in text:
|
|
return path
|
|
return None
|
|
|
|
|
|
def _detect_control(text):
|
|
if any(k in text for k in ["播放", "继续播放", "开始播放"]):
|
|
return "play"
|
|
if any(k in text for k in ["暂停", "停止播放"]):
|
|
return "pause"
|
|
if any(k in text for k in ["下一个", "下一张", "下一屏", "切换下一"]):
|
|
return "next"
|
|
if any(k in text for k in ["上一个", "上一张", "上一屏", "切换上一"]):
|
|
return "prev"
|
|
return None
|
|
|
|
|
|
def run_chat(messages):
|
|
"""输入对话消息列表([{"role","content"}]),返回 {reply, tools}"""
|
|
text = ""
|
|
for m in reversed(messages or []):
|
|
if m.get("role") in ("user", "me"):
|
|
text = (m.get("content") or "").strip()
|
|
break
|
|
|
|
reply = None
|
|
tools = []
|
|
|
|
# 1) 页面切换意图(优先级最高)
|
|
page = _detect_page(text)
|
|
if page:
|
|
label = {"/": "数据大屏", "/twin": "数字孪生", "/ai": "AI 助手", "/screen": "媒体轮播"}.get(page, page)
|
|
reply = f"好的,已为您切换到「{label}」页面。"
|
|
tools = [{"type": "navigate", "params": {"page": page}}]
|
|
return {"reply": reply, "tools": tools}
|
|
|
|
# 2) 媒体控制意图
|
|
ctrl = _detect_control(text)
|
|
if ctrl:
|
|
names = {"play": "播放", "pause": "暂停", "next": "切换下一项", "prev": "切换上一项"}
|
|
reply = f"好的,已执行:{names[ctrl]}。"
|
|
tools = [{"type": "control", "params": {"action": ctrl}}]
|
|
return {"reply": reply, "tools": tools}
|
|
|
|
# 3) 知识库规则
|
|
for rule in RULES:
|
|
if any(k in text for k in rule["match"]):
|
|
reply = rule["reply"]
|
|
tools = rule["tools"]
|
|
break
|
|
|
|
if reply is None:
|
|
reply = DEFAULT_REPLY
|
|
|
|
# 工具已在后端通过 MQTT 广播;返回值供请求端本地同步执行
|
|
return {"reply": reply, "tools": tools}
|