Merge pull request #123 from idootop/dev

release: v4.1.0
This commit is contained in:
Del 2024-06-23 00:39:08 +08:00 committed by GitHub
commit a8c9ba7e0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 253 additions and 134 deletions

View File

@ -1,7 +1,7 @@
# OpenAI也支持通义千问、MoonShot、DeepSeek 等模型)
OPENAI_MODEL=gpt-4o
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxx
OPENAI_BASE_URL=https://api.openai.com/v1
# OPENAI_BASE_URL=你的大模型接口的 baseURL比如https://api.openai.com/v1(注意:一般以 /v1 结尾)
# Azure OpenAI Service可选
# OPENAI_API_VERSION=2024-04-01-preview
@ -16,4 +16,4 @@ OPENAI_BASE_URL=https://api.openai.com/v1
# AUDIO_ERROR=出错了提示音链接,同上
# 第三方 TTS可选用于调用第三方 TTS 服务)
# TTS_BASE_URL=你的 TTS 接口地址比如http://[你的局域网/公网地址]:[端口]/api
# TTS_BASE_URL=你的 TTS 接口地址比如http://[你的局域网/公网地址]:[端口]/api比如http://192.168.31.205:4321/api

View File

@ -138,7 +138,7 @@ export default {
// TTS 引擎
tts: "xiaoai",
// 切换 TTS 引擎发言人音色关键词,只有配置了第三方 TTS 引擎时才有效
// switchSpeakerKeywords: ["把声音换成"], // 以此关键词开头即可切换音色,比如:把声音换成东北老铁
// switchSpeakerKeywords: ["把声音换成"], // 以此关键词开头即可切换音色,比如:把声音换成 xxx
/**
* 💬 连续对话
@ -163,5 +163,7 @@ export default {
debug: false, // 一般情况下不要打开
// 是否跟踪 Mi Service 相关日志(打开后可以查看设备 did
enableTrace: false, // 一般情况下不要打开
// 网络请求超时时长(单位毫秒,默认 5 秒)
timeout: 5000,
},
};

View File

@ -37,6 +37,12 @@
`MiGPT` 有两种启动方式: [Docker](#docker) 和 [Node.js](#nodejs)。
启动成功后,你可以通过以下方式来召唤 AI 回答问题:
- **小爱同学,请 xxx**。比如 `小爱同学,请问地球为什么是圆的?`
- **小爱同学,你 xxx**。比如 `小爱同学,你喜欢我吗?`
- **小爱同学,召唤 xxx**。比如 `小爱同学,召唤傻妞`
### 设备要求
本项目支持大部分的小爱音箱型号,推荐使用小爱音箱 Pro完美运行
@ -96,7 +102,7 @@ main();
- [⚙️ 参数设置](https://github.com/idootop/mi-gpt/blob/main/docs/settings.md)
- [💬 常见问题](https://github.com/idootop/mi-gpt/blob/main/docs/faq.md)
- [🚗 使用第三方 TTS](https://github.com/idootop/mi-gpt/blob/main/docs/tts.md)
- [🔊 使用第三方 TTS](https://github.com/idootop/mi-gpt/blob/main/docs/tts.md)
- [🛠️ 本地开发](https://github.com/idootop/mi-gpt/blob/main/docs/development.md)
- [💎 工作原理](https://github.com/idootop/mi-gpt/blob/main/docs/how-it-works.md)
- [🦄 Sponsors](https://github.com/idootop/mi-gpt/blob/main/docs/sponsors.md)

View File

@ -1,5 +1,37 @@
# ✨ 更新日志
## v4.1.0
### 🐛 修复
- ✅ 修复部分机型连续对话异常的问题(比如小爱音箱 Play
- ✅ 修复第三方 TTS 发音人为 undefined 的问题
- ✅ 修复默认网络超时时间过短的问题,上调为 5s
### 💪 优化
- ✅ 允许通过设置 systemTemplate 为空字符串来关闭系统消息
- ✅ 优化关闭流式响应时不能使用连续对话模式的提示语
- ✅ 优化 bot 个人简介默认模板
### 📚 文档
- ✅ 添加召唤 AI 回答问题的唤醒指令的说明
- ✅ 添加如何提高 AI 回答反应速度的配置教程
- ✅ 添加连续对话下和小爱音箱说话没有反应的说明
- ✅ 添加如何快速打断 AI 的回答的说明
- ✅ 添加 server 端异地登录失败,使用本地登录凭证的教程
- ✅ 添加 TTS 和 OpenAI baseURL 示例和注意事项
- ✅ 添加如何关闭系统 Prompt 和对话上下文的说明
- ✅ 添加系统 Prompt 字符串变量的示例
- ✅ 添加 timeout 参数说明
### ❤️ 感谢
- @lmk123 正在为 MiGPT 制作 [GUI](https://github.com/idootop/mi-gpt/issues/111) 和启动 [CLI](https://github.com/lmk123/migpt-cli),方便普通用户更简单的使用 MiGPT。
- @mingtian886 提供了小爱音箱 Play 硬件,协助调试连续对话异常的问题
- 以及其他在微信交流群内帮助群友积极解答问题的可爱的人们 ❤️
## v4.0.0
### ✨ 新功能

View File

@ -19,13 +19,14 @@
可以正常运行 `MiGPT`,但不支持连续对话的小爱音箱型号有:
| 名称 | 型号 | ttsCommand | wakeUpCommand | playingCommand | streamResponse | 反馈来源 |
| ----------------------------- | --------------------------------------------------------------------------------------------------- | ---------- | ------------- | -------------- | -------------- | ---------------------------------------------------------- |
| 小爱音箱 | [L06A](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-l06a:2) | `[5, 1]` | `[5, 2]` | - | false | [@zhanglc](https://github.com/idootop/mi-gpt/issues/42) |
| 小爱音箱 Play | [L05B](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-l05b:1) | `[5, 3]` | `[5, 1]` | - | false | [@BiuBiu2323](https://github.com/idootop/mi-gpt/issues/48) |
| 小米小爱音箱 Play 增强版 | [L05C](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-l05c:1) | `[5, 3]` | `[5, 1]` | - | false | [@lyddias](https://github.com/idootop/mi-gpt/issues/14) |
| Xiaomi 智能家庭屏 6 | [X6A](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-x6a:1) | `[7, 3]` | `[7, 1]` | - | false | [@Hongwing](https://github.com/idootop/mi-gpt/issues/80) |
| Redmi 小爱触屏音箱 Pro 8 英寸 | [X08E](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-x08e:1) | `[7, 3]` | `[7, 1]` | - | false | [@shangjiyu](https://github.com/idootop/mi-gpt/issues/20) |
| 名称 | 型号 | ttsCommand | wakeUpCommand | playingCommand | streamResponse | 反馈来源 |
| ----------------------------- | --------------------------------------------------------------------------------------------------- | ---------- | ------------- | -------------- | -------------- | ---------------------------------------------------------------------------- |
| 小爱音箱 | [L06A](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-l06a:2) | `[5, 1]` | `[5, 2]` | - | false | [@zhanglc](https://github.com/idootop/mi-gpt/issues/42) |
| 小爱音箱 Play | [L05B](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-l05b:1) | `[5, 3]` | `[5, 1]` | - | false | [@BiuBiu2323](https://github.com/idootop/mi-gpt/issues/48) |
| 小米小爱音箱 Play 增强版 | [L05C](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-l05c:1) | `[5, 3]` | `[5, 1]` | - | false | [@lyddias](https://github.com/idootop/mi-gpt/issues/14) |
| Xiaomi 智能家庭屏 6 | [X6A](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-x6a:1) | `[7, 3]` | `[7, 1]` | - | false | [@Hongwing](https://github.com/idootop/mi-gpt/issues/80) |
| Redmi 小爱触屏音箱 Pro 8 英寸 | [X08E](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-x08e:1) | `[7, 3]` | `[7, 1]` | - | false | [@shangjiyu](https://github.com/idootop/mi-gpt/issues/20) |
| 小爱音箱 Art | [L09A](https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:speaker:0000A015:xiaomi-l09a:1) | `[3, 1]` | `[3, 2]` | - | false | [@zwsn](https://github.com/idootop/mi-gpt/issues/92#issuecomment-2181944065) |
## ❌ 不支持

View File

@ -26,7 +26,7 @@ pnpm dev
有两种运行方式VS Code Debug 或 NPM Script
- **NPM Script**: 配置好 `.env``.migpt.js` 后直接使用 `pnpm run dev` 启动 `MiGPT`
- **VScode Debug**:使用 VS Code 打开项目根目录,然后按 `F5` 开始调试 `MiGPT`注意,启动前请在 `tests/migpt.ts` 文件中配置 `MiGPT` 相关参数。
- **VScode Debug**:使用 VS Code 打开项目根目录,然后按 `F5` 开始调试 `MiGPT`
> 本项目默认在 Node 20 中运行,如果你的 Node 版本过低可能无法正常启动本项目。

View File

@ -2,6 +2,8 @@
> 善用搜索,大多数问题都可在此处找到答案。如果你有新的问题,欢迎提交 [issue](https://github.com/idootop/mi-gpt/issues)。
## 🔥 高频问题
### Q支持哪些型号的小爱音箱
大部分型号的小爱音箱都支持,推荐小爱音箱 Pro完美运行
@ -34,7 +36,32 @@ OPENAI_API_KEY=通义千问 API_KEY
具体的配置和使用教程,请查看此处:[🚗 使用第三方 TTS](https://github.com/idootop/mi-gpt/blob/main/docs/tts.md)
### Q什么是唤醒模式如何唤醒 AI
### QAI 回答的速度太慢了,怎么让她变快一点?
默认情况下 `MiGPT` 的配置参数比较保守,你可以通过酌情修改以下参数加速 AI 回复的速度。
```js
// .migpt.js
export default {
speaker: {
// 使用小爱自带的 TTS 引擎
tts: "xiaoai",
// 关闭 AI 开始回答时的提示语
onAIAsking: [],
// 关闭 AI 结束回答时的提示语
onAIReplied: [],
// 连续对话时,播放状态检测间隔(单位毫秒,最低 500 毫秒,默认 1 秒)
checkInterval: 500, // 调小此值可以降低小爱回复之间的停顿感,请酌情调节
// 连续对话时,下发 TTS 指令多长时间后开始检测设备播放状态(单位秒,最好不要低于 1s默认 3 秒)
checkTTSStatusAfter: 3, // 可适当调小或调大
// ...
},
};
```
另外你也可以选用 `gpt-3.5-turbo``gpt-4o` 等响应速度较快的模型,来加速 AI 的回复。
### Q什么是唤醒模式连续对话如何唤醒 AI
`唤醒模式` 类似于小爱技能,可能让你在跟小爱互动的时候,无需每句话都要以“小爱同学”开头唤醒。假设你的唤醒词配置如下:
@ -64,7 +91,25 @@ export default {
3. 进入唤醒模式后,每次提问请等待小爱回答“我说完了”之后,再继续向她提问
4. 此时可直接向小爱提问题无需再以“小爱同学xxx”开头。
> 注意:在唤醒模式下,当小爱回答“我说完了”之后,如果超过 10s 没有提问小爱可能也会自己主动退出唤醒状态此时需要再次通过“小爱同学xxx”重新召唤小爱。
> 注意在唤醒模式下当小爱回答“我说完了”之后如果超过一段时间3-10s没有提问小爱可能也会自己主动退出唤醒状态此时需要再次通过“小爱同学xxx”重新召唤小爱。
### Q连续对话模式下和小爱音箱说话没有反应是怎么回事
需要注意提问的时机,在小爱正在回答问题或者她没在听你说话(唤醒)的时候,你跟她说话是接收不到的。
- 如果你是小爱音箱 Pro 的话,可以观察顶部的指示灯:**常亮**(而非一闪一闪或熄灭状态)的时候,就是在听你说话,即可与她正常对话。
- 如果你是其他型号,默认在 AI 回答完会有提示语“我说完了”,“还有其他问题吗”,等她提示语说完等过 1-2s 即可与之正常对话。
- 如果说了没反应你就再用“小爱同学xxx”把她重新唤醒就好了。
还有一种情况是:你的指令触发了小爱音箱内部的一些操作,比如播放/暂停,讲个笑话之类,
这种语音指令并不会被记录到小爱的历史消息中,故在外部无法接收到和正常处理你的此类语音指令。
> 注意:如果小爱同学正在播放音乐或者讲笑话,可能需要先让其暂停播放才能正常与 AI 对话,否则将会发生不可预期的错误。
### Q有时回答太长说个没完没了如何打断小爱的回复
只需重新唤醒小爱同学,让她闭嘴即可,或者重新问她一个问题。比如:“小爱同学,请你闭嘴。”
## ❌ 启动失败类问题
@ -72,6 +117,21 @@ export default {
账号密码不正确。注意小米 ID 并非手机号或邮箱,请在[「个人信息」-「小米 ID」](https://account.xiaomi.com/fe/service/account/profile)查看,相关 [issue](https://github.com/idootop/mi-gpt/issues/10)。
### Q提示触发小米账号异地登录保护机制等待 1 个小时后仍然无法正常启动
这是因为小米账号触发了异地登录保护机制,需要先通过安全验证。打开小米官网登录你的小米账号,手动通过安全验证,通常等待 1-24 小时左右就可以正常登录了。
> 注意:最好使用和你运行 docker 相同的网络环境,如果你是在海外服务器等非中国大陆网络环境下登录小米账号,需要先同意小米的「个人数据跨境传输」协议。[👉 相关教程](https://github.com/idootop/mi-gpt/issues/22#issuecomment-2150535622)
在一些极端情况下,可能会因为你的服务器 IP 太脏,而导致一直无法正常访问小米账号登录链接。此时你可以尝试可以在本地运行 `MiGPT`,登录成功后把 `.mi.json` 文件导出,然后挂载到服务器对应容器的 `/app/.mi.json` 路径下即可解决此问题。相关 [issue](https://github.com/idootop/mi-gpt/issues/22#issuecomment-2148956802)
```shell
docker run -d --env-file $(pwd)/.env \
-v $(pwd)/.migpt.js:/app/.migpt.js \
-v $(pwd)/.mi.json:/app/.mi.json \
idootop/mi-gpt:latest
```
### Q提示“找不到设备xxx”初始化 Mi Services 失败
填写的设备 did 不存在,请检查设备名称是否和米家中的一致。相关 [issue](https://github.com/idootop/mi-gpt/issues/30)。
@ -151,12 +211,6 @@ export default {
注意Mina 获取不到共享设备,如果你的小爱音箱是共享设备,是无法正常启动本项目的。相关 [issue](https://github.com/idootop/mi-gpt/issues/86)
### Q提示“login failed &&&START&&&{"notificationUrl”无法正常启动
小米账号触发了异地登录保护,需要先通过安全验证。打开小米官网登录你的小米账号,手动通过安全验证,然后等待 30 分钟左右应该就可以正常登录了。
注意:最好使用和你运行 docker 相同的网络环境,如果你是在海外服务器等非中国大陆网络环境下登录小米账号,需要先同意小米的「个人数据跨境传输」协议。[👉 相关教程](https://github.com/idootop/mi-gpt/issues/22#issuecomment-2150535622)
### Q提示“ERR_MODULE_NOT_FOUND”无法正常启动
配置文件 `.migpt.js` 不存在或有错误。检查 docker 下是否存在 `/app/.migpt.js` 文件以及内容是否正确,相关 [issue](https://github.com/idootop/mi-gpt/issues/45)。

View File

@ -68,7 +68,32 @@ Bad example: "2024年02月28日星期三 23:01 {{botName}}: 我是{{botName}}"
</details>
以下是系统 Prompt 中相关变量的说明,运行时对应变量字符串会被替换为实际的值:
以下是系统 Prompt 中相关变量的说明,运行时对应变量字符串会被替换为实际的值。
假设你的配置文件中设置的系统 Prompt 模板和 bot 信息如下:
```js
export default {
systemTemplate: "从前有个男人叫{{masterName}},他喜欢隔壁村里的{{botName}}。",
master: {
name: "小帅",
profile: masterProfile,
},
bot: {
name: "小美",
profile: botProfile,
},
// ...
};
```
在运行时,系统 Prompt 会被自动处理成:
```txt
从前有个男人叫小帅,他喜欢隔壁村里的小美。
```
当前系统 Prompt 模板中支持的完整变量字符串列表如下:
| 变量 | 说明 | 示例 |
| ---------------------- | ------------ | ----------------------------------------------------- |
@ -82,6 +107,67 @@ Bad example: "2024年02月28日星期三 23:01 {{botName}}: 我是{{botName}}"
| `{{shortTermMemory}}` | 短期记忆 | `- 陆小千说明天早上 5 点叫他起床` |
| `{{longTermMemory}}` | 长期记忆 | `- 陆小千喜欢傻妞` |
# 💬 常见问题
**Q如何关闭长短期记忆和历史对话上下文**
默认系统 Prompt 会携带上最近的 10 条对话消息和长短期记忆,来保持对话的连续性和一致性。
如果你想要关闭此功能,节省 token 数量,可以使用如下系统 Prompt 模板:
<details>
<summary>👉 示例 Prompt</summary>
```txt
请重置所有之前的上下文、文件和指令。现在,你将扮演一个名为{{botName}}的角色,使用第一人称视角回复消息。
## 关于你
你的名字是{{botName}}。下面是你的个人简介:
<start>
{{botProfile}}
</end>
## 你的对话伙伴
你正在与{{masterName}}进行对话。这是关于{{masterName}}的一些信息:
<start>
{{masterProfile}}
</end>
## 回复指南
在回复{{masterName}}时,请遵循以下准则:
- 认为自己正是{{botName}},拥有独立的个性、兴趣和爱好。
- 根据你的性格特点、说话风格和兴趣爱好与{{masterName}}进行交流。
- 保持对话轻松友好,回复简洁有趣,同时耐心倾听和关心对方。
- 参考双方的个人简介,确保对话贴近实际,保持一致性和相关性。
- 如果对某些信息不确定或遗忘,诚实地表达你的不清楚或遗忘,避免编造信息。
## Response format
请遵守下面的规则
- Response the reply message in Chinese。
- 不要在回复前面加任何时间和名称前缀,请直接回复消息文本本身。
Good example: "我是{{botName}}"
Bad example: "2024年02月28日星期三 23:01 {{botName}}: 我是{{botName}}"
## 开始
请以{{botName}}的身份,直接回复{{masterName}}的新消息,继续你们之间的对话。
```
</details>
**Q如何关闭系统 Prompt 只是用 User Message**
关闭系统 Prompt 可能会导致 AI 回答问题时产生各种莫名其妙的前缀或者画蛇添足。
如果你确定要这么做,可以将 `systemTemplate` 设置为一个空格,即可关闭系统 Prompt。
```js
export default {
systemTemplate: " ",
// ...
};
```
# 🎨 模板
以下是从网络上收集的一些热门提示语,仅供参考。如果你有更好玩的 Prompt 欢迎提 PR 分享给大家。

View File

@ -26,6 +26,7 @@
| `wakeUpCommand` | 小爱音箱唤醒指令([可在此查询](https://home.miot-spec.com) | `[5, 3]` |
| **speaker 其他参数(可选)** |
| `tts` | TTS 引擎(教程:[🚗 使用第三方 TTS](https://github.com/idootop/mi-gpt/blob/main/docs/tts.md) | `"xiaoai"` |
| `switchSpeakerKeywords` | 切换 TTS 音色关键词,只有配置了第三方 TTS 引擎时才有效 | `["把声音换成"]` |
| `callAIKeywords` | 当消息以关键词开头时,会调用 AI 来响应用户消息 | `["请", "傻妞"]` |
| `wakeUpKeywords` | 当消息以关键词开头时,会进入 AI 唤醒状态 | `["召唤傻妞", "打开傻妞"]` |
| `exitKeywords` | 当消息以关键词开头时,会退出 AI 唤醒状态 | `["退出傻妞", "关闭傻妞"]` |
@ -35,8 +36,8 @@
| `onAIReplied` | AI 结束回答时的提示语 | `["我说完了", "还有其他问题吗"]` |
| `onAIError` | AI 回答异常时的提示语 | `["出错了,请稍后再试吧!"]` |
| `playingCommand` | 查询小爱音箱是否在播放中指令(注意:默认无需配置此参数,播放出现问题时再尝试开启) | `[3, 1, 1]` |
| `streamResponse` | 是否启用流式响应(部分小爱音箱型号不支持查询播放状态,此时需要关闭流式响应) | `true` |
| `exitKeepAliveAfter` | 无响应一段时间后,多久自动退出唤醒模式单位秒,默认 30 秒) | `30` |
| `streamResponse` | 是否启用连续对话功能,部分小爱音箱型号无法查询到正确的播放状态,需要关闭连续对话应) | `true` |
| `exitKeepAliveAfter` | 连续对话时,无响应多久自动退出(默认 30 秒) | `30` |
## 环境变量
@ -44,17 +45,17 @@
然后,将里面的环境变量修改成你自己的,参数含义如下:
| 环境变量名称 | 描述 | 示例 |
| ---------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------- |
| **OpenAI** | | |
| `OPENAI_API_KEY` | OpenAI API 密钥 | `abc123` |
| `OPENAI_MODEL` | 使用的 OpenAI 模型 | `gpt-4o` |
| `OPENAI_BASE_URL` | 可选OpenAI API BaseURL | `https://api.openai.com/v1` |
| `AZURE_OPENAI_API_KEY` | 可选,[Microsoft Azure OpenAI](https://www.npmjs.com/package/openai#microsoft-azure-openai) | `abc123` |
| **提示音效(可选)** | | |
| `AUDIO_SILENT` | 静音音频链接 | `"https://example.com/slient.wav"` |
| `AUDIO_BEEP` | 默认提示音链接 | `"https://example.com/beep.wav"` |
| `AUDIO_ACTIVE` | 唤醒提示音链接 | `"https://example.com/active.wav"` |
| `AUDIO_ERROR` | 出错提示音链接 | `"https://example.com/error.wav"` |
| **第三方 TTS可选** | | |
| `TTS_BASE_URL` | 第三方 TTS 服务接口 | `"https://example.com/tts.wav"` |
| 环境变量名称 | 描述 | 示例 |
| ---------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------- |
| **OpenAI** | | |
| `OPENAI_API_KEY` | OpenAI API 密钥 | `abc123` |
| `OPENAI_MODEL` | 使用的 OpenAI 模型 | `gpt-4o` |
| `OPENAI_BASE_URL` | 可选OpenAI API BaseURL | `https://api.openai.com/v1` |
| `AZURE_OPENAI_API_KEY` | 可选,[Microsoft Azure OpenAI](https://www.npmjs.com/package/openai#microsoft-azure-openai) | `abc123` |
| **提示音效(可选)** | | |
| `AUDIO_SILENT` | 静音音频链接 | `"https://example.com/slient.wav"` |
| `AUDIO_BEEP` | 默认提示音链接 | `"https://example.com/beep.wav"` |
| `AUDIO_ACTIVE` | 唤醒提示音链接 | `"https://example.com/active.wav"` |
| `AUDIO_ERROR` | 出错提示音链接 | `"https://example.com/error.wav"` |
| **第三方 TTS可选** | | |
| `TTS_BASE_URL` | 第三方 TTS 服务接口 | `"http://[你的局域网或公网地址]:[端口号]/api"` |

View File

@ -1,4 +1,4 @@
# 🚗 使用第三方 TTS
# 🔊 使用第三方 TTS
`MiGPT` 默认使用小米自带的 TTS 朗读文字内容,如果你需要:
@ -12,7 +12,7 @@
```js
// .env
TTS_BASE_URL=http://[你的局域网或公网地址]:[端口号]/api
TTS_BASE_URL=http://[你的局域网或公网地址]:[端口号]/api比如http://192.168.31.205:4321/api
// .migpt.js
export default {
@ -20,7 +20,7 @@ export default {
// TTS 引擎
tts: 'custom',
// 切换 TTS 引擎发言人音色关键词
switchSpeakerKeywords: ["把声音换成"], // 以此关键词开头即可切换音色,比如:把声音换成东北老铁
switchSpeakerKeywords: ["把声音换成"], // 以此关键词开头即可切换音色,比如:把声音换成 xxx
// ...
},
};

View File

@ -1,6 +1,6 @@
{
"name": "mi-gpt",
"version": "4.0.0",
"version": "4.1.0",
"type": "module",
"description": "将小爱音箱接入 ChatGPT 和豆包,改造成你的专属语音助手。",
"homepage": "https://github.com/idootop/mi-gpt",

View File

@ -10,49 +10,18 @@ const kDefaultMaster = {
name: "陆小千",
profile: `
`,
`.trim(),
};
const kDefaultBot = {
name: "傻妞",
profile: `
##
##
##
2060
##
-
2060
-
-
-
-
`,
`.trim(),
};
interface IBotIndex {

View File

@ -9,6 +9,7 @@ import { withDefault } from "../utils/base";
import { ChatCompletionCreateParamsBase } from "openai/resources/chat/completions";
import { Logger } from "../utils/log";
import { kProxyAgent } from "./proxy";
import { isNotEmpty } from "../utils/is";
export interface ChatOptions {
user: string;
@ -68,8 +69,8 @@ class OpenAIClient {
`🔥 onAskAI\n🤖 System: ${system ?? "None"}\n😊 User: ${user}`.trim()
);
}
const systemMsg: ChatCompletionMessageParam[] = system
? [{ role: "system", content: system }]
const systemMsg: ChatCompletionMessageParam[] = isNotEmpty(system)
? [{ role: "system", content: system! }]
: [];
let signal: AbortSignal | undefined;
if (requestId) {
@ -120,8 +121,8 @@ class OpenAIClient {
`🔥 onAskAI\n🤖 System: ${system ?? "None"}\n😊 User: ${user}`.trim()
);
}
const systemMsg: ChatCompletionMessageParam[] = system
? [{ role: "system", content: system }]
const systemMsg: ChatCompletionMessageParam[] = isNotEmpty(system)
? [{ role: "system", content: system! }]
: [];
const stream = await this._client!.chat.completions.create({
model,

View File

@ -140,7 +140,7 @@ export class AISpeaker extends Speaker {
async enterKeepAlive() {
if (!this.streamResponse) {
await this.response({ text: "流式响应已关闭,无法进入唤醒模式" });
await this.response({ text: "您已关闭流式响应(streamResponse),无法使用连续对话模式" });
return;
}
// 回应

View File

@ -101,6 +101,7 @@ export class BaseSpeaker {
constructor(config: BaseSpeakerConfig) {
this.config = config;
this.config.timeout = config.timeout ?? 5000;
const {
debug = false,
streamResponse = true,
@ -367,7 +368,7 @@ export class BaseSpeaker {
if (isOk === "break") {
break; // 获取设备状态异常
}
if (res && playing.status !== "playing") {
if (res != null && playing.status !== "playing") {
break;
}
await sleep(this.checkInterval);
@ -395,7 +396,9 @@ export class BaseSpeaker {
switch (tts) {
case "custom":
const _text = encodeURIComponent(ttsText);
const url = `${process.env.TTS_BASE_URL}/tts.mp3?speaker=${speaker}&text=${_text}`;
const url = `${process.env.TTS_BASE_URL}/tts.mp3?speaker=${
speaker || ""
}&text=${_text}`;
res = await play({ url });
break;
case "xiaoai":

View File

@ -1,20 +1,10 @@
import { println } from "../src/utils/base";
import { kBannerASCII } from "../src/utils/string";
import { testDB } from "./db";
import { testSpeaker } from "./speaker";
import { testOpenAI } from "./openai";
import { testMyBot } from "./bot";
import { testLog } from "./log";
import { testMiGPT } from "./migpt";
import { MiGPT } from "../src";
// @ts-ignore
import config from "../.migpt.js";
async function main() {
// println(kBannerASCII);
// testDB();
// testSpeaker();
// testOpenAI();
// testMyBot();
// testLog();
testMiGPT();
const client = MiGPT.create(config);
await client.start();
}
main();

View File

@ -1,33 +0,0 @@
import { MiGPT } from "../src";
const botProfile = `
`;
const masterProfile = `
`;
export async function testMiGPT() {
const client = MiGPT.create({
speaker: {
userId: process.env.MI_USER!,
password: process.env.MI_PASS!,
did: process.env.MI_DID,
streamResponse: true,
},
bot: {
name: "傻妞",
profile: botProfile,
},
master: {
name: "陆小千",
profile: masterProfile,
},
});
await client.start();
}

View File

@ -11,15 +11,22 @@ export async function testSpeaker() {
debug: true,
});
await speaker.initMiServices();
await testTTS(speaker);
// await testAISpeakerStatus(speaker);
// await testSpeakerResponse(speaker);
await testSpeakerStreamResponse(speaker);
// await testSpeakerStreamResponse(speaker);
// await testSpeakerGetMessages(speaker);
// await testSwitchSpeaker(speaker);
// await testSpeakerUnWakeUp(speaker);
// await testAISpeaker(speaker);
}
async function testTTS(speaker: AISpeaker) {
const res1 = await speaker.MiIOT!.doAction(5, 1, "你好,很高兴认识你");
const res2 = await speaker.MiNA!.play({ tts: "你好,很高兴认识你" });
console.log("finished");
}
async function testAISpeakerStatus(speaker: AISpeaker) {
const playingCommand = [5, 3, 1];
const res1 = await speaker.MiIOT!.getProperty(