Skip to content

Commit

Permalink
Merge pull request #399 from LlmKira/dev
Browse files Browse the repository at this point in the history
CodeInterpreterTool
  • Loading branch information
sudoskys authored Apr 20, 2024
2 parents 2e05c37 + 2fb6683 commit e6b2cd5
Show file tree
Hide file tree
Showing 24 changed files with 537 additions and 92 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,4 @@ config_dir/*.secret/
/.montydb/
/.snapshot/
/.tutorial.db
app/.tutorial.db
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,17 @@ This project uses the ToolCall feature.
It integrates a message queuing and snapshot system, offering plugin mechanisms and authentication prior to plugin
execution.

The model adheres to the Openai Format Schema. Please adapt using [gateway](https://github.com/Portkey-AI/gateway)
The bot adheres to the **Openai Format Schema**. Please adapt using [gateway](https://github.com/Portkey-AI/gateway)
or [one-api](https://github.com/songquanpeng/one-api) independently.

| Demo | Vision With Voice |
|-----------------------------------|------------------------------|
| ![sticker](./docs/chain_chat.gif) | ![vision](./docs/vision.gif) |
| Demo | Vision With Voice | Code Interpreter |
|-------------------------------------------------------------------------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------|
| ![sticker](https://github.com/LlmKira/Openaibot/raw/main/docs/chain_chat.gif) | ![vision](https://github.com/LlmKira/Openaibot/raw/main/docs/vision.gif) | ![code](https://github.com/LlmKira/Openaibot/raw/main/docs/code_interpreter_func.gif) |

## 🔨 Roadmap

> The program has iterated to its fourth generation.
- [x] Removal of legacy code
- [x] Deletion of metric system
- [x] Deletion of model selection system, unified to OpenAI Schema
Expand Down Expand Up @@ -81,11 +83,11 @@ or [one-api](https://github.com/songquanpeng/one-api) independently.
information, [how to develop this](https://github.com/LlmKira/Openaibot/blob/81eddbff0f136697d5ad6e13ee1a7477b26624ed/app/components/credential.py#L20).
- `Login`: Use `/login https://api.com/v1$key$model` to login

### 🧀 Plugin Previews
### 🧀 Plugin Can Do More

| Sticker Converter | Timer Function | Translate Function |
|-------------------------------------|---------------------------------|----------------------------------------------|
| ![sticker](./docs/sticker_func.gif) | ![timer](./docs/timer_func.gif) | ![translate](./docs/translate_file_func.gif) |
| Sticker Converter | Timer Function(built-in) |
|-------------------------------------|---------------------------------|
| ![sticker](./docs/sticker_func.gif) | ![timer](./docs/timer_func.gif) |

### 🎬 Platform Support

Expand Down
5 changes: 3 additions & 2 deletions app/receiver/app.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# -*- coding: utf-8 -*-
# @Time : 2023/8/17 下午8:38
import nest_asyncio
from dotenv import load_dotenv
from loguru import logger

load_dotenv()

__area__ = "receiver"

nest_asyncio.apply()

# import nest_asyncio
# nest_asyncio.apply()


def run():
Expand Down
7 changes: 4 additions & 3 deletions app/receiver/aps.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from loguru import logger
from pytz import utc

import pytz
from tzlocal import get_localzone
timezone = pytz.timezone(get_localzone().key)
Path(".cache").mkdir(exist_ok=True)
jobstores = {"default": SQLAlchemyJobStore(url="sqlite:///.cache/aps.db")}
executors = {"default": ThreadPoolExecutor(20)}
job_defaults = {"coalesce": False, "max_instances": 3}

SCHEDULER = AsyncIOScheduler(
job_defaults=job_defaults, timezone=utc, executors=executors, jobstores=jobstores
job_defaults=job_defaults, timezone=timezone, executors=executors, jobstores=jobstores
)


Expand Down
46 changes: 42 additions & 4 deletions app/receiver/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,41 @@ async def create_snapshot(
return snapshot_credential


async def create_child_snapshot(
*,
task: TaskHeader,
memory_able: bool,
channel: str,
):
"""
认证链重发注册
"""
logger.debug(f"Create a snapshot for {task.receiver.platform}")
task_snapshot = task.model_copy()
meta: Sign = task_snapshot.task_sign.snapshot(
name=__receiver__,
memory_able=memory_able,
# 不需要记忆
response_snapshot=True,
# 要求释放快照
)
"""添加认证链并重置路由数据"""
snap_shot_task = TaskHeader(
sender=task_snapshot.sender,
receiver=task_snapshot.receiver,
task_sign=meta,
message=[],
)
task_id = await append_snapshot(
snapshot_credential=None, # 不注册为认证快照,因为只是递归启动
snapshot_data=snap_shot_task,
channel=channel,
creator=task_snapshot.receiver.uid,
expire_at=int(time.time()) + 60 * 2,
)
logger.debug(f"Create a snapshot {task_id}")


async def reply_user(platform: str, task: TaskHeader, text: str, receiver: Location):
"""
仅仅只是通知到用户,不需要LLM处理或组装
Expand Down Expand Up @@ -208,9 +243,8 @@ async def run_pending_task(task: TaskHeader, pending_task: ToolCall):
logger.debug(
"ToolCall run out, resign a new request to request stop sign."
)
await create_snapshot(
await create_child_snapshot(
task=task,
tool_calls_pending_now=pending_task,
memory_able=True,
channel=task.receiver.platform,
)
Expand Down Expand Up @@ -245,14 +279,18 @@ async def process_function_call(self, message: AbstractIncomingMessage):
task: TaskHeader = TaskHeader.model_validate_json(message.body.decode("utf-8"))
# Get Function Call
pending_task: ToolCall = await task.task_sign.get_pending_tool_call(
tool_calls_pending_now=task.task_sign.snapshot_credential,
credential=task.task_sign.snapshot_credential,
return_default_if_empty=False,
)
if pending_task:
await self.run_task(task=task, pending_task=pending_task)
if task.task_sign.snapshot_credential:
if not pending_task:
logger.warning(
f"Received A Credential {task.task_sign.snapshot_credential}, But No Pending Task!"
)
return logger.debug(
f"Received A Credential {task.task_sign.snapshot_credential}, End Run Function Call Loop!"
f"Received A Credential {task.task_sign.snapshot_credential}, End Snapshot!"
)
RUN_LIMIT = 4
for pending_task in task.task_sign.tool_calls_pending:
Expand Down
7 changes: 3 additions & 4 deletions app/receiver/kook/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@

__receiver__ = "kook"

# 魔法
import nest_asyncio

from llmkira.task.schema import Location, EventMessage

nest_asyncio.apply()

# import nest_asyncio
# nest_asyncio.apply()


class KookSender(BaseSender):
Expand Down
7 changes: 3 additions & 4 deletions app/receiver/slack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@

__receiver__ = "slack"

# 魔法
import nest_asyncio

from llmkira.task.schema import Location, EventMessage

nest_asyncio.apply()

# import nest_asyncio
# nest_asyncio.apply()


class SlackSender(BaseSender):
Expand Down
4 changes: 3 additions & 1 deletion app/receiver/telegram/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ async def forward(
text=convert(item.text),
reply_to_message_id=receiver.message_id,
parse_mode="MarkdownV2",
disable_web_page_preview=True,
)
return logger.trace("forward message")

Expand All @@ -127,6 +128,7 @@ async def reply(
if receiver.chat_id is not None:
await self.bot.send_chat_action(chat_id=receiver.chat_id, action="typing")
event_message = [
# FIXME:TYPEHint
EventMessage.from_openai_message(message=item, locate=receiver)
for item in messages
]
Expand All @@ -147,6 +149,7 @@ async def reply(
if reply_to_message
else None,
parse_mode="MarkdownV2",
disable_web_page_preview=True,
)
except telebot.apihelper.ApiTelegramException as e:
if "message to reply not found" in str(e):
Expand All @@ -165,7 +168,6 @@ async def error(self, receiver: Location, text):
reply_to_message_id=receiver.message_id,
parse_mode="MarkdownV2",
)

return logger.error("send a error message")

async def function(
Expand Down
4 changes: 2 additions & 2 deletions app/sender/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
# @File : app.py
# @Software: PyCharm

import nest_asyncio
from dotenv import load_dotenv
from loguru import logger

Expand All @@ -13,7 +12,8 @@
load_dotenv()
__area__ = "sender"

nest_asyncio.apply()
# import nest_asyncio
# nest_asyncio.apply()


def run():
Expand Down
Binary file added docs/code_interpreter_func.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 34 additions & 29 deletions docs/test_script/survey_khl_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
# @Software: PyCharm
import asyncio

import nest_asyncio

nest_asyncio.apply()

from khl import Bot, api, HTTPRequester, Cert, MessageTypes

# import nest_asyncio
# nest_asyncio.apply()

bot_token = "xxx"
# init Bot
bot = Bot(cert=Cert(token=bot_token))
Expand All @@ -19,40 +18,46 @@
# register command, send `/hello` in channel to invoke
async def world():
httpr = HTTPRequester(cert=Cert(token=bot_token))
_request = await httpr.exec_req(api.DirectMessage.create(
target_id='15648861098', # :)
type=9,
content='hello23',
# temp_target_id=msg.author.id,
)
)
_request = await httpr.exec_req(api.DirectMessage.create(
target_id='15648861098',
type=9,
content='hello232342',
# temp_target_id=msg.author.id,
_request = await httpr.exec_req(
api.DirectMessage.create(
target_id="15648861098", # :)
type=9,
content="hello23",
# temp_target_id=msg.author.id,
)
)
_request = await httpr.exec_req(
api.DirectMessage.create(
target_id="15648861098",
type=9,
content="hello232342",
# temp_target_id=msg.author.id,
)
)
# return
await bot.client.gate.exec_req(api.DirectMessage.create(
target_id='15648861098',
content='hello!---',
type=9,
))
await bot.client.gate.exec_req(
api.DirectMessage.create(
target_id="15648861098",
content="hello!---",
type=9,
)
)
# return
await bot.client.send(target=msg.ctx.channel, content='hello')
msg = None
await bot.client.send(target=msg.ctx.channel, content="hello")
# return
print(msg.ctx.channel.id)
print(await msg.ctx.channel.send("h"))
await HTTPRequester(cert=Cert(token=bot_token)).exec_req(api.Message.create(
target_id=msg.ctx.channel.id,
type=MessageTypes.KMD.value,
content='hello!',
# temp_target_id=msg.author.id,
)
await HTTPRequester(cert=Cert(token=bot_token)).exec_req(
api.Message.create(
target_id=msg.ctx.channel.id,
type=MessageTypes.KMD.value,
content="hello!",
# temp_target_id=msg.author.id,
)
)


print('hello world')
print("hello world")
loop = asyncio.get_event_loop()
loop.run_until_complete(world())
7 changes: 5 additions & 2 deletions llmkira/extra/plugins/alarm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
from app.receiver.aps import SCHEDULER # noqa

from llmkira.task import Task, TaskHeader # noqa
from pytz import utc # noqa
import pytz # noqa
from tzlocal import get_localzone


class SetAlarm(BaseModel):
Expand Down Expand Up @@ -165,10 +166,12 @@ async def run(

logger.debug("Plugin --set_alarm {} minutes".format(argument.delay))
# 这里假设您的任务应该在UTC时间下执行,如果需要在其他时区执行,根据实际情况更改tz变量
tz = utc
tz = pytz.timezone(get_localzone().key)
run_time = datetime.datetime.now() + datetime.timedelta(minutes=argument.delay)
logger.debug(run_time)
# 将本地时间转换为设定的时区
run_time = tz.localize(run_time)
logger.debug(run_time)
SCHEDULER.add_job(
func=send_notify,
id=receiver.uid,
Expand Down
Loading

0 comments on commit e6b2cd5

Please sign in to comment.