# -*- 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. 签订入驻协议,办理入驻手续\n4. 安排办公场地,对接创业导师与孵化服务\n\n目前园区在园项目 158 家,累计孵化企业 208 余家。如需协助,可直接联系园区服务中心。", "tools": [{"type": "show_card", "params": {"card": "overview"}}], }, { "match": ["政策", "补贴", "优惠", "扶持", "减免", "奖励", "资助"], "reply": "园区政策服务覆盖「七位一体」中的政策维度:\n\n· 场地租金减免:符合条件的大学生创业项目可享受场地优惠\n· 创业补贴:协助对接省、市两级创业补贴与一次性创业资助\n· 税费优惠:对接小微企业所得税减免、增值税优惠等政策\n· 项目申报:指导高企认定(目前在园高新技术企业 32 家)、科技型中小企业备案\n\n更多政策细节可咨询园区政策服务窗口。", "tools": [], }, { "match": ["场地", "办公室", "工位", "租金", "收费", "面积", "多少钱", "价格"], "reply": "园区总建筑面积 1.2 万㎡,按功能划分为三个区域:\n\n· 加速区(A1–A12):成长型项目办公室,共 11 间独立办公室 + 1 间园区管理办公室\n· 国际区(I1–I7):面向国际合作的办公空间(7 间)\n· 成长区(G1–G8):初创团队成长空间(8 间)\n\n租金按创业项目阶段与政策给予差异化优惠,具体可到园区服务中心咨询。", "tools": [{"type": "show_card", "params": {"card": "zones"}}], }, { "match": ["企业", "公司", "名录", "名单", "入驻企业", "有哪些企业", "查企业"], "reply": "园区目前有 39 家入驻企业,分布在三个区域:\n\n· 加速区:云南派音人工智能科技、米勒克尔蓝宝石珠宝、云南宸中低空经济等 9 家\n· 国际区:仰光客厅、中越生物医疗、酷享野农AI农业等 7 家\n· 成长区:Facebook越南跨境电商、昆明云韵体育、云南星瑞航空等 8 家\n\n我已在屏幕上为您展示企业分布卡片。", "tools": [{"type": "show_card", "params": {"card": "companies"}}], }, { "match": ["融资", "投资", "资金", "贷款", "估值", "资本"], "reply": "园区融资服务包含:\n\n· 融资对接:定期组织路演与投资机构对接活动\n· 孵化估值:累计孵化企业估值约 5.2 亿元\n· 金融支持:协助对接银行创业贷款、政府创业担保贷款\n· 财务辅导:提供融资方案设计与商业计划书辅导", "tools": [], }, { "match": ["就业", "招聘", "岗位", "人才", "用工"], "reply": "园区累计带动就业 2,186 人(其中高校毕业生 1,680 人,实习岗位 506 个)。\n\n· 企业招聘:在驻企业持续发布岗位\n· 人才对接:与在昆高校共建实习实训基地\n· 创业带动:园区鼓励以创业带动就业", "tools": [], }, { "match": ["导师", "培训", "课程", "辅导", "孵化服务", "孵化器"], "reply": "园区配备创业导师 58 位,提供全周期孵化服务:\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· 加速区(蓝色):成长型项目独立办公室(A1–A12),在驻 9 家\n· 国际区(青色):国际合作与跨境业务(I1–I7),在驻 7 家\n· 成长区(绿色):初创团队共享空间(G1–G8),在驻 8 家\n\n园区管理办公室位于加速区 M 房间。", "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 赋能 + 综合服务」七位一体服务,在园项目 158 家,累计带动就业 2,186 人,累计营收 2.08 亿元。\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}