xiaogpt 2.25__py3-none-any.whl → 2.30__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,7 +30,7 @@ class ChatGPTBot(ChatHistoryMixin, BaseBot):
30
30
  return openai.AsyncAzureOpenAI(
31
31
  api_key=self.openai_key,
32
32
  azure_endpoint=self.api_base,
33
- api_version="2023-07-01-preview",
33
+ api_version="2024-02-15-preview",
34
34
  azure_deployment=self.deployment_id,
35
35
  http_client=sess,
36
36
  )
xiaogpt/cli.py CHANGED
@@ -90,6 +90,16 @@ def main():
90
90
  default=None,
91
91
  help="show info",
92
92
  )
93
+ parser.add_argument(
94
+ "--azure_tts_speech_key",
95
+ dest="azure_tts_speech_key",
96
+ help="if use azure tts",
97
+ )
98
+ parser.add_argument(
99
+ "--azure_tts_service_region",
100
+ dest="azure_tts_service_region",
101
+ help="if use azure tts",
102
+ )
93
103
  tts_group = parser.add_mutually_exclusive_group()
94
104
  tts_group.add_argument(
95
105
  "--enable_edge_tts",
@@ -98,7 +108,11 @@ def main():
98
108
  const="edge",
99
109
  help="if use edge tts",
100
110
  )
101
- tts_group.add_argument("--tts", help="tts type", choices=["mi", "edge", "openai"])
111
+ tts_group.add_argument(
112
+ "--tts",
113
+ help="tts type",
114
+ choices=["mi", "edge", "openai", "azure"],
115
+ )
102
116
  bot_group = parser.add_mutually_exclusive_group()
103
117
  bot_group.add_argument(
104
118
  "--use_gpt3",
@@ -197,6 +211,9 @@ def main():
197
211
  options = parser.parse_args()
198
212
  if options.bot in ["bard"] and options.stream:
199
213
  raise Exception("For now Bard do not support stream")
214
+ if options.tts in ["edge", "openai", "azure"]:
215
+ print("Will close stream to better tts")
216
+ options.stream = False
200
217
  config = Config.from_options(options)
201
218
 
202
219
  miboy = MiGPT(config)
xiaogpt/config.py CHANGED
@@ -81,11 +81,13 @@ class Config:
81
81
  start_conversation: str = "开始持续对话"
82
82
  end_conversation: str = "结束持续对话"
83
83
  stream: bool = False
84
- tts: Literal["mi", "edge"] = "mi"
84
+ tts: Literal["mi", "edge", "azure", "openai"] = "mi"
85
85
  tts_voice: str | None = None
86
86
  gpt_options: dict[str, Any] = field(default_factory=dict)
87
87
  bing_cookie_path: str = ""
88
88
  bing_cookies: dict | None = None
89
+ azure_tts_speech_key: str | None = None
90
+ azure_tts_service_region: str = "eastasia"
89
91
 
90
92
  def __post_init__(self) -> None:
91
93
  if self.proxy:
@@ -110,6 +112,11 @@ class Config:
110
112
  raise Exception(
111
113
  "Using GPT api needs openai API key, please google how to"
112
114
  )
115
+ if self.tts == "azure" and not self.azure_tts_speech_key:
116
+ raise Exception("Using Azure TTS needs azure speech key")
117
+ if self.tts in ["azure", "edge", "openai"]:
118
+ print("Will close stream when use tts: {self.tts} for better experience")
119
+ self.stream = False
113
120
 
114
121
  @property
115
122
  def tts_command(self) -> str:
xiaogpt/tts/__init__.py CHANGED
@@ -1,3 +1,6 @@
1
1
  from xiaogpt.tts.base import TTS as TTS
2
2
  from xiaogpt.tts.edge import EdgeTTS as EdgeTTS
3
3
  from xiaogpt.tts.mi import MiTTS as MiTTS
4
+ from xiaogpt.tts.azure import AzureTTS
5
+
6
+ __all__ = ["TTS", "EdgeTTS", "MiTTS", "AzureTTS"]
xiaogpt/tts/azure.py ADDED
@@ -0,0 +1,97 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ import tempfile
5
+ from pathlib import Path
6
+ from typing import Optional
7
+
8
+ import azure.cognitiveservices.speech as speechsdk
9
+
10
+ from xiaogpt.tts.base import AudioFileTTS
11
+ from xiaogpt.utils import calculate_tts_elapse
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class AzureTTS(AudioFileTTS):
17
+ voice_name = "zh-CN-XiaoxiaoMultilingualNeural"
18
+
19
+ async def make_audio_file(self, query: str, text: str) -> tuple[Path, float]:
20
+ output_file = tempfile.NamedTemporaryFile(
21
+ suffix=".mp3", mode="wb", delete=False, dir=self.dirname.name
22
+ )
23
+
24
+ speech_synthesizer = self._build_speech_synthesizer(output_file.name)
25
+ result: Optional[speechsdk.SpeechSynthesisResult] = (
26
+ speech_synthesizer.speak_text_async(text).get()
27
+ )
28
+ if result is None:
29
+ raise RuntimeError(
30
+ f"Failed to get tts from azure with voice={self.voice_name}"
31
+ )
32
+ # Check result
33
+ if result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted:
34
+ logger.debug("Speech synthesized for text [{}]".format(text))
35
+ return Path(output_file.name), calculate_tts_elapse(text)
36
+ elif result.reason == speechsdk.ResultReason.Canceled:
37
+ cancellation_details = result.cancellation_details
38
+ logger.warning(f"Speech synthesis canceled: {cancellation_details.reason}")
39
+ if cancellation_details.reason == speechsdk.CancellationReason.Error:
40
+ errmsg = f"Error details: {cancellation_details.error_details}"
41
+ logger.error(errmsg)
42
+ raise RuntimeError(errmsg)
43
+ raise RuntimeError(f"Failed to get tts from azure with voice={self.voice_name}")
44
+
45
+ def _build_speech_synthesizer(self, filename: str):
46
+ speech_key = self.config.azure_tts_speech_key
47
+ service_region = self.config.azure_tts_service_region
48
+ if not speech_key:
49
+ raise Exception("Azure tts need speech key")
50
+ speech_config = speechsdk.SpeechConfig(
51
+ subscription=speech_key, region=service_region
52
+ )
53
+ speech_config.set_speech_synthesis_output_format(
54
+ speechsdk.SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3
55
+ )
56
+ if self.config.proxy:
57
+ host, port, username, password = self._parse_proxy(self.config.proxy)
58
+
59
+ if username and password:
60
+ speech_config.set_proxy(
61
+ hostname=host, port=port, username=username, password=password
62
+ )
63
+ else:
64
+ speech_config.set_proxy(hostname=host, port=port)
65
+
66
+ speech_config.speech_synthesis_voice_name = (
67
+ self.config.tts_voice or self.voice_name
68
+ )
69
+ speech_synthesizer = speechsdk.SpeechSynthesizer(
70
+ speech_config=speech_config,
71
+ audio_config=speechsdk.audio.AudioOutputConfig(filename=filename), # type: ignore
72
+ )
73
+ return speech_synthesizer
74
+
75
+ def _parse_proxy(self, proxy_str: str):
76
+ proxy_str = proxy_str
77
+ proxy_str_splited = proxy_str.split("://")
78
+ proxy_type = proxy_str_splited[0]
79
+ proxy_addr = proxy_str_splited[1]
80
+
81
+ if proxy_type == "http":
82
+ if "@" in proxy_addr:
83
+ proxy_addr_splited = proxy_addr.split("@")
84
+ proxy_auth = proxy_addr_splited[0]
85
+ proxy_addr_netloc = proxy_addr_splited[1]
86
+ proxy_auth_splited = proxy_auth.split(":")
87
+ username = proxy_auth_splited[0]
88
+ password = proxy_auth_splited[1]
89
+ else:
90
+ proxy_addr_netloc = proxy_addr
91
+ username, password = None, None
92
+
93
+ proxy_addr_netloc_splited = proxy_addr_netloc.split(":")
94
+ host = proxy_addr_netloc_splited[0]
95
+ port = int(proxy_addr_netloc_splited[1])
96
+ return host, port, username, password
97
+ raise NotImplementedError
xiaogpt/tts/base.py CHANGED
@@ -123,7 +123,7 @@ class AudioFileTTS(TTS):
123
123
  break
124
124
  else:
125
125
  url, duration = result
126
- logger.debug("Playing URL %s(%s seconds)", url, duration)
126
+ logger.debug("Playing URL %s (%s seconds)", url, duration)
127
127
  await self.mina_service.play_by_url(self.device_id, url)
128
128
  await self.wait_for_duration(duration)
129
129
  await task
xiaogpt/xiaogpt.py CHANGED
@@ -23,7 +23,7 @@ from xiaogpt.config import (
23
23
  WAKEUP_KEYWORD,
24
24
  Config,
25
25
  )
26
- from xiaogpt.tts import TTS, EdgeTTS, MiTTS
26
+ from xiaogpt.tts import TTS, EdgeTTS, MiTTS, AzureTTS
27
27
  from xiaogpt.tts.openai import OpenAITTS
28
28
  from xiaogpt.utils import (
29
29
  parse_cookie_string,
@@ -51,6 +51,7 @@ class MiGPT:
51
51
  self.log.setLevel(logging.DEBUG if config.verbose else logging.INFO)
52
52
  self.log.addHandler(RichHandler())
53
53
  self.log.debug(config)
54
+ self.mi_session = ClientSession()
54
55
 
55
56
  async def poll_latest_ask(self):
56
57
  async with ClientSession() as session:
@@ -78,8 +79,8 @@ class MiGPT:
78
79
  async def init_all_data(self, session):
79
80
  await self.login_miboy(session)
80
81
  await self._init_data_hardware()
81
- session.cookie_jar.update_cookies(self.get_cookie())
82
- self.cookie_jar = session.cookie_jar
82
+ self.mi_session.cookie_jar.update_cookies(self.get_cookie())
83
+ self.cookie_jar = self.mi_session.cookie_jar
83
84
  self.tts # init tts
84
85
 
85
86
  async def login_miboy(self, session):
@@ -215,14 +216,17 @@ class MiGPT:
215
216
  data = await r.json()
216
217
  except Exception:
217
218
  self.log.warning("get latest ask from xiaoai error, retry")
218
- if i == 2:
219
+ if i == 1:
219
220
  # tricky way to fix #282 #272 # if it is the third time we re init all data
220
221
  print("Maybe outof date trying to re init it")
221
- await self.init_all_data(self.session)
222
+ await self._retry()
222
223
  else:
223
224
  return self._get_last_query(data)
224
225
  return None
225
226
 
227
+ async def _retry(self):
228
+ await self.init_all_data(self.mi_session)
229
+
226
230
  def _get_last_query(self, data: dict) -> dict | None:
227
231
  if d := data.get("data"):
228
232
  records = json.loads(d).get("records")
@@ -256,6 +260,8 @@ class MiGPT:
256
260
  def tts(self) -> TTS:
257
261
  if self.config.tts == "edge":
258
262
  return EdgeTTS(self.mina_service, self.device_id, self.config)
263
+ elif self.config.tts == "azure":
264
+ return AzureTTS(self.mina_service, self.device_id, self.config)
259
265
  elif self.config.tts == "openai":
260
266
  return OpenAITTS(self.mina_service, self.device_id, self.config)
261
267
  else:
@@ -339,71 +345,69 @@ class MiGPT:
339
345
  )
340
346
 
341
347
  async def run_forever(self):
342
- async with ClientSession() as session:
343
- self.session = session
344
- await self.init_all_data(session)
345
- task = asyncio.create_task(self.poll_latest_ask())
346
- assert task is not None # to keep the reference to task, do not remove this
347
- print(
348
- f"Running xiaogpt now, 用[green]{'/'.join(self.config.keyword)}[/]开头来提问"
349
- )
350
- print(f"或用[green]{self.config.start_conversation}[/]开始持续对话")
351
- while True:
352
- self.polling_event.set()
353
- new_record = await self.last_record.get()
354
- self.polling_event.clear() # stop polling when processing the question
355
- query = new_record.get("query", "").strip()
356
-
357
- if query == self.config.start_conversation:
358
- if not self.in_conversation:
359
- print("开始对话")
360
- self.in_conversation = True
361
- await self.wakeup_xiaoai()
362
- await self.stop_if_xiaoai_is_playing()
363
- continue
364
- elif query == self.config.end_conversation:
365
- if self.in_conversation:
366
- print("结束对话")
367
- self.in_conversation = False
368
- await self.stop_if_xiaoai_is_playing()
369
- continue
348
+ await self.init_all_data(self.mi_session)
349
+ task = asyncio.create_task(self.poll_latest_ask())
350
+ assert task is not None # to keep the reference to task, do not remove this
351
+ print(
352
+ f"Running xiaogpt now, 用[green]{'/'.join(self.config.keyword)}[/]开头来提问"
353
+ )
354
+ print(f"或用[green]{self.config.start_conversation}[/]开始持续对话")
355
+ while True:
356
+ self.polling_event.set()
357
+ new_record = await self.last_record.get()
358
+ self.polling_event.clear() # stop polling when processing the question
359
+ query = new_record.get("query", "").strip()
360
+
361
+ if query == self.config.start_conversation:
362
+ if not self.in_conversation:
363
+ print("开始对话")
364
+ self.in_conversation = True
365
+ await self.wakeup_xiaoai()
366
+ await self.stop_if_xiaoai_is_playing()
367
+ continue
368
+ elif query == self.config.end_conversation:
369
+ if self.in_conversation:
370
+ print("结束对话")
371
+ self.in_conversation = False
372
+ await self.stop_if_xiaoai_is_playing()
373
+ continue
370
374
 
371
- # we can change prompt
372
- if self.need_change_prompt(new_record):
373
- print(new_record)
374
- self._change_prompt(new_record.get("query", ""))
375
+ # we can change prompt
376
+ if self.need_change_prompt(new_record):
377
+ print(new_record)
378
+ self._change_prompt(new_record.get("query", ""))
375
379
 
376
- if not self.need_ask_gpt(new_record):
377
- self.log.debug("No new xiao ai record")
378
- continue
380
+ if not self.need_ask_gpt(new_record):
381
+ self.log.debug("No new xiao ai record")
382
+ continue
379
383
 
380
- # drop 帮我回答
381
- query = re.sub(rf"^({'|'.join(self.config.keyword)})", "", query)
384
+ # drop 帮我回答
385
+ query = re.sub(rf"^({'|'.join(self.config.keyword)})", "", query)
382
386
 
383
- print("-" * 20)
384
- print("问题:" + query + "?")
385
- if not self.chatbot.has_history():
386
- query = f"{query},{self.config.prompt}"
387
- if self.config.mute_xiaoai:
388
- await self.stop_if_xiaoai_is_playing()
389
- else:
390
- # waiting for xiaoai speaker done
391
- await asyncio.sleep(8)
392
- await self.do_tts(f"正在问{self.chatbot.name}请耐心等待")
393
- try:
394
- print(
395
- "以下是小爱的回答: ",
396
- new_record.get("answers", [])[0].get("tts", {}).get("text"),
397
- )
398
- except IndexError:
399
- print("小爱没回")
400
- print(f"以下是 {self.chatbot.name} 的回答: ", end="")
401
- try:
402
- await self.tts.synthesize(query, self.ask_gpt(query))
403
- except Exception as e:
404
- print(f"{self.chatbot.name} 回答出错 {str(e)}")
405
- else:
406
- print("回答完毕")
407
- if self.in_conversation:
408
- print(f"继续对话, 或用`{self.config.end_conversation}`结束对话")
409
- await self.wakeup_xiaoai()
387
+ print("-" * 20)
388
+ print("问题:" + query + "?")
389
+ if not self.chatbot.has_history():
390
+ query = f"{query},{self.config.prompt}"
391
+ if self.config.mute_xiaoai:
392
+ await self.stop_if_xiaoai_is_playing()
393
+ else:
394
+ # waiting for xiaoai speaker done
395
+ await asyncio.sleep(8)
396
+ await self.do_tts(f"正在问{self.chatbot.name}请耐心等待")
397
+ try:
398
+ print(
399
+ "以下是小爱的回答: ",
400
+ new_record.get("answers", [])[0].get("tts", {}).get("text"),
401
+ )
402
+ except IndexError:
403
+ print("小爱没回")
404
+ print(f"以下是 {self.chatbot.name} 的回答: ", end="")
405
+ try:
406
+ await self.tts.synthesize(query, self.ask_gpt(query))
407
+ except Exception as e:
408
+ print(f"{self.chatbot.name} 回答出错 {str(e)}")
409
+ else:
410
+ print("回答完毕")
411
+ if self.in_conversation:
412
+ print(f"继续对话, 或用`{self.config.end_conversation}`结束对话")
413
+ await self.wakeup_xiaoai()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xiaogpt
3
- Version: 2.25
3
+ Version: 2.30
4
4
  Summary: Play ChatGPT or other LLM with xiaomi AI speaker
5
5
  Author-Email: yihong0618 <zouzou0208@gmail.com>
6
6
  License: MIT
@@ -14,6 +14,7 @@ Requires-Dist: openai>=1
14
14
  Requires-Dist: aiohttp
15
15
  Requires-Dist: rich
16
16
  Requires-Dist: zhipuai==2.0.1
17
+ Requires-Dist: httpx==0.24.1
17
18
  Requires-Dist: bardapi
18
19
  Requires-Dist: edge-tts>=6.1.3
19
20
  Requires-Dist: EdgeGPT==0.1.26
@@ -23,6 +24,8 @@ Requires-Dist: google-search-results>=2.4.2
23
24
  Requires-Dist: google-generativeai
24
25
  Requires-Dist: numexpr>=2.8.6
25
26
  Requires-Dist: dashscope==1.10.0
27
+ Requires-Dist: httpcore==0.15.0
28
+ Requires-Dist: azure-cognitiveservices-speech>=1.37.0
26
29
  Description-Content-Type: text/markdown
27
30
 
28
31
  # xiaogpt
@@ -47,15 +50,33 @@ Play ChatGPT and other LLM with Xiaomi AI Speaker
47
50
  - [Bard](https://github.com/dsdanielpark/Bard-API)
48
51
  - [通义千问](https://help.aliyun.com/zh/dashscope/developer-reference/api-details)
49
52
 
50
- ## Windows 获取小米音响DID
51
-
52
- 1. `pip install miservice_fork`
53
- 2. `set MI_USER=xxxx`
54
- 3. `set MI_PASS=xxx`
55
- 4. `micli list` 得到did
56
- 5. `set MI_DID=xxxx`
53
+ ## 获取小米音响DID
54
+ ### Windows(使用 set 设置环境变量)
55
+ ```cmd
56
+ pip install miservice_fork
57
+ set MI_USER=xxxx
58
+ set MI_PASS=xxx
59
+ micli list 得到did
60
+ set MI_DID=xxxx
61
+ ```
57
62
 
58
63
  - 如果获取did报错时,请更换一下无线网络,有很大概率解决问题。
64
+
65
+ ### Linux(使用 export 设置环境变量)
66
+ ```sh
67
+ # 1、安装模块
68
+ pip install miservice_fork
69
+
70
+ # 2、设置环境用户参数
71
+ export MI_USER=xxxx
72
+ export MI_PASS=xxx
73
+
74
+ # 3、使用micli list 得到did
75
+ micli list
76
+
77
+ # 4、根据did设置环境DID参数
78
+ export MI_DID=xxxx
79
+ ```
59
80
 
60
81
  ## 一点原理
61
82
 
@@ -85,6 +106,7 @@ Play ChatGPT and other LLM with Xiaomi AI Speaker
85
106
  - 可以跟小爱说 `开始持续对话` 自动进入持续对话状态,`结束持续对话` 结束持续对话状态。
86
107
  - 可以使用 `--tts edge` 来获取更好的 tts 能力
87
108
  - 可以使用 `--tts openai` 来获取 openai tts 能力
109
+ - 可以使用 `--tts azure --azure_tts_speech_key <your-speech-key>` 来获取 Azure TTS 能力
88
110
  - 可以使用 `--use_langchain` 替代 `--use_chatgpt_api` 来调用 LangChain(默认 chatgpt)服务,实现上网检索、数学运算..
89
111
 
90
112
  e.g.
@@ -183,37 +205,39 @@ Bard-API [参考](https://github.com/dsdanielpark/Bard-API)
183
205
 
184
206
  ## 配置项说明
185
207
 
186
- | 参数 | 说明 | 默认值 |可选值 |
187
- | --------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------- |
188
- | hardware | 设备型号 | |
189
- | account | 小爱账户 | |
190
- | password | 小爱账户密码 | |
191
- | openai_key | openai的apikey | |
192
- | serpapi_api_key | serpapi的key 参考 [SerpAPI](https://serpapi.com/) | |
193
- | glm_key | chatglm 的 apikey | |
194
- | gemini_key | gemini 的 apikey [参考](https://makersuite.google.com/app/apikey) | |
195
- | qwen_key | qwen 的 apikey [参考](https://help.aliyun.com/zh/dashscope/developer-reference/api-details) | |
196
- | bard_token | bard 的 token 参考 [Bard-API](https://github.com/dsdanielpark/Bard-API) | |
197
- | cookie | 小爱账户cookie (如果用上面密码登录可以不填) | |
198
- | mi_did | 设备did | |
199
- | use_command | 使用 MI command 与小爱交互 | `false` |
200
- | mute_xiaoai | 快速停掉小爱自己的回答 | `true` |
201
- | verbose | 是否打印详细日志 | `false` |
202
- | bot | 使用的 bot 类型,目前支持gpt3,chatgptapi和newbing | `chatgptapi` |
203
- | tts | 使用的 TTS 类型 | `mi` | `edge`、 `openai` |
204
- | tts_voice | TTS 的嗓音 | `zh-CN-XiaoxiaoNeural`(edge), `alloy`(openai) |
205
- | prompt | 自定义prompt | `请用100字以内回答` |
206
- | keyword | 自定义请求词列表 | `["请"]` |
207
- | change_prompt_keyword | 更改提示词触发列表 | `["更改提示词"]` |
208
- | start_conversation | 开始持续对话关键词 | `开始持续对话` |
209
- | end_conversation | 结束持续对话关键词 | `结束持续对话` |
210
- | stream | 使用流式响应,获得更快的响应 | `false` |
211
- | proxy | 支持 HTTP 代理,传入 http proxy URL | "" |
212
- | gpt_options | OpenAI API 的参数字典 | `{}` |
213
- | bing_cookie_path | NewBing使用的cookie路径,参考[这里]获取 | 也可通过环境变量 `COOKIE_FILE` 设置 |
214
- | bing_cookies | NewBing使用的cookie字典,参考[这里]获取 | |
215
- | deployment_id | Azure OpenAI 服务的 deployment ID | 参考这个[如何找到deployment_id](https://github.com/yihong0618/xiaogpt/issues/347#issuecomment-1784410784) |
216
- | api_base | 如果需要替换默认的api,或者使用Azure OpenAI 服务 | 例如:`https://abc-def.openai.azure.com/` |
208
+ | 参数 | 说明 | 默认值 | 可选值 |
209
+ | ------------------------ | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
210
+ | hardware | 设备型号 | | |
211
+ | account | 小爱账户 | | |
212
+ | password | 小爱账户密码 | | |
213
+ | openai_key | openai的apikey | | |
214
+ | serpapi_api_key | serpapi的key 参考 [SerpAPI](https://serpapi.com/) | | |
215
+ | glm_key | chatglm 的 apikey | | |
216
+ | gemini_key | gemini 的 apikey [参考](https://makersuite.google.com/app/apikey) | | |
217
+ | qwen_key | qwen 的 apikey [参考](https://help.aliyun.com/zh/dashscope/developer-reference/api-details) | | |
218
+ | bard_token | bard 的 token 参考 [Bard-API](https://github.com/dsdanielpark/Bard-API) | | |
219
+ | cookie | 小爱账户cookie (如果用上面密码登录可以不填) | | |
220
+ | mi_did | 设备did | | |
221
+ | use_command | 使用 MI command 与小爱交互 | `false` | |
222
+ | mute_xiaoai | 快速停掉小爱自己的回答 | `true` | |
223
+ | verbose | 是否打印详细日志 | `false` | |
224
+ | bot | 使用的 bot 类型,目前支持gpt3,chatgptapi和newbing | `chatgptapi` | |
225
+ | tts | 使用的 TTS 类型 | `mi` | `edge`、 `openai`、`azure` |
226
+ | tts_voice | TTS 的嗓音 | `zh-CN-XiaoxiaoNeural`(edge), `alloy`(openai), `zh-CN-XiaoxiaoMultilingualNeural`(azure) | |
227
+ | prompt | 自定义prompt | `请用100字以内回答` | |
228
+ | keyword | 自定义请求词列表 | `["请"]` | |
229
+ | change_prompt_keyword | 更改提示词触发列表 | `["更改提示词"]` | |
230
+ | start_conversation | 开始持续对话关键词 | `开始持续对话` | |
231
+ | end_conversation | 结束持续对话关键词 | `结束持续对话` | |
232
+ | stream | 使用流式响应,获得更快的响应 | `false` | |
233
+ | proxy | 支持 HTTP 代理,传入 http proxy URL | "" | |
234
+ | gpt_options | OpenAI API 的参数字典 | `{}` | |
235
+ | bing_cookie_path | NewBing使用的cookie路径,参考[这里]获取 | 也可通过环境变量 `COOKIE_FILE` 设置 | |
236
+ | bing_cookies | NewBing使用的cookie字典,参考[这里]获取 | | |
237
+ | deployment_id | Azure OpenAI 服务的 deployment ID | 参考这个[如何找到deployment_id](https://github.com/yihong0618/xiaogpt/issues/347#issuecomment-1784410784) | |
238
+ | api_base | 如果需要替换默认的api,或者使用Azure OpenAI 服务 | 例如:`https://abc-def.openai.azure.com/` | |
239
+ | azure_tts_speech_key | Azure TTS key | null | |
240
+ | azure_tts_service_region | Azure TTS 服务地区 | `eastasia` | [Regions - Speech service - Azure AI services](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/regions) |
217
241
 
218
242
  [这里]: https://github.com/acheong08/EdgeGPT#getting-authentication-required
219
243
 
@@ -264,6 +288,12 @@ xiaogpt的配置文件可通过指定volume /config,以及指定参数--config
264
288
  docker run -v <your-config-dir>:/config yihong0618/xiaogpt --config=/config/config.json
265
289
  ```
266
290
 
291
+ ### 网络使用 host 模型
292
+
293
+ ```shell
294
+ docker run -v <your-config-dir>:/config --network=host yihong0618/xiaogpt --config=/config/config.json
295
+ ```
296
+
267
297
  ### 本地编译Docker Image
268
298
 
269
299
  ```shell
@@ -1,30 +1,31 @@
1
- xiaogpt-2.25.dist-info/METADATA,sha256=c7OJCRyjioLxHRZOFFeitFyNQS7Zn3TU5ejsQWMm76Q,18887
2
- xiaogpt-2.25.dist-info/WHEEL,sha256=N2J68yzZqJh3mI_Wg92rwhw0rtJDFpZj9bwQIMJgaVg,90
3
- xiaogpt-2.25.dist-info/entry_points.txt,sha256=zLFzA72qQ_eWBepdA2YU5vdXFqORH8wXhv2Ox1vnYP8,46
4
- xiaogpt-2.25.dist-info/licenses/LICENSE,sha256=XdClh516MvlnOf9749JZHCxSB7y6_fyXcWmLDz6IkZY,1063
1
+ xiaogpt-2.30.dist-info/METADATA,sha256=XtLWjKNLdkPj3UE_52Yv2FiplsNkOD0CvrKLRUshE3k,24670
2
+ xiaogpt-2.30.dist-info/WHEEL,sha256=N2J68yzZqJh3mI_Wg92rwhw0rtJDFpZj9bwQIMJgaVg,90
3
+ xiaogpt-2.30.dist-info/entry_points.txt,sha256=zLFzA72qQ_eWBepdA2YU5vdXFqORH8wXhv2Ox1vnYP8,46
4
+ xiaogpt-2.30.dist-info/licenses/LICENSE,sha256=XdClh516MvlnOf9749JZHCxSB7y6_fyXcWmLDz6IkZY,1063
5
5
  xiaogpt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  xiaogpt/__main__.py,sha256=MSmt_5Xg84uHqzTN38JwgseJK8rsJn_11A8WD99VtEo,61
7
7
  xiaogpt/bot/__init__.py,sha256=O3Wq7WRwTVdKJdKZxkBtCPdRJ8uXrQE0dqHa1ekOnfQ,1073
8
8
  xiaogpt/bot/bard_bot.py,sha256=qC8m87mWvtbiwipKl_OMYCqRbh79gkyZEytgz5DysC0,840
9
9
  xiaogpt/bot/base_bot.py,sha256=oKn6LLFHXol4hKrSrjnxknrOqrcGICtT_GPPYRNxpkw,1467
10
- xiaogpt/bot/chatgptapi_bot.py,sha256=Z4FX7F6j2n6NoUCqH6LliAAew94zaQXzp1blsE5yKoc,3656
10
+ xiaogpt/bot/chatgptapi_bot.py,sha256=JYlq1D-YZxRwAPpd5dTFSBU7h1KNdWA7FTwgyvMxr7c,3656
11
11
  xiaogpt/bot/gemini_bot.py,sha256=udKrWYP7U83AWpNBggwRp9bvgR2DTHqLMX9E_DLFv-I,1840
12
12
  xiaogpt/bot/glm_bot.py,sha256=QoMJbnu5_rHDz4tzwn7gh3IoAuw7E4hZQLAfziMAvNY,1825
13
13
  xiaogpt/bot/gpt3_bot.py,sha256=enX45_wrGjAtOh-anf8KnjCJluWSARZbjTGD_WZgoms,2781
14
14
  xiaogpt/bot/langchain_bot.py,sha256=4Uz5iOYzA2ongCklS-9zBse2fw-7kEE_9wITH7wdVCc,1944
15
15
  xiaogpt/bot/newbing_bot.py,sha256=afUmw6tyMXbgGZvfQQWaA5h0-e0V0isFolW-WGhd0Vs,2289
16
16
  xiaogpt/bot/qwen_bot.py,sha256=325lMa4Z38rRh47HDa3J4XjvSs4SWOqMVhrMWzkGNo4,3657
17
- xiaogpt/cli.py,sha256=aLmpwjYw6tKPNy-WPZIE2XD5oLHsjSksova_PpH85II,5057
18
- xiaogpt/config.py,sha256=uo82JTKhujet0ro2SN3cOw2GXE-AamyzL7EmeFiGS5o,6287
17
+ xiaogpt/cli.py,sha256=prTtwZjwC5RDZeh3eJWzBXTUHkOvFk7hAhuq9Mmeya8,5506
18
+ xiaogpt/config.py,sha256=jKumR4BROqRnshBk79mqUAKuqSkW7gsCCPukYNzCWho,6703
19
19
  xiaogpt/langchain/callbacks.py,sha256=yR9AXQt9OHVYBWC47Q1I_BUT4Xg9iM44vnW2vv0BLpE,2616
20
20
  xiaogpt/langchain/chain.py,sha256=z0cqRlL0ElWnf31ByxZBN7AKOT-svXQDt5_NDft_nYc,1495
21
21
  xiaogpt/langchain/examples/email/mail_box.py,sha256=xauqrjE4-G4XPQnokUPE-MZgAaHQ_VrUDLlbfYTdCoo,6372
22
22
  xiaogpt/langchain/examples/email/mail_summary_tools.py,sha256=6cWvBJUaA7iaywcHdbUoww8WiCtaNw3TmwyxyF4DY7E,1561
23
- xiaogpt/tts/__init__.py,sha256=UDMNJTobFrw3Ichhvck6rHU-oREnoj8RUC_E3M9dMU8,130
24
- xiaogpt/tts/base.py,sha256=6VlTqQ_RJBbTb-perlMsnKg2qwfgKj4ELhzbdF0HD6c,4922
23
+ xiaogpt/tts/__init__.py,sha256=SZ0FVKbKVbuV7xfRtpwUt5cmqyNQaFa7LyGRYsmdDNE,220
24
+ xiaogpt/tts/azure.py,sha256=Kxgc_XIWYo0A-xZrfZ_Qs2T7BzyRVCHhfzPKGKgjiXU,3978
25
+ xiaogpt/tts/base.py,sha256=-fcF5PJ1p0AHSR8GNf0LJbIbZ1m_92WXXX7ZrfzgC3s,4923
25
26
  xiaogpt/tts/edge.py,sha256=yMFGxRTi086XS1d_mbMzQ365bvG4KgAz8ZptaoDAfGU,1172
26
27
  xiaogpt/tts/mi.py,sha256=9HkgGWByAs7k8sTpRdVlgJnnmjc44RNAccJa6tGDlXk,1096
27
28
  xiaogpt/tts/openai.py,sha256=_Qk12zYY-UuXLKvQVe3PqIvCmoRW9OcVCqQRoGCXvNc,1533
28
29
  xiaogpt/utils.py,sha256=B7NCH7g19hcwHDXsnBJPTU6UcWnXoEntKWm-pgcet2I,2072
29
- xiaogpt/xiaogpt.py,sha256=_viWq5w4-rGCTsuDetPPih-4qkPZem9FtXK-tPyChlA,15473
30
- xiaogpt-2.25.dist-info/RECORD,,
30
+ xiaogpt/xiaogpt.py,sha256=KrgvlHkhXDxlb4gUIXqDIDr6wMuiDhL13stDglYk1dk,15400
31
+ xiaogpt-2.30.dist-info/RECORD,,
File without changes