用本地大模型解析智能家居语音指令:构建一个离线可用的文本控制助手
🧠 背景介绍
随着智能家居设备的普及,用户希望用一句话完成对家电的控制。虽然很多系统依赖云端大模型服务,但我们也可以通过本地部署实现一个完全离线运行的智能控制助手。
本文将带你一步步实现一个基于本地大模型的智能家居控制系统,它具备以下能力:
- ✅ 接收文字输入
- ✅ 意图识别 + RAG 检索物模型
- ✅ 构造 Few-Shot 提示词引导输出
- ✅ 使用本地大模型生成结构化 JSON 控制指令
- ✅ JSON 校验确保输出合法
- ✅ 完全无需联网,可在 PC 或嵌入式设备上运行
📚 所需知识准备
技术 | 描述 |
---|---|
大模型 | 支持 GGUF 格式的本地模型(如 Qwen2.5-0.5B.Q2_K.gguf) |
意图识别 | 基于关键词匹配的轻量级规则模块 |
RAG 检索 | 不使用向量数据库,而是基于规则匹配设备类型 |
JSON Schema 校验 | 确保输出符合标准物模型定义 |
Java | 实现核心逻辑,适用于桌面 App 或 Electron 内部调用 |
🛠️ 整体架构设计(简化版)—
🧱 核心模块详解
1️⃣ 物模型知识库(device_knowledge.json
)
[{"device_type": "light","description": "智能灯泡","schema": {"properties": {"power": {"type": "switch", "values": ["on", "off"]},"brightness": {"type": "int", "min": 0, "max": 100}}}},{"device_type": "ac","description": "空调","schema": {"properties": {"power": {"type": "switch", "values": ["on", "off"]},"temperature": {"type": "int", "min": 16, "max": 30},"mode": {"type": "enum", "values": ["cool", "heat", "fan", "dry"]}}}
]
这个文件定义了所有设备的标准控制属性,供 RAG 检索使用。
2️⃣ 意图识别模块(IntentRecognizer.java)
import java.util.*;public class IntentRecognizer {private static final Map<String, String> INTENT_KEYWORDS = new HashMap<>();static {INTENT_KEYWORDS.put("light", "灯 亮度 灯光");INTENT_KEYWORDS.put("ac", "空调 温度 制冷 制热 冷气 热风");INTENT_KEYWORDS.put("curtain", "窗帘 开启 打开 关闭 拉上 拉开");INTENT_KEYWORDS.put("fan", "风扇 风速 摆头 摇头");INTENT_KEYWORDS.put("tv", "电视 音量 静音 影音");INTENT_KEYWORDS.put("lock", "门锁 上锁 解锁 密码");INTENT_KEYWORDS.put("humidifier", "加湿器 湿度 自动模式");}public static String recognizeIntent(String query) {for (Map.Entry<String, String> entry : INTENT_KEYWORDS.entrySet()) {String intent = entry.getKey();String keywords = entry.getValue();for (String word : keywords.split(" ")) {if (query.contains(word)) {return intent;}}}return "other";}
}
通过关键词判断用户想控制哪种设备。
3️⃣ 设备模型加载模块(DeviceModelLoader.java)
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.*;public class DeviceModelLoader {private static final List<DeviceModel> deviceModels = new ArrayList<>();static {try {ObjectMapper mapper = new ObjectMapper();File file = new File("src/main/resources/device_knowledge.json");DeviceModel[] models = mapper.readValue(file, DeviceModel[].class);deviceModels.addAll(Arrays.asList(models));} catch (Exception e) {e.printStackTrace();}}public static List<DeviceModel> getAllDeviceModels() {return deviceModels;}public static Map<String, Object> getSchemaByType(String deviceType) {for (DeviceModel model : deviceModels) {if (model.getDeviceType().equalsIgnoreCase(deviceType)) {return model.getSchema();}}return null;}
}
4️⃣ RAG 检索模块(RagRetriever.java)
import java.util.Map;public class RagRetriever {public static String retrieveContext(String query) {String intent = IntentRecognizer.recognizeIntent(query);Map<String, Object> schema = DeviceModelLoader.getSchemaByType(intent);if (schema == null) {return "";}return String.format("设备类型:%s\n" +"描述:智能设备\n" +"标准物模型定义:\n%s\n",intent,schema.toString());}
}
根据识别到的设备类型,返回对应的物模型定义。
5️⃣ Few-Shot 提示词模板(PromptBuilder.java)
public class PromptBuilder {public static String buildPrompt(String context, String query) {return String.format("""
你是一个智能家居控制助手,请根据以下设备的标准物模型定义,生成符合要求的 JSON 控制命令。请严格按照以下规则执行:
1. 输出必须是合法的 JSON 格式
2. 字段名必须为英文,值必须严格符合物模型定义
3. 不要添加任何解释、多余字段或中文内容
4. 如果无法判断意图,请返回空对象 {}以下是设备的标准物模型定义:%s以下是几个示例输入和输出供你参考:示例 1:
用户指令:“打开客厅的灯”
输出:
{"device_type": "light","property": "power","value": "on"
}示例 2:
用户指令:“把温度设为26度”
输出:
{"device_type": "ac","property": "temperature","value": 26
}现在,请根据以下用户指令生成对应的 JSON 控制命令:用户指令:“%s”
""",context, query);}
}
构造包含 Few-Shot 示例的提示词,引导模型输出规范格式。
6️⃣ 调用本地大模型生成结构化指令(LlmClient.java)
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;public class LlmClient {// Ollama API 地址(本地部署)private static final String OLLAMA_API_URL = "http://localhost:11434/api/generate";public static String generateCommand(String prompt) throws IOException {String requestBody = String.format("{\"model\": \"qwen2.5:0.5b\", \"prompt\": \"%s\", \"stream\": false}",escapeJson(prompt));HttpURLConnection connection = (HttpURLConnection) new URL(OLLAMA_API_URL).openConnection();connection.setRequestMethod("POST");connection.setRequestProperty("Content-Type", "application/json");connection.setDoOutput(true);try (OutputStream os = connection.getOutputStream()) {os.write(requestBody.getBytes());os.flush();}if (connection.getResponseCode() != 200) {throw new IOException("请求失败: HTTP " + connection.getResponseCode());}StringBuilder responseText = new StringBuilder();try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {String line;while ((line = reader.readLine()) != null) {responseText.append(line);}}// 提取 JSON 输出(简化处理)return extractJson(responseText.toString());}private static String escapeJson(String text) {return text.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r");}private static String extractJson(String rawResponse) {// 实际应使用 JSON 解析库提取 response 字段return rawResponse.contains("response") ?rawResponse.split("\"response\":\"")[1].split("\"")[0] :"{}";}
}
使用
Ollama
的本地 API 接口调用本地大模型,生成结构化 JSON 指令。
7️⃣ JSON 校验工具类(JsonSchemaValidator.java)
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;public class JsonSchemaValidator {public static String validate(String jsonStr) {try {ObjectMapper mapper = new ObjectMapper();JsonNode node = mapper.readTree(jsonStr);if (!node.has("device_type") || !node.has("property")) {return "{}";}return jsonStr;} catch (Exception ignored) {return "{}";}}
}
确保模型输出符合结构要求,防止非法参数。
8️⃣ 主程序入口(Main.java)
public class Main {public static void main(String[] args) throws Exception {String userInput = "把温度调高一点";// Step 1: 意图识别String intent = IntentRecognizer.recognizeIntent(userInput);System.out.println("识别到意图:" + intent);// Step 2: RAG 检索物模型String context = RagRetriever.retrieveContext(userInput);System.out.println("检索结果:\n" + context);// Step 3: 构造 PromptString prompt = PromptBuilder.buildPrompt(context, userInput);System.out.println("构造的 Prompt:\n" + prompt);// Step 4: 调用本地大模型String llmOutput = LlmClient.generateCommand(prompt);System.out.println("模型输出:\n" + llmOutput);// Step 5: JSON 校验String validated = JsonSchemaValidator.validate(llmOutput);System.out.println("校验后输出:\n" + validated);}
}
🧪 示例流程演示
输入:
“把温度调高一点”
输出:
{"device_type": "ac","property": "temperature","value": 28
}
流程说明:
- 意图识别:识别为
ac
(空调) - RAG 检索:加载空调的标准物模型
- 构造 Prompt:Few-Shot 示例 + 用户指令
- 调用本地大模型:输出 JSON 控制指令
- JSON 校验:确保字段合法
📦 项目结构总结
smart-home-assistant-java/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── Main.java
│ │ │ ├── IntentRecognizer.java
│ │ │ ├── DeviceModelLoader.java
│ │ │ ├── RagRetriever.java
│ │ │ ├── PromptBuilder.java
│ │ │ ├── LlmClient.java
│ │ │ └── JsonSchemaValidator.java
│ │ └── resources/
│ │ └── device_knowledge.json
│ └── build.gradle (可选)
💡 技术亮点总结
技术点 | 描述 |
---|---|
✅ 本地运行 | 不依赖互联网,隐私更安全 |
✅ 小模型支持 | 如 Qwen2.5-0.5B.Q2_K.gguf,仅约 300MB |
✅ 规则驱动 RAG | 快速检索,不依赖 embedding 向量 |
✅ Few-Shot 提示词 | 提升模型输出准确性 |
✅ JSON 校验机制 | 防止非法输出,提升稳定性 |
🧩 可扩展方向
功能 | 描述 |
---|---|
✅ 多轮对话支持 | 记录上下文,处理模糊指令 |
✅ MQTT 控制设备 | 下发 JSON 指令给设备 |
✅ Home Assistant 集成 | 直接控制真实设备 |
✅ 加入 TTS 文语转换 | 提供语音反馈 |
✅ Flutter/Electron 封装 | 打包成桌面/移动端应用 |
🔗 项目源码下载地址
🔗 点击下载完整 Java 工程 ZIP 包
包含:
- 所有 Java 源代码
- 示例
device_knowledge.json
- 编译配置与运行说明
🧑💻 总结
通过本文你学会了如何构建一个完整的本地智能家居控制助手系统:
- ✅ 从 JSON 文件中读取物模型
- ✅ 使用关键词识别设备类型
- ✅ 构建 Few-Shot 提示词
- ✅ 调用本地大模型生成结构化 JSON 指令
- ✅ 校验输出确保格式正确
这套系统可以用于:
- 💻 本地 PC 应用
- 🖥️ Electron 桌面助手
- 📱 Android App(后续可扩展)
📬 后续计划(可以继续做的)
- ✅ 把这个系统封装成 Web API(Spring Boot)
- ✅ 加入 MQTT 控制接口
- ✅ 支持多语言(英文、日文)
- ✅ 部署到树莓派做边缘计算
📢 欢迎留言讨论
如果你有任何问题,或者希望我帮你:
- ✅ 写一个 Python 版本
- ✅ 把这个系统做成 Electron App
- ✅ 提供预训练模型文件
- ✅ 支持 MQTT 控制设备
欢迎随时告诉我 👇 我会一步步带你完成这个完整的智能家居控制系统!
✅ **关注我,获取更多 AI 与 IoT 结合的实战教程