zhaoqingang
2024-12-10 08c8e8c9a4d65677de6a493446a605d70efee631
12.10 16
15个文件已修改
4 文件已重命名
3 文件已复制
6个文件已添加
589 ■■■■ 已修改文件
alembic/versions/3845dc998475_menu_table_add.py 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
alembic/versions/92ece82bc5a4_menu_table_update.py 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
alembic/versions/f49ae5b5f2c8_group_type_add.py 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/__init__.py 补丁 | 查看 | 原始文档 | blame | 历史
app/api/agent.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/api/auth.py 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/api/chat.py 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/api/files.py 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/api/report.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/api/user.py 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/api/v2/__init__.py 补丁 | 查看 | 原始文档 | blame | 历史
app/api/v2/conversation.py 补丁 | 查看 | 原始文档 | blame | 历史
app/api/v2/public_api.py 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/__init__.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/group_model.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/menu_model.py 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/token_model.py 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/service/auth.py 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/service/group.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/service/service_token.py 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/service/user.py 141 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/service/v2/__init__.py 补丁 | 查看 | 原始文档 | blame | 历史
app/service/v2/api_token.py 补丁 | 查看 | 原始文档 | blame | 历史
app/service/v2/app_register.py 补丁 | 查看 | 原始文档 | blame | 历史
app/service/v2/initialize_data.py 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/task/fetch_agent.py 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env_conf/menu_conf.json 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
alembic/versions/3845dc998475_menu_table_add.py
New file
@@ -0,0 +1,53 @@
"""menu table add
Revision ID: 3845dc998475
Revises: abc6bb9129ed
Create Date: 2024-12-10 14:22:03.798597
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision: str = '3845dc998475'
down_revision: Union[str, None] = 'abc6bb9129ed'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('menu_capacity',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('menu_id', sa.Integer(), nullable=True),
    sa.Column('capacity_id', sa.String(length=36), nullable=True),
    sa.Column('capacity_type', sa.Integer(), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('menu_id', 'capacity_id', name='menu_capacity_id_ix')
    )
    op.create_index(op.f('ix_menu_capacity_id'), 'menu_capacity', ['id'], unique=False)
    op.create_table('web_menu',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('title', sa.String(length=128), nullable=True),
    sa.Column('dialog', sa.String(length=1000), nullable=True),
    sa.Column('desc', sa.String(length=1000), nullable=True),
    sa.Column('icon', sa.String(length=16), nullable=True),
    sa.Column('img', sa.String(length=255), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_web_menu_id'), 'web_menu', ['id'], unique=False)
    op.drop_column('knowledgebase', 'count')
    # ### end Alembic commands ###
def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('knowledgebase', sa.Column('count', mysql.VARCHAR(length=32), nullable=True))
    op.drop_index(op.f('ix_web_menu_id'), table_name='web_menu')
    op.drop_table('web_menu')
    op.drop_index(op.f('ix_menu_capacity_id'), table_name='menu_capacity')
    op.drop_table('menu_capacity')
    # ### end Alembic commands ###
alembic/versions/92ece82bc5a4_menu_table_update.py
New file
@@ -0,0 +1,32 @@
"""menu table update
Revision ID: 92ece82bc5a4
Revises: 3845dc998475
Create Date: 2024-12-10 16:00:04.324833
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision: str = '92ece82bc5a4'
down_revision: Union[str, None] = '3845dc998475'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('web_menu', sa.Column('describe', sa.String(length=1000), nullable=True))
    op.drop_column('web_menu', 'dialog')
    # ### end Alembic commands ###
def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('web_menu', sa.Column('dialog', mysql.VARCHAR(length=1000), nullable=True))
    op.drop_column('web_menu', 'describe')
    # ### end Alembic commands ###
alembic/versions/f49ae5b5f2c8_group_type_add.py
New file
@@ -0,0 +1,30 @@
"""group type add
Revision ID: f49ae5b5f2c8
Revises: 92ece82bc5a4
Create Date: 2024-12-10 16:26:34.371685
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = 'f49ae5b5f2c8'
down_revision: Union[str, None] = '92ece82bc5a4'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('group', sa.Column('group_type', sa.Integer(), nullable=True))
    # ### end Alembic commands ###
def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('group', 'group_type')
    # ### end Alembic commands ###
app/__init__.py
copy from app/service/common/__init__.py copy to app/__init__.py
app/api/agent.py
@@ -42,7 +42,7 @@
    if agent.agent_type == AgentType.RAGFLOW:
        ragflow_service = RagflowService(base_url=settings.fwr_base_url)
        try:
            token = get_ragflow_token(db, current_user.id)
            token = await get_ragflow_token(db, current_user.id)
            result = await ragflow_service.get_chat_sessions(token, agent_id)
            if not result:
                result = await get_session_history(db, current_user.id, agent_id)
@@ -53,7 +53,7 @@
    elif agent.agent_type == AgentType.BISHENG:
        bisheng_service = BishengService(base_url=settings.sgb_base_url)
        try:
            token = get_bisheng_token(db, current_user.id)
            token = await get_bisheng_token(db, current_user.id)
            result = await bisheng_service.get_chat_sessions(token, agent_id,  page, limit)
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))
@@ -84,7 +84,7 @@
    if agent.agent_type == AgentType.RAGFLOW:
        ragflow_service = RagflowService(base_url=settings.fwr_base_url)
        try:
            token = get_ragflow_token(db, current_user.id)
            token = await get_ragflow_token(db, current_user.id)
            result = await ragflow_service.get_session_log(token, conversation_id)
            if 'session_log' in result and 'reference' in result:
                combined_logs = []
@@ -118,7 +118,7 @@
            is_join = True
        bisheng_service = BishengService(base_url=settings.sgb_base_url)
        try:
            token = get_bisheng_token(db, current_user.id)
            token = await get_bisheng_token(db, current_user.id)
            result = await bisheng_service.get_session_log(token, agent_id, conversation_id)
            combined_logs = []
            last_question = None
app/api/auth.py
@@ -18,7 +18,7 @@
from app.service.auth import authenticate_user, create_access_token, is_valid_password, save_register_user, \
    update_user_token, UserAppDao
from app.service.bisheng import BishengService
from app.service.common.app_register import AppRegisterDao
from app.service.v2.app_register import AppRegisterDao
from app.service.difyService import DifyService
from app.service.ragflow import RagflowService
from sqlalchemy.future import select
@@ -96,13 +96,10 @@
@router.get("/token", response_model=Response)
async def token_api(db: Session = Depends(get_db), current_user: UserModel = Depends(get_current_user)):
    # 查询现有记录
    token = get_token(db, current_user.id)
    token = await get_token(db, current_user.id)
    if token is None:
        return Response(code=400, msg="token not found")
    return Response(code=200, msg="success", data={
        "ragflow_token": token.ragflow_token,
        "bisheng_token": token.bisheng_token,
    })
    return Response(code=200, msg="success", data=token)
@router.post("/v2/login", response_model=Response)
@@ -123,7 +120,7 @@
            logger.error("未知注册应用---")
            continue
        try:
            user_app = UserAppDao(db).get_data_by_id(user.id, app["id"])
            user_app = await UserAppDao(db).get_data_by_id(user.id, app["id"])
            if user_app:
                name  = user_app.username
            token = await service.login(name, login_data.password)
@@ -134,7 +131,7 @@
    # 创建本地token
    access_token = create_access_token(data={"sub": user.username, "user_id": user.id})
    await update_token(db, user.id, access_token, token_dict)
    # await update_token(db, user.id, access_token, token_dict)
    await update_user_token(db, user.id, token_dict)
    result = await pdb.execute(select(AppToken).where(AppToken.id == user.id))
    db_app_token = result.scalars().first()
@@ -184,7 +181,7 @@
        try:
            name = app["id"] + str(int(time.time()))
            register_info = await service.register(name, user.password)
            print(register_info)
            # print(register_info)
            register_dict[app['id']] = {"id":register_info.get("id"), "name": name, "email": register_info.get("email")}
        except Exception as e:
            return Response(code=500, msg=f"Failed to register with {app['id']}: {str(e)}")
app/api/chat.py
@@ -14,7 +14,7 @@
from app.models.agent_model import AgentModel, AgentType
from app.models.base_model import get_db
from app.models.user_model import UserModel
from app.service.common.api_token import DfTokenDao
from app.service.v2.api_token import DfTokenDao
from app.service.dialog import update_session_history
from app.service.basic import BasicService
from app.service.difyService import DifyService
@@ -49,7 +49,7 @@
    if agent_type == AgentType.RAGFLOW:
        ragflow_service = RagflowService(settings.fwr_base_url)
        token = get_ragflow_token(db, current_user.id)
        token = await get_ragflow_token(db, current_user.id)
        try:
            async def forward_to_ragflow():
                while True:
@@ -135,7 +135,7 @@
                        pass
    elif agent_type == AgentType.BISHENG:
        token = get_bisheng_token(db, current_user.id)
        token = await get_bisheng_token(db, current_user.id)
        service_uri = f"{settings.sgb_websocket_url}/api/v1/assistant/chat/{agent_id}?t=&chat_id={chat_id}"
        headers = {'cookie': f"access_token_cookie={token};"}
app/api/files.py
@@ -15,7 +15,7 @@
from app.models.user_model import UserModel
from app.service.basic import BasicService
from app.service.bisheng import BishengService
from app.service.common.api_token import DfTokenDao
from app.service.v2.api_token import DfTokenDao
from app.service.difyService import DifyService
from app.service.ragflow import RagflowService
from app.service.service_token import get_ragflow_token, get_bisheng_token
@@ -50,7 +50,7 @@
            return Response(code=400, msg=str(e))
        if agent.agent_type == AgentType.RAGFLOW:
            token = get_ragflow_token(db, current_user.id)
            token = await get_ragflow_token(db, current_user.id)
            ragflow_service = RagflowService(base_url=settings.fwr_base_url)
            # 查询会话是否存在,不存在先创建会话
            history = await ragflow_service.get_session_history(token, chat_id)
@@ -65,7 +65,7 @@
        elif agent.agent_type == AgentType.BISHENG:
            bisheng_service = BishengService(base_url=settings.sgb_base_url)
            try:
                token = get_bisheng_token(db, current_user.id)
                token = await get_bisheng_token(db, current_user.id)
                result = await bisheng_service.upload(token, file.filename, file_content)
            except Exception as e:
                raise HTTPException(status_code=500, detail=str(e))
app/api/report.py
@@ -36,7 +36,7 @@
        ret = {"message": "Agent error", "type": "close"}
        return websocket.send_json(ret)
    token = get_bisheng_token(db, current_user.id)
    token = await get_bisheng_token(db, current_user.id)
    service_uri = f"{settings.sgb_websocket_url}/api/v1/chat/{agent_id}?type=L1&t=&chat_id={chat_id}"
    headers = {'cookie': f"access_token_cookie={token};"}
@@ -165,7 +165,7 @@
        return ResponseList(code=404, msg="Agent not found")
    bisheng_service = BishengService(base_url=settings.sgb_base_url)
    try:
        token = get_bisheng_token(db, current_user.id)
        token = await get_bisheng_token(db, current_user.id)
        result = await bisheng_service.variable_list(token, agent_id)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
app/api/user.py
@@ -1,11 +1,11 @@
from fastapi import APIRouter, Depends
from app.api import Response, pwd_context, get_current_user
from app.api import Response, pwd_context, get_current_user, ResponseList
from app.models.public_api_model import AppRegisterModel
from app.models.base_model import get_db
from app.models.user import PageParameter, UserStatus, UserInfo, LoginData
from app.models.user_model import UserModel
from app.service.user import get_user_list, edit_user_status, delete_user_data, create_user, edit_user_data, \
    edit_user_pwd, get_user_info, get_user_routers
    edit_user_pwd, get_user_info, get_user_routers, get_user_menus
user_router = APIRouter()
@@ -95,4 +95,12 @@
    routers = await get_user_routers(db,  current_user.id)
    if not routers:
        return Response(code=500, msg="user get failure", data={})
    return Response(code=200, msg="successfully", data=routers)
    return Response(code=200, msg="successfully", data=routers)
@user_router.get("/menus", response_model=ResponseList)
async def user_menus(current_user: UserModel = Depends(get_current_user),db=Depends(get_db)):
    menus = await get_user_menus(db,  current_user.id)
    # return Response(code=200, msg="successfully", data=menus)
    # result = [item.to_dict() for item in agents]
    return ResponseList(code=200, msg="successfully", data=menus)
app/api/v2/__init__.py
copy from app/service/common/__init__.py copy to app/api/v2/__init__.py
app/api/v2/conversation.py
copy from app/service/common/__init__.py copy to app/api/v2/conversation.py
app/api/v2/public_api.py
File was renamed from app/api/public_api.py
@@ -8,8 +8,9 @@
from app.config.const import IMAGE_TO_TEXT, DOCUMENT_TO_CLEANING, DOCUMENT_TO_REPORT, DIFY, BISHENG, RAGFLOW
from app.models.base_model import get_db
from app.models.public_api_model import DfToken, AppRegister
from app.service.common.api_token import DfTokenDao
from app.service.common.app_register import AppRegisterDao
from app.service.v2.api_token import DfTokenDao
from app.service.v2.app_register import AppRegisterDao
from app.service.v2.initialize_data import dialog_menu_sync
from app.task.sync_resources import sync_knowledge, sync_dialog, sync_agent, sync_llm, sync_resource
public_api = APIRouter()
@@ -47,7 +48,7 @@
@public_api.get("/sync/resource", response_model=Response)
async def user_group_list(resource_type:int, db=Depends(get_db)):
async def sync_resource_data(resource_type:int, db=Depends(get_db)):
    if resource_type == 1:
        await sync_knowledge()
    elif resource_type == 2:
@@ -59,4 +60,15 @@
    else:
        await sync_resource()
    return Response(code=200, msg="", data={})
    return Response(code=200, msg="", data={})
@public_api.get("/sync/dialog_menu", response_model=Response)
async def sync_dialog_menu(db=Depends(get_db)):
    try:
        await dialog_menu_sync(db)
    except Exception as e:
        logger.error(e)
        return Response(code=500, msg="failed", data={})
    return Response(code=200, msg="success", data={})
app/models/__init__.py
@@ -14,6 +14,7 @@
from .token_model import *
from .session_model import SessionModel
from .public_api_model import *
from .menu_model import *
# 获取当前时区的时间
app/models/group_model.py
@@ -39,6 +39,7 @@
    created_at = Column(DateTime, default=datetime.now())
    updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now())
    creator = Column(Integer)
    group_type = Column(Integer, default=1)
    knowledges = relationship('KnowledgeModel',
app/models/menu_model.py
New file
@@ -0,0 +1,39 @@
from datetime import datetime
from sqlalchemy import Column, Integer, String, DateTime, Table, ForeignKey, UniqueConstraint
from app.models.base_model import Base
class WebMenuModel(Base):
    __tablename__ = 'web_menu'
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(128))
    describe = Column(String(1000))
    desc = Column(String(1000))
    icon = Column(String(16))
    img = Column(String(255))
    def to_dict(self):
        return {
            'id': self.id,
            'title': self.title,
            'icon': self.icon,
            'img': self.img,
            'desc': self.desc,
            'dialog': self.describe
        }
    def __repr__(self):
        return '<Role name:%r description:%r iconCls:%r seq:%r>\n' \
            % (self.NAME, self.DESCRIPTION, self.ICONCLS, self.SEQ)
class MenuCapacityModel(Base):
    __tablename__ = 'menu_capacity'
    __table_args__ = (UniqueConstraint('menu_id', 'capacity_id', name='menu_capacity_id_ix'),)
    id = Column(Integer, primary_key=True, index=True)
    menu_id = Column(Integer)
    capacity_id = Column(String(36))
    capacity_type = Column(Integer)
app/models/token_model.py
@@ -7,6 +7,7 @@
from Log import logger
from app.config.const import RAGFLOW
from app.models.base_model import Base
from app.service.auth import UserAppDao
class TokenModel(Base):
@@ -59,7 +60,7 @@
    if not isinstance(user_id, int) or user_id <= 0:
        return
    db_token = None
    print(token)
    # print(token)
    try:
        # 查询现有记录
        db_token = db.query(TokenModel).filter_by(user_id=user_id).first()
@@ -88,5 +89,7 @@
        db.rollback()  # 回滚事务
def get_token(db: Session, user_id: int) -> Type[TokenModel] | None:
    return db.query(TokenModel).filter_by(user_id=user_id).first()
async def get_token(db: Session, user_id: int):
    # return db.query(TokenModel).filter_by(user_id=user_id).first()
    return {i.app_type.replace("app", "token"): i.access_token for i in await UserAppDao(db).get_user_datas(user_id)}
app/service/auth.py
@@ -77,7 +77,7 @@
        db.refresh(db_user)
        user_id = db_user.id
        for k, v in register_dict.items():
            UserAppDao(db).update_and_insert_token(v.get("name"), pwd, v.get("email"), user_id, str(v.get("id")), k)
            await UserAppDao(db).update_and_insert_data(v.get("name"), pwd, v.get("email"), user_id, str(v.get("id")), k)
    except Exception as e:
        logger.error(e)
@@ -89,11 +89,10 @@
async def update_user_token(db, user_id, token_dict):
    try:
        for k, v in token_dict.items():
            UserAppDao(db).update_user_app_data({"user_id": user_id, "app_type": k},
                                                {"access_token": v, "token_at": datetime.now()})
            await UserAppDao(db).update_user_app_data({"user_id": user_id, "app_type": k},
                                                      {"access_token": v, "token_at": datetime.now()})
    except Exception as e:
        logger.error(e)
@@ -105,11 +104,11 @@
    def __init__(self, db: Session):
        self.db = db
    def get_data_by_id(self, user_id: int, app_type: int) -> Type[UserAppModel] | None:
    async def get_data_by_id(self, user_id: int, app_type: int) -> Type[UserAppModel] | None:
        session = self.db.query(UserAppModel).filter_by(user_id=user_id, app_type=app_type).first()
        return session
    def update_user_app_data(self, query: int, update_data: str):
    async def update_user_app_data(self, query: dict, update_data: dict):
        logger.error("更新数据df update_app_data---------------------------")
        try:
@@ -120,7 +119,8 @@
            self.db.rollback()
            raise Exception("更新失败!")
    def insert_user_app_data(self, username: str, password: str, email: str, user_id: int, app_id: str, app_type: int):
    async def insert_user_app_data(self, username: str, password: str, email: str, user_id: int, app_id: str,
                                   app_type: int):
        logger.error("新增数据df insert_user_app_data---------------------------")
        new_session = UserAppModel(
            username=username,
@@ -135,15 +135,18 @@
        self.db.refresh(new_session)
        return new_session
    def update_and_insert_token(self, username: str, password: str, email: str, user_id: int, app_id: str,
                                app_type: int):
    async def update_and_insert_data(self, username: str, password: str, email: str, user_id: int, app_id: str,
                                     app_type: int):
        logger.error("更新或者添加数据 update_and_insert_token---------------------------")
        token_boj = self.get_data_by_id(user_id, app_type)
        token_boj = await self.get_data_by_id(user_id, app_type)
        if token_boj:
            self.update_user_app_data({"id": token_boj.id}, {"username": username,
                                                             "password": password, "email": email, "username": username,
                                                             "updated_at": datetime.now(),
                                                             })
            await self.update_user_app_data({"id": token_boj.id}, {"username": username,
                                                                   "password": password, "email": email,
                                                                   "updated_at": datetime.now(),
                                                                   })
        else:
            self.insert_user_app_data(username, password, email, user_id, app_id, app_type)
            await self.insert_user_app_data(username, password, email, user_id, app_id, app_type)
    async def get_user_datas(self, user_id: int):
        return self.db.query(UserAppModel).filter_by(user_id=user_id).all()
app/service/group.py
@@ -81,7 +81,7 @@
                         UserModel.id.in_(user_list)).all()}
        print(user_dict)
        ragflow_service = RagflowService(settings.fwr_base_url)
        token = get_ragflow_token(db, user_id)
        token = await get_ragflow_token(db, user_id)
        try:
            for old_user in group_user_list:
app/service/service_token.py
@@ -1,23 +1,26 @@
from Log import logger
from app.config.config import settings
from app.config.const import BISHENG, RAGFLOW
from app.models import UserModel
from app.models.token_model import TokenModel
from app.service.auth import UserAppDao
from app.service.bisheng import BishengService
from app.service.ragflow import RagflowService
def get_bisheng_token(db, user_id: int):
    token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first()
async def get_bisheng_token(db, user_id: int):
    # token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first()
    token = await UserAppDao.get_data_by_id(user_id, BISHENG)
    if not token:
        return None
    return token.bisheng_token
    return token.access_token
def get_ragflow_token(db, user_id: int):
    token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first()
async def get_ragflow_token(db, user_id: int):
    token = await UserAppDao.get_data_by_id(user_id, RAGFLOW)
    if not token:
        return None
    return token.ragflow_token
    return token.access_token
async def get_ragflow_new_token(db, user_id: int, app_type):
app/service/user.py
@@ -1,30 +1,35 @@
import time
from datetime import datetime
from app.api import pwd_context
from app.config.config import settings
from app.config.const import RAGFLOW, BISHENG, DIFY
from app.models import RoleModel, GroupModel, AgentType, role_resource_table
from app.models.menu_model import WebMenuModel, MenuCapacityModel
from app.models.user_model import UserModel
from Log import logger
from app.service.auth import UserAppDao
from app.service.bisheng import BishengService
from app.service.common.app_register import AppRegisterDao
from app.service.v2.app_register import AppRegisterDao
from app.service.difyService import DifyService
from app.service.ragflow import RagflowService
from app.service.service_token import get_ragflow_token, get_bisheng_token, get_ragflow_new_token
async def get_user_list(db, page_index: int, page_size: int, keyword: str, role_key:str, user_id):
    query = db.query(UserModel).filter(UserModel.permission!="admin")
async def get_user_list(db, page_index: int, page_size: int, keyword: str, role_key: str, user_id):
    query = db.query(UserModel).filter(UserModel.permission != "admin")
    # if role_key != "admin":
    #     query.filter(UserModel.creator==user_id)
    if keyword:
        query = query.filter(UserModel.group_name.like('%{}%'.format(keyword)))
    users = query.order_by(UserModel.id.desc()).limit(page_size).offset(
        (page_index - 1) * page_size).all()
    return {"total": query.count(), "rows":  [user.to_json() for user in users]}
    return {"total": query.count(), "rows": [user.to_json() for user in users]}
async def edit_user_status(db, status: str, user_id: int):
    try:
        db.query(UserModel).filter(UserModel.id == user_id).update({"status":status})
        db.query(UserModel).filter(UserModel.id == user_id).update({"status": status})
        db.commit()
    except Exception as e:
        logger.error(e)
@@ -35,7 +40,7 @@
async def delete_user_data(db, user_id: str):
    try:
        db.query(UserModel).filter(UserModel.id == user_id, UserModel.permission!="admin").delete()
        db.query(UserModel).filter(UserModel.id == user_id, UserModel.permission != "admin").delete()
        db.commit()
    except Exception as e:
        logger.error(e)
@@ -46,38 +51,65 @@
async def create_user(db, user_name, email, phone, login_name, password, roles, groups, user_id):
    try:
        bisheng_service = BishengService(settings.sgb_base_url)
        ragflow_service = RagflowService(settings.fwr_base_url)
        # 注册到毕昇
        try:
            bisheng_info = await bisheng_service.register(user_name, password)
        except Exception as e:
            logger.error(f"Failed to register with Bisheng: {str(e)}")
            return False
        # 注册到ragflow
        try:
            ragflow_info = await ragflow_service.register(user_name, password)
        except Exception as e:
            logger.error(f"Failed to register with Ragflow: {str(e)}")
            return False
        # bisheng_service = BishengService(settings.sgb_base_url)
        # ragflow_service = RagflowService(settings.fwr_base_url)
        #
        # # 注册到毕昇
        # try:
        #     bisheng_info = await bisheng_service.register(user_name, password)
        # except Exception as e:
        #     logger.error(f"Failed to register with Bisheng: {str(e)}")
        #     return False
        #
        # # 注册到ragflow
        # try:
        #     ragflow_info = await ragflow_service.register(user_name, password)
        # except Exception as e:
        #     logger.error(f"Failed to register with Ragflow: {str(e)}")
        #     return False
        app_register = AppRegisterDao(db).get_apps()
        register_dict = {}
        for app in app_register:
            if app["id"] == RAGFLOW:
                service = RagflowService(settings.fwr_base_url)
            elif app["id"] == BISHENG:
                service = BishengService(settings.sgb_base_url)
            elif app["id"] == DIFY:
                service = DifyService(settings.dify_base_url)
            else:
                logger.error("未知注册应用---")
                continue
            try:
                name = app["id"] + str(int(time.time()))
                register_info = await service.register(name, password)
                # print(register_info)
                register_dict[app['id']] = {"id": register_info.get("id"), "name": name,
                                            "email": register_info.get("email")}
            except Exception as e:
                logger.error(e)
                return False
        # 存储用户信息
        hashed_password = pwd_context.hash(password)
        user_model =  UserModel(username=user_name, hashed_password=hashed_password, email=email,ragflow_id=ragflow_info.get("id"),bisheng_id=bisheng_info.get("user_id"),
                                phone=phone,login_name=login_name)
        user_model = UserModel(username=user_name, hashed_password=hashed_password, email=email,
                               ## ragflow_id=ragflow_info.get("id"),bisheng_id=bisheng_info.get("user_id"),
                               phone=phone, login_name=login_name)
        pwd = user_model.encrypted_password(password)
        user_model.roles = [db.get(RoleModel, roleId) for roleId in roles]
        user_model.password = pwd
        if groups:
            user_model.groups = [db.get(GroupModel, groupId) for groupId in groups]
        user_model.creator = user_id
        db.add(user_model)
        db.commit()
        db.refresh(user_model)
        u_id = user_model.id
        for k, v in register_dict.items():
            await UserAppDao(db).update_and_insert_data(v.get("name"), pwd, v.get("email"), u_id, str(v.get("id")), k)
    except Exception as e:
        logger.error(e)
        db.rollback()
        # db.rollback()
        return False
    return True
@@ -100,21 +132,21 @@
    return True
async def edit_user_pwd(db, user_id, current_user_id ,new_password="000000"):
async def edit_user_pwd(db, user_id, current_user_id, new_password="000000"):
    try:
        user = db.query(UserModel).filter(UserModel.id == user_id).first()
        pwd = user.decrypted_password()
        for app_type in AppRegisterDao(db).get_app():
            if app_type == AgentType.RAGFLOW:
                token = await get_ragflow_new_token(db, user_id, app_type)
        for app in AppRegisterDao(db).get_apps():
            if app.get("id") == RAGFLOW:
                token = await get_ragflow_new_token(db, user_id, 1)
                ragflow_service = RagflowService(settings.fwr_base_url)
                await ragflow_service.set_user_password(token, pwd, new_password)
            elif app_type == AgentType.BISHENG:
                token = get_bisheng_token(db, current_user_id)
            elif app.get("id") == BISHENG:
                token = await get_bisheng_token(db, current_user_id)
                bisheng_service = BishengService(settings.sgb_base_url)
                await bisheng_service.change_password_public(token, user.username, pwd, new_password)
            else:
                logger.error("注册未知应用:{}".format(app_type))
                logger.error("注册未知应用:{}".format(app.get("id")))
        # hashed_password = pwd_context.hash(password)
        hashed_password = user.encrypted_password(new_password)
@@ -148,7 +180,7 @@
    if user.permission == "admin":
        permissions = ["*:*:*"]
    return {"permissions": list(permissions), "dept": dept , "roles":  roles, "user": user.to_dict()}
    return {"permissions": list(permissions), "dept": dept, "roles": roles, "user": user.to_dict()}
async def role_resource(role_set, role_list, permissions, roles):
@@ -167,6 +199,7 @@
    dept_set = set()
    user = db.query(UserModel).filter_by(id=user_id).first()
    parent_id = ""
    async def role_resource(role_set, permissions, roles):
        nonlocal parent_id
        for role in roles:
@@ -192,14 +225,50 @@
                parent_ogt = parent_ogt.parent
    tmp_dit = {}
    for permission in permissions.values():
        tmp_dit[permission["parentId"]] = tmp_dit.get(permission["parentId"], []) +[permission]
        tmp_dit[permission["parentId"]] = tmp_dit.get(permission["parentId"], []) + [permission]
    def get_child(parent_id):
        res = permissions[parent_id]
        res["children"] = [get_child(i["id"]) for i in tmp_dit.get(parent_id, [])]
        return res
    print(parent_id)
    print(tmp_dit)
    return {"routers": [get_child(i["id"]) for i in tmp_dit.get(parent_id, [])]}
async def get_user_menus(db, user_id):
    dialog_list = []
    agent_list = []
    menu_dict = {}
    res = []
    user = db.query(UserModel).filter_by(id=user_id).first()
    for group in user.groups:
        for dialog in group.dialogs:
            dialog_list.append(dialog.id)
        for agent in group.agents:
            agent_list.append(agent.id)
    menu_list = db.query(WebMenuModel.id, WebMenuModel.title, WebMenuModel.describe, WebMenuModel.icon, WebMenuModel.desc,
                         WebMenuModel.img, MenuCapacityModel.capacity_id, MenuCapacityModel.capacity_type).outerjoin(
        MenuCapacityModel, WebMenuModel.id == MenuCapacityModel.menu_id).all()
    for menu in menu_list:
        menu_dict[menu.id] = menu_dict.get(menu.id, []) + [menu]
    # print(dialog_list)
    for menus in menu_dict.values():
        for m in menus:
            if user.permission == "admin":
                continue
            elif not m.capacity_type or m.capacity_type == 1 and m.capacity_id not in dialog_list:
                break
            elif not m.capacity_type or m.capacity_type == 2 and m.capacity_id not in agent_list:
                break
        else:
            res.append({
            'id': menus[0].id,
            'title': menus[0].title,
            'icon': menus[0].icon,
            'img': menus[0].img,
            'desc': menus[0].desc,
            'dialog': menus[0].describe
        })
    return res
app/service/v2/__init__.py
app/service/v2/api_token.py
app/service/v2/app_register.py
app/service/v2/initialize_data.py
New file
@@ -0,0 +1,36 @@
import json
from Log import logger
from app.models import MenuCapacityModel, WebMenuModel, GroupModel
async def dialog_menu_sync(db):
    menu_list = []
    with open("env_conf/menu_conf.json", 'r', encoding='utf-8') as file:
        # 加载JSON数据
        data = json.load(file)
        menu_list = data.get("data", [])
    db.query(WebMenuModel).delete()
    db.query(MenuCapacityModel).delete()
    db.commit()
    for menu in menu_list:
        # print(menu)
        agent = menu.pop("agent", [])
        for i in agent:
            capacity = MenuCapacityModel(menu_id=menu["id"], capacity_id=i, capacity_type=2)
            db.add(capacity)
        dialog = menu.pop("dialog", [])
        for i in dialog:
            capacity = MenuCapacityModel(menu_id=menu["id"], capacity_id=i, capacity_type=1)
            db.add(capacity)
        menu_obj = WebMenuModel(**menu)
        db.add(menu_obj)
    db.commit()
async def default_group_sync(db):
    group = db.query(GroupModel).filter_by(group_type=2).first()
    if not group:
        logger.error("未初始化")
app/task/fetch_agent.py
@@ -1,12 +1,14 @@
from typing import Dict, List, Tuple
from sqlalchemy import create_engine, Column, String, Integer
from sqlalchemy.dialects.postgresql import array
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import sessionmaker
from app.config.config import settings
from app.models.agent_model import AgentModel
from app.models.base_model import SessionLocal, Base
from app.service.v2.initialize_data import dialog_menu_sync
# 创建数据库引擎和会话工厂
engine_bisheng = create_engine(settings.sgb_db_url)
@@ -147,3 +149,13 @@
        print("Agents synchronized successfully")
    except Exception as e:
        print(f"Failed to sync agents: {str(e)}")
async def sync_web_menu():
    db = SessionLocal()
    await dialog_menu_sync(db)
async def sync_default_group():
    db = SessionLocal()
    await dialog_menu_sync(db)
env_conf/menu_conf.json
New file
@@ -0,0 +1,104 @@
{
  "data": [
    {
      "id": 10,
      "title": "报告生成",
      "icon": "2",
      "img": "/src/assets/index/2.png",
      "desc": "基于您创建的报告格式和知识库中的文档内容,快速生成定制报告,并支持一键下载。",
      "describe": "基于您创建的报告格式和知识库中的文档内容,快速生成定制报告,并支持一键下载。",
      "agent" : [],
      "dialog": ["1"]
    },
    {
      "id": 1,
      "title": "报表合并",
      "icon": "6",
      "img": "/src/assets/index/6.png",
      "desc": "基于您上传的报表进行合并,助您快速完成报表整合与分析",
      "describe": "基于您上传的报表进行合并,助您快速完成报表整合与分析",
      "agent" : [],
      "dialog": ["2"]
    },
    {
      "id": 2,
      "title": "知识问答",
      "icon": "5",
      "img": "/src/assets/index/5.png",
      "desc": "遍历已创建的文档知识库,生成完整和准确的答案,同时显示来源文档供您参考",
      "describe": "垂域知识的问答助手,针对你的提问,我们将遍历已创建的文档知识库,生成完整和准确的答案,同时显示来源文档供您参考。",
      "agent" : [],
      "dialog": []
    },
    {
      "id": 3,
      "title": "文档智能",
      "icon": "7",
      "img": "/src/assets/index/7.png",
      "desc": "个人知识库的问答助手,基于您上传的文档进行问答,支持多文档",
      "describe": "个人知识库的问答助手,基于您上传的文档进行问答,支持多文档,大小在30M以内。",
      "agent" : [],
      "dialog": ["3"]
    },
    {
      "id": 4,
      "title": "智能问答",
      "icon": "1",
      "img": "/src/assets/index/1.png",
      "desc": "能够理解和学习人类的语言,具备多轮对话的能力",
      "describe": "我可以理解和学习人类的语言,具备多轮对话的能力,现在和我开始交流吧~",
      "agent" : [],
      "dialog": []
    },
    {
      "id": 5,
      "title": "智能数据",
      "icon": "8",
      "img": "/src/assets/index/8.png",
      "desc": "您可以上传文档或添加数据库地址,小数可针对你文档的数据进行分析,并生成指定的图表",
      "describe": "您可以上传文档或添加数据库地址,小数可针对你文档的数据进行分析,并生成指定的图表",
      "agent" : ["3", "4"],
      "dialog": []
    },
    {
      "id": 6,
      "title": "小数绘图",
      "icon": "7",
      "img": "/src/assets/index/7.png",
      "desc": "基于您上传的图片,生成对应的文字描述并基于图片内容实现问答。",
      "describe": "基于您上传的图片,生成对应的文字描述并基于图片内容实现问答。",
      "agent" : ["3"],
      "dialog": []
    },
    {
      "id": 7,
      "title": "文档出卷",
      "icon": "6",
      "img": "/src/assets/index/6.png",
      "desc": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
      "describe": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
      "agent" : [],
      "dialog": []
    },
    {
      "id": 8,
      "title": "出题组卷",
      "icon": "6",
      "img": "/src/assets/index/6.png",
      "desc": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
      "describe": "您可以上传文档,小数能针对单文档或多个文档内容自动出题,高效便捷的帮助你建立私人题库。",
      "agent" : ["4"],
      "dialog": []
    },
    {
      "id": 9,
      "title": "文档报告",
      "icon": "2",
      "img": "/src/assets/index/2.png",
      "desc": "基于您创建的报告格式和上传的文档内容,快速生成定制报告,并支持一键下载。",
      "describe": "基于您创建的报告格式和上传的文档内容,快速生成定制报告,并支持一键下载。",
      "agent" : [],
      "dialog": []
    }
  ]
}
main.py
@@ -14,16 +14,14 @@
from app.api.knowledge import knowledge_router
from app.api.llm import llm_router
from app.api.organization import dept_router
from app.api.public_api import public_api
from app.api.v2.public_api import public_api
from app.api.report import router as report_router
from app.api.resource import menu_router
# from app.api.sync_data import sync_router
from app.api.user import user_router
from app.api.group import group_router
from app.api.role import role_router
from app.models.base_model import init_db
from app.task.fetch_agent import sync_agents, initialize_agents
from app.task.sync_resources import sync_resource
from app.task.fetch_agent import sync_agents, initialize_agents, sync_web_menu
# 使用 Lifespan 事件处理程序
@@ -33,6 +31,8 @@
    initialize_agents()
    # 在应用启动时同步代理
    sync_agents()
    await sync_default_group()
    await sync_web_menu()
    yield
    # 在应用关闭时执行清理操作(如果需要)
    pass