xiaogpt 1.71__py3-none-any.whl → 1.81__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/bard_bot.py +3 -2
- xiaogpt/bot/base_bot.py +33 -2
- xiaogpt/bot/chatgptapi_bot.py +6 -17
- xiaogpt/bot/glm_bot.py +6 -15
- xiaogpt/bot/gpt3_bot.py +2 -2
- xiaogpt/bot/langchain_bot.py +34 -21
- xiaogpt/bot/newbing_bot.py +3 -3
- xiaogpt/langchain/callbacks.py +87 -0
- xiaogpt/langchain/chain.py +12 -15
- xiaogpt/utils.py +1 -1
- xiaogpt/xiaogpt.py +21 -19
- {xiaogpt-1.71.dist-info → xiaogpt-1.81.dist-info}/METADATA +4 -4
- xiaogpt-1.81.dist-info/RECORD +23 -0
- xiaogpt/langchain/stream_call_back.py +0 -16
- xiaogpt-1.71.dist-info/RECORD +0 -23
- {xiaogpt-1.71.dist-info → xiaogpt-1.81.dist-info}/WHEEL +0 -0
- {xiaogpt-1.71.dist-info → xiaogpt-1.81.dist-info}/entry_points.txt +0 -0
- {xiaogpt-1.71.dist-info → xiaogpt-1.81.dist-info}/licenses/LICENSE +0 -0
xiaogpt/bot/bard_bot.py
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
"""ChatGLM bot"""
|
2
2
|
from __future__ import annotations
|
3
|
+
|
3
4
|
from typing import Any
|
4
5
|
|
5
6
|
from bardapi import BardAsync
|
6
7
|
from rich import print
|
7
8
|
|
8
|
-
from xiaogpt.bot.base_bot import BaseBot
|
9
|
+
from xiaogpt.bot.base_bot import BaseBot, ChatHistoryMixin
|
9
10
|
|
10
11
|
|
11
|
-
class BardBot(BaseBot):
|
12
|
+
class BardBot(ChatHistoryMixin, BaseBot):
|
12
13
|
def __init__(
|
13
14
|
self,
|
14
15
|
bard_token: str,
|
xiaogpt/bot/base_bot.py
CHANGED
@@ -9,8 +9,6 @@ T = TypeVar("T", bound="BaseBot")
|
|
9
9
|
|
10
10
|
|
11
11
|
class BaseBot(ABC):
|
12
|
-
history: list
|
13
|
-
|
14
12
|
@abstractmethod
|
15
13
|
async def ask(self, query: str, **options: Any) -> str:
|
16
14
|
pass
|
@@ -23,3 +21,36 @@ class BaseBot(ABC):
|
|
23
21
|
@abstractmethod
|
24
22
|
def from_config(cls: type[T], config: Config) -> T:
|
25
23
|
pass
|
24
|
+
|
25
|
+
@abstractmethod
|
26
|
+
def has_history(self) -> bool:
|
27
|
+
pass
|
28
|
+
|
29
|
+
@abstractmethod
|
30
|
+
def change_prompt(self, new_prompt: str) -> None:
|
31
|
+
pass
|
32
|
+
|
33
|
+
|
34
|
+
class ChatHistoryMixin:
|
35
|
+
history: list[tuple[str, str]]
|
36
|
+
|
37
|
+
def has_history(self) -> bool:
|
38
|
+
return bool(self.history)
|
39
|
+
|
40
|
+
def change_prompt(self, new_prompt: str) -> None:
|
41
|
+
if self.history:
|
42
|
+
print(self.history)
|
43
|
+
self.history[0][0] = new_prompt
|
44
|
+
|
45
|
+
def get_messages(self) -> list[dict]:
|
46
|
+
ms = []
|
47
|
+
for h in self.history:
|
48
|
+
ms.append({"role": "user", "content": h[0]})
|
49
|
+
ms.append({"role": "assistant", "content": h[1]})
|
50
|
+
return ms
|
51
|
+
|
52
|
+
def add_message(self, query: str, message: str) -> None:
|
53
|
+
self.history.append([f"{query}", message])
|
54
|
+
# only keep 5 history
|
55
|
+
first_history = self.history.pop(0)
|
56
|
+
self.history = [first_history] + self.history[-5:]
|
xiaogpt/bot/chatgptapi_bot.py
CHANGED
@@ -3,11 +3,11 @@ from __future__ import annotations
|
|
3
3
|
import openai
|
4
4
|
from rich import print
|
5
5
|
|
6
|
-
from xiaogpt.bot.base_bot import BaseBot
|
6
|
+
from xiaogpt.bot.base_bot import BaseBot, ChatHistoryMixin
|
7
7
|
from xiaogpt.utils import split_sentences
|
8
8
|
|
9
9
|
|
10
|
-
class ChatGPTBot(BaseBot):
|
10
|
+
class ChatGPTBot(ChatHistoryMixin, BaseBot):
|
11
11
|
default_options = {"model": "gpt-3.5-turbo-0613"}
|
12
12
|
|
13
13
|
def __init__(
|
@@ -42,10 +42,7 @@ class ChatGPTBot(BaseBot):
|
|
42
42
|
)
|
43
43
|
|
44
44
|
async def ask(self, query, **options):
|
45
|
-
ms =
|
46
|
-
for h in self.history:
|
47
|
-
ms.append({"role": "user", "content": h[0]})
|
48
|
-
ms.append({"role": "assistant", "content": h[1]})
|
45
|
+
ms = self.get_messages()
|
49
46
|
ms.append({"role": "user", "content": f"{query}"})
|
50
47
|
kwargs = {**self.default_options, **options}
|
51
48
|
try:
|
@@ -60,18 +57,12 @@ class ChatGPTBot(BaseBot):
|
|
60
57
|
.encode("utf8")
|
61
58
|
.decode()
|
62
59
|
)
|
63
|
-
self.
|
64
|
-
# only keep 5 history
|
65
|
-
first_history = self.history.pop(0)
|
66
|
-
self.history = [first_history] + self.history[-5:]
|
60
|
+
self.add_message(query, message)
|
67
61
|
print(message)
|
68
62
|
return message
|
69
63
|
|
70
64
|
async def ask_stream(self, query, **options):
|
71
|
-
ms =
|
72
|
-
for h in self.history:
|
73
|
-
ms.append({"role": "user", "content": h[0]})
|
74
|
-
ms.append({"role": "assistant", "content": h[1]})
|
65
|
+
ms = self.get_messages()
|
75
66
|
ms.append({"role": "user", "content": f"{query}"})
|
76
67
|
kwargs = {"model": "gpt-3.5-turbo", **options}
|
77
68
|
if openai.api_type == "azure":
|
@@ -99,6 +90,4 @@ class ChatGPTBot(BaseBot):
|
|
99
90
|
yield sentence
|
100
91
|
finally:
|
101
92
|
print()
|
102
|
-
self.
|
103
|
-
first_history = self.history.pop(0)
|
104
|
-
self.history = [first_history] + self.history[-5:]
|
93
|
+
self.add_message(query, message)
|
xiaogpt/bot/glm_bot.py
CHANGED
@@ -1,21 +1,18 @@
|
|
1
1
|
"""ChatGLM bot"""
|
2
2
|
from __future__ import annotations
|
3
3
|
|
4
|
-
from typing import Any
|
4
|
+
from typing import Any
|
5
5
|
|
6
6
|
import zhipuai
|
7
7
|
from rich import print
|
8
8
|
|
9
|
-
from xiaogpt.bot.base_bot import BaseBot
|
9
|
+
from xiaogpt.bot.base_bot import BaseBot, ChatHistoryMixin
|
10
10
|
|
11
11
|
|
12
|
-
class GLMBot(BaseBot):
|
12
|
+
class GLMBot(ChatHistoryMixin, BaseBot):
|
13
13
|
default_options = {"model": "chatglm_130b"}
|
14
14
|
|
15
|
-
def __init__(
|
16
|
-
self,
|
17
|
-
glm_key: str,
|
18
|
-
) -> None:
|
15
|
+
def __init__(self, glm_key: str) -> None:
|
19
16
|
self.history = []
|
20
17
|
zhipuai.api_key = glm_key
|
21
18
|
|
@@ -24,10 +21,7 @@ class GLMBot(BaseBot):
|
|
24
21
|
return cls(glm_key=config.glm_key)
|
25
22
|
|
26
23
|
def ask(self, query, **options):
|
27
|
-
ms =
|
28
|
-
for h in self.history:
|
29
|
-
ms.append({"role": "user", "content": h[0]})
|
30
|
-
ms.append({"role": "assistant", "content": h[1]})
|
24
|
+
ms = self.get_messages()
|
31
25
|
kwargs = {**self.default_options, **options}
|
32
26
|
kwargs["prompt"] = ms
|
33
27
|
ms.append({"role": "user", "content": f"{query}"})
|
@@ -40,10 +34,7 @@ class GLMBot(BaseBot):
|
|
40
34
|
for i in r.events():
|
41
35
|
message += str(i.data)
|
42
36
|
|
43
|
-
self.
|
44
|
-
# only keep 5 history
|
45
|
-
first_history = self.history.pop(0)
|
46
|
-
self.history = [first_history] + self.history[-5:]
|
37
|
+
self.add_message(query, message)
|
47
38
|
print(message)
|
48
39
|
return message
|
49
40
|
|
xiaogpt/bot/gpt3_bot.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
import openai
|
2
2
|
from rich import print
|
3
3
|
|
4
|
-
from xiaogpt.bot.base_bot import BaseBot
|
4
|
+
from xiaogpt.bot.base_bot import BaseBot, ChatHistoryMixin
|
5
5
|
from xiaogpt.utils import split_sentences
|
6
6
|
|
7
7
|
|
8
|
-
class GPT3Bot(BaseBot):
|
8
|
+
class GPT3Bot(ChatHistoryMixin, BaseBot):
|
9
9
|
def __init__(self, openai_key, api_base=None, proxy=None):
|
10
10
|
openai.api_key = openai_key
|
11
11
|
if api_base:
|
xiaogpt/bot/langchain_bot.py
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import
|
3
|
+
import asyncio
|
4
|
+
import os
|
5
|
+
|
6
|
+
from langchain.memory import ConversationBufferWindowMemory
|
4
7
|
from rich import print
|
5
8
|
|
6
9
|
from xiaogpt.bot.base_bot import BaseBot
|
7
|
-
from xiaogpt.
|
8
|
-
|
10
|
+
from xiaogpt.langchain.callbacks import AsyncIteratorCallbackHandler
|
9
11
|
from xiaogpt.langchain.chain import agent_search
|
10
|
-
from xiaogpt.
|
11
|
-
|
12
|
-
import os
|
12
|
+
from xiaogpt.utils import split_sentences
|
13
13
|
|
14
14
|
|
15
15
|
class LangChainBot(BaseBot):
|
@@ -17,32 +17,45 @@ class LangChainBot(BaseBot):
|
|
17
17
|
self,
|
18
18
|
openai_key: str,
|
19
19
|
serpapi_api_key: str,
|
20
|
+
proxy: str | None = None,
|
21
|
+
api_base: str | None = None,
|
20
22
|
) -> None:
|
21
23
|
# Set environment indicators
|
22
24
|
os.environ["OPENAI_API_KEY"] = openai_key
|
23
25
|
os.environ["SERPAPI_API_KEY"] = serpapi_api_key
|
24
|
-
|
25
|
-
|
26
|
+
if api_base:
|
27
|
+
os.environ["OPENAI_API_BASE"] = api_base
|
28
|
+
if proxy:
|
29
|
+
os.environ["OPENAI_PROXY"] = proxy
|
30
|
+
self.memory = ConversationBufferWindowMemory(return_messages=True)
|
31
|
+
|
32
|
+
def has_history(self) -> bool:
|
33
|
+
return len(self.memory.chat_memory.messages) > 0
|
34
|
+
|
35
|
+
def change_prompt(self, new_prompt: str) -> None:
|
36
|
+
self.memory.clear()
|
37
|
+
self.memory.chat_memory.add_user_message(new_prompt)
|
26
38
|
|
27
39
|
@classmethod
|
28
40
|
def from_config(cls, config):
|
29
|
-
return cls(
|
41
|
+
return cls(
|
42
|
+
openai_key=config.openai_key,
|
43
|
+
serpapi_api_key=config.serpapi_api_key,
|
44
|
+
proxy=config.proxy,
|
45
|
+
api_base=config.api_base,
|
46
|
+
)
|
30
47
|
|
31
48
|
async def ask(self, query, **options):
|
32
|
-
|
33
|
-
raise Exception(
|
34
|
-
"The bot does not support it. Please use 'ask_stream,add: --stream'"
|
35
|
-
)
|
49
|
+
return await agent_search(query, self.memory)
|
36
50
|
|
37
51
|
async def ask_stream(self, query, **options):
|
38
|
-
|
52
|
+
callback = AsyncIteratorCallbackHandler()
|
53
|
+
task = asyncio.create_task(agent_search(query, self.memory, callback))
|
39
54
|
try:
|
40
|
-
|
41
|
-
|
42
|
-
token = streaming_call_queue.get()
|
43
|
-
print(token, end="")
|
44
|
-
yield token
|
45
|
-
else:
|
46
|
-
break
|
55
|
+
async for message in split_sentences(callback.aiter()):
|
56
|
+
yield message
|
47
57
|
except Exception as e:
|
48
58
|
print("An error occurred:", str(e))
|
59
|
+
finally:
|
60
|
+
print()
|
61
|
+
await task
|
xiaogpt/bot/newbing_bot.py
CHANGED
@@ -4,13 +4,13 @@ import re
|
|
4
4
|
|
5
5
|
from EdgeGPT import Chatbot, ConversationStyle
|
6
6
|
|
7
|
-
from xiaogpt.bot.base_bot import BaseBot
|
7
|
+
from xiaogpt.bot.base_bot import BaseBot, ChatHistoryMixin
|
8
8
|
from xiaogpt.utils import split_sentences
|
9
9
|
|
10
10
|
_reference_link_re = re.compile(r"\[\d+\]: .+?\n+")
|
11
11
|
|
12
12
|
|
13
|
-
class NewBingBot(BaseBot):
|
13
|
+
class NewBingBot(ChatHistoryMixin, BaseBot):
|
14
14
|
def __init__(
|
15
15
|
self,
|
16
16
|
bing_cookie_path: str = "",
|
@@ -52,7 +52,7 @@ class NewBingBot(BaseBot):
|
|
52
52
|
kwargs = {"conversation_style": ConversationStyle.balanced, **options}
|
53
53
|
try:
|
54
54
|
completion = self._bot.ask_stream(prompt=query, **kwargs)
|
55
|
-
except Exception
|
55
|
+
except Exception:
|
56
56
|
return
|
57
57
|
|
58
58
|
async def text_gen():
|
@@ -0,0 +1,87 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import asyncio
|
4
|
+
from typing import Any, AsyncIterator
|
5
|
+
from uuid import UUID
|
6
|
+
|
7
|
+
from langchain.callbacks.base import AsyncCallbackHandler
|
8
|
+
|
9
|
+
|
10
|
+
class AsyncIteratorCallbackHandler(AsyncCallbackHandler):
|
11
|
+
"""Callback handler that returns an async iterator."""
|
12
|
+
|
13
|
+
@property
|
14
|
+
def always_verbose(self) -> bool:
|
15
|
+
return True
|
16
|
+
|
17
|
+
def __init__(self) -> None:
|
18
|
+
self.queue = asyncio.Queue()
|
19
|
+
self.done = asyncio.Event()
|
20
|
+
|
21
|
+
async def on_chain_start(
|
22
|
+
self,
|
23
|
+
serialized: dict[str, Any],
|
24
|
+
inputs: dict[str, Any],
|
25
|
+
*,
|
26
|
+
run_id: UUID,
|
27
|
+
parent_run_id: UUID | None = None,
|
28
|
+
tags: list[str] | None = None,
|
29
|
+
metadata: dict[str, Any] | None = None,
|
30
|
+
**kwargs: Any,
|
31
|
+
) -> None:
|
32
|
+
self.done.clear()
|
33
|
+
|
34
|
+
async def on_llm_new_token(self, token: str, **kwargs: Any) -> None:
|
35
|
+
if token is not None and token != "":
|
36
|
+
print(token, end="", flush=True)
|
37
|
+
self.queue.put_nowait(token)
|
38
|
+
|
39
|
+
async def on_chain_end(
|
40
|
+
self,
|
41
|
+
outputs: dict[str, Any],
|
42
|
+
*,
|
43
|
+
run_id: UUID,
|
44
|
+
parent_run_id: UUID | None = None,
|
45
|
+
tags: list[str] | None = None,
|
46
|
+
**kwargs: Any,
|
47
|
+
) -> None:
|
48
|
+
self.done.set()
|
49
|
+
|
50
|
+
async def on_chain_error(
|
51
|
+
self,
|
52
|
+
error: BaseException,
|
53
|
+
*,
|
54
|
+
run_id: UUID,
|
55
|
+
parent_run_id: UUID | None = None,
|
56
|
+
tags: list[str] | None = None,
|
57
|
+
**kwargs: Any,
|
58
|
+
) -> None:
|
59
|
+
self.done.set()
|
60
|
+
|
61
|
+
async def aiter(self) -> AsyncIterator[str]:
|
62
|
+
while not self.queue.empty() or not self.done.is_set():
|
63
|
+
# Wait for the next token in the queue,
|
64
|
+
# but stop waiting if the done event is set
|
65
|
+
done, other = await asyncio.wait(
|
66
|
+
[
|
67
|
+
# NOTE: If you add other tasks here, update the code below,
|
68
|
+
# which assumes each set has exactly one task each
|
69
|
+
asyncio.ensure_future(self.queue.get()),
|
70
|
+
asyncio.ensure_future(self.done.wait()),
|
71
|
+
],
|
72
|
+
return_when=asyncio.FIRST_COMPLETED,
|
73
|
+
)
|
74
|
+
|
75
|
+
# Cancel the other task
|
76
|
+
if other:
|
77
|
+
other.pop().cancel()
|
78
|
+
|
79
|
+
# Extract the value of the first completed task
|
80
|
+
token_or_done = done.pop().result()
|
81
|
+
|
82
|
+
# If the extracted value is the boolean True, the done event was set
|
83
|
+
if token_or_done is True:
|
84
|
+
break
|
85
|
+
|
86
|
+
# Otherwise, the extracted value is a token, which we yield
|
87
|
+
yield token_or_done
|
xiaogpt/langchain/chain.py
CHANGED
@@ -1,23 +1,20 @@
|
|
1
|
-
from
|
2
|
-
|
3
|
-
from langchain.
|
4
|
-
from langchain.
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from langchain.agents import AgentType, Tool, initialize_agent
|
4
|
+
from langchain.callbacks.base import BaseCallbackHandler
|
5
5
|
from langchain.chains import LLMMathChain
|
6
|
-
from langchain.utilities import SerpAPIWrapper
|
7
6
|
from langchain.chat_models import ChatOpenAI
|
8
|
-
from langchain.memory import
|
9
|
-
from
|
10
|
-
from langchain.agents.agent_toolkits import ZapierToolkit
|
11
|
-
from langchain.utilities.zapier import ZapierNLAWrapper
|
12
|
-
from langchain.memory import ConversationBufferMemory
|
7
|
+
from langchain.schema.memory import BaseMemory
|
8
|
+
from langchain.utilities import SerpAPIWrapper
|
13
9
|
|
14
10
|
|
15
|
-
def agent_search(
|
11
|
+
async def agent_search(
|
12
|
+
query: str, memeory: BaseMemory, callback: BaseCallbackHandler | None = None
|
13
|
+
) -> str:
|
16
14
|
llm = ChatOpenAI(
|
17
15
|
streaming=True,
|
18
16
|
temperature=0,
|
19
17
|
model="gpt-3.5-turbo-0613",
|
20
|
-
callbacks=[StreamCallbackHandler()],
|
21
18
|
)
|
22
19
|
|
23
20
|
# Initialization: search chain, mathematical calculation chain
|
@@ -31,8 +28,8 @@ def agent_search(query):
|
|
31
28
|
]
|
32
29
|
|
33
30
|
agent = initialize_agent(
|
34
|
-
tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=False
|
31
|
+
tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=False, memory=memeory
|
35
32
|
)
|
36
|
-
|
33
|
+
callbacks = [callback] if callback else None
|
37
34
|
# query eg:'杭州亚运会中国队获得了多少枚金牌?' // '计算3的2次方'
|
38
|
-
agent.
|
35
|
+
return await agent.arun(query, callbacks=callbacks)
|
xiaogpt/utils.py
CHANGED
@@ -29,7 +29,7 @@ def calculate_tts_elapse(text: str) -> float:
|
|
29
29
|
return len(_no_elapse_chars.sub("", text)) / speed
|
30
30
|
|
31
31
|
|
32
|
-
_ending_punctuations = ("。", "?", "!", ";", "
|
32
|
+
_ending_punctuations = ("。", "?", "!", ";", "\n", "?", "!", ";")
|
33
33
|
|
34
34
|
|
35
35
|
async def split_sentences(text_stream: AsyncIterator[str]) -> AsyncIterator[str]:
|
xiaogpt/xiaogpt.py
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
|
+
from __future__ import annotations
|
3
|
+
|
2
4
|
import asyncio
|
3
5
|
import functools
|
4
6
|
import http.server
|
@@ -69,7 +71,6 @@ class MiGPT:
|
|
69
71
|
|
70
72
|
self.mi_token_home = Path.home() / ".mi.token"
|
71
73
|
self.last_timestamp = int(time.time() * 1000) # timestamp last call mi speaker
|
72
|
-
self.last_record = None
|
73
74
|
self.cookie_jar = None
|
74
75
|
self._chatbot = None
|
75
76
|
self.device_id = ""
|
@@ -78,7 +79,7 @@ class MiGPT:
|
|
78
79
|
self.miio_service = None
|
79
80
|
self.in_conversation = False
|
80
81
|
self.polling_event = asyncio.Event()
|
81
|
-
self.
|
82
|
+
self.last_record = asyncio.Queue(1)
|
82
83
|
self.temp_dir = None
|
83
84
|
if self.config.enable_edge_tts:
|
84
85
|
self.temp_dir = tempfile.TemporaryDirectory(prefix="xiaogpt-tts-")
|
@@ -96,14 +97,14 @@ class MiGPT:
|
|
96
97
|
self.log.debug(
|
97
98
|
"Listening new message, timestamp: %s", self.last_timestamp
|
98
99
|
)
|
99
|
-
await self.get_latest_ask_from_xiaoai(session)
|
100
|
+
new_record = await self.get_latest_ask_from_xiaoai(session)
|
100
101
|
start = time.perf_counter()
|
101
102
|
self.log.debug("Polling_event, timestamp: %s", self.last_timestamp)
|
102
103
|
await self.polling_event.wait()
|
103
104
|
if (
|
104
105
|
self.config.mute_xiaoai
|
105
|
-
and
|
106
|
-
and self.need_ask_gpt(
|
106
|
+
and new_record
|
107
|
+
and self.need_ask_gpt(new_record)
|
107
108
|
):
|
108
109
|
await self.stop_if_xiaoai_is_playing()
|
109
110
|
if (d := time.perf_counter() - start) < 1:
|
@@ -230,11 +231,9 @@ class MiGPT:
|
|
230
231
|
new_prompt = "以下都" + new_prompt
|
231
232
|
print(f"Prompt from {self.config.prompt} change to {new_prompt}")
|
232
233
|
self.config.prompt = new_prompt
|
233
|
-
|
234
|
-
print(self.chatbot.history)
|
235
|
-
self.chatbot.history[0][0] = new_prompt
|
234
|
+
self.chatbot.change_prompt(new_prompt)
|
236
235
|
|
237
|
-
async def get_latest_ask_from_xiaoai(self, session):
|
236
|
+
async def get_latest_ask_from_xiaoai(self, session: ClientSession) -> dict | None:
|
238
237
|
retries = 3
|
239
238
|
for i in range(retries):
|
240
239
|
try:
|
@@ -261,18 +260,23 @@ class MiGPT:
|
|
261
260
|
await self.init_all_data(self.session)
|
262
261
|
else:
|
263
262
|
return self._get_last_query(data)
|
263
|
+
return None
|
264
264
|
|
265
|
-
def _get_last_query(self, data):
|
265
|
+
def _get_last_query(self, data: dict) -> dict | None:
|
266
266
|
if d := data.get("data"):
|
267
267
|
records = json.loads(d).get("records")
|
268
268
|
if not records:
|
269
|
-
return
|
269
|
+
return None
|
270
270
|
last_record = records[0]
|
271
271
|
timestamp = last_record.get("time")
|
272
272
|
if timestamp > self.last_timestamp:
|
273
|
-
|
274
|
-
|
275
|
-
|
273
|
+
try:
|
274
|
+
self.last_record.put_nowait(last_record)
|
275
|
+
self.last_timestamp = timestamp
|
276
|
+
return last_record
|
277
|
+
except asyncio.QueueFull:
|
278
|
+
pass
|
279
|
+
return None
|
276
280
|
|
277
281
|
async def do_tts(self, value, wait_for_finish=False):
|
278
282
|
if not self.config.use_command:
|
@@ -403,7 +407,7 @@ class MiGPT:
|
|
403
407
|
task = asyncio.create_task(collect_stream(queue))
|
404
408
|
task.add_done_callback(done_callback)
|
405
409
|
while True:
|
406
|
-
if is_eof or self.
|
410
|
+
if is_eof or not self.last_record.empty():
|
407
411
|
break
|
408
412
|
message = await queue.get()
|
409
413
|
if message is EOF:
|
@@ -451,9 +455,7 @@ class MiGPT:
|
|
451
455
|
print(f"或用`{self.config.start_conversation}`开始持续对话")
|
452
456
|
while True:
|
453
457
|
self.polling_event.set()
|
454
|
-
await self.
|
455
|
-
self.new_record_event.clear()
|
456
|
-
new_record = self.last_record
|
458
|
+
new_record = await self.last_record.get()
|
457
459
|
self.polling_event.clear() # stop polling when processing the question
|
458
460
|
query = new_record.get("query", "").strip()
|
459
461
|
|
@@ -485,7 +487,7 @@ class MiGPT:
|
|
485
487
|
|
486
488
|
print("-" * 20)
|
487
489
|
print("问题:" + query + "?")
|
488
|
-
if not self.chatbot.
|
490
|
+
if not self.chatbot.has_history():
|
489
491
|
query = f"{query},{self.config.prompt}"
|
490
492
|
if self.config.mute_xiaoai:
|
491
493
|
await self.stop_if_xiaoai_is_playing()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: xiaogpt
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.81
|
4
4
|
Summary: Play ChatGPT or other LLM with xiaomi AI speaker
|
5
5
|
Author-Email: yihong0618 <zouzou0208@gmail.com>
|
6
6
|
License: MIT
|
@@ -8,7 +8,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
8
8
|
Classifier: Operating System :: OS Independent
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
10
10
|
Project-URL: Homepage, https://github.com/yihong0618/xiaogpt
|
11
|
-
Requires-Python: >=3.
|
11
|
+
Requires-Python: >=3.8.1
|
12
12
|
Requires-Dist: miservice_fork
|
13
13
|
Requires-Dist: openai
|
14
14
|
Requires-Dist: aiohttp
|
@@ -19,10 +19,10 @@ Requires-Dist: edge-tts>=6.1.3
|
|
19
19
|
Requires-Dist: EdgeGPT==0.1.26
|
20
20
|
Requires-Dist: langchain==0.0.301
|
21
21
|
Requires-Dist: datetime==5.2
|
22
|
-
Requires-Dist:
|
22
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
23
23
|
Requires-Dist: chardet==5.1.0
|
24
24
|
Requires-Dist: typing==3.7.4.3
|
25
|
-
Requires-Dist: google-search-results
|
25
|
+
Requires-Dist: google-search-results>=2.4.2
|
26
26
|
Requires-Dist: numexpr==2.8.6
|
27
27
|
Description-Content-Type: text/markdown
|
28
28
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
xiaogpt-1.81.dist-info/METADATA,sha256=GxxsqfbaekP1hfO5djLz3qVw9HcuhRn7TGN3Vq8eyZg,14306
|
2
|
+
xiaogpt-1.81.dist-info/WHEEL,sha256=C8f_gqhOWmHrh81n3Ukx5iURrqMhsHla81fuY1yuwvs,90
|
3
|
+
xiaogpt-1.81.dist-info/entry_points.txt,sha256=zLFzA72qQ_eWBepdA2YU5vdXFqORH8wXhv2Ox1vnYP8,46
|
4
|
+
xiaogpt-1.81.dist-info/licenses/LICENSE,sha256=XdClh516MvlnOf9749JZHCxSB7y6_fyXcWmLDz6IkZY,1063
|
5
|
+
xiaogpt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
+
xiaogpt/__main__.py,sha256=MSmt_5Xg84uHqzTN38JwgseJK8rsJn_11A8WD99VtEo,61
|
7
|
+
xiaogpt/bot/__init__.py,sha256=raXM63RFkZFQWLwT0sz8NY0jAkCQip9TmIShpEU4wIA,909
|
8
|
+
xiaogpt/bot/bard_bot.py,sha256=_OX8UVyksdxQb5E9xPkX2V0yIC24PUL8xUTONe5sR3c,811
|
9
|
+
xiaogpt/bot/base_bot.py,sha256=YmFoNK4-_D-3bXSbt6cfPsm5rZiaoVyaEps5bNih6OE,1452
|
10
|
+
xiaogpt/bot/chatgptapi_bot.py,sha256=rDhtQ-YCv27_3MyLU0sMnr4VDrHAu7hI5AdJUoij3yE,2983
|
11
|
+
xiaogpt/bot/glm_bot.py,sha256=7VZJGRYU1Xlo6N7gICIsGMV5JkNgAbfBQKvhoO8ren4,1107
|
12
|
+
xiaogpt/bot/gpt3_bot.py,sha256=IoMhsfmQ-ITy6V1nRrdm755vyEsS0Bb0bOLIv-F-fr8,1863
|
13
|
+
xiaogpt/bot/langchain_bot.py,sha256=Kc4qXWIR1GBucxWmm1Y5YpAB3UzTVZmUpaEZSQIoaYY,1919
|
14
|
+
xiaogpt/bot/newbing_bot.py,sha256=8VONq_2VAK66zUnjCacM9jg_4oHlYHTuKLAHob48Q2I,2187
|
15
|
+
xiaogpt/cli.py,sha256=L0nmhSj6C931ya4KHIBktltnYTOGgPJNMavyXefTGpY,4478
|
16
|
+
xiaogpt/config.py,sha256=B3AiG4WZjMGuwJrR2yMe9TiaVEoLN7N6D7CUYTpcsPc,5863
|
17
|
+
xiaogpt/langchain/callbacks.py,sha256=yR9AXQt9OHVYBWC47Q1I_BUT4Xg9iM44vnW2vv0BLpE,2616
|
18
|
+
xiaogpt/langchain/chain.py,sha256=rcbXzCV6H_r2r-Mi7mA__X8UZctDMl7nHloy3SAXXvw,1381
|
19
|
+
xiaogpt/langchain/examples/email/mail_box.py,sha256=kpAZmfl5clbDBOkvHaaWZ_QY-VLBBvV1dsuegEptClw,6360
|
20
|
+
xiaogpt/langchain/examples/email/mail_summary_tools.py,sha256=6cWvBJUaA7iaywcHdbUoww8WiCtaNw3TmwyxyF4DY7E,1561
|
21
|
+
xiaogpt/utils.py,sha256=B7NCH7g19hcwHDXsnBJPTU6UcWnXoEntKWm-pgcet2I,2072
|
22
|
+
xiaogpt/xiaogpt.py,sha256=Ojq0Pw3SVsVzwgImpWS87XrKqCAHIfddqgmoA5_kMf0,19885
|
23
|
+
xiaogpt-1.81.dist-info/RECORD,,
|
@@ -1,16 +0,0 @@
|
|
1
|
-
import chardet
|
2
|
-
from queue import Queue
|
3
|
-
from typing import Any, Dict, List, Optional
|
4
|
-
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
|
5
|
-
|
6
|
-
DEFAULT_ANSWER_PREFIX_TOKENS = [""]
|
7
|
-
streaming_call_queue = Queue()
|
8
|
-
|
9
|
-
|
10
|
-
class StreamCallbackHandler(StreamingStdOutCallbackHandler):
|
11
|
-
def on_llm_new_token(self, token: str, **kwargs: Any) -> None:
|
12
|
-
token_copy = token
|
13
|
-
code = chardet.detect(token_copy.encode())["encoding"]
|
14
|
-
if code is not None:
|
15
|
-
# Receive stream messages into the queue and dequeue when ask_stream
|
16
|
-
streaming_call_queue.put(token)
|
xiaogpt-1.71.dist-info/RECORD
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
xiaogpt-1.71.dist-info/METADATA,sha256=QQU5dfoNTdqIjzHigKN1Qj5gJrtE2Ao05yp8h3dIV6g,14294
|
2
|
-
xiaogpt-1.71.dist-info/WHEEL,sha256=C8f_gqhOWmHrh81n3Ukx5iURrqMhsHla81fuY1yuwvs,90
|
3
|
-
xiaogpt-1.71.dist-info/entry_points.txt,sha256=zLFzA72qQ_eWBepdA2YU5vdXFqORH8wXhv2Ox1vnYP8,46
|
4
|
-
xiaogpt-1.71.dist-info/licenses/LICENSE,sha256=XdClh516MvlnOf9749JZHCxSB7y6_fyXcWmLDz6IkZY,1063
|
5
|
-
xiaogpt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
xiaogpt/__main__.py,sha256=MSmt_5Xg84uHqzTN38JwgseJK8rsJn_11A8WD99VtEo,61
|
7
|
-
xiaogpt/bot/__init__.py,sha256=raXM63RFkZFQWLwT0sz8NY0jAkCQip9TmIShpEU4wIA,909
|
8
|
-
xiaogpt/bot/bard_bot.py,sha256=UKgfLLKwte8XBZFl7H7bAQRZM17qbI8Sa2AUrtzBrwM,774
|
9
|
-
xiaogpt/bot/base_bot.py,sha256=kzbUw1eQrgFqkE_eZZrWmcbPdwFrQezJBLm7cJAM8qw,554
|
10
|
-
xiaogpt/bot/chatgptapi_bot.py,sha256=cq0CwXD6ynNw7hB-bYubP0Nsz7pT49JYKp0_UjRoIps,3477
|
11
|
-
xiaogpt/bot/glm_bot.py,sha256=bCJnwo4J6746kkRNq_OTrUgT-XZvV5KTndCz1ftiHIg,1386
|
12
|
-
xiaogpt/bot/gpt3_bot.py,sha256=Ju_c9izW09XbCCSgZTp-3Rjz1zBMeBGj19zH0UwqGFw,1827
|
13
|
-
xiaogpt/bot/langchain_bot.py,sha256=0AHdm8oUfGhoxz3B-stf_TdkGmmOBBSGrRsjiN24474,1417
|
14
|
-
xiaogpt/bot/newbing_bot.py,sha256=fRRrNnnw6xVFlkp4aQ37XRrOCnZmc2tCyMmW7BFgrOE,2156
|
15
|
-
xiaogpt/cli.py,sha256=L0nmhSj6C931ya4KHIBktltnYTOGgPJNMavyXefTGpY,4478
|
16
|
-
xiaogpt/config.py,sha256=B3AiG4WZjMGuwJrR2yMe9TiaVEoLN7N6D7CUYTpcsPc,5863
|
17
|
-
xiaogpt/langchain/chain.py,sha256=TkI4Arp8t0dIs7xy94V6yhaO6FyAy-2sQQQJd4ZNin8,1481
|
18
|
-
xiaogpt/langchain/examples/email/mail_box.py,sha256=kpAZmfl5clbDBOkvHaaWZ_QY-VLBBvV1dsuegEptClw,6360
|
19
|
-
xiaogpt/langchain/examples/email/mail_summary_tools.py,sha256=6cWvBJUaA7iaywcHdbUoww8WiCtaNw3TmwyxyF4DY7E,1561
|
20
|
-
xiaogpt/langchain/stream_call_back.py,sha256=NHlgtETZkD5Ydt1Fm-sj5iZmBi0Fn5hBwVcPYzTyCsE,606
|
21
|
-
xiaogpt/utils.py,sha256=kJ8nOBkilEoo1i2uUSp9tkUWV4pWrd5_EzEicZXzNjY,2071
|
22
|
-
xiaogpt/xiaogpt.py,sha256=sPuvNDVT3Gy4q1BM4kiMZodtOGi2yH2dcbZ8JLuF2I0,19846
|
23
|
-
xiaogpt-1.71.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|