Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Pydantic #340

Merged
merged 8 commits into from
Nov 12, 2023
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
42 changes: 27 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@
FROM python:3.10-slim AS builder
# 第一个阶段
FROM python:3.11-buster as builder

RUN apt update && \
apt install build-essential -y
RUN apt update && apt install -y build-essential \
&& pip install poetry==1.6.1

ENV POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_IN_PROJECT=1 \
POETRY_VIRTUALENVS_CREATE=1 \
POETRY_CACHE_DIR=/tmp/poetry_cache

COPY ./requirements.txt .
COPY pm2.json .
COPY start.sh .
# 将 config_dir 的设置文件映射到宿主机
COPY ./config_dir /config_dir
WORKDIR /app

COPY poetry.lock pyproject.toml ./
VOLUME ["/redis", "/rabbitmq", "/mongodb", "run.log", "/config_dir"]

RUN pip install --upgrade --no-cache-dir pip && pip install --no-cache-dir -r requirements.txt
RUN poetry config virtualenvs.in-project true && \
poetry install --without dev --no-root && rm -rf $POETRY_CACHE_DIR

FROM python:3.10-slim
RUN apt-get update && \
# 第二个阶段
FROM python:3.11-slim-buster as runtime

RUN apt update && \
apt install -y npm && \
npm install pm2 -g

ENV WORKDIR /app
WORKDIR $WORKDIR
ADD . $WORKDIR
COPY --from=builder /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages
ENV VIRTUAL_ENV=/app/.venv \
PATH="/app/.venv/bin:$PATH"

WORKDIR /app

COPY --from=builder /app/.venv /app/.venv

COPY pm2.json ./
COPY config_dir ./config_dir

CMD [ "pm2-runtime", "pm2.json" ]
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,10 @@ docker-compose -f docker-compose.yml up -d

```shell
git clone https://github.com/LlmKira/Openaibot.git
pip install poetry
cd Openaibot
pip install -r requirements.txt
# poetry config virtualenvs.in-project true
poetry install
cp .env.exp .env&&nano .env
apt install npm -y && npm install pm2 && pm2 start pm2.json
pm2 monit
Expand Down
4 changes: 3 additions & 1 deletion README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ curl -sSL https://raw.githubusercontent.com/LLMKira/Openaibot/main/deploy.sh | b
```shell
git clone https://github.com/LlmKira/Openaibot.git
cd Openaibot
pip install -r requirements.txt
pip install poetry
# poetry config virtualenvs.in-project true
poetry install
docker-compose -f docker-compose.yml up -d

```
Expand Down
4 changes: 3 additions & 1 deletion deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ cd Openaibot || echo "DO NOT Exist Openaibot Dir" && exit

# Install project dependencies
echo "$(tput setaf 6)Installing project dependencies...$(tput sgr0)"
python3 -m pip install -r requirements.txt
python3 -m pip install poetry
poetry config virtualenvs.in-project true &&
poetry install
python3 -m pip install rich loguru && python3 start_tutorial.py
echo "$(tput setaf 2)Project dependencies installation complete.$(tput sgr0)"

Expand Down
2 changes: 1 addition & 1 deletion docs/test_script/funtion.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ def add_property(self, property_name: str,
required=True
)
# print(Function.schema_json(indent=4))
print(json.dumps(f.dict(), indent=4))
print(json.dumps(f.model_dump(), indent=4))
2 changes: 1 addition & 1 deletion docs/test_script/note_pydantic_alias_usage.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ class Child(Test):
env_required = ["test"]


_r = Child().dict()
_r = Child().model_dump()
_s = Child().env_help_docs
print(_r)
23 changes: 23 additions & 0 deletions docs/test_script/pydantic_feat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# @Time : 2023/11/12 下午9:12
# @Author : sudoskys
# @File : pydantic_feat.py
# @Software: PyCharm
from pydantic import field_validator, BaseModel, ValidationError


class UserModel(BaseModel):
id: int
name: str

@field_validator('name')
def name_must_contain_space(cls, v: str) -> str:
if ' ' not in v:
raise ValueError('must contain a space')
return v.title()


try:
UserModel(id=0, name='JohnDoe')
except ValidationError as e:
print(e)
8 changes: 5 additions & 3 deletions docs/test_script/survey_arg_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@
# @Author : sudoskys
# @File : arg.py.py
# @Software: PyCharm
from typing import Optional

from pydantic import BaseModel, Field


class Search(BaseModel):
"""
测试搜索类型
"""
keywords: str = Field(None, description="关键词")
text: str = Field(None, description="文本")
keywords: Optional[str] = Field(None, description="关键词")
text: Optional[str] = Field(None, description="文本")

def run(self):
return self.keywords + self.text


print(Search.schema())
print(Search.model_json_schema())
8 changes: 4 additions & 4 deletions docs/test_script/web_craw_note/note_unstructured.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# @Author : sudoskys
# @File : note_unstructured.py
# @Software: PyCharm
from typing import List
from typing import List, Optional

from pydantic import BaseModel, Field
from rich import print
Expand All @@ -20,13 +20,13 @@
class UnstructuredElement(BaseModel):
class Meta(BaseModel):
url: str
title: str = Field(None, alias="title")
filetype: str = Field(None, alias="filetype")
title: Optional[str] = Field(None, alias="title")
filetype: Optional[str] = Field(None, alias="filetype")
page_number: int = Field(None, alias="page_number")
languages: List[str] = Field(None, alias="languages")
category_depth: int = Field(None, alias="category_depth")
link_urls: List[str] = Field(None, alias="link_urls")
link_texts: str = Field(None, alias="link_text")
link_texts: Optional[str] = Field(None, alias="link_text")

text: str
metadata: Meta
Expand Down
6 changes: 5 additions & 1 deletion llmkira/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
# @File : error.py
# @Software: PyCharm


class ReplyNeededError(Exception):
"""
Raised a error that need reply
"""
pass

def __init__(self, message: str = None, *args):
# 拦截 url 信息
super().__init__(message, *args)


# 更安全的 format
Expand Down
8 changes: 4 additions & 4 deletions llmkira/extra/plugins/_finish.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from pydantic import ConfigDict

__package__name__ = "llmkira.extra.plugins.finish"
__plugin_name__ = "finish_conversation"
__openapi_version__ = "20231111"
Expand Down Expand Up @@ -31,9 +33,7 @@

class Finish(BaseModel):
comment: str = Field(default=":)", description="end with a question or a comment.(__language: $context)")

class Config:
extra = "allow"
model_config = ConfigDict(extra="allow")


class FinishTool(BaseTool):
Expand Down Expand Up @@ -99,7 +99,7 @@ async def run(self,
"""
处理message,返回message
"""
_set = Finish.parse_obj(arg)
_set = Finish.model_validate(arg)
# META
_meta = task.task_meta.reply_message(
plugin_name=__plugin_name__,
Expand Down
8 changes: 4 additions & 4 deletions llmkira/extra/plugins/_translate_doc.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from pydantic import ConfigDict

__package__name__ = "llmkira.extra.plugins.translate_file"
__plugin_name__ = "translate_file"
__openapi_version__ = "20231027"
Expand Down Expand Up @@ -44,9 +46,7 @@
class Translate(BaseModel):
language: str
file_id: str

class Config:
extra = "allow"
model_config = ConfigDict(extra="allow")


class TranslateTool(BaseTool):
Expand Down Expand Up @@ -179,7 +179,7 @@ async def run(self,
for i in item.file:
_translate_file.append(i)
try:
translate_arg = Translate.parse_obj(arg)
translate_arg = Translate.model_validate(arg)
except Exception:
raise ValueError("Please specify the following parameters clearly\n file_id=xxx,language=xxx")
_file_obj = [await i.raw_file()
Expand Down
34 changes: 15 additions & 19 deletions llmkira/extra/plugins/alarm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from pydantic import field_validator, ConfigDict

__package__name__ = "llmkira.extra.plugins.alarm"
__plugin_name__ = "set_alarm_reminder"
__openapi_version__ = "20231111"
Expand All @@ -10,18 +12,17 @@

import datetime
import re
import time

from loguru import logger
from pydantic import validator, BaseModel
from pydantic import BaseModel

from llmkira.receiver.aps import SCHEDULER
from llmkira.schema import RawMessage
from llmkira.sdk.func_calling import PluginMetadata, BaseTool
from llmkira.sdk.func_calling.schema import FuncPair
from llmkira.task import Task, TaskHeader

from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Optional

if TYPE_CHECKING:
from llmkira.sdk.schema import TaskBatch
Expand All @@ -44,11 +45,9 @@
class Alarm(BaseModel):
delay: int
content: str
model_config = ConfigDict(extra="allow")

class Config:
extra = "allow"

@validator("delay")
@field_validator("delay")
def delay_validator(cls, v):
if v < 0:
raise ValueError("delay must be greater than 0")
Expand All @@ -58,9 +57,9 @@ def delay_validator(cls, v):
async def send_notify(_platform, _meta, _sender: dict, _receiver: dict, _user, _chat, _content: str):
await Task(queue=_platform).send_task(
task=TaskHeader(
sender=TaskHeader.Location.parse_obj(_sender), # 继承发送者
receiver=TaskHeader.Location.parse_obj(_receiver), # 因为可能有转发,所以可以单配
task_meta=TaskHeader.Meta.parse_obj(_meta),
sender=TaskHeader.Location.model_validate(_sender), # 继承发送者
receiver=TaskHeader.Location.model_validate(_receiver), # 因为可能有转发,所以可以单配
task_meta=TaskHeader.Meta.model_validate(_meta),
message=[
RawMessage(
user_id=_user,
Expand All @@ -79,7 +78,7 @@ class AlarmTool(BaseTool):
silent: bool = False
function: Function = alarm
keywords: list = ["闹钟", "提醒", "定时", "到点", '分钟']
pattern = re.compile(r"(\d+)(分钟|小时|天|周|月|年)后提醒我(.*)")
pattern: Optional[re.Pattern] = re.compile(r"(\d+)(分钟|小时|天|周|月|年)后提醒我(.*)")
require_auth: bool = True

# env_required: list = ["SCHEDULER", "TIMEZONE"]
Expand Down Expand Up @@ -148,7 +147,7 @@ async def run(self,
"""
处理message,返回message
"""
_set = Alarm.parse_obj(arg)
_set = Alarm.model_validate(arg)
_meta = task.task_meta.reply_message(
plugin_name=__plugin_name__,
callback=[
Expand All @@ -163,22 +162,19 @@ async def run(self,
logger.debug("Plugin:set alarm {} minutes later".format(_set.delay))
SCHEDULER.add_job(
func=send_notify,
id=str(time.time()),
id=str(receiver.user_id),
trigger="date",
replace_existing=True,
misfire_grace_time=1000,
run_date=datetime.datetime.now() + datetime.timedelta(minutes=_set.delay),
args=[
task.receiver.platform,
_meta.dict(),
task.sender.dict(), receiver.dict(),
_meta.model_dump(),
task.sender.model_dump(), receiver.model_dump(),
receiver.user_id, receiver.chat_id,
_set.content
]
)
try:
SCHEDULER.start()
except Exception as e:
print(f"[155035]{e}")
await Task(queue=receiver.platform).send_task(
task=TaskHeader(
sender=task.sender, # 继承发送者
Expand Down
12 changes: 8 additions & 4 deletions llmkira/extra/plugins/search.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from pydantic import ConfigDict

__package__name__ = "llmkira.extra.plugins.search"
__plugin_name__ = "search_in_google"
__openapi_version__ = "20231111"
Expand All @@ -25,6 +27,10 @@
search = Function(
name=__plugin_name__,
description="Search/validate on google.com.[ONLY IF NECESSARY]",
).update_config(
config=Function.FunctionExtra(
system_prompt='Search only if necessary',
)
)
search.add_property(
property_name="keywords",
Expand Down Expand Up @@ -70,9 +76,7 @@ def search_on_duckduckgo(search_sentence: str, key_words: str = None):

class Search(BaseModel):
keywords: str

class Config:
extra = "allow"
model_config = ConfigDict(extra="allow")


class SearchTool(BaseTool):
Expand Down Expand Up @@ -196,7 +200,7 @@ async def run(self,
处理message,返回message
"""

_set = Search.parse_obj(arg)
_set = Search.model_validate(arg)
_search_result = search_on_duckduckgo(_set.keywords)
# META
_meta = task.task_meta.reply_raw(
Expand Down
Loading
Loading