xiaogpt 2.60__py3-none-any.whl → 2.62__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/bot/__init__.py +6 -3
- xiaogpt/bot/doubao_bot.py +76 -0
- xiaogpt/bot/gemini_bot.py +24 -6
- xiaogpt/cli.py +7 -0
- xiaogpt/config.py +12 -0
- xiaogpt/xiaogpt.py +1 -1
- {xiaogpt-2.60.dist-info → xiaogpt-2.62.dist-info}/METADATA +11 -6
- {xiaogpt-2.60.dist-info → xiaogpt-2.62.dist-info}/RECORD +11 -10
- {xiaogpt-2.60.dist-info → xiaogpt-2.62.dist-info}/WHEEL +0 -0
- {xiaogpt-2.60.dist-info → xiaogpt-2.62.dist-info}/entry_points.txt +0 -0
- {xiaogpt-2.60.dist-info → xiaogpt-2.62.dist-info}/licenses/LICENSE +0 -0
xiaogpt/bot/__init__.py
CHANGED
@@ -2,11 +2,12 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from xiaogpt.bot.base_bot import BaseBot
|
4
4
|
from xiaogpt.bot.chatgptapi_bot import ChatGPTBot
|
5
|
-
from xiaogpt.bot.
|
6
|
-
from xiaogpt.bot.glm_bot import GLMBot
|
5
|
+
from xiaogpt.bot.doubao_bot import DoubaoBot
|
7
6
|
from xiaogpt.bot.gemini_bot import GeminiBot
|
8
|
-
from xiaogpt.bot.
|
7
|
+
from xiaogpt.bot.glm_bot import GLMBot
|
9
8
|
from xiaogpt.bot.langchain_bot import LangChainBot
|
9
|
+
from xiaogpt.bot.newbing_bot import NewBingBot
|
10
|
+
from xiaogpt.bot.qwen_bot import QwenBot
|
10
11
|
from xiaogpt.config import Config
|
11
12
|
|
12
13
|
BOTS: dict[str, type[BaseBot]] = {
|
@@ -16,6 +17,7 @@ BOTS: dict[str, type[BaseBot]] = {
|
|
16
17
|
"gemini": GeminiBot,
|
17
18
|
"qwen": QwenBot,
|
18
19
|
"langchain": LangChainBot,
|
20
|
+
"doubao": DoubaoBot,
|
19
21
|
}
|
20
22
|
|
21
23
|
|
@@ -34,4 +36,5 @@ __all__ = [
|
|
34
36
|
"QwenBot",
|
35
37
|
"get_bot",
|
36
38
|
"LangChainBot",
|
39
|
+
"DoubaoBot",
|
37
40
|
]
|
@@ -0,0 +1,76 @@
|
|
1
|
+
"""ChatGLM bot"""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
import json
|
6
|
+
from typing import Any, AsyncIterator
|
7
|
+
|
8
|
+
import httpx
|
9
|
+
from rich import print
|
10
|
+
|
11
|
+
from xiaogpt.bot.base_bot import BaseBot, ChatHistoryMixin
|
12
|
+
from xiaogpt.config import Config
|
13
|
+
from xiaogpt.utils import split_sentences
|
14
|
+
|
15
|
+
|
16
|
+
class DoubaoBot(ChatHistoryMixin, BaseBot):
|
17
|
+
API_URL = "https://maas-api.ml-platform-cn-beijing.volces.com"
|
18
|
+
name = "豆包"
|
19
|
+
default_options = {"model": "skylark-chat"}
|
20
|
+
|
21
|
+
def __init__(self, access_key: str, secret_key: str) -> None:
|
22
|
+
from tetos.volc import VolcSignAuth
|
23
|
+
|
24
|
+
self.auth = VolcSignAuth(access_key, secret_key, "ml_maas", "cn-beijing")
|
25
|
+
self.history = []
|
26
|
+
|
27
|
+
@classmethod
|
28
|
+
def from_config(cls, config: Config):
|
29
|
+
return cls(access_key=config.volc_access_key, secret_key=config.volc_secret_key)
|
30
|
+
|
31
|
+
def _get_data(self, query: str, **options: Any):
|
32
|
+
options = {**self.default_options, **options}
|
33
|
+
model = options.pop("model")
|
34
|
+
ms = self.get_messages()
|
35
|
+
ms.append({"role": "user", "content": query})
|
36
|
+
return {"model": {"name": model}, "parameters": options, "messages": ms}
|
37
|
+
|
38
|
+
async def ask(self, query, **options):
|
39
|
+
data = self._get_data(query, **options)
|
40
|
+
async with httpx.AsyncClient(base_url=self.API_URL, auth=self.auth) as client:
|
41
|
+
resp = await client.post("/api/v1/chat", json=data)
|
42
|
+
resp.raise_for_status()
|
43
|
+
try:
|
44
|
+
message = resp.json()["choice"]["message"]["content"]
|
45
|
+
except Exception as e:
|
46
|
+
print(str(e))
|
47
|
+
return
|
48
|
+
self.add_message(query, message)
|
49
|
+
print(message)
|
50
|
+
return message
|
51
|
+
|
52
|
+
async def ask_stream(self, query: str, **options: Any):
|
53
|
+
data = self._get_data(query, **options)
|
54
|
+
data["stream"] = True
|
55
|
+
|
56
|
+
async def sse_gen(line_iter: AsyncIterator[str]) -> AsyncIterator[str]:
|
57
|
+
message = ""
|
58
|
+
async for chunk in line_iter:
|
59
|
+
if not chunk.startswith("data:"):
|
60
|
+
continue
|
61
|
+
message = chunk[5:].strip()
|
62
|
+
if message == "[DONE]":
|
63
|
+
break
|
64
|
+
data = json.loads(message)
|
65
|
+
text = data["choice"]["message"]["content"]
|
66
|
+
print(text, end="", flush=True)
|
67
|
+
message += text
|
68
|
+
yield text
|
69
|
+
print()
|
70
|
+
self.add_message(query, message)
|
71
|
+
|
72
|
+
async with httpx.AsyncClient(base_url=self.API_URL, auth=self.auth) as client:
|
73
|
+
async with client.stream("POST", "/api/v1/chat", json=data) as resp:
|
74
|
+
resp.raise_for_status()
|
75
|
+
async for sentence in split_sentences(sse_gen(resp.aiter_lines())):
|
76
|
+
yield sentence
|
xiaogpt/bot/gemini_bot.py
CHANGED
@@ -12,7 +12,7 @@ generation_config = {
|
|
12
12
|
"temperature": 0.7,
|
13
13
|
"top_p": 1,
|
14
14
|
"top_k": 1,
|
15
|
-
"max_output_tokens":
|
15
|
+
"max_output_tokens": 4096,
|
16
16
|
}
|
17
17
|
|
18
18
|
safety_settings = [
|
@@ -32,10 +32,26 @@ safety_settings = [
|
|
32
32
|
class GeminiBot(ChatHistoryMixin, BaseBot):
|
33
33
|
name = "Gemini"
|
34
34
|
|
35
|
-
def __init__(self, gemini_key: str) -> None:
|
35
|
+
def __init__(self, gemini_key: str, gemini_api_domain: str) -> None:
|
36
36
|
import google.generativeai as genai
|
37
37
|
|
38
|
-
|
38
|
+
from google.auth import api_key
|
39
|
+
|
40
|
+
credentials = api_key.Credentials(gemini_key)
|
41
|
+
if len(gemini_api_domain) > 0:
|
42
|
+
print("Use custom gemini_api_domain: " + gemini_api_domain)
|
43
|
+
credentials._universe_domain = gemini_api_domain
|
44
|
+
genai.configure(
|
45
|
+
transport="rest",
|
46
|
+
credentials=credentials,
|
47
|
+
client_options={
|
48
|
+
"api_endpoint": "https://" + gemini_api_domain,
|
49
|
+
"universe_domain": gemini_api_domain,
|
50
|
+
},
|
51
|
+
)
|
52
|
+
else:
|
53
|
+
genai.configure(api_key=gemini_key)
|
54
|
+
|
39
55
|
self.history = []
|
40
56
|
model = genai.GenerativeModel(
|
41
57
|
model_name="gemini-pro",
|
@@ -46,11 +62,13 @@ class GeminiBot(ChatHistoryMixin, BaseBot):
|
|
46
62
|
|
47
63
|
@classmethod
|
48
64
|
def from_config(cls, config):
|
49
|
-
return cls(
|
65
|
+
return cls(
|
66
|
+
gemini_key=config.gemini_key, gemini_api_domain=config.gemini_api_domain
|
67
|
+
)
|
50
68
|
|
51
69
|
async def ask(self, query, **options):
|
52
|
-
self.convo.send_message(query)
|
53
|
-
message =
|
70
|
+
response = self.convo.send_message(query)
|
71
|
+
message = response.text.strip()
|
54
72
|
print(message)
|
55
73
|
if len(self.convo.history) > 10:
|
56
74
|
self.convo.history = self.convo.history[2:]
|
xiaogpt/cli.py
CHANGED
@@ -37,6 +37,11 @@ def main():
|
|
37
37
|
dest="gemini_key",
|
38
38
|
help="gemini api key",
|
39
39
|
)
|
40
|
+
parser.add_argument(
|
41
|
+
"--gemini_api_domain",
|
42
|
+
dest="gemini_api_domain",
|
43
|
+
help="custom gemini api domain",
|
44
|
+
)
|
40
45
|
parser.add_argument(
|
41
46
|
"--qwen_key",
|
42
47
|
dest="qwen_key",
|
@@ -78,6 +83,8 @@ def main():
|
|
78
83
|
default=None,
|
79
84
|
help="try to mute xiaoai answer",
|
80
85
|
)
|
86
|
+
parser.add_argument("--volc-access-key", help="Volcengine access key")
|
87
|
+
parser.add_argument("--volc-secret-key", help="Volcengine secret key")
|
81
88
|
parser.add_argument(
|
82
89
|
"--verbose",
|
83
90
|
dest="verbose",
|
xiaogpt/config.py
CHANGED
@@ -56,6 +56,11 @@ class Config:
|
|
56
56
|
gemini_key: str = os.getenv("GEMINI_KEY", "") # keep the old rule
|
57
57
|
qwen_key: str = os.getenv("DASHSCOPE_API_KEY", "") # keep the old rule
|
58
58
|
serpapi_api_key: str = os.getenv("SERPAPI_API_KEY", "")
|
59
|
+
gemini_api_domain: str = os.getenv(
|
60
|
+
"GEMINI_API_DOMAIN", ""
|
61
|
+
) # 自行部署的 Google Gemini 代理
|
62
|
+
volc_access_key: str = os.getenv("VOLC_ACCESS_KEY", "")
|
63
|
+
volc_secret_key: str = os.getenv("VOLC_SECRET_KEY", "")
|
59
64
|
proxy: str | None = None
|
60
65
|
mi_did: str = os.getenv("MI_DID", "")
|
61
66
|
keyword: Iterable[str] = KEY_WORD
|
@@ -117,6 +122,13 @@ class Config:
|
|
117
122
|
for key, value in vars(options).items():
|
118
123
|
if value is not None and key in cls.__dataclass_fields__:
|
119
124
|
config[key] = value
|
125
|
+
if config.get("tts") == "volc":
|
126
|
+
config.setdefault("tts_options", {}).setdefault(
|
127
|
+
"access_key", config.get("volc_access_key")
|
128
|
+
)
|
129
|
+
config.setdefault("tts_options", {}).setdefault(
|
130
|
+
"secret_key", config.get("volc_secret_key")
|
131
|
+
)
|
120
132
|
return cls(**config)
|
121
133
|
|
122
134
|
@classmethod
|
xiaogpt/xiaogpt.py
CHANGED
@@ -411,7 +411,7 @@ class MiGPT:
|
|
411
411
|
await self.wakeup_xiaoai()
|
412
412
|
|
413
413
|
async def speak(self, text_stream: AsyncIterator[str]) -> None:
|
414
|
-
text = await
|
414
|
+
text = await text_stream.__anext__()
|
415
415
|
# See if the first part contains language code(e.g. en-US|Hello world)
|
416
416
|
lang, _, first_chunk = text.rpartition("|")
|
417
417
|
if len(lang) > 7:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: xiaogpt
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.62
|
4
4
|
Summary: Play ChatGPT or other LLM with xiaomi AI speaker
|
5
5
|
Author-Email: yihong0618 <zouzou0208@gmail.com>
|
6
6
|
License: MIT
|
@@ -22,7 +22,7 @@ Requires-Dist: google-search-results>=2.4.2
|
|
22
22
|
Requires-Dist: google-generativeai
|
23
23
|
Requires-Dist: numexpr>=2.8.6
|
24
24
|
Requires-Dist: dashscope>=1.10.0
|
25
|
-
Requires-Dist: tetos>=0.1.
|
25
|
+
Requires-Dist: tetos>=0.1.1
|
26
26
|
Requires-Dist: aiohttp==3.9.5; extra == "locked"
|
27
27
|
Requires-Dist: aiosignal==1.3.1; extra == "locked"
|
28
28
|
Requires-Dist: annotated-types==0.6.0; extra == "locked"
|
@@ -102,7 +102,7 @@ Requires-Dist: socksio==1.0.0; extra == "locked"
|
|
102
102
|
Requires-Dist: soupsieve==2.5; extra == "locked"
|
103
103
|
Requires-Dist: sqlalchemy==2.0.25; extra == "locked"
|
104
104
|
Requires-Dist: tenacity==8.2.3; extra == "locked"
|
105
|
-
Requires-Dist: tetos==0.1.
|
105
|
+
Requires-Dist: tetos==0.1.1; extra == "locked"
|
106
106
|
Requires-Dist: tqdm==4.66.1; extra == "locked"
|
107
107
|
Requires-Dist: typing-extensions==4.9.0; extra == "locked"
|
108
108
|
Requires-Dist: typing-inspect==0.9.0; extra == "locked"
|
@@ -191,6 +191,8 @@ xiaogpt --hardware LX06 --mute_xiaoai --use_chatgpt_api
|
|
191
191
|
xiaogpt --hardware LX06 --mute_xiaoai --stream
|
192
192
|
# 如果你想使用 google 的 gemini
|
193
193
|
xiaogpt --hardware LX06 --mute_xiaoai --use_gemini --gemini_key ${gemini_key}
|
194
|
+
# 如果你想使用自己的 google gemini 服务
|
195
|
+
python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_gemini --gemini_key ${gemini_key} --gemini_api_domain ${gemini_api_domain}
|
194
196
|
# 如果你想使用阿里的通义千问
|
195
197
|
xiaogpt --hardware LX06 --mute_xiaoai --use_qwen --qen_key ${qwen_key}
|
196
198
|
# 如果你想用 edge-tts
|
@@ -218,6 +220,8 @@ python3 xiaogpt.py --hardware LX06 --mute_xiaoai --stream
|
|
218
220
|
python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_glm --glm_key ${glm_key}
|
219
221
|
# 如果你想使用 google 的 gemini
|
220
222
|
python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_gemini --gemini_key ${gemini_key}
|
223
|
+
# 如果你想使用自己的 google gemini 服务
|
224
|
+
python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_gemini --gemini_key ${gemini_key} --gemini_api_domain ${gemini_api_domain}
|
221
225
|
# 如果你想使用阿里的通义千问
|
222
226
|
python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_qwen --qen_key ${qwen_key}
|
223
227
|
# 如果你想使用 LangChain+SerpApi 实现上网检索或其他本地服务(目前仅支持 stream 模式)
|
@@ -272,6 +276,7 @@ ChatGLM [文档](http://open.bigmodel.cn/doc/api#chatglm_130b)
|
|
272
276
|
| serpapi_api_key | serpapi的key 参考 [SerpAPI](https://serpapi.com/) | | |
|
273
277
|
| glm_key | chatglm 的 apikey | | |
|
274
278
|
| gemini_key | gemini 的 apikey [参考](https://makersuite.google.com/app/apikey) | | |
|
279
|
+
| gemini_api_domain | gemini 的自定义域名 [参考](https://github.com/antergone/palm-netlify-proxy) | |
|
275
280
|
| qwen_key | qwen 的 apikey [参考](https://help.aliyun.com/zh/dashscope/developer-reference/api-details) | | |
|
276
281
|
| cookie | 小爱账户cookie (如果用上面密码登录可以不填) | | |
|
277
282
|
| mi_did | 设备did | | |
|
@@ -292,9 +297,9 @@ ChatGLM [文档](http://open.bigmodel.cn/doc/api#chatglm_130b)
|
|
292
297
|
| bing_cookie_path | NewBing使用的cookie路径,参考[这里]获取 | 也可通过环境变量 `COOKIE_FILE` 设置 | |
|
293
298
|
| bing_cookies | NewBing使用的cookie字典,参考[这里]获取 | | |
|
294
299
|
| deployment_id | Azure OpenAI 服务的 deployment ID | 参考这个[如何找到deployment_id](https://github.com/yihong0618/xiaogpt/issues/347#issuecomment-1784410784) | |
|
295
|
-
| api_base | 如果需要替换默认的api,或者使用Azure OpenAI 服务 | 例如:`https://abc-def.openai.azure.com/` |
|
296
|
-
|
297
|
-
|
300
|
+
| api_base | 如果需要替换默认的api,或者使用Azure OpenAI 服务 | 例如:`https://abc-def.openai.azure.com/` |
|
301
|
+
| volc_access_key | 火山引擎的 access key 请在[这里](https://console.volcengine.com/iam/keymanage/)获取 | | |
|
302
|
+
| volc_secret_key | 火山引擎的 secret key 请在[这里](https://console.volcengine.com/iam/keymanage/)获取 | | |
|
298
303
|
[这里]: https://github.com/acheong08/EdgeGPT#getting-authentication-required
|
299
304
|
|
300
305
|
## 注意
|
@@ -1,19 +1,20 @@
|
|
1
|
-
xiaogpt-2.
|
2
|
-
xiaogpt-2.
|
3
|
-
xiaogpt-2.
|
4
|
-
xiaogpt-2.
|
1
|
+
xiaogpt-2.62.dist-info/METADATA,sha256=F5kqCAKbDAl4v58QUa8GXbieUj464ZQiK9prugStQXc,28013
|
2
|
+
xiaogpt-2.62.dist-info/WHEEL,sha256=7sv5iXvIiTVJSnAxCz2tGBm9DHsb2vPSzeYeT7pvGUY,90
|
3
|
+
xiaogpt-2.62.dist-info/entry_points.txt,sha256=zLFzA72qQ_eWBepdA2YU5vdXFqORH8wXhv2Ox1vnYP8,46
|
4
|
+
xiaogpt-2.62.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
|
-
xiaogpt/bot/__init__.py,sha256=
|
7
|
+
xiaogpt/bot/__init__.py,sha256=kOIY1lR0r-tbrnlcv_lj3cXxcwM4UpM8THxQ-JrRfwM,1006
|
8
8
|
xiaogpt/bot/base_bot.py,sha256=oKn6LLFHXol4hKrSrjnxknrOqrcGICtT_GPPYRNxpkw,1467
|
9
9
|
xiaogpt/bot/chatgptapi_bot.py,sha256=JYlq1D-YZxRwAPpd5dTFSBU7h1KNdWA7FTwgyvMxr7c,3656
|
10
|
-
xiaogpt/bot/
|
10
|
+
xiaogpt/bot/doubao_bot.py,sha256=UufQmYcPbwTLTYDZUQwRy4Hg24vgPEa3hdeZWMWw9YM,2773
|
11
|
+
xiaogpt/bot/gemini_bot.py,sha256=vX-fTWyPwdB4N0HDQ9uIRCB4KvV-YgBqXjkrqgg4WHs,2516
|
11
12
|
xiaogpt/bot/glm_bot.py,sha256=QoMJbnu5_rHDz4tzwn7gh3IoAuw7E4hZQLAfziMAvNY,1825
|
12
13
|
xiaogpt/bot/langchain_bot.py,sha256=4Uz5iOYzA2ongCklS-9zBse2fw-7kEE_9wITH7wdVCc,1944
|
13
14
|
xiaogpt/bot/newbing_bot.py,sha256=afUmw6tyMXbgGZvfQQWaA5h0-e0V0isFolW-WGhd0Vs,2289
|
14
15
|
xiaogpt/bot/qwen_bot.py,sha256=325lMa4Z38rRh47HDa3J4XjvSs4SWOqMVhrMWzkGNo4,3657
|
15
|
-
xiaogpt/cli.py,sha256=
|
16
|
-
xiaogpt/config.py,sha256=
|
16
|
+
xiaogpt/cli.py,sha256=y7Cs1M5IbCjtdbeLU9h_2__fLT-7C8qt3FIDrG2LaBQ,4696
|
17
|
+
xiaogpt/config.py,sha256=hCdggjjmBpQ_BX1teOuatjxUO9tRCUbSa3TLSnoiRkA,6444
|
17
18
|
xiaogpt/langchain/callbacks.py,sha256=yR9AXQt9OHVYBWC47Q1I_BUT4Xg9iM44vnW2vv0BLpE,2616
|
18
19
|
xiaogpt/langchain/chain.py,sha256=z0cqRlL0ElWnf31ByxZBN7AKOT-svXQDt5_NDft_nYc,1495
|
19
20
|
xiaogpt/langchain/examples/email/mail_box.py,sha256=xauqrjE4-G4XPQnokUPE-MZgAaHQ_VrUDLlbfYTdCoo,6372
|
@@ -23,5 +24,5 @@ xiaogpt/tts/base.py,sha256=fljxdXy60HXqdLXyQlsJZtzJBo5VtTwLkkWTi58tzQc,4656
|
|
23
24
|
xiaogpt/tts/mi.py,sha256=1MzCB27DBohPQ_4Xz4W_FV9p-chJFDavOHB89NviLcM,1095
|
24
25
|
xiaogpt/tts/tetos.py,sha256=9DaSrfU8Pf_aa7mI6JXMvE70XYJogIPvbim4Yuhcc3k,1903
|
25
26
|
xiaogpt/utils.py,sha256=B7NCH7g19hcwHDXsnBJPTU6UcWnXoEntKWm-pgcet2I,2072
|
26
|
-
xiaogpt/xiaogpt.py,sha256=
|
27
|
-
xiaogpt-2.
|
27
|
+
xiaogpt/xiaogpt.py,sha256=r1wl94caTA3CfK-tSz3b8D2Qt7J6uPzNlWMLvoeuspw,15826
|
28
|
+
xiaogpt-2.62.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|