zhaoqingang
2024-11-11 c1768114de381e37e272e9faf7db8e95a93ff381
role group user..
8个文件已修改
14个文件已添加
1140 ■■■■■ 已修改文件
app/Log/__init__.py 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/Log/log.log 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/api/group.py 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/api/organization.py 补丁 | 查看 | 原始文档 | blame | 历史
app/api/role.py 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/api/user.py 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/__init__.py 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/agent_model.py 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/dialog_model.py 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/group_model.py 119 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/knowledge_model.py 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/llm_model.py 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/organization_model.py 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/resource_model.py 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/role_model.py 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/models/user_model.py 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/service/group.py 68 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/service/organization.py 补丁 | 查看 | 原始文档 | blame | 历史
app/service/ragflow.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/service/role.py 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/service/user.py 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.py 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/Log/__init__.py
New file
@@ -0,0 +1,16 @@
import logging
import logging.handlers
def init_log():
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    # ch = logging.StreamHandler()
    fh = logging.handlers.RotatingFileHandler("app/Log/log.log",mode="a",maxBytes = 100*1024, backupCount = 10)
    formatter = logging.Formatter(
        "%(asctime)s - %(module)s - %(funcName)s - line:%(lineno)d - %(levelname)s - %(message)s"
    )
    fh.setFormatter(formatter)
    logger.addHandler(fh)  # 将日志输出至文件
    return logger
logger = init_log()
app/Log/log.log
New file
@@ -0,0 +1 @@
2024-11-11 16:33:10,255 - user - get_user_list - line:5 - ERROR - ffffffff
app/api/group.py
@@ -1,16 +1,13 @@
from ast import parse
from fastapi import APIRouter, Depends
from app.api import Response, pwd_context, get_current_user, ResponseList
from app.config.config import settings
from win32ctypes.pywin32.pywintypes import datetime
from app.api import Response, get_current_user
from app.models.base_model import get_db
from app.models.group_model import GroupInfoModel, UserGroupModel, GroupData, GroupUsers
from app.models.group_model import GroupModel, GroupData, GroupUsers
from app.models.user import PageParameter
from app.models.user_model import UserModel
from app.service.bisheng import BishengService
from app.service.group import create_group, group_list, edit_group_data, delete_group_data, get_group_users, \
    save_user_to_group
from app.service.token import get_bisheng_token
group_router = APIRouter()
@@ -25,7 +22,7 @@
async def add_group(group: GroupData, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    if not group.group_name:
        return Response(code=400, msg="The group_name cannot be empty!")
    db_group = db.query(GroupInfoModel).filter(GroupInfoModel.group_name == group.group_name).first()
    db_group = db.query(GroupModel).filter(GroupModel.group_name == group.group_name).first()
    if db_group:
        return Response(code=200, msg="group already created")
    is_create = await create_group(db, group.group_name, group.group_description)
@@ -38,11 +35,12 @@
async def edit_group(group: GroupData, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    if not group.group_name:
        return Response(code=400, msg="The group_name cannot be empty!")
    db_group = db.query(GroupInfoModel).filter(GroupInfoModel.group_name == group.group_name).first()
    db_group = db.query(GroupModel).filter(GroupModel.group_name == group.group_name).first()
    if db_group:
        return Response(code=200, msg="group_name already created")
    is_edit = await edit_group_data(db, group.id,
                                    {"group_name": group.group_name, "group_description": group.group_description})
                                    {"group_name": group.group_name, "group_description": group.group_description,
                                     "updated_at": datetime.now()})
    if not is_edit:
        return Response(code=200, msg="group edit failure", data={})
    return Response(code=200, msg="group edit successfully", data={"group_name": group.group_name})
@@ -50,13 +48,13 @@
@group_router.post("/edit_group_status", response_model=Response)
async def edit_group_status(group: GroupData, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    if group.group_status not in [0, 1]:
    if group.group_status not in ["0", "1"]:
        return Response(code=400, msg="The status cannot be {}!".format(group.group_status))
    db_group = db.query(GroupInfoModel).filter(GroupInfoModel.group_id == group.id).first()
    db_group = db.query(GroupModel).filter(GroupModel.id == group.id).first()
    if not db_group:
        return Response(code=200, msg="group does not exist")
    is_edit = await edit_group_data(db, group.id,
                                    {"group_status": group.group_status})
                                    {"status": group.group_status,"updated_at": datetime.now()})
    if not is_edit:
        return Response(code=200, msg="group status edit failure", data={})
    return Response(code=200, msg="group status edit successfully", data={"group_name": group.group_name})
@@ -64,7 +62,7 @@
@group_router.post("/delete_group", response_model=Response)
async def delete_group(group: GroupData, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    db_group = db.query(GroupInfoModel).filter(GroupInfoModel.group_id == group.id).first()
    db_group = db.query(GroupModel).filter(GroupModel.id == group.id).first()
    if not db_group:
        return Response(code=200, msg="group does not exist")
    is_edit = await delete_group_data(db, group.id)
@@ -75,16 +73,16 @@
@group_router.post("/group_users", response_model=Response)
async def group_users(group: GroupData, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    db_group = db.query(GroupInfoModel).filter(GroupInfoModel.group_id == group.id).first()
    db_group = db.query(GroupModel).filter(GroupModel.id == group.id).first()
    if not db_group:
        return Response(code=200, data={})
        return Response(code=200, msg="group does not exist", data={})
    return Response(code=200, msg="success", data=await get_group_users(db, group.id))
@group_router.post("/save_group_user", response_model=Response)
async def save_group_user(group_user: GroupUsers, current_user: UserModel = Depends(get_current_user),
                          db=Depends(get_db)):
    db_group = db.query(GroupInfoModel).filter(GroupInfoModel.group_id == group_user.id).first()
    db_group = db.query(GroupModel).filter(GroupModel.id == group_user.id).first()
    if not db_group:
        return Response(code=200, msg="group does not exist")
    is_success = await save_user_to_group(db, current_user.id, group_user.id, group_user.user_list)
app/api/organization.py
app/api/role.py
New file
@@ -0,0 +1,66 @@
# coding:utf-8
from fastapi import APIRouter, Depends
from app.api import Response, get_current_user
from app.models.base_model import get_db
from app.models.role_model import RoleData, RoleModel, RoleStatus, RoleEdit
from app.models.user import PageParameter
from app.models.user_model import UserModel
from app.service.role import role_list, create_role, delete_role_data, edit_role_status, edit_role_resource
role_router = APIRouter()
@role_router.get("/list", response_model=Response)
async def user_group_list(paras: PageParameter, current_user: UserModel = Depends(get_current_user),
                          db=Depends(get_db)):
    return Response(code=200, msg="", data=await role_list(db, paras.page_size, paras.page_index, paras.keyword))
@role_router.post("/add_role", response_model=Response)
async def add_role(role: RoleData, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    if not role.roleName:
        return Response(code=400, msg="The roleName cannot be empty!")
    db_role = db.query(RoleModel).filter(RoleModel.name == role.roleName).first()
    if db_role:
        return Response(code=200, msg="role already created")
    is_create = await create_role(db, role.roleName, role.remark, current_user.id)
    if not is_create:
        return Response(code=200, msg="role create failure", data={})
    return Response(code=200, msg="role create successfully", data={"roleName": role.roleName})
@role_router.delete("/delete_role/{role_id}", response_model=Response)
async def delete_group(role_id: str, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    db_role = db.query(RoleModel).filter(RoleModel.id == role_id).first()
    if not db_role:
        return Response(code=200, msg="role does not exist")
    is_edit = await delete_role_data(db, role_id)
    if not is_edit:
        return Response(code=200, msg="role delete failure", data={})
    return Response(code=200, msg="role delete successfully", data={})
@role_router.put("/change_status", response_model=Response)
async def edit_group_status(role: RoleStatus, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    if role.status not in ["0", "1"]:
        return Response(code=400, msg="The status cannot be {}!".format(role.status))
    db_role = db.query(RoleModel).filter(RoleModel.id == role.role_id).first()
    if not db_role:
        return Response(code=200, msg="role does not exist")
    is_edit = await edit_role_status(db, role.status,role.role_id)
    if not is_edit:
        return Response(code=200, msg="role status edit failure", data={})
    return Response(code=200, msg="role status edit successfully", data={})
@role_router.put("/edit_role", response_model=Response)
async def edit_role_data(role: RoleEdit, current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    db_role = db.query(RoleModel).filter(RoleModel.id == role.role_id).first()
    if not db_role:
        return Response(code=200, msg="role does not exist")
    if role.roleName:
        db_role = db.query(RoleModel).filter(RoleModel.name == role.roleName).first()
        if db_role:
            return Response(code=200, msg="role already created")
    is_edit = await edit_role_resource(db, role.role_id,role.roleName, role.remark, role.resources)
    if not is_edit:
        return Response(code=200, msg="role edit failure", data={})
    return Response(code=200, msg="role edit successfully", data={})
app/api/user.py
@@ -1,35 +1,16 @@
from fastapi import APIRouter, Depends
from app.api import Response, pwd_context, get_current_user, ResponseList
from app.config.config import settings
from app.api import Response, pwd_context, get_current_user
from app.models.base_model import get_db
from app.models.group_model import UserGroupModel
from app.models.user import PageParameter
from app.models.user_model import UserModel
from app.service.bisheng import BishengService
from app.service.ragflow import RagflowService
from app.service.token import get_bisheng_token
from app.service.user import get_user_list
user_router = APIRouter()
@user_router.post("/list", response_model=Response)
async def user_list(current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    bisheng_service = BishengService(settings.sgb_base_url)
    ragflow_service = RagflowService(settings.fwr_base_url)
    db_user = db.query(UserModel).filter(UserGroupModel.group_name == UserModel.username).first()
    if db_user:
        return Response(code=200, msg="Username already registered")
    # 注册到毕昇
    try:
        token = get_bisheng_token(db, current_user.id)
        print(token)
        result = await bisheng_service.user_list(token)
        print(result)
    except Exception as e:
        return Response(code=500, msg=f"Failed to register with Bisheng: {str(e)}")
    return ResponseList(code=200, msg="", data=result)
@user_router.get("/list", response_model=Response)
async def user_list(paras: PageParameter,current_user: UserModel = Depends(get_current_user), db=Depends(get_db)):
    return Response(code=200, msg="", data=await get_user_list(db, paras.page_size, paras.page_index, paras.keyword))
app/models/__init__.py
New file
@@ -0,0 +1,9 @@
from .agent_model import *
from .dialog_model import *
from .group_model import *
from .knowledge_model import *
from .llm_model import *
from .organization_model import *
from .resource_model import *
from .role_model import *
from .user_model import *
app/models/agent_model.py
@@ -1,5 +1,7 @@
import json
from datetime import datetime
from enum import IntEnum
from sqlalchemy import Column, String, Enum as SQLAlchemyEnum, Integer
from sqlalchemy import Column, String, Enum as SQLAlchemyEnum, Integer, BigInteger, DateTime, Text, Float, Boolean
from app.models.base_model import Base
@@ -25,3 +27,111 @@
            'agent_type': self.agent_type,
            'type': self.type
        }
class CanvasModel(Base):
    __tablename__ = 'user_canvas'
    __mapper_args__ = {
        # "order_by": 'SEQ'
    }
    id = Column(String(32), primary_key=True)
    create_time = Column(BigInteger)
    create_date = Column(DateTime, default=datetime.now)
    update_time = Column(BigInteger)
    update_date = Column(DateTime, default=datetime.now)
    avatar = Column(Text)
    user_id = Column(String(255))
    title = Column(String(255))
    description = Column(Text)
    canvas_type = Column(String(32))
    dsl = Column(Text)
    def get_id(self):
        return str(self.id)
    def to_json(self):
        return {
            'id': self.id,
            'create_time': self.create_time,
            'create_date': self.create_date,
            'update_time': self.update_time,
            'update_date': self.update_date,
            'avatar': self.avatar,
            'user_id': self.user_id,
            'title': self.title,
            'description': self.description,
            'canvas_type': self.canvas_type,
            'dsl': self.dsl
        }
class UnifiedAgentModel(Base):
    __tablename__ = 'unified_agent'
    id = Column(String(32), primary_key=True)
    tenant_id = Column(String(32))
    name = Column(String(255))
    description = Column(Text)
    icon = Column(Text)
    prompt_type = Column(String(16))
    prompt_config = Column(Text, default='{}')
    status = Column(String(1))
    prompts = Column(Text, default='[]')
    language = Column(String(32))
    llm_id = Column(String(128), default='')
    llm_setting = Column(Text, default='{}')
    similarity_threshold = Column(Float, default=0.0)
    vector_similarity_weight = Column(Float, default=0.0)
    top_n = Column(Integer, default=0)
    top_k = Column(Integer, default=0)
    do_refer = Column(String(1), default='')
    rerank_id = Column(String(128), default='')
    kb_ids = Column(Text, default='[]')
    hide = Column(Boolean, default=False)
    type = Column(Integer)
    canvas_type = Column(String(32), default="")
    dsl = Column(Text, default='{}')
    def get_id(self):
        return str(self.id)
    def to_json(self):
        if self.prompts is None or self.prompts == '':
            self.prompts = '[]'
        if self.prompt_config is None or self.prompt_config == '':
            self.prompt_config = '{}'
        if self.dsl is None or self.dsl == '':
            self.dsl = '{}'
        if self.kb_ids is None or self.kb_ids == '':
            self.kb_ids = '[]'
        return {
            'id': self.id,
            'create_time': self.create_time,
            'create_date': self.create_date,
            'update_time': self.update_time,
            'update_date': self.update_date,
            'tenant_id': self.tenant_id,
            'name': self.name,
            'description': self.description,
            'icon': self.icon,
            'language': self.language,
            'llm_id': self.llm_id,
            'similarity_threshold': self.similarity_threshold,
            'vector_similarity_weight': self.vector_similarity_weight,
            'top_n': self.top_n,
            'top_k': self.top_k,
            'do_refer': self.do_refer,
            'kb_ids': self.kb_ids,
            'status': self.status,
            'prompt_type': self.prompt_type,
            'prompt_config': json.loads(self.prompt_config),
            'prompts': json.loads(self.prompts),
            'dsl': json.loads(self.dsl)
        }
    @staticmethod
    def is_type(record_id, t):
        record = UnifiedAgent.get_by_id(record_id)
        return record and record.type == t
app/models/dialog_model.py
New file
@@ -0,0 +1,62 @@
from datetime import datetime
from sqlalchemy import Column, Integer, String, Table, ForeignKey, DateTime, BigInteger, Text, Float, Boolean
from sqlalchemy.orm import relationship, backref
from app.models.base_model import Base
class DialogModel(Base):
    __tablename__ = 'dialogs'
    __mapper_args__ = {
        # "order_by": 'SEQ'
    }
    id = Column(String(32), primary_key=True)
    create_time = Column(BigInteger)
    create_date = Column(DateTime)
    update_time = Column(BigInteger)
    update_date = Column(DateTime)
    tenant_id = Column(String(32))
    name = Column(String(255))
    description = Column(Text)
    icon = Column(Text)
    language = Column(String(32))
    llm_id = Column(String(128))
    llm_setting = Column(Text)
    prompt_type = Column(String(16))
    prompt_config = Column(Text)
    similarity_threshold = Column(Float)
    vector_similarity_weight = Column(Float)
    top_n = Column(Integer)
    top_k = Column(Integer)
    do_refer = Column(String(1))
    rerank_id = Column(String(128))
    kb_ids = Column(Text)
    status = Column(String(1))
    hide = Column(Boolean)
    def get_id(self):
        return str(self.id)
    def to_json(self):
        return {
            'id': self.id,
            'create_time': self.create_time,
            'create_date': self.create_date,
            'update_time': self.update_time,
            'update_date': self.update_date,
            'tenant_id': self.tenant_id,
            'name': self.name,
            'description': self.description,
            'icon': self.icon,
            'language': self.language,
            'llm_id': self.llm_id,
            'prompt_type': self.prompt_type,
            'prompt_config': self.prompt_config,
            'similarity_threshold': self.similarity_threshold,
            'vector_similarity_weight': self.vector_similarity_weight,
            'top_n': self.top_n,
            'top_k': self.top_k,
            'do_refer': self.do_refer,
            'kb_ids': self.kb_ids,
            'status': self.status
        }
app/models/group_model.py
@@ -2,49 +2,128 @@
from enum import IntEnum
from typing import Optional
from sqlalchemy import Column, Integer, String, DateTime, Enum, Index
from sqlalchemy import Column, Integer, String, DateTime, Enum, Index, Table, ForeignKey
from pydantic import BaseModel
from sqlalchemy.orm import relationship, backref
from app.models.base_model import Base
class GroupStatus(IntEnum):
    NO = 1
    OFF = 0
group_knowledge_table = Table('group_Knowledge', Base.metadata
                           , Column('group_id', Integer, ForeignKey('group.id'))
                           , Column('knowledge_id', String(32), ForeignKey('knowledgebase.id')))
group_dialog_table = Table('group_dialogs', Base.metadata
                           , Column('group_id', Integer, ForeignKey('group.id'))
                           , Column('dialog_id', String(36), ForeignKey('dialogs.id')))
group_agent_table = Table('group_agent', Base.metadata
                           , Column('group_id', Integer, ForeignKey('group.id'))
                           , Column('agent_id', String(36), ForeignKey('user_canvas.id')))
group_llm_table = Table('group_llm', Base.metadata
                           , Column('group_id', Integer, ForeignKey('group.id'))
                           , Column('llm_id', String(36), ForeignKey('common_llm.id')))
group_unified_agent_table = Table('group_unified_agent', Base.metadata
                                    , Column('group_id', Integer, ForeignKey('group.id'))
                                    ,Column('unified_agent_id', String(36), ForeignKey('unified_agent.id')))
class GroupInfoModel(Base):
    __tablename__ = "group_info"
    group_id = Column(Integer, primary_key=True, index=True)
class GroupModel(Base):
    __tablename__ = "group"
    id = Column(Integer, primary_key=True, index=True)
    group_name = Column(String(255), unique=True, nullable=False, index=True)
    group_description = Column(String(255))
    group_status = Column(Integer, nullable=False, default=1)
    status = Column(String(10), nullable=False, default="1")
    created_at = Column(DateTime, default=datetime.now())
    updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now())
    knowledges = relationship('KnowledgeModel',
                                 secondary=group_knowledge_table,
                                 backref=backref('groups', lazy='dynamic'),
                                 lazy="dynamic")
    dialogs = relationship('DialogModel',
                              secondary=group_dialog_table,
                              backref=backref('groups', lazy='dynamic'),
                              lazy="dynamic")
    agents = relationship('CanvasModel',
                             secondary=group_agent_table,
                             backref=backref('groups', lazy='dynamic'),
                             lazy="dynamic")
    llms = relationship('CommonLlmModel',
                           secondary=group_llm_table,
                           backref=backref('groups', lazy='dynamic'),
                           lazy="dynamic")
    unified_agents = relationship('UnifiedAgentModel',
                                     secondary=group_unified_agent_table,
                                     backref=backref('roles', lazy='dynamic'),
                                     lazy="dynamic")
    def to_dict(self):
        return {
            'id': self.group_id,
            'groupId': self.id,
            'name': self.group_name,
            'group_description': self.group_description,
            'group_status': self.group_status,
            'created_at': self.created_at.strftime("%Y.%m.%d %H:%M")
            'description': self.group_description,
            'status': self.status,
            'createTime': self.created_at.strftime("%Y-%m-%d %H:%M:%S")
        }
class UserGroupModel(Base):
    __tablename__ = "user_group"
    id = Column(Integer, primary_key=True)
    group_id = Column(Integer, nullable=False)
    user_id = Column(Integer, nullable=False)
    Index('ix_user_group_id', group_id, user_id, unique=True)
    def get_id(self):
        return str(self.ID)
    def __repr__(self):
        return '<Role name:%r description:%r iconCls:%r seq:%r>\n' \
            % (self.NAME, self.DESCRIPTION, self.ICONCLS, self.SEQ)
    def to_json(self):
        json = {
            'roleId': self.id,
            'createTime': self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
            'updateTime': self.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
            'groupName': self.group_name,
            'remark': self.group_description,
            'status': self.status,
        }
        if len(self.knowledges.all()) > 0:
            json['knowledges'] = [knowledge.to_json() for knowledge in self.knowledges]
        if len(self.dialogs.all()) > 0:
            json['dialogs'] = [dialog.to_json() for dialog in self.dialogs]
        if len(self.agents.all()) > 0:
            json['agents'] = [agent.to_json() for agent in self.agents]
        if len(self.llms.all()) > 0:
            json['llms'] = [llm.to_json() for llm in self.llms]
        json['users'] = [user.to_dict() for user in self.users]
        if hasattr(self, 'flag'):
            json['flag'] = self.flag
        return json
# class UserGroupModel(Base):
#     __tablename__ = "user_group"
#     id = Column(Integer, primary_key=True)
#     group_id = Column(Integer, nullable=False)
#     user_id = Column(Integer, nullable=False)
#     Index('ix_user_group_id', group_id, user_id, unique=True)
class GroupData(BaseModel):
    id: Optional[int] = None
    group_name: Optional[str] = ""
    group_description: Optional[str] = ""
    group_status: Optional[int] = None
    group_status: Optional[str] = ""
class GroupUsers(BaseModel):
    id: int
app/models/knowledge_model.py
New file
@@ -0,0 +1,62 @@
from datetime import datetime
from sqlalchemy import Column, Integer, String, Table, ForeignKey, DateTime, BigInteger, Text, Float, Boolean
from sqlalchemy.orm import relationship, backref
from app.models.base_model import Base
class KnowledgeModel(Base):
    __tablename__ = 'knowledgebase'
    __mapper_args__ = {
        # "order_by": 'SEQ'
    }
    id = Column(String(32), primary_key=True)
    name = Column(String(128))
    create_time = Column(BigInteger)
    create_date = Column(DateTime)
    update_time = Column(BigInteger)
    update_date = Column(DateTime)
    avatar = Column(Text)
    tenant_id = Column(String(32))
    language = Column(String(32))
    description = Column(Text)
    embd_id = Column(String(128))
    permission = Column(String(16))
    created_by = Column(String(32))
    doc_num = Column(Integer)
    token_num = Column(Integer)
    chunk_num = Column(Integer)
    similarity_threshold = Column(Float)
    vector_similarity_weight = Column(Float)
    parser_id = Column(String(32))
    parser_config = Column(Text)
    status = Column(String(1))
    hide = Column(Boolean)
    def get_id(self):
        return str(self.id)
    def to_json(self):
        return {
            'id': self.id,
            'name': self.name,
            'create_time': self.create_time,
            'update_time': self.update_time,
            'avatar': self.avatar,
            'tenant_id': self.tenant_id,
            'language': self.language,
            'description': self.description,
            'embd_id': self.embd_id,
            'permission': self.permission,
            'created_by': self.created_by,
            'doc_num': self.doc_num,
            'token_num': self.token_num,
            'chunk_num': self.chunk_num,
            'similarity_threshold': self.similarity_threshold,
            'vector_similarity_weight': self.vector_similarity_weight,
            'parser_id': self.parser_id,
            'parser_config': json.loads(self.parser_config),
            'status': self.status
        }
    def __repr__(self):
        return '<Knowledge name:%r url:%r>\n' % (self.name, self.id)
app/models/llm_model.py
New file
@@ -0,0 +1,33 @@
from datetime import datetime
from enum import IntEnum
from typing import Optional
from sqlalchemy import Column, Integer, String, DateTime, Enum, Index, Table, ForeignKey
from pydantic import BaseModel
from sqlalchemy.orm import relationship, backref
from app.models.base_model import Base
class CommonLlmModel(Base):
    __tablename__ = 'common_llm'
    __mapper_args__ = {
        # "order_by": 'SEQ'
    }
    id = Column(String(36), primary_key=True, nullable=False)
    llm_factory = Column(String(128), nullable=False)
    model_type = Column(String(128), nullable=False)
    llm_name = Column(String(128), nullable=False)
    api_key = Column(String(1024), nullable=True)
    api_base = Column(String(255), nullable=True)
    def to_json(self):
        json = {
            'id': self.ID,
            'llm_factory': self.llm_factory,
            'model_type': self.model_type,
            'llm_name': self.llm_name,
            'api_key': self.api_key,
            'api_base': self.api_base,
        }
        return json
app/models/organization_model.py
New file
@@ -0,0 +1,111 @@
from datetime import datetime
from sqlalchemy import Column, Integer, String, Table, ForeignKey, DateTime
from sqlalchemy.orm import relationship, backref
from app.models.base_model import Base
organization_group_table = Table('organization_group', Base.metadata,
                                       Column('group_id', Integer, ForeignKey('group.id')),
                                       Column('organization_id', String(36), ForeignKey('organization.id')))
# #构建对role表的关系
organization_role_table = Table('organization_role', Base.metadata,
                                   Column('role_id', String(36), ForeignKey('role.id')),
                                   Column('organization_id', String(36), ForeignKey('organization.id')))
class OrganizationModel(Base):
    __tablename__ = 'organization'
    id = Column(String(36), primary_key=True)
    created_at = Column(DateTime, default=datetime.now())
    updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now())
    name = Column(String(200))
    address = Column(String(200))
    code = Column(String(200))
    iconcls = Column(String(255))
    seq = Column(Integer)
    leader = Column(String(255))
    phone = Column(String(11))
    email = Column(String(64))
    status = Column(String(10), nullable=False, default="0")
    groups = relationship('GroupModel',
                                secondary=organization_group_table,
                                backref=backref('organizations', lazy='dynamic'))
    roles = relationship('RoleModel',
                            secondary=organization_role_table,
                            backref=backref('organizations', lazy='dynamic'))
    organization_id = Column(String(36), ForeignKey('organization.id'))
    parent = relationship('OrganizationModel', remote_side=[id], backref='childrens', uselist=False)
    children = relationship('OrganizationModel')
    def to_json(self):
        json = {
            'deptId': self.id,
            'createTime': self.created_at,
            'updateTime': self.updated_at,
            'deptName': self.name,
            'address': self.address,
            'code': self.code,
            'iconCls': self.iconcls,
            'orderNum': self.seq,
            'parentId': self.get_pid(),
            'parentName': self.get_pName(),
            'leader': self.leader,
            'phone': self.phone,
            'email': self.email,
            'status': self.status,
            'roles': [self.role_json(role) for role in self.roles],
            'groups': [self.group_json(group) for group in self.groups],
            'children': [
                org.to_json() for org in self.children
            ]
        }
        return json
    def role_json(self, role):
        return {
            'roleId': role.id,
            'roleName': role.name,
            'deptId': self.id,
        }
    def group_json(self, group):
        return {
            'groupId': group.id,
            'groupName': group.name,
            'deptId': self.id,
        }
    def to_tree_select_json(self):
        return {
            'id': self.ID,
            'label': self.NAME,
            'children': [org.to_tree_select_json() for org in self.children]
        }
    def get_pid(self):
        if self.parent:
            return self.parent.ID
        return ''
    def get_pName(self):
        if self.parent:
            return self.parent.NAME
        return ''
    def get_id(self):
        return str(self.ID)
    def __repr__(self):
        return '<Organization %r>\n' %(self.NAME)
app/models/resource_model.py
New file
@@ -0,0 +1,140 @@
from datetime import datetime
from sqlalchemy import Column, Integer, String, DateTime, Table, ForeignKey
from sqlalchemy.orm import relationship, backref
from app.models.base_model import Base
class ResourceModel(Base):
    __tablename__ = 'resource'
    id = Column(String(36), primary_key=True, index=True)
    created_at = Column(DateTime, default=datetime.now())
    updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now())
    name = Column(String(128))
    url = Column(String(200))
    path = Column(String(200))
    perms = Column(String(150))
    description = Column(String(200))
    icon = Column(String(100))
    seq = Column(Integer)
    target = Column(String(100))
    canbdeeleted = Column(Integer)
    resource_type_id = Column(String(36), ForeignKey('resource_type.id'))
    resource_id = Column(String(36), ForeignKey('resource.id'))
    parent = relationship('ResourceModel', remote_side=[id], backref='resources', uselist=False)
    children = relationship('ResourceModel')
    status = Column(String(10))
    hidden = Column(Integer, default=0)
    def get_id(self):
        return str(self.ID)
    def to_json(self):
        return {
            'menuId': self.id,
            'createTime': self.created_at,
            'updateTime': self.updated_at,
            'menuName': self.name,
            'component': self.url,
            'description': self.description,
            'icon': self.icon,
            'orderNum': self.seq,
            'target': self.target,
            'parentId': self.get_pid(),
            'parentName': self.get_pName(),
            'syresourcetype': self.get_type_json(),
            'status': self.status,
            'path': self.path,
            'perms': self.perms,
            # 类型(0目录 1菜单 2按钮)
            'menuType': self.resource_type_id,
        }
    def to_tree_select_json(self):
        return {
            'menuId': self.id,
            'menuName': self.name,
            'menuType': self.resource_type_id,
            'children': [res.to_tree_select_json() for res in self.children]
        }
    def to_router_json(self):
        router = {
            'name': self.path.capitalize() if self.path else '',
            'path': self.path,
            'hidden': bool(self.hidden),
            'redirect': 'noRedirect',
            'component': self.url,
            'alwaysShow': True,
            'meta': {
                'title': self.name,
                'icon': self.icon,
                'noCache': False,
                'link': ''
            },
            'children': [
                res.to_router_json() for res in self.children if res.type.id == '3' or res.type.id == '0'
            ]
        }
        if not router['children']:
            del router['children']
            del router['redirect']
            del router['alwaysShow']
        if not router['component']:
            router['component'] = 'Layout'
        return router
    def to_menu_json(self):
        return {
            'id': self.id,
            'iconCls': self.icon,
            'pid': self.get_pid(),
            'state': 'open',
            'checked': False,
            'attributes': {
                'target': self.target,
                'url': self.url
            },
            'text': self.name
        }
    def get_pid(self):
        if self.parent:
            return self.parent.id
        return ''
    def get_pName(self):
        if self.parent:
            return self.parent.name
        return ''
    def get_type_json(self):
        if self.type:
            return self.type.to_json()
        return {}
    def __repr__(self):
        return '<ResourceModel name:%r url:%r>\n' % (self.NAME, self.URL)
class ResourceTypeModel(Base):
    __tablename__ = 'resource_type'
    id = Column(String(36), primary_key=True)
    created_at = Column(DateTime, default=datetime.now())
    updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now())
    name = Column(String(128))
    description = Column(String(255))
    resources = relationship('ResourceModel', backref='type', lazy='dynamic')
    def to_json(self):
        return {
            'id': self.id,
            'createdatetime': self.created_at,
            'updatedatetime': self.updated_at,
            'name': self.name,
            'description': self.description
        }
    def __repr__(self):
        return '<ResourceTypeModel %r>\n' %(self.name)
app/models/role_model.py
New file
@@ -0,0 +1,83 @@
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, constr
from sqlalchemy import Column, Integer, String, DateTime, Table, ForeignKey
from sqlalchemy.orm import relationship, backref
from app.models.base_model import Base
# 角色资源关联表
role_resource_table = Table('role_resource', Base.metadata,
                            Column('role_id', String(36), ForeignKey('role.id')),
                            Column('resource_id', String(36), ForeignKey('resource.id')))
class RoleModel(Base):
    __tablename__ = 'role'
    id = Column(String(36), primary_key=True, index=True)
    created_at = Column(DateTime, default=datetime.now())
    updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now())
    name = Column(String(128), unique=True, nullable=False, index=True)
    description = Column(String(255))
    iconCls = Column(String(100))
    seq = Column(Integer)
    roleKey = Column(String(100))
    dataScope = Column(Integer)
    status = Column(String(10), default="0")
    creator = Column(Integer)
    # 包含资源
    resources = relationship('ResourceModel',
                             secondary=role_resource_table,
                             backref=backref('roles', lazy='dynamic'))  # 资源所属角色
    def get_id(self):
        return str(self.id)
    def to_dict(self):
        return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])
    def __repr__(self):
        return '<Role name:%r description:%r iconCls:%r seq:%r>\n' \
            % (self.NAME, self.DESCRIPTION, self.ICONCLS, self.SEQ)
    def to_json(self):
        json = {
            'roleId': self.id,
            'createTime': self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
            'updateTime': self.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
            'roleName': self.name,
            'remark': self.description,
            'iconCls': self.iconCls,
            'roleSort': self.seq,
            'status': self.status,
            'roleKey': self.roleKey,
            'dataScope': self.dataScope
        }
        if len(self.resources) > 0:
            json['resources'] = [resource.to_json() for resource in self.resources]
        if hasattr(self, 'flag'):
            json['flag'] = self.flag
        return json
class RoleData(BaseModel):
    remark: Optional[str] = ""
    roleName: str
class RoleStatus(BaseModel):
    role_id: str
    status: constr(min_length=1, max_length=1, pattern='^(0|1)$')
class RoleEdit(BaseModel):
    role_id: str
    remark: Optional[str] = ""
    roleName: Optional[str] = ""
    resources: Optional[list] = []
app/models/user_model.py
@@ -1,6 +1,22 @@
from sqlalchemy import Column, Integer, String
from datetime import datetime
from sqlalchemy import Column, Integer, String, Table, ForeignKey, DateTime
from sqlalchemy.orm import relationship, backref
from app.models.base_model import Base
user_organization_table = Table('user_organization',Base.metadata
                                   , Column('user_id', Integer, ForeignKey('user.id'))
                                   , Column('organization_id', String(36), ForeignKey('organization.id')))
user_role_table = Table('user_role', Base.metadata
                           , Column('user_id', Integer, ForeignKey('user.id'))
                           , Column('role_id', String(36), ForeignKey('role.id')))
user_group_table = Table('user_group', Base.metadata
                           , Column('user_id', Integer, ForeignKey('user.id'))
                           , Column('group_id', Integer, ForeignKey('group.id')))
class UserModel(Base):
@@ -13,4 +29,92 @@
    email = Column(String(255), nullable=False, default="")
    description = Column(String(255), nullable=False, default="")
    ragflow_id = Column(String(32), unique=True, index=True)
    bisheng_id = Column(Integer, unique=True, index=True)
    bisheng_id = Column(Integer, unique=True, index=True)
    login_name = Column(String(100))
    status = Column(String(10), nullable=False, default="1")
    creator = Column(String(36))
    sex = Column(String(1))
    age = Column(Integer)
    created_at = Column(DateTime, default=datetime.now())
    updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now())
    organizations = relationship('OrganizationModel',
                                    secondary=user_organization_table,
                                    backref=backref('users', lazy='dynamic'))
    roles = relationship('RoleModel',
                            secondary=user_role_table,
                            backref=backref('users', lazy='dynamic'))
    groups = relationship('GroupModel',
                         secondary=user_group_table,
                         backref=backref('users', lazy='dynamic'))
    def have_permission(self, url):
        permissions = []
        for resource in self.resources:
            permissions.extend(resource)
        if filter(lambda x: x.URL == url, permissions):
            return True
        permissions = []
        for organization in self.organizations:
            permissions.extend([resource for resource in organization.resources])
        return filter(lambda x: x.NAME == url, permissions)
    def __repr__(self):
        return '<User %r>\n' % (self.NAME)
    def to_dict(self):
        return {
            'userId': self.id,
            'userName': self.username,
            'loginName': self.login_name if self.login_name else "",
            'status': self.status,
        }
    def to_json(self):
        json = {
            'userId': self.id,
            'createTime': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else "",
            'updateTime': self.updated_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else "",
            'userName': self.username,
            'loginName': self.login_name,
            'sex': self.sex,
            'age': self.age,
            "status": self.status,
            'photo': self.phone,
            'email': self.email,
            # 'phoneNumber': self.phone_number
        }
        if len(self.organizations) > 0:
            json['dept'] = [organization.to_json() for organization in self.organizations]
        json['groups'] = [group.to_dict() for group in self.groups]
        roles = []
        # if len(self.roles.all()) > 0:
        #     roles = [role.to_json() for role in self.roles]
        # organization_roles = [role.to_json() for organization in self.organizations for role in
        #                       organization.role_list]
        # for role in organization_roles:
        #     if role not in roles:
        #         roles.append(role)
        json['roles'] = roles
        return json
    def get_children(self):
        """递归获取指定用户的子用户ID列表"""
        users = UserModel.query.filter_by(CREATOR=self.ID).all()
        user_id_list = [user.ID for user in users]
        for user in users:
            user_id_list.extend(user.get_children())
        return user_id_list
app/service/group.py
@@ -1,41 +1,43 @@
from sqlalchemy.testing.pickleable import Order
from app.config.config import settings
from app.models.group_model import GroupInfoModel, UserGroupModel
from app.models.group_model import GroupModel
from app.models.user_model import UserModel
from app.service.ragflow import RagflowService
from app.service.token import get_ragflow_token
from app.Log import logger
async def group_list(db, page_size: int, page_index: int, keyword: str):
    query = db.query(GroupInfoModel)
    logger.info("-------------------------group_list----------------------------------")
    query = db.query(GroupModel)
    if keyword:
        query = query.filter(GroupInfoModel.group_name.like('%{}%'.format(keyword)))
    items = query.order_by(GroupInfoModel.group_id.desc()).limit(page_size).offset(
        query = query.filter(GroupModel.group_name.like('%{}%'.format(keyword)))
    items = query.order_by(GroupModel.id.desc()).limit(page_size).offset(
        (page_index - 1) * page_size).all()
    items_list = [item.to_dict() for item in items]
    groups = [i["id"] for i in items_list]
    group_dict = {}
    for group_user in db.query(UserGroupModel.group_id, UserModel.id, UserModel.username).outerjoin(UserModel,
                                                                                                    UserModel.id == UserGroupModel.user_id).filter(
        UserGroupModel.group_id.in_(groups)).all():
        if group_user.group_id in group_dict:
            group_dict[group_user.group_id].append({"user_id": group_user.id, "user_name": group_user.username})
        else:
            group_dict[group_user.group_id] = [{"user_id": group_user.id, "user_name": group_user.username}]
    for item in items_list:
        item["users"] = group_dict.get(item["id"], [])
    return {"total": query.count(), "items": items_list}
    # items_list = [item.to_dict() for item in items]
    # groups = [i["id"] for i in items_list]
    # group_dict = {}
    # for group_user in db.query(GroupModel.group_id, UserModel.id, UserModel.username).outerjoin(UserModel,
    #                                                                                                 UserModel.id == UserGroupModel.user_id).filter(
    #     GroupModel.group_id.in_(groups)).all():
    #     if group_user.group_id in group_dict:
    #         group_dict[group_user.group_id].append({"user_id": group_user.id, "user_name": group_user.username})
    #     else:
    #         group_dict[group_user.group_id] = [{"user_id": group_user.id, "user_name": group_user.username}]
    # for item in items_list:
    #     item["users"] = group_dict.get(item["id"], [])
    return {"total": query.count(), "items": [item.to_json() for item in items]}
async def create_group(db, group_name: str, group_description: str):
    try:
        group_model = GroupInfoModel(group_name=group_name, group_description=group_description)
        group_model = GroupModel(group_name=group_name, group_description=group_description)
        db.add(group_model)
        db.commit()
        db.refresh(group_model)
    except Exception as e:
        print(e)
        logger.error(e)
        db.rollback()
        return False
    return True
@@ -43,10 +45,10 @@
async def edit_group_data(db, group_id: int, data):
    try:
        db.query(GroupInfoModel).filter(GroupInfoModel.group_id == group_id).update(data)
        db.query(GroupModel).filter(GroupModel.id == group_id).update(data)
        db.commit()
    except Exception as e:
        print(e)
        logger.error(e)
        db.rollback()
        return False
    return True
@@ -54,10 +56,10 @@
async def delete_group_data(db, group_id: int):
    try:
        db.query(GroupInfoModel).filter(GroupInfoModel.group_id == group_id).delete()
        db.query(GroupModel).filter(GroupModel.id == group_id).delete()
        db.commit()
    except Exception as e:
        print(e)
        logger.error(e)
        db.rollback()
        return False
    return True
@@ -66,8 +68,8 @@
async def get_group_users(db, group_id):
    not_group_user = []
    in_group_user = []
    user_list = [i.user_id for i in
                 db.query(UserGroupModel.user_id).filter(UserGroupModel.group_id.__eq__(group_id)).all()]
    user_list = [u.id for i in
                 db.query(GroupModel).filter(GroupModel.id.__eq__(group_id)).all() for u in i.users]
    for u in db.query(UserModel.id, UserModel.username).order_by(UserModel.id.desc()).all():
        if u.id in user_list:
            in_group_user.append({"user_id": u.id, "user_name": u.username})
@@ -77,8 +79,9 @@
async def save_user_to_group(db, user_id, group_id, user_list):
    group_user_list = [i.user_id for i in
                       db.query(UserGroupModel.user_id).filter(UserGroupModel.group_id.__eq__(group_id)).all()]
    group_user_list = [u.id for i in
                 db.query(GroupModel).filter(GroupModel.id.__eq__(group_id)).all() for u in i.users]
    # print(group_user_list)
    new_users = set([i for i in user_list if i not in group_user_list])
    delete_user = [i for i in group_user_list if i not in user_list]
    if new_users:
@@ -105,15 +108,14 @@
                                                              user_dict[user2]["email"],
                                                              user_dict[user2]["rg_id"])
        except Exception as e:
            print(e)
            logger.error(e)
            return False
    try:
        for user in new_users:
            db_user = UserGroupModel(group_id=group_id, user_id=user)
            db.add(db_user)
        db.query(UserGroupModel).filter(UserGroupModel.group_id.__eq__(group_id), UserGroupModel.user_id.in_(delete_user)).delete()
        group = db.query(GroupModel).filter(GroupModel.id.__eq__(group_id)).first()
        group.users = [db.get(UserModel, user) for user in user_list]
        db.commit()
    except Exception as e:
        print(e)
        logger.error(e)
        return False
    return True
app/service/organization.py
app/service/ragflow.py
@@ -1,7 +1,5 @@
import httpx
from typing import Union, Dict, List
from Tools.scripts.objgraph import ignore
from fastapi import HTTPException
from starlette import status
@@ -152,10 +150,7 @@
        url = f"{self.base_url}/v1/tenant/{tenant_id}/user"
        headers = {"Authorization": token}
        data = {"email": email, "user_id": user_id}
        print(url)
        print(data)
        async with httpx.AsyncClient(timeout=60) as client:
            response = await client.post(url, headers=headers, json=data)
            print(response.text)
            if response.status_code != 200:
                raise Exception(f"Ragflow add user to tenant failed: {response.text}")
app/service/role.py
New file
@@ -0,0 +1,65 @@
import uuid
from app.Log import logger
from app.models.resource_model import ResourceModel, ResourceTypeModel
from app.models.role_model import RoleModel
async def role_list(db, page_size: int, page_index: int, keyword: str):
    query = db.query(RoleModel)
    if keyword:
        query = query.filter(RoleModel.name.like('%{}%'.format(keyword)))
    roles = query.order_by(RoleModel.id.desc()).limit(page_size).offset(
        (page_index - 1) * page_size).all()
    return {"total": query.count(), "rows":  [role.to_json() for role in roles]}
async def create_role(db, role_name: str, description: str, user_id):
    try:
        role_model = RoleModel(id=str(uuid.uuid4()),name=role_name, description=description,creator=user_id)
        db.add(role_model)
        db.commit()
        db.refresh(role_model)
    except Exception as e:
        logger.error(e)
        db.rollback()
        return False
    return True
async def delete_role_data(db, role_id: str):
    try:
        db.query(RoleModel).filter(RoleModel.id == role_id).delete()
        db.commit()
    except Exception as e:
        logger.error(e)
        db.rollback()
        return False
    return True
async def edit_role_status(db, status: str, role_id: str):
    try:
        db.query(RoleModel).filter(RoleModel.id == role_id).update({"status":status})
        db.commit()
    except Exception as e:
        logger.error(e)
        db.rollback()
        return False
    return True
async def edit_role_resource(db, role_id:str, role_name:str, description:str, resources:list):
    try:
        role = db.query(RoleModel).filter(RoleModel.id == role_id).first()
        if role_name: role.name = role_name
        if description: role.description = description
        if resources:
            role.resources = [db.get(ResourceModel, resourcesId) for resourcesId in resources]
        db.add(role)
        db.commit()
    except Exception as e:
        logger.error(e)
        db.rollback()
        return False
    return True
app/service/user.py
New file
@@ -0,0 +1,11 @@
from app.models.user_model import UserModel
from app.Log import logger
async def get_user_list(db, page_size: int, page_index: int, keyword: str):
    logger.error("ffffffff")
    query = db.query(UserModel)
    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]}
main.py
@@ -1,6 +1,7 @@
from contextlib import asynccontextmanager
from fastapi import FastAPI
from app.Log import init_log
from app.api.auth import router as auth_router
from app.api.chat import router as chat_router
from app.api.agent import router as agent_router
@@ -9,6 +10,7 @@
from app.api.report import router as report_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
@@ -32,6 +34,7 @@
    lifespan=lifespan
)
app.include_router(auth_router, prefix='/api/auth', tags=["auth"])
app.include_router(chat_router, prefix='/api/chat', tags=["chat"])
app.include_router(agent_router, prefix='/api/agent', tags=["agent"])
@@ -40,6 +43,7 @@
app.include_router(report_router, prefix='/api/report', tags=["report"])
app.include_router(user_router, prefix='/api/user', tags=["user"])
app.include_router(group_router, prefix='/api/group', tags=["group"])
app.include_router(role_router, prefix='/api/role', tags=["role"])
if __name__ == "__main__":
    import uvicorn