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
157 changes: 157 additions & 0 deletions ruoyi-fastapi-backend/module_ai/controller/ai_chat_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
from typing import Annotated

from fastapi import Body, Path, Request, Response
from fastapi.responses import StreamingResponse
from sqlalchemy.ext.asyncio import AsyncSession

from common.annotation.log_annotation import Log
from common.aspect.db_seesion import DBSessionDependency
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
from common.enums import BusinessType
from common.router import APIRouterPro
from common.vo import DataResponseModel, ResponseBaseModel
from module_admin.entity.vo.user_vo import CurrentUserModel
from module_ai.entity.vo.ai_chat_vo import (
AiChatConfigModel,
AiChatRequestModel,
AiChatSessionBaseModel,
AiChatSessionModel,
)
from module_ai.service.ai_chat_service import AiChatService
from utils.log_util import logger
from utils.response_util import ResponseUtil

ai_chat_controller = APIRouterPro(
prefix='/ai/chat', order_num=19, tags=['AI管理-AI对话'], dependencies=[PreAuthDependency()]
)


@ai_chat_controller.post(
'/send',
summary='发送对话消息',
description='流式返回对话结果',
response_class=StreamingResponse,
responses={
200: {
'description': '流式返回对话结果',
'content': {
'text/event-stream': {},
},
}
},
)
async def send_chat_message(
request: Request,
chat_req: AiChatRequestModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> StreamingResponse:
user_id = current_user.user.user_id if current_user and current_user.user else 1
chat_stream = AiChatService.chat_services(query_db, chat_req, user_id)
logger.info(f'用户{user_id}发送对话消息成功')

return StreamingResponse(content=chat_stream, media_type='text/event-stream')


@ai_chat_controller.get(
'/config',
summary='获取用户对话配置',
description='获取当前用户的AI对话配置',
response_model=DataResponseModel[AiChatConfigModel],
)
async def get_user_chat_config(
request: Request,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
user_id = current_user.user.user_id
ai_chat_config_detail_result = await AiChatService.ai_chat_config_detail_services(query_db, user_id)
logger.info(f'获取user_id为{user_id}的对话配置成功')

return ResponseUtil.success(data=ai_chat_config_detail_result)


@ai_chat_controller.put(
'/config',
summary='保存用户对话配置',
description='保存当前用户的AI对话配置',
response_model=DataResponseModel[AiChatConfigModel],
)
@Log(title='AI对话配置管理', business_type=BusinessType.INSERT)
async def save_user_chat_config(
request: Request,
ai_chat_config: AiChatConfigModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
user_id = current_user.user.user_id if current_user and current_user.user else 1
save_ai_chat_config_result = await AiChatService.save_ai_chat_config_services(query_db, user_id, ai_chat_config)
logger.info(save_ai_chat_config_result.message)

return ResponseUtil.success(msg=save_ai_chat_config_result.message)


@ai_chat_controller.get(
'/session/list',
summary='获取会话列表',
description='获取用户的会话列表',
response_model=DataResponseModel[list[AiChatSessionBaseModel]],
)
async def get_chat_session_list(
request: Request,
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await AiChatService.get_chat_session_list_services(current_user.user.user_id)
logger.info('获取成功')

return ResponseUtil.success(data=result)


@ai_chat_controller.delete(
'/session/{session_id}',
summary='删除会话',
description='删除指定会话',
response_model=ResponseBaseModel,
)
@Log(title='AI对话会话管理', business_type=BusinessType.DELETE)
async def delete_chat_session(
request: Request,
session_id: Annotated[str, Path(description='会话ID')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
) -> Response:
delete_chat_session_result = await AiChatService.delete_chat_session_services(session_id)
logger.info(delete_chat_session_result.message)

return ResponseUtil.success(msg=delete_chat_session_result.message)


@ai_chat_controller.get(
'/session/{session_id}',
summary='获取会话消息详情',
description='获取指定会话的消息详情',
response_model=DataResponseModel[AiChatSessionModel],
)
async def get_chat_session_detail(
request: Request,
session_id: Annotated[str, Path(description='会话ID')],
) -> Response:
chat_session_detail_result = await AiChatService.get_chat_session_detail_services(session_id)
logger.info(f'获取session_id为{session_id}的信息成功')

return ResponseUtil.success(data=chat_session_detail_result)


@ai_chat_controller.post(
'/cancel',
summary='取消对话',
description='取消正在进行的对话',
response_model=ResponseBaseModel,
)
async def cancel_chat_run(
request: Request,
run_id: Annotated[str, Body(embed=True, description='运行ID', alias='runId')],
) -> Response:
cancel_result = await AiChatService.cancel_run_services(run_id)
logger.info(cancel_result.message)

return ResponseUtil.success(msg=cancel_result.message)
170 changes: 170 additions & 0 deletions ruoyi-fastapi-backend/module_ai/controller/ai_model_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
from datetime import datetime
from typing import Annotated

from fastapi import Path, Query, Request, Response
from pydantic_validation_decorator import ValidateFields
from sqlalchemy import ColumnElement
from sqlalchemy.ext.asyncio import AsyncSession

from common.annotation.log_annotation import Log
from common.aspect.data_scope import DataScopeDependency
from common.aspect.db_seesion import DBSessionDependency
from common.aspect.interface_auth import UserInterfaceAuthDependency
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
from common.enums import BusinessType
from common.router import APIRouterPro
from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel
from module_admin.entity.vo.user_vo import CurrentUserModel
from module_ai.entity.do.ai_model_do import AiModels
from module_ai.entity.vo.ai_model_vo import AiModelModel, AiModelPageQueryModel, DeleteAiModelModel
from module_ai.service.ai_model_service import AiModelService
from utils.log_util import logger
from utils.response_util import ResponseUtil

ai_model_controller = APIRouterPro(
prefix='/ai/model', order_num=18, tags=['AI管理-模型管理'], dependencies=[PreAuthDependency()]
)


@ai_model_controller.get(
'/list',
summary='获取AI模型分页列表接口',
description='用于获取AI模型分页列表',
response_model=PageResponseModel[AiModelModel],
dependencies=[UserInterfaceAuthDependency('ai:model:list')],
)
async def get_ai_model_list(
request: Request,
ai_model_page_query: Annotated[AiModelPageQueryModel, Query()],
query_db: Annotated[AsyncSession, DBSessionDependency()],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(AiModels)],
) -> Response:
# 获取分页数据
result = await AiModelService.get_ai_model_list_services(
query_db, ai_model_page_query, data_scope_sql, is_page=True
)
logger.info('获取成功')

return ResponseUtil.success(model_content=result)


@ai_model_controller.get(
'/all',
summary='获取AI模型不分页列表接口',
description='用于获取AI模型不分页列表',
response_model=DataResponseModel[AiModelModel],
)
async def get_ai_model_all(
request: Request,
query_db: Annotated[AsyncSession, DBSessionDependency()],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(AiModels)],
) -> Response:
# 获取不分页数据
ai_model_page_query = AiModelPageQueryModel(status='0')
result = await AiModelService.get_ai_model_list_services(
query_db, ai_model_page_query, data_scope_sql, is_page=False
)
logger.info('获取成功')

return ResponseUtil.success(data=result)


@ai_model_controller.post(
'',
summary='新增AI模型接口',
description='用于新增AI模型',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('ai:model:add')],
)
@ValidateFields(validate_model='add_ai_model')
@Log(title='AI模型管理', business_type=BusinessType.INSERT)
async def add_ai_model(
request: Request,
add_ai_model: AiModelModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
add_ai_model.user_id = current_user.user.user_id
add_ai_model.dept_id = current_user.user.dept_id
add_ai_model.create_by = current_user.user.user_name
add_ai_model.create_time = datetime.now()
add_ai_model.update_by = current_user.user.user_name
add_ai_model.update_time = datetime.now()
add_ai_model_result = await AiModelService.add_ai_model_services(query_db, add_ai_model)
logger.info(add_ai_model_result.message)

return ResponseUtil.success(msg=add_ai_model_result.message)


@ai_model_controller.put(
'',
summary='编辑AI模型接口',
description='用于编辑AI模型',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('ai:model:edit')],
)
@ValidateFields(validate_model='edit_ai_model')
@Log(title='AI模型管理', business_type=BusinessType.UPDATE)
async def edit_ai_model(
request: Request,
edit_ai_model: AiModelModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(AiModels)],
) -> Response:
if not current_user.user.admin:
await AiModelService.check_ai_model_data_scope_services(query_db, edit_ai_model.model_id, data_scope_sql)
edit_ai_model.update_by = current_user.user.user_name
edit_ai_model.update_time = datetime.now()
edit_ai_model_result = await AiModelService.edit_ai_model_services(query_db, edit_ai_model)
logger.info(edit_ai_model_result.message)

return ResponseUtil.success(msg=edit_ai_model_result.message)


@ai_model_controller.delete(
'/{model_ids}',
summary='删除AI模型接口',
description='用于删除AI模型',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('ai:model:remove')],
)
@Log(title='AI模型管理', business_type=BusinessType.DELETE)
async def delete_ai_model(
request: Request,
model_ids: Annotated[str, Path(description='需要删除的模型ID')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(AiModels)],
) -> Response:
model_id_list = model_ids.split(',')
for model_id in model_id_list:
if not current_user.user.admin:
await AiModelService.check_ai_model_data_scope_services(query_db, int(model_id), data_scope_sql)
delete_ai_model = DeleteAiModelModel(modelIds=model_ids)
delete_ai_model_result = await AiModelService.delete_ai_model_services(query_db, delete_ai_model)
logger.info(delete_ai_model_result.message)

return ResponseUtil.success(msg=delete_ai_model_result.message)


@ai_model_controller.get(
'/{model_id}',
summary='获取AI模型详情接口',
description='用于获取指定AI模型的详细信息',
response_model=DataResponseModel[AiModelModel],
dependencies=[UserInterfaceAuthDependency('ai:model:query')],
)
async def get_ai_model_detail(
request: Request,
model_id: Annotated[int, Path(description='模型ID')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(AiModels)],
) -> Response:
if not current_user.user.admin:
await AiModelService.check_ai_model_data_scope_services(query_db, model_id, data_scope_sql)
ai_model_detail_result = await AiModelService.ai_model_detail_services(query_db, model_id)
logger.info(f'获取model_id为{model_id}的信息成功')

return ResponseUtil.success(data=ai_model_detail_result)
52 changes: 52 additions & 0 deletions ruoyi-fastapi-backend/module_ai/dao/ai_chat_dao.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession

from module_ai.entity.do.ai_chat_do import AiChatConfig
from module_ai.entity.vo.ai_chat_vo import AiChatConfigModel


class AiChatConfigDao:
"""
AI对话配置数据库操作层
"""

@classmethod
async def get_chat_config_detail_by_user_id(cls, db: AsyncSession, user_id: int) -> AiChatConfig | None:
"""
根据用户ID获取配置

:param db: orm对象
:param user_id: 用户ID
:return: 配置对象
"""
ai_chat_config = (
(await db.execute(select(AiChatConfig).where(AiChatConfig.user_id == user_id))).scalars().first()
)

return ai_chat_config

@classmethod
async def add_chat_config_dao(cls, db: AsyncSession, chat_config: AiChatConfigModel) -> AiChatConfig:
"""
新增对话配置数据库操作

:param db: orm对象
:param chat_config: 对话配置对象
:return: 配置对象
"""
db_chat_config = AiChatConfig(**chat_config.model_dump(exclude_unset=True))
db.add(db_chat_config)
await db.flush()

return db_chat_config

@classmethod
async def edit_chat_config_dao(cls, db: AsyncSession, chat_config: dict) -> None:
"""
编辑对话配置数据库操作

:param db: orm对象
:param chat_config: 需要更新的对话配置字典
:return:
"""
await db.execute(update(AiChatConfig), [chat_config])
Loading