Skip to content

Commit e4b30b4

Browse files
authored
feat: support gemini close #402 #412 #403 #338 (#420)
* feat: support gemini close #402 #412 #403 #338 Signed-off-by: yihong0618 <[email protected]> * fix: versions things Signed-off-by: yihong0618 <[email protected]> * fix: lint Signed-off-by: yihong0618 <[email protected]> --------- Signed-off-by: yihong0618 <[email protected]>
1 parent 05a2027 commit e4b30b4

File tree

8 files changed

+866
-733
lines changed

8 files changed

+866
-733
lines changed

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Play ChatGPT and other LLM with Xiaomi AI Speaker
1616
- ChatGPT
1717
- New Bing
1818
- [ChatGLM](http://open.bigmodel.cn/)
19+
- [Gemini](https://makersuite.google.com/app/apikey)
1920
- [Bard](https://github.com/dsdanielpark/Bard-API)
2021

2122
## Windows 获取小米音响DID
@@ -73,6 +74,8 @@ xiaogpt --hardware LX06 --mute_xiaoai --stream
7374
# 如果你想使用 gpt3 ai
7475
export OPENAI_API_KEY=${your_api_key}
7576
xiaogpt --hardware LX06 --mute_xiaoai --use_gpt3
77+
# 如果你想使用 google 的 gemini
78+
xiaogpt --hardware LX06 --mute_xiaoai --use_gemini --gemini_key ${gemini_key}
7679
# 如果你想用 edge-tts
7780
xiaogpt --hardware LX06 --cookie ${cookie} --use_chatgpt_api --tts edge
7881
# 如果你想使用 LangChain + SerpApi 实现上网检索或其他本地服务(目前仅支持 stream 模式)
@@ -101,6 +104,8 @@ python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_gpt3
101104
python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_glm --glm_key ${glm_key}
102105
# 如果你想使用 google 的 bard
103106
python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_bard --bard_token ${bard_token}
107+
# 如果你想使用 google 的 gemini
108+
python3 xiaogpt.py --hardware LX06 --mute_xiaoai --use_gemini --gemini_key ${gemini_key}
104109
# 如果你想使用 LangChain+SerpApi 实现上网检索或其他本地服务(目前仅支持 stream 模式)
105110
export OPENAI_API_KEY=${your_api_key}
106111
export SERPAPI_API_KEY=${your_serpapi_key}
@@ -153,6 +158,7 @@ Bard-API [参考](https://github.com/dsdanielpark/Bard-API)
153158
| openai_key | openai的apikey | |
154159
| serpapi_api_key | serpapi的key 参考 [SerpAPI](https://serpapi.com/) | |
155160
| glm_key | chatglm 的 apikey | |
161+
| gemini_key | gemini 的 apikey [参与](https://makersuite.google.com/app/apikey) | |
156162
| bard_token | bard 的 token 参考 [Bard-API](https://github.com/dsdanielpark/Bard-API) | |
157163
| cookie | 小爱账户cookie (如果用上面密码登录可以不填) | |
158164
| mi_did | 设备did | |

pdm.lock

+774-731
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ classifiers = [
1010
"Operating System :: OS Independent",
1111
"Programming Language :: Python :: 3",
1212
]
13-
requires-python = ">=3.8.1"
13+
requires-python = ">=3.9"
1414
dependencies = [
1515
"miservice_fork",
1616
"openai>=1",
@@ -23,6 +23,7 @@ dependencies = [
2323
"langchain>=0.0.343",
2424
"beautifulsoup4>=4.12.0",
2525
"google-search-results>=2.4.2",
26+
"google-generativeai",
2627
"numexpr>=2.8.6",
2728
]
2829
license = {text = "MIT"}

xiao_config.json.example

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"password": "",
55
"openai_key": "",
66
"glm_key": "",
7+
"gemini_key": "",
78
"bard_token": "",
89
"serpapi_api_key": "",
910
"cookie": "",

xiaogpt/bot/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from xiaogpt.bot.newbing_bot import NewBingBot
77
from xiaogpt.bot.glm_bot import GLMBot
88
from xiaogpt.bot.bard_bot import BardBot
9+
from xiaogpt.bot.gemini_bot import GeminiBot
910
from xiaogpt.bot.langchain_bot import LangChainBot
1011
from xiaogpt.config import Config
1112

@@ -15,6 +16,7 @@
1516
"chatgptapi": ChatGPTBot,
1617
"glm": GLMBot,
1718
"bard": BardBot,
19+
"gemini": GeminiBot,
1820
"langchain": LangChainBot,
1921
}
2022

@@ -32,6 +34,7 @@ def get_bot(config: Config) -> BaseBot:
3234
"NewBingBot",
3335
"GLMBot",
3436
"BardBot",
37+
"GeminiBot",
3538
"get_bot",
3639
"LangChainBot",
3740
]

xiaogpt/bot/gemini_bot.py

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""Google Gemini bot"""
2+
from __future__ import annotations
3+
4+
from typing import Any
5+
6+
from rich import print
7+
import google.generativeai as genai
8+
from google.generativeai.types.generation_types import StopCandidateException
9+
10+
from xiaogpt.bot.base_bot import BaseBot, ChatHistoryMixin
11+
12+
generation_config = {
13+
"temperature": 0.7,
14+
"top_p": 1,
15+
"top_k": 1,
16+
"max_output_tokens": 2048,
17+
}
18+
19+
safety_settings = [
20+
{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"},
21+
{"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_MEDIUM_AND_ABOVE"},
22+
{
23+
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
24+
"threshold": "BLOCK_MEDIUM_AND_ABOVE",
25+
},
26+
{
27+
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
28+
"threshold": "BLOCK_MEDIUM_AND_ABOVE",
29+
},
30+
]
31+
32+
33+
class GeminiBot(ChatHistoryMixin, BaseBot):
34+
name = "Gemini"
35+
36+
def __init__(self, gemini_key: str) -> None:
37+
genai.configure(api_key=gemini_key)
38+
self.history = []
39+
model = genai.GenerativeModel(
40+
model_name="gemini-pro",
41+
generation_config=generation_config,
42+
safety_settings=safety_settings,
43+
)
44+
self.convo = model.start_chat()
45+
46+
@classmethod
47+
def from_config(cls, config):
48+
return cls(gemini_key=config.gemini_key)
49+
50+
async def ask(self, query, **options):
51+
self.convo.send_message(query)
52+
message = self.convo.last.text.strip()
53+
print(message)
54+
if len(self.convo.history) > 10:
55+
self.convo.history = self.convo.history[2:]
56+
return message
57+
58+
async def ask_stream(self, query: str, **options: Any):
59+
if len(self.convo.history) > 10:
60+
self.convo.history = self.convo.history[2:]
61+
response = self.convo.send_message(query, stream=True)
62+
for chunk in response:
63+
print(chunk.text)
64+
yield chunk.text

xiaogpt/cli.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ def main():
3232
dest="glm_key",
3333
help="chatglm api key",
3434
)
35+
parser.add_argument(
36+
"--gemini_key",
37+
dest="gemini_key",
38+
help="gemini api key",
39+
)
3540
parser.add_argument(
3641
"--bard_token",
3742
dest="bard_token",
@@ -132,6 +137,13 @@ def main():
132137
const="bard",
133138
help="if use bard",
134139
)
140+
bot_group.add_argument(
141+
"--use_gemini",
142+
dest="bot",
143+
action="store_const",
144+
const="gemini",
145+
help="if use gemini",
146+
)
135147
parser.add_argument(
136148
"--bing_cookie_path",
137149
dest="bing_cookie_path",
@@ -141,7 +153,7 @@ def main():
141153
"--bot",
142154
dest="bot",
143155
help="bot type",
144-
choices=["gpt3", "chatgptapi", "newbing", "glm", "bard", "langchain"],
156+
choices=["gpt3", "chatgptapi", "newbing", "glm", "bard", "gemini", "langchain"],
145157
)
146158
parser.add_argument(
147159
"--config",

xiaogpt/config.py

+3
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class Config:
6262
password: str = os.getenv("MI_PASS", "")
6363
openai_key: str = os.getenv("OPENAI_API_KEY", "")
6464
glm_key: str = os.getenv("CHATGLM_KEY", "")
65+
gemini_key: str = os.getenv("GEMINI_KEY", "") # keep the old rule
6566
bard_token: str = os.getenv("BARD_TOKEN", "")
6667
serpapi_api_key: str = os.getenv("SERPAPI_API_KEY", "")
6768
proxy: str | None = None
@@ -147,6 +148,8 @@ def read_from_file(cls, config_path: str) -> dict:
147148
key, value = "bot", "newbing"
148149
elif key == "use_glm":
149150
key, value = "bot", "glm"
151+
elif key == "use_gemini":
152+
key, value = "bot", "gemini"
150153
elif key == "use_bard":
151154
key, value = "bot", "bard"
152155
elif key == "use_langchain":

0 commit comments

Comments
 (0)