xiaogpt 2.60__tar.gz → 2.61__tar.gz

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.
Files changed (27) hide show
  1. {xiaogpt-2.60 → xiaogpt-2.61}/PKG-INFO +11 -6
  2. {xiaogpt-2.60 → xiaogpt-2.61}/README.md +8 -3
  3. {xiaogpt-2.60 → xiaogpt-2.61}/pyproject.toml +3 -3
  4. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/bot/__init__.py +6 -3
  5. xiaogpt-2.61/xiaogpt/bot/doubao_bot.py +76 -0
  6. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/bot/gemini_bot.py +24 -6
  7. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/cli.py +7 -0
  8. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/config.py +12 -0
  9. {xiaogpt-2.60 → xiaogpt-2.61}/LICENSE +0 -0
  10. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/__init__.py +0 -0
  11. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/__main__.py +0 -0
  12. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/bot/base_bot.py +0 -0
  13. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/bot/chatgptapi_bot.py +0 -0
  14. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/bot/glm_bot.py +0 -0
  15. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/bot/langchain_bot.py +0 -0
  16. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/bot/newbing_bot.py +0 -0
  17. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/bot/qwen_bot.py +0 -0
  18. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/langchain/callbacks.py +0 -0
  19. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/langchain/chain.py +0 -0
  20. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/langchain/examples/email/mail_box.py +0 -0
  21. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/langchain/examples/email/mail_summary_tools.py +0 -0
  22. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/tts/__init__.py +0 -0
  23. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/tts/base.py +0 -0
  24. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/tts/mi.py +0 -0
  25. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/tts/tetos.py +0 -0
  26. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/utils.py +0 -0
  27. {xiaogpt-2.60 → xiaogpt-2.61}/xiaogpt/xiaogpt.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xiaogpt
3
- Version: 2.60
3
+ Version: 2.61
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.0
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.0; extra == "locked"
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
  ## 注意
@@ -74,6 +74,8 @@ xiaogpt --hardware LX06 --mute_xiaoai --use_chatgpt_api
74
74
  xiaogpt --hardware LX06 --mute_xiaoai --stream
75
75
  # 如果你想使用 google 的 gemini
76
76
  xiaogpt --hardware LX06 --mute_xiaoai --use_gemini --gemini_key ${gemini_key}
77
+ # 如果你想使用自己的 google gemini 服务
78
+ python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_gemini --gemini_key ${gemini_key} --gemini_api_domain ${gemini_api_domain}
77
79
  # 如果你想使用阿里的通义千问
78
80
  xiaogpt --hardware LX06 --mute_xiaoai --use_qwen --qen_key ${qwen_key}
79
81
  # 如果你想用 edge-tts
@@ -101,6 +103,8 @@ python3 xiaogpt.py --hardware LX06 --mute_xiaoai --stream
101
103
  python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_glm --glm_key ${glm_key}
102
104
  # 如果你想使用 google 的 gemini
103
105
  python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_gemini --gemini_key ${gemini_key}
106
+ # 如果你想使用自己的 google gemini 服务
107
+ python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_gemini --gemini_key ${gemini_key} --gemini_api_domain ${gemini_api_domain}
104
108
  # 如果你想使用阿里的通义千问
105
109
  python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_qwen --qen_key ${qwen_key}
106
110
  # 如果你想使用 LangChain+SerpApi 实现上网检索或其他本地服务(目前仅支持 stream 模式)
@@ -155,6 +159,7 @@ ChatGLM [文档](http://open.bigmodel.cn/doc/api#chatglm_130b)
155
159
  | serpapi_api_key | serpapi的key 参考 [SerpAPI](https://serpapi.com/) | | |
156
160
  | glm_key | chatglm 的 apikey | | |
157
161
  | gemini_key | gemini 的 apikey [参考](https://makersuite.google.com/app/apikey) | | |
162
+ | gemini_api_domain | gemini 的自定义域名 [参考](https://github.com/antergone/palm-netlify-proxy) | |
158
163
  | qwen_key | qwen 的 apikey [参考](https://help.aliyun.com/zh/dashscope/developer-reference/api-details) | | |
159
164
  | cookie | 小爱账户cookie (如果用上面密码登录可以不填) | | |
160
165
  | mi_did | 设备did | | |
@@ -175,9 +180,9 @@ ChatGLM [文档](http://open.bigmodel.cn/doc/api#chatglm_130b)
175
180
  | bing_cookie_path | NewBing使用的cookie路径,参考[这里]获取 | 也可通过环境变量 `COOKIE_FILE` 设置 | |
176
181
  | bing_cookies | NewBing使用的cookie字典,参考[这里]获取 | | |
177
182
  | deployment_id | Azure OpenAI 服务的 deployment ID | 参考这个[如何找到deployment_id](https://github.com/yihong0618/xiaogpt/issues/347#issuecomment-1784410784) | |
178
- | api_base | 如果需要替换默认的api,或者使用Azure OpenAI 服务 | 例如:`https://abc-def.openai.azure.com/` | |
179
-
180
-
183
+ | api_base | 如果需要替换默认的api,或者使用Azure OpenAI 服务 | 例如:`https://abc-def.openai.azure.com/` |
184
+ | volc_access_key | 火山引擎的 access key 请在[这里](https://console.volcengine.com/iam/keymanage/)获取 | | |
185
+ | volc_secret_key | 火山引擎的 secret key 请在[这里](https://console.volcengine.com/iam/keymanage/)获取 | | |
181
186
  [这里]: https://github.com/acheong08/EdgeGPT#getting-authentication-required
182
187
 
183
188
  ## 注意
@@ -25,10 +25,10 @@ dependencies = [
25
25
  "google-generativeai",
26
26
  "numexpr>=2.8.6",
27
27
  "dashscope>=1.10.0",
28
- "tetos>=0.1.0",
28
+ "tetos>=0.1.1",
29
29
  ]
30
30
  dynamic = []
31
- version = "2.60"
31
+ version = "2.61"
32
32
 
33
33
  [project.license]
34
34
  text = "MIT"
@@ -120,7 +120,7 @@ locked = [
120
120
  "soupsieve==2.5",
121
121
  "sqlalchemy==2.0.25",
122
122
  "tenacity==8.2.3",
123
- "tetos==0.1.0",
123
+ "tetos==0.1.1",
124
124
  "tqdm==4.66.1",
125
125
  "typing-extensions==4.9.0",
126
126
  "typing-inspect==0.9.0",
@@ -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.newbing_bot import NewBingBot
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.qwen_bot import QwenBot
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
@@ -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": 2048,
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
- genai.configure(api_key=gemini_key)
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(gemini_key=config.gemini_key)
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 = self.convo.last.text.strip()
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:]
@@ -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",
@@ -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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes