Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions xiao_config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ verbose: false
proxy: ""

# ===== 对话 AI 设置 =====
# 使用的 bot 类型,目前支持 chatgptapi, glm, gemini, langchain, qwen, doubao, moonshot, yi, llama, ppio
# 使用的 bot 类型,目前支持 chatgptapi, glm, gemini, langchain, qwen, doubao, moonshot, yi, llama, ppio, jiekou
bot: chatgptapi
# 自定义 prompt
prompt: "请用300字以内回答"
Expand Down Expand Up @@ -89,9 +89,13 @@ volc_access_key: ""
volc_secret_key: ""

# ----- PPIO 派欧云 -----
# PPIO API key: https://ppio.com/docs/models/reference-authentication
# PPIO API key: https://ppio.com/settings/key-management
ppio_api_key: ""

# ----- 接口AI -----
# Jiekou AI API key: https://jiekou.ai/settings/key-management
jiekou_api_key: ""

# ===== 语音设置 =====
# 使用的 TTS 类型,目前支持 mi, edge, openai, azure, volc, baidu, google, minimax, fish
tts: mi
Expand Down
3 changes: 3 additions & 0 deletions xiaogpt/bot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from xiaogpt.bot.doubao_bot import DoubaoBot
from xiaogpt.bot.gemini_bot import GeminiBot
from xiaogpt.bot.glm_bot import GLMBot
from xiaogpt.bot.jiekou_bot import JiekouBot
from xiaogpt.bot.langchain_bot import LangChainBot
from xiaogpt.bot.llama_bot import LlamaBot
from xiaogpt.bot.moonshot_bot import MoonshotBot
Expand All @@ -24,6 +25,7 @@
"yi": YiBot,
"llama": LlamaBot,
"ppio": PPIOBot,
"jiekou": JiekouBot,
}


Expand All @@ -46,4 +48,5 @@ def get_bot(config: Config) -> BaseBot:
"YiBot",
"LlamaBot",
"PPIOBot",
"JiekouBot",
]
98 changes: 98 additions & 0 deletions xiaogpt/bot/jiekou_bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
"""Jiekou AI bot"""

from __future__ import annotations

import dataclasses
from typing import TYPE_CHECKING, ClassVar

import httpx
from rich import print

from xiaogpt.bot.base_bot import BaseBot, ChatHistoryMixin
from xiaogpt.utils import split_sentences

if TYPE_CHECKING:
import openai


@dataclasses.dataclass
class JiekouBot(ChatHistoryMixin, BaseBot):
name: ClassVar[str] = "Jiekou AI"
default_options: ClassVar[dict[str, str]] = {"model": "deepseek/deepseek-v3.2"}
jiekou_api_key: str
api_base: str = "https://api.jiekou.ai/openai"
proxy: str | None = None
history: list[tuple[str, str]] = dataclasses.field(default_factory=list, init=False)

def _make_openai_client(self, sess: httpx.AsyncClient) -> openai.AsyncOpenAI:
import openai

return openai.AsyncOpenAI(
api_key=self.jiekou_api_key,
base_url=self.api_base,
http_client=sess,
)

@classmethod
def from_config(cls, config):
return cls(
jiekou_api_key=config.jiekou_api_key,
api_base="https://api.jiekou.ai/openai",
proxy=config.proxy,
)

async def ask(self, query, **options):
ms = self.get_messages()
ms.append({"role": "user", "content": f"{query}"})
kwargs = {**self.default_options, **options}
httpx_kwargs = {}
if self.proxy:
httpx_kwargs["proxies"] = self.proxy
async with httpx.AsyncClient(trust_env=True, **httpx_kwargs) as sess:
client = self._make_openai_client(sess)
try:
completion = await client.chat.completions.create(messages=ms, **kwargs)
except Exception as e:
print(str(e))
return ""

message = completion.choices[0].message.content
self.add_message(query, message)
print(message)
return message

async def ask_stream(self, query, **options):
ms = self.get_messages()
ms.append({"role": "user", "content": f"{query}"})
kwargs = {**self.default_options, **options}
httpx_kwargs = {}
if self.proxy:
httpx_kwargs["proxies"] = self.proxy
async with httpx.AsyncClient(trust_env=True, **httpx_kwargs) as sess:
client = self._make_openai_client(sess)
try:
completion = await client.chat.completions.create(
messages=ms, stream=True, **kwargs
)
except Exception as e:
print(str(e))
return

async def text_gen():
async for event in completion:
if not event.choices:
continue
chunk_message = event.choices[0].delta
if chunk_message.content is None:
continue
print(chunk_message.content, end="")
yield chunk_message.content

message = ""
try:
async for sentence in split_sentences(text_gen()):
message += sentence
yield sentence
finally:
print()
self.add_message(query, message)
13 changes: 13 additions & 0 deletions xiaogpt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ def main():
dest="ppio_api_key",
help="PPIO api key",
)
parser.add_argument(
"--jiekou_api_key",
dest="jiekou_api_key",
help="Jiekou AI api key",
)
parser.add_argument(
"--serpapi_api_key",
dest="serpapi_api_key",
Expand Down Expand Up @@ -198,6 +203,13 @@ def main():
const="ppio",
help="if use PPIO api",
)
bot_group.add_argument(
"--use_jiekou",
dest="bot",
action="store_const",
const="jiekou",
help="if use Jiekou AI api",
)
parser.add_argument(
"--bing_cookie_path",
dest="bing_cookie_path",
Expand All @@ -218,6 +230,7 @@ def main():
"yi",
"llama",
"ppio",
"jiekou",
],
)
parser.add_argument(
Expand Down
8 changes: 8 additions & 0 deletions xiaogpt/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Config:
volc_secret_key: str = os.getenv("VOLC_SECRET_KEY", "")
volc_api_key: str = os.getenv("volc_api_key", "")
ppio_api_key: str = os.getenv("PPIO_API_KEY", "")
jiekou_api_key: str = os.getenv("JIEKOU_API_KEY", "")
proxy: str | None = None
mi_did: str = os.getenv("MI_DID", "")
keyword: Iterable[str] = KEY_WORD
Expand Down Expand Up @@ -112,6 +113,11 @@ def __post_init__(self) -> None:
raise Exception(
"Using PPIO api needs PPIO API key, please visit https://ppio.com/docs/models/reference-authentication"
)
if self.bot == "jiekou":
if not self.jiekou_api_key:
raise Exception(
"Using Jiekou AI api needs Jiekou API key, please visit https://api.jiekou.ai"
)

@property
def tts_command(self) -> str:
Expand Down Expand Up @@ -182,6 +188,8 @@ def read_from_file(cls, config_path: str) -> dict:
key, value = "bot", "langchain"
elif key == "use_ppio":
key, value = "bot", "ppio"
elif key == "use_jiekou":
key, value = "bot", "jiekou"
elif key == "enable_edge_tts":
key, value = "tts", "edge"
if key in cls.__dataclass_fields__:
Expand Down