xiaogpt 2.83__py3-none-any.whl → 2.90__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.
- xiaogpt/utils.py +22 -1
- xiaogpt/xiaogpt.py +6 -20
- {xiaogpt-2.83.dist-info → xiaogpt-2.90.dist-info}/METADATA +30 -18
- {xiaogpt-2.83.dist-info → xiaogpt-2.90.dist-info}/RECORD +7 -7
- {xiaogpt-2.83.dist-info → xiaogpt-2.90.dist-info}/WHEEL +1 -1
- {xiaogpt-2.83.dist-info → xiaogpt-2.90.dist-info}/entry_points.txt +0 -0
- {xiaogpt-2.83.dist-info → xiaogpt-2.90.dist-info}/licenses/LICENSE +0 -0
xiaogpt/utils.py
CHANGED
@@ -5,11 +5,14 @@ import os
|
|
5
5
|
import re
|
6
6
|
import socket
|
7
7
|
from http.cookies import SimpleCookie
|
8
|
-
from typing import AsyncIterator
|
8
|
+
from typing import TYPE_CHECKING, AsyncIterator
|
9
9
|
from urllib.parse import urlparse
|
10
10
|
|
11
11
|
from requests.utils import cookiejar_from_dict
|
12
12
|
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
from lingua import LanguageDetector
|
15
|
+
|
13
16
|
|
14
17
|
### HELP FUNCTION ###
|
15
18
|
def parse_cookie_string(cookie_string):
|
@@ -69,3 +72,21 @@ def get_hostname() -> str:
|
|
69
72
|
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
|
70
73
|
s.connect(("8.8.8.8", 80))
|
71
74
|
return s.getsockname()[0]
|
75
|
+
|
76
|
+
|
77
|
+
def _get_detector() -> LanguageDetector | None:
|
78
|
+
try:
|
79
|
+
from lingua import LanguageDetectorBuilder
|
80
|
+
except ImportError:
|
81
|
+
return None
|
82
|
+
return LanguageDetectorBuilder.from_all_spoken_languages().build()
|
83
|
+
|
84
|
+
|
85
|
+
_detector = _get_detector()
|
86
|
+
|
87
|
+
|
88
|
+
def detect_language(text: str) -> str:
|
89
|
+
if _detector is None:
|
90
|
+
return "zh" # default to Chinese if langdetect module is not available
|
91
|
+
lang = _detector.detect_language_of(text)
|
92
|
+
return lang.iso_code_639_1.name.lower() if lang is not None else "zh"
|
xiaogpt/xiaogpt.py
CHANGED
@@ -24,9 +24,7 @@ from xiaogpt.config import (
|
|
24
24
|
Config,
|
25
25
|
)
|
26
26
|
from xiaogpt.tts import TTS, MiTTS, TetosTTS
|
27
|
-
from xiaogpt.utils import
|
28
|
-
parse_cookie_string,
|
29
|
-
)
|
27
|
+
from xiaogpt.utils import detect_language, parse_cookie_string
|
30
28
|
|
31
29
|
EOF = object()
|
32
30
|
|
@@ -390,11 +388,6 @@ class MiGPT:
|
|
390
388
|
query = f"{query},{self.config.prompt}"
|
391
389
|
# some model can not detect the language code, so we need to add it
|
392
390
|
|
393
|
-
if self.config.tts != "mi": # mi only say Chinese
|
394
|
-
query += (
|
395
|
-
",并用本段话的language code作为开头,用|分隔,如:en-US|你好……"
|
396
|
-
)
|
397
|
-
|
398
391
|
if self.config.mute_xiaoai:
|
399
392
|
await self.stop_if_xiaoai_is_playing()
|
400
393
|
else:
|
@@ -420,18 +413,11 @@ class MiGPT:
|
|
420
413
|
await self.wakeup_xiaoai()
|
421
414
|
|
422
415
|
async def speak(self, text_stream: AsyncIterator[str]) -> None:
|
423
|
-
|
424
|
-
#
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
lang, first_chunk = "", text
|
429
|
-
|
430
|
-
lang = (
|
431
|
-
matches[0]
|
432
|
-
if (matches := re.findall(r"([a-z]{2}-[A-Z]{2})", lang))
|
433
|
-
else "zh-CN"
|
434
|
-
)
|
416
|
+
first_chunk = await text_stream.__anext__()
|
417
|
+
# Detect the language from the first chunk
|
418
|
+
# Add suffix '-' because tetos expects it to exist when selecting voices
|
419
|
+
# however, the nation code is never used.
|
420
|
+
lang = detect_language(first_chunk) + "-"
|
435
421
|
|
436
422
|
async def gen(): # reconstruct the generator
|
437
423
|
yield first_chunk
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: xiaogpt
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.90
|
4
4
|
Summary: Play ChatGPT or other LLM with xiaomi AI speaker
|
5
5
|
Author-Email: yihong0618 <zouzou0208@gmail.com>
|
6
6
|
License: MIT
|
@@ -25,6 +25,7 @@ Requires-Dist: tetos>=0.2.1
|
|
25
25
|
Requires-Dist: groq>=0.5.0
|
26
26
|
Requires-Dist: pyyaml>=6.0.1
|
27
27
|
Requires-Dist: langchain-community>=0.0.38
|
28
|
+
Requires-Dist: lingua-language-detector>=2.0.2; python_version < "3.13"
|
28
29
|
Requires-Dist: aiohttp==3.9.5; extra == "locked"
|
29
30
|
Requires-Dist: aiosignal==1.3.1; extra == "locked"
|
30
31
|
Requires-Dist: annotated-types==0.6.0; extra == "locked"
|
@@ -38,24 +39,25 @@ Requires-Dist: certifi==2024.2.2; extra == "locked"
|
|
38
39
|
Requires-Dist: charset-normalizer==3.3.2; extra == "locked"
|
39
40
|
Requires-Dist: click==8.1.7; extra == "locked"
|
40
41
|
Requires-Dist: colorama==0.4.6; platform_system == "Windows" and extra == "locked"
|
41
|
-
Requires-Dist: dashscope==1.
|
42
|
+
Requires-Dist: dashscope==1.20.1; extra == "locked"
|
42
43
|
Requires-Dist: dataclasses-json==0.6.3; extra == "locked"
|
43
44
|
Requires-Dist: distro==1.9.0; extra == "locked"
|
44
45
|
Requires-Dist: edge-tts==6.1.10; extra == "locked"
|
46
|
+
Requires-Dist: et-xmlfile==1.1.0; python_version ~= "3.8" and python_full_version != "3.9.7" and extra == "locked"
|
45
47
|
Requires-Dist: exceptiongroup==1.2.0; python_version < "3.11" and extra == "locked"
|
46
48
|
Requires-Dist: frozenlist==1.4.1; extra == "locked"
|
47
|
-
Requires-Dist: google-ai-generativelanguage==0.6.
|
49
|
+
Requires-Dist: google-ai-generativelanguage==0.6.6; extra == "locked"
|
48
50
|
Requires-Dist: google-api-core==2.15.0; extra == "locked"
|
49
51
|
Requires-Dist: google-api-core[grpc]==2.15.0; extra == "locked"
|
50
52
|
Requires-Dist: google-api-python-client==2.125.0; extra == "locked"
|
51
53
|
Requires-Dist: google-auth==2.26.1; extra == "locked"
|
52
54
|
Requires-Dist: google-auth-httplib2==0.2.0; extra == "locked"
|
53
55
|
Requires-Dist: google-cloud-texttospeech==2.16.3; extra == "locked"
|
54
|
-
Requires-Dist: google-generativeai==0.
|
56
|
+
Requires-Dist: google-generativeai==0.7.1; extra == "locked"
|
55
57
|
Requires-Dist: google-search-results==2.4.2; extra == "locked"
|
56
58
|
Requires-Dist: googleapis-common-protos==1.62.0; extra == "locked"
|
57
59
|
Requires-Dist: greenlet==3.0.3; (platform_machine == "win32" or platform_machine == "WIN32" or platform_machine == "AMD64" or platform_machine == "amd64" or platform_machine == "x86_64" or platform_machine == "ppc64le" or platform_machine == "aarch64") and extra == "locked"
|
58
|
-
Requires-Dist: groq==0.
|
60
|
+
Requires-Dist: groq==0.9.0; extra == "locked"
|
59
61
|
Requires-Dist: grpcio==1.60.0; extra == "locked"
|
60
62
|
Requires-Dist: grpcio-status==1.60.0; extra == "locked"
|
61
63
|
Requires-Dist: h11==0.14.0; extra == "locked"
|
@@ -66,49 +68,58 @@ Requires-Dist: httpx[socks]==0.27.0; extra == "locked"
|
|
66
68
|
Requires-Dist: idna==3.7; extra == "locked"
|
67
69
|
Requires-Dist: jsonpatch==1.33; extra == "locked"
|
68
70
|
Requires-Dist: jsonpointer==2.4; extra == "locked"
|
69
|
-
Requires-Dist: langchain==0.2.
|
70
|
-
Requires-Dist: langchain-community==0.2.
|
71
|
-
Requires-Dist: langchain-core==0.2.
|
71
|
+
Requires-Dist: langchain==0.2.6; extra == "locked"
|
72
|
+
Requires-Dist: langchain-community==0.2.6; extra == "locked"
|
73
|
+
Requires-Dist: langchain-core==0.2.11; extra == "locked"
|
72
74
|
Requires-Dist: langchain-text-splitters==0.2.0; extra == "locked"
|
73
|
-
Requires-Dist: langsmith==0.1.
|
75
|
+
Requires-Dist: langsmith==0.1.84; extra == "locked"
|
76
|
+
Requires-Dist: lingua-language-detector==2.0.2; python_version < "3.13" and extra == "locked"
|
74
77
|
Requires-Dist: markdown-it-py==3.0.0; extra == "locked"
|
75
78
|
Requires-Dist: marshmallow==3.20.1; extra == "locked"
|
76
79
|
Requires-Dist: mdurl==0.1.2; extra == "locked"
|
77
|
-
Requires-Dist: miservice-fork==2.
|
80
|
+
Requires-Dist: miservice-fork==2.7.0; extra == "locked"
|
78
81
|
Requires-Dist: multidict==6.0.5; extra == "locked"
|
79
82
|
Requires-Dist: mutagen==1.47.0; extra == "locked"
|
80
83
|
Requires-Dist: mypy-extensions==1.0.0; extra == "locked"
|
81
|
-
Requires-Dist: numexpr==2.10.
|
84
|
+
Requires-Dist: numexpr==2.10.1; extra == "locked"
|
82
85
|
Requires-Dist: numpy==1.26.3; extra == "locked"
|
83
|
-
Requires-Dist: openai==1.
|
86
|
+
Requires-Dist: openai==1.35.10; extra == "locked"
|
87
|
+
Requires-Dist: openpyxl==3.1.5; python_version ~= "3.8" and python_full_version != "3.9.7" and extra == "locked"
|
84
88
|
Requires-Dist: orjson==3.10.0; extra == "locked"
|
85
89
|
Requires-Dist: packaging==23.2; extra == "locked"
|
90
|
+
Requires-Dist: pandas==2.2.2; python_version ~= "3.8" and python_full_version != "3.9.7" and extra == "locked"
|
86
91
|
Requires-Dist: proto-plus==1.23.0; extra == "locked"
|
87
92
|
Requires-Dist: protobuf==4.25.1; extra == "locked"
|
88
93
|
Requires-Dist: pyasn1==0.5.1; extra == "locked"
|
89
94
|
Requires-Dist: pyasn1-modules==0.3.0; extra == "locked"
|
90
|
-
Requires-Dist: pydantic==2.
|
91
|
-
Requires-Dist: pydantic-core==2.
|
95
|
+
Requires-Dist: pydantic==2.8.2; extra == "locked"
|
96
|
+
Requires-Dist: pydantic-core==2.20.1; extra == "locked"
|
92
97
|
Requires-Dist: pygments==2.17.2; extra == "locked"
|
93
98
|
Requires-Dist: pyjwt==2.8.0; extra == "locked"
|
94
99
|
Requires-Dist: pyparsing==3.1.2; python_version > "3.0" and extra == "locked"
|
100
|
+
Requires-Dist: python-dateutil==2.9.0.post0; python_version ~= "3.8" and python_full_version != "3.9.7" and extra == "locked"
|
101
|
+
Requires-Dist: pytz==2024.1; python_version ~= "3.8" and python_full_version != "3.9.7" and extra == "locked"
|
95
102
|
Requires-Dist: pyyaml==6.0.1; extra == "locked"
|
96
103
|
Requires-Dist: requests==2.31.0; extra == "locked"
|
97
104
|
Requires-Dist: rich==13.7.1; extra == "locked"
|
98
105
|
Requires-Dist: rsa==4.9; extra == "locked"
|
106
|
+
Requires-Dist: six==1.16.0; python_version ~= "3.8" and python_full_version != "3.9.7" and extra == "locked"
|
99
107
|
Requires-Dist: sniffio==1.3.0; extra == "locked"
|
100
108
|
Requires-Dist: socksio==1.0.0; extra == "locked"
|
101
109
|
Requires-Dist: soupsieve==2.5; extra == "locked"
|
102
110
|
Requires-Dist: sqlalchemy==2.0.25; extra == "locked"
|
103
111
|
Requires-Dist: tenacity==8.2.3; extra == "locked"
|
104
|
-
Requires-Dist: tetos==0.
|
112
|
+
Requires-Dist: tetos==0.3.0; extra == "locked"
|
105
113
|
Requires-Dist: tqdm==4.66.1; extra == "locked"
|
106
|
-
Requires-Dist: typing-extensions==4.
|
114
|
+
Requires-Dist: typing-extensions==4.12.2; extra == "locked"
|
107
115
|
Requires-Dist: typing-inspect==0.9.0; extra == "locked"
|
116
|
+
Requires-Dist: tzdata==2024.1; python_version ~= "3.8" and python_full_version != "3.9.7" and extra == "locked"
|
108
117
|
Requires-Dist: uritemplate==4.1.1; extra == "locked"
|
109
118
|
Requires-Dist: urllib3==2.1.0; extra == "locked"
|
119
|
+
Requires-Dist: websocket-client==1.8.0; extra == "locked"
|
120
|
+
Requires-Dist: websockets==12.0; extra == "locked"
|
110
121
|
Requires-Dist: yarl==1.9.4; extra == "locked"
|
111
|
-
Requires-Dist: zhipuai==2.
|
122
|
+
Requires-Dist: zhipuai==2.1.2; extra == "locked"
|
112
123
|
Provides-Extra: locked
|
113
124
|
Description-Content-Type: text/markdown
|
114
125
|
|
@@ -420,9 +431,10 @@ docker run -v <your-config-dir>:/config -p 9527:9527 -e XIAOGPT_HOSTNAME=<your i
|
|
420
431
|
|
421
432
|
注意端口必须映射为与容器内一致,XIAOGPT_HOSTNAME 需要设置为宿主机的 IP 地址,否则小爱无法正常播放语音。
|
422
433
|
|
423
|
-
##
|
434
|
+
## 推荐的类似项目
|
424
435
|
|
425
436
|
- [XiaoBot](https://github.com/longbai/xiaobot) -> Go语言版本的Fork, 带支持不同平台的UI
|
437
|
+
- [MiGPT](https://github.com/idootop/mi-gpt) -> Node.js 版,支持流式响应和长短期记忆
|
426
438
|
|
427
439
|
## 感谢
|
428
440
|
|
@@ -1,7 +1,7 @@
|
|
1
|
-
xiaogpt-2.
|
2
|
-
xiaogpt-2.
|
3
|
-
xiaogpt-2.
|
4
|
-
xiaogpt-2.
|
1
|
+
xiaogpt-2.90.dist-info/METADATA,sha256=8DaSfOAe4cGAaG3XGw0husfhBovVJKeURJYtH9gi4jo,30847
|
2
|
+
xiaogpt-2.90.dist-info/WHEEL,sha256=mbxFTmdEUhG7evcdMkR3aBt9SWcoFBJ4CDwnfguNegA,90
|
3
|
+
xiaogpt-2.90.dist-info/entry_points.txt,sha256=zLFzA72qQ_eWBepdA2YU5vdXFqORH8wXhv2Ox1vnYP8,46
|
4
|
+
xiaogpt-2.90.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=BDGvj1JuWVw47qfREWGKnSXeiFg6DVJJAz2rHVryqmc,1160
|
@@ -25,6 +25,6 @@ xiaogpt/tts/__init__.py,sha256=xasHDrmgECirf1MSyrfURSaMBqtdZBi3cQNeDvPo_cQ,145
|
|
25
25
|
xiaogpt/tts/base.py,sha256=k0ZUcLJZWU5U_fXu_w-cLFgZpE2KkV89ARbVDXLqTck,4665
|
26
26
|
xiaogpt/tts/mi.py,sha256=1MzCB27DBohPQ_4Xz4W_FV9p-chJFDavOHB89NviLcM,1095
|
27
27
|
xiaogpt/tts/tetos.py,sha256=fkuOSYGqAfJyyPEXbsiOS--CewGf1JUiahoN33nzOAA,1058
|
28
|
-
xiaogpt/utils.py,sha256=
|
29
|
-
xiaogpt/xiaogpt.py,sha256=
|
30
|
-
xiaogpt-2.
|
28
|
+
xiaogpt/utils.py,sha256=YYmRDNtccxqB9gyN_xhKZwgL1_PNYEp7So_-jt2tiVg,2668
|
29
|
+
xiaogpt/xiaogpt.py,sha256=3Q8Au9QcJy1fRGrMd0XKYbUn9_uKvVPce8PE-DA6heg,16153
|
30
|
+
xiaogpt-2.90.dist-info/RECORD,,
|
File without changes
|
File without changes
|