Skip to content

Commit

Permalink
Merge pull request LlmKira#361 from LlmKira/dev
Browse files Browse the repository at this point in the history
Patch Plugin System
  • Loading branch information
sudoskys authored Nov 15, 2023
2 parents e8324cc + 80c7230 commit 6609f9b
Show file tree
Hide file tree
Showing 10 changed files with 431 additions and 164 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ docs
/llmkira/mongodb/
/docs/test/
/jobs.sqlite
/config_dir/*.pem
/config_dir/*.secret/
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,5 @@ config_dir/*.db
/memray-*.html
/docs/test_script/sticker/
/jobs.sqlite
config_dir/*.pem
config_dir/*.secret/
65 changes: 65 additions & 0 deletions docs/test_script/note_github_bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
# @Time : 2023/11/15 下午9:49
# @Author : sudoskys
# @File : note_github_bot.py
# @Software: PyCharm
import os

import requests
from dotenv import load_dotenv
from flask import Flask, request
from github import Github, GithubIntegration

load_dotenv()

__flask_app_name__ = 'github_bot'
app = Flask(__flask_app_name__)
app_id = int(os.environ['GITHUB_APP_ID'])
with open(
os.path.normpath(os.path.expanduser(os.getenv("GITHUB_PRIVATE_KEY_FILE", '~/.certs/github/bot_key.pem'))),
'r'
) as cert_file:
app_key = cert_file.read()

git_integration = GithubIntegration(
app_id,
app_key,
)


@app.route("/", methods=['POST'])
def bot():
# Get the event payload
payload = request.json
# Check if the event is a GitHub PR creation event
if not all(k in payload.keys() for k in ['action', 'pull_request']) and \
payload['action'] == 'opened':
return "ok"
owner = payload['repository']['owner']['login']
repo_name = payload['repository']['name']
# Get a git connection as our bot
# Here is where we are getting the permission to talk as our bot and not
# as a Python webservice
git_connection = Github(
login_or_token=git_integration.get_access_token(
git_integration.get_installation(owner, repo_name).id
).token
)
repo = git_connection.get_repo(f"{owner}/{repo_name}")

issue = repo.get_issue(number=payload['pull_request']['number'])

# Call meme-api to get a random meme
response = requests.get(url='https://meme-api.herokuapp.com/gimme')
if response.status_code != 200:
return 'ok'

# Get the best resolution meme
meme_url = response.json()['preview'][-1]
# Create a comment with the random meme
issue.create_comment(f"![Alt Text]({meme_url})")
return "ok"


if __name__ == "__main__":
app.run(debug=True, port=5000)
58 changes: 58 additions & 0 deletions docs/test_script/note_github_bot_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
# @Time : 2023/11/15 下午10:19
# @Author : sudoskys
# @File : note_github_bot_test.py
# @Software: PyCharm
import os

from dotenv import load_dotenv
from github_bot_api import Event, Webhook
from github_bot_api import GithubApp
from github_bot_api.flask import create_flask_app

load_dotenv()

app_id = int(os.environ['GITHUB_APP_ID'])
with open(
os.path.normpath(os.path.expanduser(os.getenv("GITHUB_PRIVATE_KEY_FILE", '~/.certs/github/bot_key.pem'))),
'r'
) as cert_file:
app_key = cert_file.read()

app = GithubApp(
user_agent='my-bot/0.0.0',
app_id=app_id,
private_key=app_key
)

webhook = Webhook(secret=None)


@webhook.listen('issues')
def on_pull_request(event: Event) -> bool:
print(event.payload)
client = app.installation_client(event.payload['installation']['id'])
repo = client.get_repo(event.payload['repository']['full_name'])
issue = repo.get_issue(number=event.payload['issue']['number'])
issue.create_comment('Hello World')
return True


@webhook.listen('issue_comment')
def on_issue_comment(event: Event) -> bool:
print(event.payload)
client = app.installation_client(event.payload['installation']['id'])
repo = client.get_repo(event.payload['repository']['full_name'])
issue = repo.get_issue(number=event.payload['issue']['number'])
issue.edit(
body=f"Hello World\n\n{issue.body}"

)
return True


import os

os.environ['FLASK_ENV'] = 'development'
flask_app = create_flask_app(__name__, webhook)
flask_app.run()
9 changes: 6 additions & 3 deletions llmkira/middleware/func_reorganize/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,12 @@ async def _build(self) -> None:
for _index, _message in enumerate(self.task.message):
_message: RawMessage
functions.extend(
ToolRegister().filter_pair(key_phrases=_message.text,
message_raw=_message,
file_list=_message.file)
ToolRegister().filter_pair(
key_phrases=_message.text,
message_raw=_message,
file_list=_message.file,
address=(self.task.sender, self.task.receiver),
)
)
self.task.task_meta.function_list = functions
if self.task.task_meta.sign_as[0] == 0:
Expand Down
7 changes: 5 additions & 2 deletions llmkira/sdk/func_calling/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from typing import TYPE_CHECKING

from llmkira.sdk.func_calling import PluginMetadata

from . import _openapi_version_, BaseTool, get_loaded_plugins, Plugin, get_plugin
from .schema import FuncPair
from ..schema import Function, File
Expand Down Expand Up @@ -69,6 +68,7 @@ def filter_pair(self,
key_phrases: str,
message_raw: "RawMessage" = None,
file_list: List[File] = None,
address: tuple = None,
ignore: List[str] = None
) -> List[Function]:
"""
Expand All @@ -88,7 +88,10 @@ def _match_file(_tool, _file_list):

for func_name, pair_cls in self.pair_function.items():
_tool_cls = pair_cls.tool()
if _tool_cls.func_message(message_text=key_phrases, message_raw=message_raw):
if _tool_cls.func_message(message_text=key_phrases,
message_raw=message_raw,
address=address
):
# 关键词大类匹配成功
if func_name in ignore:
continue # 忽略函数
Expand Down
1 change: 1 addition & 0 deletions llmkira/sdk/func_calling/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ def func_message(self, message_text, **kwargs):
如果合格则返回message,否则返回None,表示不处理
message_text: 消息文本
message_raw: 消息原始数据 `RawMessage`
address: 消息地址 `tuple(sender,receiver)`
"""
for i in self.keywords:
if i in message_text:
Expand Down
26 changes: 20 additions & 6 deletions llmkira/sdk/openapi/fuse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
__error_table__: Dict[str, int] = {}


def get_error_plugin(error_times: int = 10):
def get_error_plugin(error_times: int = 10) -> list:
"""
获取错误次数过多的插件
:param error_times: 错误次数
Expand All @@ -30,7 +30,7 @@ def get_error_plugin(error_times: int = 10):
return [k for k, v in __error_table__.items() if v > error_times]


def recover_error_plugin(function_name: str):
def recover_error_plugin(function_name: str) -> None:
"""
恢复错误插件
:param function_name:
Expand All @@ -39,10 +39,22 @@ def recover_error_plugin(function_name: str):
__error_table__[function_name] = 0


def resign_plugin_executor(function: "Function", handle_exceptions: tuple = (Exception,)):
def resign_plugin_executor(function: "Function",
*,
handle_exceptions: tuple = (Exception,),
exclude_exceptions: tuple = ()
):
"""
装饰器
装饰器,先判断是否排除,再判断是否处理
:param function: 被装饰的函数
:param handle_exceptions: 处理的异常,只有在此列表中的异常才会被计数
:param exclude_exceptions: 排除的异常,不会被计数。不可以是宽泛的异常,如 Exception
:return: 装饰器
"""
if not handle_exceptions:
handle_exceptions = (Exception,)
if Exception in handle_exceptions or BaseException in handle_exceptions:
raise ValueError("Exception is not allowed in handle_exceptions")
logger.success(f"📦 [Plugin exception hook] {function.name}")

@wrapt.decorator # 保留被装饰函数的元信息
Expand All @@ -57,11 +69,13 @@ def wrapper(wrapped, instance, args, kwargs):
try:
res = wrapped(*args, **kwargs)
except Exception as e:
if e in exclude_exceptions:
logger.exception(e)
return {}
if e in handle_exceptions:
__error_table__[function.name] = __error_table__.get(function.name, 0) + 1
logger.exception(e)
else:
raise e
logger.warning(f"📦 [Plugin Not Handle Exception Hook] {function.name} {e}")
else:
return res
return {}
Expand Down
Loading

0 comments on commit 6609f9b

Please sign in to comment.