feat: crud of platform/bots

This commit is contained in:
Junyan Qin
2025-03-27 01:20:00 +08:00
parent 6c1ee922de
commit 5be17c55d2
14 changed files with 188 additions and 7 deletions
+4 -2
View File
@@ -20,9 +20,11 @@ class PipelinesRouterGroup(group.RouterGroup):
elif quart.request.method == 'POST': elif quart.request.method == 'POST':
json_data = await quart.request.json json_data = await quart.request.json
await self.ap.pipeline_service.create_pipeline(json_data) pipeline_uuid = await self.ap.pipeline_service.create_pipeline(json_data)
return self.success() return self.success(data={
'uuid': pipeline_uuid
})
@self.route('/_/metadata', methods=['GET']) @self.route('/_/metadata', methods=['GET'])
async def _() -> str: async def _() -> str:
@@ -0,0 +1,25 @@
import quart
from ... import group
@group.group_class('adapters', '/api/v1/platform/adapters')
class AdaptersRouterGroup(group.RouterGroup):
async def initialize(self) -> None:
@self.route('', methods=['GET'])
async def _() -> str:
return self.success(data={
'adapters': self.ap.platform_mgr.get_available_adapters_info()
})
@self.route('/<adapter_name>', methods=['GET'])
async def _(adapter_name: str) -> str:
adapter_info = self.ap.platform_mgr.get_available_adapter_info_by_name(adapter_name)
if adapter_info is None:
return self.http_status(404, -1, 'adapter not found')
return self.success(data={
'adapter': adapter_info
})
@@ -0,0 +1,38 @@
import quart
from ... import group
@group.group_class('bots', '/api/v1/platform/bots')
class BotsRouterGroup(group.RouterGroup):
async def initialize(self) -> None:
@self.route('', methods=['GET', 'POST'])
async def _() -> str:
if quart.request.method == 'GET':
return self.success(data={
'bots': await self.ap.bot_service.get_bots()
})
elif quart.request.method == 'POST':
json_data = await quart.request.json
bot_uuid = await self.ap.bot_service.create_bot(json_data)
return self.success(data={
'uuid': bot_uuid
})
@self.route('/<bot_uuid>', methods=['GET', 'PUT', 'DELETE'])
async def _(bot_uuid: str) -> str:
if quart.request.method == 'GET':
bot = await self.ap.bot_service.get_bot(bot_uuid)
if bot is None:
return self.http_status(404, -1, 'bot not found')
return self.success(data={
'bot': bot
})
elif quart.request.method == 'PUT':
json_data = await quart.request.json
await self.ap.bot_service.update_bot(bot_uuid, json_data)
return self.success()
elif quart.request.method == 'DELETE':
await self.ap.bot_service.delete_bot(bot_uuid)
return self.success()
@@ -18,9 +18,11 @@ class LLMModelsRouterGroup(group.RouterGroup):
elif quart.request.method == 'POST': elif quart.request.method == 'POST':
json_data = await quart.request.json json_data = await quart.request.json
await self.ap.model_service.create_llm_model(json_data) model_uuid = await self.ap.model_service.create_llm_model(json_data)
return self.success() return self.success(data={
'uuid': model_uuid
})
@self.route('/<model_uuid>', methods=['GET', 'DELETE']) @self.route('/<model_uuid>', methods=['GET', 'DELETE'])
async def _(model_uuid: str) -> str: async def _(model_uuid: str) -> str:
+1
View File
@@ -10,6 +10,7 @@ from ....core import app, entities as core_entities
from .groups import logs, system, settings, plugins, stats, user, pipelines from .groups import logs, system, settings, plugins, stats, user, pipelines
from .groups.provider import models, requesters from .groups.provider import models, requesters
from .groups.platform import bots, adapters
from . import group from . import group
+70
View File
@@ -0,0 +1,70 @@
from __future__ import annotations
import uuid
import datetime
import sqlalchemy
from ....core import app
from ....entity.persistence import bot as persistence_bot
class BotService:
"""机器人服务"""
ap: app.Application
def __init__(self, ap: app.Application) -> None:
self.ap = ap
async def get_bots(self) -> list[dict]:
"""获取所有机器人"""
result = await self.ap.persistence_mgr.execute_async(
sqlalchemy.select(persistence_bot.Bot)
)
bots = result.all()
return [
self.ap.persistence_mgr.serialize_model(persistence_bot.Bot, bot)
for bot in bots
]
async def get_bot(self, bot_uuid: str) -> dict | None:
"""获取机器人"""
result = await self.ap.persistence_mgr.execute_async(
sqlalchemy.select(persistence_bot.Bot).where(persistence_bot.Bot.uuid == bot_uuid)
)
bot = result.first()
if bot is None:
return None
return self.ap.persistence_mgr.serialize_model(persistence_bot.Bot, bot)
async def create_bot(self, bot_data: dict) -> str:
"""创建机器人"""
bot_data['uuid'] = str(uuid.uuid4())
await self.ap.persistence_mgr.execute_async(
sqlalchemy.insert(persistence_bot.Bot).values(bot_data)
)
# TODO: 加载机器人到机器人管理器
return bot_data['uuid']
async def update_bot(self, bot_uuid: str, bot_data: dict) -> None:
"""更新机器人"""
if 'uuid' in bot_data:
del bot_data['uuid']
await self.ap.persistence_mgr.execute_async(
sqlalchemy.update(persistence_bot.Bot).values(bot_data).where(persistence_bot.Bot.uuid == bot_uuid)
)
# TODO: 加载机器人到机器人管理器
async def delete_bot(self, bot_uuid: str) -> None:
"""删除机器人"""
await self.ap.persistence_mgr.execute_async(
sqlalchemy.delete(persistence_bot.Bot).where(persistence_bot.Bot.uuid == bot_uuid)
)
# TODO: 从机器人管理器中删除机器人
+6 -1
View File
@@ -26,7 +26,7 @@ class ModelsService:
for model in models for model in models
] ]
async def create_llm_model(self, model_data: dict) -> None: async def create_llm_model(self, model_data: dict) -> str:
model_data['uuid'] = str(uuid.uuid4()) model_data['uuid'] = str(uuid.uuid4())
@@ -37,6 +37,8 @@ class ModelsService:
) )
await self.ap.model_mgr.load_llm_model(model_data) await self.ap.model_mgr.load_llm_model(model_data)
return model_data['uuid']
async def get_llm_model(self, model_uuid: str) -> dict | None: async def get_llm_model(self, model_uuid: str) -> dict | None:
result = await self.ap.persistence_mgr.execute_async( result = await self.ap.persistence_mgr.execute_async(
sqlalchemy.select(persistence_model.LLMModel).where(persistence_model.LLMModel.uuid == model_uuid) sqlalchemy.select(persistence_model.LLMModel).where(persistence_model.LLMModel.uuid == model_uuid)
@@ -50,6 +52,9 @@ class ModelsService:
return self.ap.persistence_mgr.serialize_model(persistence_model.LLMModel, model) return self.ap.persistence_mgr.serialize_model(persistence_model.LLMModel, model)
async def update_llm_model(self, model_uuid: str, model_data: dict) -> None: async def update_llm_model(self, model_uuid: str, model_data: dict) -> None:
if 'uuid' in model_data:
del model_data['uuid']
await self.ap.persistence_mgr.execute_async( await self.ap.persistence_mgr.execute_async(
sqlalchemy.update(persistence_model.LLMModel).where(persistence_model.LLMModel.uuid == model_uuid).values(**model_data) sqlalchemy.update(persistence_model.LLMModel).where(persistence_model.LLMModel.uuid == model_uuid).values(**model_data)
) )
+3 -1
View File
@@ -46,7 +46,7 @@ class PipelineService:
return self.ap.persistence_mgr.serialize_model(persistence_pipeline.LegacyPipeline, pipeline) return self.ap.persistence_mgr.serialize_model(persistence_pipeline.LegacyPipeline, pipeline)
async def create_pipeline(self, pipeline_data: dict) -> None: async def create_pipeline(self, pipeline_data: dict) -> str:
pipeline_data['uuid'] = str(uuid.uuid4()) pipeline_data['uuid'] = str(uuid.uuid4())
pipeline_data['for_version'] = self.ap.ver_mgr.get_current_version() pipeline_data['for_version'] = self.ap.ver_mgr.get_current_version()
pipeline_data['stages'] = stagemgr.stage_order.copy() pipeline_data['stages'] = stagemgr.stage_order.copy()
@@ -58,6 +58,8 @@ class PipelineService:
) )
# TODO: 更新到pipeline manager # TODO: 更新到pipeline manager
return pipeline_data['uuid']
async def update_pipeline(self, pipeline_uuid: str, pipeline_data: dict) -> None: async def update_pipeline(self, pipeline_uuid: str, pipeline_data: dict) -> None:
del pipeline_data['uuid'] del pipeline_data['uuid']
del pipeline_data['for_version'] del pipeline_data['for_version']
+3
View File
@@ -27,6 +27,7 @@ from ..api.http.controller import main as http_controller
from ..api.http.service import user as user_service from ..api.http.service import user as user_service
from ..api.http.service import model as model_service from ..api.http.service import model as model_service
from ..api.http.service import pipeline as pipeline_service from ..api.http.service import pipeline as pipeline_service
from ..api.http.service import bot as bot_service
from ..discover import engine as discover_engine from ..discover import engine as discover_engine
from ..utils import logcache, ip from ..utils import logcache, ip
from . import taskmgr from . import taskmgr
@@ -123,6 +124,8 @@ class Application:
pipeline_service: pipeline_service.PipelineService = None pipeline_service: pipeline_service.PipelineService = None
bot_service: bot_service.BotService = None
def __init__(self): def __init__(self):
pass pass
+4
View File
@@ -20,6 +20,7 @@ from ...api.http.controller import main as http_controller
from ...api.http.service import user as user_service from ...api.http.service import user as user_service
from ...api.http.service import model as model_service from ...api.http.service import model as model_service
from ...api.http.service import pipeline as pipeline_service from ...api.http.service import pipeline as pipeline_service
from ...api.http.service import bot as bot_service
from ...discover import engine as discover_engine from ...discover import engine as discover_engine
from ...utils import logcache from ...utils import logcache
from .. import taskmgr from .. import taskmgr
@@ -131,5 +132,8 @@ class BuildAppStage(stage.BootingStage):
pipeline_service_inst = pipeline_service.PipelineService(ap) pipeline_service_inst = pipeline_service.PipelineService(ap)
ap.pipeline_service = pipeline_service_inst ap.pipeline_service = pipeline_service_inst
bot_service_inst = bot_service.BotService(ap)
ap.bot_service = bot_service_inst
ctrl = controller.Controller(ap) ctrl = controller.Controller(ap)
ap.ctrl = ctrl ap.ctrl = ctrl
+17
View File
@@ -0,0 +1,17 @@
import sqlalchemy
from .base import Base
class Bot(Base):
"""机器人"""
__tablename__ = 'bots'
uuid = sqlalchemy.Column(sqlalchemy.String(255), primary_key=True)
name = sqlalchemy.Column(sqlalchemy.String(255), nullable=False)
description = sqlalchemy.Column(sqlalchemy.String(255), nullable=False)
adapter = sqlalchemy.Column(sqlalchemy.String(255), nullable=False)
adapter_config = sqlalchemy.Column(sqlalchemy.JSON, nullable=False)
enable = sqlalchemy.Column(sqlalchemy.Boolean, nullable=False, default=False)
created_at = sqlalchemy.Column(sqlalchemy.DateTime, nullable=False, server_default=sqlalchemy.func.now())
updated_at = sqlalchemy.Column(sqlalchemy.DateTime, nullable=False, server_default=sqlalchemy.func.now(), onupdate=sqlalchemy.func.now())
+1 -1
View File
@@ -8,7 +8,7 @@ import sqlalchemy.ext.asyncio as sqlalchemy_asyncio
import sqlalchemy import sqlalchemy
from . import database from . import database
from ..entity.persistence import user, model, base from ..entity.persistence import base, user, model, pipeline, bot
from ..core import app from ..core import app
from .databases import sqlite from .databases import sqlite
+12
View File
@@ -110,6 +110,18 @@ class PlatformManager:
if len(self.adapters) == 0: if len(self.adapters) == 0:
self.ap.logger.warning('未运行平台适配器,请根据文档配置并启用平台适配器。') self.ap.logger.warning('未运行平台适配器,请根据文档配置并启用平台适配器。')
def get_available_adapters_info(self) -> list[dict]:
return [
component.to_plain_dict()
for component in self.message_platform_adapter_components
]
def get_available_adapter_info_by_name(self, name: str) -> dict | None:
for component in self.message_platform_adapter_components:
if component.metadata.name == name:
return component.to_plain_dict()
return None
async def write_back_config(self, adapter_name: str, adapter_inst: msadapter.MessagePlatformAdapter, config: dict): async def write_back_config(self, adapter_name: str, adapter_inst: msadapter.MessagePlatformAdapter, config: dict):
index = -2 index = -2